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/03 19:15:23 UTC

[05/51] [abbrv] isis git commit: ISIS-1243: moved domain services into their own guide.

http://git-wip-us.apache.org/repos/asf/isis/blob/0d8aeafc/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-BackgroundService_Quartz.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-BackgroundService_Quartz.adoc b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-BackgroundService_Quartz.adoc
new file mode 100644
index 0000000..c8a0b04
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-BackgroundService_Quartz.adoc
@@ -0,0 +1,162 @@
+[[_rgsvc-api_manpage-BackgroundService_Quartz]]
+= Quartz Scheduler Configuration
+: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 last part of the puzzle is to actually run the (appropriate implementation of) `BackgroundCommandExecution).  This could be run in a batch job overnight, or run continually by, say, the http://quartz-scheduler.org[Quartz] scheduler or by http://camel.apache.org]Apache Camel].  This section looks at configuring Quartz.
+
+If using (non-ASF) http://github.com/isisaddons/isis-module-command[Isis addons' command] module, then note that this already provides a suitable concrete implementation, namely `org.isisaddons.module.command.dom.BackgroundCommandExecutionFromBackgroundCommandServiceJdo`.  We therefore just need to schedule this to run as a Quartz job.
+
+
+First, we need to define a Quartz job, for example:
+
+[source,java]
+----
+import org.isisaddons.module.command.dom.BackgroundCommandExecutionFromBackgroundCommandServiceJdo;
+public class BackgroundCommandExecutionQuartzJob extends AbstractIsisQuartzJob {
+    public BackgroundCommandExecutionQuartzJob() {
+        super(new BackgroundCommandExecutionFromBackgroundCommandServiceJdo());
+    }
+}
+----
+
+where `AbstractIsisQuartzJob` is in turn the following boilerplate:
+
+[source,java]
+----
+package domainapp.webapp.quartz;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+...
+public class AbstractIsisQuartzJob implements Job {
+    public static enum ConcurrentInstancesPolicy {
+        SINGLE_INSTANCE_ONLY,
+        MULTIPLE_INSTANCES
+    }
+
+    private final AbstractIsisSessionTemplate isisRunnable;
+    private final ConcurrentInstancesPolicy concurrentInstancesPolicy;
+    private boolean executing;
+
+    public AbstractIsisQuartzJob(AbstractIsisSessionTemplate isisRunnable) {
+        this(isisRunnable, ConcurrentInstancesPolicy.SINGLE_INSTANCE_ONLY);
+    }
+    public AbstractIsisQuartzJob(
+            AbstractIsisSessionTemplate isisRunnable,
+            ConcurrentInstancesPolicy concurrentInstancesPolicy) {
+        this.isisRunnable = isisRunnable;
+        this.concurrentInstancesPolicy = concurrentInstancesPolicy;
+    }
+
+    public void execute(final JobExecutionContext context)
+            throws JobExecutionException {
+        final AuthenticationSession authSession = newAuthSession(context);
+        try {
+            if(concurrentInstancesPolicy == ConcurrentInstancesPolicy.SINGLE_INSTANCE_ONLY &&
+               executing) {
+                return;
+            }
+            executing = true;
+
+            isisRunnable.execute(authSession, context);
+        } finally {
+            executing = false;
+        }
+    }
+
+    AuthenticationSession newAuthSession(JobExecutionContext context) {
+        String user = getKey(context, SchedulerConstants.USER_KEY);
+        String rolesStr = getKey(context, SchedulerConstants.ROLES_KEY);
+        String[] roles = Iterables.toArray(
+                Splitter.on(",").split(rolesStr), String.class);
+        return new SimpleSession(user, roles);
+    }
+
+    String getKey(JobExecutionContext context, String key) {
+        return context.getMergedJobDataMap().getString(key);
+    }
+}
+----
+
+
+This job can then be configured to run using Quartz' `quartz-config.xml` file:
+
+[source,xml]
+----
+<?xml version="1.0" encoding="UTF-8"?>
+<job-scheduling-data
+    xmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://www.quartz-scheduler.org/xml/JobSchedulingData
+http://www.quartz-scheduler.org/xml/job_scheduling_data_1_8.xsd"
+    version="1.8">
+    <schedule>
+       <job>
+         <name>BackgroundCommandExecutionJob</name>
+         <group>Isis</group>
+         <description>
+                Poll and execute any background actions persisted by the BackgroundActionServiceJdo domain service
+            </description>
+         <job-class>domainapp.webapp.quartz.BackgroundCommandExecutionQuartzJob</job-class>
+         <job-data-map>
+          <entry>
+              <key>webapp.scheduler.user</key>
+              <value>scheduler_user</value>
+          </entry>
+          <entry>
+              <key>webapp.scheduler.roles</key>
+              <value>admin_role</value>
+          </entry>
+         </job-data-map>
+       </job>
+       <trigger>
+         <cron>
+          <name>BackgroundCommandExecutionJobEveryTenSeconds</name>
+          <job-name>BackgroundCommandExecutionJob</job-name>
+          <job-group>Isis</job-group>
+          <cron-expression>0/10 * * * * ?</cron-expression>
+         </cron>
+       </trigger>
+    </schedule>
+</job-scheduling-data>
+----
+
+The remaining two pieces of configuration are the `quartz.properties` file:
+
+[source,ini]
+----
+org.quartz.scheduler.instanceName = SchedulerQuartzConfigXml
+org.quartz.threadPool.threadCount = 1
+org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
+org.quartz.plugin.jobInitializer.class =org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
+org.quartz.plugin.jobInitializer.fileNames = webapp/scheduler/quartz-config.xml
+org.quartz.plugin.jobInitializer.failOnFileNotFound = true
+----
+
+and the entry in `web.xml` for the Quartz servlet:
+
+[source,xml]
+----
+<servlet>
+     <servlet-name>QuartzInitializer</servlet-name>
+     <servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class>
+     <init-param>
+         <param-name>config-file</param-name>
+         <param-value>webapp/scheduler/quartz.properties</param-value>
+     </init-param>
+     <init-param>
+         <param-name>shutdown-on-unload</param-name>
+         <param-value>true</param-value>
+     </init-param>
+     <init-param>
+         <param-name>start-scheduler-on-load</param-name>
+         <param-value>true</param-value>
+     </init-param>
+     <load-on-startup>1</load-on-startup>
+ </servlet>
+----
+

http://git-wip-us.apache.org/repos/asf/isis/blob/0d8aeafc/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-BookmarkService.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-BookmarkService.adoc b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-BookmarkService.adoc
new file mode 100644
index 0000000..4881da8
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-BookmarkService.adoc
@@ -0,0 +1,116 @@
+[[_rgsvc-api_manpage-BookmarkService]]
+= `BookmarkService`
+: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 `BookmarkService` provides the ability to obtain a serializable `o.a.i.applib.bookmarks.Bookmark` for any (persisted) domain object, and to lookup domain objects given a `Bookmark`.  This can then in turn be converted to and from a string.
+
+For example, a `Customer` object with:
+
+* an object type of "custmgmt.Customer" (as per xref:rgant.adoc#_rgant-DomainObject_objectType[`DomainObject#objectType()`] or equivalent) , and
+* an id=123
+
+could correspond to a `Bookmark` with a string representation of `custmgmt.Customer|123`.
+
+[NOTE]
+====
+A `Bookmark` is little more than an API equivalent of Apache Isis' internal `Oid` (object identifier).  Nevertheless, the ability to uniquely address _any_ domain object within an Apache Isis system -- to in effect provide a URN -- is immensely useful.
+
+For example, a `Bookmark` could be converted into a barcode, and then this used for automated scanning of correspondence from a customer.
+====
+
+``Bookmark``s are used by several other domain services as a means of storing areference to an arbitrary object (a polymorphic relationship).  For example, the (non-ASF) http://github.com/isisaddons/isis-module-auditing[Isis addons' auditing] module's implementation of xref:rgsvc.adoc#_rgsvc-spi_manpage-AuditingService[`AuditingService`] uses bookmarks to capture the object that is being audited.
+
+[TIP]
+====
+One downside of using ``Bookmark``s is that there is no way for the JDO/DataNucleus objectstore to enforce any kind of referental integrity.  However, the (non-ASF) http://github.com/isisaddons/isis-module-poly[Isis addons' poly] module describes and supports a design pattern to address this requirement.
+====
+
+
+
+
+== API & Implementation
+
+The API defined by `BookmarkService` is:
+
+[source,java]
+----
+public interface BookmarkService {
+    @Programmatic
+    Object lookup(BookmarkHolder bookmarkHolder);
+    @Programmatic
+    Object lookup(Bookmark bookmark);
+    @Programmatic
+    <T> T lookup(Bookmark bookmark, Class<T> cls);   // <1>
+    @Programmatic
+    Bookmark bookmarkFor(Object domainObject);
+    @Programmatic
+    Bookmark bookmarkFor(Class<?> cls, String identifier);
+}
+----
+<1> same as `lookup(Bookmark bookmark)`, but downcasts to the specified type.
+
+
+The core framework provides a default implementation of this API, namely `o.a.i.core.metamodel.services.bookmarks.BookmarkServiceDefault`
+
+
+== `BookmarkHolder`
+
+The `BookmarkHolder` interface is intended to be implemented by domain objects that use a `Bookmark` to reference a (single) domain object; an example might be a class such as the audit entry, mentioned above.  The interface is simply:
+
+
+[source,java]
+----
+public interface BookmarkHolder {
+    @Programmatic
+    Bookmark bookmark();
+}
+
+----
+
+There are two services that will contribute to this interface:
+
+* `BookmarkHolderActionContributions` will provide a `lookup(...)` action
+* `BookmarkHolderAssociationContributions` provides an `object` property.
+
+Either of these can be suppressed, if required, using a vetoing subscriber.  For example, to suppress the `object` property (so that only the `lookup(...)` action is ever shown for implementations of `BookmarkHolder`, define:
+
+[source,java]
+----
+@DomainObject
+public class AlwaysHideBookmarkHolderAssociationsObjectProperty {
+    @Subscribe
+    public void on(BookmarkHolderAssociationContributions.ObjectDomainEvent ev) {
+        ev.hide();
+    }
+}
+----
+
+A more sophisticated implementation could look inside the passed `ev` argument and selectively hide or not based on the contributee.
+
+
+
+
+== Usage by other services
+
+Bookmarks are used by the (non-ASF) http://github.com/isisaddons/isis-module-command[Isis addons' command] module's implementation of  xref:rgsvc.adoc#_rgsvc-api_manpage-BackgroundCommandService[`BackgroundCommandService`], which uses a bookmark to capture the target object on which an action will be invoked subsequently.
+
+Bookmarks are also used by the (non-ASF) http://github.com/isisaddons/isis-module-publishing[Isis addons' publishing] module's implementation of xref:rgsvc.adoc#_rgsvc-spi_manpage-PublishingService[`PublishingService`], and by the (non-ASF) http://github.com/isisaddons/isis-module-auditing[Isis addons' auditing] module's implementation of xref:rgsvc.adoc#_rgsvc-spi_manpage-AuditingService[`AuditingService`].
+
+
+
+
+== Registering the Service
+
+Assuming that the `configuration-and-annotation` services installer is configured (implicit if using the
+`AppManifest` to xref:rg.adoc#_rg_classes_AppManifest-bootstrapping[bootstrap the app]) then Apache Isis' core
+implementation of `BookmarkService` is automatically registered (it is annotated with `@DomainService`) so no further
+configuration is required.
+
+To use an alternative implementation, use
+xref:rgant.adoc#_rgant-DomainServiceLayout_menuOrder[`@DomainServiceLayout#menuOrder()`] (as explained
+further in this xref:ug.adoc#_ug_how-tos_replacing-default-service-implementations["how to"] tip).
+
+

http://git-wip-us.apache.org/repos/asf/isis/blob/0d8aeafc/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-BulkInteractionContext.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-BulkInteractionContext.adoc b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-BulkInteractionContext.adoc
new file mode 100644
index 0000000..00a37eb
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-BulkInteractionContext.adoc
@@ -0,0 +1,9 @@
+[[_rgsvc-api_manpage-BulkInteractionContext]]
+= `BulkInteractionContext`
+: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 service is deprecated, replaced by xref:rgsvc.adoc#_rgsvc-api_manpage-ActionInvocationContext[`ActionInvocationContext`].
+

http://git-wip-us.apache.org/repos/asf/isis/blob/0d8aeafc/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-ClockService.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-ClockService.adoc b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-ClockService.adoc
new file mode 100644
index 0000000..552f1cc
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-ClockService.adoc
@@ -0,0 +1,101 @@
+[[_rgsvc-api_manpage-ClockService]]
+= `ClockService`
+: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/
+
+
+
+
+Most applications deal with dates and times in one way or another. For example, if an `Order` is placed, then the `Customer` may have 30 days to pay the `Invoice`, otherwise a penalty may be levied.
+
+However, such date/time related functionality can quickly complicate automated testing: "today+30" will be a different value every time the test is run.
+
+Even disregarding testing, there may be a requirement to ensure that date/times are obtained from an NNTP server (rather than the system PC). While instantiating a `java.util.Date` to current the current time is painless enough, we would not want complex technical logic for querying an NNTP server spread around domain logic code.
+
+Therefore it's common to provide a domain service whose responsibility is to provide the current time.  This service can be injected into any domain object (and can be mocked out for unit testing). Apache Isis provides such a facade through the `ClockService`.
+
+
+
+== API & Implementation
+
+The API defined by `ClockService` is:
+
+[source,java]
+----
+@DomainService(nature = NatureOfService.DOMAIN)
+public class ClockService {
+    @Programmatic
+    public LocalDate now() { ... }
+    @Programmatic
+    public LocalDateTime nowAsLocalDateTime() { ... }
+    @Programmatic
+    public DateTime nowAsDateTime() { ... }
+    @Programmatic
+    public Timestamp nowAsJavaSqlTimestamp() { ... }
+    @Programmatic
+    public long nowAsMillis() { ... }
+}
+----
+
+This class (`o.a.i.applib.services.clock.ClockService`) is also the default implementation.  The time provided by this default implementation is based on the system clock.
+
+
+
+
+== Testing Support
+
+The default `ClockService` implementation in fact simply delegates to another class defined in the API, namely the `o.a.i.applib.clock.Clock`, an abstract singleton class.  It is not recommended that your code use the `Clock` directly, but you should understand how this all works:
+
+* there are two subclasses implementations `Clock`, namely `SystemClock` and `FixtureClock`.
+* the first implementation that is instantiated registers itself as the singleton.
+* if running in xref:rg.adoc#_rg_runtime_deployment-types[production] (server) mode, then (unless another implementation has beaten it to the punch) the framework will instantiate the ``SystemClock`.  Once instantiated this cannot be replaced.
+* if running in xref:rg.adoc#_rg_runtime_deployment-types[prototype] mode, then the framework will instead instantiate `FixtureClock`.  This _can_ be replaced if required.
+
+The `FixtureClock` will behave as the system clock, unless its is explicitly set using `FixtureClock#setDate(...)` or `FixtureClock#setTime(...)` and so forth.
+
+
+
+=== Alternative Implementations
+
+Suppose you want (as discussed in the introduction to this service) to use a clock that delegates to NNTP.  For most domain services this would amount to implementing the appropriate service and registering in `isis.properties` so that it is used in preference to any implementations provided by default by the framework.
+
+In the case of the `ClockService`, though, this approach (unfortunately) will not work, because parts of Apache Isis (still) delegate to the `Clock` singleton rather than using the `ClockService` domain service.
+
+The workaround, therefore, is to implement your functionality as a subclass of `Clock`.  You can write a domain service that will ensure that your implementation is used ahead of any implementations provided by the framework.
+
+For example:
+
+[source,java]
+----
+@DomainService(nature=NatureOfService.DOMAIN)
+public class NntpClockServiceInitializer  {
+    @Programmatic
+    @PostConstruct
+    public void postConstruct(Map<String,String> properties) {
+        new NntpClock(properties);                       // <1>
+    }
+    private static class NntpClock extends Clock {
+        NntpClock(Map<String,String> properties) { ... } // <2>
+        protected long time() { ... }                    // <3>
+            ... NNTP stuff here ...
+        }
+    }
+}
+----
+<1> enough to simply instantiate the `Clock`; it will register itself as singleton
+<2> connect to NNTP service using configuration properties from `isis.properties`
+<3> call to NNTP service here
+
+
+
+
+== Registering the Service
+
+Assuming that the `configuration-and-annotation` services installer is configured (implicit if using the
+`AppManifest` to xref:rg.adoc#_rg_classes_AppManifest-bootstrapping[bootstrap the app]) then Apache Isis' core
+implementation of `ClockService` is automatically registered (it is annotated with `@DomainService`) so no further
+configuration is required.
+
+If you want to use a different implementation of `Clock`, eg delegating to NNTP, then do _not_ register directly, but
+instead subclass from `o.a.i.applib.clock.Clock` singleton (as described in the section above).

http://git-wip-us.apache.org/repos/asf/isis/blob/0d8aeafc/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-CommandContext.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-CommandContext.adoc b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-CommandContext.adoc
new file mode 100644
index 0000000..1e57959
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-CommandContext.adoc
@@ -0,0 +1,216 @@
+[[_rgsvc-api_manpage-CommandContext]]
+= `CommandContext`
+: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 `CommandContext` service is a xref:rgant.adoc#_rgant-RequestScoped[request-scoped] service that reifies the invocation of an action on a domain object into an object itself. This reified information is encapsulated within the `Command` object.
+
+By default, the `Command` is held in-memory only; once the action invocation has completed, the `Command` object is gone. The optional
+ supporting xref:rgsvc.adoc#_rgsvc-spi_manpage-CommandService[`CommandService`] enables the implementation of `Command` to be pluggable. With an appropriate implementation (eg as provided by the (non-ASF) http://github.com/isisaddons/isis-module-command[Isis addons' command] module's xref:rgsvc.adoc#_rgsvc-spi_manpage-CommandService[`CommandService`]) the `Command` may then be persisted.
+
+Persistent ``Command``s support several use cases:
+
+* they enable profiling of the running application (which actions are invoked then most often, what is their response time)
+* they act as a parent to any background commands that might be invoked through the xref:rgsvc.adoc#_rgsvc-api_manpage-BackgroundService[`BackgroundService`]
+* if xref:rgsvc.adoc#_rgsvc-spi_manpage-AuditingService[`AuditingService`] is configured, they provide better audit information, since the `Command` (the 'cause' of an action) can be correlated to the audit records (the "effect" of the action) through the unique `transactionId` GUID
+* if xref:rgsvc.adoc#_rgsvc-spi_manpage-PublishingService[`PublishingService`] is configured, they provide better traceability as the `Command` is also correlated with any published events, again through the unique `transactionId` GUID
+
+Assuming that the `CommandService` supports persistent `Command`s, the associated xref:rgant.adoc#_rgant-Action_command[`@Action#command()`] annotation also allows action invocations to be performed in the background. In this case the act of invoking the action on an object instead returns the `Command` to the user.
+
+
+
+[[_rgsvc-api_manpage-CommandContext_screencast]]
+== Screencast
+
+
+The screencast provides a run-through of the command (profiling) service, auditing service, publishing service. It also shows how commands can be run in the background either explicitly by scheduling through the background service or implicitly by way of a framework annotation.
+
+video::tqXUZkPB3EI[youtube,width="640px",height="360px"]
+
+[NOTE]
+====
+Note that this screencast shows an earlier version of the xref:ugvw.adoc#[Wicket viewer] UI (specifically, pre 1.8.0).
+====
+
+
+
+
+== API & Implementation
+
+The `CommandContext` request-scoped service defines the following very simple API:
+
+[source,java]
+----
+@RequestScoped
+public class CommandContext {
+    @Programmatic
+    public Command getCommand() { ... }
+}
+----
+
+This class (`o.a.i.applib.services.CommandContext`) is also the default implementation.  Under normal circumstances there shouldn't be any need to replace this implementation with another.
+
+The `Command` type referenced above is in fact an interface, defined as:
+
+[source,java]
+----
+public interface Command extends HasTransactionId {
+
+    public abstract String getUser();               // <1>
+    public abstract Timestamp getTimestamp();       // <2>
+
+    public abstract Bookmark getTarget();           // <3>
+    public abstract String getMemberIdentifier();   // <4>
+    public abstract String getTargetClass();        // <5>
+    public abstract String getTargetAction();       // <6>
+    public String getArguments();                   // <7>
+    public String getMemento();                     // <8>
+
+    public ExecuteIn getExecuteIn();                // <9>
+    public Executor getExecutor();                  // <10>
+    public Persistence getPersistence();            // <11>
+    public boolean isPersistHint();                 // <12>
+
+    public abstract Timestamp getStartedAt();       // <13>
+    public abstract Timestamp getCompletedAt();     // <14>
+    public Command getParent();                     // <15>
+
+    public Bookmark getResult();                    // <16>
+    public String getException();                   // <17>
+}
+----
+<1> `getUser()` - is the user that initiated the action.
+<2> `getTimestamp()` - the date/time at which this action was created.
+<3> `getTarget()` - bookmark of the target object (entity or service) on which this action was performed
+<4> `getMemberIdentifier()` - holds a string representation of the invoked action
+<5> `getTargetClass()` - a human-friendly description of the class of the target object
+<6> `getTargetAction()` - a human-friendly name of the action invoked on the target object
+<7> `getArguments()` - a human-friendly description of the arguments with which the action was invoked
+<8> `getMemento()` - a formal (XML or similar) specification of the action to invoke/being invoked
+<9> `getExecuteIn()` - whether this command is executed in the foreground or background
+<10> `getExecutor()` - the (current) executor of this command, either user, or background service, or other (eg redirect after post).
+<11> `getPersistence()`- the policy controlling whether this command should ultimately be persisted (either "persisted", "if hinted", or "not persisted")
+<12> `isPersistHint()` - whether that the command should be persisted, if persistence policy is "if hinted".
+<13> `getStartedAt()` - the date/time at which this action started (same as `timestamp` property for foreground commands)
+<14> `getCompletedAt()` - the date/time at which this action completed.
+<15> `getParent()` - for actions created through the `BackgroundService`, captures the parent action
+<16> `getResult()` - bookmark to object returned by action, if any
+<17> `getException()` - exception stack trace if action threw exception
+
+
+
+
+== Usage
+
+The typical way to indicate that an action should be treated as a command is to annotate it with the xref:rgant.adoc#_rgant-Action_command[`@Action#command()`] annotation.
+
+For example:
+
+[source,java]
+----
+public class ToDoItem ... {
+    @Action(command=CommandReification.ENABLED)
+    public ToDoItem completed() { ... }
+}
+----
+
+
+[TIP]
+====
+As an alternative to annotating every action with `@Action#command()`, alternatively this can be configured as the default using `isis.services.command.actions` configuration property.
+
+See xref:rgant.adoc#_rgant-Action_command[`@Action#command()`] and xref:rg.adoc#_rg_runtime_configuring-core[runtime configuration] for further details.
+====
+
+
+The xref:rgant.adoc#_rgant-Action_command[`@Action#command()`] annotation can also be used to specify whether the command should be performed in the background, for example:
+
+[source,java]
+----
+public class ToDoItem ... {
+    @Command(executeIn=ExecuteIn.BACKGROUND)
+    public ToDoItem scheduleImplicitly() {
+        completeSlowly(3000);
+        return this;
+    }
+}
+----
+
+When a background command is invoked, the user is returned the command object itself (to provide a handle to the command being invoked).
+
+This requires that an implementation of xref:rgsvc.adoc#_rgsvc-spi_manpage-CommandService[`CommandService`] that persists the commands (such as the (non-ASF) http://github.com/isisaddons/isis-module-command[Isis addons' command] module's `CommandService`) is configured. It also requires that a scheduler is configured to execute the background commands, see xref:rgsvc.adoc#_rgsvc-spi_manpage-BackgroundCommandService[`BackgroundCommandService`]).
+
+
+
+== Interacting with the services
+
+Typically the domain objects have little need to interact with the `CommandContext` and `Command` directly; what is more useful is that these are persisted in support of the various use cases identified above.
+
+One case however where a domain object might want to obtain the `Command` is to determine whether it has been invoked in the foreground, or in the background. It can do this using the `getExecutedIn()` method:
+
+Although not often needed, this then allows the domain object to access the `Command` object through the `CommandContext` service.  To expand th above example:
+
+
+[source,java]
+----
+public class ToDoItem ... {
+    @Action(
+        command=CommandReification.ENABLED,
+        commandExecuteIn=CommandExecuteIn.BACKGROUND
+    )
+    public ToDoItem completed() {
+        ...
+        Command currentCommand = commandContext.getCommand();
+        ...
+    }
+    @Inject
+    CommandContext commandContext;
+}
+----
+
+
+If run in the background, it might then notify the user (eg by email) if all work is done.
+
+This leads us onto a related point, distinguishing the current effective user vs the originating "real" user. When running in the foreground, the current user can be obtained from the `DomainObjectContainer`, using:
+
+[source,java]
+----
+String user = container.getUser().getName();
+----
+
+If running in the background, however, then the current user will be the credentials of the background process, for example as run by a Quartz scheduler job.
+
+The domain object can still obtain the original ("effective") user that caused the job to be created, using:
+
+[source,java]
+----
+String user = commandContext.getCommand().getUser();
+----
+
+
+
+
+
+== Registering the Services
+
+Assuming that the `configuration-and-annotation` services installer is configured (implicit if using the
+`AppManifest` to xref:rg.adoc#_rg_classes_AppManifest-bootstrapping[bootstrap the app]) then Apache Isis' core
+implementation of `CommandContext` service is automatically registered and injected (it is annotated with
+`@DomainService`) so no further configuration is required.
+
+To use an alternative implementation, use
+xref:rgant.adoc#_rgant-DomainServiceLayout_menuOrder[`@DomainServiceLayout#menuOrder()`] (as explained
+further in this xref:ug.adoc#_ug_how-tos_replacing-default-service-implementations["how to"] tip).
+
+
+
+
+
+== Related Services
+
+As discussed above, the supporting xref:rgsvc.adoc#_rgsvc-spi_manpage-CommandService[`CommandService`] enables `Command` objects to be persisted. Other related services are the xref:rgsvc.adoc#_rgsvc-api_manpage-BackgroundService[`BackgroundService`] and xref:rgsvc.adoc#_rgsvc-spi_manpage-BackgroundCommandService[`BackgroundCommandService`]). For `BackgroundService` captures commands for execution in the background, while the [BackgroundCommandService] persists such commands for execution.
+
+The implementations of `CommandService` and `BackgroundCommandService` are intended to go together, so that persistent parent `Command`s can be associated with their child background `Command`s.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/0d8aeafc/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DeepLinkService.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DeepLinkService.adoc b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DeepLinkService.adoc
new file mode 100644
index 0000000..703250e
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DeepLinkService.adoc
@@ -0,0 +1,56 @@
+[[_rgsvc-api_manpage-DeepLinkService]]
+= `DeepLinkService`
+: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 `DeepLinkService` provides the ability to obtain a `java.net.URI` that links to a representation of any (persisted) domain entity or
+view model.
+
+A typical use case is to generate a clickable link for rendering in an email, PDF, tweet or other communication.
+
+
+
+== API & Implementation
+
+The API defined by `DeepLinkService` is:
+
+[source,java]
+----
+public interface DeepLinkService {
+    URI deepLinkFor(Object domainObject); // <1>
+}
+----
+<1> Creates a URI that can be used to obtain a representation of the provided domain object in one of the Apache Isis viewers.
+
+The xref:ugvw.adoc#[Wicket viewer] this provides an implementation for accessing the representation through this viewer.  (For the xref:ugvro.adoc#[RestfulObjects viewer], a URL can be constructed according to the link:http://www.restfulobjects.org[Restful Objects spec] in conjunction with a `Bookmark` obtained via the xref:rgsvc.adoc#_rgsvc-api_manpage-BookmarkService[`BookmarkService`]).
+
+
+
+== Usage within the framework
+
+The xref:rgsvc.adoc#_rgsvc-spi_manpage-EmailNotificationService[`EmailNotificationService`] uses this service in order to generate emails as part of xref:ugvw.adoc#_ugvw_features_user-registration[user registration].
+
+
+
+== Implementations
+
+The Wicket viewer core framework provides a default implementation of this API:
+
+* `org.apache.isis.viewer.wicket.viewer.services.DeepLinkServiceWicket`
+
+
+
+
+== Registering the Services
+
+Assuming that the `configuration-and-annotation` services installer is configured (implicit if using the
+`AppManifest` to xref:rg.adoc#_rg_classes_AppManifest-bootstrapping[bootstrap the app]), _and_ that the
+xref:ugvw.adoc#[Wicket viewer] is being used, then an implementation of `DeepLinkService` is
+automatically registered and injected (it is annotated with `@DomainService`) so no further configuration is required.
+
+To use an alternative implementation, use
+xref:rgant.adoc#_rgant-DomainServiceLayout_menuOrder[`@DomainServiceLayout#menuOrder()`] (as explained
+further in this xref:ug.adoc#_ug_how-tos_replacing-default-service-implementations["how to"] tip).

http://git-wip-us.apache.org/repos/asf/isis/blob/0d8aeafc/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer.adoc b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer.adoc
new file mode 100644
index 0000000..822beda
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer.adoc
@@ -0,0 +1,40 @@
+[[_rgsvc-api_manpage-DomainObjectContainer]]
+= `DomainObjectContainer`
+: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 `DomainObjectContainer` service provides a set of general purpose functionality for domain objects to call.  Principal amongst these are a generic APIs for querying objects and creating and persisting objects.  In addition, the service provides access to security context (the "current user"), allows information and warning messages to be raised, and various other miscellaneous functions.
+
+[NOTE]
+====
+Compared to other services provided by Apache Isis, the `DomainObjectContainer` provides by far the most number of methods, addressing several quite distinct responsibilities.  This is a historical accident: in early versions of Apache Isis the `DomainObjectContainer` was the one and only domain service provided by the framework.
+
+In the future we may deprecate this service and break out its responsibilities into a number of small services.  However, given how important this service was in days past, we are unlikely to delete it as a service even once it has been deprecated.
+====
+
+The sections below discuss the functions provided by the service, broken out into categories.
+
+
+include::_rgsvc-api_manpage-DomainObjectContainer_object-creation-api.adoc[leveloffset=+1]
+include::_rgsvc-api_manpage-DomainObjectContainer_generic-repository-api.adoc[leveloffset=+1]
+include::_rgsvc-api_manpage-DomainObjectContainer_object-persistence-api.adoc[leveloffset=+1]
+include::_rgsvc-api_manpage-DomainObjectContainer_messages-api.adoc[leveloffset=+1]
+include::_rgsvc-api_manpage-DomainObjectContainer_security-api.adoc[leveloffset=+1]
+include::_rgsvc-api_manpage-DomainObjectContainer_presentation-api.adoc[leveloffset=+1]
+include::_rgsvc-api_manpage-DomainObjectContainer_validation-api.adoc[leveloffset=+1]
+include::_rgsvc-api_manpage-DomainObjectContainer_properties-api.adoc[leveloffset=+1]
+include::_rgsvc-api_manpage-DomainObjectContainer_services-api.adoc[leveloffset=+1]
+
+
+
+
+
+== Registering the Service
+
+Assuming that the `configuration-and-annotation` services installer is configured (implicit if using the
+`AppManifest` to xref:rg.adoc#_rg_classes_AppManifest-bootstrapping[bootstrap the app]) then Apache Isis' core
+implementation of `DomainObjectContainer` service is automatically registered and injected (it is annotated with
+`@DomainService`) so no further configuration is required.
+

http://git-wip-us.apache.org/repos/asf/isis/blob/0d8aeafc/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_generic-repository-api.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_generic-repository-api.adoc b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_generic-repository-api.adoc
new file mode 100644
index 0000000..72daf8f
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_generic-repository-api.adoc
@@ -0,0 +1,89 @@
+[[_rgsvc-api_manpage-DomainObjectContainer_generic-repository-api]]
+= Generic Repository API
+: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 repository API acts as an abstraction over the JDO/DataNucleus objectstore.  You can use it during prototyping to write naive queries (find all rows, then filter using the Guava `Predicate` API, or you can use it to call JDO link:http://www.datanucleus.org/products/accessplatform_4_0/jdo/query.html#named[named queries] using JDOQL.
+
+As an alternative, you could also use link:http://www.datanucleus.org/products/accessplatform_4_0/jdo/jdoql_typesafe.html[JDO typesafe queries] through the xref:rgsvc.adoc#_rgsvc-api_manpage-IsisJdoSupport[`IsisJdoSupport`] service.
+
+
+[source,java]
+----
+public interface DomainObjectContainer {
+    @Programmatic
+    public <T> List<T> allInstances(Class<T> ofType, long... range);                        // <1>
+    @Programmatic
+    <T> List<T> allMatches(Query<T> query);                                                 // <2>
+    @Programmatic
+    <T> List<T> allMatches(Class<T> ofType, Predicate<? super T> predicate, long... range); // <3>
+    @Programmatic
+    <T> List<T> allMatches(Class<T> ofType, String title, long... range);                   // <4>
+    @Programmatic
+    <T> List<T> allMatches(Class<T> ofType, T pattern, long... range);                      // <5>
+    ...
+}
+----
+<1> all persisted instances of specified type.  Mostly for prototyping, though can be useful to obtain all instances of domain entities if the number is known to be small.  The optional varargs parameters are for paging control; more on this below.
+<2> all persistence instances matching the specified `Query`.  Query itself is an Isis abstraction on top of JDO/DataNucleus' Query API.  *This is the primary API used for querying*
+<3> all persistenced instances of specified type matching `Predicate`.  Only really intended for prototyping because in effect constitutes a client-side WHERE clause
+<4> all persisted instances with the specified string as their title.  Only very occasionally used
+<5> all persisted instances matching object (query-by-example).  Only very occasionally used
+
+There are various implementations of the `Query` API, but these either duplicate functionality of the other overloads of `allMatches(...)` or they are not supported by the JDO/DataNucleus object store.   The only significant implementation of `Query` to be aware of is `QueryDefault`, which identifies a named query and a set of parameter/argument tuples.
+
+For example, in the (non-ASF) http://github.com/isisaddons/isis-app-todoapp[Isis addons' todoapp] the `ToDoItem` is annotated:
+
+[source,java]
+----
+@javax.jdo.annotations.Queries( {
+    @javax.jdo.annotations.Query(
+            name = "findByAtPathAndComplete", language = "JDOQL",               // <1>
+            value = "SELECT "
+                    + "FROM todoapp.dom.module.todoitem.ToDoItem "
+                    + "WHERE atPath.indexOf(:atPath) == 0 "                     // <2>
+                    + "   && complete == :complete"),                           // <3>
+    ...
+})
+public class ToDoItem ... {
+    ...
+}
+----
+<1> name of the query
+<2> defines the `atPath` parameter
+<3> defines the `complete` parameter
+
+This JDO query definitions are used in the `ToDoItemRepositoryImplUsingJdoql` service:
+
+[source,java]
+----
+@DomainService(nature = NatureOfService.DOMAIN)
+public class ToDoItemRepositoryImplUsingJdoql implements ToDoItemRepositoryImpl {
+    @Programmatic
+    public List<ToDoItem> findByAtPathAndCategory(final String atPath, final Category category) {
+        return container.allMatches(
+                new QueryDefault<>(ToDoItem.class,
+                        "findByAtPathAndCategory",                              // <1>
+                        "atPath", atPath,                                       // <2>
+                        "category", category));                                 // <3>
+    }
+    ...
+    @javax.inject.Inject
+    DomainObjectContainer container;
+}
+----
+<1> corresponds to the "findByAtPathAndCategory" JDO named query
+<2> provide argument for the `atPath` parameter.  The pattern is parameter, argument, parameter, argument, ... and so on.
+<3> provide argument for the `category` parameter.  The pattern is parameter, argument, parameter, argument, ... and so on.
+
+Other JDOQL named queries (not shown) follow the exact same pattern.
+
+With respect to the other query APIs, the varargs parameters are optional, but allow for (client-side and managed) paging.  The first parameter is the `start` (0-based, the second is the `count`.
+
+[TIP]
+====
+It is also possible to query using DataNucleus' type-safe query API.  For more details, see xref:rgsvc.adoc#_rgsvc-api_manpage-IsisJdoSupport[`IsisJdoSupport`].
+====

http://git-wip-us.apache.org/repos/asf/isis/blob/0d8aeafc/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_messages-api.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_messages-api.adoc b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_messages-api.adoc
new file mode 100644
index 0000000..19b0924
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_messages-api.adoc
@@ -0,0 +1,50 @@
+[[_rgsvc-api_manpage-DomainObjectContainer_messages-api]]
+= Messages API
+: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 `DomainObjectContainer` allows domain objects to raise information, warning or error messages.  These messages can either be simple strings, or can be translated.
+
+[source,java]
+----
+public interface DomainObjectContainer {
+    @Programmatic
+    void informUser(String message);                                                            // <1>
+    @Programmatic
+    String informUser(TranslatableString message, Class<?> contextClass, String contextMethod); // <2>
+
+    @Programmatic
+    void warnUser(String message);                                                              // <3>
+    @Programmatic
+    String warnUser(TranslatableString message, Class<?> contextClass, String contextMethod);   // <4>
+
+    @Programmatic
+    void raiseError(String message);                                                            // <5>
+    @Programmatic
+    String raiseError(TranslatableString message, Class<?> contextClass, String contextMethod); // <6>
+    ...
+}
+----
+<1> display as a transient message to the user (not requiring acknowledgement).  In the xref:ugvw.adoc#[Wicket viewer] this is implemented as a toast that automatically disappears after a period of time.
+<2> ditto, but with translatable string, for xref:ugbtb.adoc#_ugbtb_more-advanced_i18n[i18n support].
+<3> warn the user about a situation with the specified message.  In the xref:ugvw.adoc#[Wicket viewer] this is implemented as a toast that must be closed by the end-user.
+<4> ditto, but with translatable string, for i18n support.
+<5> show the user an unexpected application error.  In the xref:ugvw.adoc#[Wicket viewer] this is implemented as a toast (with a different colour) that must be closed by the end-user.
+<6> ditto, but with translatable string, for i18n support.
+
+
+For example:
+
+[source,java]
+----
+public Order addItem(Product product, @ParameterLayout(named="Quantity) int quantity) {
+    if(productRepository.stockLevel(product) == 0) {
+        container.warnUser(
+            product.getDescription() + " out of stock; order fulfillment may be delayed");
+    }
+    ...
+}
+----

http://git-wip-us.apache.org/repos/asf/isis/blob/0d8aeafc/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_object-creation-api.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_object-creation-api.adoc b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_object-creation-api.adoc
new file mode 100644
index 0000000..86f4a02
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_object-creation-api.adoc
@@ -0,0 +1,49 @@
+[[_rgsvc-api_manpage-DomainObjectContainer_object-creation-api]]
+= Object Creation API
+: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 object creation APIs are used to instantiate new domain objects or view models.
+
+[source,java]
+----
+public interface DomainObjectContainer {
+    @Programmatic
+    <T> T newTransientInstance(final Class<T> ofType);                              // <1>
+    @Programmatic
+    <T> T newViewModelInstance(final Class<T> ofType, final String memento);        // <2>
+    @Programmatic
+    <T> T mixin();                                                                  // <3>
+    ...
+}
+----
+<1> create a new non-persisted domain entity.  Any services will be automatically injected into the service
+<2> create a new view model, with the specified memento (as per xref:rg.adoc#_rg_classes_super_manpage-AbstractViewModel[ViewModel#viewModelMemento()].  In general it is easier to just annotate with xref:rgant.adoc#_rgant-ViewModel[`@ViewModel`] and let Apache Isis manage the memento automatically.
+<3> programmatically instantiate a mixin, as annotated with
+xref:rgant.adoc#_rgant-Mixin[`@Mixin`] or xref:rgant.adoc#_rgant-DomainObject_nature[`@DomainObject#nature()`].
+
+For example:
+
+[source,java]
+----
+Customer cust = container.newTransientInstance(Customer.class);
+cust.setFirstName("Freddie");
+cust.setLastName("Mercury");
+container.persist(cust);
+----
+
+As an alternative to using `newTransientInstance(...)` or `mixin(...)`, you could also simply `new()` up the object.
+Doing this will not inject any domain services, but they can be injected manually using xref:rg .adoc#_rgsvc-api_manpage-DomainObjectContainer_services-api[#injectServicesInto(...)`].
+
+[NOTE]
+====
+Calling `new(...)` also this circumvents Apache Isis' xref:rg.adoc#_rg_methods_reserved_manpage-created[`created()`]
+callback, and in addition any default values for properties (either explicitly set by
+xref:rg.adoc#_rg_methods_prefixes_manpage-default[`default...()`] or defaulted implicitly according to Apache Isis'
+own conventions) will not be called either.  If you don't intend to use these features, though, the net effect is code
+that has less coupling to Isis and is arguably easier to understand (has "less magic" happening).
+====
+

http://git-wip-us.apache.org/repos/asf/isis/blob/0d8aeafc/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_object-persistence-api.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_object-persistence-api.adoc b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_object-persistence-api.adoc
new file mode 100644
index 0000000..5bc40f8
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_object-persistence-api.adoc
@@ -0,0 +1,62 @@
+[[_rgsvc-api_manpage-DomainObjectContainer_object-persistence-api]]
+= Object Persistence API
+: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 persistence API is used to persist newly created objects (as per xref:rgsvc.adoc#_rgsvc-api_manpage-DomainObjectContainer_object-creation-api[`#newTransientInstance(...)`], above and to delete (remove) objects that are persistent.
+
+Note that there is no API for updating existing objects; the framework (or rather, JDO/DataNucleus) performs object dirty tracking and so any objects that are modified in the course of a request will be automatically updated).
+
+
+[source,java]
+----
+public interface DomainObjectContainer {
+    @Programmatic
+    boolean isPersistent(Object domainObject);          // <1>
+    @Programmatic
+    boolean isViewModel(Object domainObject);           // <2>
+
+    @Programmatic
+    void persist(Object domainObject);                  // <3>
+    @Programmatic
+    void persistIfNotAlready(Object domainObject);      // <4>
+
+    @Programmatic
+    void remove(Object persistentDomainObject);         // <5>
+    @Programmatic
+    void removeIfNotAlready(Object domainObject);       // <6>
+
+    @Programmatic
+    boolean flush();                                    // <7>
+    ...
+}
+----
+<1> test whether a particular domain object is persistent or not
+<2> test whether a particular domain object is a view model or not.  Note that this includes any domain objects annotated with xref:rgant.adoc#_rgant-DomainObject_nature[`@DomainObject#nature=Nature.EXTERNAL_ENTITY)`] or xref:rgant.adoc#_rgant-DomainObject_nature[`@DomainObject#nature=Nature.INMEMORY_ENTITY`]
+<3> persist a transient object.  Note though that this will throw an exception if the object is already persistent; this can happen if JDO/DataNucleus's link:http://www.datanucleus.org/products/accessplatform_4_0/jdo/orm/cascading.html[persistence-by-reachability] is in effect.  For this reason it is generally better to use:
+<4> persist an object but only if know to not have been persistent.  But if the object is persistent, is a no-op
+<5> remove (ie DELETE) a persistent object.  For similar reasons to the persistence, it is generally better to use:
+<6> remove (ie DELETE) an object only if known to be persistent.  But if the object has already been deleted, then is a no-op.
+<7> flushes all pending changes to the objectstore.  Explained further below.
+
+For example:
+
+[source,java]
+----
+Customer cust = container.newTransientInstance(Customer.class);
+cust.setFirstName("Freddie");
+cust.setLastName("Mercury");
+container.persistIfNotAlready(cust);
+----
+
+You should be aware that by default Apache Isis queues up calls to `#persist()` and `#remove()`.  These are then executed either when the request completes (and the transaction commits), or if the queue is flushed.  This can be done either implicitly by the framework, or as the result of a direct call to `#flush()`.
+
+By default the framework itself will cause `#flush()` to be called whenever a query is executed by way of `#allMatches(Query)`, as documented xref:rgsvc.adoc#_rgsvc-api_manpage-DomainObjectContainer_generic-repository-api[above].  However, this behaviour can be disabled using the  xref:rg.adoc#_rg_runtime_configuring-core[configuration property] `isis.services.container.disableAutoFlush`.
+
+
+

http://git-wip-us.apache.org/repos/asf/isis/blob/0d8aeafc/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_presentation-api.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_presentation-api.adoc b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_presentation-api.adoc
new file mode 100644
index 0000000..6126de5
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_presentation-api.adoc
@@ -0,0 +1,46 @@
+[[_rgsvc-api_manpage-DomainObjectContainer_presentation-api]]
+= Presentation API
+: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 responsibility of every domain object is to return a title.  This can be done declaratively using the xref:rgant.adoc#_rgant-Title[`@Title`] annotation on property/ies, or it can be done imperatively by writing a xref:rg.adoc#_rg_methods_reserved_manpage-title[`title()`] method.
+
+It's quite common for titles to be built up of the titles of other objects.  If using building up the title using `@Title` then Apache Isis will automatically use the title of the objects referenced by the annotated properties.  We also need programmatic access to these titles if going the imperative route.
+
+Similarly, it often makes sense if xref:rgsvc.adoc#_rgsvc-api_manpage-DomainObjectContainer_messages-api[raising messages] to use the title of an object in a message rather (than a some other property of the object), because this is how end-users will be used to identifying the object.
+
+The API defined by `DomainObjectContainer` is simply:
+
+[source,java]
+----
+public interface DomainObjectContainer {
+    @Programmatic
+    String titleOf(Object domainObject);                // <1>
+    ...
+}
+----
+<1> return the title of the object, as rendered in the UI by the Apache Isis viewers.
+
+
+By way of example, here's some code from the (non-ASF) http://github.com/isisaddons/isis-app-todoapp[Isis addons' todoapp] showing the use of the API in an message:
+
+[source,java]
+----
+    public List<ToDoItem> delete() {
+        final String title = container.titleOf(this);   // <1>
+        ...
+        container.removeIfNotAlready(this);
+        container.informUser(
+                TranslatableString.tr(
+                    "Deleted {title}", "title", title), // <2>
+                    this.getClass(), "delete");
+        ...
+    }
+
+----
+<1> the title is obtained first, because we're not allowed to reference object after it's been deleted
+<2> use the title in an i18n `TranslatableString`

http://git-wip-us.apache.org/repos/asf/isis/blob/0d8aeafc/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_properties-api.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_properties-api.adoc b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_properties-api.adoc
new file mode 100644
index 0000000..517412c
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_properties-api.adoc
@@ -0,0 +1,54 @@
+[[_rgsvc-api_manpage-DomainObjectContainer_properties-api]]
+: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/
+
+
+
+
+
+= Properties API
+
+The properties API allows domain objects to read the configuration properties aggregated from the various xref:rg.adoc#_rg_runtime_configuration-files[configuration files].
+
+[source,java]
+----
+public interface DomainObjectContainer {
+    @Programmatic
+    String getProperty(String name);                        // <1>
+    @Programmatic
+    String getProperty(String name, String defaultValue);   // <2>
+    @Programmatic
+    List<String> getPropertyNames();                        // <3>
+}
+----
+<1> Return the configuration property with the specified name; else return null.
+<2> Return the configuration property with the specified name; if it doesn't exist then return the specified default value.
+<3> Return the names of all the available properties.
+
+For example, here's a fictitious service that might wrap link:http://twitter4j.org/en/configuration.html[Twitter4J]. say:
+
+[source,java]
+----
+@DomainService(nature=NatureOfService.DOMAIN)
+public class TweetService {
+    @Programmatic
+    @PostConstruct
+    public void init() {
+        this.oauthConsumerKey = container.getProperty("tweetservice.oauth.consumerKey");
+        this.oauthConsumerSecret = container.getProperty("tweetservice.oauth.consumerSecret");
+        this.oauthAccessToken = container.getProperty("tweetservice.oauth.accessToken");
+        this.oauthAccessTokenSecret = container.getProperty("tweetservice.oauth.accessTokenSecret");
+    }
+    ...
+    @Inject
+    DomainObjectContainer container;
+}
+----
+
+[TIP]
+====
+If you _do_ have a domain service that needs to access properties, then note that an alternative is to define a xref:rgant.adoc#_rgant-PostConstruct[`@PostConstruct`] method and pass in a `Map<String,String>` of properties.  The two techniques are almost identical; it's mostly a matter of taste.
+====
+
+

http://git-wip-us.apache.org/repos/asf/isis/blob/0d8aeafc/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_security-api.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_security-api.adoc b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_security-api.adoc
new file mode 100644
index 0000000..e8887f3
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_security-api.adoc
@@ -0,0 +1,48 @@
+[[_rgsvc-api_manpage-DomainObjectContainer_security-api]]
+= Security API
+: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 security API allows the domain object to obtain the identity of the user interacting with said object.
+
+[source,java]
+----
+public interface DomainObjectContainer {
+    @Programmatic
+    UserMemento getUser();
+    ...
+}
+----
+
+where in turn (the essence of) `UserMemento` is:
+
+[source,java]
+----
+public final class UserMemento {
+    public String getName() { ... }
+    public boolean isCurrentUser(final String userName) { ... }
+
+    public List<RoleMemento> getRoles() { ... }
+    public boolean hasRole(final RoleMemento role) { ... }
+    public boolean hasRole(final String roleName) { ... }
+    ...
+}
+----
+
+and `RoleMemento` is simpler still:
+
+[source,java]
+----
+public final class RoleMemento {
+    public String getName() { ... }
+    public String getDescription() { ... }
+    ...
+}
+----
+
+The roles associated with the `UserMemento` will be based on the configured xref:ugsec.adoc#[security] (typically Shiro).
+
+In addition, when using the xref:ugvw.adoc#[Wicket viewer] there will be an additional "org.apache.isis.viewer.wicket.roles.USER" role; this is used internally to restrict access to web pages without authenticating.

http://git-wip-us.apache.org/repos/asf/isis/blob/0d8aeafc/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_services-api.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_services-api.adoc b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_services-api.adoc
new file mode 100644
index 0000000..4ccc9c3
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_services-api.adoc
@@ -0,0 +1,37 @@
+[[_rgsvc-api_manpage-DomainObjectContainer_services-api]]
+= Services API
+: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 services API allows your domain objects to programmatically inject services into arbitrary objects, as well as to look up services by type:
+
+[source,java]
+----
+public interface DomainObjectContainer {
+    @Programmatic
+    <T> T injectServicesInto(final T domainObject);     // <1>
+    @Programmatic
+    <T> T lookupService(Class<T> service);              // <2>
+    @Programmatic
+    <T> Iterable<T> lookupServices(Class<T> service);   // <3>
+    ...
+}
+----
+<1> injects services into domain object; used extensively internally by the framework (eg to inject to other services, or to entities, or integration test instances, or fixture scripts).  Service injection is done automatically if objects are created using `#newTransientInstance()`, described xref:rgsvc.adoc#_rgsvc-api_manpage-DomainObjectContainer_object-creation-api[above]
+<2> returns the first registered service that implements the specified class
+<3> returns an `Iterable` in order to iterate over all registered services that implement the specified class
+
+The primary use case is to instantiate domain objects using a regular constructor ("new is the new new") rather than using the xref:rgsvc.adoc#_rgsvc-api_manpage-DomainObjectContainer_object-creation-api[`#newTransientInstance()`] API, and then using the `#injectServicesInto(...)` API to set up any dependencies.
+
+For example:
+
+[source,java]
+----
+Customer cust = container.injectServicesInto( new Customer());
+cust.setFirstName("Freddie");
+cust.setLastName("Mercury");
+container.persist(cust);
+----
+

http://git-wip-us.apache.org/repos/asf/isis/blob/0d8aeafc/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_validation-api.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_validation-api.adoc b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_validation-api.adoc
new file mode 100644
index 0000000..b6ad616
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-DomainObjectContainer_validation-api.adoc
@@ -0,0 +1,26 @@
+[[_rgsvc-api_manpage-DomainObjectContainer_validation-api]]
+= Validation API
+: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 validation API allows a domain object to programmatically validate itself or any other domain object.  Specifically, this means the validating the current state of all properties, as well as any object-level validation defined by xref:rg.adoc#_rg_methods_reserved_manpage-validate[`validate()`].
+
+The API provided is:
+
+[source,java]
+----
+public interface DomainObjectContainer {
+    @Programmatic
+    boolean isValid(Object domainObject);
+    @Programmatic
+    String validate(Object domainObject);
+    ...
+}
+----
+
+If an object is changed by editing its properties, then (using the xref:ugvw.adoc#[Wicket viewer] at least) Apache Isis will check that the state of the object is valid.  There is currently however no equivalent guarantee for actions.
+
+The intent of this API was (originally at least) to provide a fallback whereby actions could at least be able to perform this validation programmatically (eg in their own xref:rg.adoc#_rg_methods_prefixes_manpage-validate[`validate...()`] or xref:rg.adoc#_rg_methods_prefixes_manpage-disable[`disable...()`] methods.  However, this feature should be considered experimental; your mileage may vary.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/0d8aeafc/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-EmailService.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-EmailService.adoc b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-EmailService.adoc
new file mode 100644
index 0000000..3a7cef9
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgsvc-api_manpage-EmailService.adoc
@@ -0,0 +1,95 @@
+[[_rgsvc-api_manpage-EmailService]]
+= `EmailService`
+: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 `EmailService` provides the ability to send HTML emails, with attachments, to one or more recipients.
+
+Apache Isis provides a default implementation to send emails using an external SMTP provider.  Note that this must be configured (using a number of configuration properties) before it can be used.  The that sends email as an HTML message, using an external SMTP provider.
+
+
+
+== API & Implementation
+
+The API for the service is:
+
+[source,java]
+----
+public interface EmailService {
+    @Programmatic
+    boolean send(                                                   // <1>
+        List<String> to, List<String> cc, List<String> bcc,         // <2>
+        String subject,
+        String body,                                                // <3>
+        DataSource... attachments);
+    @Programmatic
+    boolean isConfigured();                                         // <4>
+  }
+----
+<1> is the main API to send the email (and optional attachments). Will return `false` if failed to send
+<2> pass either `null` or `Collections.emptyList()` if not required
+<3> should be HTML text
+<4> indicates whether the implementation was configured and initialized correctly.  If this returns `false` then any attempt to call `send(...)` will fail.
+
+As noted in the introduction, the core framework provides a default implementation (`EmailServiceDefault`) that sends email as an HTML message, using an external SMTP provider.
+
+
+
+== Configuration
+
+To use this service the following properties must be configured:
+
+* `isis.service.email.sender.address`
+* `isis.service.email.sender.password`
+
+and these properties may optionally be configured (each has a default to use gmail, documented xref:rg.adoc#_rg_runtime_configuring-core[here]):
+
+* `isis.service.email.sender.hostname`
+* `isis.service.email.port`
+* `isis.service.email.tls.enabled`
+
+These configuration properties can be specified either in `isis.properties` or in an xref:ugbtb.adoc#_ugbtb_deployment_externalized-configuration[external configuration file].
+
+If prototyping (that is, running the app using `org.apache.isis.WebServer`), the configuration properties can also be specified as system properties. For example, if you create a test email account on gmail, you can configure the service using:
+
+[source,ini]
+----
+-Disis.service.email.sender.address=xxx@gmail.com -Disis.service.email.sender.password=yyy
+----
+
+where "xxx" is the gmail user account and "yyy" is its password
+
+
+
+
+== Alternative Implementations
+
+If you wish to write an alternative implementation, be aware that it should process the message body as HTML (as opposed to plain text or any other format).
+
+Also, note that (unlike most Apache Isis domain services) the implementation is also instantiated and injected by Google Guice. This is because `EmailService` is used as part of the xref:ugvw.adoc#_ugvw_features_user-registration[user registration] functionality and is used by Wicket pages that are accessed outside of the usual Apache Isis runtime. This implies a couple of additional constraints:
+
+* first, implementation class should also be annotated with `@com.google.inject.Singleton`
+* second, there may not be any Apache Isis session running. (If necessary, one can be created on the fly using `IsisContext.doInSession(...)`)
+
+To ensure that your alternative implementation takes the place of the default implementation, register it explicitly in `isis.properties`.
+
+
+
+== Registering the Services
+
+Assuming that the `configuration-and-annotation` services installer is configured (implicit if using the
+`AppManifest` to xref:rg.adoc#_rg_classes_AppManifest-bootstrapping[bootstrap the app]) then Apache Isis' core
+implementation of `EmailService` service is automatically registered and injected (it is annotated with
+`@DomainService`) so no further configuration is required.
+
+To use an alternative implementation, use
+xref:rgant.adoc#_rgant-DomainServiceLayout_menuOrder[`@DomainServiceLayout#menuOrder()`] (as explained
+further in this xref:ug.adoc#_ug_how-tos_replacing-default-service-implementations["how to"] tip).
+
+
+== Related Services
+
+The email service is used by the xref:rgsvc.adoc#_rgsvc-spi_manpage-EmailNotificationService[`EmailNotificationService`] which is, in turn, used by xref:rgsvc.adoc#_rgsvc-spi_manpage-UserRegistrationService[`UserRegistrationService`].
\ No newline at end of file