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

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

commit bebe78fc002e2dfbf77fe79fabb8ac96f2a02871
Author: Dan Haywood <[email protected]>
AuthorDate: Wed May 22 23:21:27 2024 +0100

    CAUSEWAY-2873: updates petclinic tutorial up to 2.5 incl.
---
 .../petclinic/pages/010-getting-started.adoc       |  40 ++-
 .../petclinic/pages/020-the-petclinic-domain.adoc  | 317 ++++++++++++++++++++-
 .../partials/fixture-scripts/api-and-usage.adoc    |   1 +
 3 files changed, 330 insertions(+), 28 deletions(-)

diff --git 
a/antora/components/tutorials/modules/petclinic/pages/010-getting-started.adoc 
b/antora/components/tutorials/modules/petclinic/pages/010-getting-started.adoc
index ec13043e16..a4a1e6e8a8 100644
--- 
a/antora/components/tutorials/modules/petclinic/pages/010-getting-started.adoc
+++ 
b/antora/components/tutorials/modules/petclinic/pages/010-getting-started.adoc
@@ -10,11 +10,11 @@ You'll need:
 
 * Java 11
 +
-Apache Causeway should work up to at least Java 15, but stick with Java 11 for 
now.
+Apache Causeway works up to at least Java 21, but stick with Java 11 for now.
 
-* Maven 3.6.x
+* Maven 3.9.x
 +
-Maven 3.6.x or later is recommended.
+Maven 3.9.x or later is recommended.
 
 * git
 +
@@ -25,14 +25,14 @@ This has multiple tags for the various checkpoints so you 
can pick up the tutori
 +
 The Apache Causeway website has detailed documentation for setting up to use 
xref:setupguide:intellij:about.adoc[IntelliJ] or 
xref:setupguide:eclipse:about.adoc[Eclipse].
 +
-For this tutorial, make sure that your IDE is configured to support Lombok.
+For this tutorial, also make sure that your IDE is configured to support 
Lombok.
 
 
 
 [#exercise-1-1-starter-apps-clone-the-repo]
 == Ex 1.1: Starter apps / clone the repo
 
-Apache Causeway provides a two starter apps, 
xref:docs:starters:helloworld.adoc[HelloWorld] and 
xref:docs:starters:simpleapp.adoc[SimpleApp].
+Apache Causeway provides two starter apps, 
xref:docs:starters:helloworld.adoc[HelloWorld] and 
xref:docs:starters:simpleapp.adoc[SimpleApp].
 These are identical in terms of functionality, but the simpleapp provides more 
structure and includes example tests.
 
 NOTE: there are JPA and JDO variants of the starter apps.
@@ -40,7 +40,6 @@ This tutorial uses JPA as it is the more commonly used 
persistence mechanism.
 
 We start the tutorial simply with a copy of 
xref:docs:starters:simpleapp.adoc[SimpleApp]; in subsequent exercises we'll 
refactor and build upon it to morph it into the petclinic domain.
 
-
 * Clone the repo:
 +
 [source,bash]
@@ -59,6 +58,16 @@ This will make it easier to inspect differences between 
different tags.
 git checkout tags/01-01-starter-app
 mvn clean install
 ----
++
+[NOTE]
+====
+The code at this tag was created by copying the `v2-jpa` tag of 
xref:docs:starters:simpleapp.adoc[SimpleApp]:
+
+[source,bash]
+----
+curl https://codeload.github.com/apache/causeway-app-simpleapp/zip/v2-jpa | 
jar xv
+----
+====
 
 * run the app:
 +
@@ -93,13 +102,11 @@ Running from the command line isn't ideal, so
 
 * load the project into your IDE as a Maven project, build and run.
 
-* The app is a Spring boot application, so locate the class with a main, and 
run.
+* The app is a Spring boot application, so locate the class with a `main()` 
method, and run.
 
 * alternatively, your IDE might also have specialised support for Spring Boot 
apps, so run the app that way if you wish.
 
-* with the IDE load
-
-If you want to go deeper, open up the xref:docs:starters:simpleapp.adoc[page 
describing the SimpleApp] and start to explore the 
xref:docs:starters:simpleapp.adoc#structure-of-the-app[structure of the app] 
files.
+If you want to go deeper, use the xref:docs:starters:simpleapp.adoc[Simple App 
docs] to xref:docs:starters:simpleapp.adoc#structure-of-the-app[explore the 
structure] of the application.
 
 
 
@@ -111,10 +118,9 @@ Apache Causeway is an implementation of the _naked objects 
pattern_, which means
 [TIP]
 ====
 An ORM such as JPA (EclipseLink or Hibernate) maps domain objects into an 
RDBMS or other datastore.
-You can think of Apache Causeway (and naked objects) similarly, but it's an 
OIM - an object _interface_ mapper.
-It maps to the UI layer rather than the persistence layer.
+Apache Causeway does a similar trick, but in the opposite direction: it maps 
the domain objects to the UI layer.
 
-Common to both ORMs and OIMs is an internal metamodel; this is where much of 
the power comes from.
+Common to both is an internal metamodel, which is where much of the power 
comes from.
 ====
 
 We can explore this by looking at the classes provided by the starter app:
@@ -167,7 +173,7 @@ Typically this is static and in the same package as the 
class; see `SimpleObject
 
 *Mini-Exercise*:
 
-(No solution is provided for this exercise).
+(no solution is provided for this exercise).
 
 * replace the `@Title` annotation with a `title()` method:
 +
@@ -190,7 +196,7 @@ In many cases the details of that representation can be 
inferred directly from t
 For example the label of a field for an object's property (eg 
`SimpleObject#name`) can be derived directly from the name of the object 
property itself (`getName()`).
 
 In the absence of other metadata, Apache Causeway will render a domain object 
with its properties to the left-hand side and its collections (if any) to the 
right.
-The order of these properties and collections can be specified using the 
`@PropertyLayout` annotation and the `@CollectionLayout` annotation.
+The order of these properties and collections can be specified using the 
xref:refguide:applib:index/annotation/PropertyLayout.adoc[@PropertyLayout] 
annotation and the 
xref:refguide:applib:index/annotation/CollectionLayout.adoc[@CollectionLayout] 
annotation.
 There are other annotations to group properties together and to associate 
action buttons with either properties or collections.
 
 The downside of using annotations is that changing the layout requires that 
the application be restarted, and certain more complex UIs, such as 
multi-columns or tab groups are difficult or impossible to express.
@@ -200,6 +206,8 @@ This is modelled upon bootstrap and so supports arbitrary 
rows and columns as we
 
 *Mini-Exercise*:
 
+(no solution is provided for this exercise).
+
 * locate the `SimpleObject.layout.xml` file
 * compare the structure of the layout file to that of the rendered object
 * change the file, eg the relative widths of the columns
@@ -220,6 +228,8 @@ In a similar fashion, the actions of the various domain 
services are grouped int
 
 *Mini-Exercise*:
 
+(no solution is provided for this exercise).
+
 * locate the `menubars.layout.xml` file
 * compare the structure of the layout file to that of the rendered menu bar
 * change the file, eg reorder menu items or create new menus
diff --git 
a/antora/components/tutorials/modules/petclinic/pages/020-the-petclinic-domain.adoc
 
b/antora/components/tutorials/modules/petclinic/pages/020-the-petclinic-domain.adoc
index bd3033c4a4..72d06a82ee 100644
--- 
a/antora/components/tutorials/modules/petclinic/pages/020-the-petclinic-domain.adoc
+++ 
b/antora/components/tutorials/modules/petclinic/pages/020-the-petclinic-domain.adoc
@@ -29,36 +29,327 @@ Some of the use cases we might want to support include:
 This tutorial has worked solutions for all of these.
 
 [#exercise-2-1-refactor-simpleobject-to-petowner]
-== Ex 2.1: Refactor `SimpleObject` to `PetOwner`
+== Ex 2.1: Create a new `pets` module with `PetOwner`
+
+Using the `simple` module as a guide, we'll create a new `petowners` module 
and create a `PetOwner` and `PetOwners` domain service as reference.
+(We leave the `simple` module untouched, to use as a reference).
 
-To start with, let's rename the `SimpleObject` entity to `PetOwner`
 
 === Solution
 
 [source,bash]
 ----
-git checkout tags/02-01-renames-SimpleObject-to-PetOwner
+git checkout tags/02-01-copies-SimpleObject-to-PetOwner
 mvn clean install
 mvn -pl spring-boot:run
 ----
 
 === Tasks
 
-Just checkout the solution above and review the git history to see the changes 
that have already been made.
-These include:
-
-* Domain classes renamed (along with corresponding tests)
+To save time, just checkout the solution tag above and review the git history 
to see the classes that were copied and renamed:
 
-** `SimpleObject` entity -> `PetOwner`
-** `SimpleObjects` domain service -> `PetOwners`
+* `dom.petowner` package:
+** `SimpleObject` -> `PetOwner` (entity)
++
+plus related `.layout.xml`, `.png` and `.columnOrder.txt` files
+** `SimpleObjects` -> `PetOwners` (domain service)
 ** `SimpleObjectRepository` repository service -> `PetOwnerRepository`
+** `SimpleModule` -> `PetOwnerModule` (module)
+* `fixture` package:
+** `PetOwner_persona` (fixture script)
+* `types` package
+** `Name` (meta annotation)
+** `Notes` (meta annotation)
+* root package of module
+** `PetOwnerModule` (Spring `@Configuration`, aka module class)
+
+* In the `PetOwnerModule`, the namespace and schema constants were changed:
++
+[source, java]
+.PetOwnerModule.java
+----
+// ...
+public class PetOwnerModule implements ModuleWithFixtures {
+
+    public static final String NAMESPACE = "petowner";
+    public static final String SCHEMA = "petowner";
+
+    // ...
+}
+----
+
+* in `application.properties`, the "petowner" schema was also added to the 
xref:refguide:config:sections/causeway.persistence.schema.adoc#causeway.persistence.schema.auto-create-schemas[causeway.persistence.schema.auto-create-schemas]
 config property:
++
+[source,properties]
+.application.properties
+----
+causeway.persistence.schema.auto-create-schemas=petowner,simple,...
+----
+
+Resource classes were also copied.
+
+In addition, the new Maven module was defined in the top-level `pom.xml`, and 
included in `<modules>`.
+
+Confirm that the code still builds:
+
+[source,bash]
+----
+mvn install
+----
+
+However, if you run the app confirm that it is still showing just the original 
`simpleapp` module:
+
+[source,bash]
+----
+mvn -pl webapp spring-boot:run
+----
+
+We'll fix this in the next exercise.
+
+
+[#exercise-2-2-configure-the-app-to-include-the-petowner-module]
+== Ex 2.2: Configure the app to include the `petowner` module
+
+We have our new `petowner` module, but we're not actually using it; if we run 
the application we still see the original `simpleapp` module.
+
+[source,bash]
+----
+mvn -pl webapp spring-boot:run
+----
 
-** Infrastructure classes renamed
+In this exercise we'll update the app to include `petowners` as well.
 
-** `SimpleModule` -> `PetsModule`
-** `SimpleApp` -> `PetClinicApp`
 
+=== Solution
+
+[source,bash]
+----
+git checkout tags/02-02-configure-the-app-to-include-petowner
+mvn clean install
+mvn -pl spring-boot:run
+----
+
+=== Tasks
+
+Rename the main class that acts as the entry point for the app (annotated with 
`@@SpringBootApplication`):
+
+* locate the `SimpleApp` class and rename to `PetClinicApp`
+
+* Also update classes that reference this type (in particular, in `pom.xml`).
++
+Your IDE can probably do this for you automatically.
+
+The `PetClinicApp` main class references the `AppManifest`, a top-level Spring 
`@Configuration` which imports all the other classes.
+
+* Inspect the `AppManifest` class: most will be ``CausewayXxxModule``s
+* note that it also imports the `ApplicationModule`, which defines your own 
modules which make up the application
+
+We want to update `ApplicationModule` to reference `PetOwnerModule`.
+We need to change both Maven and then Spring:
 
-Build and run the application (note that the main class has changed) to make 
sure it still runs fine.
+* in the `pom.xml` (of the `webapp` module), add in a dependency to the 
`petowner` module:
++
+[source,xml]
+.webapp/pom.xml
+----
+<dependencies>
+
+    <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>simpleapp-jpa-module-petowner</artifactId>
+    </dependency>
+    ...
+<dependencies>
+----
++
+You might need to reimport or refresh so that your IDE rebuilds its classpath.
+
+* in the `ApplicationModule`, update the `@Import` to reference the 
`PetOwnerModule`:
++
+[source,java]
+.Application.java
+----
+@Configuration
+@Import({
+        PetOwnerModule.class,   //<.>
+        SimpleModule.class,
+})
+@ComponentScan
+public class ApplicationModule {
+
+}
+----
+<.> add this import
+
+Run up the application using the IDE or from maven command line.
+Although everything looks good, in fact you won't see any change.
+That's because the simpleapp starter app includes the 
xref:security:secman:about.adoc[SecMan] security module, for users, roles and 
permissions.
+We'll fix this in the next exercise.
+
+
+[#exercise-2-3-add-security-role-for-petowner-module]
+== Ex 2.3: Add security role for the `petowner` module
+
+In this exercise we'll add a security role to grant access to our new 
`petowner` module, and we'll make sure that our "sven" demo user is a member of 
this role.
+
+=== Solution
+
+[source,bash]
+----
+git checkout tags/02-03-add-security-role-for-petowner
+mvn clean install
+mvn -pl spring-boot:run
+----
+
+=== Tasks
+
+The starter app is configured to use an in-memory database.
+The xref:security:secman:about.adoc[SecMan] roles and permissions are 
therefore set up each time the applicatoin is bootstrapped, using a fixture 
scripts.
+We'll learn more about fixture scripts and their role in testing in a later 
exercise.
+For now, all that's necessary to know is that we can use them to set up the 
roles.
+
+* Locate the `CustomRolesAndUsers` fixture script class
+
+* within it, copy the existing `SimpleModuleSuperuserRole` to create a similar 
`PetOwnerModuleSuperuserRole`:
++
+[source,java]
+.CustomRolesAndUsers.java
+----
+private static class PetOwnerModuleSuperuserRole
+        extends AbstractRoleAndPermissionsFixtureScript {
+
+    public static final String ROLE_NAME = "petowner-superuser";
+
+    public PetOwnerModuleSuperuserRole() {
+        super(ROLE_NAME, "Permission to use everything in the 'petowner' 
module");
+    }
+
+    @Override
+    protected void execute(ExecutionContext executionContext) {
+        newPermissions(
+                ApplicationPermissionRule.ALLOW,
+                ApplicationPermissionMode.CHANGING,
+                Can.of(ApplicationFeatureId.newNamespace("petowner"))
+        );
+    }
+}
+----
+
+* further down in the same class, update the fixture script for the "sven" 
end-user, and add them into our new role:
++
+[source,java]
+.CustomRolesAndUsers.java
+----
+private static class SvenUser extends AbstractUserAndRolesFixtureScript {
+    ...
+
+    private static class RoleSupplier implements Supplier<Can<String>> {
+        @Override
+        public Can<String> get() {
+            return Can.of(
+                    
causewayConfiguration.getExtensions().getSecman().getSeed().getRegularUser().getRoleName(),
 // built-in stuff
+                    PetOwnerModuleSuperuserRole.ROLE_NAME,  // <.>
+                    SimpleModuleSuperuserRole.ROLE_NAME
+                    );
+        }
+        @Inject CausewayConfiguration causewayConfiguration;
+    }
+}
+----
+<.> reference new role.
+
+* and in the `execute()` method at top of the class, remember to include the 
call to the new fixture script:
++
+[source,java]
+.CustomRolesAndUsers.java
+----
+@Override
+protected void execute(ExecutionContext executionContext) {
+    executionContext.executeChildren(this,
+            new SimpleModuleSuperuserRole(),
+            new PetOwnerModuleSuperuserRole(),      // <.>
+            new SvenUser());
+}
+----
+<.> Remember to call the new module
+
+
+Now run the application from the IDE or Maven:
+
+* The menubar should now show a new "Other" menu - these are the now-visible 
actions arising from the `PetOwners` domain service.
+
+* Create a new `PetOwner` using "Other > Create".
++
+The resultant object will look identical in structure to a `SimpleObject`, but 
you can confirm that it is indeed an instance of a `PetOwner` by hovering over 
the title or icon and checking the tooltip.
+
+The fact that the `PetOwners` domain service's actions are displayed 
automatically is an important principle of the _naked objects pattern_ as 
implemented by Apache Causeway.
+
+[#exercise-2-4-update-menubar-for-PetOwners]
+== Ex 2.4: Update menubar for PetOwners
+
+Let's now update the menu bar so that the actions to create ``PetOwner``s live 
under an appropriately named menu, "Pet Owners".
+
+=== Solution
+
+[source,bash]
+----
+git checkout tags/02-04-update-menubar-for-petowners
+mvn clean install
+mvn -pl spring-boot:run
+----
+
+=== Tasks
+
+* Locate the `menubars.layout.xml` file.
++
+You should find it in `src/main/resources` (in the `webapp` module).
+
+* Add in the following XML, under the `<mb3:primary>` tag:
++
+[source,xml]
+.menubars.layout.xml
+----
+<mb3:primary>
+    <mb3:menu>
+        <mb3:named>Pet Owners</mb3:named>
+        <mb3:section>
+            <mb3:serviceAction objectType="petowner.PetOwners" id="create"/>
+            <mb3:serviceAction objectType="petowner.PetOwners" 
id="findByName"/>
+            <mb3:serviceAction objectType="petowner.PetOwners" 
id="findByNameLike"/>
+            <mb3:serviceAction objectType="petowner.PetOwners" id="listAll"/>
+        </mb3:section>
+    </mb3:menu>
+...
+</mb3:primary>
+----
++
+The `objectType` attribute corresponds to the `@Named` value of the 
`PetOwners` domain service (its "logical type name"), while the `id` attribute 
matches the method name of each action.
+
+Run the application; the menubar should be updated correctly.
+
+
+[#exercise-2-5-setup-demo-PetOwners]
+== Ex 2.5: Set up demo PetOwners
+
+xref:testing:fixtures:about.adoc#fixture-scripts[Fixture scripts] are used for 
both prototyping and for integration testing, allowing us to quickly create 
demo data in the H2 in-memory database.
+
+The xref:testing:fixtures:about.adoc#personas-and-builders[persona] pattern 
lets us define example data in an enum (the "what"), while a companion builder 
uses that data to set up the corresponding domain entities (the "how").
+
+In this exercise we'll modify the `PetOwners_persona` (copied from 
`SimpleObjects_persona` earlier) to create more realistic data.
+
+
+=== Solution
+
+[source,bash]
+----
+git checkout tags/02-05-setup-demo-petowners
+mvn clean install
+mvn -pl spring-boot:run
+----
+
+=== Tasks
 
+* locate the `PetOwners_persona` class
+* refactor the enum constants and values to create 10 realistic pet owner names
+* (optional) we'll use the associated `.pdf` to store a "veterinary clinic 
service agreement" for each pet owner.
 
diff --git 
a/testing/fixtures/adoc/modules/fixtures/partials/fixture-scripts/api-and-usage.adoc
 
b/testing/fixtures/adoc/modules/fixtures/partials/fixture-scripts/api-and-usage.adoc
index 43b1160552..86b26e697f 100644
--- 
a/testing/fixtures/adoc/modules/fixtures/partials/fixture-scripts/api-and-usage.adoc
+++ 
b/testing/fixtures/adoc/modules/fixtures/partials/fixture-scripts/api-and-usage.adoc
@@ -192,6 +192,7 @@ This was demonstrated in the <<fixturescript, previous 
section>>
 The latter use case is much less frequently used, but can be helpful for 
example in demos, where the number of objects can be specified in the 
`parameters` parameter of the 
xref:refguide:testing:index/fixtures/applib/fixturescripts/FixtureScripts.adoc#runFixtureScript_String_String[run
 fixture script] action.
 
 
+[#personas-and-builders]
 == Personas and Builders
 
 Good integration tests are probably the best way to understand the behaviour 
of the domain model: better, even, than reading the code itself.

Reply via email to