You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2015/12/22 23:40:33 UTC

[3/4] isis git commit: ISIS-1243: reworking the ugbtb (beyond the basics) guide a little, breaking out and renaming the techniques chapter

http://git-wip-us.apache.org/repos/asf/isis/blob/29452af6/adocs/documentation/src/main/asciidoc/guides/_ugbtb_decoupling_vetoing-visibility.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_decoupling_vetoing-visibility.adoc b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_decoupling_vetoing-visibility.adoc
new file mode 100644
index 0000000..d304c1b
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_decoupling_vetoing-visibility.adoc
@@ -0,0 +1,15 @@
+[[_ugbtb_decoupling_vetoing-visibility]]
+= Vetoing Visibility
+: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 agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+:_basedir: ../
+:_imagesdir: images/
+
+
+NOTE: TODO - a write-up of the "vetoing subscriber" design pattern, eg as described in the  xref:rgsvc.adoc#_rgsvc_api_BookmarkService[`BookmarkService`]
+
+
+eg if included an addon such as auditing or security.
+
+solution is to write a domain event subscriber that vetoes the visibility
+
+All the addons actions inherit from common base classes so this can be as broad-brush or fine-grained as required
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/29452af6/adocs/documentation/src/main/asciidoc/guides/_ugbtb_headless-access.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_headless-access.adoc b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_headless-access.adoc
new file mode 100644
index 0000000..7dcc5a8
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_headless-access.adoc
@@ -0,0 +1,27 @@
+[[_ugbtb_headless-access]]
+= Headless access
+: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 agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+:_basedir: ../
+:_imagesdir: images/
+
+This section tackles the topic of enabling access to an Isis application directly, or at least, not through either the xref:ugvw.adoc#[Wicket] or xref:ugvro.adoc#[Restful] viewers.
+
+There are several main use-cases:
+
+* enabling background execution, eg of a thread managed by Quartz scheduler and running within the webapp
+
+* integration from other systems, eg for a subscriber on a pub/sub mechanism such as Camel, pushing changes through an Apache Isis domain model.
+
+* leveraging an Isis application within a batch process
+
+Note that the calling thread runs in the same process space as the Apache Isis domain object model (must be physically linked to the JAR files containing the domain classes).  For use cases where the calling thread runs in some other process space (eg migrating data from a legacy system), then the xref:ugvro.adoc#[Restful Objects viewer] is usually the way to go.
+
+The API described in this chapter is reasonably low-level, allowing code to interact very directly with the Apache Isis metamodel and runtime.  Such callers should be considered trusted: they do not (by default) honour any business rules eg implicit in the Isis annotations or hide/disable/validate methods.  However the xref:rgsvc.adoc#_rgsvc_api_WrapperFactory[`WrapperFactory`] service could be used to enforce such business rules if required.
+
+
+
+include::_ugbtb_headless-access_AbstractIsisSessionTemplate.adoc[leveloffset=+1]
+include::_ugbtb_headless-access_BackgroundCommandExecution.adoc[leveloffset=+1]
+
+
+

http://git-wip-us.apache.org/repos/asf/isis/blob/29452af6/adocs/documentation/src/main/asciidoc/guides/_ugbtb_headless-access_AbstractIsisSessionTemplate.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_headless-access_AbstractIsisSessionTemplate.adoc b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_headless-access_AbstractIsisSessionTemplate.adoc
new file mode 100644
index 0000000..14e0e36
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_headless-access_AbstractIsisSessionTemplate.adoc
@@ -0,0 +1,40 @@
+[[_ugbtb_headless-access_AbstractIsisSessionTemplate]]
+= AbstractIsisSessionTemplate
+: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 agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+:_basedir: ../
+:_imagesdir: images/
+
+
+The `AbstractIsisSessionTemplate` class (whose name is inspired by the Spring framework's naming convention for similar classes that query http://docs.spring.io/spring/docs/2.5.x/reference/jdbc.html#jdbc-JdbcTemplate[JDBC], http://docs.spring.io/spring/docs/2.5.x/reference/jms.html#jms-jmstemplate[JMS], http://docs.spring.io/spring/docs/2.5.x/reference/orm.html#orm-jpa-template[JPA] etc.) provides the mechanism to open up a 'session' within the Apache Isis framework, in order to resolve and interact with entities.
+
+The class itself is intended to be subclassed:
+
+[source,java]
+----
+public abstract class AbstractIsisSessionTemplate {
+
+    public void execute(final AuthenticationSession authSession, final Object context) { ... } //<1>
+    protected abstract void doExecute(Object context); // <2>
+
+    protected ObjectAdapter adapterFor(final Object targetObject) { ... }
+    protected ObjectAdapter adapterFor(final RootOid rootOid) { ... }
+
+    protected PersistenceSession getPersistenceSession() { ... }
+    protected IsisTransactionManager getTransactionManager() { ... }
+    protected AdapterManager getAdapterManager() { ... }
+}
+----
+<1> `execute(...)` sets up the `IsisSession` and delegates to ...
+<2> `doExecute(...)`, the mandatory hook method for subclasses to implement.
+The passed object represents passes a context from the caller (eg the scheduler, cron job, JMS etc) that instantiated and executed the class.
+
+The `protected` methods expose key internal APIs within Apache Isis, for the subclass to use as necessary.
+
+
+[TIP]
+====
+One notable feature of `AbstractIsisSessionTemplate` is that it will automatically inject any domain services into itself. Thus, it is relatively easy for the subclass to "reach into" the domain, through injected repository services.
+====
+
+
+

http://git-wip-us.apache.org/repos/asf/isis/blob/29452af6/adocs/documentation/src/main/asciidoc/guides/_ugbtb_headless-access_BackgroundCommandExecution.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_headless-access_BackgroundCommandExecution.adoc b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_headless-access_BackgroundCommandExecution.adoc
new file mode 100644
index 0000000..570e1de
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_headless-access_BackgroundCommandExecution.adoc
@@ -0,0 +1,45 @@
+[[_ugbtb_headless-access_BackgroundCommandExecution]]
+= BackgroundCommandExecution
+: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 agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+:_basedir: ../
+:_imagesdir: images/
+
+
+
+The `BackgroundCommandExecution` class (a subclass of xref:ugbtb.adoc#_ugbtb_headless-access_AbstractIsisSessionTemplate[AbstractIsisSessionTemplate]) is intended to simplify the execution of background ``Command``s persisted by way of the xref:rgsvc.adoc#_rgsvc_spi_CommandService[`CommandService`] and the xref:rgsvc.adoc#_rgsvc_spi_BackgroundCommandService[`BackgroundCommandService`].
+
+Its signature is:
+
+[source,java]
+----
+public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemplate {
+    protected void doExecute(Object context) { ... }
+    protected abstract List<? extends Command> findBackgroundCommandsToExecute(); // <1>
+}
+----
+<1> `findBackgroundCommandsToExecute()` is a mandatory hook method for subclasses to implement.
+
+This allows for different implementations of the `CommandService` and `BackgroundCommandService` to persist to wherever.
+
+The diagram below (http://yuml.me/edit/363b335f[yuml.me/363b335f]) shows the dependencies between these various classes:
+
+.Inheritance Hierarchy for `BackgroundCommandExecution`
+image::{_imagesdir}headless-access/BackgroundCommandExecution.png[width="400px"]
+
+
+
+
+
+
+
+== Background Execution
+
+The `BackgroundCommandExecutionFromBackgroundCommandServiceJdo` is a concrete subclass of `BackgroundCommandExecution` (see the xref:rgsvc.adoc#_rgsvc_api_BackgroundService[`BackgroundCommandService`]), the intended use being for the class to be instantiated regularly (eg every 10 seconds) by a scheduler such as http://quartz-scheduler.org[Quartz]) to poll for ``Command``s to be executed, and then execute them.
+
+This implementation queries for ``Command``s persisted by the link:http://www.isisaddons.org/isis-module-command[Isis addons Command Module]'s  implementations of xref:rgsvc.adoc#_rgsvc_spi_CommandService[`CommandService`] and xref:rgsvc.adoc#_rgsvc_spi_BackgroundCommandService[`BackgroundCommandService`] using the `BackgroundCommandServiceJdoRepository`.
+
+The diagram below (link:http://yuml.me/edit/25343da1[yuml.me/25343da1]) shows the inheritance hierarchy for this class:
+
+.Inheritance Hierarchy for `BackgroundCommandExecutionFromBackgroundCommandServiceJdo`
+image::{_imagesdir}headless-access/BackgroundCommandExecutionFromBackgroundCommandServiceJdo.png[width="500px"]
+

http://git-wip-us.apache.org/repos/asf/isis/blob/29452af6/adocs/documentation/src/main/asciidoc/guides/_ugbtb_i18n.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_i18n.adoc b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_i18n.adoc
new file mode 100644
index 0000000..e63293c
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_i18n.adoc
@@ -0,0 +1,409 @@
+[[_ugbtb_i18n]]
+= i18n
+: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 agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+:_basedir: ../
+:_imagesdir: images/
+
+
+Apache Isis' support for i18n allows every element of the domain model (the class names, property names, action names, parameter names and so forth) to be translated.
+
+It also supports translations of messages raised imperatively, by which we mean as the result of a call to `title()` to obtain an object's title, or messages resulting from any business rule violations (eg xref:rgcms.adoc#_rgcms_methods_prefixes_disable[`disable...()`] or xref:rgcms.adoc#_rgcms_methods_prefixes_validate[`validate...()`], and so on.
+
+Isis does not translate the values of your domain objects, though.  So, if you have a domain concept such as `Country` whose name is intended to be localized according to the current user, you will need to model
+
+
+
+== Implementation Approach
+
+Most Java frameworks tackle i18n by using Java's own `ResourceBundle` API.  However, there are some serious drawbacks in this approach, such as:
+
+* if a string appears more than once (eg "name" or "description") then it must be translated everywhere it appears in every resource bundle file
+* there is no support for plural forms (see this link:http://stackoverflow.com/questions/14326653/java-internationalization-i18n-with-proper-plurals/14327683#14327683[SO answer])
+* there is no tooling support for translators
+
+Apache Isis therefore takes a different approach, drawing inspiration from GNU's https://www.gnu.org/software/gettext/manual/index.html[gettext] API and specifically its `.pot` and `.po` files.  These are intended to be used as follows:
+
+* the `.pot` (portable object template) file holds the message text to be translated
+* this file is translated into multiple `.po` (portable object) files, one per supported locale
+* these `.po` files are renamed according to their locale, and placed into the 'appropriate' location to be picked up by the runtime.  The name of each `.po` resolved in a very similar way to resource bundles.
+
+The format of the `.pot` and `.po` files is identical; the only difference is that the `.po` file has translations for each of the message strings.   These message strings can also have singular and plural forms.
+
+
+[IMPORTANT]
+====
+Although Apache Isis' implementation is modelled after GNU's API, it does _not_ use any GNU software.  This is for two reasons: (a) to simplify the toolchain/developer experience, and (b) because GNU software is usually GPL, which would be incompatible with the Apache license).
+====
+
+This design tackles all the issues of ``ResourceBundle``s:
+
+* the `.po` message format is such that any given message text to translate need only be translated once, even if it appears in multiple places in the application (eg "Name")
+* the `.po` message format includes translations for (optional) plural form as well as singular form
+* there are lots of freely available editors https://www.google.co.uk/search?q=.po+file+editor[to be found], many summarized on this https://www.drupal.org/node/11131[Drupal.org] webpage. +
++
+In fact, there are also online communities/platforms of translators to assist with translating files. One such is https://crowdin.com/[crowdin] (nb: this link does not imply endorsement).
+
+In Apache Isis' implementation, if the translation is missing from the `.po` file then the original message text from the `.pot` file will be returned.  In fact, it isn't even necessary for there to be any `.po` files; `.po` translations can be added piecemeal as the need arises.
+
+
+
+
+== `TranslationService`
+
+The cornerstone of Apache Isis' support for i18n is the `TranslationService` service. This is defined in the applib with the following API:
+
+[source,java]
+----
+public interface TranslationService {
+    public String translate(      // <1>
+            final String context,
+            final String text);
+    public String translate(      // <2>
+            final String context,
+            final String singularText,
+            final String pluralText,
+            final int num);
+    public enum Mode {
+        READ,
+        WRITE;
+    }
+    Mode getMode();               // <3>
+}
+----
+<1> is to translate the singular form of the text
+<2> is to translate the plural form of the text
+<3> indicates whether the translation service is in read or write mode.
+
+The `translate(...)` methods are closely modelled on GNU's gettext API.  The first version is used when no translation is required, the second is when both a singular and plural form will be required, with the `num` parameter being used to select which is returned.  In both cases the `context` parameter provides some contextual information for the translator; this generally corresponds to the class member.
+
+The mode meanwhile determines the behaviour of the service.  More on this below.
+
+
+
+=== `TranslationServicePo`
+
+Isis provides a default implementation of `TranslationService`, namely `TranslationServicePo`.
+
+If the service is running in the normal read mode, then it simply provides translations for the locale of the current user.  This means locates the appropriate `.po` file (based on the requesting user's locale), finds the translation and returns it.
+
+If however the service is configured to run in write mode, then it instead records the fact that the message was requested to be translated (a little like a spy/mock in unit testing mock), and returns the original message. The service can then be queried to discover which messages need to be translated.  All requested translations are written into the `.pot` file.
+
+To make the service as convenient as possible to use, the service configures itself as follows:
+
+* if running in prototype mode xref:rgcfg.adoc#_rgcfg_deployment-types[deployment type] or during integration tests, then the service runs in *write* mode, in which case it records all translations into the `.pot` file.  The `.pot` file is written out when the system is shutdown.
+* if running in server (production) mode xref:rgcfg.adoc#_rgcfg_deployment-types[deployment type], then the service runs in *read* mode. It is also possible to set a configuration setting in `isis.properties` to force read mode even if running in prototype mode (useful to manually test/demo the translations).
+
+When running in write mode the original text is returned to the caller untranslated. If in read mode, then the translated `.po` files are read and translations provided as required.
+
+
+
+
+
+== Imperative messages
+
+The `TranslationService` is used internally by Apache Isis when building up the metamodel; the name and description of every class, property, collection, action and action parameter is automatically translated.  Thus the simple act of bootstrapping Apache Isis will cause most of the messages requiring translation (that is: those for the Apache Isis metamodel) to be captured by the `TranslationService`.
+
+However, for an application to be fully internationalized, any validation messages (from either `disableXxx()` or `validateXxx()` supporting methods) and also possibly an object's title (from the `title()` method) will also require translation. Moreover, these messages must be captured in the `.pot` file such that they can be translated.
+
+
+=== `TranslatableString`
+
+The first part of the puzzle is tackled by an extension to Apache Isis' programming model.  Whereas previously the `disableXxx()` / `validateXxx()` / `title()` methods could only return a `java.lang.String`, they may now optionally return a `TranslatableString` (defined in Isis applib) instead.
+
+Here's a (silly) example from the xref:ugfun.adoc#_ugfun_getting-started_simpleapp-archetype[SimpleApp archetype]:
+
+[source,java]
+----
+public TranslatableString validateUpdateName(final String name) {
+    return name.contains("!")? TranslatableString.tr("Exclamation mark is not allowed"): null;
+}
+----
+
+This corresponds to the following entry in the `.pot` file:
+
+[source,ini]
+----
+#: dom.simple.SimpleObject#updateName()
+msgid "Exclamation mark is not allowed"
+msgstr ""
+----
+
+The full API of `TranslatableString` is modelled on the design of GNU gettext (in particular the https://code.google.com/p/gettext-commons/wiki/Tutorial[gettext-commons] library):
+
+[source,java]
+----
+public final class TranslatableString {
+    public static TranslatableString tr(       // <1>
+            final String pattern,
+            final Object... paramArgs) { ... }
+    public static TranslatableString trn(      // <2>
+            final String singularPattern,
+            final String pluralPattern,
+            final int number,
+            final Object... paramArgs) { ... }
+    public String translate(                   // <3>
+            final TranslationService translationService,
+            final String context) { ... }
+}
+----
+<1> returns a translatable string with a single pattern for both singular and plural forms.
+<2> returns a translatable string with different patterns for singular and plural forms; the one to use is determined by the 'number' argument
+<3> translates the string using the provided `TranslationService`, using the appropriate singular/regular or plural form, and interpolating any arguments.
+
+The interpolation uses the format `{xxx}`, where the placeholder can occur multiple times.
+
+For example:
+
+[source,java]
+----
+final TranslatableString ts = TranslatableString.tr(
+    "My name is {lastName}, {firstName} {lastName}.",
+    "lastName", "Bond", "firstName", "James");
+----
+
+would interpolate (for the English locale) as "My name is Bond, James Bond".
+
+For a German user, on the other hand, if the translation in the corresponding `.po` file was:
+
+[source,ini]
+----
+#: xxx.yyy.Whatever#context()
+msgid "My name is {lastName}, {firstName} {lastName}."
+msgstr "Iche heisse {firstName} {lastName}."
+----
+
+then the translation would be: "Ich heisse James Bond".
+
+
+The same class is used in xref:rgsvc.adoc#_rgsvc_api_DomainObjectContainer[`DomainObjectContainer`] so that you can raise translatable info, warning and error messages; each of the relevant methods are overloaded.
+
+For example:
+
+[source,java]
+----
+public interface DomainObjectContainer {
+    void informUser(String message);
+    void informUser(
+        TranslatableMessage message,
+        final Class<?> contextClass, final String contextMethod); // <1>
+    ...
+}
+----
+<1> are concatenated together to form the context for the `.pot` file.
+
+
+
+=== `TranslatableException`
+
+Another mechanism by which messages can be rendered to the user are as the result of exception messages thrown and recognized by an xref:rgsvc.adoc#_rgsvc_spi_ExceptionRecognizer[`ExceptionRecognizer`].
+
+In this case, if the exception implements `TranslatableException`, then the message will automatically be translated before being rendered.  The `TranslatableException` itself takes the form:
+
+[source,java]
+----
+public interface TranslatableException {
+    TranslatableString getTranslatableMessage(); // <1>
+    String getTranslationContext();              // <2>
+}
+
+----
+<1> the message to translate.  If returns `null`, then the `Exception#getMessage()` is used as a fallback
+<2> the context to use when translating the message
+
+
+
+
+
+== Integration Testing
+
+So much for the API; but as noted, it is also necessary to ensure that the required translations are recorded (by the `TranslationService`) into the `.pot` file.
+
+For this, we recommend that you ensure that all such methods are tested through an xref:ugtst.adoc#_ugtst_integ-test-support[integration test] (not unit test).
+
+For example, here's the corresponding integration test for the "Exclamation mark" example from the simpleapp (above):
+
+[source,java]
+----
+@Rule
+public ExpectedException expectedException = ExpectedException.none();
+
+@Inject
+FixtureScripts fixtureScripts;
+
+@Test
+public void failsValidation() throws Exception {
+    // given
+    RecreateSimpleObjects fs = new RecreateSimpleObjects().setNumber(1);
+    fixtureScripts.runFixtureScript(fs, null);
+    SimpleObject simpleObjectWrapped = wrap(fs.getSimpleObjects().get(0));
+
+    // expect
+    expectedExceptions.expect(InvalidException.class);
+    expectedExceptions.expectMessage("Exclamation mark is not allowed");
+
+    // when
+    simpleObjectWrapped.updateName("new name!");
+}
+----
+
+Running this test will result in the framework calling the `validateUpdateName(...)` method, and thus to record that a translation is required in the `.pot` file.
+
+When the integration tests are complete (that is, when Apache Isis is shutdown), the `TranslationServicePo` will write out all captured translations to its log (more on this below). This will include all the translations captured from the Apache Isis metamodel, along with all translations as exercised by the integration tests.
+
+To ensure your app is fully internationalized app, you must therefore:
+
+* use `TranslatableString` rather than `String` for all validation/disable and title methods.
+* ensure that (at a minimum) all validation messages and title methods are integration tested.
+
+[NOTE]
+====
+We make no apologies for this requirement: one of the reasons that we decided to implement Apache Isis' i18n support in this way is because it encourages/requires the app to be properly tested.
+
+Behind the scenes Apache Isis uses a JUnit rule (`ExceptionRecognizerTranslate`) to intercept any exceptions that are thrown.  These are simply passed through to the registered xref:rgsvc.adoc#_rgsvc_spi_ExceptionRecognizer[`ExceptionRecognizer`]s so that any messages are recorded as requiring translation.
+====
+
+
+
+
+
+
+== Escaped strings
+
+Translated messages can be escaped if required, eg to include embedded markup.
+
+[source,ini]
+----
+#: com.mycompany.myapp.OrderItem#quantity
+msgid "<i>Quantity</i>"
+msgstr "<i>Quantité</i>"
+----
+
+For this to work, the `namedEscaped()` attribute must be specified using either the
+xref:ugfun.adoc#_ugfun_object-layout_dynamic[dynamic layout] json file, or using an annotation such as
+xref:rgant.adoc#_rgant_PropertyLayout[`@PropertyLayout`] or xref:rgant.adoc#_rgant_ParameterLayout[`@ParameterLayout`].
+
+For example:
+
+[source,java]
+----
+@ParameterLayout(
+    named="<i>Quantity</i>",      // <1>
+    namedEscaped=false
+)
+public Integer getQuantity() { ... }
+----
+<1> required (even though it won't be used when a translation is read; otherwise the escaped flag is ignored)
+
+
+
+
+== Configuration
+
+There are several different aspects of the translation service that can be configured.
+
+=== Logging
+
+To configure the `TranslationServicePo` to write to out the `translations.pot` file, add the following to the _integtests_ `logging.properties` file:
+
+[source,ini]
+----
+log4j.appender.translations-po=org.apache.log4j.FileAppender
+log4j.appender.translations-po.File=./translations.pot
+log4j.appender.translations-po.Append=false
+log4j.appender.translations-po.layout=org.apache.log4j.PatternLayout
+log4j.appender.translations-po.layout.ConversionPattern=%m%n
+
+log4j.logger.org.apache.isis.core.runtime.services.i18n.po.PoWriter=INFO,translations-po
+log4j.additivity.org.apache.isis.core.runtime.services.i18n.po.PotWriter=false
+----
+
+Just to repeat, this is _not_ the `WEB-INF/logging.properties` file, it should instead be added to the `integtests/logging.properties` file.
+
+=== Location of the `.po` files
+
+The default location of the translated `.po` files is in the `WEB-INF` directory. These are named and searched for similarly to regular Java resource bundles.
+
+For example, assuming these translations:
+
+[source,ini]
+----
+/WEB-INF/translations-en-US.po
+        /translations-en.po
+        /translations-fr-FR.po
+        /translations.po
+----
+
+then:
+
+* a user with `en-US` locale will use `translations-en-US.po`
+* a user with `en-GB` locale will use `translations-en.po`
+* a user with `fr-FR` locale will use `translations-fr-FR.po`
+* a user with `fr-CA` locale will use `translations.po`
+
+The basename for translation files is always `translations`; this cannot be altered.
+
+
+=== Externalized translation files
+
+Normally Apache Isis configuration files are read from the `WEB-INF` file. However, Apache Isis can be configured to read config files from an xref:ugbtb.adoc#_ugbtb_deployment_externalized-configuration[external directory]; this is also supported for translations.
+
+Thus, if in `web.xml` the external configuration directory has been set:
+
+[source,xml]
+----
+<context-param>
+    <param-name>isis.config.dir</param-name>
+    <param-value>location of external config directory</param-value>
+</context-param>
+----
+
+Then this directory will be used as the base for searching for translations (rather than the default 'WEB-INF/' directory).
+
+=== Force read mode
+
+As noted above, if running in prototype mode then `TranslationServicePo` will be in write mode, if in production mode then will be in read mode. To force read mode (ie use translations) even if in prototype mode, add the following configuration property to `isis.properties`:
+
+[source,ini]
+----
+isis.services.translation.po.mode=read
+----
+
+== Supporting services
+
+The `TranslationServicePo` has a number of supporting/related services.
+
+=== `LocaleProvider`
+
+The `LocaleProvider` API is used by the `TranslationServicePo` implementation to obtain the locale of the "current user".
+
+A default implementation is provided by the Wicket viewer.
+
+[NOTE]
+====
+Note that this default implementation does not support requests made through the Restful Objects viewer (there is no Wicket 'application' object available); the upshot is that requests through Restful Objects are never translated. Registering a different implementation of `LocaleProvider` that taps into appropriate REST (RestEasy?) APIs would be the way to address this.
+====
+
+
+=== `TranslationsResolver`
+
+The `TranslationResolver` is used by the `TranslationService` implementation to lookup translations for a specified locale. It is this service that reads from the `WEB-INF/` (or externalized directory).
+
+
+=== `TranslationServicePoMenu`
+
+The `TranslationServicePoMenu` provides a couple of menu actions in the UI (prototype mode only) that interacts with the underlying `TranslationServicePo`:
+
+* the `downloadTranslationsFile()` action - available only in write mode - allows the current `.pot` file to be downloaded. +
++
+[NOTE]
+====
+While this will contain all the translations from the metamodel, it will not necessarily contain all translations for all imperative methods returning `TranslatableString` instances; which are present and which are missing will depend on which imperative methods have been called (recorded by the service) prior to downloading.
+====
+
+* the `clearTranslationsCache()` action - available only in read mode - will clear the cache so that new translations can be loaded. +
++
+This allows a translator to edit the appropriate `translations-xx-XX.po` file and check the translation is correct without having to restart the app.
+
+
+
+

http://git-wip-us.apache.org/repos/asf/isis/blob/29452af6/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced.adoc b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced.adoc
deleted file mode 100644
index 051c8d6..0000000
--- a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced.adoc
+++ /dev/null
@@ -1,26 +0,0 @@
-[[_ugbtb_more-advanced]]
-= Techniques
-: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 agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-:_basedir: ../
-:_imagesdir: images/
-
-
-
-This chapter pulls together a number of more advanced techniques that we've discovered and developed while building our own Isis applications.
-
-
-include::_ugbtb_more-advanced_decoupling.adoc[leveloffset=+1]
-include::_ugbtb_more-advanced_overriding-jdo-annotations.adoc[leveloffset=+1]
-include::_ugbtb_more-advanced_view-models.adoc[leveloffset=+1]
-include::_ugbtb_more-advanced_mapping-rdbms-views.adoc[leveloffset=+1]
-include::_ugbtb_more-advanced_transactions-and-errors.adoc[leveloffset=+1]
-include::_ugbtb_more-advanced_i18n.adoc[leveloffset=+1]
-include::_ugbtb_more-advanced_multi-tenancy.adoc[leveloffset=+1]
-include::_ugbtb_more-advanced_persisted-title.adoc[leveloffset=+1]
-include::_ugbtb_more-advanced_replacing-default-service-implementations.adoc[leveloffset=+1]include::_ugbtb_more-advanced_tips-n-tricks.adoc[leveloffset=+1]
-include::_ugbtb_more-advanced_headless-access.adoc[leveloffset=+1]
-
-
-
-
-

http://git-wip-us.apache.org/repos/asf/isis/blob/29452af6/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling.adoc b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling.adoc
deleted file mode 100644
index c0983ec..0000000
--- a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling.adoc
+++ /dev/null
@@ -1,28 +0,0 @@
-[[_ugbtb_more-advanced_decoupling]]
-= Decoupling
-: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 agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-:_basedir: ../
-:_imagesdir: images/
-
-
-We use Java packages as a way to group related domain objects together; the package name forms a namespace. We can then
-reason about all the classes in that package/namespace as a single unit, or module.
-
-This section describes how to use Apache Isis' features to ensure that your domain application remains decoupled.  The techniques described here are also the ones that have been adopted by the various http://github.com/isisaddons[Isis Addons] modules (not ASF) for security, commands, auditing etc.
-
-The following sections describe how to re-assemble an application, in particular where some modules are in-house but others are potentially third-party (eg the Isis Addons modules).
-
-[NOTE]
-====
-There is some overlap with OSGi and Java 9's Jigsaw concepts of "module"; in the future we expect to refactor Apache Isis to leverage these module systems.
-====
-
-include::_ugbtb_more-advanced_decoupling_db-schemas.adoc[leveloffset=+1]
-include::_ugbtb_more-advanced_decoupling_mixins.adoc[leveloffset=+1]
-include::_ugbtb_more-advanced_decoupling_contributions.adoc[leveloffset=+1]
-include::_ugbtb_more-advanced_decoupling_vetoing-visibility.adoc[leveloffset=+1]
-include::_ugbtb_more-advanced_decoupling_event-bus.adoc[leveloffset=+1]
-include::_ugbtb_more-advanced_decoupling_pushing-changes.adoc[leveloffset=+1]
-
-
-

http://git-wip-us.apache.org/repos/asf/isis/blob/29452af6/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_contributions.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_contributions.adoc b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_contributions.adoc
deleted file mode 100644
index 255f716..0000000
--- a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_contributions.adoc
+++ /dev/null
@@ -1,23 +0,0 @@
-[[_ugbtb_more-advanced_decoupling_contributions]]
-= Contributions
-: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 agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-:_basedir: ../
-:_imagesdir: images/
-
-
-Contributed services provide many of the same benefits as xref:ugbtb.adoc#_ugbtb_more-advanced_decoupling_mixins[mixins];
-indeed mixins are an evolution and refinement of the contributions concept.
-
-The main difference between contributed services and mixins is that the actions of a contributed service will
-contribute to _all_ the parameters of its actions, whereas a mixin only contributes to the type accepted in its
-constructor.  Also, contributed services are long-lived
-singletons, whereas mixins are instantiated as required (by the framework) and then discarded almost immediately.
-
-For more on contributed services:
-
-* the syntax of writing contributed actions/properties/collections is described in this xref:ugfun.adoc#_ugfun_how-tos_contributed-members[how-to]
-
-* there's also useful information in the reference guide, discussing the xref:rgant.adoc#_rgant-DomainService_nature[@DomainService#nature()] attribute, for the `NatureOfService.VIEW_CONTRIBUTIONS_ONLY` nature.
-
-
-

http://git-wip-us.apache.org/repos/asf/isis/blob/29452af6/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_db-schemas.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_db-schemas.adoc b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_db-schemas.adoc
deleted file mode 100644
index 687fb32..0000000
--- a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_db-schemas.adoc
+++ /dev/null
@@ -1,141 +0,0 @@
-[[_ugbtb_more-advanced_decoupling_db-schemas]]
-= Database Schemas
-: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 agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-:_basedir: ../
-:_imagesdir: images/
-
-In the same way that Java packages act as a namespace for domain objects, it's good practice to map domain entities to
-their own (database) schemas. As of 1.9.0, all the link:http://www.isisaddons.org[Isis Addons] (non-ASF) modules do this, for example:
-
-
-
-[source,java]
-----
-@javax.jdo.annotations.PersistenceCapable( ...
-        schema = "isissecurity",
-        table = "ApplicationUser")
-public class ApplicationUser ... { ... }
-----
-
-results in a `CREATE TABLE` statement of:
-
-[source,sql]
-----
-CREATE TABLE isissecurity."ApplicationUser" (
-    ...
-)
-----
-
-
-while:
-
-[source,java]
-----
-@javax.jdo.annotations.PersistenceCapable( ...
-        schema = "isisaudit",
-        table="AuditEntry")
-public class AuditEntry ... { ... }
-----
-
-similarly results in:
-
-[source,sql]
-----
-CREATE TABLE isisaudit."AuditEntry" (
-    ...
-)
-----
-
-
-[TIP]
-====
-If for some reason you don't want to use schemas (though we strongly recommend that you do), then note that you can override the `@PersistenceCapable` annotation by providing XML metadata (the `mappings.jdo` file); see the section on xref:rgcfg.adoc#_rgcfg_configuring-datanucleus[configuring DataNucleus Overriding Annotations] for more details.
-====
-
-
-
-
-== Listener to create schema
-
-JDO/DataNucleus does not automatically create these schema objects, but it _does_ provide a listener callback API
-on the initialization of each class into the JDO metamodel.
-
-[TIP]
-====
-Actually, the above statement isn't quite true.  In DN 3.2.x (as used by Apache Isis up to v1.8.0) there was no support for schemas.  As of Apache Isis 1.9.0 and DN 4.0 there is now support.  But we implemented this feature initially against DN 3.2.x, and it still works, so for now we've decided to leave it in.
-====
-
-Therefore Apache Isis attaches a listener, `CreateSchemaObjectFromClassMetadata`, that checks for the schema's existence, and creates the schema if required.
-
-The guts of its implementation is:
-
-[source,java]
-----
-public class CreateSchemaObjectFromClassMetadata
-        implements MetaDataListener,
-                   DataNucleusPropertiesAware {
-    @Override
-    public void loaded(final AbstractClassMetaData cmd) { ... }
-
-    protected String buildSqlToCheck(final AbstractClassMetaData cmd) {
-        final String schemaName = schemaNameFor(cmd);
-        return String.format(
-            "SELECT count(*) FROM INFORMATION_SCHEMA.SCHEMATA where SCHEMA_NAME = '%s'", schemaName);
-    }
-    protected String buildSqlToExec(final AbstractClassMetaData cmd) {
-        final String schemaName = schemaNameFor(cmd);
-        return String.format("CREATE SCHEMA \"%s\"", schemaName);
-    }
-}
-----
-
-where `MetaDataListener` is the DataNucleus listener API:
-
-[source,java]
-----
-public interface MetaDataListener {
-    void loaded(AbstractClassMetaData cmd);
-}
-----
-
-Although not formal API, the default `CreateSchemaObjectFromClassMetadata` has been designed to be easily overrideable if you
-need to tweak it to support other RDBMS'.  Any implementation must implement `org.datanucleus.metadata.MetaDataListener`:
-
-The implementation provided has has been tested for HSQLDB, PostgreSQL and MS SQL Server, and is used automatically unless an alternative implementation is specified (as described in the section below).
-
-
-
-
-
-== Alternative implementation
-
-An alternative implementation can be registered and used through the following configuration property:
-
-[source,ini]
-----
-isis.persistor.datanucleus.classMetadataLoadedListener=\
-        org.apache.isis.objectstore.jdo.datanucleus.CreateSchemaObjectFromClassMetadata
-----
-
-
-Because this pertains to the JDO Objectstore we suggest you put this configuration property in `WEB-INF/persistor_datanucleus.properties`; but putting it in `isis.properties` will also work.
-
-Any implementation must implement `org.datanucleus.metadata.MetaDataListener`.  In many cases simply subclassing from `CreateSchemaObjectFromClassMetadata` and overriding `buildSqlToCheck(...)` and `buildSqlToExec(...)` should suffice.
-
-If you _do_ need more control, your implementation can also optionally implement  `org.apache.isis.objectstore.jdo.datanucleus.DataNucleusPropertiesAware`:
-
-[source,java]
-----
-public interface DataNucleusPropertiesAware {
-    public void setDataNucleusProperties(final Map<String, String> properties);
-}
-----
-
-This provides access to the properties passed through to JDO/DataNucleus.
-
-
-[IMPORTANT]
-====
-If you do extend Apache Isis' `CreateSchemaObjectFromClassMetadata` class for some other database, please https://issues.apache.org/jira/browse/ISIS[contribute back] your improvements.
-====
-

http://git-wip-us.apache.org/repos/asf/isis/blob/29452af6/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_event-bus.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_event-bus.adoc b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_event-bus.adoc
deleted file mode 100644
index 97dd52c..0000000
--- a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_event-bus.adoc
+++ /dev/null
@@ -1,11 +0,0 @@
-[[_ugbtb_more-advanced_decoupling_event-bus]]
-= Event Bus
-: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 agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-:_basedir: ../
-:_imagesdir: images/
-
-NOTE: TODO - see xref:rgsvc.adoc#_rgsvc_api_EventBusService[`EventBusService`], xref:rgant.adoc#_rgant-Action_domainEvent[`@Action#domainEvent()`], xref:rgant.adoc#_rgant-Property_domainEvent[`@Property#domainEvent()`], xref:rgant.adoc#_rgant-Collection_domainEvent[`@Collection#domainEvent()`], xref:rgsvc.adoc#_rgsvc_api_WrapperFactory[`WrapperFactory`].
-
-
-
-

http://git-wip-us.apache.org/repos/asf/isis/blob/29452af6/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_mixins.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_mixins.adoc b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_mixins.adoc
deleted file mode 100644
index 29eb3e6..0000000
--- a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_mixins.adoc
+++ /dev/null
@@ -1,191 +0,0 @@
-[[_ugbtb_more-advanced_decoupling_mixins]]
-= Mixins
-: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 agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-:_basedir: ../
-:_imagesdir: images/
-
-
-A mixin object allows one class to contribute behaviour - actions, (derived) properties and
-(derived) collections - to another domain object, either a domain entity or view model.
-
-Some programming languages use the term "trait" instead of mixin, and some languages (such as AspectJ) define their own
-syntax for defining such constructs.  In Apache Isis a mixin is very similar to a domain service, however it also
-defines a single 1-arg constructor that defines the type of the domain objects that it contributes to.
-
-Why do this?  The main reason is to allow the app to be decoupled, so that it doesn't degrade into the proverbial
-link:http://www.laputan.org/mud/mud.html#BigBallOfMud["big ball of mud"].  Mixins (and contributions) allow dependency
-to be inverted, so that the dependencies between modules can be kept acyclic and under control.
-
-
-
-== Example
-
-This is probably best explained by way of an example.  Suppose we have the `Customer` domain object which implements
-a `DocumentHolder` interface:
-
-[source,java]
-----
-public class Customer implements DocumentHolder {
-    ...
-}
-----
-
-
-We could then imagine a mixin that would contribute behaviour to list, add and remove the ``Document``s for this holder:
-
-[source,java]
-----
-@Mixin                                                          // <1>
-public class DocumentHolder_documents {
-    private final DocumentHolder holder;
-    public DocumentHolder_documents(DocumentHolder holder) {    // <2>
-        this.holder = holder;
-    }
-    @Action(semantics=SemanticsOf.SAFE)
-    @ActionLayout(contributed = Contributed.AS_ASSOCIATION)
-    @CollectionLayout(render = RenderType.EAGERLY)
-    public List<Document> documents() {
-        ...                                                     // <3>
-    }
-    @Action(semantics=SemanticsOf.IDEMPOTENT)
-    public DocumentHolder add(Document document) {
-        ...                                                     // <4>
-    }
-    @Action(semantics=SemanticsOf.IDEMPOTENT)
-    public DocumentHolder remove(Document document) {
-        ...                                                     // <5>
-    }
-}
-----
-<1> alternatively can use `@DomainObject(nature=Nature.MIXIN)`
-<2> constructor indicates the type that is contributed to
-<3> implementation could, for example, use the (non-ASF)
-http://github.com/isisaddons/isis-module-poly[Isis addons' poly] module.
-<4> implementation would probably delegate to an injected repository to (ultimately) insert data into some table
-<5> implementation would probably delegate to an injected repository to (ultimately) delete data from some table
-
-The above example also omits any supporting methods, eg `hideXxx()`, `disableXxx()`, `validateXxx()`, etc.
-
-In the user interface the "documents" collection, the "add" and the "delete" actions will appear to be part of
-`Customer`.  In essence the framework constructs a composite UI from the parts of multiple objects.
-
-
-[TIP]
-====
-The (non-ASF) http://github.com/incodehq/incode-module-note[Incode note] and
-http://github.com/incodehq/incode-module-commchannel[Incode commchannel] modules are real-world examples that use this
-technique throughout.
-====
-
-
-
-== Contributing a single member
-
-The mixin can contribute as much or as little behaviour as makes sense.  For example, in the example above it might be
-that ``Document``s are created through some other mechanism (eg scanned) and are never deleted.  In that case, the
-mixin might be simply:
-
-[source,java]
-----
-@Mixin
-public class DocumentHolder_documents {
-    ..
-    public List<Document> documents() { ... }
-    ...
-}
-----
-
-
-For the case where there is only a single member being contributed, the special name "__" (that is, two underscores)
-can be used instead.  In this case, the contributee member's name will be inferred from the mixin's class name.  If the
-class name itself contains an underscore, then the last part of the class name will be used.
-
-Thus, for a mixin whose class name is `DocumentHolder_documents`, the effective member name is `documents`.  We could
-therefore rewrite the mixin as:
-
-[source,java]
-----
-@Mixin
-public class DocumentHolder_documents {
-    ..
-    public List<Document> __() { ... }
-    ...
-}
-----
-
-The benefit of this is marginal unless there are supporting methods, in which case the removal of boilerplate is welcome:
-
-[source,java]
-----
-@Mixin
-public class DocumentHolder_documents {
-    ..
-    public List<Document> __() { ... }
-    public boolean hide__() { ... }
-    public String disable__() { ... }
-    ...
-}
-----
-
-
-== Programmatic usage
-
-When a domain object is rendered, the framework will automatically instantiate all required mixins and delegate to them
-dynamically.  If writing integration tests or fixtures, or (sometimes) just regular domain logic, then you may need to
-instantiate mixins directly.
-
-For this you can use the
-xref:rgsvc.adoc#_rgsvc_api_DomainObjectContainer_object-creation-api[`DomainObjectContainer#mixin(...)`
-method.  For example:
-
-[source,java]
-----
-DocumentHolder_documents mixin = container.mixin(DocumentHolder_documents.class, customer);
-----
-
-The xref:ugtst.adoc#_ugtst_integ-test-support_bootstrapping_IntegrationTestAbstract[`IntegrationTestAbstract`] and
-xref:rgcms.adoc#_rgcms_classes_super_FixtureScript[`FixtureScript`] classes both provide a `mixin(...)` convenience
-method.
-
-
-
-== Other reasons to use mixins
-
-In the introduction to this topic we mentioned that mixins are most useful for ensuring that the domain app remains
-decoupled.  This applies to the case where the contributee (eg `Customer`, being mixed into) is in one module, while
-the contributor mixin (`DocumentHolder_documents`) is in some other module.  The `customer` module knows about the
-`document` module, but not vice versa.
-
-However, you might also want to consider moving behaviour out of entities even within the same module, perhaps even
-within the same Java package.  And the reason for this is to support hot-reloading of Java classes, so that you can
-modify and recompile your application without having to restart it.  This can provide substantial productivity gains.
-
-The Hotspot JVM has limited support for hot reloading; generally you can change method implementations but you cannot
-introduce new methods.  However, the link:https://dcevm.github.io/[DCEVM] open source project will patch the JVM to
-support much more complete hot reloading support.  There are also, of course, commercial products such as JRebel.
-
-The main snag in all this is the DataNucleus enhancer... any change to entities is going to require the entity to be
-re-enhanced, and the JDO metamodel recreated, which usually "stuffs things up".  So hot-reloading of an app whose
-fundamental structure is changing is likely to remain a no-no.
-
-However, chances are that the structure of your domain objects (the data) will change much less rapidly than
-the behaviour of those domain objects.  Thus, it's the behaviour that you're most likely wanting to change while the
-app is still running.  If you move that behaviour out into mixins (or
-xref:ugbtb.adoc#_ugbtb_more-advanced_decoupling_contributions[contributed services]), then these can be reloaded happily.
-(When running in prototype mode), Apache Isis will automatically recreate the portion of the metamodel for any domain
-object as it is rendered.
-
-
-
-== Related reading
-
-Mixins are an implementation of the link:http://www.artima.com/articles/dci_vision.html[DCI architecture] architecture, as formulated and described by link:https://en.wikipedia.org/wiki/Trygve_Reenskaug[Trygve Reenskaug] and link:https://en.wikipedia.org/wiki/Jim_Coplien[Jim Coplien].  Reenskaug was the inventor of the MVC pattern (and also the external
-examiner for Richard Pawson's PhD thesis), while Coplien has a long history in object-orientation, C++ and patterns.
-
-DCI stands for Data-Context-Interaction and is presented as an evolution of object-oriented programming, but one where
-behaviour is bound to objects dynamically rather than statically in some context or other.  The `@Mixin`
-pattern is Apache Isis' straightforward take on the same basic concept.
-
-You might also wish to check out link:http://zest.apache.org[Apache Zest] (formerly Qi4J), which implements a much more
-general purpose implementation of the same concepts.
-

http://git-wip-us.apache.org/repos/asf/isis/blob/29452af6/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_pushing-changes.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_pushing-changes.adoc b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_pushing-changes.adoc
deleted file mode 100644
index 7cd2f5d..0000000
--- a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_pushing-changes.adoc
+++ /dev/null
@@ -1,140 +0,0 @@
-[[_ugbtb_more-advanced_decoupling_pushing-changes]]
-= Pushing Changes
-: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 agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-:_basedir: ../
-:_imagesdir: images/
-
-
-[NOTE]
-====
-This technique is much less powerful than using xref:ugbtb.adoc#_ugbtb_more-advanced_decoupling_event-bus[the event bus] .  We present it mostly for completeness.
-====
-
-
-
-
-== When a property is changed
-
-If you want to invoke functionality whenever a property is changed by the user, then you should create a supporting `modifyXxx()` method and include the functionality within that. The syntax is:
-
-[source,java]
---
-public void modifyPropertyName(PropertyType param) { ... }
---
-
-Why not just put this functionality in the setter? Well, the setter is used by the object store to recreate the state of an already persisted object. Putting additional behaviour in the setter would cause it to be triggered incorrectly.
-
-For example:
-
-[source,java]
---
-public class Order() {
-    public Integer getAmount() { ... }
-    public void setAmount(Integer amount) { ... }
-    public void modifyAmount(Integer amount) { // <1>
-        setAmount(amount);  // <3>
-        addToTotal(amount); // <2>
-    }
-    ...
-}
---
-<1> The `modifyAmount()` method calls ...
-<2> ... the `addToTotal()` (not shown) to maintain some running total.
-
-We don't want this `addToCall()` method to be called when pulling the object back from the object store, so we put it into the modify, not the setter.
-
-You may optionally also specify a `clearXxx()` which works the same way as modify `modify Xxx()` but is called when the property is cleared by the user (i.e. the current value replaced by nothing). The syntax is:
-
-[source,java]
---
-public void clearPropertyName() { ... }
---
-
-To extend the above example:
-
-[source,java]
---
-public class Order() {
-    public Integer getAmount() { ... }
-    public void setAmount(Integer amount) { ... }
-    public void modifyAmount(Integer amount) { ... }
-    public void clearAmount() {
-        removeFromTotal(this.amount);
-        setAmount(null);
-    }
-    ...
-}
---
-
-
-
-
-== When a collection is modified
-
-A collection may have a corresponding `addToXxx()` and/or
-`removeFromXxx()` method. If present, and direct manipulation of the
-contents of the connection has not been disabled (see ?), then they will
-be called (instead of adding/removing an object directly to the
-collection returned by the accessor).
-
-The reason for this behaviour is to allow other behaviour to be
-triggered when the contents of the collection is altered. That is, it is
-directly equivalent to the supporting `modifyXxx()` and `clearXxx()`
-methods for properties (see ?).
-
-The syntax is:
-
-[source,java]
---
-public void addTo<CollectionName>(EntityType param) { ... }
---
-
-and
-
-[source,java]
---
-public void removeFromCollectionName(EntityType param) { ... }
---
-
-where `EntityType` is the same type as the generic collection type.
-
-For example:
-
-[source,java]
---
-public class Employee { ... }
-
-public class Department {
-
-    private int numMaleEmployees;                           // <1>
-    private int numFemaleEmployees;                         // <2>
-
-    private Set<Employee> employees = new TreeSet<Employee>();
-    public Set<Employee> getEmployees() {
-        return employees;
-    }
-    private void setEmployees(Set<Employee> employees) {
-        this.employees = employees;
-    }
-    public void addToEmployees(Employee employee) {         // <3>
-        numMaleEmployees += countOneMale(employee);
-        numFemaleEmployees += countOneFemale(employee);
-        employees.add(employee);
-    }
-    public void removeFromEmployees(Employee employee) {    // <4>
-        numMaleEmployees -= countOneMale(employee);
-        numFemaleEmployees -= countOneFemale(employee);
-        employees.remove(employee);
-    }
-    private int countOneMale(Employee employee) { return employee.isMale()?1:0; }
-    private int countOneFemale(Employee employee) { return employee.isFemale()?1:0; }
-
-    ...
-}
---
-<1> maintain a count of the number of male ...
-<2> ... and female employees (getters and setters omitted)
-<3> the xref:rgcms.adoc#_rgcms_methods_prefixes_addTo[`addTo...()`] method increments the derived properties
-<4> the xref:rgcms.adoc#_rgcms_methods_prefixes_removeFrom[`removeFrom...()`] method similarly decrements the derived properties
-
-

http://git-wip-us.apache.org/repos/asf/isis/blob/29452af6/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_vetoing-visibility.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_vetoing-visibility.adoc b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_vetoing-visibility.adoc
deleted file mode 100644
index d5abe7f..0000000
--- a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_decoupling_vetoing-visibility.adoc
+++ /dev/null
@@ -1,15 +0,0 @@
-[[_ugbtb_more-advanced_decoupling_vetoing-visibility]]
-= Vetoing Visibility
-: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 agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-:_basedir: ../
-:_imagesdir: images/
-
-
-NOTE: TODO - a write-up of the "vetoing subscriber" design pattern, eg as described in the  xref:rgsvc.adoc#_rgsvc_api_BookmarkService[`BookmarkService`]
-
-
-eg if included an addon such as auditing or security.
-
-solution is to write a domain event subscriber that vetoes the visibility
-
-All the addons actions inherit from common base classes so this can be as broad-brush or fine-grained as required
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/29452af6/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_headless-access.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_headless-access.adoc b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_headless-access.adoc
deleted file mode 100644
index b7c77c0..0000000
--- a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_headless-access.adoc
+++ /dev/null
@@ -1,27 +0,0 @@
-[[_ugbtb_more-advanced_headless-access]]
-= Headless access
-: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 agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-:_basedir: ../
-:_imagesdir: images/
-
-This section tackles the topic of enabling access to an Isis application directly, or at least, not through either the xref:ugvw.adoc#[Wicket] or xref:ugvro.adoc#[Restful] viewers.
-
-There are several main use-cases:
-
-* enabling background execution, eg of a thread managed by Quartz scheduler and running within the webapp
-
-* integration from other systems, eg for a subscriber on a pub/sub mechanism such as Camel, pushing changes through an Apache Isis domain model.
-
-* leveraging an Isis application within a batch process
-
-Note that the calling thread runs in the same process space as the Apache Isis domain object model (must be physically linked to the JAR files containing the domain classes).  For use cases where the calling thread runs in some other process space (eg migrating data from a legacy system), then the xref:ugvro.adoc#[Restful Objects viewer] is usually the way to go.
-
-The API described in this chapter is reasonably low-level, allowing code to interact very directly with the Apache Isis metamodel and runtime.  Such callers should be considered trusted: they do not (by default) honour any business rules eg implicit in the Isis annotations or hide/disable/validate methods.  However the xref:rgsvc.adoc#_rgsvc_api_WrapperFactory[`WrapperFactory`] service could be used to enforce such business rules if required.
-
-
-
-include::_ugbtb_more-advanced_headless-access_AbstractIsisSessionTemplate.adoc[leveloffset=+1]
-include::_ugbtb_more-advanced_headless-access_BackgroundCommandExecution.adoc[leveloffset=+1]
-
-
-

http://git-wip-us.apache.org/repos/asf/isis/blob/29452af6/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_headless-access_AbstractIsisSessionTemplate.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_headless-access_AbstractIsisSessionTemplate.adoc b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_headless-access_AbstractIsisSessionTemplate.adoc
deleted file mode 100644
index a0dcc5a..0000000
--- a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_headless-access_AbstractIsisSessionTemplate.adoc
+++ /dev/null
@@ -1,40 +0,0 @@
-[[_ugbtb_more-advanced_headless-access_AbstractIsisSessionTemplate]]
-= AbstractIsisSessionTemplate
-: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 agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-:_basedir: ../
-:_imagesdir: images/
-
-
-The `AbstractIsisSessionTemplate` class (whose name is inspired by the Spring framework's naming convention for similar classes that query http://docs.spring.io/spring/docs/2.5.x/reference/jdbc.html#jdbc-JdbcTemplate[JDBC], http://docs.spring.io/spring/docs/2.5.x/reference/jms.html#jms-jmstemplate[JMS], http://docs.spring.io/spring/docs/2.5.x/reference/orm.html#orm-jpa-template[JPA] etc.) provides the mechanism to open up a 'session' within the Apache Isis framework, in order to resolve and interact with entities.
-
-The class itself is intended to be subclassed:
-
-[source,java]
-----
-public abstract class AbstractIsisSessionTemplate {
-
-    public void execute(final AuthenticationSession authSession, final Object context) { ... } //<1>
-    protected abstract void doExecute(Object context); // <2>
-
-    protected ObjectAdapter adapterFor(final Object targetObject) { ... }
-    protected ObjectAdapter adapterFor(final RootOid rootOid) { ... }
-
-    protected PersistenceSession getPersistenceSession() { ... }
-    protected IsisTransactionManager getTransactionManager() { ... }
-    protected AdapterManager getAdapterManager() { ... }
-}
-----
-<1> `execute(...)` sets up the `IsisSession` and delegates to ...
-<2> `doExecute(...)`, the mandatory hook method for subclasses to implement.
-The passed object represents passes a context from the caller (eg the scheduler, cron job, JMS etc) that instantiated and executed the class.
-
-The `protected` methods expose key internal APIs within Apache Isis, for the subclass to use as necessary.
-
-
-[TIP]
-====
-One notable feature of `AbstractIsisSessionTemplate` is that it will automatically inject any domain services into itself. Thus, it is relatively easy for the subclass to "reach into" the domain, through injected repository services.
-====
-
-
-

http://git-wip-us.apache.org/repos/asf/isis/blob/29452af6/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_headless-access_BackgroundCommandExecution.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_headless-access_BackgroundCommandExecution.adoc b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_headless-access_BackgroundCommandExecution.adoc
deleted file mode 100644
index 06d6747..0000000
--- a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_more-advanced_headless-access_BackgroundCommandExecution.adoc
+++ /dev/null
@@ -1,45 +0,0 @@
-[[_ugbtb_more-advanced_headless-access_BackgroundCommandExecution]]
-= BackgroundCommandExecution
-: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 agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-:_basedir: ../
-:_imagesdir: images/
-
-
-
-The `BackgroundCommandExecution` class (a subclass of xref:ugbtb.adoc#_ugbtb_more-advanced_headless-access_AbstractIsisSessionTemplate[AbstractIsisSessionTemplate]) is intended to simplify the execution of background ``Command``s persisted by way of the xref:rgsvc.adoc#_rgsvc_spi_CommandService[`CommandService`] and the xref:rgsvc.adoc#_rgsvc_spi_BackgroundCommandService[`BackgroundCommandService`].
-
-Its signature is:
-
-[source,java]
-----
-public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemplate {
-    protected void doExecute(Object context) { ... }
-    protected abstract List<? extends Command> findBackgroundCommandsToExecute(); // <1>
-}
-----
-<1> `findBackgroundCommandsToExecute()` is a mandatory hook method for subclasses to implement.
-
-This allows for different implementations of the `CommandService` and `BackgroundCommandService` to persist to wherever.
-
-The diagram below (http://yuml.me/edit/363b335f[yuml.me/363b335f]) shows the dependencies between these various classes:
-
-.Inheritance Hierarchy for `BackgroundCommandExecution`
-image::{_imagesdir}headless-access/BackgroundCommandExecution.png[width="400px"]
-
-
-
-
-
-
-
-== Background Execution
-
-The `BackgroundCommandExecutionFromBackgroundCommandServiceJdo` is a concrete subclass of `BackgroundCommandExecution` (see the xref:rgsvc.adoc#_rgsvc_api_BackgroundService[`BackgroundCommandService`]), the intended use being for the class to be instantiated regularly (eg every 10 seconds) by a scheduler such as http://quartz-scheduler.org[Quartz]) to poll for ``Command``s to be executed, and then execute them.
-
-This implementation queries for ``Command``s persisted by the link:http://www.isisaddons.org/isis-module-command[Isis addons Command Module]'s  implementations of xref:rgsvc.adoc#_rgsvc_spi_CommandService[`CommandService`] and xref:rgsvc.adoc#_rgsvc_spi_BackgroundCommandService[`BackgroundCommandService`] using the `BackgroundCommandServiceJdoRepository`.
-
-The diagram below (link:http://yuml.me/edit/25343da1[yuml.me/25343da1]) shows the inheritance hierarchy for this class:
-
-.Inheritance Hierarchy for `BackgroundCommandExecutionFromBackgroundCommandServiceJdo`
-image::{_imagesdir}headless-access/BackgroundCommandExecutionFromBackgroundCommandServiceJdo.png[width="500px"]
-