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

danhaywood pushed a commit to branch maint-1.16.1
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 39524c701a60d4d7729a17b75aec6fc8fb637ee1
Author: Dan Haywood <d...@haywood-associates.co.uk>
AuthorDate: Tue Feb 13 22:25:58 2018 +0000

    ISIS-1813: removes the petclinic tutorial, since out of date
---
 .../asciidoc/pages/tg/_tg_pet-clinic-extended.adoc |  13 -
 .../src/main/asciidoc/pages/tg/_tg_pet-clinic.adoc | 565 -----------------
 .../tg/_tg_stop-scaffolding-start-coding.adoc      | 694 ---------------------
 .../tutorials/pet-clinic/010-01-login-page.png     | Bin 31965 -> 0 bytes
 .../tutorials/pet-clinic/010-02-home-page.png      | Bin 54415 -> 0 bytes
 .../pet-clinic/010-03-prototyping-menu.png         | Bin 59183 -> 0 bytes
 .../tutorials/pet-clinic/010-04-simpleobjects.png  | Bin 57805 -> 0 bytes
 .../pet-clinic/010-05-simpleobject-list.png        | Bin 29631 -> 0 bytes
 .../pet-clinic/020-01-idea-configuration.png       | Bin 35012 -> 0 bytes
 .../pet-clinic/020-02-idea-configuration.png       | Bin 7430 -> 0 bytes
 .../030-01-idea-configuration-updated.png          | Bin 35122 -> 0 bytes
 .../tutorials/pet-clinic/030-02-updated-app.png    | Bin 32215 -> 0 bytes
 .../040-01-idea-configuration-updated.png          | Bin 35349 -> 0 bytes
 .../tutorials/pet-clinic/050-01-list-all.png       | Bin 33299 -> 0 bytes
 .../tutorials/pet-clinic/050-02-view-pet.png       | Bin 34270 -> 0 bytes
 .../tutorials/pet-clinic/060-01-owners-menu.png    | Bin 65309 -> 0 bytes
 .../tutorials/pet-clinic/060-02-owners-list.png    | Bin 31905 -> 0 bytes
 .../tutorials/pet-clinic/060-03-pets-list.png      | Bin 36166 -> 0 bytes
 .../pet-clinic/060-04-pet-owner-autoComplete.png   | Bin 40468 -> 0 bytes
 .../images/tutorials/pet-clinic/domain-model.png   | Bin 27464 -> 0 bytes
 .../src/main/asciidoc/pages/tg/tg.adoc             | 683 +++++++++++++++++++-
 21 files changed, 672 insertions(+), 1283 deletions(-)

diff --git 
a/adocs/documentation/src/main/asciidoc/pages/tg/_tg_pet-clinic-extended.adoc 
b/adocs/documentation/src/main/asciidoc/pages/tg/_tg_pet-clinic-extended.adoc
deleted file mode 100644
index 4fb1ac3..0000000
--- 
a/adocs/documentation/src/main/asciidoc/pages/tg/_tg_pet-clinic-extended.adoc
+++ /dev/null
@@ -1,13 +0,0 @@
-[[_tg_pet-clinic-extended]]
-= Pet Clinic (Extended)
-: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 [...]
-:_basedir: ../../
-:_imagesdir: images/
-
-
-
-An extended version of the xref:tg.adoc#_tg_tutorials_pet-clinic[pet clinic] 
can be found on 
link:https://github.com/johandoornenbal/tutorial_code/blob/master/AsciiDoc/1_petclinic_introduction.adoc[this
 github repo].
-It was written by Johan Doornenbal.
-
-This version also includes a 
link:https://github.com/johandoornenbal/petclinic_mynewcode[sample solution], 
also as a github repo.
-
diff --git a/adocs/documentation/src/main/asciidoc/pages/tg/_tg_pet-clinic.adoc 
b/adocs/documentation/src/main/asciidoc/pages/tg/_tg_pet-clinic.adoc
deleted file mode 100644
index 0285e76..0000000
--- a/adocs/documentation/src/main/asciidoc/pages/tg/_tg_pet-clinic.adoc
+++ /dev/null
@@ -1,565 +0,0 @@
-[[_tg_pet-clinic]]
-= Pet Clinic
-: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 [...]
-:_basedir: ../../
-:_imagesdir: images/
-
-
-This is a step-by-step tutorial to build up a simple "petclinic" application, 
starting from the 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_getting-started_simpleapp-archetype[SimpleApp
 archetype].
-It was originally written by Jeroen van der Wal.
-
-It consists of just three domain classes 
(http://yuml.me/edit/3db2078c[http://yuml.me/3db2078c]):
-
-image::{_imagesdir}tutorials/pet-clinic/domain-model.png[link="{_imagesdir}tutorials/pet-clinic/domain-model.png"]
-
-
-This supports the following use cases:
-
-* register a `Pet`
-* register an `Owner`
-* maintain a ``Pet``'s details
-* check in a `Pet` to visit the clinic
-* enter a `Diagnosis`
-* check out a `Pet` after visiting the clinic
-
-Either follow along or check out the tags from the corresponding 
https://github.com/danhaywood/isis-app-petclinic[github repo].
-
-
-== Prerequisites
-
-You'll need:
-
-* Java 7 JDK
-* http://maven.apache.org/[Maven] 3.2.x
-* an IDE, such as http://www.eclipse.org/[Eclipse] or 
https://www.jetbrains.com/idea/[IntelliJ IDEA].
-
-
-
-
-== Run the archetype
-
-Throughout this tutorial you can, if you wish, just checkout from the github 
repo wherever you see a "git checkout" note:
-
-[TIP]
-====
-[source,bash]
-----
-git checkout 
https://github.com/danhaywood/isis-app-petclinic/commit/249abe476797438d83faa12ff88365da2c362451
-----
-
-Do note that the tutorial was originally developed against Apache Isis 
1.8.0-SNAPSHOT; replace "1.8.0-SNAPSHOT" for the any version from 1.8.0 up to 
1.13.1.
-(The structure of Apache Isis archetype changed in 1.13.2).
-====
-
-
-Run the simpleapp archetype to build an empty Isis application.
-With the *nix bash shell, use:
-
-[source,bash]
-----
-mvn archetype:generate  \
-    -D archetypeGroupId=org.apache.isis.archetype \
-    -D archetypeArtifactId=simpleapp-archetype \
-    -D archetypeVersion=1.13.1 \
-    -D groupId=com.mycompany \
-    -D artifactId=petclinic \
-    -D version=1.0-SNAPSHOT \
-    -D 
archetypeRepository=http://repository-estatio.forge.cloudbees.com/snapshot/ \
-    -B
-----
-
-Adjust as necessary if using Windows `cmd.exe` or Powershell.
-
-[NOTE]
-====
-You can use 1.13.2 (or later) version of the archetype if you wish, however be 
aware that the structure of the solution repo (mentioned above) will be 
different from the structure for applications generated using 1.13.2 onwards.
-====
-
-
-
-This will generate the app in a `petclinic` directory. Move the contents back:
-
-[source,bash]
-----
-mv petclinic/* .
-rmdir petclinic
-----
-
-
-
-
-== Build and run
-
-Start off by building the app from the command line:
-
-[source,bash]
-----
-mvn clean install
-----
-
-
-You can run using the mvn-jetty-plugin:
-
-[source,bash]
-----
-mvn -pl webapp jetty:run
-----
-
-You can then browser to http://localhost:8080[http://localhost:8080]
-
-
-If using 1.13.2 or later, then you can also use the 
link:https://github.com/danhaywood/java-mavenmixin-jettyconsole/blob/master/README.adoc[jetty-console]
 plugin:
-
-[source,bash]
-----
-mvn clean install -Dmavenmixin-jettyconsole
-mvn -pl webapp antrun:run -Dmavenmixin-jettyconsole
-----
-
-This packages the app as a standalone JAR, and then runs using the AntRun 
plugin.
-
-
-== Using the app
-
-Navigate to the Wicket UI (eg 
http://localhost:8080/wicket[http://localhost:8080/wicket]), and login 
(sven/pass).
-
-image::{_imagesdir}tutorials/pet-clinic/010-01-login-page.png[width="600px",link="{_imagesdir}tutorials/pet-clinic/010-01-login-page.png"]
-
-
-
-The home page should be shown:
-
-image::{_imagesdir}tutorials/pet-clinic/010-02-home-page.png[width="600px",link="{_imagesdir}tutorials/pet-clinic/010-02-home-page.png"]
-
-
-
-Install the fixtures (example test data) using the `Prototyping` menu:
-
-image::{_imagesdir}tutorials/pet-clinic/010-03-prototyping-menu.png[width="600px",link="{_imagesdir}tutorials/pet-clinic/010-03-prototyping-menu.png"]
-
-
-
-List all objects using the `Simple Objects` menu:
-
-image::{_imagesdir}tutorials/pet-clinic/010-04-simpleobjects.png[width="600px",link="{_imagesdir}tutorials/pet-clinic/010-04-simpleobjects.png"]
-
-
-To return the objects created:
-
-image::{_imagesdir}tutorials/pet-clinic/010-05-simpleobject-list.png[width="600px",link="{_imagesdir}tutorials/pet-clinic/010-05-simpleobject-list.png"]
-
-
-
-Experiment some more, to:
-
-* create a new object
-* list all objects
-
-Go back to the splash screen, and quit the app. Note that the database runs 
in-memory (using HSQLDB) so any data created will be lost between runs.
-
-
-
-
-== Dev environment
-
-Set up xref:../../guides/dg/dg.adoc#_dg_ide[an IDE] and import the project to 
be able to run and debug the app.
-
-Then set up a launch configuration so that you can run the app from within the 
IDE. To save having to run the fixtures
-every time, specify the following system properties:
-
-[source,bash]
-----
--Disis.persistor.datanucleus.install-fixtures=true 
-Disis.fixtures=fixture.simple.scenario.SimpleObjectsFixture
-----
-
-For example, here's what a launch configuration in IntelliJ idea looks like:
-
-image::{_imagesdir}tutorials/pet-clinic/020-01-idea-configuration.png[width="600px",link="{_imagesdir}tutorials/pet-clinic/020-01-idea-configuration.png"]
-
-
-
-where the "before launch" maven goal (to run the DataNucleus enhancer) is 
defined as:
-
-
-image::{_imagesdir}tutorials/pet-clinic/020-02-idea-configuration.png[width="400px",link="{_imagesdir}tutorials/pet-clinic/020-02-idea-configuration.png"]
-
-
-
-
-== Explore codebase
-
-Apache Isis applications are organized into several Maven modules. Within your 
IDE navigate to the various classes and correlate back to the generated UI:
-
-* `petclinic` : parent module
-* `petclinic-dom`: domain objects module
-** entity: `dom.simple.SimpleObject`
-** repository: `dom.simple.SimpleObjects`
-* `petclinic-fixture`: fixtures module
-** fixture script:`fixture.simple.SimpleObjectsFixture`
-* `petclinic-integtests`: integration tests module
-* `petclinic-webapp`: webapp module
-** (builds the WAR file)
-
-
-
-
-== Testing
-
-Testing is of course massively important, and Apache Isis makes both unit 
testing and (end-to-end) integration testing easy. Building the app from the 
Maven command line ("mvn clean install") will run all tests, but you should 
also run the tests from within the IDE.
-
-* `myapp-dom` unit tests
-* run
-* inspect, eg
- - `SimpleObjectTest`
-* `myapp-integtests` integration tests
-* run
-* inspect, eg:
-** `integration.tests.smoke.SimpleObjectsTest`
-** `integration.specs.simple.SimpleObjectSpec_listAllAndCreate.feature`
-* generated report, eg
- - `myapp/integtests/target/cucumber-html-report/index.html`
-** change test in IDE, re-run (in Maven)
-
-If you have issues with the integration tests, make sure that the domain 
classes have been enhanced by the DataNucleus enhancer. (The exact mechanics 
depends on the IDE being used).
-
-
-
-
-== Update POM files
-
-[TIP]
-====
-[source,bash]
-----
-git checkout 
https://github.com/danhaywood/isis-app-petclinic/commit/68904752bc2de9ebb3c853b79236df2b3ad2c944
-----
-
-====
-
-The POM files generated by the simpleapp archetype describe the app as 
"SimpleApp". Update them to say "PetClinic" instead.
-
-
-
-
-== Delete the BDD specs
-
-[TIP]
-====
-[source,bash]
-----
-git checkout 
https://github.com/danhaywood/isis-app-petclinic/commit/9046226249429b269325dfa2baccf03635841c20
-----
-
-====
-
-
-During this tutorial we're going to keep the integration tests in-sync with 
the code, but we're going to stop short of writing BDD/Cucumber specs.
-
-Therefore delete the BDD feature spec and glue in the `integtest` module:
-
-* `integration/specs/*`
-* `integration/glue/*`
-
-
-
-
-== Rename artifacts
-
-[TIP]
-====
-[source,bash]
-----
-git checkout 
https://github.com/danhaywood/isis-app-petclinic/commit/bee3629c0b64058f939b6dd20f226be31810fc66
-----
-
-====
-
-
-Time to start refactoring the app. The heart of the PetClinic app is the `Pet` 
concept, so go through the code and refactor. While we're at it, refactor the 
app itself from "SimpleApp" to "PetClinicApp".
-
-See the git commit for more detail, but in outline, the renames required are:
-
-* in the `dom` module's production code
-** `SimpleObject` -&gt; `Pet` (entity)
-** `SimpleObjects` -&gt; `Pets` (repository domain service)
-** `SimpleObject.layout.json` -&gt; `Pet.layout.json` (layout hints for the 
`Pet` entity)
-** delete the `SimpleObject.png`, and add a new `Pet.png` (icon shown against 
all `Pet` instances).
-* in the `dom` module's unit test code
-** `SimpleObjectTest` -&gt; `PetTest` (unit tests for `Pet` entity)
-** `SimpleObjectsTest` -&gt; `PetsTest` (unit tests for `Pets` domain service)
-* in the `fixture` module:
-** `SimpleObjectsFixturesService` -&gt; `PetClinicAppFixturesService` 
(rendered as the prototyping menu in the UI)
-** `SimpleObjectsTearDownService` -&gt; `PetClinicAppTearDownService` (tear 
down all objects between integration tests)
-** `SimpleObjectAbstract` -&gt; `PetAbstract` (abstract class for setting up a 
single pet object
-*** and corresponding subclasses to set up sample data (eg `PetForFido`)
-** `SimpleObjectsFixture` -&gt; `PetsFixture` (tear downs system and then sets 
up all pets)
-* in the `integtest` module:
-** `SimpleAppSystemInitializer` -&gt; `PetClinicAppSystemInitializer` 
(bootstraps integration tests with domain service/repositories)
-** `SimpleAppIntegTest` -&gt; `PetClinicAppIntegTest` (base class for 
integration tests)
-** `SimpleObjectTest` -&gt; `PetTest` (integration test for `Pet` entity)
-** `SimpleObjectsTest` -&gt; `PetsTest` (integration test for `Pets` domain 
service)
-* in the `webapp` module:
-** `SimpleApplication` -&gt; `PetClinicApplication`
-** update `isis.properties`
-** update `web.xml`
-
-
-Note that `Pet` has both both Isis and JDO annotations:
-
-[source,java]
-----
-@javax.jdo.annotations.PersistenceCapable(identityType=IdentityType.DATASTORE) 
// <1>
-@javax.jdo.annotations.DatastoreIdentity(                                      
// <2>
-        strategy=javax.jdo.annotations.IdGeneratorStrategy.IDENTITY,
-         column="id")
-@javax.jdo.annotations.Version(                                                
// <3>
-        strategy=VersionStrategy.VERSION_NUMBER,
-        column="version")
-@javax.jdo.annotations.Unique(name="Pet_name_UNQ", members = {"name"})         
// <4>
-@ObjectType("PET")                                                             
// <5>
-@Bookmarkable                                                                  
// <6>
-public class Pet implements Comparable<Pet> {
-    ...
-}
-----
-
-where:
-
-<1> `@PersistenceCapable` and
-<2> `@DatastoreIdentity` specify a surrogate `Id` column to be used as the 
primary key
-<3> `@Version` provides support for optimistic locking
-<4> `@Unique` enforces a uniqueness constraint so that no two `Pet`s can have 
the same name (unrealistic, but can refactor later)
-<5> `@ObjectType` is used by Apache Isis for its own internal "OID" 
identifier; this also appears in the URL in Apache Isis' Wicket viewer and REST 
API
-<6> `@Bookmarkable` indicates that the object can be automatically bookmarked 
in Apache Isis' Wicket viewer
-
-[NOTE]
-====
-The `@ObjectType` and `@Bookmarkable` annotations have since been deprecated, 
replaced with `@DomainObject(objectType=...)` and 
`@DomainObjectLayout(bookmarking=...)`
-====
-
-
-The `Pets` domain service also has Isis annotations:
-
-[source,java]
-----
-@DomainService(repositoryFor = Pet.class)
-@DomainServiceLayout(menuOrder = "10")
-public class Pets {
-    ...
-}
-----
-
-where:
-
-* `DomainService` indicates that the service should be instantiated 
automatically (as a singleton)
-* `DomainServiceLayout` provides UI hints, in this case the positioning of the 
menu for the actions provided by the service
-
-To run the application will require an update to the IDE configuration, for 
the changed name of the fixture class:
-
-
-image::{_imagesdir}tutorials/pet-clinic/030-01-idea-configuration-updated.png[width="600px",link="{_imagesdir}tutorials/pet-clinic/030-01-idea-configuration-updated.png"]
-
-
-Running the app should now show `Pet`s:
-
-image::{_imagesdir}tutorials/pet-clinic/030-02-updated-app.png[width="600px",link="{_imagesdir}tutorials/pet-clinic/030-02-updated-app.png"]
-
-
-
-
-
-== Update package names
-
-[TIP]
-====
-[source,bash]
-----
-git checkout 
https://github.com/danhaywood/isis-app-petclinic/commit/55ec36e520191f5fc8fe7f5b89956814eaf13317
-----
-
-====
-
-
-
-The classes created by the simpleapp archetype are by default in the `simple` 
package. Move these classes to `pets` package instead. Also adjust package 
names where they appear as strings:
-
-* in `PetClinicAppFixturesService`, change the package name from 
"fixture.simple" to "fixture.pets".
-* in `PetClinicAppSystemInitializer`, change the package name "dom.simple" to 
"dom.pets", and similarly "fixture.simple" to "fixture.pets"
-* in `WEB-INF/isis.properties`, similarly change the package name "dom.simple" 
to "dom.pets", and similarly "fixture.simple" to "fixture.pets"
-
-To run the application will require a further update to the IDE configuration, 
for the changed package of the fixture class:
-
-
-image::{_imagesdir}tutorials/pet-clinic/040-01-idea-configuration-updated.png[width="600px",link="{_imagesdir}tutorials/pet-clinic/040-01-idea-configuration-updated.png"]
-
-
-
-== Add `PetSpecies` enum
-
-[TIP]
-====
-[source,bash]
-----
-git checkout 
https://github.com/danhaywood/isis-app-petclinic/commit/55c9cd28ff960220719b3dc7cb8abadace8d0829
-----
-
-====
-
-
-Each `Pet` is of a particular species. Model these as an enum called 
`PetSpecies`:
-
-[source,java]
-----
-public enum PetSpecies {
-    Cat,
-    Dog,
-    Budgie,
-    Hamster,
-    Tortoise
-}
-----
-
-Introduce a new property on `Pet` of this type:
-
-[source,java]
-----
-public class Pet {
-    ...
-    private PetSpecies species;
-    @javax.jdo.annotations.Column(allowsNull = "false")
-    public PetSpecies getSpecies() { return species; }
-    public void setSpecies(final PetSpecies species) { this.species = species; 
}
-    ...
-}
-----
-
-Update fixtures, unit tests and integration tests.
-
-
-
-
-== Icon to reflect pet species
-
-[TIP]
-====
-[source,bash]
-----
-git checkout 
https://github.com/danhaywood/isis-app-petclinic/commit/2212765694693eb463f8fa88bab1bad154add0cb
-----
-
-====
-
-
-Rather than using a single icon for a domain class, instead a different icon 
can be supplied for each instance. We can therefore have different icon files 
for each pet, reflecting that pet's species.
-
-[source,java]
-----
-public class Pet {
-    ...
-    public String iconName() {
-        return getSpecies().name();
-    }
-    ...
-}
-----
-
-Download corresponding icon files (`Dog.png`, `Cat.png` etc)
-
-Running the app shows the `Pet` and its associated icon:
-
-image::{_imagesdir}tutorials/pet-clinic/050-01-list-all.png[width="600px",link="{_imagesdir}tutorials/pet-clinic/050-01-list-all.png"]
-
-
-
-with the corresponding view of the `Pet`:
-
-image::{_imagesdir}tutorials/pet-clinic/050-02-view-pet.png[width="600px",link="{_imagesdir}tutorials/pet-clinic/050-02-view-pet.png"]
-
-
-== Add pet's `Owner`
-
-[TIP]
-====
-[source,bash]
-----
-git checkout 
https://github.com/danhaywood/isis-app-petclinic/commit/6f92a8ee8e76696d005da2a8b7a746444d017546
-----
-
-====
-
-
-Add the `Owner` entity and corresponding `Owners` domain service (repository). 
Add a query to find `Order`s by name:
-
-[source,java]
-----
-...
-@javax.jdo.annotations.Queries( {
-        @javax.jdo.annotations.Query(
-                name = "findByName", language = "JDOQL",
-                value = "SELECT "
-                        + "FROM dom.owners.Owner "
-                        + "WHERE name.matches(:name)")
-})
-public class Owner ... {
-    ...
-}
-----
-
-and `findByName(...)` in `Owners`:
-
-[source,java]
-----
-public class Owners {
-    ...
-    public List<Owner> findByName(
-            @ParameterLayout(named = "Name")
-            final String name) {
-        final String nameArg = String.format(".*%s.*", name);
-        final List<Owner> owners = container.allMatches(
-                new QueryDefault<>(
-                        Owner.class,
-                        "findByName",
-                        "name", nameArg));
-        return owners;
-    }
-    ...
-}
-----
-
-Add an `owner` property to `Pet`, with supporting `autoCompleteXxx()` method 
(so that available owners are shown in a drop-down list box):
-
-[source,java]
-----
-public class Pet ... {
-    ...
-    private Owner owner;
-    @javax.jdo.annotations.Column(allowsNull = "false")
-    public Owner getOwner() { return owner; }
-    public void setOwner(final Owner owner) { this.owner = owner; }
-    public Collection<Owner> autoCompleteOwner(final @MinLength(1) String 
name) {
-        return owners.findByName(name);
-    }
-    ...
-}
-----
-
-Also updated fixture data to set up a number of `Owner`s, and associate each 
`Pet` with an `Owner`. Also add unit tests and integration tests for 
`Owner`/`Owners` and updated for `Pet`/`Pets`.
-
-When running the app, notice the new `Owners` menu:
-
-image::{_imagesdir}tutorials/pet-clinic/060-01-owners-menu.png[width="600px",link="{_imagesdir}tutorials/pet-clinic/060-01-owners-menu.png"]
-
-which when invoked returns all `Owner` objects:
-
-image::{_imagesdir}tutorials/pet-clinic/060-02-owners-list.png[width="600px",link="{_imagesdir}tutorials/pet-clinic/060-02-owners-list.png"]
-
-
-Each `Pet` also indicates its corresponding `Owner`:
-
-image::{_imagesdir}tutorials/pet-clinic/060-03-pets-list.png[width="600px",link="{_imagesdir}tutorials/pet-clinic/060-03-pets-list.png"]
-
-
-And, on editing a `Pet`, a new `Owner` can be specified using the autoComplete:
-
-image::{_imagesdir}tutorials/pet-clinic/060-04-pet-owner-autoComplete.png[width="600px",link="{_imagesdir}tutorials/pet-clinic/060-04-pet-owner-autoComplete.png"]
-
diff --git 
a/adocs/documentation/src/main/asciidoc/pages/tg/_tg_stop-scaffolding-start-coding.adoc
 
b/adocs/documentation/src/main/asciidoc/pages/tg/_tg_stop-scaffolding-start-coding.adoc
deleted file mode 100644
index 0e6c42c..0000000
--- 
a/adocs/documentation/src/main/asciidoc/pages/tg/_tg_stop-scaffolding-start-coding.adoc
+++ /dev/null
@@ -1,694 +0,0 @@
-[[_tg_stop-scaffolding-start-coding]]
-= Stop scaffolding, start coding
-: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 [...]
-:_basedir: ../../
-:_imagesdir: images/
-
-
-This is a half-day tutorial on developing domain-driven apps using Apache 
Isis.  Actually, you could probably spend a full day working through this 
tutorial if you wanted to, so pick and choose the bits that look interesting.
-It was originally written by Dan Haywood.
-
-There's a bit of overlap with the xref:tg.adoc#_tg_tutorials_pet-clinic[Pet 
Clinic] tutorial initially, but it then sets off on its own.
-
-
-
-== Prerequisites
-
-You'll need:
-
-* Java 7 JDK
-* http://maven.apache.org/[Maven] 3.2.x
-* an IDE, such as http://www.eclipse.org/[Eclipse] or 
https://www.jetbrains.com/idea/[IntelliJ IDEA].
-
-
-
-== Run the archetype
-
-Run the simpleapp archetype to build an empty Isis application.
-With the *nix bash shell, use:
-
-
-[source,bash]
-----
-mvn archetype:generate  \
-    -D archetypeGroupId=org.apache.isis.archetype \
-    -D archetypeArtifactId=simpleapp-archetype \
-    -D archetypeVersion=1.16.0 \
-    -D groupId=com.mycompany \
-    -D artifactId=myapp \
-    -D version=1.0-SNAPSHOT \
-    -D 
archetypeRepository=http://repository-estatio.forge.cloudbees.com/snapshot/ \
-    -B
-----
-
-Adjust as necessary if using Windows `cmd.exe` or Powershell.
-
-
-
-== Build and run
-
-Start off by building the app from the command line:
-
-[source,bash]
-----
-cd myapp
-mvn clean install -D mavenmixin-jettyconsole
-----
-
-Once that's built then run using:
-
-[source,bash]
-----
-mvn -pl webapp antrun:run -D mavenmixin-jettyconsole
-----
-
-A splash screen should appear offering to start up the app. Go ahead and 
start; the web browser should be opened at 
http://localhost:8080[http://localhost:8080]
-
-Alternatively, you can run using the mvn-jetty-plugin:
-
-[source,bash]
-----
-mvn -pl webapp jetty:run
-----
-
-This will accomplish the same thing, though the webapp is mounted at a 
slightly different URL
-
-
-
-
-== Using the app
-
-Navigate to the Wicket UI (eg 
link:http://localhost:8080/wicket[http://localhost:8080/wicket]), and login 
(sven/pass).
-
-Once at the home page:
-
-* install fixtures
-* list all objects
-* create a new object
-* list all objects
-
-Go back to the splash screen, and quit the app. Note that the database runs 
in-memory (using HSQLDB) so any data created will be lost between runs.
-
-
-
-
-== Dev environment
-
-Set up xref:../../guides/dg/dg.adoc#_dg_ide[an IDE] and import the project to 
be able to run and debug the app.
-
-Then set up a launch configuration and check that you can:
-
-* Run the app from within the IDE
-* Run the app in debug mode
-* Run with different deploymentTypes; note whether prototype actions (those 
annotated 
xref:../../guides/rgant/rgant.adoc#_rgant-Action_restrictTo[`@Action(restrictTo=PROTOTYPING`])
 are available or not:
-* `--type SERVER_PROTOTYPE`
-* `--type SERVER`
-
-
-
-
-== Explore codebase
-
-Apache Isis applications are organized into several Maven modules. Within your 
IDE navigate to the various classes and correlate back to the generated UI:
-
-* `myapp` : parent module
-* `myapp-dom`: domain objects module
-* entity: `dom.simple.SimpleObject`
-* repository: `dom.simple.SimpleObjects`
-* `myapp-fixture`: fixtures module
-* fixture script:`fixture.simple.SimpleObjectsFixture`
-* `myapp-integtests`: integration tests module
-* `myapp-webapp`: webapp module
-* (builds the WAR file)
-
-
-
-
-== Testing
-
-Testing is of course massively important, and Apache Isis makes both unit 
testing and (end-to-end) integration testing easy. Building the app from the 
Maven command line ("mvn clean install") will run all tests, but you should 
also run the tests from within the IDE.
-
-* `myapp-dom` unit tests
-* run
-* inspect, eg
- - `SimpleObjectTest`
-* `myapp-integtests` integration tests
-* run
-* inspect, eg:
-** `integration.tests.smoke.SimpleObjectsTest`
-** `integration.specs.simple.SimpleObjectSpec_listAllAndCreate.feature`
-* generated report, eg
- - `myapp/integtests/target/cucumber-html-report/index.html`
-** change test in IDE, re-run (in Maven)
-
-If you have issues with the integration tests, make sure that the domain 
classes have been enhanced by the DataNucleus enhancer. (The exact mechanics 
depends on the IDE being used).
-
-
-
-
-== Prototyping
-
-Although testing is important, in this tutorial we want to concentrate on how 
to write features and to iterate quickly. So for now, exclude the `integtests` 
module. Later on in the tutorial we'll add the tests back in so you can learn 
how to write automated tests for the features of your app.
-
-In the parent `pom.xml`:
-
-[source,xml]
-----
-<modules>
-    <module>dom</module>
-    <module>fixture</module>
-    <module>integtests</module>
-    <module>webapp</module>
-</modules>
-----
-
-change to:
-
-[source,xml]
-----
-<modules>
-    <module>dom</module>
-    <module>fixture</module>
-    <!--
-    <module>integtests</module>
-    -->
-    <module>webapp</module>
-</modules>
-----
-
-
-
-
-== Build a domain app
-
-The remainder of the tutorial provides guidance on building a domain 
application. We don't mandate any particular design, but we suggest one with no 
more than 3 to 6 domain entities in the first instance. If you're stuck for 
ideas, then how about:
-
-* a todo app (``ToDoItem``s)
-* a pet clinic (`Pet`, `Owner`, `PetSpecies`, `Visit`)
-* a library (`Book`, `Title`, `LibraryMember`, `Loan`, `Reservation`)
-* a holiday cottage rental system
-* a scrum/kanban system (inspired by Trello)
-* a meeting planner (inspired by Doodle)
-* (the domain model for) a CI server (inspired by Travis/Jenkins)
-* a shipping system (inspired by the example in the DDD "blue" book)
-* a system for ordering coffee (inspired by Restbucks, the example in "Rest in 
Practice" book)
-
-Hopefully one of those ideas appeals or sparks an idea for something of your 
own.
-
-
-
-
-== Domain entity
-
-Most domain objects in Apache Isis applications are persistent entities. In 
the simpleapp archetype the `SimpleObject` is an example. We can start 
developing our app by refactoring that class:
-
-* rename the `SimpleObject` class
-** eg rename to `Pet`
-* if required, rename the `SimpleObject` class' `name` property
-** for `Pet`, can leave `name` property as is
-* specify a 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_ui-hints_object-titles-and-icons[title]
-* specify an 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_ui-hints_object-titles-and-icons[icon]
-* make the entity bookmarkable by adding the 
xref:../../guides/rgant/rgant.adoc#_rgant-DomainObjectLayout_bookmarking[`@DomainObjectLayout#bookmarking()`]
 attribute.
-* confirm is available from bookmark panel (top-left of Wicket UI)
-
-
-
-
-== Domain service
-
-Domain services often act as factories or repositories to entities; more 
generally can be used to "bridge across" to other domains/bounded contexts. 
Most are application-scoped, but they can also be request-scoped if required.
-
-In the simpleapp archetype the `SimpleObjects` service is a factory/repository 
for the original `SimpleObject` entity. For our app it therefore makes sense to 
refactor that class into our own first service:
-
-* rename the `SimpleObjects` class
-** eg rename to `Pets`
-* review `create` action (acting as a factory)
-** as per the docs describing 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_crud[how to create or delete objects]
-* rename if you wish
-** eg `newPet(...)` or `addPet(...)`
-* review `listAll` action (acting as a repository)
-* as per the docs describing 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_crud[how to write a custom repository]
-* note the annotations on the corresponding domain class (originally called 
`SimpleObject`, though renamed by now, eg to `Pet`)
-* rename if you wish
-** eg `listPets()`
-* note the 
xref:../../guides/rgant/rgant.adoc#_rgant-DomainService[`@DomainService`] 
annotation
-* optional: add an action to a return subset of objects
-** use the JDO `@Query` annotation
-** see for example the Isisaddons example 
https://github.com/isisaddons/isis-app-todoapp[todoapp] (not ASF), see 
https://github.com/apache/isis/blob/b3e936c9aae28754fb46c2df52b1cb9b023f9ab8/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java#L93[here]
 and 
https://github.com/apache/isis/blob/b3e936c9aae28754fb46c2df52b1cb9b023f9ab8/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItems.java#L63[here]
-
-
-
-
-== Fixture scripts
-
-Fixture scripts are used to setup the app into a known state. They are great 
for demo's and as a time-saver when implementing a feature, and they can also 
be reused in automated integration tests. We usually also have a fixture script 
to zap all the (non-reference) data (or some logical subset of the data)
-
-* rename the `SimpleObjectsTearDownFixture` class
-* and update to delete from the appropriate underlying database table(s)
-* use the injected 
xref:../../guides/rgsvc/rgsvc.adoc#_rgsvc_persistence-layer-api_IsisJdoSupport[`IsisJdoSupport`]
 domain service.
-* refactor/rename the fixture script classes that create instances your entity:
-* `RecreateSimpleObjects`, which sets up a set of objects for a given scenario
-* `SimpleObjectCreate` which creates a single object
-* note that domain services can be injected into these fixture scripts
-
-
-
-
-== Actions
-
-Most business functionality is implemented using actions basically a `public` 
method accepting domain classes and primitives as its parameter types. The 
action can return a domain entity, or a collection of entities, or a 
primitive/String/value, or void. If a domain entity is returned then that 
object is rendered immediately; if a collection is returned then the Wicket 
viewer renders a table. Such collections are sometimes called "standalone" 
collections.
-
-* write an action to update the domain property (originally called 
`SimpleObject#name`, though renamed by now)
-* use the 
xref:../../guides/rgant/rgant.adoc#_rgant-ParameterLayout_named[`@ParameterLayout(named=...)`]
 annotation to specify the name of action parameters
-* use the 
xref:../../guides/rgant/rgant.adoc#_rgant-Action_semantics[`@Action(semanticsOf=...)`]
  annotation to indicate the semantics of the action (safe/query-only, 
idempotent or non-idempotent)
-* annotate safe action as bookmarkable using 
xref:../../guides/rgant/rgant.adoc#_rgant-ActionLayout_bookmarking[`@ActionLayout(bookmarking=...)`]
-* confirm is available from bookmark panel (top-left of Wicket UI)
-* optional: add an action to clone an object
-
-
-
-
-== REST API
-
-As well as exposing the Wicket viewer, Isis also exposes a REST API (an 
implementation of the http://restfulobjects.org[Restful Objects spec]). All of 
the functionality of the domain object model is available through this REST API.
-
-* add Chrome extensions
-* install 
https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en[Postman]
-* install 
https://chrome.google.com/webstore/detail/jsonview/chklaanhfefbnpoihckbnefhakgolnmc?hl=en[JSON-View]
-* browse to Wicket viewer, install fixtures
-* browse to the http://localhost:8080/restful[http://localhost:8080/restful] 
API
-* invoke the service to list all objects
-* services
-* actions
-* invoke (invoking 0-arg actions is easy; the Restful Objects spec defines how 
to invoke N-arg actions)
-
-
-
-
-== Specify Action semantics
-
-The semantics of an action (whether it is safe/query only, whether it is 
idempotent, whether it is neither) can be specified for each action; if not 
specified then Isis assumes non-idempotent. In the Wicket viewer this matters 
in that only query-only actions can be bookmarked or used as contributed 
properties/collections. In the RESTful viewer this matters in that it 
determines the HTTP verb (GET, PUT or POST) that is used to invoke the action.
-
-* experiment changing 
xref:../../guides/rgant/rgant.adoc#_rgant-Action_semantics[`@Action(semantics=...)`]
 on actions
-* note the HTTP methods exposed in the REST API change
-* note whether the non-safe actions are bookmarkable (assuming that it has 
been annotated with `@ActionLayout(bookmarking=...)`, that is).
-
-
-
-
-== Value properties
-
-Domain entities have state: either values (primitives, strings) or references 
to other entities. In this section we explore adding some value properties
-
-* add some 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_programming-model_properties[value 
properties]; also:
-* for string properties
-** use the 
xref:../../guides/rgant/rgant.adoc#_rgant-PropertyLayout_multiLine[`@PropertyLayout(multiLine=...)`]
 annotation to render a text area instead of a text box
-** use the 
xref:../../guides/rgant/rgant.adoc#_rgant-Property_maxLength[`@Property(maxLength=...)`]
 annotation to specify the maximum number of characters allowable
-** use joda date/time properties, bigdecimals and blob/clob properties
-* use the 
xref:../../guides/rgant/rgant.adoc#_rgant-Property_optionality[`@Column(allowsNull=...)`]
 annotation specify whether a property is optional or mandatory
-* use enums for properties (eg as used in the Isis addons example 
https://github.com/isisaddons/isis-app-todoapp[todoapp], see 
https://github.com/apache/isis/blob/b3e936c9aae28754fb46c2df52b1cb9b023f9ab8/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java#L207[here]
 and 
https://github.com/apache/isis/blob/b3e936c9aae28754fb46c2df52b1cb9b023f9ab8/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java#L266[here])
-* update the corresponding domain service for creating new instances
-* for all non-optional properties will either need to prompt for a value, or 
calculate some suitable default
-* change the implementation of title, if need be
-* revisit the title, consider whether to use the 
xref:../../guides/rgant/rgant.adoc#_rgant-Title[`@Title`] annotation
-** rather than the 
xref:../../guides/rgcms/rgcms.adoc#_rgcms_methods_reserved_title[`title()`] 
method
-* order the properties using the 
xref:../../guides/rgant/rgant.adoc#_rgant-MemberOrder[`@MemberOrder`], also 
`@MemberGroupLayout`
-** see also the docs on 
xref:../../guides/ugvw/ugvw.adoc#_ugvw_layout_annotation-based[static layouts]
-* use the 
xref:../../guides/rgant/rgant.adoc#_rgant-PropertyLayout[`@PropertyLayout`] 
annotation to position property/action parameter labels either to the LEFT, TOP 
or NONE
-** do the same for parameters using 
xref:../../guides/rgant/rgant.adoc#_rgant-ParameterLayout[`@ParameterLayout`]
-
-
-
-
-== Reference properties
-
-Domain entities can also reference other domain entities. These references may 
be either scalar (single-valued) or vector (multi-valued). In this section we 
focus on scalar reference properties.
-
-* add some 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_programming-model_properties[reference
 properties]
-* update the corresponding domain service (for creation actoin)
-* use different techniques to obtain references (shown in drop-down list box)
-** use the 
xref:../../guides/rgant/rgant.adoc#_rgant-DomainObject_bounded[`@DomainObjectLayout(bounded=...)`]
 annotation on the referenced type if there are only a small number (bounded) 
of instances
-** use a 
xref:../../guides/rgcms/rgcms.adoc#_rgcms_methods_prefixes_choices[`choices...()`]
 supporting method
-*** on a property
-*** on an action parameter
-** use a 
xref:../../guides/rgcms/rgcms.adoc#_rgcms_methods_prefixes_autoComplete[`autoComplete...()`]
 supporting method
-*** on a property
-*** on an action parameter
-
-
-
-
-== Usability: Defaults
-
-Quick detour: often we want to set up defaults to go with choices. Sensible 
defaults for action parameters can really improve the usability of the app.
-
-* Add 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_drop-downs-and-defaults[defaults] for 
action parameters
-
-
-
-
-== Collections
-
-Returning back to references, Isis also supports vector (multi-valued) 
references to another object instances in other words collections. We sometimes 
called these "parented" collections (to distinguish from a "standalone" 
collection as returned from an action)
-
-* Ensure that all domain classes implement `java.lang.Comparable`
-** use the 
xref:../../guides/rgcms/rgcms.adoc#_rgcms_classes_utility_ObjectContracts[`ObjectContracts`]
 utility class to help implement `Comparable`
-*** you can also implement `equals()`, `hashCode()`, `toString()`
-* Add a 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_programming-model_collections[collection]
 to one of the entities
-** Use `SortedSet` as the class
-** Use the 
xref:../../guides/rgant/rgant.adoc#_rgant-CollectionLayout_render[`@CollectionLayout(render=...)`]
 annotation to indicate if the collection should be visible or hidden by default
-* optional: use the 
xref:../../guides/rgant/rgant.adoc#_rgant-CollectionLayout_sortedBy[`@CollectionLayout(sortedBy=...)`]
 annotation to specify a different comparator than the natural ordering
-
-
-
-
-
-== Actions and Collections
-
-The Wicket UI doesn't allow collections to be modified (added to/removed 
from). However, we can easily write actions to accomplish the same. Moreover, 
these actions can provide some additional business logic. For example: it 
probably shouldn't be possible to add an object twice into a collection, so it 
should not be presented in the list of choices/autoComplete; conversely, only 
those objects in the collection should be offered as choices to be removed.
-
-* Add domain actions to add/remove from the collection
-* to create objects, 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_programming-model_inject-services[inject]
 associated domain service
-** generally we recommend using the 
xref:../../guides/rgant/rgant.adoc#_rgant-Inject[`@Inject`] annotation with 
either private or default visibility
-* the service itself should use 
xref:../../guides/rgsvc/rgsvc.adoc#_rgsvc_core-domain-api_DomainObjectContainer[`DomainObjectContainer`]
-* use the 
xref:../../guides/rgant/rgant.adoc#_rgant-MemberOrder[`@MemberOrder(name=...)`] 
annotation to associate an action with a property or with a collection
-
-
-
-
-== CSS UI Hints
-
-CSS classes can be associated with any class member (property, collection, 
action). But for actions in particular:
-
-* the bootstrap "btn" CSS classes can be used using the 
xref:../../guides/rgant/rgant.adoc#_rgant-ActionLayout_cssClass[`@ActionLayout(cssClass=...)`]
 annotation
-
-*  the http://fortawesome.github.io/Font-Awesome/icons/[Font Awesome] icons 
can be used using the 
xref:../../guides/rgant/rgant.adoc#_rgant-ActionLayout_cssClassFa[`@ActionLayout(cssClassFa=...)`]
-
-It's also possible to use Font Awesome icons for the 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_ui-hints_object-titles-and-icons[domain
 object icon].
-
-So:
-- for some of the actions of your domain services or entities, annotate using 
`@ActionLayout(cssClass=...)` or `@ActionLayout(cssClassFa=...)`
-
-
-
-
-== File-based Layout
-
-Up to this point we've been using annotations (`@MemberOrder`, 
`@MemberGroupLayout`, `@Named`, `@PropertyLayout`, `@ParameterLayout`, 
`@ActionLayout` and so on) for UI hints. However, the feedback loop is not 
good: it requires us stopping the app, editing the code, recompiling and 
running again.
-So instead, all these UI hints (and more) can be specified dynamically, using 
a corresponding `.layout.xml` file. If edited while the app is running, it will 
be reloaded automatically (in IntelliJ, use Run&gt;Reload Changed Classes):
-
-* Delete the various hint annotations and instead specify layout hints using a 
 xref:../../guides/ugvw/ugvw.adoc#_ugvw_layout_file-based[.layout.xml] file.
-
-
-
-
-== Business rules
-
-Apache Isis excels for domains where there are complex business rules to 
enforce. The UI tries not to constrain the user from navigating around freely, 
however the domain objects nevertheless ensure that they cannot change into an 
invalid state. Such rules can be enforced either declaratively (using 
annotations) or imperatively (using code). The objects can do this in one of 
three ways:
-
-* visibility: preventing the user from even seeing a property/collection/action
-* usability: allowing the user to view a property/collection/action but not 
allowing the user to change it
-* validity: allowing the user to modify the property/invoke the action, but 
validating that the new value/action arguments are correct before hand.
-
-Or, more pithily: "see it, use it, do it"
-
-
-=== See it!
-
-* Use the 
xref:../../guides/rgant/rgant.adoc#_rgant-Property_hidden[`Property(hidden=...)`]
 annotation to make properties invisible
-** likewise 
xref:../../guides/rgant/rgant.adoc#_rgant-Collection_hidden[`@Collection(hidden=...)`]
 for collections
-** the xref:../../guides/rgant/rgant.adoc#_rgant-Programmatic[`@Programmatic`] 
 annotation can also be used and in many cases is to be preferred; the 
difference is that the latter means the member is not part of the Apache Isis 
metamodel.
-* Use the 
xref:../../guides/rgcms/rgcms.adoc#_rgcms_methods_prefixes_hide[`hide...()`] 
supporting method on properties, collections and actions to make a 
property/collection/action invisible according to some imperative rule
-
-
-=== Use it!
-
-* Use the 
xref:../../guides/rgant/rgant.adoc#_rgant-Property_editing[`Property(editing=...)`]
 annotation to make property read-only
-** likewise 
xref:../../guides/rgant/rgant.adoc#_rgant-Collection_editing[`@Collection(editing=...)`]
 for collections
-** alternatively, use 
xref:../../guides/rgant/rgant.adoc#_rgant-DomainObject_editing[`@DomainObject(editing=...)`]
 to disable editing for all properties/collections
-* Use the 
xref:../../guides/rgcms/rgcms.adoc#_rgcms_methods_prefixes_disable[`disable...()`]
 supporting method on properties and actions to make a property/action disabled 
according to some imperative rule
-
-
-=== Do it!
-
-* use the 
xref:../../guides/rgant/rgant.adoc#_rgant-Property_regexPattern[`@Property(regexPattern=...)`]
 annotation to specify a regex pattern for properties, and use 
xref:../../guides/rgant/rgant.adoc#_rgant-Parameter_regexPattern[`@Parameter(regexPattern=...)`]
 for parameters
-* use the 
xref:../../guides/rgant/rgant.adoc#_rgant-Property_maxLength[`@Property(maxLength=...)`]
 annotation to indicate a maxmum number of characters, and 
xref:../../guides/rgant/rgant.adoc#_rgant-Parameter_maxLength[`@Parameter(maxLength=...)`]
 for parameters
-* Use the 
xref:../../guides/rgcms/rgcms.adoc#_rgcms_methods_prefixes_validate[`validate...()`]
 supporting method on properties or action parameter
-* optional: for any data type:
-** use the 
xref:../../guides/rgant/rgant.adoc#_rgant-Property_mustSatisfy[`Property(mustSatisfy=...)`]
 and 
xref:../../guides/rgant/rgant.adoc#_rgant-Parameter_mustSatisfy[`Parameter(mustSatisfy=...)`]
 annotations to specify arbitrary constraints on properties and parameters
-
-
-
-
-== Home page
-
-The Wicket UI will automatically invoke the "home page" action, if available. 
This is a no-arg action of one of the domain services, that can return either 
an object (eg representing the current user) or a standalone action.
-
-* Add the xref:../../guides/rgant/rgant.adoc#_rgant-HomePage[`@HomePage`] 
annotation to one (no more) of the domain services' no-arg actions
-
-
-
-
-== Clock Service
-
-To ensure testability, there should be no dependencies on system time, for 
example usage of `LocalDate.now()`. Instead the domain objects should delegate 
to the provided `ClockService`.
-
-* remove any dependencies on system time (eg defaults for date/time action 
parameters)
-* inject 
xref:../../guides/rgsvc/rgsvc.adoc#_rgsvc_core-domain-api_ClockService[`ClockService`]
-* call `ClockService.now()` etc where required.
-
-
-
-
-== Using Contributions
-
-One of Apache Isis' most powerful features is the ability for the UI to 
combine functionality from domain services into the representation of an 
entity. The effect is similar to traits or mix-ins in other languages, however 
the "mixing in" is done at runtime, within the Apache Isis metamodel. In Apache 
Isis' terminology, we say that the domain service action is contributed to the 
entity.
-
-Any action of a domain service that has a domain entity type as one of its 
parameter types will (by default) be contributed. If the service action takes 
more than one argument, or does not have safe semantics, then it will be 
contributed as an entity action. If the service action has precisely one 
parameter type (that of the entity) and has safe semantics then it will be 
contributed either as a collection or as a property (dependent on whether it 
returns a collection of a scalar).
-
-Why are contributions so useful? Because the service action will match not on 
the entity type, but also on any of the entity's supertypes (all the way up to 
`java.lang.Object`). That means that you can apply the 
http://en.wikipedia.org/wiki/Dependency_inversion_principle[dependency 
inversion principle] to ensure that the modules of your application have 
acyclic dependencies; but in the UI it can still appear as if there are 
bidirectional dependencies between those modules. The lack of bi [...]
-
-Finally, note that the layout of contributed actions/collections/properties 
can be specified using the `.layout.json` file (and it is highly recommended 
that you do so).
-
-=== Contributed Actions
-
-* Write a new domain service
-** by convention, called "XxxContributions"
-** annotate with 
xref:../../guides/rgant/rgant.adoc#_rgant-DomainService_nature[`@DomainService(nature=NatureOfService.VIEW_CONTRIBUTIONS_ONLY)`]
-*** indicates that all of the service's actions should _not_ be included in 
the main application menu bar
-*** should be rendered "as if" an action of the entity
-* Write an action accepting &gt;1 args:
-** one being a domain entity
-** other being a primitive or String
-
-=== Contributed Collections
-
-* Write a new domain service (or update the one previously)
-* Write a query-only action accepting exactly 1 arg (a domain entity)
-* returning a collection, list or set
-* For this action:
-** add the 
xref:../../guides/rgant/rgant.adoc#_rgant-ActionLayout_contributedAs[`@ActionLayout(contributedAs=ASSOCIATION)`]
 annotation
-** should be rendered in the UI "as if" a collection of the entity
-* use `.layout.json` to position as required
-
-
-=== Contributed Properties
-
-* As for contributed collections, write a new domain service with a query-only 
action accepting exactly 1 arg (a domain entity); except:
-** returning a scalar value rather than a collection
-* For this action:
-** add the 
xref:../../guides/rgant/rgant.adoc#_rgant-ActionLayout_contributedAs[`@ActionLayout(contributedAs=ASSOCIATION)`]
 annotation
-* should be rendered in the UI "as if" a property of the entity
-* use `.layout.json` to position as required
-
-
-
-== Using the Event Bus
-
-Another way in which Apache Isis helps you keep your application nicely 
modularized is through its event bus. Each action invocation, or property 
modification, can be used to generate a succession of events that allows 
subscribers to veto the interaction (the see it/use it/do it rules) or, if the 
action is allowed, to perform work prior to the execution of the action or 
after the execution of the action.
-
-Under the covers Apache Isis uses the 
https://code.google.com/p/guava-libraries/wiki/EventBusExplained[Guava event 
bus] and subscribers (always domain services) subscribe by writing methods 
annotated with `@com.google.common.eventbus.Subscribe` annotation.
-
-By default the events generated are `ActionDomainEvent.Default` (for actions) 
and `PropertyDomainEvent.Default` (for properties). Subclasses of these can be 
specified using the 
xref:../../guides/rgant/rgant.adoc#_rgant-Action_domainEvent[`@Action(domainEvent=...)`]
 or 
xref:../../guides/rgant/rgant.adoc#_rgant-Property_domainEvent[`Property(domainEvent=...)`]
 for properties.
-
-
-Using the guidance in the docs for the 
xref:../../guides/rgsvc/rgsvc.adoc#_rgsvc_core-domain-api_EventBusService[`EventBusService`]:
-
-* write a domain service subscriber to subscribe to events
-* use the domain service to perform log events
-* use the domain service to veto actions (hide/disable or validate)
-
-
-
-== Bulk actions
-
-Bulk actions are actions that can be invoked on a collection of actions, that 
is on collections returned by invoking an action. Actions are specified as 
being bulk actions using the 
xref:../../guides/rgant/rgant.adoc#_rgant-Action_invokeOn[`@action(invokeOn=OBJECT_AND_COLLECTION)`]
 annotation.
-
-[NOTE]
-====
-Note that currently (1.8.0) only no-arg actions can be specified as bulk 
actions.
-====
-
-Thus:
-* Write a no-arg action for your domain entity, annotate with 
`@Action(invokeOn=...)`
-* Inject the 
xref:../../guides/rgsvc/rgsvc.adoc#_rgsvc_application-layer-api_ActionInvocationContext[`ActionInteractionContext`]
 (request-scoped) service
-* Use the `ActionInteractionContext` service to determine whether the action 
was invoked in bulk or as a regular action.
-* return null if invoked on a collection; the Wicket viewer will go back to 
the original collection
-** (if return non-null, then Wicket viewer will navigate to the object of the 
last invocation generally not what is required)
-
-The similar 
xref:../../guides/rgsvc/rgsvc.adoc#_rgsvc_core-domain-api_Scratchpad[`Scratchpad`]
 (request-scoped) domain service is a good way to share information between 
bulk action invocations:
-
-* Inject the `Scratchpad` domain service
-* for each action, store state (eg a running total)
-* in the last invoked bulk action, perform some aggregate processing (eg 
calculate the average) and return
-
-
-
-
-== Performance tuning
-
-The 
xref:../../guides/rgsvc/rgsvc.adoc#_rgsvc_persistence-layer-api_QueryResultsCache[`QueryResultsCache`]
 (request-scoped) domain service allows arbitrary objects to be cached for the 
duration of a request.
-
-This can be helpful for "naive" code which would normally make the same query 
within a loop.
-
-* optional: inject the `QueryResultsCache` service, invoke queries "through" 
the cache API
-* remember that the service is request-scoped, so it only really makes sense 
to use this service for code that invokes queries within a loop
-
-
-
-
-== Extending the Wicket UI
-
-Each element in the Wicket viewer (entity form, properties, collections, 
action button etc) is a component, each created by a internal API 
(`ComponentFactory`, described 
xref:../../guides/ugvw/ugvw.adoc#_ugvw_extending[here]).
-For collections there can be multiple views, and the Wicket viewer provides a 
view selector drop down (top right of each collection panel).
-
-Moreover, we can add additional views. In this section we'll explore some of 
these, already provided through the (non-ASF) 
link:http://platform.incode.org[Incode Platform^].
-
-
-=== Excel download
-
-The Incode Platform's Excel Wicket component allows the collection to be 
downloaded as an Excel spreadsheet (`.xlsx`).
-
-* Use the instructions on the add-on module's README to add in the excel 
download module (ie: update the POM).
-
-=== Fullcalendar2
-
-The Incode Platform's Fullcalendar2 Wicket component allows entities to be 
rendered in a full-page calendar.
-
-* Use the instructions on the add-on module's README to add in the 
fullcalendar2 module (ie: update the POM).
-* on one of your entities, implement either the `CalendarEventable` interface 
or the (more complex) `Calendarable` interface.
-* update fixture scripts to populate any new properties
-* when the app is run, a collection of the entities should be shown within a 
calendar view
-
-=== gmap3
-
-The Incode Platform's Gmap3 Wicket componet allows entities that implement 
certain APIs to be rendered in a full-page gmap3.
-
-* Use the instructions on the add-on module's README to add in the gmap3 
module (ie: update the POM).
-* on one of your entities, implement the `Locatable` interface
-* update fixture scripts to populate any new properties
-* when the app is run, a collection of the entities should be shown within a 
map view
-
-
-
-
-== Add-on modules (optional)
-
-In addition to providing Wicket viewer extensions, the (non-ASF) 
link:http://platform.incode.org[Incode Platform^] also has a large number of 
other modules.
-These address such cross-cutting concerns as security, command (profiling), 
auditing and publishing.
-
-* (optional): follow the security module README.
- There is also a http://youtu.be/bj8735nBRR4[screencast] that refers to the 
Incode Platform's predecessor, the isisaddons.org website.
-* (optional): follow the command module README.
-There is also a http://youtu.be/g01tK58MxJ8[screencast] that refers to the 
Incode Platform's predecessor, the isisaddons.org website.
-* (optional): follow the auditing module README.
-Or, see (the same) http://youtu.be/g01tK58MxJ8[screencast].
-
-
-
-
-== View models
-
-In most cases users can accomplish the business operations they need by 
invoking actions directly on domain entities. For some high-volume or 
specialized uses cases, though, there may be a requirement to bring together 
data or functionality that spans several entities.
-
-Also, if using Apache Isis' REST API then the REST client may be a native 
application (on a smartphone or tablet, say) that is deployed by a third party. 
In these cases exposing the entities directly would be inadvisable because a 
refactoring of the domain entity would change the REST API and probably break 
that REST client.
-
-To support these use cases, Apache Isis therefore allows you to write a view 
model, either by annotating the class with 
xref:../../guides/rgant/rgant.adoc#_rgant-ViewModel[`@ViewModel`] or (for more 
control) by implementing the 
xref:../../guides/rgcms/rgcms.adoc#_rgcms_classes_super_AbstractViewModel[`ViewModel`]
 interface.
-
-* build a view model summarizing the state of the app (a "dashboard")
-* write a new `@HomePage` domain service action returning this dashboard 
viewmodel (and remove the `@HomePage` annotation from any other domain service 
if present)
-
-
-
-
-== Testing
-
-Up to this point we've been introducing the features of Isis and building out 
our domain application, but with little regard to testing. Time to fix that.
-
-
-=== Unit testing
-
-Unit testing domain entities and domain services is easy; just use JUnit and 
mocking libraries to mock out interactions with domain services.
-
-https://code.google.com/p/mockito/[Mockito] seems to be the current favourite 
among Java developers for mocking libraries, but if you use JMock then you'll 
find we provide a `JUnitRuleMockery2` class and a number of other utility 
classes, documented 
xref:../../guides/ugtst/ugtst.adoc#_ugtst_unit-test-support[here].
-
-* write some unit tests (adapt from the unit tests in the `myapp-dom` Maven 
module).
-
-
-
-=== Integration testing
-
-Although unit tests are easy to write and fast to execute, integration tests 
are more valuable: they test interactions of the system from the outside-in, 
simulating the way in which the end-users use the application.
-
-Earlier on in the tutorial we commented out the `myapp-integtests` module. 
Let's commented it back in. In the parent `pom.xml`:
-
-[source,xml]
-----
-<modules>
-    <module>dom</module>
-    <module>fixture</module>
-    <!--
-    <module>integtests</module>
-    -->
-    <module>webapp</module>
-</modules>
-----
-
-change back to:
-
-[source,xml]
-----
-<modules>
-    <module>dom</module>
-    <module>fixture</module>
-    <module>integtests</module>
-    <module>webapp</module>
-</modules>
-----
-
-There will probably be some compile issues to fix up once you've done this; 
comment out all code that doesn't compile.
-
-Isis has great support for writing 
xref:../../guides/ugtst/ugtst.adoc#_ugtst_integ-test-support[integration 
tests]; well-written integration tests should leverage fixture scripts and use 
the 
xref:../../guides/rgsvc/rgsvc.adoc#_rgsvc_application-layer-api_WrapperFactory[`@WrapperFactory`]
 domain service.
-
-* use the tests from the original archetype and the documentation on the 
website to develop integration tests for your app's functionality.
-
-
-
-
-== Customising the REST API
-
-The REST API generated by Apache Isis conforms to the Restful Objects 
specification. Apache Isis 1.8.0 provides experimental support to allow the 
representations to be customized.
-
-* as per 
xref:../../guides/ugvro/ugvro.adoc#__ugvro_simplified-representations_configuration-properties[the
 documentation], configure the Restful Objects viewer to generate a simplified 
object representation: +
-+
-[source,ini]
-----
-isis.viewer.restfulobjects.objectPropertyValuesOnly=true
-----
-
-
-
-
-== Configuring to use an external database
-
-If you have an external database available, then update the `pom.xml` for the 
classpath and update the JDBC properties in `WEB-INF\persistor.properties` to 
point to your database.
\ No newline at end of file
diff --git 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/010-01-login-page.png
 
b/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/010-01-login-page.png
deleted file mode 100644
index 068c3a8..0000000
Binary files 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/010-01-login-page.png
 and /dev/null differ
diff --git 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/010-02-home-page.png
 
b/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/010-02-home-page.png
deleted file mode 100644
index 59c2726..0000000
Binary files 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/010-02-home-page.png
 and /dev/null differ
diff --git 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/010-03-prototyping-menu.png
 
b/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/010-03-prototyping-menu.png
deleted file mode 100644
index ed85463..0000000
Binary files 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/010-03-prototyping-menu.png
 and /dev/null differ
diff --git 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/010-04-simpleobjects.png
 
b/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/010-04-simpleobjects.png
deleted file mode 100644
index 324083d..0000000
Binary files 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/010-04-simpleobjects.png
 and /dev/null differ
diff --git 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/010-05-simpleobject-list.png
 
b/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/010-05-simpleobject-list.png
deleted file mode 100644
index 79bfffa..0000000
Binary files 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/010-05-simpleobject-list.png
 and /dev/null differ
diff --git 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/020-01-idea-configuration.png
 
b/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/020-01-idea-configuration.png
deleted file mode 100644
index 1ee8280..0000000
Binary files 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/020-01-idea-configuration.png
 and /dev/null differ
diff --git 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/020-02-idea-configuration.png
 
b/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/020-02-idea-configuration.png
deleted file mode 100644
index 99be18b..0000000
Binary files 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/020-02-idea-configuration.png
 and /dev/null differ
diff --git 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/030-01-idea-configuration-updated.png
 
b/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/030-01-idea-configuration-updated.png
deleted file mode 100644
index c836f14..0000000
Binary files 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/030-01-idea-configuration-updated.png
 and /dev/null differ
diff --git 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/030-02-updated-app.png
 
b/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/030-02-updated-app.png
deleted file mode 100644
index c438315..0000000
Binary files 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/030-02-updated-app.png
 and /dev/null differ
diff --git 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/040-01-idea-configuration-updated.png
 
b/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/040-01-idea-configuration-updated.png
deleted file mode 100644
index acddc93..0000000
Binary files 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/040-01-idea-configuration-updated.png
 and /dev/null differ
diff --git 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/050-01-list-all.png
 
b/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/050-01-list-all.png
deleted file mode 100644
index 1c87cca..0000000
Binary files 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/050-01-list-all.png
 and /dev/null differ
diff --git 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/050-02-view-pet.png
 
b/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/050-02-view-pet.png
deleted file mode 100644
index 77824ce..0000000
Binary files 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/050-02-view-pet.png
 and /dev/null differ
diff --git 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/060-01-owners-menu.png
 
b/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/060-01-owners-menu.png
deleted file mode 100644
index 642f9dc..0000000
Binary files 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/060-01-owners-menu.png
 and /dev/null differ
diff --git 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/060-02-owners-list.png
 
b/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/060-02-owners-list.png
deleted file mode 100644
index db0ec25..0000000
Binary files 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/060-02-owners-list.png
 and /dev/null differ
diff --git 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/060-03-pets-list.png
 
b/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/060-03-pets-list.png
deleted file mode 100644
index f2b9230..0000000
Binary files 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/060-03-pets-list.png
 and /dev/null differ
diff --git 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/060-04-pet-owner-autoComplete.png
 
b/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/060-04-pet-owner-autoComplete.png
deleted file mode 100644
index d301b59..0000000
Binary files 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/060-04-pet-owner-autoComplete.png
 and /dev/null differ
diff --git 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/domain-model.png
 
b/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/domain-model.png
deleted file mode 100644
index 268e998..0000000
Binary files 
a/adocs/documentation/src/main/asciidoc/pages/tg/images/tutorials/pet-clinic/domain-model.png
 and /dev/null differ
diff --git a/adocs/documentation/src/main/asciidoc/pages/tg/tg.adoc 
b/adocs/documentation/src/main/asciidoc/pages/tg/tg.adoc
index f0265c7..f5cdefb 100644
--- a/adocs/documentation/src/main/asciidoc/pages/tg/tg.adoc
+++ b/adocs/documentation/src/main/asciidoc/pages/tg/tg.adoc
@@ -1,26 +1,687 @@
 [[tg]]
-= Tutorials
+= Tutorial
 :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 [...]
 :_basedir: ../../
 :_imagesdir: images/
 :numbered:
 
 
-[[__tg]]
-== Tutorials
+This is a half-day tutorial on developing domain-driven apps using Apache Isis.
 
-This page contains a couple of tutorials for you to follow.
+Actually, you could probably spend a full day working through this tutorial if 
you wanted to, so pick and choose the bits that look interesting.
+The tutorial was originally written by Dan Haywood, for a conference workshop.
 
-* the xref:tg.adoc#_tg_tutorials_pet-clinic["petclinic"] tutorial takes you 
step-by-step through building a simple application of just three classes.  
There are example solutions in the github repo in case you get lost.
 
-* an xref:tg.adoc#_tg_tutorials_pet-clinic-extended[extended version] of the 
"petclinic" tutorial, (with the text hosted on github repo).
 
-* the xref:tg.adoc#_tg_tutorials_stop-scaffolding-start-coding["stop 
scaffolding, start coding"] tutorial is taken from a conference workshop.  It 
has less hand-holding, but lists out the steps for you to follow.  It's a good 
cookbook to follow when you're readng to take things further.
 
-Have fun!
+== Prerequisites
 
+You'll need:
 
+* Java 7 JDK
+* http://maven.apache.org/[Maven] 3.2.x
+* an IDE, such as http://www.eclipse.org/[Eclipse] or 
https://www.jetbrains.com/idea/[IntelliJ IDEA].
 
-include::_tg_pet-clinic.adoc[leveloffset=+1]
-include::_tg_pet-clinic-extended.adoc[leveloffset=+1]
-include::_tg_stop-scaffolding-start-coding.adoc[leveloffset=+1]
+
+
+== Run the archetype
+
+Run the simpleapp archetype to build an empty Isis application.
+With the *nix bash shell, use:
+
+
+[source,bash]
+----
+mvn archetype:generate  \
+    -D archetypeGroupId=org.apache.isis.archetype \
+    -D archetypeArtifactId=simpleapp-archetype \
+    -D archetypeVersion=1.16.0 \
+    -D groupId=com.mycompany \
+    -D artifactId=myapp \
+    -D version=1.0-SNAPSHOT \
+    -D 
archetypeRepository=http://repository-estatio.forge.cloudbees.com/snapshot/ \
+    -B
+----
+
+Adjust as necessary if using Windows `cmd.exe` or Powershell.
+
+
+
+== Build and run
+
+Start off by building the app from the command line:
+
+[source,bash]
+----
+cd myapp
+mvn clean install -D mavenmixin-jettyconsole
+----
+
+Once that's built then run using:
+
+[source,bash]
+----
+mvn -pl webapp antrun:run -D mavenmixin-jettyconsole
+----
+
+A splash screen should appear offering to start up the app. Go ahead and 
start; the web browser should be opened at 
http://localhost:8080[http://localhost:8080]
+
+Alternatively, you can run using the mvn-jetty-plugin:
+
+[source,bash]
+----
+mvn -pl webapp jetty:run
+----
+
+This will accomplish the same thing, though the webapp is mounted at a 
slightly different URL
+
+
+
+
+== Using the app
+
+Navigate to the Wicket UI (eg 
link:http://localhost:8080/wicket[http://localhost:8080/wicket]), and login 
(sven/pass).
+
+Once at the home page:
+
+* install fixtures
+* list all objects
+* create a new object
+* list all objects
+
+Go back to the splash screen, and quit the app. Note that the database runs 
in-memory (using HSQLDB) so any data created will be lost between runs.
+
+
+
+
+== Dev environment
+
+Set up xref:../../guides/dg/dg.adoc#_dg_ide[an IDE] and import the project to 
be able to run and debug the app.
+
+Then set up a launch configuration and check that you can:
+
+* Run the app from within the IDE
+* Run the app in debug mode
+* Run with different deploymentTypes; note whether prototype actions (those 
annotated 
xref:../../guides/rgant/rgant.adoc#_rgant-Action_restrictTo[`@Action(restrictTo=PROTOTYPING`])
 are available or not:
+* `--type SERVER_PROTOTYPE`
+* `--type SERVER`
+
+
+
+
+== Explore codebase
+
+Apache Isis applications are organized into several Maven modules. Within your 
IDE navigate to the various classes and correlate back to the generated UI.
+
+
+
+
+
+== Testing
+
+Testing is of course massively important, and Apache Isis makes both unit 
testing and (end-to-end) integration testing easy. Building the app from the 
Maven command line ("mvn clean install") will run all tests, but you should 
also run the tests from within the IDE.
+
+* `myapp-dom` unit tests
+* run
+* inspect, eg
+** `SimpleObjectTest`
+* `myapp-integtests` integration tests
+* run
+* inspect, eg:
+** `integration.tests.smoke.SimpleObjectsTest`
+** `integration.specs.simple.SimpleObjectSpec_listAllAndCreate.feature`
+* generated report, eg
+** `myapp/integtests/target/cucumber-html-report/index.html`
+** change test in IDE, re-run (in Maven)
+
+If you have issues with the integration tests, make sure that the domain 
classes have been enhanced by the DataNucleus enhancer. (The exact mechanics 
depends on the IDE being used).
+
+
+
+
+== Prototyping
+
+Although testing is important, in this tutorial we want to concentrate on how 
to write features and to iterate quickly. So for now, exclude the `integtests` 
module. Later on in the tutorial we'll add the tests back in so you can learn 
how to write automated tests for the features of your app.
+
+In the parent `pom.xml`:
+
+[source,xml]
+----
+<modules>
+    <module>dom</module>
+    <module>fixture</module>
+    <module>integtests</module>
+    <module>webapp</module>
+</modules>
+----
+
+change to:
+
+[source,xml]
+----
+<modules>
+    <module>dom</module>
+    <module>fixture</module>
+    <!--
+    <module>integtests</module>
+    -->
+    <module>webapp</module>
+</modules>
+----
+
+
+
+
+== Build a domain app
+
+The remainder of the tutorial provides guidance on building a domain 
application. We don't mandate any particular design, but we suggest one with no 
more than 3 to 6 domain entities in the first instance. If you're stuck for 
ideas, then how about:
+
+* a todo app (``ToDoItem``s)
+* a pet clinic (`Pet`, `Owner`, `PetSpecies`, `Visit`)
+* a library (`Book`, `Title`, `LibraryMember`, `Loan`, `Reservation`)
+* a holiday cottage rental system
+* a scrum/kanban system (inspired by Trello)
+* a meeting planner (inspired by Doodle)
+* (the domain model for) a CI server (inspired by Travis/Jenkins)
+* a shipping system (inspired by the example in the DDD "blue" book)
+* a system for ordering coffee (inspired by Restbucks, the example in "Rest in 
Practice" book)
+
+Hopefully one of those ideas appeals or sparks an idea for something of your 
own.
+
+
+
+
+== Domain entity
+
+Most domain objects in Apache Isis applications are persistent entities. In 
the simpleapp archetype the `SimpleObject` is an example. We can start 
developing our app by refactoring that class:
+
+* rename the `SimpleObject` class
+** eg rename to `Pet`
+* if required, rename the `SimpleObject` class' `name` property
+** for `Pet`, can leave `name` property as is
+* specify a 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_ui-hints_object-titles-and-icons[title]
+* specify an 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_ui-hints_object-titles-and-icons[icon]
+* make the entity bookmarkable by adding the 
xref:../../guides/rgant/rgant.adoc#_rgant-DomainObjectLayout_bookmarking[`@DomainObjectLayout#bookmarking()`]
 attribute.
+* confirm is available from bookmark panel (top-left of Wicket UI)
+
+
+
+
+== Domain service
+
+Domain services often act as factories or repositories to entities; more 
generally can be used to "bridge across" to other domains/bounded contexts. 
Most are application-scoped, but they can also be request-scoped if required.
+
+In the simpleapp archetype the `SimpleObjects` service is a factory/repository 
for the original `SimpleObject` entity. For our app it therefore makes sense to 
refactor that class into our own first service:
+
+* rename the `SimpleObjects` class
+** eg rename to `Pets`
+* review `create` action (acting as a factory)
+** as per the docs describing 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_crud[how to create or delete objects]
+* rename if you wish
+** eg `newPet(...)` or `addPet(...)`
+* review `listAll` action (acting as a repository)
+* as per the docs describing 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_crud[how to write a custom repository]
+* note the annotations on the corresponding domain class (originally called 
`SimpleObject`, though renamed by now, eg to `Pet`)
+* rename if you wish
+** eg `listPets()`
+* note the 
xref:../../guides/rgant/rgant.adoc#_rgant-DomainService[`@DomainService`] 
annotation
+* optional: add an action to a return subset of objects
+** use the JDO `@Query` annotation
+** see for example the Isisaddons example 
https://github.com/isisaddons/isis-app-todoapp[todoapp] (not ASF), see 
https://github.com/apache/isis/blob/b3e936c9aae28754fb46c2df52b1cb9b023f9ab8/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java#L93[here]
 and 
https://github.com/apache/isis/blob/b3e936c9aae28754fb46c2df52b1cb9b023f9ab8/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItems.java#L63[here]
+
+
+
+
+== Fixture scripts
+
+Fixture scripts are used to setup the app into a known state. They are great 
for demo's and as a time-saver when implementing a feature, and they can also 
be reused in automated integration tests. We usually also have a fixture script 
to zap all the (non-reference) data (or some logical subset of the data)
+
+* rename the `SimpleObjectsTearDownFixture` class
+* and update to delete from the appropriate underlying database table(s)
+* use the injected 
xref:../../guides/rgsvc/rgsvc.adoc#_rgsvc_persistence-layer-api_IsisJdoSupport[`IsisJdoSupport`]
 domain service.
+* refactor/rename the fixture script classes that create instances your entity:
+* `RecreateSimpleObjects`, which sets up a set of objects for a given scenario
+* `SimpleObjectCreate` which creates a single object
+* note that domain services can be injected into these fixture scripts
+
+
+
+
+== Actions
+
+Most business functionality is implemented using actions basically a `public` 
method accepting domain classes and primitives as its parameter types. The 
action can return a domain entity, or a collection of entities, or a 
primitive/String/value, or void. If a domain entity is returned then that 
object is rendered immediately; if a collection is returned then the Wicket 
viewer renders a table. Such collections are sometimes called "standalone" 
collections.
+
+* write an action to update the domain property (originally called 
`SimpleObject#name`, though renamed by now)
+* use the 
xref:../../guides/rgant/rgant.adoc#_rgant-ParameterLayout_named[`@ParameterLayout(named=...)`]
 annotation to specify the name of action parameters
+* use the 
xref:../../guides/rgant/rgant.adoc#_rgant-Action_semantics[`@Action(semanticsOf=...)`]
  annotation to indicate the semantics of the action (safe/query-only, 
idempotent or non-idempotent)
+* annotate safe action as bookmarkable using 
xref:../../guides/rgant/rgant.adoc#_rgant-ActionLayout_bookmarking[`@ActionLayout(bookmarking=...)`]
+* confirm is available from bookmark panel (top-left of Wicket UI)
+* optional: add an action to clone an object
+
+
+
+
+== REST API
+
+As well as exposing the Wicket viewer, Isis also exposes a REST API (an 
implementation of the http://restfulobjects.org[Restful Objects spec]). All of 
the functionality of the domain object model is available through this REST API.
+
+* add Chrome extensions
+* install 
https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en[Postman]
+* install 
https://chrome.google.com/webstore/detail/jsonview/chklaanhfefbnpoihckbnefhakgolnmc?hl=en[JSON-View]
+* browse to Wicket viewer, install fixtures
+* browse to the http://localhost:8080/restful[http://localhost:8080/restful] 
API
+* invoke the service to list all objects
+* services
+* actions
+* invoke (invoking 0-arg actions is easy; the Restful Objects spec defines how 
to invoke N-arg actions)
+
+
+
+
+== Specify Action semantics
+
+The semantics of an action (whether it is safe/query only, whether it is 
idempotent, whether it is neither) can be specified for each action; if not 
specified then Isis assumes non-idempotent. In the Wicket viewer this matters 
in that only query-only actions can be bookmarked or used as contributed 
properties/collections. In the RESTful viewer this matters in that it 
determines the HTTP verb (GET, PUT or POST) that is used to invoke the action.
+
+* experiment changing 
xref:../../guides/rgant/rgant.adoc#_rgant-Action_semantics[`@Action(semantics=...)`]
 on actions
+* note the HTTP methods exposed in the REST API change
+* note whether the non-safe actions are bookmarkable (assuming that it has 
been annotated with `@ActionLayout(bookmarking=...)`, that is).
+
+
+
+
+== Value properties
+
+Domain entities have state: either values (primitives, strings) or references 
to other entities. In this section we explore adding some value properties
+
+* add some 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_programming-model_properties[value 
properties]; also:
+* for string properties
+** use the 
xref:../../guides/rgant/rgant.adoc#_rgant-PropertyLayout_multiLine[`@PropertyLayout(multiLine=...)`]
 annotation to render a text area instead of a text box
+** use the 
xref:../../guides/rgant/rgant.adoc#_rgant-Property_maxLength[`@Property(maxLength=...)`]
 annotation to specify the maximum number of characters allowable
+** use joda date/time properties, bigdecimals and blob/clob properties
+* use the 
xref:../../guides/rgant/rgant.adoc#_rgant-Property_optionality[`@Column(allowsNull=...)`]
 annotation specify whether a property is optional or mandatory
+* use enums for properties (eg as used in the Isis addons example 
https://github.com/isisaddons/isis-app-todoapp[todoapp], see 
https://github.com/apache/isis/blob/b3e936c9aae28754fb46c2df52b1cb9b023f9ab8/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java#L207[here]
 and 
https://github.com/apache/isis/blob/b3e936c9aae28754fb46c2df52b1cb9b023f9ab8/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java#L266[here])
+* update the corresponding domain service for creating new instances
+* for all non-optional properties will either need to prompt for a value, or 
calculate some suitable default
+* change the implementation of title, if need be
+* revisit the title, consider whether to use the 
xref:../../guides/rgant/rgant.adoc#_rgant-Title[`@Title`] annotation
+** rather than the 
xref:../../guides/rgcms/rgcms.adoc#_rgcms_methods_reserved_title[`title()`] 
method
+* order the properties using the 
xref:../../guides/rgant/rgant.adoc#_rgant-MemberOrder[`@MemberOrder`], also 
`@MemberGroupLayout`
+** see also the docs on 
xref:../../guides/ugvw/ugvw.adoc#_ugvw_layout_annotation-based[static layouts]
+* use the 
xref:../../guides/rgant/rgant.adoc#_rgant-PropertyLayout[`@PropertyLayout`] 
annotation to position property/action parameter labels either to the LEFT, TOP 
or NONE
+** do the same for parameters using 
xref:../../guides/rgant/rgant.adoc#_rgant-ParameterLayout[`@ParameterLayout`]
+
+
+
+
+== Reference properties
+
+Domain entities can also reference other domain entities. These references may 
be either scalar (single-valued) or vector (multi-valued). In this section we 
focus on scalar reference properties.
+
+* add some 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_programming-model_properties[reference
 properties]
+* update the corresponding domain service (for creation actoin)
+* use different techniques to obtain references (shown in drop-down list box)
+** use the 
xref:../../guides/rgant/rgant.adoc#_rgant-DomainObject_bounded[`@DomainObjectLayout(bounded=...)`]
 annotation on the referenced type if there are only a small number (bounded) 
of instances
+** use a 
xref:../../guides/rgcms/rgcms.adoc#_rgcms_methods_prefixes_choices[`choices...()`]
 supporting method
+*** on a property
+*** on an action parameter
+** use a 
xref:../../guides/rgcms/rgcms.adoc#_rgcms_methods_prefixes_autoComplete[`autoComplete...()`]
 supporting method
+*** on a property
+*** on an action parameter
+
+
+
+
+== Usability: Defaults
+
+Quick detour: often we want to set up defaults to go with choices. Sensible 
defaults for action parameters can really improve the usability of the app.
+
+* Add 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_drop-downs-and-defaults[defaults] for 
action parameters
+
+
+
+
+== Collections
+
+Returning back to references, Isis also supports vector (multi-valued) 
references to another object instances in other words collections. We sometimes 
called these "parented" collections (to distinguish from a "standalone" 
collection as returned from an action)
+
+* Ensure that all domain classes implement `java.lang.Comparable`
+** use the 
xref:../../guides/rgcms/rgcms.adoc#_rgcms_classes_utility_ObjectContracts[`ObjectContracts`]
 utility class to help implement `Comparable`
+*** you can also implement `equals()`, `hashCode()`, `toString()`
+* Add a 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_programming-model_collections[collection]
 to one of the entities
+** Use `SortedSet` as the class
+** Use the 
xref:../../guides/rgant/rgant.adoc#_rgant-CollectionLayout_render[`@CollectionLayout(render=...)`]
 annotation to indicate if the collection should be visible or hidden by default
+* optional: use the 
xref:../../guides/rgant/rgant.adoc#_rgant-CollectionLayout_sortedBy[`@CollectionLayout(sortedBy=...)`]
 annotation to specify a different comparator than the natural ordering
+
+
+
+
+
+== Actions and Collections
+
+The Wicket UI doesn't allow collections to be modified (added to/removed 
from). However, we can easily write actions to accomplish the same. Moreover, 
these actions can provide some additional business logic. For example: it 
probably shouldn't be possible to add an object twice into a collection, so it 
should not be presented in the list of choices/autoComplete; conversely, only 
those objects in the collection should be offered as choices to be removed.
+
+* Add domain actions to add/remove from the collection
+* to create objects, 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_programming-model_inject-services[inject]
 associated domain service
+** generally we recommend using the 
xref:../../guides/rgant/rgant.adoc#_rgant-Inject[`@Inject`] annotation with 
either private or default visibility
+* the service itself should use 
xref:../../guides/rgsvc/rgsvc.adoc#_rgsvc_core-domain-api_DomainObjectContainer[`DomainObjectContainer`]
+* use the 
xref:../../guides/rgant/rgant.adoc#_rgant-MemberOrder[`@MemberOrder(name=...)`] 
annotation to associate an action with a property or with a collection
+
+
+
+
+== CSS UI Hints
+
+CSS classes can be associated with any class member (property, collection, 
action). But for actions in particular:
+
+* the bootstrap "btn" CSS classes can be used using the 
xref:../../guides/rgant/rgant.adoc#_rgant-ActionLayout_cssClass[`@ActionLayout(cssClass=...)`]
 annotation
+
+*  the http://fortawesome.github.io/Font-Awesome/icons/[Font Awesome] icons 
can be used using the 
xref:../../guides/rgant/rgant.adoc#_rgant-ActionLayout_cssClassFa[`@ActionLayout(cssClassFa=...)`]
+
+It's also possible to use Font Awesome icons for the 
xref:../../guides/ugfun/ugfun.adoc#_ugfun_ui-hints_object-titles-and-icons[domain
 object icon].
+
+So:
+- for some of the actions of your domain services or entities, annotate using 
`@ActionLayout(cssClass=...)` or `@ActionLayout(cssClassFa=...)`
+
+
+
+
+== File-based Layout
+
+Up to this point we've been using annotations (`@MemberOrder`, 
`@MemberGroupLayout`, `@Named`, `@PropertyLayout`, `@ParameterLayout`, 
`@ActionLayout` and so on) for UI hints. However, the feedback loop is not 
good: it requires us stopping the app, editing the code, recompiling and 
running again.
+So instead, all these UI hints (and more) can be specified dynamically, using 
a corresponding `.layout.xml` file. If edited while the app is running, it will 
be reloaded automatically (in IntelliJ, use Run&gt;Reload Changed Classes):
+
+* Delete the various hint annotations and instead specify layout hints using a 
 xref:../../guides/ugvw/ugvw.adoc#_ugvw_layout_file-based[.layout.xml] file.
+
+
+
+
+== Business rules
+
+Apache Isis excels for domains where there are complex business rules to 
enforce. The UI tries not to constrain the user from navigating around freely, 
however the domain objects nevertheless ensure that they cannot change into an 
invalid state. Such rules can be enforced either declaratively (using 
annotations) or imperatively (using code). The objects can do this in one of 
three ways:
+
+* visibility: preventing the user from even seeing a property/collection/action
+* usability: allowing the user to view a property/collection/action but not 
allowing the user to change it
+* validity: allowing the user to modify the property/invoke the action, but 
validating that the new value/action arguments are correct before hand.
+
+Or, more pithily: "see it, use it, do it"
+
+
+=== See it!
+
+* Use the 
xref:../../guides/rgant/rgant.adoc#_rgant-Property_hidden[`Property(hidden=...)`]
 annotation to make properties invisible
+** likewise 
xref:../../guides/rgant/rgant.adoc#_rgant-Collection_hidden[`@Collection(hidden=...)`]
 for collections
+** the xref:../../guides/rgant/rgant.adoc#_rgant-Programmatic[`@Programmatic`] 
 annotation can also be used and in many cases is to be preferred; the 
difference is that the latter means the member is not part of the Apache Isis 
metamodel.
+* Use the 
xref:../../guides/rgcms/rgcms.adoc#_rgcms_methods_prefixes_hide[`hide...()`] 
supporting method on properties, collections and actions to make a 
property/collection/action invisible according to some imperative rule
+
+
+=== Use it!
+
+* Use the 
xref:../../guides/rgant/rgant.adoc#_rgant-Property_editing[`Property(editing=...)`]
 annotation to make property read-only
+** likewise 
xref:../../guides/rgant/rgant.adoc#_rgant-Collection_editing[`@Collection(editing=...)`]
 for collections
+** alternatively, use 
xref:../../guides/rgant/rgant.adoc#_rgant-DomainObject_editing[`@DomainObject(editing=...)`]
 to disable editing for all properties/collections
+* Use the 
xref:../../guides/rgcms/rgcms.adoc#_rgcms_methods_prefixes_disable[`disable...()`]
 supporting method on properties and actions to make a property/action disabled 
according to some imperative rule
+
+
+=== Do it!
+
+* use the 
xref:../../guides/rgant/rgant.adoc#_rgant-Property_regexPattern[`@Property(regexPattern=...)`]
 annotation to specify a regex pattern for properties, and use 
xref:../../guides/rgant/rgant.adoc#_rgant-Parameter_regexPattern[`@Parameter(regexPattern=...)`]
 for parameters
+* use the 
xref:../../guides/rgant/rgant.adoc#_rgant-Property_maxLength[`@Property(maxLength=...)`]
 annotation to indicate a maxmum number of characters, and 
xref:../../guides/rgant/rgant.adoc#_rgant-Parameter_maxLength[`@Parameter(maxLength=...)`]
 for parameters
+* Use the 
xref:../../guides/rgcms/rgcms.adoc#_rgcms_methods_prefixes_validate[`validate...()`]
 supporting method on properties or action parameter
+* optional: for any data type:
+** use the 
xref:../../guides/rgant/rgant.adoc#_rgant-Property_mustSatisfy[`Property(mustSatisfy=...)`]
 and 
xref:../../guides/rgant/rgant.adoc#_rgant-Parameter_mustSatisfy[`Parameter(mustSatisfy=...)`]
 annotations to specify arbitrary constraints on properties and parameters
+
+
+
+
+== Home page
+
+The Wicket UI will automatically invoke the "home page" action, if available. 
This is a no-arg action of one of the domain services, that can return either 
an object (eg representing the current user) or a standalone action.
+
+* Add the xref:../../guides/rgant/rgant.adoc#_rgant-HomePage[`@HomePage`] 
annotation to one (no more) of the domain services' no-arg actions
+
+
+
+
+== Clock Service
+
+To ensure testability, there should be no dependencies on system time, for 
example usage of `LocalDate.now()`. Instead the domain objects should delegate 
to the provided `ClockService`.
+
+* remove any dependencies on system time (eg defaults for date/time action 
parameters)
+* inject 
xref:../../guides/rgsvc/rgsvc.adoc#_rgsvc_core-domain-api_ClockService[`ClockService`]
+* call `ClockService.now()` etc where required.
+
+
+
+
+== Using Contributions
+
+One of Apache Isis' most powerful features is the ability for the UI to 
combine functionality from domain services into the representation of an 
entity. The effect is similar to traits or mix-ins in other languages, however 
the "mixing in" is done at runtime, within the Apache Isis metamodel. In Apache 
Isis' terminology, we say that the domain service action is contributed to the 
entity.
+
+Any action of a domain service that has a domain entity type as one of its 
parameter types will (by default) be contributed. If the service action takes 
more than one argument, or does not have safe semantics, then it will be 
contributed as an entity action. If the service action has precisely one 
parameter type (that of the entity) and has safe semantics then it will be 
contributed either as a collection or as a property (dependent on whether it 
returns a collection of a scalar).
+
+Why are contributions so useful? Because the service action will match not on 
the entity type, but also on any of the entity's supertypes (all the way up to 
`java.lang.Object`). That means that you can apply the 
http://en.wikipedia.org/wiki/Dependency_inversion_principle[dependency 
inversion principle] to ensure that the modules of your application have 
acyclic dependencies; but in the UI it can still appear as if there are 
bidirectional dependencies between those modules. The lack of bi [...]
+
+Finally, note that the layout of contributed actions/collections/properties 
can be specified using the `.layout.json` file (and it is highly recommended 
that you do so).
+
+=== Contributed Actions
+
+* Write a new domain service
+** by convention, called "XxxContributions"
+** annotate with 
xref:../../guides/rgant/rgant.adoc#_rgant-DomainService_nature[`@DomainService(nature=NatureOfService.VIEW_CONTRIBUTIONS_ONLY)`]
+*** indicates that all of the service's actions should _not_ be included in 
the main application menu bar
+*** should be rendered "as if" an action of the entity
+* Write an action accepting &gt;1 args:
+** one being a domain entity
+** other being a primitive or String
+
+=== Contributed Collections
+
+* Write a new domain service (or update the one previously)
+* Write a query-only action accepting exactly 1 arg (a domain entity)
+* returning a collection, list or set
+* For this action:
+** add the 
xref:../../guides/rgant/rgant.adoc#_rgant-ActionLayout_contributedAs[`@ActionLayout(contributedAs=ASSOCIATION)`]
 annotation
+** should be rendered in the UI "as if" a collection of the entity
+* use `.layout.json` to position as required
+
+
+=== Contributed Properties
+
+* As for contributed collections, write a new domain service with a query-only 
action accepting exactly 1 arg (a domain entity); except:
+** returning a scalar value rather than a collection
+* For this action:
+** add the 
xref:../../guides/rgant/rgant.adoc#_rgant-ActionLayout_contributedAs[`@ActionLayout(contributedAs=ASSOCIATION)`]
 annotation
+* should be rendered in the UI "as if" a property of the entity
+* use `.layout.json` to position as required
+
+
+
+== Using the Event Bus
+
+Another way in which Apache Isis helps you keep your application nicely 
modularized is through its event bus. Each action invocation, or property 
modification, can be used to generate a succession of events that allows 
subscribers to veto the interaction (the see it/use it/do it rules) or, if the 
action is allowed, to perform work prior to the execution of the action or 
after the execution of the action.
+
+Under the covers Apache Isis uses the 
https://code.google.com/p/guava-libraries/wiki/EventBusExplained[Guava event 
bus] and subscribers (always domain services) subscribe by writing methods 
annotated with `@com.google.common.eventbus.Subscribe` annotation.
+
+By default the events generated are `ActionDomainEvent.Default` (for actions) 
and `PropertyDomainEvent.Default` (for properties). Subclasses of these can be 
specified using the 
xref:../../guides/rgant/rgant.adoc#_rgant-Action_domainEvent[`@Action(domainEvent=...)`]
 or 
xref:../../guides/rgant/rgant.adoc#_rgant-Property_domainEvent[`Property(domainEvent=...)`]
 for properties.
+
+
+Using the guidance in the docs for the 
xref:../../guides/rgsvc/rgsvc.adoc#_rgsvc_core-domain-api_EventBusService[`EventBusService`]:
+
+* write a domain service subscriber to subscribe to events
+* use the domain service to perform log events
+* use the domain service to veto actions (hide/disable or validate)
+
+
+
+== Bulk actions
+
+Bulk actions are actions that can be invoked on a collection of actions, that 
is on collections returned by invoking an action. Actions are specified as 
being bulk actions using the 
xref:../../guides/rgant/rgant.adoc#_rgant-Action_invokeOn[`@action(invokeOn=OBJECT_AND_COLLECTION)`]
 annotation.
+
+[NOTE]
+====
+Note that currently (1.8.0) only no-arg actions can be specified as bulk 
actions.
+====
+
+Thus:
+* Write a no-arg action for your domain entity, annotate with 
`@Action(invokeOn=...)`
+* Inject the 
xref:../../guides/rgsvc/rgsvc.adoc#_rgsvc_application-layer-api_ActionInvocationContext[`ActionInteractionContext`]
 (request-scoped) service
+* Use the `ActionInteractionContext` service to determine whether the action 
was invoked in bulk or as a regular action.
+* return null if invoked on a collection; the Wicket viewer will go back to 
the original collection
+** (if return non-null, then Wicket viewer will navigate to the object of the 
last invocation generally not what is required)
+
+The similar 
xref:../../guides/rgsvc/rgsvc.adoc#_rgsvc_core-domain-api_Scratchpad[`Scratchpad`]
 (request-scoped) domain service is a good way to share information between 
bulk action invocations:
+
+* Inject the `Scratchpad` domain service
+* for each action, store state (eg a running total)
+* in the last invoked bulk action, perform some aggregate processing (eg 
calculate the average) and return
+
+
+
+
+== Performance tuning
+
+The 
xref:../../guides/rgsvc/rgsvc.adoc#_rgsvc_persistence-layer-api_QueryResultsCache[`QueryResultsCache`]
 (request-scoped) domain service allows arbitrary objects to be cached for the 
duration of a request.
+
+This can be helpful for "naive" code which would normally make the same query 
within a loop.
+
+* optional: inject the `QueryResultsCache` service, invoke queries "through" 
the cache API
+* remember that the service is request-scoped, so it only really makes sense 
to use this service for code that invokes queries within a loop
+
+
+
+
+== Extending the Wicket UI
+
+Each element in the Wicket viewer (entity form, properties, collections, 
action button etc) is a component, each created by a internal API 
(`ComponentFactory`, described 
xref:../../guides/ugvw/ugvw.adoc#_ugvw_extending[here]).
+For collections there can be multiple views, and the Wicket viewer provides a 
view selector drop down (top right of each collection panel).
+
+Moreover, we can add additional views. In this section we'll explore some of 
these, already provided through the (non-ASF) 
link:http://platform.incode.org[Incode Platform^].
+
+
+=== Excel download
+
+The Incode Platform's Excel Wicket component allows the collection to be 
downloaded as an Excel spreadsheet (`.xlsx`).
+
+* Use the instructions on the add-on module's README to add in the excel 
download module (ie: update the POM).
+
+=== Fullcalendar2
+
+The Incode Platform's Fullcalendar2 Wicket component allows entities to be 
rendered in a full-page calendar.
+
+* Use the instructions on the add-on module's README to add in the 
fullcalendar2 module (ie: update the POM).
+* on one of your entities, implement either the `CalendarEventable` interface 
or the (more complex) `Calendarable` interface.
+* update fixture scripts to populate any new properties
+* when the app is run, a collection of the entities should be shown within a 
calendar view
+
+=== gmap3
+
+The Incode Platform's Gmap3 Wicket componet allows entities that implement 
certain APIs to be rendered in a full-page gmap3.
+
+* Use the instructions on the add-on module's README to add in the gmap3 
module (ie: update the POM).
+* on one of your entities, implement the `Locatable` interface
+* update fixture scripts to populate any new properties
+* when the app is run, a collection of the entities should be shown within a 
map view
+
+
+
+
+== Add-on modules (optional)
+
+In addition to providing Wicket viewer extensions, the (non-ASF) 
link:http://platform.incode.org[Incode Platform^] also has a large number of 
other modules.
+These address such cross-cutting concerns as security, command (profiling), 
auditing and publishing.
+
+* (optional): follow the security module README.
+ There is also a http://youtu.be/bj8735nBRR4[screencast] that refers to the 
Incode Platform's predecessor, the isisaddons.org website.
+* (optional): follow the command module README.
+There is also a http://youtu.be/g01tK58MxJ8[screencast] that refers to the 
Incode Platform's predecessor, the isisaddons.org website.
+* (optional): follow the auditing module README.
+Or, see (the same) http://youtu.be/g01tK58MxJ8[screencast].
+
+
+
+
+== View models
+
+In most cases users can accomplish the business operations they need by 
invoking actions directly on domain entities. For some high-volume or 
specialized uses cases, though, there may be a requirement to bring together 
data or functionality that spans several entities.
+
+Also, if using Apache Isis' REST API then the REST client may be a native 
application (on a smartphone or tablet, say) that is deployed by a third party. 
In these cases exposing the entities directly would be inadvisable because a 
refactoring of the domain entity would change the REST API and probably break 
that REST client.
+
+To support these use cases, Apache Isis therefore allows you to write a view 
model, either by annotating the class with 
xref:../../guides/rgant/rgant.adoc#_rgant-ViewModel[`@ViewModel`] or (for more 
control) by implementing the 
xref:../../guides/rgcms/rgcms.adoc#_rgcms_classes_super_AbstractViewModel[`ViewModel`]
 interface.
+
+* build a view model summarizing the state of the app (a "dashboard")
+* write a new `@HomePage` domain service action returning this dashboard 
viewmodel (and remove the `@HomePage` annotation from any other domain service 
if present)
+
+
+
+
+== Testing
+
+Up to this point we've been introducing the features of Isis and building out 
our domain application, but with little regard to testing. Time to fix that.
+
+
+=== Unit testing
+
+Unit testing domain entities and domain services is easy; just use JUnit and 
mocking libraries to mock out interactions with domain services.
+
+https://code.google.com/p/mockito/[Mockito] seems to be the current favourite 
among Java developers for mocking libraries, but if you use JMock then you'll 
find we provide a `JUnitRuleMockery2` class and a number of other utility 
classes, documented 
xref:../../guides/ugtst/ugtst.adoc#_ugtst_unit-test-support[here].
+
+* write some unit tests (adapt from the unit tests in the `myapp-dom` Maven 
module).
+
+
+
+=== Integration testing
+
+Although unit tests are easy to write and fast to execute, integration tests 
are more valuable: they test interactions of the system from the outside-in, 
simulating the way in which the end-users use the application.
+
+Earlier on in the tutorial we commented out the `myapp-integtests` module. 
Let's commented it back in. In the parent `pom.xml`:
+
+[source,xml]
+----
+<modules>
+    <module>dom</module>
+    <module>fixture</module>
+    <!--
+    <module>integtests</module>
+    -->
+    <module>webapp</module>
+</modules>
+----
+
+change back to:
+
+[source,xml]
+----
+<modules>
+    <module>dom</module>
+    <module>fixture</module>
+    <module>integtests</module>
+    <module>webapp</module>
+</modules>
+----
+
+There will probably be some compile issues to fix up once you've done this; 
comment out all code that doesn't compile.
+
+Isis has great support for writing 
xref:../../guides/ugtst/ugtst.adoc#_ugtst_integ-test-support[integration 
tests]; well-written integration tests should leverage fixture scripts and use 
the 
xref:../../guides/rgsvc/rgsvc.adoc#_rgsvc_application-layer-api_WrapperFactory[`@WrapperFactory`]
 domain service.
+
+* use the tests from the original archetype and the documentation on the 
website to develop integration tests for your app's functionality.
+
+
+
+
+== Customising the REST API
+
+The REST API generated by Apache Isis conforms to the Restful Objects 
specification. Apache Isis 1.8.0 provides experimental support to allow the 
representations to be customized.
+
+* as per 
xref:../../guides/ugvro/ugvro.adoc#__ugvro_simplified-representations_configuration-properties[the
 documentation], configure the Restful Objects viewer to generate a simplified 
object representation: +
++
+[source,ini]
+----
+isis.viewer.restfulobjects.objectPropertyValuesOnly=true
+----
+
+
+
+
+== Configuring to use an external database
+
+If you have an external database available, then update the `pom.xml` for the 
classpath and update the JDBC properties in `WEB-INF\persistor.properties` to 
point to your database.

-- 
To stop receiving notification emails like this one, please contact
danhayw...@apache.org.

Reply via email to