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 298a8aa2327a6dffec9876ab1b4af45d9f92c70f
Author: danhaywood <[email protected]>
AuthorDate: Mon May 22 07:25:25 2023 +0100

    CAUSEWAY-2485: resurrects the customui for demo app
---
 .../java/demoapp/dom/featured/FeaturedMenu.java    | 39 +++++----
 .../customui/{geocoding => }/GeoapifyClient.java   | 21 ++---
 ...n.adoc => WhereInTheWorldPage-description.adoc} | 93 ++++++++--------------
 ...eInTheWorldVm.java => WhereInTheWorldPage.java} | 33 +++-----
 .../dom/featured/customui/{latlng => }/Zoom.java   |  2 +-
 .../dom/featured/customui/latlng/LatLng.java       | 30 -------
 .../dom/featured/customui/latlng/LatLngUtils.java  | 46 -----------
 .../dom/featured/customui/latlng/Latitude.java     | 51 ------------
 .../dom/featured/customui/latlng/Longitude.java    | 51 ------------
 .../dom/featured/customui/vm/BoundingBox.java      | 56 -------------
 .../featured/{ => layout/tooltip}/DemoItem.java    |  4 +-
 .../dom/featured/layout/tooltip/TooltipPage.java   |  1 -
 .../featured/customui}/WhereInTheWorldPanel.java   | 12 +--
 .../customui}/WhereInTheWorldPanelFactory.java     | 31 ++++----
 .../customui/GeocodeResponseUtilsTest.java         | 37 ---------
 .../geocoding/GeoapifyClientTest_geocode.java      | 12 +--
 examples/demo/wicket/common/pom.xml                |  4 +-
 .../common/{ui => }/DemoAppWicketCommon.java       |  4 +-
 .../customui}/WhereInTheWorldPanel.html            |  2 +-
 .../customui}/WhereInTheWorldPanel.java            | 12 +--
 .../customui}/WhereInTheWorldPanelFactory.java     | 29 ++++---
 .../webapp/wicket/jdo/DemoAppWicketJdo.java        |  2 +-
 .../webapp/wicket/jpa/DemoAppWicketJpa.java        |  2 +-
 23 files changed, 132 insertions(+), 442 deletions(-)

diff --git 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/FeaturedMenu.java 
b/examples/demo/domain/src/main/java/demoapp/dom/featured/FeaturedMenu.java
index 391cde9bc9..8fca85b272 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/featured/FeaturedMenu.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/featured/FeaturedMenu.java
@@ -34,12 +34,14 @@ import org.apache.causeway.applib.annotation.SemanticsOf;
 import org.apache.causeway.applib.annotation.Where;
 import org.apache.causeway.applib.services.factory.FactoryService;
 
+import demoapp.dom.featured.customui.WhereInTheWorldPage;
+import demoapp.dom.featured.layout.tooltip.DemoItem;
+
 import lombok.RequiredArgsConstructor;
 import lombok.val;
 
-import demoapp.dom.featured.customui.geocoding.GeoapifyClient;
-import demoapp.dom.featured.customui.latlng.Zoom;
-import demoapp.dom.featured.customui.vm.WhereInTheWorldVm;
+import demoapp.dom.featured.customui.GeoapifyClient;
+import demoapp.dom.featured.customui.Zoom;
 import demoapp.dom.featured.layout.tooltip.TooltipPage;
 import demoapp.dom.featured.layout.tabs.TabDemo;
 
@@ -79,27 +81,26 @@ public class FeaturedMenu {
 
 
 
-    //tag::whereInTheWorldAction[]
-    @Inject
-    private GeoapifyClient geoapifyClient;
+//tag::whereInTheWorldAction[]
+    @Inject private GeoapifyClient geoapifyClient;
 
     @Action(semantics = SemanticsOf.SAFE)
     @ActionLayout(
-            cssClassFa="fa-globe",
-            describedAs="Opens a Custom UI page displaying a map for the 
provided address"
+        cssClassFa="fa-globe",
+        describedAs="Opens a Custom UI page displaying a map for the provided 
address"
     )
-    public WhereInTheWorldVm whereInTheWorld(
+    public WhereInTheWorldPage whereInTheWorld(
             final String address,
-            @Zoom final int zoom) {
-        val vm = new WhereInTheWorldVm();
+            @Zoom final int zoom) {                                     // <.>
+        final WhereInTheWorldPage page = new WhereInTheWorldPage();
 
-        val latLng = geoapifyClient.geocode(address);
-        vm.setAddress(address);
-        vm.setLatitude(latLng.getLatitude());
-        vm.setLongitude(latLng.getLongitude());
-        vm.setZoom(zoom);
+        final GeoapifyClient.GeocodeResponse response = 
geoapifyClient.geocode(address);
+        page.setAddress(address);
+        page.setLatitude(response.getLatitude());
+        page.setLongitude(response.getLongitude());
+        page.setZoom(zoom);
 
-        return vm;
+        return page;
     }
 //end::whereInTheWorldAction[]
     @MemberSupport public List<String> choices0WhereInTheWorld() {
@@ -111,8 +112,4 @@ public class FeaturedMenu {
     @MemberSupport public int default1WhereInTheWorld() {
         return 14;
     }
-
-
-
-
 }
diff --git 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/geocoding/GeoapifyClient.java
 
b/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/GeoapifyClient.java
similarity index 90%
rename from 
examples/demo/domain/src/main/java/demoapp/dom/featured/customui/geocoding/GeoapifyClient.java
rename to 
examples/demo/domain/src/main/java/demoapp/dom/featured/customui/GeoapifyClient.java
index eb1dd8ca13..db35b6b038 100644
--- 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/geocoding/GeoapifyClient.java
+++ 
b/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/GeoapifyClient.java
@@ -16,13 +16,14 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.featured.customui.geocoding;
+package demoapp.dom.featured.customui;
 
 import java.io.IOException;
 import java.io.Serializable;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 import java.util.List;
 
 import javax.inject.Inject;
@@ -38,6 +39,7 @@ import lombok.Builder;
 import lombok.Data;
 import lombok.Getter;
 import lombok.SneakyThrows;
+import lombok.Value;
 import lombok.val;
 
 import demoapp.dom.AppConfiguration;
@@ -60,12 +62,10 @@ public class GeoapifyClient implements Serializable {
 
 
 //tag::class[]
-    @Data
+    @Value
     public class GeocodeResponse {
-        @Getter
-        private final String latitude;
-        @Getter
-        private final String longitude;
+        String latitude;
+        String longitude;
     }
 
     @SneakyThrows
@@ -75,7 +75,7 @@ public class GeoapifyClient implements Serializable {
 
         val url = new URL(String.format(
                 "https://api.geoapify.com/v1/geocode/search?text=%s&apiKey=%s";
-                , URLEncoder.encode(address, "UTF-8")
+                , URLEncoder.encode(address, StandardCharsets.UTF_8)
                 , apiKey));
 
         val response = objectMapper.readValue(url, Response.class);
@@ -86,7 +86,6 @@ public class GeoapifyClient implements Serializable {
         );
 //tag::class[]
     }
-
 //end::class[]
 
     @Data
@@ -100,7 +99,10 @@ public class GeoapifyClient implements Serializable {
     }
 
 //tag::class[]
-    public byte[] toJpeg(final String latitude, final String longitude, final 
int zoom) throws IOException {
+    public byte[] toJpeg(
+            final String latitude,
+            final String longitude,
+            final int zoom) throws IOException {
         //...
 //end::class[]
         return 
toJpeg(JpegRequest.builder().latitude(latitude).longitude(longitude).zoom(zoom).build());
@@ -136,5 +138,6 @@ public class GeoapifyClient implements Serializable {
         List<Feature> features;
     }
 
+//tag::class[]
 }
 //end::class[]
diff --git 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/vm/WhereInTheWorldVm-description.adoc
 
b/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/WhereInTheWorldPage-description.adoc
similarity index 59%
rename from 
examples/demo/domain/src/main/java/demoapp/dom/featured/customui/vm/WhereInTheWorldVm-description.adoc
rename to 
examples/demo/domain/src/main/java/demoapp/dom/featured/customui/WhereInTheWorldPage-description.adoc
index 7e3fa49214..80f7687d6b 100644
--- 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/vm/WhereInTheWorldVm-description.adoc
+++ 
b/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/WhereInTheWorldPage-description.adoc
@@ -1,50 +1,60 @@
 :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 link:https://causeway.apache.org/vw/{causeway-version}/about.html[Wicket 
viewer] renders the generic UI for entities and view models using a series of 
Wicket ``Component``s, with each such `Component` created by a 
`ComponentFactory`.
+The link:https://causeway.apache.org/vw/2.0.0-RC1/about.html[Wicket viewer] 
renders the generic UI for entities and view models using a series of Wicket 
``Component``s, with each such `Component` created by a `ComponentFactory`.
 
 You can customise the UI by providing alternate implementations of 
`ComponentFactory`, for any component on the page, including the top-level 
component for the entire domain object.
 
-This custom UI uses the technique to provide a custom page for a 
`WhereInTheWorldVm` view model.
+== How this demo works
 
+This page is implemented as a custom page for the `WhereInTheWorldPage` view 
model.
+As you will have seen already, the `FeaturedMenu` domain service prompts for 
an address.
+This address is converted into a latitude and longitude, which is then 
displayed on a map.
 
-== Domain Objects
 
-The domain objects involved are the `WhereInTheWorldMenu` domain service and 
`WhereInTheWorldVm` view model.
+=== Domain Objects
 
-The `WhereInTheWorldMenu` domain service prompts for an address, and uses the 
injected `GeoapifyClient` service to determine the latitude and longitude.
-A `zoom` level, which will be used when retrieving the map, is also prompted 
for:
+The domain objects (not involving custom UI code) consist of `FeaturedMenu`, 
which prompts for the address, the `WhereinTheWorldPage` view model, and the 
`GeoapifyClient` which converts the address into a latitude and longitude:
 
+* the `FeaturedMenu` action is:
++
 [source,java,indent=0]
-.WhereInTheWorldMenu.java
+.FeaturedMenu.java
 ----
-include::../../FeaturedMenu.java[tags=whereInTheWorldAction]
+include::../FeaturedMenu.java[tags=whereInTheWorldAction]
 ----
+<.> uses a custom annotation with 
link:https://causeway.apache.org/refguide/2.0.0-RC1/applib/index/annotation/Parameter.html#mustsatisfy[@Parameter#mustSatisfy]
 to enforce a range constraint.
 
-The `WhereInTheWorldVm` view model returned by the menu is defined normally.
-In this case, we have a JAXB view model with four properties:
-
+* The `WhereInTheWorldPage` view model returned by the menu is:
++
 [source,java]
-.WhereInTheWorldVm.java
+.WhereInTheWorldPage.java
 ----
-include::WhereInTheWorldVm.java[tags=class]
+include::WhereInTheWorldPage.java[tags=class]
 ----
+<.> must be serializable
 
-== Wicket components
-
-To provide a custom component, we need to implement the 
`o.a.i.viewer.wicket.ui.ComponentFactory` interface, as a domain service.
+* the `GeoapifyClient` domain service provides a geocode lookup of (lat, lng) 
for an address.
+It also provides a jpeg image for that location, at the specified zoom:
++
+[source,java]
+.GeoapifyClient.java
+----
+include::GeoapifyClient.java[tags=class]
+----
 
-TIP: For more on this topic, see the 
link:https://causeway.apache.org/vw/{causeway-version}/extending.html#replacing-page-elements[Wicket
 viewer documentation].
+=== Wicket components
 
+To provide a custom component, we need to provide a domain service 
implementing the 
link:https://causeway.apache.org/vw/2.0.0-RC1/extending/replacing-page-elements.html#how-to-replace-a-component[ComponentFactory]
 interface.
 There are various subclasses available; as we want to replace the component 
for the entire entity, we can subclass from `EntityComponentFactoryAbstract`:
 
 
 [source,java]
 .WhereInTheWorldPanelFactory.java
 ----
-include::../../../../webapp/wicket/ui/custom/WhereInTheWorldPanelFactory.java[tags=class]
+include::../../../webapp/wicket/common/featured/customui/WhereInTheWorldPanelFactory.java[tags=class]
 ----
 <.> the framework use the chain-of-responsibility pattern to look for a 
component factory to render the domain object.
-This `@javax.annotation.Priority` precedence ensures that this custom 
implementation is consulted early on.
+The `@javax.annotation.Priority` precedence ensures that this custom 
implementation is consulted early on.
 <.> indicates that this component applies when rendering a domain object 
(applies to view models as well as domain entities)
 <.> the superclass ensures that an `EntityModel` is provided to inspect.
 This is a Wicket model that is a serializable equivalent to the core 
framework's notion of a domain object.
@@ -64,7 +74,7 @@ The `WhereInTheWorldPanel` is the actual custom Wicket 
component, using the Wick
 [source,java]
 .WhereInTheWorldPanel.java
 ----
-include::../wicket/WhereInTheWorldPanel.java[tags=class]
+include::../../../webapp/wicket/common/featured/customui/WhereInTheWorldPanel.java[tags=class]
 ----
 <.> Wicket components are required to be serializable.
 <.> The `GeoapifyClient` as provided by the component factory, above.
@@ -75,7 +85,7 @@ Note that this must _also_ be serializable.
 [source,java,indent=0]
 .WhereInTheWorldPanel.java
 ----
-include::../../../../webapp/wicket/ui/custom/WhereInTheWorldPanel.java[tags=onInitialize]
+include::../../../webapp/wicket/common/featured/customui/WhereInTheWorldPanel.java[tags=onInitialize]
 ----
 <.> obtain the core framework's `ManagedObject` from the Wicket model...
 <.> \... and obtain the domain object in turn.
@@ -96,56 +106,23 @@ Wicket requires there to be corresponding HTML 
(`WhereInTheWorld.html`) file for
 [source,java,indent=0]
 .WhereInTheWorldPanel.java
 ----
-include::../../../../webapp/wicket/ui/custom/WhereInTheWorldPanel.java[tags=createMapComponent]
+include::../../../webapp/wicket/common/featured/customui/WhereInTheWorldPanel.java[tags=createMapComponent]
 ----
 <.> call the `GeoapifyClient` to download the JPEG...
 <.> \... and returns an `Image` component holding same
 
 * the `createPropertyComponent()` helper is:
-*
++
 [source,java,indent=0]
 .WhereInTheWorldPanel.java
 ----
-include::../../../../../webapp/wicket/common/ui/custom/WhereInTheWorldPanel.java[tags=createPropertyComponent]
+include::../../../webapp/wicket/common/featured/customui/WhereInTheWorldPanel.java[tags=createPropertyComponent]
 ----
 <.> obtains the `ObjectSpecification` (the framework's equivalent of 
`java.lang.Class`) for the domain object
 <.> obtains the `OneToOneAssociation` (the framework's equivalent of a 
`java.lang.reflect.Method`) for the specified property
-<.> creates a Wicket (serializable) model to represent this aspect of the 
framework's metamodel
 <.> uses the parent entity model to create a scalar model holding the actual 
value of the property of the domain object
 <.> uses the Wicket viewer's `ComponentFactoryRegistry` to create an 
appropriate component for this property value.
 
-This example therefore shows that the resultant page can be a mix of entirely 
custom Wicket components, and also reusing components provided by the Wicket 
viewer.
-
-== GeoapifyClient
+This example therefore shows that the resultant page can be a mix of 
components provided out-of-the-box by the Wicket viewer supplemented by 
entirely custom Wicket components.
 
-We have already seen the `GeoapifyClient` domain service; it provides a 
geocode lookup of (lat, lng) for an address, and provides a jpeg image for that 
location, at the specified zoom:
 
-[source,java]
-.GeoapifyClient.java
-----
-include::../geocoding/GeoapifyClient.java[tags=class]
-----
-
-== Classpath
-
-It's probably best practice for the custom Wicket component classes to be in 
the `webapp` module, rather than here in the domain module; we've placed them 
here just to have all the code together and to be easily locatable.
-
-It does however mean that we had to tweak the classpath to bring in a 
dependency on the Wicket viewer modules:
-
-[source,xml]
-.pom.xml
-----
-<dependencies>
-    <dependency>
-        <groupId>org.apache.causeway.viewer</groupId>
-        <artifactId>causeway-viewer-wicket-model</artifactId>
-        <optional>true</optional>      <!--1-->
-    </dependency>
-    <dependency>
-        <groupId>org.apache.causeway.viewer</groupId>
-        <artifactId>causeway-viewer-wicket-ui</artifactId>
-        <optional>true</optional>      <!--1-->
-    </dependency>
-</dependencies>
-----
-<.> to avoid polluting the classpath
diff --git 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/vm/WhereInTheWorldVm.java
 
b/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/WhereInTheWorldPage.java
similarity index 72%
rename from 
examples/demo/domain/src/main/java/demoapp/dom/featured/customui/vm/WhereInTheWorldVm.java
rename to 
examples/demo/domain/src/main/java/demoapp/dom/featured/customui/WhereInTheWorldPage.java
index 85249231f1..24867ff9f4 100644
--- 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/vm/WhereInTheWorldVm.java
+++ 
b/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/WhereInTheWorldPage.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.featured.customui.vm;
+package demoapp.dom.featured.customui;
 
 import java.io.Serializable;
 
@@ -34,35 +34,20 @@ import lombok.Getter;
 import lombok.Setter;
 
 import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
-import demoapp.dom.featured.customui.latlng.Latitude;
-import demoapp.dom.featured.customui.latlng.Longitude;
-import demoapp.dom.featured.customui.latlng.Zoom;
 
 //tag::class[]
-@XmlRootElement(name = "demo.CustomUiVm")
+@XmlRootElement(name = "demo.WhereInTheWorldPage")
 @XmlType
 @XmlAccessorType(XmlAccessType.FIELD)
-@Named("demo.CustomUiVm")
+@Named("demo.WhereInTheWorldPage")
 @DomainObject(nature=Nature.VIEW_MODEL)
-public class WhereInTheWorldVm
-implements HasAsciiDocDescription, Serializable {
-
+public class WhereInTheWorldPage
+implements HasAsciiDocDescription, Serializable {       // <.>
     private static final long serialVersionUID = 1L;
-
     @Title
-    @Getter @Setter
-    private String address;
-
-    @Latitude
-    @Getter @Setter
-    private String latitude;
-
-    @Longitude
-    @Getter @Setter
-    private String longitude;
-
-    @Zoom
-    @Getter @Setter
-    private int zoom;
+    @Getter @Setter private String address;
+    @Getter @Setter private String latitude;
+    @Getter @Setter private String longitude;
+    @Getter @Setter private int zoom;
 }
 //end::class[]
diff --git 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/latlng/Zoom.java
 b/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/Zoom.java
similarity index 97%
rename from 
examples/demo/domain/src/main/java/demoapp/dom/featured/customui/latlng/Zoom.java
rename to 
examples/demo/domain/src/main/java/demoapp/dom/featured/customui/Zoom.java
index 379efa4821..256fa12340 100644
--- 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/latlng/Zoom.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/Zoom.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.featured.customui.latlng;
+package demoapp.dom.featured.customui;
 
 
 import java.lang.annotation.ElementType;
diff --git 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/latlng/LatLng.java
 
b/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/latlng/LatLng.java
deleted file mode 100644
index 33b7acdd92..0000000000
--- 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/latlng/LatLng.java
+++ /dev/null
@@ -1,30 +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.featured.customui.latlng;
-
-import lombok.Data;
-import lombok.Getter;
-
-@Data
-public class LatLng {
-    @Getter
-    private final String latitude;
-    @Getter
-    private final String longitude;
-}
diff --git 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/latlng/LatLngUtils.java
 
b/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/latlng/LatLngUtils.java
deleted file mode 100644
index 8f85caa05e..0000000000
--- 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/latlng/LatLngUtils.java
+++ /dev/null
@@ -1,46 +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.featured.customui.latlng;
-
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-
-import lombok.val;
-import lombok.experimental.UtilityClass;
-
-
-@UtilityClass
-public class LatLngUtils {
-
-    public static BigDecimal toBigDecimal(final String val) {
-        return new BigDecimal(val);
-    }
-
-    public static String toString(BigDecimal val) {
-        return val.toPlainString();
-    }
-
-    public static String add(final String val, final int hundredths) {
-        val scaleBd = new BigDecimal(hundredths).setScale(2, 
RoundingMode.HALF_UP);
-        val scaleDividedBy100 = scaleBd.divide(new BigDecimal(100), 
RoundingMode.HALF_UP);
-        val bd = toBigDecimal(val);
-        val newVal = bd.add(scaleDividedBy100);
-        return toString(newVal);
-    }
-}
diff --git 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/latlng/Latitude.java
 
b/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/latlng/Latitude.java
deleted file mode 100644
index ec0161f157..0000000000
--- 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/latlng/Latitude.java
+++ /dev/null
@@ -1,51 +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.featured.customui.latlng;
-
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import org.apache.causeway.applib.annotation.Parameter;
-import org.apache.causeway.applib.annotation.Property;
-
-@Property(
-        regexPattern = Latitude.PATTERN
-        , regexPatternReplacement = "Does not match format of latitude"
-)
-@Parameter(
-        regexPattern = Latitude.PATTERN
-        , regexPatternReplacement = "Does not match format of latitude"
-)
-@Inherited
-@Target({
-        ElementType.FIELD,
-        ElementType.METHOD,
-        ElementType.PARAMETER,
-        ElementType.ANNOTATION_TYPE
-})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Latitude {
-
-    String PATTERN = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$";
-
-}
diff --git 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/latlng/Longitude.java
 
b/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/latlng/Longitude.java
deleted file mode 100644
index 23899085a8..0000000000
--- 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/latlng/Longitude.java
+++ /dev/null
@@ -1,51 +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.featured.customui.latlng;
-
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import org.apache.causeway.applib.annotation.Parameter;
-import org.apache.causeway.applib.annotation.Property;
-
-@Property(
-        regexPattern = Longitude.PATTERN
-        , regexPatternReplacement = "Does not match format of longitude"
-)
-@Parameter(
-        regexPattern = Longitude.PATTERN
-        , regexPatternReplacement = "Does not match format of longitude"
-)
-@Inherited
-@Target({
-        ElementType.FIELD,
-        ElementType.METHOD,
-        ElementType.PARAMETER,
-        ElementType.ANNOTATION_TYPE
-})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Longitude {
-
-    String PATTERN = 
"^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$";
-
-}
diff --git 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/vm/BoundingBox.java
 
b/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/vm/BoundingBox.java
deleted file mode 100644
index c9ffe65a46..0000000000
--- 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/customui/vm/BoundingBox.java
+++ /dev/null
@@ -1,56 +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.featured.customui.vm;
-
-import lombok.Data;
-import lombok.Getter;
-
-import demoapp.dom.featured.customui.latlng.LatLng;
-
-@Data
-public class BoundingBox {
-    @Getter
-    private final LatLng minimum;
-    @Getter
-    private final LatLng maximum;
-
-    public String getMinimumLatitude() {
-        return minimum.getLatitude();
-    }
-
-    public String getMinimumLongitude() {
-        return minimum.getLongitude();
-    }
-
-    public String getMaximumLatitude() {
-        return maximum.getLatitude();
-    }
-
-    public String getMaximumLongitude() {
-        return maximum.getLongitude();
-    }
-
-    public final String toUrl(String divider) {
-        return getMinimumLongitude() + divider + this.getMinimumLatitude() + 
divider + getMaximumLongitude() + divider + getMaximumLatitude();
-    }
-
-    public final String toUrl() {
-        return toUrl("%2C");
-    }
-}
diff --git 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/DemoItem.java 
b/examples/demo/domain/src/main/java/demoapp/dom/featured/layout/tooltip/DemoItem.java
similarity index 96%
rename from 
examples/demo/domain/src/main/java/demoapp/dom/featured/DemoItem.java
rename to 
examples/demo/domain/src/main/java/demoapp/dom/featured/layout/tooltip/DemoItem.java
index 20a21a60e8..56118a2b0c 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/featured/DemoItem.java
+++ 
b/examples/demo/domain/src/main/java/demoapp/dom/featured/layout/tooltip/DemoItem.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.dom.featured;
+package demoapp.dom.featured.layout.tooltip;
 
 import javax.inject.Named;
 
@@ -32,7 +32,7 @@ import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
 
-@Named("demo.AssociatedActionDemoTask")
+@Named("demo.DemoItem")
 @DomainObject(nature=Nature.VIEW_MODEL)
 @NoArgsConstructor
 @AllArgsConstructor(staticName="of")
diff --git 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/layout/tooltip/TooltipPage.java
 
b/examples/demo/domain/src/main/java/demoapp/dom/featured/layout/tooltip/TooltipPage.java
index d432e2c101..e29d439c72 100644
--- 
a/examples/demo/domain/src/main/java/demoapp/dom/featured/layout/tooltip/TooltipPage.java
+++ 
b/examples/demo/domain/src/main/java/demoapp/dom/featured/layout/tooltip/TooltipPage.java
@@ -53,7 +53,6 @@ import lombok.Getter;
 import lombok.Setter;
 
 import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription;
-import demoapp.dom.featured.DemoItem;
 
 @XmlRootElement(name = "Demo")
 @XmlType
diff --git 
a/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/ui/custom/WhereInTheWorldPanel.java
 
b/examples/demo/domain/src/main/resources/demoapp/webapp/wicket/common/featured/customui/WhereInTheWorldPanel.java
similarity index 92%
copy from 
examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/ui/custom/WhereInTheWorldPanel.java
copy to 
examples/demo/domain/src/main/resources/demoapp/webapp/wicket/common/featured/customui/WhereInTheWorldPanel.java
index 95cd27f986..6937126512 100644
--- 
a/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/ui/custom/WhereInTheWorldPanel.java
+++ 
b/examples/demo/domain/src/main/resources/demoapp/webapp/wicket/common/featured/customui/WhereInTheWorldPanel.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.webapp.wicket.common.ui.custom;
+package demoapp.webapp.wicket.common.featured.customui;
 
 import org.apache.wicket.Component;
 import org.apache.wicket.markup.html.basic.Label;
@@ -31,11 +31,12 @@ import 
org.apache.causeway.viewer.wicket.model.hints.UiHintContainer;
 import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt;
 import org.apache.causeway.viewer.wicket.ui.panels.PanelAbstract;
 
+import demoapp.dom.featured.customui.WhereInTheWorldPage;
+
 import lombok.SneakyThrows;
 import lombok.val;
 
-import demoapp.dom.featured.customui.geocoding.GeoapifyClient;
-import demoapp.dom.featured.customui.vm.WhereInTheWorldVm;
+import demoapp.dom.featured.customui.GeoapifyClient;
 
 //tag::class[]
 public class WhereInTheWorldPanel
@@ -68,7 +69,7 @@ extends PanelAbstract<ManagedObject, UiObjectWkt>  {
         super.onInitialize();
 
         val managedObject = getModel().getObject();;                       // 
<.>
-        val customUiVm = (WhereInTheWorldVm) managedObject.getPojo();      // 
<.>
+        val customUiVm = (WhereInTheWorldPage) managedObject.getPojo();    // 
<.>
 
         val latitude = new Label("latitude", customUiVm.getLatitude());    // 
<.>
         val longitude = new Label("longitude", customUiVm.getLongitude()); // 
<.>
@@ -87,7 +88,7 @@ extends PanelAbstract<ManagedObject, UiObjectWkt>  {
 
 //tag::createMapComponent[]
     @SneakyThrows
-    private Image createMapComponent(final String id, final WhereInTheWorldVm 
vm)  {
+    private Image createMapComponent(final String id, final 
WhereInTheWorldPage vm)  {
         val bytes = geoapifyClient.toJpeg(
                         vm.getLatitude(), vm.getLongitude(), vm.getZoom());  
// <.>
         return new Image(id, new ByteArrayResource("image/jpeg", bytes));    
// <.>
@@ -99,7 +100,6 @@ extends PanelAbstract<ManagedObject, UiObjectWkt>  {
         val managedObject = getModel().getManagedObject();
         val spec = managedObject.getSpecification();                           
    // <.>
         val property = spec.getPropertyElseFail(propertyId);                   
    // <.>
-        //val pm = otoa.getMemento();                                          
    // <.>
 
         val scalarModel =
                 getModel().getPropertyModel(                                   
    // <.>
diff --git 
a/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/ui/custom/WhereInTheWorldPanelFactory.java
 
b/examples/demo/domain/src/main/resources/demoapp/webapp/wicket/common/featured/customui/WhereInTheWorldPanelFactory.java
similarity index 72%
copy from 
examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/ui/custom/WhereInTheWorldPanelFactory.java
copy to 
examples/demo/domain/src/main/resources/demoapp/webapp/wicket/common/featured/customui/WhereInTheWorldPanelFactory.java
index 9f57058d18..684176e226 100644
--- 
a/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/ui/custom/WhereInTheWorldPanelFactory.java
+++ 
b/examples/demo/domain/src/main/resources/demoapp/webapp/wicket/common/featured/customui/WhereInTheWorldPanelFactory.java
@@ -16,8 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.webapp.wicket.common.ui.custom;
+package demoapp.webapp.wicket.common.featured.customui;
 
+import javax.annotation.Priority;
 import javax.inject.Inject;
 
 import org.apache.wicket.Component;
@@ -29,39 +30,37 @@ import 
org.apache.causeway.viewer.commons.model.components.UiComponentType;
 import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt;
 import 
org.apache.causeway.viewer.wicket.ui.components.entity.EntityComponentFactoryAbstract;
 
-import demoapp.dom.featured.customui.geocoding.GeoapifyClient;
-import demoapp.dom.featured.customui.vm.WhereInTheWorldVm;
+import demoapp.dom.featured.customui.WhereInTheWorldPage;
+import demoapp.dom.featured.customui.GeoapifyClient;
 
 //tag::class[]
 @org.springframework.stereotype.Component
[email protected](PriorityPrecedence.EARLY)                           
                  // <.>
-public class WhereInTheWorldPanelFactory extends 
EntityComponentFactoryAbstract {
-
+@Priority(PriorityPrecedence.EARLY)                                            
 // <.>
+public class WhereInTheWorldPanelFactory
+        extends EntityComponentFactoryAbstract {
     private static final long serialVersionUID = 1L;
 
     public WhereInTheWorldPanelFactory() {
         super(
-            UiComponentType.ENTITY                                          // 
<.>
-            , WhereInTheWorldPanel.class
+                UiComponentType.ENTITY                                         
 // <.>
+                , WhereInTheWorldPanel.class
         );
     }
 
     @Override
     protected ApplicationAdvice doAppliesTo(final UiObjectWkt entityModel) {   
 // <.>
-        final ManagedObject managedObject = entityModel.getObject();      // 
<.>
-        final Object domainObject = managedObject.getPojo();              // 
<.>
+        final ManagedObject managedObject = entityModel.getObject();           
 // <.>
+        final Object domainObject = managedObject.getPojo();                   
 // <.>
         return ApplicationAdvice.appliesIf(
-                domainObject instanceof WhereInTheWorldVm);               // 
<.>
+                domainObject instanceof WhereInTheWorldPage);                  
 // <.>
     }
 
     @Override
     public Component createComponent(final String id, final IModel<?> model) {
-        UiObjectWkt entityModel = (UiObjectWkt) model;                    // 
<.>
-        return new WhereInTheWorldPanel(id, entityModel, geoapifyClient); // 
<.>
+        UiObjectWkt entityModel = (UiObjectWkt) model;                         
 // <.>
+        return new WhereInTheWorldPanel(id, entityModel, geoapifyClient);      
 // <.>
     }
 
-    @Inject
-    private GeoapifyClient geoapifyClient;                                // 
<.>
-
+    @Inject private GeoapifyClient geoapifyClient;                             
 // <.>
 }
 //end::class[]
diff --git 
a/examples/demo/domain/src/test/java/demoapp/dom/featured/customui/GeocodeResponseUtilsTest.java
 
b/examples/demo/domain/src/test/java/demoapp/dom/featured/customui/GeocodeResponseUtilsTest.java
deleted file mode 100644
index 864719da89..0000000000
--- 
a/examples/demo/domain/src/test/java/demoapp/dom/featured/customui/GeocodeResponseUtilsTest.java
+++ /dev/null
@@ -1,37 +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.featured.customui;
-
-import org.assertj.core.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-import lombok.val;
-
-import demoapp.dom.featured.customui.latlng.LatLngUtils;
-
-class GeocodeResponseUtilsTest {
-
-    @Test
-    void add() {
-        val add = LatLngUtils.add("51.753500", 1);
-        Assertions.assertThat(add).isEqualTo("51.763500");
-    }
-}
diff --git 
a/examples/demo/domain/src/test/java/demoapp/dom/featured/customui/geocoding/GeoapifyClientTest_geocode.java
 
b/examples/demo/domain/src/test/java/demoapp/dom/featured/customui/geocoding/GeoapifyClientTest_geocode.java
index d693633b38..48773cda26 100644
--- 
a/examples/demo/domain/src/test/java/demoapp/dom/featured/customui/geocoding/GeoapifyClientTest_geocode.java
+++ 
b/examples/demo/domain/src/test/java/demoapp/dom/featured/customui/geocoding/GeoapifyClientTest_geocode.java
@@ -22,6 +22,7 @@ import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
+import demoapp.dom.featured.customui.GeoapifyClient;
 import lombok.val;
 
 import demoapp.dom.AppConfiguration;
@@ -32,14 +33,15 @@ class GeoapifyClientTest_geocode {
     void happy_case() {
 
         // given
-        val appConfiguration = new AppConfiguration();
-        val client = new GeoapifyClient(appConfiguration);
+        final AppConfiguration appConfiguration = new AppConfiguration();
+        final GeoapifyClient client = new GeoapifyClient(appConfiguration);
 
         // when
-        val latLng = client.geocode("38 Upper Montagu Street, Westminster W1H 
1LJ, United Kingdom");
+        final GeoapifyClient.GeocodeResponse response =
+                client.geocode("38 Upper Montagu Street, Westminster W1H 1LJ, 
United Kingdom");
 
         // then
-        assertEquals(Double.valueOf(latLng.getLatitude()), 51.520, 1E-2);
-        assertEquals(Double.valueOf(latLng.getLongitude()), -0.160, 1E-2);
+        assertEquals(Double.valueOf(response.getLatitude()), 51.520, 1E-2);
+        assertEquals(Double.valueOf(response.getLongitude()), -0.160, 1E-2);
     }
 }
diff --git a/examples/demo/wicket/common/pom.xml 
b/examples/demo/wicket/common/pom.xml
index 71dfdb0e77..327b9c5336 100644
--- a/examples/demo/wicket/common/pom.xml
+++ b/examples/demo/wicket/common/pom.xml
@@ -89,7 +89,7 @@
                        <groupId>org.apache.causeway.valuetypes</groupId>
                        
<artifactId>causeway-valuetypes-markdown-ui-wkt</artifactId>
                </dependency>
-               
+
                <dependency>
                        <groupId>org.apache.causeway.valuetypes</groupId>
                        <artifactId>causeway-valuetypes-vega-ui-wkt</artifactId>
@@ -110,7 +110,7 @@
                        <groupId>org.apache.causeway.extensions</groupId>
                        
<artifactId>causeway-extensions-fullcalendar-wicket-ui</artifactId>
                </dependency>
-               
+
                <dependency>
                        <groupId>org.apache.causeway.extensions</groupId>
                        
<artifactId>causeway-extensions-exceldownload-wicket-ui</artifactId>
diff --git 
a/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/ui/DemoAppWicketCommon.java
 
b/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/DemoAppWicketCommon.java
similarity index 92%
rename from 
examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/ui/DemoAppWicketCommon.java
rename to 
examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/DemoAppWicketCommon.java
index ec1eddf7c1..5429f66bee 100644
--- 
a/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/ui/DemoAppWicketCommon.java
+++ 
b/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/DemoAppWicketCommon.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.webapp.wicket.common.ui;
+package demoapp.webapp.wicket.common;
 
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
@@ -24,7 +24,7 @@ import org.springframework.context.annotation.Import;
 import 
org.apache.causeway.extensions.fullcalendar.wkt.ui.viewer.CausewayModuleExtFullCalendarWicketUi;
 import 
org.apache.causeway.extensions.viewer.wicket.exceldownload.ui.CausewayModuleExtExcelDownloadWicketUi;
 
-import demoapp.webapp.wicket.common.ui.custom.WhereInTheWorldPanelFactory;
+import 
demoapp.webapp.wicket.common.featured.customui.WhereInTheWorldPanelFactory;
 
 /**
  * Featured Wicket specific extensions.
diff --git 
a/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/ui/custom/WhereInTheWorldPanel.html
 
b/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/featured/customui/WhereInTheWorldPanel.html
similarity index 97%
rename from 
examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/ui/custom/WhereInTheWorldPanel.html
rename to 
examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/featured/customui/WhereInTheWorldPanel.html
index 66832ca05a..8146ee0e7f 100644
--- 
a/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/ui/custom/WhereInTheWorldPanel.html
+++ 
b/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/featured/customui/WhereInTheWorldPanel.html
@@ -51,7 +51,7 @@
                     <fieldset class="memberGroup" id="fieldSet-description">
                         <div class="panel panel-default">
                             <div class="panel-heading">
-                                <span class="panel-title">Description</span>
+                                <span class="panel-title"></span>
                             </div>
                             <div class="properties panel-body">
                                 <div>
diff --git 
a/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/ui/custom/WhereInTheWorldPanel.java
 
b/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/featured/customui/WhereInTheWorldPanel.java
similarity index 92%
rename from 
examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/ui/custom/WhereInTheWorldPanel.java
rename to 
examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/featured/customui/WhereInTheWorldPanel.java
index 95cd27f986..6937126512 100644
--- 
a/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/ui/custom/WhereInTheWorldPanel.java
+++ 
b/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/featured/customui/WhereInTheWorldPanel.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.webapp.wicket.common.ui.custom;
+package demoapp.webapp.wicket.common.featured.customui;
 
 import org.apache.wicket.Component;
 import org.apache.wicket.markup.html.basic.Label;
@@ -31,11 +31,12 @@ import 
org.apache.causeway.viewer.wicket.model.hints.UiHintContainer;
 import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt;
 import org.apache.causeway.viewer.wicket.ui.panels.PanelAbstract;
 
+import demoapp.dom.featured.customui.WhereInTheWorldPage;
+
 import lombok.SneakyThrows;
 import lombok.val;
 
-import demoapp.dom.featured.customui.geocoding.GeoapifyClient;
-import demoapp.dom.featured.customui.vm.WhereInTheWorldVm;
+import demoapp.dom.featured.customui.GeoapifyClient;
 
 //tag::class[]
 public class WhereInTheWorldPanel
@@ -68,7 +69,7 @@ extends PanelAbstract<ManagedObject, UiObjectWkt>  {
         super.onInitialize();
 
         val managedObject = getModel().getObject();;                       // 
<.>
-        val customUiVm = (WhereInTheWorldVm) managedObject.getPojo();      // 
<.>
+        val customUiVm = (WhereInTheWorldPage) managedObject.getPojo();    // 
<.>
 
         val latitude = new Label("latitude", customUiVm.getLatitude());    // 
<.>
         val longitude = new Label("longitude", customUiVm.getLongitude()); // 
<.>
@@ -87,7 +88,7 @@ extends PanelAbstract<ManagedObject, UiObjectWkt>  {
 
 //tag::createMapComponent[]
     @SneakyThrows
-    private Image createMapComponent(final String id, final WhereInTheWorldVm 
vm)  {
+    private Image createMapComponent(final String id, final 
WhereInTheWorldPage vm)  {
         val bytes = geoapifyClient.toJpeg(
                         vm.getLatitude(), vm.getLongitude(), vm.getZoom());  
// <.>
         return new Image(id, new ByteArrayResource("image/jpeg", bytes));    
// <.>
@@ -99,7 +100,6 @@ extends PanelAbstract<ManagedObject, UiObjectWkt>  {
         val managedObject = getModel().getManagedObject();
         val spec = managedObject.getSpecification();                           
    // <.>
         val property = spec.getPropertyElseFail(propertyId);                   
    // <.>
-        //val pm = otoa.getMemento();                                          
    // <.>
 
         val scalarModel =
                 getModel().getPropertyModel(                                   
    // <.>
diff --git 
a/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/ui/custom/WhereInTheWorldPanelFactory.java
 
b/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/featured/customui/WhereInTheWorldPanelFactory.java
similarity index 76%
rename from 
examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/ui/custom/WhereInTheWorldPanelFactory.java
rename to 
examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/featured/customui/WhereInTheWorldPanelFactory.java
index 9f57058d18..66305ad0bd 100644
--- 
a/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/ui/custom/WhereInTheWorldPanelFactory.java
+++ 
b/examples/demo/wicket/common/src/main/java/demoapp/webapp/wicket/common/featured/customui/WhereInTheWorldPanelFactory.java
@@ -16,8 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package demoapp.webapp.wicket.common.ui.custom;
+package demoapp.webapp.wicket.common.featured.customui;
 
+import javax.annotation.Priority;
 import javax.inject.Inject;
 
 import org.apache.wicket.Component;
@@ -29,39 +30,37 @@ import 
org.apache.causeway.viewer.commons.model.components.UiComponentType;
 import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt;
 import 
org.apache.causeway.viewer.wicket.ui.components.entity.EntityComponentFactoryAbstract;
 
-import demoapp.dom.featured.customui.geocoding.GeoapifyClient;
-import demoapp.dom.featured.customui.vm.WhereInTheWorldVm;
+import demoapp.dom.featured.customui.WhereInTheWorldPage;
+import demoapp.dom.featured.customui.GeoapifyClient;
 
 //tag::class[]
 @org.springframework.stereotype.Component
[email protected](PriorityPrecedence.EARLY)                           
                  // <.>
-public class WhereInTheWorldPanelFactory extends 
EntityComponentFactoryAbstract {
-
+@Priority(PriorityPrecedence.EARLY)                                            
 // <.>
+public class WhereInTheWorldPanelFactory
+        extends EntityComponentFactoryAbstract {
     private static final long serialVersionUID = 1L;
 
     public WhereInTheWorldPanelFactory() {
         super(
-            UiComponentType.ENTITY                                          // 
<.>
+            UiComponentType.ENTITY                                             
 // <.>
             , WhereInTheWorldPanel.class
         );
     }
 
     @Override
     protected ApplicationAdvice doAppliesTo(final UiObjectWkt entityModel) {   
 // <.>
-        final ManagedObject managedObject = entityModel.getObject();      // 
<.>
-        final Object domainObject = managedObject.getPojo();              // 
<.>
+        final ManagedObject managedObject = entityModel.getObject();           
 // <.>
+        final Object domainObject = managedObject.getPojo();                   
 // <.>
         return ApplicationAdvice.appliesIf(
-                domainObject instanceof WhereInTheWorldVm);               // 
<.>
+                domainObject instanceof WhereInTheWorldPage);                  
 // <.>
     }
 
     @Override
     public Component createComponent(final String id, final IModel<?> model) {
-        UiObjectWkt entityModel = (UiObjectWkt) model;                    // 
<.>
-        return new WhereInTheWorldPanel(id, entityModel, geoapifyClient); // 
<.>
+        UiObjectWkt entityModel = (UiObjectWkt) model;                         
 // <.>
+        return new WhereInTheWorldPanel(id, entityModel, geoapifyClient);      
 // <.>
     }
 
-    @Inject
-    private GeoapifyClient geoapifyClient;                                // 
<.>
-
+    @Inject private GeoapifyClient geoapifyClient;                             
 // <.>
 }
 //end::class[]
diff --git 
a/examples/demo/wicket/jdo/src/main/java/demoapp/webapp/wicket/jdo/DemoAppWicketJdo.java
 
b/examples/demo/wicket/jdo/src/main/java/demoapp/webapp/wicket/jdo/DemoAppWicketJdo.java
index 690eaf5139..76068a063d 100644
--- 
a/examples/demo/wicket/jdo/src/main/java/demoapp/webapp/wicket/jdo/DemoAppWicketJdo.java
+++ 
b/examples/demo/wicket/jdo/src/main/java/demoapp/webapp/wicket/jdo/DemoAppWicketJdo.java
@@ -42,7 +42,7 @@ import 
org.apache.causeway.viewer.wicket.applib.CausewayModuleViewerWicketApplib
 import 
org.apache.causeway.viewer.wicket.viewer.CausewayModuleViewerWicketViewer;
 
 import demoapp.web.DemoAppManifestJdo;
-import demoapp.webapp.wicket.common.ui.DemoAppWicketCommon;
+import demoapp.webapp.wicket.common.DemoAppWicketCommon;
 
 /**
  * Bootstrap the application.
diff --git 
a/examples/demo/wicket/jpa/src/main/java/demoapp/webapp/wicket/jpa/DemoAppWicketJpa.java
 
b/examples/demo/wicket/jpa/src/main/java/demoapp/webapp/wicket/jpa/DemoAppWicketJpa.java
index 50be485cff..0cd0934a56 100644
--- 
a/examples/demo/wicket/jpa/src/main/java/demoapp/webapp/wicket/jpa/DemoAppWicketJpa.java
+++ 
b/examples/demo/wicket/jpa/src/main/java/demoapp/webapp/wicket/jpa/DemoAppWicketJpa.java
@@ -42,7 +42,7 @@ import 
org.apache.causeway.viewer.wicket.applib.CausewayModuleViewerWicketApplib
 import 
org.apache.causeway.viewer.wicket.viewer.CausewayModuleViewerWicketViewer;
 
 import demoapp.web.DemoAppManifestJpa;
-import demoapp.webapp.wicket.common.ui.DemoAppWicketCommon;
+import demoapp.webapp.wicket.common.DemoAppWicketCommon;
 
 /**
  * Bootstrap the application.

Reply via email to