You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2021/10/02 06:40:48 UTC
[isis] branch ISIS-2873-petclinic updated: ISIS-2873: ex 3.7
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch ISIS-2873-petclinic
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/ISIS-2873-petclinic by this push:
new f22ff9e ISIS-2873: ex 3.7
f22ff9e is described below
commit f22ff9e8d3377d92bbecc50c0381246f13736f80
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Sat Oct 2 07:40:41 2021 +0100
ISIS-2873: ex 3.7
---
.../pages/030-fleshing-out-the-owner-entity.adoc | 178 ++++++++++++---------
1 file changed, 105 insertions(+), 73 deletions(-)
diff --git a/antora/components/tutorials/modules/petclinic/pages/030-fleshing-out-the-owner-entity.adoc b/antora/components/tutorials/modules/petclinic/pages/030-fleshing-out-the-owner-entity.adoc
index 6a9b2f2..f07b790 100644
--- a/antora/components/tutorials/modules/petclinic/pages/030-fleshing-out-the-owner-entity.adoc
+++ b/antora/components/tutorials/modules/petclinic/pages/030-fleshing-out-the-owner-entity.adoc
@@ -351,148 +351,180 @@ isis:
-
-
-
-
-
== Exercise 3.7: Derived name property
-UP TO HERE.
-
-The ``Owner``'s `firstName` and `lastName` properties are updated using the `updateName` action, but when the action's button is invoked, it only "replaces" the `firstName` property:
+The ``PetOwner``'s `firstName` and `lastName` properties are updated using the `updateName` action, but when the action's button is invoked, it only "replaces" the `lastName` property:
image::Owner-updateName-prompt.png[width="400px",link="_images/Owner-updateName-prompt.png"]
-We can improve this by introducing a derived `name` property and then hiding the `firstName` and `lastName`:
+In this exercise we'll improve the UI by introducing a derived `name` property and then hiding the `firstName` and `lastName`:
image::Owner-name.png[width="400px",link="_images/Owner-name.png"]
-And, when `Owner#updateName` is invoked, the prompt we'll see is:
+When `PetOwner#updateName` is invoked, the prompt we'll want see is:
image::Owner-name-updated.png[width="400px",link="_images/Owner-name-updated.png"]
-
=== Solution
[source,bash]
----
-git checkout tags/080-derived-name-property
-mvn clean package jetty:run
+git checkout tags/03-07-derived-PetOwner-name
+mvn clean install
+mvn -pl spring-boot:run
----
-=== Exercise
+
+=== Tasks
+
* Add `getName()` as the derived `name` property:
+
[source,java]
----
-@Property(notPersisted = true)
+@Transient
+@PropertyLayout(fieldSetId = "name", sequence = "1")
public String getName() {
return getFirstName() + " " + getLastName();
}
----
-* Hide the `firstName` and `lastName` properties, using `@Property(hidden=...)`:
+* Hide the `lastName` and `firstName` properties, using `@Property(hidden=...)`.
+We can also remove the `@PropertyLayout` annotation.
+
[source,java]
----
-@javax.jdo.annotations.Column(allowsNull = "false", length = 40)
+@LastName
+@Column(length = LastName.MAX_LEN, nullable = false)
+@Getter @Setter @ToString.Include
@Property(hidden = Where.EVERYWHERE)
-@Getter @Setter
private String lastName;
+
+@FirstName
+@Column(length = FirstName.MAX_LEN, nullable = true)
+@Getter @Setter @ToString.Include
+@Property(hidden = Where.EVERYWHERE)
+private String firstName;
----
-* Update the `Owner.layout.xml` layout file:
+* Update the `PetOwner#updateName` to associate with the new `name` property:
+
[source,xml]
----
-<c:property id="name" namedEscaped="true">
- <c:action id="updateName">
- <c:describedAs>Updates the object's name</c:describedAs>
- </c:action>
-</c:property>
+@ActionLayout(associateWith = "name",)
+public PetOwner updateName( ... ) {}
----
-== Digression: Changing the App Name
+Run the application and check that it behaves as you expect.
-Let's remove the remaining vestiges of the "hello world" archetype, and rename our application to "pet clinic".
+However, if you now try to build the app (`mvn clean install`) then you'll hit test errors, because we have changed the visibility of the `lastName` and `firstName` properties.
-=== Solution
+We will be looking at tests later on, so if you want to just comment out the failing tests, then do that.
+Alternatively, here are the changes that need to be made:
-[source,bash]
-----
-git checkout tags/090-digression-changing-the-app-name
-mvn clean package jetty:run
+* update the `PetOwner_IntegTest#name` nested static test class:
++
+[source,java]
----
+@Nested
+public static class name extends PetOwner_IntegTest {
-=== Exercise
-
-Rename:
+ @Test
+ public void accessible() {
+ // when
+ final String name = wrap(petOwner).getName(); // <.>
-* `HelloWorldModule` -> `PetClinicModule`
+ // then
+ assertThat(name).isEqualTo(petOwner.getLastName());
+ }
-* `HelloWorldApplication` -> `PetClinicApplication`
+ // <.>
+}
+----
+<.> change this line from `getLastName()` to `getName()`
+<.> delete the 'editable' test
-** Also update the string literals in `newIsisWicketModule()` method
-** Also update the reference to the application class in `web.xml`.
+* add a new `PetOwner_IntegTest#lastName` nested static test class to check that the `lastName` property can no longer be viewed:
++
+[source,java]
+----
+@Nested
+public static class lastName extends PetOwner_IntegTest {
-* `HelloWorldAppManifest` -> `PetClinicAppManifest`
+ @Test
+ public void not_accessible() {
+ // expect
+ assertThrows(HiddenException.class, ()->{
-** Also update `isis.appManifest` property in the `isis.properties` file
+ // when
+ wrap(petOwner).getLastName();
+ });
+ }
+}
+----
++
+This asserts that the `lastName` property cannot be viewed.
-* various text references to "Hello World" or "HelloWorld" literals in `pom.xml`, `index.html` and `welcome.html` files
+* add a new `PetOwner_IntegTest#firstName` nested static test class to check that the `firstName` property can no longer be viewed.
++
+[source,java]
+----
+@Nested
+public static class firstName extends PetOwner_IntegTest {
+ @Test
+ public void not_accessible() {
+ // expect
+ assertThrows(HiddenException.class, ()->{
-== Changing the "Object Type" Class Alias
+ // when
+ wrap(petOwner).getFirstName();
+ });
+ }
+}
+----
-The Apache Isis framework allows an optional alias to be specified for each domain class; this is called the "objectType".
-This crops up in various places, including the `menubars.layout.xml`, and the REST API.
-It can used when persisting data, eg to hold a reference to an arbitrary domain object (a "polymorphic association").
+* update the `PetOwner_IntegTest#updateName` nested static test class, specifically the assertion:
++
+[source,java]
+----
+@Nested
+public static class updateName extends PetOwner_IntegTest {
-It's good practice to specify an object type, because it makes refactoring easier if we subsequently move the class to another package, or rename it.
+ @Test
+ public void can_be_updated_directly() {
-=== Solution
+ // when
+ wrap(petOwner).updateName("McAdam", "Adam"); // <.>
+ transactionService.flushTransaction();
-[source,bash]
-----
-git checkout tags/100-changing-the-object-type-class-alias
-mvn clean package jetty:run
+ // then
+ assertThat(petOwner.getLastName()).isEqualTo("McAdam"); // <.>
+ assertThat(petOwner.getFirstName()).isEqualTo("Adam"); // <2>
+ }
+ //...
+}
----
+<.> provide both `lastName` and `firstName` parameters
+<.> assert on both properties.
+Note that the `petOwner` object cannot be "wrapped".
-=== Exercise
+In case you are wondering, the wrap method is a call to xref:refguide:applib:index/services/wrapper/WrapperFactory.adoc[WrapperFactory], which provides a proxy to the object.
+This proxy emulates the UI, in this case enforcing the "hidden" rule by throwing an exception if it would not be visible.
+For this test, we _want_ to peek under the covers to check the direct state of the entity, therefore we don't wrap the object.
-* Update `Owners` domain service.
-The object type alias is specified in `@DomainService(objectType=...)`:
-+
-[source,java]
-----
-@DomainService(
- nature = NatureOfService.VIEW_MENU_ONLY,
- objectType = "pets.Owners"
-)
-public class Owners { ... }
-----
-* Update `Owner` domain entity.
-The object type alias is derived from the database schema and the class's (simple) name:
-+
-[source,java]
-----
-@javax.jdo.annotations.PersistenceCapable(identityType = IdentityType.DATASTORE, schema = "pets" )
-...
-public class Owner implements Comparable<Owner> { ... }
-----
-* also, update `menubars.layout.xml`, changing "myapp.Owners" to "pets.Owners".
== Add other properties for `Owner`
+UP to here
+
Let's add the two remaining properties for `Owner`.
[plantuml]