You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2021/05/23 07:50:45 UTC

[isis] branch master updated: ISIS-2513: Demo: prepare Blob, Clob, Image et al. for JPA

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new 5c09a81  ISIS-2513: Demo: prepare Blob, Clob, Image et al. for JPA
5c09a81 is described below

commit 5c09a81f69df58ff16c47e6384c0f5f067099d8a
Author: andi-huber <ah...@apache.org>
AuthorDate: Sun May 23 09:50:28 2021 +0200

    ISIS-2513: Demo: prepare Blob, Clob, Image et al. for JPA
---
 .../dom/types/isis/blobs/jdo/IsisBlobJdo.java      |  7 ++-
 .../types/isis/blobs/jdo/IsisBlobJdoEntities.java  | 26 ++++------
 .../isis/blobs/jdo/IsisBlobJdoSeedService.java     | 55 --------------------
 .../IsisBlobEntity.java}                           | 42 +++++++---------
 .../blobs/persistence/IsisBlobEntity.layout.xml}   |  0
 .../blobs/persistence/IsisBlobSeeding.java}        | 26 ++++------
 .../dom/types/isis/clobs/jdo/IsisClobJdo.java      |  7 ++-
 .../types/isis/clobs/jdo/IsisClobJdoEntities.java  | 26 ++++------
 .../isis/clobs/jdo/IsisClobJdoSeedService.java     | 54 --------------------
 .../IsisClobEntity.java}                           | 42 +++++++---------
 .../clobs/persistence/IsisClobEntity.layout.xml}   |  0
 .../clobs/persistence/IsisClobSeeding.java}        | 26 ++++------
 .../jdo/IsisLocalResourcePathJdo.java              |  7 ++-
 .../jdo/IsisLocalResourcePathJdoEntities.java      | 26 ++++------
 .../jdo/IsisLocalResourcePathJdoSeedService.java   | 54 --------------------
 .../persistence/IsisLocalResourcePathEntity.java}  | 45 ++++++++---------
 .../IsisLocalResourcePathEntity.layout.xml}        |  0
 .../persistence/IsisLocalResourcePathSeeding.java} | 26 ++++------
 .../dom/types/isis/markups/jdo/IsisMarkupJdo.java  |  7 ++-
 .../isis/markups/jdo/IsisMarkupJdoEntities.java    | 26 ++++------
 .../isis/markups/jdo/IsisMarkupJdoSeedService.java | 55 --------------------
 .../IsisMarkupEntity.java}                         | 42 +++++++---------
 .../IsisMarkupEntity.layout.xml}                   |  0
 .../markups/persistence/IsisMarkupSeeding.java}    | 26 ++++------
 .../types/isis/passwords/jdo/IsisPasswordJdo.java  |  7 ++-
 .../passwords/jdo/IsisPasswordJdoEntities.java     | 27 +++++-----
 .../passwords/jdo/IsisPasswordJdoSeedService.java  | 57 ---------------------
 .../IsisPasswordEntity.java}                       | 39 +++++++--------
 .../persistence/IsisPasswordEntity.layout.xml}     |  0
 .../IsisPasswordSeeding.java}                      | 26 ++++------
 .../isisext/asciidocs/jdo/IsisAsciiDocJdo.java     |  7 ++-
 .../asciidocs/jdo/IsisAsciiDocJdoEntities.java     | 27 +++++-----
 .../asciidocs/jdo/IsisAsciiDocJdoSeedService.java  | 58 ----------------------
 .../IsisAsciiDocEntity.java}                       | 39 +++++++--------
 .../persistence/IsisAsciiDocEntity.layout.xml}     |  0
 .../IsisAsciiDocSeeding.java}                      | 26 ++++------
 .../isisext/markdowns/jdo/IsisMarkdownJdo.java     |  7 ++-
 .../markdowns/jdo/IsisMarkdownJdoEntities.java     | 27 +++++-----
 .../markdowns/jdo/IsisMarkdownJdoSeedService.java  | 57 ---------------------
 .../IsisMarkdownEntity.java}                       | 39 +++++++--------
 .../persistence/IsisMarkdownEntity.layout.xml}     |  0
 .../IsisMarkdownSeeding.java}                      | 26 ++++------
 .../types/javaawt/images/jdo/JavaAwtImageJdo.java  | 11 ++--
 .../images/jdo/JavaAwtImageJdoEntities.java        | 23 ++++-----
 .../images/jdo/JavaAwtImageJdoSeedService.java     | 58 ----------------------
 .../JavaAwtImageEntity.java}                       | 45 ++++++++---------
 .../JavaAwtImageEntity.layout.xml}                 |  0
 .../JavaAwtImageSeeding.java}                      | 24 ++++-----
 48 files changed, 343 insertions(+), 912 deletions(-)

diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jdo/IsisBlobJdo.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jdo/IsisBlobJdo.java
index efc31ab..fa3d0a0 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jdo/IsisBlobJdo.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jdo/IsisBlobJdo.java
@@ -33,8 +33,7 @@ import org.apache.isis.applib.annotation.PropertyLayout;
 import org.apache.isis.applib.annotation.Title;
 import org.apache.isis.applib.value.Blob;
 
-import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
-import demoapp.dom.types.isis.blobs.holder.IsisBlobHolder2;
+import demoapp.dom.types.isis.blobs.persistence.IsisBlobEntity;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -42,10 +41,10 @@ import lombok.Setter;
 @PersistenceCapable(identityType = IdentityType.DATASTORE, schema = "demo")
 @DatastoreIdentity(strategy = IdGeneratorStrategy.IDENTITY, column = "id")
 @DomainObject(
-        objectType = "demo.IsisBlobJdo"
+        objectType = "demo.IsisBlobEntity"
 )
 public class IsisBlobJdo                                            // <.>
-        implements HasAsciiDocDescription, IsisBlobHolder2 {
+        extends IsisBlobEntity {
 
 //end::class[]
     public IsisBlobJdo(Blob initialValue) {
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jdo/IsisBlobJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jdo/IsisBlobJdoEntities.java
index 453477d..ea14cb8 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jdo/IsisBlobJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jdo/IsisBlobJdoEntities.java
@@ -18,31 +18,25 @@
  */
 package demoapp.dom.types.isis.blobs.jdo;
 
-import java.util.List;
-import java.util.Optional;
-
-import javax.inject.Inject;
-
+import org.springframework.context.annotation.Profile;
 import org.springframework.stereotype.Service;
 
-import org.apache.isis.applib.services.repository.RepositoryService;
 import org.apache.isis.applib.value.Blob;
 
-import lombok.RequiredArgsConstructor;
+import demoapp.dom._infra.values.ValueHolderRepository;
 
+@Profile("demo-jdo")
 @Service
-@RequiredArgsConstructor(onConstructor_ = { @Inject })
-public class IsisBlobJdoEntities {
+public class IsisBlobJdoEntities
+extends ValueHolderRepository<Blob, IsisBlobJdo> {
 
-    final RepositoryService repositoryService;
-
-    public Optional<IsisBlobJdo> find(final Blob readOnlyProperty) {
-        return repositoryService.firstMatch(IsisBlobJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
+    protected IsisBlobJdoEntities() {
+        super(IsisBlobJdo.class);
     }
 
-    public List<IsisBlobJdo> all() {
-        return repositoryService.allInstances(IsisBlobJdo.class);
+    @Override
+    protected IsisBlobJdo newDetachedEntity(Blob value) {
+        return new IsisBlobJdo(value);
     }
 
-
 }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jdo/IsisBlobJdoSeedService.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jdo/IsisBlobJdoSeedService.java
deleted file mode 100644
index c2b1891..0000000
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jdo/IsisBlobJdoSeedService.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package demoapp.dom.types.isis.blobs.jdo;
-
-import javax.inject.Inject;
-
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.services.repository.RepositoryService;
-import org.apache.isis.applib.value.Blob;
-import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScript;
-
-import demoapp.dom._infra.seed.SeedServiceAbstract;
-import demoapp.dom.types.Samples;
-
-@Service
-public class IsisBlobJdoSeedService extends SeedServiceAbstract {
-
-    public IsisBlobJdoSeedService() {
-        super(IsisBlobJdoEntityFixture::new);
-    }
-
-
-    static class IsisBlobJdoEntityFixture extends FixtureScript {
-
-        @Override
-        protected void execute(ExecutionContext executionContext) {
-            samples.stream()
-                    .map(IsisBlobJdo::new)
-                    .forEach(domainObject -> {
-                        repositoryService.persist(domainObject);
-                        executionContext.addResult(this, domainObject);
-                    });
-        }
-
-        @Inject RepositoryService repositoryService;
-        @Inject Samples<Blob> samples;
-    }
-}
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jdo/IsisBlobJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/persistence/IsisBlobEntity.java
similarity index 55%
copy from examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jdo/IsisBlobJdoEntities.java
copy to examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/persistence/IsisBlobEntity.java
index 453477d..2c3875b 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jdo/IsisBlobJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/persistence/IsisBlobEntity.java
@@ -16,33 +16,27 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.types.isis.blobs.jdo;
+package demoapp.dom.types.isis.blobs.persistence;
 
-import java.util.List;
-import java.util.Optional;
-
-import javax.inject.Inject;
-
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.services.repository.RepositoryService;
+import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.value.Blob;
 
-import lombok.RequiredArgsConstructor;
-
-@Service
-@RequiredArgsConstructor(onConstructor_ = { @Inject })
-public class IsisBlobJdoEntities {
-
-    final RepositoryService repositoryService;
-
-    public Optional<IsisBlobJdo> find(final Blob readOnlyProperty) {
-        return repositoryService.firstMatch(IsisBlobJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
-    }
-
-    public List<IsisBlobJdo> all() {
-        return repositoryService.allInstances(IsisBlobJdo.class);
+import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
+import demoapp.dom._infra.values.ValueHolder;
+import demoapp.dom.types.isis.blobs.holder.IsisBlobHolder2;
+
+@DomainObject(
+        objectType = "demo.IsisBlobEntity" // shared permissions with concrete sub class
+)
+public abstract class IsisBlobEntity
+implements
+    HasAsciiDocDescription,
+    IsisBlobHolder2,
+    ValueHolder<Blob> {
+
+    @Override
+    public Blob value() {
+        return getReadOnlyProperty();
     }
 
-
 }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/jdo/IsisMarkdownJdo.layout.xml b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/persistence/IsisBlobEntity.layout.xml
similarity index 100%
rename from examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/jdo/IsisMarkdownJdo.layout.xml
rename to examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/persistence/IsisBlobEntity.layout.xml
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/persistence/IsisBlobSeeding.java
similarity index 60%
copy from examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java
copy to examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/persistence/IsisBlobSeeding.java
index aa7f929..29ec861 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/persistence/IsisBlobSeeding.java
@@ -16,30 +16,24 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.types.javaawt.images.jdo;
-
-import java.awt.image.BufferedImage;
-import java.util.List;
-import java.util.Optional;
+package demoapp.dom.types.isis.blobs.persistence;
 
 import javax.inject.Inject;
 
 import org.springframework.stereotype.Service;
 
-import org.apache.isis.applib.services.repository.RepositoryService;
-
-@Service
-public class JavaAwtImageJdoEntities {
+import org.apache.isis.applib.value.Blob;
 
-    public Optional<JavaAwtImageJdo> find(final BufferedImage readOnlyProperty) {
-        return repositoryService.firstMatch(JavaAwtImageJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
-    }
+import demoapp.dom._infra.seed.SeedServiceAbstract;
+import demoapp.dom._infra.values.ValueHolderRepository;
 
-    public List<JavaAwtImageJdo> all() {
-        return repositoryService.allInstances(JavaAwtImageJdo.class);
-    }
+@Service
+public class IsisBlobSeeding
+extends SeedServiceAbstract {
 
     @Inject
-    RepositoryService repositoryService;
+    public IsisBlobSeeding(ValueHolderRepository<Blob, ? extends IsisBlobEntity> entities) {
+        super(entities);
+    }
 
 }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jdo/IsisClobJdo.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jdo/IsisClobJdo.java
index cfbc999..07ec34d 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jdo/IsisClobJdo.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jdo/IsisClobJdo.java
@@ -33,8 +33,7 @@ import org.apache.isis.applib.annotation.PropertyLayout;
 import org.apache.isis.applib.annotation.Title;
 import org.apache.isis.applib.value.Clob;
 
-import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
-import demoapp.dom.types.isis.clobs.holder.IsisClobHolder2;
+import demoapp.dom.types.isis.clobs.persistence.IsisClobEntity;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -42,10 +41,10 @@ import lombok.Setter;
 @PersistenceCapable(identityType = IdentityType.DATASTORE, schema = "demo")
 @DatastoreIdentity(strategy = IdGeneratorStrategy.IDENTITY, column = "id")
 @DomainObject(
-        objectType = "demo.IsisClobJdo"
+        objectType = "demo.IsisClobEntity"
 )
 public class IsisClobJdo                                          // <.>
-        implements HasAsciiDocDescription, IsisClobHolder2 {
+        extends IsisClobEntity {
 
 //end::class[]
     public IsisClobJdo(Clob initialValue) {
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jdo/IsisClobJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jdo/IsisClobJdoEntities.java
index bbda4ee..966e72d 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jdo/IsisClobJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jdo/IsisClobJdoEntities.java
@@ -18,31 +18,25 @@
  */
 package demoapp.dom.types.isis.clobs.jdo;
 
-import java.util.List;
-import java.util.Optional;
-
-import javax.inject.Inject;
-
+import org.springframework.context.annotation.Profile;
 import org.springframework.stereotype.Service;
 
-import org.apache.isis.applib.services.repository.RepositoryService;
 import org.apache.isis.applib.value.Clob;
 
-import lombok.RequiredArgsConstructor;
+import demoapp.dom._infra.values.ValueHolderRepository;
 
+@Profile("demo-jdo")
 @Service
-@RequiredArgsConstructor(onConstructor_ = { @Inject })
-public class IsisClobJdoEntities {
+public class IsisClobJdoEntities
+extends ValueHolderRepository<Clob, IsisClobJdo> {
 
-    final RepositoryService repositoryService;
-
-    public Optional<IsisClobJdo> find(final Clob readOnlyProperty) {
-        return repositoryService.firstMatch(IsisClobJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
+    protected IsisClobJdoEntities() {
+        super(IsisClobJdo.class);
     }
 
-    public List<IsisClobJdo> all() {
-        return repositoryService.allInstances(IsisClobJdo.class);
+    @Override
+    protected IsisClobJdo newDetachedEntity(Clob value) {
+        return new IsisClobJdo(value);
     }
 
-
 }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jdo/IsisClobJdoSeedService.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jdo/IsisClobJdoSeedService.java
deleted file mode 100644
index 5d2253d..0000000
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jdo/IsisClobJdoSeedService.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package demoapp.dom.types.isis.clobs.jdo;
-
-import javax.inject.Inject;
-
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.services.repository.RepositoryService;
-import org.apache.isis.applib.value.Clob;
-import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScript;
-
-import demoapp.dom._infra.seed.SeedServiceAbstract;
-import demoapp.dom.types.Samples;
-
-@Service
-public class IsisClobJdoSeedService extends SeedServiceAbstract {
-
-    public IsisClobJdoSeedService() {
-        super(IsisClobJdoEntityFixture::new);
-    }
-
-    static class IsisClobJdoEntityFixture extends FixtureScript {
-
-        @Override
-        protected void execute(ExecutionContext executionContext) {
-            samples.stream()
-                    .map(IsisClobJdo::new)
-                    .forEach(domainObject -> {
-                        repositoryService.persist(domainObject);
-                        executionContext.addResult(this, domainObject);
-                    });
-        }
-
-        @Inject RepositoryService repositoryService;
-        @Inject Samples<Clob> samples;
-    }
-}
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jdo/IsisClobJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/persistence/IsisClobEntity.java
similarity index 55%
copy from examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jdo/IsisClobJdoEntities.java
copy to examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/persistence/IsisClobEntity.java
index bbda4ee..07f6899 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jdo/IsisClobJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/persistence/IsisClobEntity.java
@@ -16,33 +16,27 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.types.isis.clobs.jdo;
+package demoapp.dom.types.isis.clobs.persistence;
 
-import java.util.List;
-import java.util.Optional;
-
-import javax.inject.Inject;
-
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.services.repository.RepositoryService;
+import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.value.Clob;
 
-import lombok.RequiredArgsConstructor;
-
-@Service
-@RequiredArgsConstructor(onConstructor_ = { @Inject })
-public class IsisClobJdoEntities {
-
-    final RepositoryService repositoryService;
-
-    public Optional<IsisClobJdo> find(final Clob readOnlyProperty) {
-        return repositoryService.firstMatch(IsisClobJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
-    }
-
-    public List<IsisClobJdo> all() {
-        return repositoryService.allInstances(IsisClobJdo.class);
+import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
+import demoapp.dom._infra.values.ValueHolder;
+import demoapp.dom.types.isis.clobs.holder.IsisClobHolder2;
+
+@DomainObject(
+        objectType = "demo.IsisClobEntity" // shared permissions with concrete sub class
+)
+public abstract class IsisClobEntity
+implements
+    HasAsciiDocDescription,
+    IsisClobHolder2,
+    ValueHolder<Clob> {
+
+    @Override
+    public Clob value() {
+        return getReadOnlyProperty();
     }
 
-
 }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdo.layout.xml b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/persistence/IsisClobEntity.layout.xml
similarity index 100%
rename from examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdo.layout.xml
rename to examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/persistence/IsisClobEntity.layout.xml
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/persistence/IsisClobSeeding.java
similarity index 60%
copy from examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java
copy to examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/persistence/IsisClobSeeding.java
index aa7f929..592abfb 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/persistence/IsisClobSeeding.java
@@ -16,30 +16,24 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.types.javaawt.images.jdo;
-
-import java.awt.image.BufferedImage;
-import java.util.List;
-import java.util.Optional;
+package demoapp.dom.types.isis.clobs.persistence;
 
 import javax.inject.Inject;
 
 import org.springframework.stereotype.Service;
 
-import org.apache.isis.applib.services.repository.RepositoryService;
-
-@Service
-public class JavaAwtImageJdoEntities {
+import org.apache.isis.applib.value.Clob;
 
-    public Optional<JavaAwtImageJdo> find(final BufferedImage readOnlyProperty) {
-        return repositoryService.firstMatch(JavaAwtImageJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
-    }
+import demoapp.dom._infra.seed.SeedServiceAbstract;
+import demoapp.dom._infra.values.ValueHolderRepository;
 
-    public List<JavaAwtImageJdo> all() {
-        return repositoryService.allInstances(JavaAwtImageJdo.class);
-    }
+@Service
+public class IsisClobSeeding
+extends SeedServiceAbstract {
 
     @Inject
-    RepositoryService repositoryService;
+    public IsisClobSeeding(ValueHolderRepository<Clob, ? extends IsisClobEntity> entities) {
+        super(entities);
+    }
 
 }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/jdo/IsisLocalResourcePathJdo.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/jdo/IsisLocalResourcePathJdo.java
index b91ddaf..f495033 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/jdo/IsisLocalResourcePathJdo.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/jdo/IsisLocalResourcePathJdo.java
@@ -33,8 +33,7 @@ import org.apache.isis.applib.annotation.PropertyLayout;
 import org.apache.isis.applib.annotation.Title;
 import org.apache.isis.applib.value.LocalResourcePath;
 
-import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
-import demoapp.dom.types.isis.localresourcepaths.holder.IsisLocalResourcePathHolder2;
+import demoapp.dom.types.isis.localresourcepaths.persistence.IsisLocalResourcePathEntity;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -42,10 +41,10 @@ import lombok.Setter;
 @PersistenceCapable(identityType = IdentityType.DATASTORE, schema = "demo")
 @DatastoreIdentity(strategy = IdGeneratorStrategy.IDENTITY, column = "id")
 @DomainObject(
-        objectType = "demo.IsisLocalResourcePathJdo"
+        objectType = "demo.IsisLocalResourcePathEntity"
 )
 public class IsisLocalResourcePathJdo                                   // <.>
-        implements HasAsciiDocDescription, IsisLocalResourcePathHolder2 {
+        extends IsisLocalResourcePathEntity {
 
 //end::class[]
     public IsisLocalResourcePathJdo(LocalResourcePath initialValue) {
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/jdo/IsisLocalResourcePathJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/jdo/IsisLocalResourcePathJdoEntities.java
index 7e9026d..05e72e1 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/jdo/IsisLocalResourcePathJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/jdo/IsisLocalResourcePathJdoEntities.java
@@ -18,31 +18,25 @@
  */
 package demoapp.dom.types.isis.localresourcepaths.jdo;
 
-import java.util.List;
-import java.util.Optional;
-
-import javax.inject.Inject;
-
+import org.springframework.context.annotation.Profile;
 import org.springframework.stereotype.Service;
 
-import org.apache.isis.applib.services.repository.RepositoryService;
 import org.apache.isis.applib.value.LocalResourcePath;
 
-import lombok.RequiredArgsConstructor;
+import demoapp.dom._infra.values.ValueHolderRepository;
 
+@Profile("demo-jdo")
 @Service
-@RequiredArgsConstructor(onConstructor_ = { @Inject })
-public class IsisLocalResourcePathJdoEntities {
+public class IsisLocalResourcePathJdoEntities
+extends ValueHolderRepository<LocalResourcePath, IsisLocalResourcePathJdo> {
 
-    final RepositoryService repositoryService;
-
-    public Optional<IsisLocalResourcePathJdo> find(final LocalResourcePath readOnlyProperty) {
-        return repositoryService.firstMatch(IsisLocalResourcePathJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
+    protected IsisLocalResourcePathJdoEntities() {
+        super(IsisLocalResourcePathJdo.class);
     }
 
-    public List<IsisLocalResourcePathJdo> all() {
-        return repositoryService.allInstances(IsisLocalResourcePathJdo.class);
+    @Override
+    protected IsisLocalResourcePathJdo newDetachedEntity(LocalResourcePath value) {
+        return new IsisLocalResourcePathJdo(value);
     }
 
-
 }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/jdo/IsisLocalResourcePathJdoSeedService.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/jdo/IsisLocalResourcePathJdoSeedService.java
deleted file mode 100644
index 244ff0a..0000000
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/jdo/IsisLocalResourcePathJdoSeedService.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package demoapp.dom.types.isis.localresourcepaths.jdo;
-
-import javax.inject.Inject;
-
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.services.repository.RepositoryService;
-import org.apache.isis.applib.value.LocalResourcePath;
-import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScript;
-
-import demoapp.dom._infra.seed.SeedServiceAbstract;
-import demoapp.dom.types.Samples;
-
-@Service
-public class IsisLocalResourcePathJdoSeedService extends SeedServiceAbstract {
-
-    public IsisLocalResourcePathJdoSeedService() {
-        super(IsisLocalResourcePathJdoEntityFixture::new);
-    }
-
-    static class IsisLocalResourcePathJdoEntityFixture extends FixtureScript {
-
-        @Override
-        protected void execute(ExecutionContext executionContext) {
-            samples.stream()
-                    .map(IsisLocalResourcePathJdo::new)
-                    .forEach(domainObject -> {
-                        repositoryService.persist(domainObject);
-                        executionContext.addResult(this, domainObject);
-                    });
-        }
-
-        @Inject RepositoryService repositoryService;
-        @Inject Samples<LocalResourcePath> samples;
-    }
-}
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/persistence/IsisLocalResourcePathEntity.java
similarity index 53%
copy from examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdoEntities.java
copy to examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/persistence/IsisLocalResourcePathEntity.java
index 930108b..61451be 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/persistence/IsisLocalResourcePathEntity.java
@@ -16,30 +16,27 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.types.isisext.asciidocs.jdo;
-
-import java.util.List;
-import java.util.Optional;
-
-import javax.inject.Inject;
-
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.services.repository.RepositoryService;
-import org.apache.isis.valuetypes.asciidoc.applib.value.AsciiDoc;
-
-@Service
-public class IsisAsciiDocJdoEntities {
-
-    public Optional<IsisAsciiDocJdo> find(final AsciiDoc readOnlyProperty) {
-        return repositoryService.firstMatch(IsisAsciiDocJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
-    }
-
-    public List<IsisAsciiDocJdo> all() {
-        return repositoryService.allInstances(IsisAsciiDocJdo.class);
+package demoapp.dom.types.isis.localresourcepaths.persistence;
+
+import org.apache.isis.applib.annotation.DomainObject;
+import org.apache.isis.applib.value.LocalResourcePath;
+
+import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
+import demoapp.dom._infra.values.ValueHolder;
+import demoapp.dom.types.isis.localresourcepaths.holder.IsisLocalResourcePathHolder2;
+
+@DomainObject(
+        objectType = "demo.IsisLocalResourcePathEntity" // shared permissions with concrete sub class
+)
+public abstract class IsisLocalResourcePathEntity
+implements
+    HasAsciiDocDescription,
+    IsisLocalResourcePathHolder2,
+    ValueHolder<LocalResourcePath> {
+
+    @Override
+    public LocalResourcePath value() {
+        return getReadOnlyProperty();
     }
 
-    @Inject
-    RepositoryService repositoryService;
-
 }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/jdo/IsisPasswordJdo.layout.xml b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/persistence/IsisLocalResourcePathEntity.layout.xml
similarity index 100%
rename from examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/jdo/IsisPasswordJdo.layout.xml
rename to examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/persistence/IsisLocalResourcePathEntity.layout.xml
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/persistence/IsisLocalResourcePathSeeding.java
similarity index 60%
copy from examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java
copy to examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/persistence/IsisLocalResourcePathSeeding.java
index aa7f929..c3945db 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/persistence/IsisLocalResourcePathSeeding.java
@@ -16,30 +16,24 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.types.javaawt.images.jdo;
-
-import java.awt.image.BufferedImage;
-import java.util.List;
-import java.util.Optional;
+package demoapp.dom.types.isis.localresourcepaths.persistence;
 
 import javax.inject.Inject;
 
 import org.springframework.stereotype.Service;
 
-import org.apache.isis.applib.services.repository.RepositoryService;
-
-@Service
-public class JavaAwtImageJdoEntities {
+import org.apache.isis.applib.value.LocalResourcePath;
 
-    public Optional<JavaAwtImageJdo> find(final BufferedImage readOnlyProperty) {
-        return repositoryService.firstMatch(JavaAwtImageJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
-    }
+import demoapp.dom._infra.seed.SeedServiceAbstract;
+import demoapp.dom._infra.values.ValueHolderRepository;
 
-    public List<JavaAwtImageJdo> all() {
-        return repositoryService.allInstances(JavaAwtImageJdo.class);
-    }
+@Service
+public class IsisLocalResourcePathSeeding
+extends SeedServiceAbstract {
 
     @Inject
-    RepositoryService repositoryService;
+    public IsisLocalResourcePathSeeding(ValueHolderRepository<LocalResourcePath, ? extends IsisLocalResourcePathEntity> entities) {
+        super(entities);
+    }
 
 }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/jdo/IsisMarkupJdo.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/jdo/IsisMarkupJdo.java
index 42b099c..48ee3b8 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/jdo/IsisMarkupJdo.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/jdo/IsisMarkupJdo.java
@@ -34,8 +34,7 @@ import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.services.bookmark.BookmarkService;
 import org.apache.isis.applib.value.Markup;
 
-import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
-import demoapp.dom.types.isis.markups.holder.IsisMarkupHolder2;
+import demoapp.dom.types.isis.markups.persistence.IsisMarkupEntity;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -43,10 +42,10 @@ import lombok.Setter;
 @PersistenceCapable(identityType = IdentityType.DATASTORE, schema = "demo")
 @DatastoreIdentity(strategy = IdGeneratorStrategy.IDENTITY, column = "id")
 @DomainObject(
-        objectType = "demo.IsisMarkupJdo"
+        objectType = "demo.IsisMarkupEntity"
 )
 public class IsisMarkupJdo                                          // <.>
-        implements HasAsciiDocDescription, IsisMarkupHolder2 {
+        extends IsisMarkupEntity {
 
 //end::class[]
     public IsisMarkupJdo(Markup initialValue) {
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/jdo/IsisMarkupJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/jdo/IsisMarkupJdoEntities.java
index 1174fdd..ee95dcb 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/jdo/IsisMarkupJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/jdo/IsisMarkupJdoEntities.java
@@ -18,31 +18,25 @@
  */
 package demoapp.dom.types.isis.markups.jdo;
 
-import java.util.List;
-import java.util.Optional;
-
-import javax.inject.Inject;
-
+import org.springframework.context.annotation.Profile;
 import org.springframework.stereotype.Service;
 
-import org.apache.isis.applib.services.repository.RepositoryService;
 import org.apache.isis.applib.value.Markup;
 
-import lombok.RequiredArgsConstructor;
+import demoapp.dom._infra.values.ValueHolderRepository;
 
+@Profile("demo-jdo")
 @Service
-@RequiredArgsConstructor(onConstructor_ = { @Inject })
-public class IsisMarkupJdoEntities {
+public class IsisMarkupJdoEntities
+extends ValueHolderRepository<Markup, IsisMarkupJdo> {
 
-    final RepositoryService repositoryService;
-
-    public Optional<IsisMarkupJdo> find(final Markup readOnlyProperty) {
-        return repositoryService.firstMatch(IsisMarkupJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
+    protected IsisMarkupJdoEntities() {
+        super(IsisMarkupJdo.class);
     }
 
-    public List<IsisMarkupJdo> all() {
-        return repositoryService.allInstances(IsisMarkupJdo.class);
+    @Override
+    protected IsisMarkupJdo newDetachedEntity(Markup value) {
+        return new IsisMarkupJdo(value);
     }
 
-
 }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/jdo/IsisMarkupJdoSeedService.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/jdo/IsisMarkupJdoSeedService.java
deleted file mode 100644
index a599f99..0000000
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/jdo/IsisMarkupJdoSeedService.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package demoapp.dom.types.isis.markups.jdo;
-
-import javax.inject.Inject;
-
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.services.repository.RepositoryService;
-import org.apache.isis.applib.value.Markup;
-import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScript;
-
-import demoapp.dom._infra.seed.SeedServiceAbstract;
-import demoapp.dom.types.Samples;
-
-@Service
-public class IsisMarkupJdoSeedService extends SeedServiceAbstract {
-
-    public IsisMarkupJdoSeedService() {
-        super(IsisMarkupJdoEntityFixture::new);
-    }
-
-    static class IsisMarkupJdoEntityFixture extends FixtureScript {
-
-        @Override
-        protected void execute(ExecutionContext executionContext) {
-            samples.stream()
-                    .map(IsisMarkupJdo::new)
-                    .forEach(domainObject -> {
-                        repositoryService.persist(domainObject);
-                        executionContext.addResult(this, domainObject);
-                    });
-        }
-
-        @Inject RepositoryService repositoryService;
-        @Inject Samples<Markup> samples;
-
-    }
-}
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/jdo/IsisMarkupJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/persistence/IsisMarkupEntity.java
similarity index 54%
copy from examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/jdo/IsisMarkupJdoEntities.java
copy to examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/persistence/IsisMarkupEntity.java
index 1174fdd..61ca74a 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/jdo/IsisMarkupJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/persistence/IsisMarkupEntity.java
@@ -16,33 +16,27 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.types.isis.markups.jdo;
+package demoapp.dom.types.isis.markups.persistence;
 
-import java.util.List;
-import java.util.Optional;
-
-import javax.inject.Inject;
-
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.services.repository.RepositoryService;
+import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.value.Markup;
 
-import lombok.RequiredArgsConstructor;
-
-@Service
-@RequiredArgsConstructor(onConstructor_ = { @Inject })
-public class IsisMarkupJdoEntities {
-
-    final RepositoryService repositoryService;
-
-    public Optional<IsisMarkupJdo> find(final Markup readOnlyProperty) {
-        return repositoryService.firstMatch(IsisMarkupJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
-    }
-
-    public List<IsisMarkupJdo> all() {
-        return repositoryService.allInstances(IsisMarkupJdo.class);
+import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
+import demoapp.dom._infra.values.ValueHolder;
+import demoapp.dom.types.isis.markups.holder.IsisMarkupHolder2;
+
+@DomainObject(
+        objectType = "demo.IsisMarkupEntity" // shared permissions with concrete sub class
+)
+public abstract class IsisMarkupEntity
+implements
+    HasAsciiDocDescription,
+    IsisMarkupHolder2,
+    ValueHolder<Markup> {
+
+    @Override
+    public Markup value() {
+        return getReadOnlyProperty();
     }
 
-
 }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/jdo/IsisMarkupJdo.layout.xml b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/persistence/IsisMarkupEntity.layout.xml
similarity index 100%
rename from examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/jdo/IsisMarkupJdo.layout.xml
rename to examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/persistence/IsisMarkupEntity.layout.xml
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/persistence/IsisMarkupSeeding.java
similarity index 60%
copy from examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java
copy to examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/persistence/IsisMarkupSeeding.java
index aa7f929..e0a5d08 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/markups/persistence/IsisMarkupSeeding.java
@@ -16,30 +16,24 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.types.javaawt.images.jdo;
-
-import java.awt.image.BufferedImage;
-import java.util.List;
-import java.util.Optional;
+package demoapp.dom.types.isis.markups.persistence;
 
 import javax.inject.Inject;
 
 import org.springframework.stereotype.Service;
 
-import org.apache.isis.applib.services.repository.RepositoryService;
-
-@Service
-public class JavaAwtImageJdoEntities {
+import org.apache.isis.applib.value.Markup;
 
-    public Optional<JavaAwtImageJdo> find(final BufferedImage readOnlyProperty) {
-        return repositoryService.firstMatch(JavaAwtImageJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
-    }
+import demoapp.dom._infra.seed.SeedServiceAbstract;
+import demoapp.dom._infra.values.ValueHolderRepository;
 
-    public List<JavaAwtImageJdo> all() {
-        return repositoryService.allInstances(JavaAwtImageJdo.class);
-    }
+@Service
+public class IsisMarkupSeeding
+extends SeedServiceAbstract {
 
     @Inject
-    RepositoryService repositoryService;
+    public IsisMarkupSeeding(ValueHolderRepository<Markup, ? extends IsisMarkupEntity> entities) {
+        super(entities);
+    }
 
 }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/jdo/IsisPasswordJdo.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/jdo/IsisPasswordJdo.java
index 118828e..fca61c1 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/jdo/IsisPasswordJdo.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/jdo/IsisPasswordJdo.java
@@ -32,8 +32,7 @@ import org.apache.isis.applib.annotation.PropertyLayout;
 import org.apache.isis.applib.annotation.Title;
 import org.apache.isis.applib.value.Password;
 
-import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
-import demoapp.dom.types.isis.passwords.holder.IsisPasswordHolder2;
+import demoapp.dom.types.isis.passwords.persistence.IsisPasswordEntity;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -41,10 +40,10 @@ import lombok.Setter;
 @PersistenceCapable(identityType = IdentityType.DATASTORE, schema = "demo")
 @DatastoreIdentity(strategy = IdGeneratorStrategy.IDENTITY, column = "id")
 @DomainObject(
-        objectType = "demo.IsisPasswordJdo"
+        objectType = "demo.IsisPasswordEntity"
 )
 public class IsisPasswordJdo                                          // <.>
-        implements HasAsciiDocDescription, IsisPasswordHolder2 {
+        extends IsisPasswordEntity {
 
 //end::class[]
     public IsisPasswordJdo(Password initialValue) {
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/jdo/IsisPasswordJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/jdo/IsisPasswordJdoEntities.java
index 3e83be8..acd9844 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/jdo/IsisPasswordJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/jdo/IsisPasswordJdoEntities.java
@@ -18,28 +18,25 @@
  */
 package demoapp.dom.types.isis.passwords.jdo;
 
-import java.util.List;
-import java.util.Optional;
-
-import javax.inject.Inject;
-
+import org.springframework.context.annotation.Profile;
 import org.springframework.stereotype.Service;
 
-import org.apache.isis.applib.services.repository.RepositoryService;
 import org.apache.isis.applib.value.Password;
 
+import demoapp.dom._infra.values.ValueHolderRepository;
+
+@Profile("demo-jdo")
 @Service
-public class IsisPasswordJdoEntities {
+public class IsisPasswordJdoEntities
+extends ValueHolderRepository<Password, IsisPasswordJdo> {
 
-    public Optional<IsisPasswordJdo> find(final Password readOnlyProperty) {
-        return repositoryService.firstMatch(IsisPasswordJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
+    protected IsisPasswordJdoEntities() {
+        super(IsisPasswordJdo.class);
     }
 
-    public List<IsisPasswordJdo> all() {
-        return repositoryService.allInstances(IsisPasswordJdo.class);
+    @Override
+    protected IsisPasswordJdo newDetachedEntity(Password value) {
+        return new IsisPasswordJdo(value);
     }
 
-    @Inject
-    RepositoryService repositoryService;
-
-}
+}
\ No newline at end of file
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/jdo/IsisPasswordJdoSeedService.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/jdo/IsisPasswordJdoSeedService.java
deleted file mode 100644
index 3ae20b1..0000000
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/jdo/IsisPasswordJdoSeedService.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package demoapp.dom.types.isis.passwords.jdo;
-
-import javax.inject.Inject;
-
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.services.repository.RepositoryService;
-import org.apache.isis.applib.value.Password;
-import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScript;
-
-import demoapp.dom._infra.seed.SeedServiceAbstract;
-import demoapp.dom.types.Samples;
-
-@Service
-public class IsisPasswordJdoSeedService extends SeedServiceAbstract {
-
-    public IsisPasswordJdoSeedService() {
-        super(IsisPasswordJdoEntityFixture::new);
-    }
-
-    static class IsisPasswordJdoEntityFixture extends FixtureScript {
-
-        @Override
-        protected void execute(ExecutionContext executionContext) {
-            samples.stream()
-                    .map(IsisPasswordJdo::new)
-                    .forEach(domainObject -> {
-                        repositoryService.persist(domainObject);
-                        executionContext.addResult(this, domainObject);
-                    });
-        }
-
-        @Inject
-        RepositoryService repositoryService;
-
-        @Inject
-        Samples<Password> samples;
-    }
-}
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/jdo/IsisPasswordJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/persistence/IsisPasswordEntity.java
similarity index 57%
copy from examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/jdo/IsisPasswordJdoEntities.java
copy to examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/persistence/IsisPasswordEntity.java
index 3e83be8..7303d0f 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/jdo/IsisPasswordJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/persistence/IsisPasswordEntity.java
@@ -16,30 +16,27 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.types.isis.passwords.jdo;
+package demoapp.dom.types.isis.passwords.persistence;
 
-import java.util.List;
-import java.util.Optional;
-
-import javax.inject.Inject;
-
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.services.repository.RepositoryService;
+import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.value.Password;
 
-@Service
-public class IsisPasswordJdoEntities {
-
-    public Optional<IsisPasswordJdo> find(final Password readOnlyProperty) {
-        return repositoryService.firstMatch(IsisPasswordJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
+import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
+import demoapp.dom._infra.values.ValueHolder;
+import demoapp.dom.types.isis.passwords.holder.IsisPasswordHolder2;
+
+@DomainObject(
+        objectType = "demo.IsisPasswordEntity" // shared permissions with concrete sub class
+)
+public abstract class IsisPasswordEntity
+implements
+    HasAsciiDocDescription,
+    IsisPasswordHolder2,
+    ValueHolder<Password> {
+
+    @Override
+    public Password value() {
+        return getReadOnlyProperty();
     }
 
-    public List<IsisPasswordJdo> all() {
-        return repositoryService.allInstances(IsisPasswordJdo.class);
-    }
-
-    @Inject
-    RepositoryService repositoryService;
-
 }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/jdo/IsisLocalResourcePathJdo.layout.xml b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/persistence/IsisPasswordEntity.layout.xml
similarity index 100%
rename from examples/demo/domain/src/main/java/demoapp/dom/types/isis/localresourcepaths/jdo/IsisLocalResourcePathJdo.layout.xml
rename to examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/persistence/IsisPasswordEntity.layout.xml
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/jdo/IsisPasswordJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/persistence/IsisPasswordSeeding.java
similarity index 63%
copy from examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/jdo/IsisPasswordJdoEntities.java
copy to examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/persistence/IsisPasswordSeeding.java
index 3e83be8..2ccb4e7 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/jdo/IsisPasswordJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/passwords/persistence/IsisPasswordSeeding.java
@@ -16,30 +16,24 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.types.isis.passwords.jdo;
-
-import java.util.List;
-import java.util.Optional;
+package demoapp.dom.types.isis.passwords.persistence;
 
 import javax.inject.Inject;
 
 import org.springframework.stereotype.Service;
 
-import org.apache.isis.applib.services.repository.RepositoryService;
 import org.apache.isis.applib.value.Password;
 
-@Service
-public class IsisPasswordJdoEntities {
-
-    public Optional<IsisPasswordJdo> find(final Password readOnlyProperty) {
-        return repositoryService.firstMatch(IsisPasswordJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
-    }
+import demoapp.dom._infra.seed.SeedServiceAbstract;
+import demoapp.dom._infra.values.ValueHolderRepository;
 
-    public List<IsisPasswordJdo> all() {
-        return repositoryService.allInstances(IsisPasswordJdo.class);
-    }
+@Service
+public class IsisPasswordSeeding
+extends SeedServiceAbstract {
 
     @Inject
-    RepositoryService repositoryService;
+    public IsisPasswordSeeding(ValueHolderRepository<Password, ? extends IsisPasswordEntity> entities) {
+        super(entities);
+    }
 
-}
+}
\ No newline at end of file
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdo.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdo.java
index fab7060..12510fa 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdo.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdo.java
@@ -34,8 +34,7 @@ import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.services.bookmark.BookmarkService;
 import org.apache.isis.valuetypes.asciidoc.applib.value.AsciiDoc;
 
-import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
-import demoapp.dom.types.isisext.asciidocs.holder.IsisAsciiDocHolder2;
+import demoapp.dom.types.isisext.asciidocs.persistence.IsisAsciiDocEntity;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -43,10 +42,10 @@ import lombok.Setter;
 @PersistenceCapable(identityType = IdentityType.DATASTORE, schema = "demo")
 @DatastoreIdentity(strategy = IdGeneratorStrategy.IDENTITY, column = "id")
 @DomainObject(
-        objectType = "demo.IsisAsciiDocJdo"
+        objectType = "demo.IsisAsciiDocEntity"
 )
 public class IsisAsciiDocJdo                                          // <.>
-        implements HasAsciiDocDescription, IsisAsciiDocHolder2 {
+        extends IsisAsciiDocEntity {
 
 //end::class[]
     public IsisAsciiDocJdo(AsciiDoc initialValue) {
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdoEntities.java
index 930108b..8e807f4 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdoEntities.java
@@ -18,28 +18,25 @@
  */
 package demoapp.dom.types.isisext.asciidocs.jdo;
 
-import java.util.List;
-import java.util.Optional;
-
-import javax.inject.Inject;
-
+import org.springframework.context.annotation.Profile;
 import org.springframework.stereotype.Service;
 
-import org.apache.isis.applib.services.repository.RepositoryService;
 import org.apache.isis.valuetypes.asciidoc.applib.value.AsciiDoc;
 
+import demoapp.dom._infra.values.ValueHolderRepository;
+
+@Profile("demo-jdo")
 @Service
-public class IsisAsciiDocJdoEntities {
+public class IsisAsciiDocJdoEntities
+extends ValueHolderRepository<AsciiDoc, IsisAsciiDocJdo> {
 
-    public Optional<IsisAsciiDocJdo> find(final AsciiDoc readOnlyProperty) {
-        return repositoryService.firstMatch(IsisAsciiDocJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
+    protected IsisAsciiDocJdoEntities() {
+        super(IsisAsciiDocJdo.class);
     }
 
-    public List<IsisAsciiDocJdo> all() {
-        return repositoryService.allInstances(IsisAsciiDocJdo.class);
+    @Override
+    protected IsisAsciiDocJdo newDetachedEntity(AsciiDoc value) {
+        return new IsisAsciiDocJdo(value);
     }
 
-    @Inject
-    RepositoryService repositoryService;
-
-}
+}
\ No newline at end of file
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdoSeedService.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdoSeedService.java
deleted file mode 100644
index 3de81c9..0000000
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdoSeedService.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package demoapp.dom.types.isisext.asciidocs.jdo;
-
-import javax.inject.Inject;
-
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.services.repository.RepositoryService;
-import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScript;
-import org.apache.isis.valuetypes.asciidoc.applib.value.AsciiDoc;
-
-import demoapp.dom._infra.seed.SeedServiceAbstract;
-import demoapp.dom.types.Samples;
-
-@Service
-public class IsisAsciiDocJdoSeedService extends SeedServiceAbstract {
-
-    public IsisAsciiDocJdoSeedService() {
-        super(IsisAsciiDocJdoEntityFixture::new);
-    }
-
-    static class IsisAsciiDocJdoEntityFixture extends FixtureScript {
-
-        @Override
-        protected void execute(ExecutionContext executionContext) {
-            repositoryService.removeAll(IsisAsciiDocJdo.class);
-            samples.stream()
-                    .map(IsisAsciiDocJdo::new)
-                    .forEach(domainObject -> {
-                        repositoryService.persist(domainObject);
-                        executionContext.addResult(this, domainObject);
-                    });
-        }
-
-        @Inject
-        RepositoryService repositoryService;
-
-        @Inject
-        Samples<AsciiDoc> samples;
-    }
-}
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/persistence/IsisAsciiDocEntity.java
similarity index 57%
copy from examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdoEntities.java
copy to examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/persistence/IsisAsciiDocEntity.java
index 930108b..f00c6a4 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/persistence/IsisAsciiDocEntity.java
@@ -16,30 +16,27 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.types.isisext.asciidocs.jdo;
+package demoapp.dom.types.isisext.asciidocs.persistence;
 
-import java.util.List;
-import java.util.Optional;
-
-import javax.inject.Inject;
-
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.services.repository.RepositoryService;
+import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.valuetypes.asciidoc.applib.value.AsciiDoc;
 
-@Service
-public class IsisAsciiDocJdoEntities {
-
-    public Optional<IsisAsciiDocJdo> find(final AsciiDoc readOnlyProperty) {
-        return repositoryService.firstMatch(IsisAsciiDocJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
+import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
+import demoapp.dom._infra.values.ValueHolder;
+import demoapp.dom.types.isisext.asciidocs.holder.IsisAsciiDocHolder2;
+
+@DomainObject(
+        objectType = "demo.IsisAsciiDocEntity" // shared permissions with concrete sub class
+)
+public abstract class IsisAsciiDocEntity
+implements
+    HasAsciiDocDescription,
+    IsisAsciiDocHolder2,
+    ValueHolder<AsciiDoc> {
+
+    @Override
+    public AsciiDoc value() {
+        return getReadOnlyProperty();
     }
 
-    public List<IsisAsciiDocJdo> all() {
-        return repositoryService.allInstances(IsisAsciiDocJdo.class);
-    }
-
-    @Inject
-    RepositoryService repositoryService;
-
 }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jdo/IsisClobJdo.layout.xml b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/persistence/IsisAsciiDocEntity.layout.xml
similarity index 100%
rename from examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jdo/IsisClobJdo.layout.xml
rename to examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/persistence/IsisAsciiDocEntity.layout.xml
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/persistence/IsisAsciiDocSeeding.java
similarity index 63%
copy from examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdoEntities.java
copy to examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/persistence/IsisAsciiDocSeeding.java
index 930108b..033c76b 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/jdo/IsisAsciiDocJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/asciidocs/persistence/IsisAsciiDocSeeding.java
@@ -16,30 +16,24 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.types.isisext.asciidocs.jdo;
-
-import java.util.List;
-import java.util.Optional;
+package demoapp.dom.types.isisext.asciidocs.persistence;
 
 import javax.inject.Inject;
 
 import org.springframework.stereotype.Service;
 
-import org.apache.isis.applib.services.repository.RepositoryService;
 import org.apache.isis.valuetypes.asciidoc.applib.value.AsciiDoc;
 
-@Service
-public class IsisAsciiDocJdoEntities {
-
-    public Optional<IsisAsciiDocJdo> find(final AsciiDoc readOnlyProperty) {
-        return repositoryService.firstMatch(IsisAsciiDocJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
-    }
+import demoapp.dom._infra.seed.SeedServiceAbstract;
+import demoapp.dom._infra.values.ValueHolderRepository;
 
-    public List<IsisAsciiDocJdo> all() {
-        return repositoryService.allInstances(IsisAsciiDocJdo.class);
-    }
+@Service
+public class IsisAsciiDocSeeding
+extends SeedServiceAbstract {
 
     @Inject
-    RepositoryService repositoryService;
+    public IsisAsciiDocSeeding(ValueHolderRepository<AsciiDoc, ? extends IsisAsciiDocEntity> entities) {
+        super(entities);
+    }
 
-}
+}
\ No newline at end of file
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/jdo/IsisMarkdownJdo.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/jdo/IsisMarkdownJdo.java
index 2bfb0c0..d7d0bfa 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/jdo/IsisMarkdownJdo.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/jdo/IsisMarkdownJdo.java
@@ -34,8 +34,7 @@ import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.services.bookmark.BookmarkService;
 import org.apache.isis.valuetypes.markdown.applib.value.Markdown;
 
-import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
-import demoapp.dom.types.isisext.markdowns.holder.IsisMarkdownHolder2;
+import demoapp.dom.types.isisext.markdowns.persistence.IsisMarkdownEntity;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -43,10 +42,10 @@ import lombok.Setter;
 @PersistenceCapable(identityType = IdentityType.DATASTORE, schema = "demo")
 @DatastoreIdentity(strategy = IdGeneratorStrategy.IDENTITY, column = "id")
 @DomainObject(
-        objectType = "demo.IsisMarkdownJdo"
+        objectType = "demo.IsisMarkdownEntity"
 )
 public class IsisMarkdownJdo                                          // <.>
-        implements HasAsciiDocDescription, IsisMarkdownHolder2 {
+        extends IsisMarkdownEntity {
 
 //end::class[]
     public IsisMarkdownJdo(Markdown initialValue) {
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/jdo/IsisMarkdownJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/jdo/IsisMarkdownJdoEntities.java
index b93fc43..b4eb8ac 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/jdo/IsisMarkdownJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/jdo/IsisMarkdownJdoEntities.java
@@ -18,28 +18,25 @@
  */
 package demoapp.dom.types.isisext.markdowns.jdo;
 
-import java.util.List;
-import java.util.Optional;
-
-import javax.inject.Inject;
-
+import org.springframework.context.annotation.Profile;
 import org.springframework.stereotype.Service;
 
-import org.apache.isis.applib.services.repository.RepositoryService;
 import org.apache.isis.valuetypes.markdown.applib.value.Markdown;
 
+import demoapp.dom._infra.values.ValueHolderRepository;
+
+@Profile("demo-jdo")
 @Service
-public class IsisMarkdownJdoEntities {
+public class IsisMarkdownJdoEntities
+extends ValueHolderRepository<Markdown, IsisMarkdownJdo> {
 
-    public Optional<IsisMarkdownJdo> find(final Markdown readOnlyProperty) {
-        return repositoryService.firstMatch(IsisMarkdownJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
+    protected IsisMarkdownJdoEntities() {
+        super(IsisMarkdownJdo.class);
     }
 
-    public List<IsisMarkdownJdo> all() {
-        return repositoryService.allInstances(IsisMarkdownJdo.class);
+    @Override
+    protected IsisMarkdownJdo newDetachedEntity(Markdown value) {
+        return new IsisMarkdownJdo(value);
     }
 
-    @Inject
-    RepositoryService repositoryService;
-
-}
+}
\ No newline at end of file
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/jdo/IsisMarkdownJdoSeedService.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/jdo/IsisMarkdownJdoSeedService.java
deleted file mode 100644
index 7d0e947..0000000
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/jdo/IsisMarkdownJdoSeedService.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package demoapp.dom.types.isisext.markdowns.jdo;
-
-import javax.inject.Inject;
-
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.services.repository.RepositoryService;
-import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScript;
-import org.apache.isis.valuetypes.markdown.applib.value.Markdown;
-
-import demoapp.dom._infra.seed.SeedServiceAbstract;
-import demoapp.dom.types.Samples;
-
-@Service
-public class IsisMarkdownJdoSeedService extends SeedServiceAbstract {
-
-    public IsisMarkdownJdoSeedService() {
-        super(IsisMarkdownJdoEntityFixture::new);
-    }
-
-    static class IsisMarkdownJdoEntityFixture extends FixtureScript {
-
-        @Override
-        protected void execute(ExecutionContext executionContext) {
-            samples.stream()
-                    .map(IsisMarkdownJdo::new)
-                    .forEach(domainObject -> {
-                        repositoryService.persist(domainObject);
-                        executionContext.addResult(this, domainObject);
-                    });
-        }
-
-        @Inject
-        RepositoryService repositoryService;
-
-        @Inject
-        Samples<Markdown> samples;
-    }
-}
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/jdo/IsisMarkdownJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/persistence/IsisMarkdownEntity.java
similarity index 57%
copy from examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/jdo/IsisMarkdownJdoEntities.java
copy to examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/persistence/IsisMarkdownEntity.java
index b93fc43..f418a9e 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/jdo/IsisMarkdownJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/persistence/IsisMarkdownEntity.java
@@ -16,30 +16,27 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.types.isisext.markdowns.jdo;
+package demoapp.dom.types.isisext.markdowns.persistence;
 
-import java.util.List;
-import java.util.Optional;
-
-import javax.inject.Inject;
-
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.services.repository.RepositoryService;
+import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.valuetypes.markdown.applib.value.Markdown;
 
-@Service
-public class IsisMarkdownJdoEntities {
-
-    public Optional<IsisMarkdownJdo> find(final Markdown readOnlyProperty) {
-        return repositoryService.firstMatch(IsisMarkdownJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
+import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
+import demoapp.dom._infra.values.ValueHolder;
+import demoapp.dom.types.isisext.markdowns.holder.IsisMarkdownHolder2;
+
+@DomainObject(
+        objectType = "demo.IsisMarkdownEntity" // shared permissions with concrete sub class
+)
+public abstract class IsisMarkdownEntity
+implements
+    HasAsciiDocDescription,
+    IsisMarkdownHolder2,
+    ValueHolder<Markdown> {
+
+    @Override
+    public Markdown value() {
+        return getReadOnlyProperty();
     }
 
-    public List<IsisMarkdownJdo> all() {
-        return repositoryService.allInstances(IsisMarkdownJdo.class);
-    }
-
-    @Inject
-    RepositoryService repositoryService;
-
 }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jdo/IsisBlobJdo.layout.xml b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/persistence/IsisMarkdownEntity.layout.xml
similarity index 100%
rename from examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jdo/IsisBlobJdo.layout.xml
rename to examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/persistence/IsisMarkdownEntity.layout.xml
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/jdo/IsisMarkdownJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/persistence/IsisMarkdownSeeding.java
similarity index 63%
copy from examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/jdo/IsisMarkdownJdoEntities.java
copy to examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/persistence/IsisMarkdownSeeding.java
index b93fc43..1c1ae49 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/jdo/IsisMarkdownJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isisext/markdowns/persistence/IsisMarkdownSeeding.java
@@ -16,30 +16,24 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.types.isisext.markdowns.jdo;
-
-import java.util.List;
-import java.util.Optional;
+package demoapp.dom.types.isisext.markdowns.persistence;
 
 import javax.inject.Inject;
 
 import org.springframework.stereotype.Service;
 
-import org.apache.isis.applib.services.repository.RepositoryService;
 import org.apache.isis.valuetypes.markdown.applib.value.Markdown;
 
-@Service
-public class IsisMarkdownJdoEntities {
-
-    public Optional<IsisMarkdownJdo> find(final Markdown readOnlyProperty) {
-        return repositoryService.firstMatch(IsisMarkdownJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
-    }
+import demoapp.dom._infra.seed.SeedServiceAbstract;
+import demoapp.dom._infra.values.ValueHolderRepository;
 
-    public List<IsisMarkdownJdo> all() {
-        return repositoryService.allInstances(IsisMarkdownJdo.class);
-    }
+@Service
+public class IsisMarkdownSeeding
+extends SeedServiceAbstract {
 
     @Inject
-    RepositoryService repositoryService;
+    public IsisMarkdownSeeding(ValueHolderRepository<Markdown, ? extends IsisMarkdownEntity> entities) {
+        super(entities);
+    }
 
-}
+}
\ No newline at end of file
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdo.java b/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdo.java
index 6ab1009..b96ce9a 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdo.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdo.java
@@ -31,7 +31,7 @@ import org.apache.isis.applib.annotation.Optionality;
 import org.apache.isis.applib.annotation.Property;
 import org.apache.isis.applib.annotation.PropertyLayout;
 
-import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
+import demoapp.dom.types.javaawt.images.persistence.JavaAwtImageEntity;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -42,10 +42,9 @@ import lombok.Setter;
         objectType = "demo.JavaAwtImageJdo"
 )
 public class JavaAwtImageJdo                                          // <.>
-        implements HasAsciiDocDescription
+        extends JavaAwtImageEntity
 //end::class[]
 // label positions not yet supported
-//        , JavaAwtImageHolder2
 //tag::class[]
 {
 
@@ -68,6 +67,12 @@ public class JavaAwtImageJdo                                          // <.>
     private BufferedImage readOnlyProperty;
 
 //end::class[]
+
+    @Override // once JavaAwtImageHolder2 is implemented by this class, move this up to JavaAwtImageEntity
+    public java.awt.image.BufferedImage value() {
+        return getReadOnlyProperty();
+    }
+
 // editable properties not yet supported:
 //    @Property(editing = Editing.ENABLED)                          // <.>
 //    @PropertyLayout(group = "editable-properties", sequence = "1")
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java
index aa7f929..5459f20 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java
@@ -19,27 +19,24 @@
 package demoapp.dom.types.javaawt.images.jdo;
 
 import java.awt.image.BufferedImage;
-import java.util.List;
-import java.util.Optional;
-
-import javax.inject.Inject;
 
+import org.springframework.context.annotation.Profile;
 import org.springframework.stereotype.Service;
 
-import org.apache.isis.applib.services.repository.RepositoryService;
+import demoapp.dom._infra.values.ValueHolderRepository;
 
+@Profile("demo-jdo")
 @Service
-public class JavaAwtImageJdoEntities {
+public class JavaAwtImageJdoEntities
+extends ValueHolderRepository<BufferedImage, JavaAwtImageJdo> {
 
-    public Optional<JavaAwtImageJdo> find(final BufferedImage readOnlyProperty) {
-        return repositoryService.firstMatch(JavaAwtImageJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
+    protected JavaAwtImageJdoEntities() {
+        super(JavaAwtImageJdo.class);
     }
 
-    public List<JavaAwtImageJdo> all() {
-        return repositoryService.allInstances(JavaAwtImageJdo.class);
+    @Override
+    protected JavaAwtImageJdo newDetachedEntity(BufferedImage value) {
+        return new JavaAwtImageJdo(value);
     }
 
-    @Inject
-    RepositoryService repositoryService;
-
 }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoSeedService.java b/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoSeedService.java
deleted file mode 100644
index 7cda5bd..0000000
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoSeedService.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package demoapp.dom.types.javaawt.images.jdo;
-
-import java.awt.image.BufferedImage;
-
-import javax.inject.Inject;
-
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.services.repository.RepositoryService;
-import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScript;
-
-import demoapp.dom._infra.seed.SeedServiceAbstract;
-import demoapp.dom.types.Samples;
-
-@Service
-public class JavaAwtImageJdoSeedService extends SeedServiceAbstract {
-
-    public JavaAwtImageJdoSeedService() {
-        super(JavaAwtImageJdoEntityFixture::new);
-    }
-
-    static class JavaAwtImageJdoEntityFixture extends FixtureScript {
-
-        @Override
-        protected void execute(ExecutionContext executionContext) {
-            samples.stream()
-                    .map(JavaAwtImageJdo::new)
-                    .forEach(domainObject -> {
-                        repositoryService.persist(domainObject);
-                        executionContext.addResult(this, domainObject);
-                    });
-        }
-
-        @Inject
-        RepositoryService repositoryService;
-
-        @Inject
-        Samples<BufferedImage> samples;
-    }
-}
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/persistence/JavaAwtImageEntity.java
similarity index 54%
copy from examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java
copy to examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/persistence/JavaAwtImageEntity.java
index aa7f929..e61a650 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/persistence/JavaAwtImageEntity.java
@@ -16,30 +16,25 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.types.javaawt.images.jdo;
-
-import java.awt.image.BufferedImage;
-import java.util.List;
-import java.util.Optional;
-
-import javax.inject.Inject;
-
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.services.repository.RepositoryService;
-
-@Service
-public class JavaAwtImageJdoEntities {
-
-    public Optional<JavaAwtImageJdo> find(final BufferedImage readOnlyProperty) {
-        return repositoryService.firstMatch(JavaAwtImageJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
-    }
-
-    public List<JavaAwtImageJdo> all() {
-        return repositoryService.allInstances(JavaAwtImageJdo.class);
-    }
-
-    @Inject
-    RepositoryService repositoryService;
+package demoapp.dom.types.javaawt.images.persistence;
+
+import org.apache.isis.applib.annotation.DomainObject;
+
+import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
+import demoapp.dom._infra.values.ValueHolder;
+
+@DomainObject(
+        objectType = "demo.JavaAwtImageEntity" // shared permissions with concrete sub class
+)
+public abstract class JavaAwtImageEntity
+implements
+    HasAsciiDocDescription,
+    //JavaAwtImageHolder2,
+    ValueHolder<java.awt.image.BufferedImage> {
+
+//    @Override
+//    public java.awt.image.BufferedImage value() {
+//        return getReadOnlyProperty();
+//    }
 
 }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdo.layout.xml b/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/persistence/JavaAwtImageEntity.layout.xml
similarity index 100%
rename from examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdo.layout.xml
rename to examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/persistence/JavaAwtImageEntity.layout.xml
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/persistence/JavaAwtImageSeeding.java
similarity index 63%
copy from examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java
copy to examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/persistence/JavaAwtImageSeeding.java
index aa7f929..8f782aa 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/jdo/JavaAwtImageJdoEntities.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/javaawt/images/persistence/JavaAwtImageSeeding.java
@@ -16,30 +16,24 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.types.javaawt.images.jdo;
+package demoapp.dom.types.javaawt.images.persistence;
 
 import java.awt.image.BufferedImage;
-import java.util.List;
-import java.util.Optional;
 
 import javax.inject.Inject;
 
 import org.springframework.stereotype.Service;
 
-import org.apache.isis.applib.services.repository.RepositoryService;
+import demoapp.dom._infra.seed.SeedServiceAbstract;
+import demoapp.dom._infra.values.ValueHolderRepository;
 
 @Service
-public class JavaAwtImageJdoEntities {
-
-    public Optional<JavaAwtImageJdo> find(final BufferedImage readOnlyProperty) {
-        return repositoryService.firstMatch(JavaAwtImageJdo.class, x -> x.getReadOnlyProperty() == readOnlyProperty);
-    }
-
-    public List<JavaAwtImageJdo> all() {
-        return repositoryService.allInstances(JavaAwtImageJdo.class);
-    }
+public class JavaAwtImageSeeding
+extends SeedServiceAbstract {
 
     @Inject
-    RepositoryService repositoryService;
+    public JavaAwtImageSeeding(ValueHolderRepository<BufferedImage, ? extends JavaAwtImageEntity> entities) {
+        super(entities);
+    }
 
-}
+}
\ No newline at end of file