You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by da...@apache.org on 2023/03/27 19:23:25 UTC

[causeway] branch CAUSEWAY-2485 created (now 886709cfdb)

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

danhaywood pushed a change to branch CAUSEWAY-2485
in repository https://gitbox.apache.org/repos/asf/causeway.git


      at 886709cfdb CAUSEWAY-2485: adds @DomainObject#bounding to demo app

This branch includes the following new commits:

     new 886709cfdb CAUSEWAY-2485: adds @DomainObject#bounding to demo app

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[causeway] 01/01: CAUSEWAY-2485: adds @DomainObject#bounding to demo app

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch CAUSEWAY-2485
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit 886709cfdb3f5901858796d9e6c105299c8870ef
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Mon Mar 27 20:23:18 2023 +0100

    CAUSEWAY-2485: adds @DomainObject#bounding to demo app
---
 .../src/main/java/demoapp/dom/DemoModuleJpa.java   |  2 +
 .../aliased/DomainObjectAliasedVm-description.adoc |  1 +
 .../aliased/DomainObjectAliasedVm.layout.xml       |  2 +
 .../DomainObjectAutoCompleteVm-description.adoc    |  5 ++-
 .../DomainObjectAutoCompleteVm.layout.xml          |  2 +
 .../DomainObjectAutoCompleteVm_find.java           |  5 +--
 .../jpa/DomainObjectAutoCompleteJpa.java           |  4 +-
 .../DomainObject/bounded/DomainObjectBounding.java | 45 +++++++++++++++++++++
 .../DomainObjectBounding.layout.xml}               | 47 +++++++++++++++++-----
 .../bounded/DomainObjectBoundingSeeding.java       | 38 +++++++++++++++++
 .../DomainObjectBoundingVm-description.adoc        | 27 ++++++++++---
 .../bounded/DomainObjectBoundingVm.layout.xml      |  5 +++
 .../bounded/DomainObjectBoundingVm_objects.java    | 32 +++++++++++++++
 .../DomainObjectBoundingJpa-description.adoc}      | 13 +++---
 .../jpa/DomainObjectBoundingJpa.java}              | 17 ++++----
 .../jpa/DomainObjectBoundingJpaEntities.java       | 40 ++++++++++++++++++
 .../bounded/jpa/DomainObjectBoundingVm_find.java   | 27 +++++++++++++
 17 files changed, 274 insertions(+), 38 deletions(-)

diff --git a/examples/demo/domain/src/main/java/demoapp/dom/DemoModuleJpa.java b/examples/demo/domain/src/main/java/demoapp/dom/DemoModuleJpa.java
index 86afd966fe..cd47ca03b2 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/DemoModuleJpa.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/DemoModuleJpa.java
@@ -30,6 +30,7 @@ import demoapp.dom.domain.actions.Action.commandPublishing.jpa.ActionCommandPubl
 import demoapp.dom.domain.actions.Action.executionPublishing.jpa.ActionExecutionPublishingJpa;
 import demoapp.dom.domain.objects.DomainObject.aliased.jpa.DomainObjectAliasedJpa;
 import demoapp.dom.domain.objects.DomainObject.autoComplete.jpa.DomainObjectAutoCompleteJpa;
+import demoapp.dom.domain.objects.DomainObject.bounded.jpa.DomainObjectBoundingJpa;
 import demoapp.dom.domain.objects.DomainObject.entityChangePublishing.annotated.disabled.jpa.DomainObjectEntityChangePublishingDisabledJpa;
 import demoapp.dom.domain.objects.DomainObject.entityChangePublishing.annotated.enabled.jpa.DomainObjectEntityChangePublishingEnabledJpa;
 import demoapp.dom.domain.objects.DomainObject.entityChangePublishing.metaAnnot.enabled.jpa.DomainObjectEntityChangePublishingEnabledMetaAnnotatedJpa;
@@ -95,6 +96,7 @@ import demoapp.dom.types.primitive.shorts.jpa.PrimitiveShortJpa;
 
         DomainObjectAliasedJpa.class,
         DomainObjectAutoCompleteJpa.class,
+        DomainObjectBoundingJpa.class,
 
         CausewayBlobJpa.class,
         CausewayClobJpa.class,
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/aliased/DomainObjectAliasedVm-description.adoc b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/aliased/DomainObjectAliasedVm-description.adoc
index 003a3ad349..4ba9b43570 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/aliased/DomainObjectAliasedVm-description.adoc
+++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/aliased/DomainObjectAliasedVm-description.adoc
@@ -22,6 +22,7 @@ The "lookup" (mixin) action uses the https://causeway.apache.org/refguide/2.0.0-
 For convenience, the action provides a choices method for all possible values.
 
 [source,java,indent=0]
+.DomainObjectAliasedVm_lookup.java
 ----
 include::DomainObjectAliasedVm_lookup.java[tags=class]
 ----
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/aliased/DomainObjectAliasedVm.layout.xml b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/aliased/DomainObjectAliasedVm.layout.xml
index 6475b00890..e09c011efa 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/aliased/DomainObjectAliasedVm.layout.xml
+++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/aliased/DomainObjectAliasedVm.layout.xml
@@ -39,6 +39,8 @@
 				<cpt:action id="downloadMetamodelXml"  position="PANEL_DROPDOWN"/>
 				<cpt:action id="inspectMetamodel"  position="PANEL_DROPDOWN"/>
                 <cpt:action id="recentCommands"  position="PANEL_DROPDOWN"/>
+                <cpt:action id="recentExecutions"  position="PANEL_DROPDOWN"/>
+                <cpt:action id="recentAuditTrailEntries"  position="PANEL_DROPDOWN"/>
 				<cpt:action id="downloadJdoMetadata"  position="PANEL_DROPDOWN"/>
 				<cpt:action id="openRestApi" position="PANEL_DROPDOWN" />
 				<cpt:property id="description"/>
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/DomainObjectAutoCompleteVm-description.adoc b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/DomainObjectAutoCompleteVm-description.adoc
index b44e2a81d1..2ffd132ead 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/DomainObjectAutoCompleteVm-description.adoc
+++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/DomainObjectAutoCompleteVm-description.adoc
@@ -1,7 +1,6 @@
 :Notice: 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 ag [...]
 
 If an action parameter is a reference type (typically an entity), then a mechanism is required to present a list of relevant existing instances for the end-user to select.
-One means to do that is to write a supporting `choices` or `autoComplete` method for the action; `choices` if there is a comparatively short list, or `autoComplete` if the list of candidates if long: the end-user enters some characters and these are used to search for available instances that are relevant for this particular action.
 
 If the list of available instances is always or often the same, then this can result in a lot of boilerplate.
 The link:https://causeway.apache.org/refguide/2.0.0-SNAPSHOT/applib/index/annotation/DomainObject.html#autoCompleteRepository[@DomainObject#autoCompleteRepository] attribute allows a `@Repository` service to be nominated as containing a suitable `autoComplete(String)` method returning a list of the corresponding domain class.
@@ -16,11 +15,13 @@ The collection on the left shows a set of entity instances, of type `DomainObjec
 The "find" (mixin) action defines the entity class as its parameter type, and simply returns it.
 
 [source,java,indent=0]
+.DomainObjectAutoCompleteVm_find.java
 ----
 include::DomainObjectAutoCompleteVm_find.java[tags=class]
 ----
 
-<.> xxx
+<.> just returns the provided object.
+The main work is performed when the framework renders the action prompt, using the `autoCompleteXxx` attributes to determine how to obtain the objects to provide (in a drop-down list box).
 
 The autoComplete search to perform is specified using the link:https://causeway.apache.org/refguide/2.0.0-SNAPSHOT/applib/index/annotation/DomainObject.html#autoCompleteRepository[autoCompleteRepository] and link:https://causeway.apache.org/refguide/2.0.0-SNAPSHOT/applib/index/annotation/DomainObject.html#autoCompleteMethod[autoCompleteMethod] attributes.
 
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/DomainObjectAutoCompleteVm.layout.xml b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/DomainObjectAutoCompleteVm.layout.xml
index 18ecaf7b16..319686dee1 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/DomainObjectAutoCompleteVm.layout.xml
+++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/DomainObjectAutoCompleteVm.layout.xml
@@ -39,6 +39,8 @@
 				<cpt:action id="downloadMetamodelXml"  position="PANEL_DROPDOWN"/>
 				<cpt:action id="inspectMetamodel"  position="PANEL_DROPDOWN"/>
                 <cpt:action id="recentCommands"  position="PANEL_DROPDOWN"/>
+                <cpt:action id="recentExecutions"  position="PANEL_DROPDOWN"/>
+                <cpt:action id="recentAuditTrailEntries"  position="PANEL_DROPDOWN"/>
 				<cpt:action id="downloadJdoMetadata"  position="PANEL_DROPDOWN"/>
 				<cpt:action id="openRestApi" position="PANEL_DROPDOWN" />
 				<cpt:property id="description"/>
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/DomainObjectAutoCompleteVm_find.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/DomainObjectAutoCompleteVm_find.java
index cb934a5f35..9e9423786e 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/DomainObjectAutoCompleteVm_find.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/DomainObjectAutoCompleteVm_find.java
@@ -1,6 +1,5 @@
 package demoapp.dom.domain.objects.DomainObject.autoComplete;
 
-import demoapp.dom.domain.objects.DomainObject.aliased.DomainObjectAliased;
 import lombok.RequiredArgsConstructor;
 
 import org.apache.causeway.applib.annotation.Action;
@@ -16,8 +15,8 @@ public class DomainObjectAutoCompleteVm_find {
     private final DomainObjectAutoCompleteVm mixee;
 
     @MemberSupport
-    public DomainObjectAliased act(final DomainObjectAliased domainObjectAliased) {  // <.>
-        return domainObjectAliased;
+    public DomainObjectAutoComplete act(final DomainObjectAutoComplete domainObjectAutoComplete) {  // <.>
+        return domainObjectAutoComplete;
     }
 
 }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/jpa/DomainObjectAutoCompleteJpa.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/jpa/DomainObjectAutoCompleteJpa.java
index 3680f28df1..44520dbae9 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/jpa/DomainObjectAutoCompleteJpa.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/jpa/DomainObjectAutoCompleteJpa.java
@@ -36,10 +36,10 @@ import org.springframework.context.annotation.Profile;
 @Entity
 @Table(
     schema = "demo",
-    name = "DomainObjectAutoCompleteCustomerJpa"
+    name = "DomainObjectAutoCompleteJpa"
 )
 @EntityListeners(CausewayEntityListener.class)
-@Named("demo.autoComplete.Customer")
+@Named("demo.DomainObjectAutoComplete")
 @DomainObject(
         autoCompleteRepository = DomainObjectAutoCompleteRepository.class,  // <.>
         autoCompleteMethod = "findMatching"                 // <.>
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBounding.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBounding.java
new file mode 100644
index 0000000000..56657db6ac
--- /dev/null
+++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBounding.java
@@ -0,0 +1,45 @@
+/*
+ *  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.domain.objects.DomainObject.bounded;
+
+import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
+import demoapp.dom._infra.values.ValueHolder;
+
+import org.apache.causeway.applib.annotation.Bounding;
+import org.apache.causeway.applib.annotation.DomainObject;
+
+@SuppressWarnings("CdiManagedBeanInconsistencyInspection")
+public abstract class DomainObjectBounding
+        implements
+        HasAsciiDocDescription,
+        ValueHolder<String> {
+
+    public String title() {
+        return value();
+    }
+
+    @Override
+    public String value() {
+        return getName();
+    }
+
+    public abstract String getName();
+    public abstract void setName(String value);
+
+}
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/DomainObjectAutoCompleteVm.layout.xml b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBounding.layout.xml
similarity index 63%
copy from examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/DomainObjectAutoCompleteVm.layout.xml
copy to examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBounding.layout.xml
index 18ecaf7b16..1135efb565 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/DomainObjectAutoCompleteVm.layout.xml
+++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBounding.layout.xml
@@ -26,25 +26,52 @@
 
 	<bs3:row>
 		<bs3:col span="6">
-			<cpt:fieldSet name="Other" id="other" unreferencedProperties="true"/>
-			<cpt:collection id="objects">
-				<cpt:action id="find"/>
-			</cpt:collection>
+			<bs3:tabGroup>
+				<bs3:tab name="General">
+					<bs3:row>
+						<bs3:col span="12">
+							<cpt:fieldSet name="General" id="general" >
+								<cpt:property id="name"/>
+							</cpt:fieldSet>
+						</bs3:col>
+					</bs3:row>
+				</bs3:tab>
+				<bs3:tab name="Metadata">
+					<bs3:row>
+						<bs3:col span="12">
+							<cpt:fieldSet name="Metadata" id="metadata" >
+								<cpt:property id="id"/>
+								<cpt:property id="logicalTypeName"/>
+								<cpt:property id="version"/>
+							</cpt:fieldSet>
+						</bs3:col>
+					</bs3:row>
+				</bs3:tab>
+				<bs3:tab name="Other">
+					<bs3:row>
+						<bs3:col span="12">
+							<cpt:fieldSet name="Other" id="other" unreferencedProperties="true"/>
+						</bs3:col>
+					</bs3:row>
+				</bs3:tab>
+			</bs3:tabGroup>
 		</bs3:col>
 		<bs3:col span="6">
 			<cpt:fieldSet name="Description" id="description" >
 				<cpt:action id="clearHints" position="PANEL" />
-				<cpt:action id="downloadLayoutXml"  position="PANEL_DROPDOWN"/>
 				<cpt:action id="rebuildMetamodel" position="PANEL"/>
-				<cpt:action id="downloadMetamodelXml"  position="PANEL_DROPDOWN"/>
+				<cpt:action id="downloadLayout"  position="PANEL_DROPDOWN"/>
 				<cpt:action id="inspectMetamodel"  position="PANEL_DROPDOWN"/>
-                <cpt:action id="recentCommands"  position="PANEL_DROPDOWN"/>
-				<cpt:action id="downloadJdoMetadata"  position="PANEL_DROPDOWN"/>
+				<cpt:action id="downloadMetamodelXml"  position="PANEL_DROPDOWN"/>
+				<cpt:action id="downloadJdoMetamodel"  position="PANEL_DROPDOWN"/>
+				<cpt:action id="recentCommands"  position="PANEL_DROPDOWN"/>
+				<cpt:action id="recentExecutions"  position="PANEL_DROPDOWN"/>
+				<cpt:action id="recentAuditTrailEntries"  position="PANEL_DROPDOWN"/>
+				<cpt:action id="impersonateWithRoles"  position="PANEL_DROPDOWN"/>
 				<cpt:action id="openRestApi" position="PANEL_DROPDOWN" />
 				<cpt:property id="description"/>
 			</cpt:fieldSet>
-		</bs3:col>
-	</bs3:row>
+		</bs3:col>	</bs3:row>
 	<bs3:row>
 		<bs3:col span="12" unreferencedCollections="true"/>
 	</bs3:row>
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBoundingSeeding.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBoundingSeeding.java
new file mode 100644
index 0000000000..583f4dcb6c
--- /dev/null
+++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBoundingSeeding.java
@@ -0,0 +1,38 @@
+/*
+ *  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.domain.objects.DomainObject.bounded;
+
+import demoapp.dom._infra.seed.SeedServiceAbstract;
+import demoapp.dom._infra.values.ValueHolderRepository;
+
+import javax.inject.Inject;
+
+import org.springframework.stereotype.Service;
+
+@Service
+public class DomainObjectBoundingSeeding
+extends SeedServiceAbstract {
+
+    @Inject
+    public DomainObjectBoundingSeeding(
+            ValueHolderRepository<String, ? extends DomainObjectBounding> entities) {
+        super(entities);
+    }
+
+}
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBoundingVm-description.adoc b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBoundingVm-description.adoc
index f44168d7a4..f60a3122c3 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBoundingVm-description.adoc
+++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBoundingVm-description.adoc
@@ -1,10 +1,27 @@
 :Notice: 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 ag [...]
 
-The `bounding` attribute ...
+If an action parameter is a reference type (typically an entity), then a mechanism is required to present a list of relevant existing instances for the end-user to select.
 
-WARNING: TODO[CAUSEWAY-3312]
-Indicates that the class has a bounded, or finite, set of instances.
-Takes precedence over auto-complete.
-Note: this replaces bounded=true|false prior to v2.x
+One means to do that is to write a supporting `choices` or `autoComplete` method for the action.
+If the entity is "reference data" with a small, fixed set of instances, then a better option is to declare that the entity is bounded (as in "has a bounded set of instances").
+This is done using link:https://causeway.apache.org/refguide/2.0.0-SNAPSHOT/applib/index/annotation/DomainObject.html#bounding[@DomainObject#bounding] attribute.
 
+=== How this demo works
 
+The collection on the left shows a set of entity instances, of type `DomainObjectBounding`.
+
+The "find" (mixin) action defines the entity class as its parameter type, and simply returns it.
+
+For example, with JPA:
+
+[source,java,indent=0]
+.DomainObjectBoundingVm_find.java
+----
+include::jpa/DomainObjectBoundingVm_find.java[tags=class]
+----
+<.> just returns the provided object.
+The main work is performed when the framework renders the action prompt, using the `bounding` attribute to determine how to obtain the objects to provide (in a drop-down list box).
+
+Note that the class must be concrete.
+
+Navigate through to the entity to see the corresponding source code.
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBoundingVm.layout.xml b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBoundingVm.layout.xml
index b4f853de75..319686dee1 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBoundingVm.layout.xml
+++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBoundingVm.layout.xml
@@ -27,6 +27,9 @@
 	<bs3:row>
 		<bs3:col span="6">
 			<cpt:fieldSet name="Other" id="other" unreferencedProperties="true"/>
+			<cpt:collection id="objects">
+				<cpt:action id="find"/>
+			</cpt:collection>
 		</bs3:col>
 		<bs3:col span="6">
 			<cpt:fieldSet name="Description" id="description" >
@@ -36,6 +39,8 @@
 				<cpt:action id="downloadMetamodelXml"  position="PANEL_DROPDOWN"/>
 				<cpt:action id="inspectMetamodel"  position="PANEL_DROPDOWN"/>
                 <cpt:action id="recentCommands"  position="PANEL_DROPDOWN"/>
+                <cpt:action id="recentExecutions"  position="PANEL_DROPDOWN"/>
+                <cpt:action id="recentAuditTrailEntries"  position="PANEL_DROPDOWN"/>
 				<cpt:action id="downloadJdoMetadata"  position="PANEL_DROPDOWN"/>
 				<cpt:action id="openRestApi" position="PANEL_DROPDOWN" />
 				<cpt:property id="description"/>
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBoundingVm_objects.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBoundingVm_objects.java
new file mode 100644
index 0000000000..0e269cb008
--- /dev/null
+++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBoundingVm_objects.java
@@ -0,0 +1,32 @@
+package demoapp.dom.domain.objects.DomainObject.bounded;
+
+import demoapp.dom._infra.values.ValueHolderRepository;
+import demoapp.dom.domain.objects.DomainObject.autoComplete.DomainObjectAutoComplete;
+import demoapp.dom.domain.objects.DomainObject.autoComplete.DomainObjectAutoCompleteVm;
+import lombok.RequiredArgsConstructor;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.causeway.applib.annotation.Collection;
+import org.apache.causeway.applib.annotation.CollectionLayout;
+import org.apache.causeway.applib.annotation.MemberSupport;
+
+@Collection()
+@CollectionLayout()
+@RequiredArgsConstructor
+public class DomainObjectBoundingVm_objects {
+
+    @SuppressWarnings("unused")
+    private final DomainObjectBoundingVm mixee;
+
+    @MemberSupport
+    public List<? extends DomainObjectBounding> coll() {
+        return objectRepository.all();
+    }
+
+    @Inject
+    ValueHolderRepository<String, ? extends DomainObjectBounding> objectRepository;
+
+}
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBoundingVm-description.adoc b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/jpa/DomainObjectBoundingJpa-description.adoc
similarity index 77%
copy from examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBoundingVm-description.adoc
copy to examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/jpa/DomainObjectBoundingJpa-description.adoc
index f44168d7a4..00d80cab53 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/DomainObjectBoundingVm-description.adoc
+++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/jpa/DomainObjectBoundingJpa-description.adoc
@@ -1,10 +1,9 @@
 :Notice: 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 ag [...]
 
-The `bounding` attribute ...
-
-WARNING: TODO[CAUSEWAY-3312]
-Indicates that the class has a bounded, or finite, set of instances.
-Takes precedence over auto-complete.
-Note: this replaces bounded=true|false prior to v2.x
-
+[source,java,indent=0]
+.DomainObjectBoundingJpa.java
+----
+include::DomainObjectBoundingJpa.java[tags=class]
+----
+<.> indicates that there are a fixed (bounded) set of instances of this domain object.
 
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/jpa/DomainObjectAutoCompleteJpa.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/jpa/DomainObjectBoundingJpa.java
similarity index 71%
copy from examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/jpa/DomainObjectAutoCompleteJpa.java
copy to examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/jpa/DomainObjectBoundingJpa.java
index 3680f28df1..b3d37d0bff 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/autoComplete/jpa/DomainObjectAutoCompleteJpa.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/jpa/DomainObjectBoundingJpa.java
@@ -16,10 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.domain.objects.DomainObject.autoComplete.jpa;
+package demoapp.dom.domain.objects.DomainObject.bounded.jpa;
 
-import demoapp.dom.domain.objects.DomainObject.autoComplete.DomainObjectAutoComplete;
-import demoapp.dom.domain.objects.DomainObject.autoComplete.DomainObjectAutoCompleteRepository;
+import demoapp.dom.domain.objects.DomainObject.bounded.DomainObjectBounding;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
@@ -27,6 +26,7 @@ import lombok.Setter;
 import javax.inject.Named;
 import javax.persistence.*;
 
+import org.apache.causeway.applib.annotation.Bounding;
 import org.apache.causeway.applib.annotation.DomainObject;
 import org.apache.causeway.persistence.jpa.applib.integration.CausewayEntityListener;
 import org.springframework.context.annotation.Profile;
@@ -36,20 +36,19 @@ import org.springframework.context.annotation.Profile;
 @Entity
 @Table(
     schema = "demo",
-    name = "DomainObjectAutoCompleteCustomerJpa"
+    name = "DomainObjectBoundingJpa"
 )
 @EntityListeners(CausewayEntityListener.class)
-@Named("demo.autoComplete.Customer")
+@Named("demo.DomainObjectBounding")
 @DomainObject(
-        autoCompleteRepository = DomainObjectAutoCompleteRepository.class,  // <.>
-        autoCompleteMethod = "findMatching"                 // <.>
+        bounding = Bounding.BOUNDED         // <.>
 )
 @NoArgsConstructor
-public class DomainObjectAutoCompleteJpa extends DomainObjectAutoComplete {
+public class DomainObjectBoundingJpa extends DomainObjectBounding {
     // ...
 //end::class[]
 
-    public DomainObjectAutoCompleteJpa(String value) {
+    public DomainObjectBoundingJpa(String value) {
         setName(value);
     }
 
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/jpa/DomainObjectBoundingJpaEntities.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/jpa/DomainObjectBoundingJpaEntities.java
new file mode 100644
index 0000000000..844036973c
--- /dev/null
+++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/jpa/DomainObjectBoundingJpaEntities.java
@@ -0,0 +1,40 @@
+/*
+ *  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.domain.objects.DomainObject.bounded.jpa;
+
+import demoapp.dom._infra.values.ValueHolderRepository;
+
+import org.springframework.context.annotation.Profile;
+import org.springframework.stereotype.Service;
+
+@Profile("demo-jpa")
+@Service
+public class DomainObjectBoundingJpaEntities
+extends ValueHolderRepository<String, DomainObjectBoundingJpa> {
+
+    protected DomainObjectBoundingJpaEntities() {
+        super(DomainObjectBoundingJpa.class);
+    }
+
+    @Override
+    protected DomainObjectBoundingJpa newDetachedEntity(String value) {
+        return new DomainObjectBoundingJpa(value);
+    }
+
+}
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/jpa/DomainObjectBoundingVm_find.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/jpa/DomainObjectBoundingVm_find.java
new file mode 100644
index 0000000000..8ba34e7f0c
--- /dev/null
+++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/bounded/jpa/DomainObjectBoundingVm_find.java
@@ -0,0 +1,27 @@
+package demoapp.dom.domain.objects.DomainObject.bounded.jpa;
+
+import demoapp.dom.domain.objects.DomainObject.bounded.DomainObjectBounding;
+import demoapp.dom.domain.objects.DomainObject.bounded.DomainObjectBoundingVm;
+import lombok.RequiredArgsConstructor;
+
+import org.apache.causeway.applib.annotation.Action;
+import org.apache.causeway.applib.annotation.MemberSupport;
+import org.apache.causeway.applib.annotation.SemanticsOf;
+import org.springframework.context.annotation.Profile;
+
+//tag::class[]
+@Profile("demo-jpa")
+@Action(semantics = SemanticsOf.SAFE)
+@RequiredArgsConstructor
+public class DomainObjectBoundingVm_find {
+
+    @SuppressWarnings("unused")
+    private final DomainObjectBoundingVm mixee;
+
+    @MemberSupport
+    public DomainObjectBoundingJpa act(final DomainObjectBoundingJpa domainObjectBounding) {  // <.>
+        return domainObjectBounding;
+    }
+
+}
+//end::class[]