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 2017/05/12 10:25:58 UTC

[09/18] isis git commit: ISIS-1594: updates domain service .adoc names and ids, so that the edit buttons are added correctly to subdocuments. Also some further minor improvements on scrolling.

http://git-wip-us.apache.org/repos/asf/isis/blob/20b83ae7/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_core-domain-api_EventBusService.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_core-domain-api_EventBusService.adoc b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_core-domain-api_EventBusService.adoc
new file mode 100644
index 0000000..a6244df
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_core-domain-api_EventBusService.adoc
@@ -0,0 +1,405 @@
+[[_rgsvc_core-domain-api_EventBusService]]
+= `EventBusService`
+: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 `EventBusService` allows domain objects to emit events to subscribing domain services using an in-memory event bus.
+
+The primary user of the service is the framework itself, which automatically emit events for xref:../rgant/rgant.adoc#_rgant-Action_domainEvent[actions], xref:../rgant/rgant.adoc#_rgant-Property_domainEvent[properties] and xref:../rgant/rgant.adoc#_rgant-Collection_domainEvent[collections].  Multiple events are generated:
+
+* when an object member is to be viewed, an event is fired; subscribers can veto (meaning that the member is hidden)
+* when an object member is to be enabled, the same event instance is fired; subscribers can veto (meaning that the member is disabled, ie cannot be edited/invoked)
+* when an object member is being validated, then a new event instance is fired; subscribers can veto (meaning that the candidate values/action arguments are rejected)
+* when an object member is about to be changed, then the same event instance is fired; subscribers can perform pre-execution operations
+* when an object member has been changed, then the same event instance is fired; subscribers can perform post-execution operations
+
+If a subscriber throws an exception in the first three steps, then the interaction is vetoed. If a subscriber throws an exception in the last two steps, then the transaction is aborted.  For more on this topic, see xref:../rgant/rgant.adoc#_rgant-Action_domainEvent[`@Action#domainEvent()`], xref:../rgant/rgant.adoc#_rgant-Property_domainEvent[`@Property#domainEvent()`] and xref:../rgant/rgant.adoc#_rgant-Collection_domainEvent[`@Collection#domainEvent()`].
+
+It is also possible for domain objects to programmatically generate domain events.  However the events are published, the primary use case is to decoupling interactions from one module/package/namespace and another.
+
+Two implementations are available, using either link:https://code.google.com/p/guava-libraries/[Guava]'s https://code.google.com/p/guava-libraries/wiki/EventBusExplained[`EventBus`], or alternatively using the link:http://www.axonframework.org/[AxonFramework]'s link:http://www.axonframework.org/docs/2.4/single.html#d5e1489[SimpleEventBus].  It is also possible to plug in a custom implementation.
+
+
+
+[[__rgsvc_core-domain-api_EventBusService_api-and-implementation]]
+== API & Implementation
+
+The API defined by `EventBusService` is:
+
+[source,java]
+----
+public abstract class EventBusService {
+    @Programmatic
+    public void post(Object event) { ... }                          // <1>
+    @Programmatic
+    public void register(final Object domainService) { ... }        // <2>
+    @Programmatic
+    public void unregister(final Object domainService) { ... }      // <3>
+}
+----
+<1> posts the event onto event bus
+<2> allows domain services to register themselves.  This should be done in their xref:../rgant/rgant.adoc#_rgant-PostConstruct[`@PostConstruct`] initialization method (for both singleton and xref:../rgant/rgant.adoc#_rgant-RequestScoped[`@RequestScoped`] domain services.
+<3> exists for symmetry, but need never be called (it is in fact deliberately a no-op).
+
+Isis provides a default implementation of the service, `o.a.i.objectstore.jdo.datanucleus.service.eventbus.EventBusServiceJdo`.
+
+
+
+
+
+== Registering Subscribers
+
+The `register()` method should be called in the xref:../rgant/rgant.adoc#_rgant-PostConstruct[`@PostConstruct`] lifecycle method.  It is valid and probably the least confusing to readers to also "unregister" in the xref:../rgant/rgant.adoc#_rgant-PreDestroy[`@PreDestroy`] lifecycle method (though as noted xref:../rgsvc/rgsvc.adoc#__rgsvc_core-domain-api_EventBusService_api-and-implementation[above], unregistering is actually a no-op).
+
+For example:
+
+[source,java]
+----
+@DomainService(nature=NatureOfService.DOMAIN)   // <1>
+@DomainServiceLayout( menuOrder="1")            // <2>
+public class MySubscribingDomainService {
+    @PostConstruct
+    public void postConstruct() {
+        eventBusService.register(this);         // <3>
+    }
+    @PreDestroy
+    public void preDestroy() {
+        eventBusService.unregister(this);       // <4>
+    }
+    ...
+    @javax.inject.Inject
+    EventBusService eventBusService;
+}
+----
+<1> subscribers are typically not visible in the UI, so specify a `DOMAIN` nature
+<2> It's important that subscribers register before any domain services that might emit events on the event bus service.
+For example, the (non-ASF) http://github.com/isisaddons/isis-module-security[Isis addons' security] module provides a
+domain service that automatically seeds certain domain entities; these will generate
+xref:../rgcms/rgcms.adoc#_rgcms_classes_lifecycleevent[lifecycle events] and so any subscribers must be registered before such seed
+services.  The easiest way to do this is to use the xref:../rgant/rgant.adoc#_rgant-DomainServiceLayout_menuOrder[`@DomainServiceLayout#menuOrder()`] attribute.
+<3> register with the event bus service during xref:../rgant/rgant.adoc#_rgant-PostConstruct[`@PostConstruct`]
+    initialization
+<4> corresponding deregister when shutting down
+
+This works for both singleton (application-scoped) and also xref:../rgant/rgant.adoc#_rgant-RequestScoped[`@RequestScoped`] domain services.
+
+
+[TIP]
+====
+The xref:../rgcms/rgcms.adoc#_rgcms_classes_super_AbstractSubscriber[`AbstractSubscriber`] class automatically performs this
+registration.  As a convenience, it is also annotated with the
+xref:../rgant/rgant.adoc#_rgant-DomainServiceLayout_menuOrder[`@DomainServiceLayout#menuOrder()`] attribute.
+====
+
+
+
+== Annotating Members
+
+As discussed in the introduction, the framework will automatically emit domain events for all of the object members (actions, properties or collections) of an object whenever that object is rendered or (more generally) interacted with.
+
+For example:
+
+[source,java]
+----
+public class Customer {
+    @Action
+    public Customer placeOrder(Product product, @ParameterLayout(named="Quantity") int qty) { ... }
+    ...
+}
+----
+
+will propagate an instance of the default `o.a.i.applib.services.eventbus.ActionDomainEvent.Default` class.   If using the Guava event bus this can be subscribed to using:
+
+[source,java]
+----
+@DomainService(nature=NatureOfService.DOMAIN)
+public class MySubscribingDomainService
+    @Programmatic
+    @com.google.common.eventbus.Subscribe
+    public void on(ActionDomainEvent ev) { ... }
+    ...
+}
+----
+
+or if using Axonframework, the subscriber uses a different annotation:
+
+[source,java]
+----
+@DomainService(nature=NatureOfService.DOMAIN)
+public class MySubscribingDomainService
+    @Programmatic
+    @org.axonframework.eventhandling.annotation.EventHandler
+    public void on(ActionDomainEvent ev) { ... }
+    ...
+}
+----
+
+More commonly though you will probably want to emit domain events of a specific subtype.  As a slightly more interesting example, suppose in a library domain that a `LibraryMember` wants to leave the library. A letter should be sent out detailing any books that they still have out on loan:
+
+In the `LibraryMember` class, we publish the event by way of an annotation:
+
+[source,java]
+----
+public class LibraryMember {
+    @Action(domainEvent=LibraryMemberLeaveEvent.class)  // <1>
+    public void leave() { ... }
+    ...
+}
+----
+<1> `LibraryMemberLeaveEvent` is a subclass of `o.a.i.applib.eventbus.ActionDomainEvent`.  The topic of subclassing is discussed in more detail xref:../rgsvc/rgsvc.adoc#__rgsvc_core-domain-api_EventBusService_event-hierarchy[below].
+
+Meanwhile, in the `BookRepository` domain service, we subscribe to the event and act upon it.  For example:
+
+[source,java]
+----
+public class BookRepository {
+    @Programmatic
+    @com.google.common.eventbus.Subscribe
+    public void onLibraryMemberLeaving(LibraryMemberLeaveEvent e) {
+        LibraryMember lm = e.getLibraryMember();
+        List<Book> lentBooks = findBooksOnLoanFor(lm);
+        if(!lentBooks.isEmpty()) {
+            sendLetter(lm, lentBooks);
+        }
+    }
+    ...
+}
+----
+
+This design allows the `libraryMember` module to be decoupled from the `book` module.
+
+
+
+[[__rgsvc_core-domain-api_EventBusService_event-hierarchy]]
+== Event hierarchy
+
+By creating domain event subtypes we can be more semantically precise and in turn providesmore flexibility for subscribers: they can choose whether to be broadly applicable (by subscribing to a superclass) or to be tightly focussed (by subscribing to a subclass).
+
+We recommend that you define event classes at (up to) four scopes:
+
+* at the top "global" scope is the Apache Isis-defined `o.a.i.applib.event.ActionDomainEvent`
+* for the "module" scope, create a static class to represent the module itself, and creating nested classes within
+* for each "class" scope, create a nested static event class in the domain object's class for all of the domain object's actions
+* for each "action" scope, create a nested static event class for that action, inheriting from the "domain object" class.
+
+To put all that into code; at the module level we can define:
+
+[source,java]
+----
+package com.mycompany.modules.libmem;
+...
+public static class LibMemModule {
+    private LibMemModule() {}
+    public abstract static class ActionDomainEvent<S>
+                extends org.apache.isis.applib.event.ActionDomainEvent<S> {}
+    ...                                                                             // <1>
+    public abstract static class PropertyDomainEvent<S,T>
+                extends org.apache.isis.applib.event.PropertyDomainEvent<S,T> {}
+    public abstract static class CollectionDomainEvent<S,E>
+                extends org.apache.isis.applib.event.CollectionDomainEvent<S,E> {}
+}
+----
+<1> similar events for properties and collections should also be defined
+
+For the class-level we can define:
+
+[source,java]
+----
+public static class LibraryMember {
+    public abstract static class ActionDomainEvent
+            extends LibMemModule.ActionDomainEvent<LibraryMember> { }
+    ...                                                                             // <1>
+}
+----
+<1> similar events for properties and collections should also be defined
+
+and finally at the action level we can define:
+
+[source,java]
+----
+public class LibraryMember {
+    public static class LeaveEvent extends LibraryMember.ActionDomainEvent { }
+    @Action(domainEvent=LeaveEvent.class)
+    public void leave() { ... }
+    ...
+}
+----
+
+The subscriber can subscribe either to the general superclass (as before), or to any of the classes in the hierarchy.
+
+
+=== Variation (for contributing services)
+
+A slight variation on this is to not fix the generic parameter at the class level, ie:
+
+[source,java]
+----
+public static class LibraryMember {
+    public abstract static class ActionDomainEvent<S>
+            extends LibMemModule.ActionDomainEvent<S> { }
+    ...
+}
+----
+
+and instead parameterize down at the action level:
+
+[source,java]
+----
+public class LibraryMember {
+    public static class LeaveEvent
+            extends LibraryMember.ActionDomainEvent<LibraryMember> { } // <1>
+    }
+    @Action(domainEvent=LeaveEvent.class)
+    public void leave() { ... }
+    ...
+}
+----
+
+This then allows for other classes - in particular domain services contributing members - to also inherit from the class-level domain events.
+
+
+
+
+== Programmatic posting
+
+To programmatically post an event, simply call `#post()`.
+
+The `LibraryMember` example described above could for example be rewritten into:
+
+[source,java]
+----
+public class LibraryMember {
+    ...
+    public void leave() {
+        ...
+        eventBusService.post(new LibraryMember.LeaveEvent(...));    // <1>
+    }
+    ...
+}
+----
+<1> `LibraryMember.LeaveEvent` could be _any_ class, not just a subclass of `o.a.i.applib.event.ActionDomainEvent`.
+
+In practice we suspect there will be few cases where the programmatic approach is required rather than the declarative approach afforded by xref:../rgant/rgant.adoc#_rgant-Action_domainEvent[`@Action#domainEvent()`] et al.
+
+
+
+== Using `WrapperFactory`
+
+An alternative way to cause events to be posted is through the xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-api_WrapperFactory[`WrapperFactory`].  This is useful when you wish to enforce a (lack-of-) trust boundary between the caller and the callee.
+
+For example, suppose that `Customer#placeOrder(...)` emits a `PlaceOrderEvent`, which is subscribed to by a `ReserveStockSubscriber`.  This subscriber in turn calls `StockManagementService#reserveStock(...)`.  Any business rules on `#reserveStock(...)` should be enforced.
+
+In the `ReserveStockSubscriber`, we therefore use the `WrapperFactory`:
+
+[source,java]
+----
+@DomainService(nature=NatureOfService.DOMAIN)
+public class ReserveStockSubscriber {
+    @Programmatic
+    @Subscribe
+    public void on(Customer.PlaceOrderEvent ev) {
+        wrapperFactory.wrap(stockManagementService)
+                      .reserveStock(ev.getProduct(), ev.getQuantity());
+    }
+    ...
+    @Inject
+    StockManagementService stockManagementService;
+    @Inject
+    WrapperFactory wrapperFactory;
+}
+----
+
+
+== Implementation SPI
+
+The implementation of `EventBusService` provided by Apache Isis will by default use link:https://code.google.com/p/guava-libraries/[Guava]'s https://code.google.com/p/guava-libraries/wiki/EventBusExplained[`EventBus`] as the underlying in-memory event bus.  Alternatively the link:http://www.axonframework.org/[AxonFramework]'s link:http://www.axonframework.org/docs/2.4/single.html#d5e1489[SimpleEventBus] can be used.  Which is used is specified through configuration property (described xref:../rgsvc/rgsvc.adoc#__rgsvc_core-domain-api_EventBusService_Configuration[below]).
+
+[NOTE]
+.Guava vs Axon, which to use?
+====
+Guava actually queues up events; they are not guaranteed to be dispatched immediately.  This generally is not problem, but can be for cases where the subscriber may in turn want to post its own events (using xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-api_WrapperFactory[`WrapperFactory`]).
+
+The Axon `SimpleEventBus`-based implementation on the other hand is fully synchronous; events are dispatched as soon as they are posted.  This works well in all scenarios (that we have tested).
+====
+
+
+It is also possible to use some other implementation.
+
+[source,java]
+----
+public interface EventBusImplementation {
+    void register(Object domainService);
+    void unregister(Object domainService);
+    void post(Object event);
+}
+----
+
+As is probably obvious, the `EventBusService` just delegates down to these method calls when its own similarly named methods are called.
+
+If you do provide your own implementation of this SPI, be aware that your subscribers will need to use whatever convention is required (eg different annotations) such that the events are correctly routed through to your subscribers.
+
+
+
+[[__rgsvc_core-domain-api_EventBusService_Configuration]]
+== Configuration
+
+The implementation of `EventBusService` provided by Apache Isis will by default use link:https://code.google.com/p/guava-libraries/[Guava]'s https://code.google.com/p/guava-libraries/wiki/EventBusExplained[`EventBus`] as the underlying in-memory event bus.  Alternatively the link:http://www.axonframework.org/[AxonFramework]'s link:http://www.axonframework.org/docs/2.4/single.html#d5e1489[SimpleEventBus] can be used.
+
+To specify which, add the xref:../rgcfg/rgcfg.adoc#_rgcfg_configuring-core[configuration property] `isis.services.eventbus.implementation`:
+
+[source,ini]
+----
+isis.services.eventbus.implementation=guava
+----
+
+or
+
+[source,ini]
+----
+isis.services.eventbus.implementation=axon
+----
+
+If you have written your own implementation of the `EventBusServiceImplementation` SPI, then specify instead its fully-qualified class name:
+
+[source,ini]
+----
+isis.services.eventbus.implementation=com.mycompany.isis.MyEventBusServiceImplementation
+----
+
+
+
+In addition, there is one further configuration property, whether to allow "late registration":
+
+[source,ini]
+----
+isis.services.eventbus.allowLateRegistration=false
+----
+
+Late registration refers to the idea that a domain service can register itself with the `EventBusService` after events have been posted.  Since domain services are set up at boot time, this almost certainly constitutes a bug in the code and so by default late registration is _not_ allowed.  Setting the above property to `true` disables this check.
+
+
+
+
+
+== Registering the Services
+
+Assuming that the `configuration-and-annotation` services installer is configured (implicit if using the
+`AppManifest` to xref:../rgcms/rgcms.adoc#_rgcms_classes_AppManifest-bootstrapping[bootstrap the app]) then Apache Isis' core
+implementation of `EventBusService` 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/rgant.adoc#_rgant-DomainServiceLayout_menuOrder[`@DomainServiceLayout#menuOrder()`] (as explained
+in the xref:../rgsvc/rgsvc.adoc#__rgsvc_intro_overriding-the-services[introduction] to this guide).
+
+
+
+
+== Related Services
+
+The `EventBusService` is intended for fine-grained publish/subscribe for object-to-object interactions within an Apache Isis domain object model. The event propagation is strictly in-memory, and there are no restrictions on the object acting as the event (it need not be serializable, for example).
+
+The xref:../rgsvc/rgsvc.adoc#_rgsvc_persistence-layer-spi_PublishingService[`PublishingService`] meanwhile is intended for coarse-grained publish/subscribe for system-to-system interactions, from Apache Isis to some other system. Here the only events published are those that action invocations (for actions annotated with xref:../rgant/rgant.adoc#_rgant-Action_publishing[`@Action#publishing()`]) and of changed objects (for objects annotated with xref:../rgant/rgant.adoc#_rgant-DomainObject_publishing[`@DomainObject#publishing()`]).
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/20b83ae7/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_core-domain-api_FactoryService.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_core-domain-api_FactoryService.adoc b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_core-domain-api_FactoryService.adoc
new file mode 100644
index 0000000..b2b5c67
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_core-domain-api_FactoryService.adoc
@@ -0,0 +1,79 @@
+[[_rgsvc_core-domain-api_FactoryService]]
+= `FactoryService`
+: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 `FactoryService` collects together methods for instantiating domain objects.
+
+[NOTE]
+====
+The methods in this service replace similar methods (now deprecated) in xref:../rgsvc/rgsvc.adoc#_rgsvc_core-domain-api_DomainObjectContainer[`DomainObjectContainer`].
+====
+
+
+== API
+
+The API of `FactoryService` is:
+
+[source,java]
+----
+public interface FactoryService {
+    <T> T instantiate(final Class<T> ofType);       // <1>
+    <T> T mixin();                                  // <2>
+}
+----
+<1> create a new non-persisted domain entity.  Any services will be automatically injected into the service.
+<2> programmatically instantiate a mixin, as annotated with xref:../rgant/rgant.adoc#_rgant-Mixin[`@Mixin`] or xref:../rgant/rgant.adoc#_rgant-DomainObject_nature[`@DomainObject#nature()`].
+
+
+The object is created in memory, but is not persisted.  The benefits of using this method (instead of simply using the Java `new` keyword) are:
+
+* any services will be injected into the object immediately (otherwise they will not be injected until the frameworkbecomes aware of the object, typically when it is persisted through the xref:../rgsvc/rgsvc.adoc#_rgsvc_persistence-layer-api_RepositoryService[`RepositoryService`]
+
+* the default value for any properties (usually as specified by `defaultXxx()` supporting methods) will not be set and the `created()` callback will be called.
+
+The corollary is: if your code never uses `defaultXxx()` or the `created()` callback, then you can just `new` up the object.  The xref:../rgsvc/rgsvc.adoc#_rgsvc_metadata-api_ServiceRegistry[`ServiceRegistry`] service can be used to inject services into the domain object.
+
+
+
+== Usage
+
+For example:
+
+[source,java]
+----
+Customer cust = factoryService.instantiate(Customer.class);
+cust.setFirstName("Freddie");
+cust.setLastName("Mercury");
+repositoryService.persist(cust);
+----
+
+
+== Implementation
+
+The core framework provides a default implementation of this service (`o.a.i.core.metamodel.services.factory.FactoryServiceDefault`).
+
+
+
+
+== Registering the Service
+
+Assuming that the `configuration-and-annotation` services installer is configured (implicit if using the
+`AppManifest` to xref:../rgcms/rgcms.adoc#_rgcms_classes_AppManifest-bootstrapping[bootstrap the app]) then Apache Isis' core
+implementation of `FactoryService` 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/rgant.adoc#_rgant-DomainServiceLayout_menuOrder[`@DomainServiceLayout#menuOrder()`] (as explained
+in the xref:../rgsvc/rgsvc.adoc#__rgsvc_intro_overriding-the-services[introduction] to this guide).
+
+
+== Related Services
+
+The xref:../rgsvc/rgsvc.adoc#_rgsvc_persistence-layer-api_RepositoryService[`RepositoryService`] is often used in conjunction with the `FactoryService`, to persist domain objects after they have been instantiated and populated.
+
+An alternative to using the factory service is to simply instantiate the object ("new is the new new") and then use the
+xref:../rgsvc/rgsvc.adoc#_rgsvc_metadata-api_ServiceRegistry[`ServiceRegistry`] service to inject other domain services into the
+instantiated object.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/20b83ae7/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_core-domain-api_Scratchpad.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_core-domain-api_Scratchpad.adoc b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_core-domain-api_Scratchpad.adoc
new file mode 100644
index 0000000..2fd2252
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_core-domain-api_Scratchpad.adoc
@@ -0,0 +1,128 @@
+[[_rgsvc_core-domain-api_Scratchpad]]
+= `Scratchpad`
+: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 `Scratchpad` service is a link:../../more-advanced-topics/how-to-09-020-How-to-write-a-typical-domain-service.html[request-scoped] service to allow objects to exchange information even if they do not directly call each other.
+
+
+
+
+== API & Implementation
+
+The API of `Scratchpad` service is:
+
+[source,java]
+----
+@RequestScoped
+public class Scratchpad {
+    @Programmatic
+    public Object get(Object key) { ... }
+    @Programmatic
+    public void put(Object key, Object value) { ... }
+    @Programmatic
+    public void clear() { ... }
+}
+----
+
+This class (`o.a.i.applib.services.scratchpad.Scratchpad`) is also the implementation.  And, as you can see, the service is just a request-scoped wrapper around a `java.util.Map`.
+
+
+
+
+
+== Usage
+
+The most common use-case is for xref:../rgant/rgant.adoc#_rgant-Action_invokeOn[bulk] actions that act upon multiple objects in a list.  The (same) `Scratchpad` service is injected into each of these objects, and so they can use pass information.
+
+For example, the Isis addons example https://github.com/isisaddons/isis-app-todoapp/[todoapp] (not ASF) demonstrates how the `Scratchpad` service can be used to calculate the total cost of the selected `ToDoItem`s:
+
+
+[source,java]
+----
+@Action(
+    semantics=SemanticsOf.SAFE,
+    invokeOn=InvokeOn.COLLECTION_ONLY
+)
+public BigDecimal totalCost() {
+    BigDecimal total = (BigDecimal) scratchpad.get("runningTotal");
+    if(getCost() != null) {
+        total = total != null ? total.add(getCost()) : getCost();
+        scratchpad.put("runningTotal", total);
+    }
+    return total.setScale(2);
+}
+@Inject
+Scratchpad scratchpad;
+----
+
+A more complex example could use a xref:../ugfun/ugfun.adoc#_ugfun_building-blocks_types-of-domain-objects_view-models[view model] to enable bulk updates to a set of objects. The view model's job is to gather track of the items to be updated:
+
+[source,java]
+----
+public class ToDoItemUpdateBulkUpdate extends AbstractViewModel {
+    private List<ToDoItem> _items = ...;
+    public ToDoItemBulkUpdate add(ToDoItem item) {
+        _items.add(item);
+        return this;
+    }
+    ...                 // <1>
+}
+----
+<1> not shown - the implementation of `ViewModel` for converting the list of `_items` into a string.
+
+The bulk action in the objects simply adds the selected item to the view model:
+
+[source,java]
+----
+@Action(
+    invokeOn=InvokeOn.COLLECTIONS_ONLY
+    semantics=SemanticsOf.SAFE
+)
+public ToDoItemBulkUpdate bulkUpdate() {
+    return lookupBulkUpdateViewModel().add(this);
+}
+private ToDoItemBulkUpdate lookupBulkUpdateViewModel() {
+    ToDoItemBulkUpdate bulkUpdate =
+        (ToDoItemBulkUpdate) scratchpad.get("bulkUpdateViewModel");     // <1>
+    if(bulkUpdate == null) {
+        bulkUpdate = container.injectServicesInto(new ToDoItemBulkUpdate());
+        scratchpad.put("bulkUpdateViewModel", bulkUpdate);              // <2>
+    }
+    return bulkUpdate;
+}
+@Inject
+Scratchpad scratchpad;
+----
+<1> look for the `ToDoItemBulkUpdate` in the scratchpad...
+<2> ... and add one if there isn't one (ie for the first object returned).
+
+If using the xref:../ugvw/ugvw.adoc#[Wicket viewer], the `ToDoItemBulkUpdate` view model returned from the last action invoked will be displayed. Thereafter this view model can be used to perform a bulk update of the "enlisted" items.
+
+
+
+
+
+== Registering the Service
+
+Assuming that the `configuration-and-annotation` services installer is configured (implicit if using the
+`AppManifest` to xref:../rgcms/rgcms.adoc#_rgcms_classes_AppManifest-bootstrapping[bootstrap the app]) then Apache Isis' core
+implementation of `Scratchpad` 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/rgant.adoc#_rgant-DomainServiceLayout_menuOrder[`@DomainServiceLayout#menuOrder()`] (as explained
+in the xref:../rgsvc/rgsvc.adoc#__rgsvc_intro_overriding-the-services[introduction] to this guide).
+
+
+
+
+
+== Related Services
+
+The xref:../rgsvc/rgsvc.adoc#_rgsvc_api_ActionInteractionContext[`ActionInteractionContext`] service allows xref:../rgant/rgant.adoc#_rgant-Action_invokeOn[bulk actions] to co-ordinate with each other.
+
+The xref:../rgsvc/rgsvc.adoc#_rgsvc_persistence-layer-api_QueryResultsCache[`QueryResultsCache`] is useful for caching the results of expensive method calls.

http://git-wip-us.apache.org/repos/asf/isis/blob/20b83ae7/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_core-domain-api_UserService.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_core-domain-api_UserService.adoc b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_core-domain-api_UserService.adoc
new file mode 100644
index 0000000..62e217f
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_core-domain-api_UserService.adoc
@@ -0,0 +1,85 @@
+[[_rgsvc_core-domain-api_UserService]]
+= `UserService`
+: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 `UserService` allows the domain object to obtain the identity of the user interacting with said object.
+
+If xref:../rgsvc/rgsvc.adoc#_rgsvc_testing_SudoService[`SudoService`] has been used to temporarily override the user and/or roles, then this service will report the overridden values instead.
+
+
+[NOTE]
+====
+The methods in this service replace similar methods (now deprecated) in xref:../rgsvc/rgsvc.adoc#_rgsvc_core-domain-api_DomainObjectContainer[`DomainObjectContainer`].
+====
+
+
+
+
+== API and Usage
+
+The API of `UserService` is:
+
+[source,java]
+----
+public interface UserService {
+    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/ugsec.adoc#[security] (typically Shiro).
+
+In addition, when using the xref:../ugvw/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.
+
+
+
+
+
+== Implementation
+
+The core framework provides a default implementation of this service (`o.a.i.core.runtime.services.user.UserServiceDefault`).
+
+
+
+
+== Registering the Service
+
+Assuming that the `configuration-and-annotation` services installer is configured (implicit if using the
+`AppManifest` to xref:../rgcms/rgcms.adoc#_rgcms_classes_AppManifest-bootstrapping[bootstrap the app]) then Apache Isis' core
+implementation of `UserService` 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/rgant.adoc#_rgant-DomainServiceLayout_menuOrder[`@DomainServiceLayout#menuOrder()`] (as explained
+in the xref:../rgsvc/rgsvc.adoc#__rgsvc_intro_overriding-the-services[introduction] to this guide).
+
+
+

http://git-wip-us.apache.org/repos/asf/isis/blob/20b83ae7/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api.adoc b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api.adoc
index 302523f..b0e0ef1 100644
--- a/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api.adoc
@@ -22,7 +22,7 @@ The table below summarizes the integration APIs defined by Apache Isis.  It also
 
 
 
-|xref:../rgsvc/rgsvc.adoc#_rgsvc_api_BookmarkService[`o.a.i.applib.` +
+|xref:../rgsvc/rgsvc.adoc#_rgsvc_integration-api_BookmarkService[`o.a.i.applib.` +
 `services.bookmark` +
 `BookmarkService2`]
 |Convert object reference to a serializable "bookmark", and vice versa.
@@ -37,7 +37,7 @@ The table below summarizes the integration APIs defined by Apache Isis.  It also
 `Contributions`
 
 
-|xref:../rgsvc/rgsvc.adoc#_rgsvc_api_DeepLinkService[`o.a.i.applib` +
+|xref:../rgsvc/rgsvc.adoc#_rgsvc_integration-api_DeepLinkService[`o.a.i.applib` +
 `services.deeplink` +
 `DeepLinkService`]
 |Obtain a URL to a domain object (eg for use within an email or report)
@@ -47,7 +47,7 @@ The table below summarizes the integration APIs defined by Apache Isis.  It also
 |Implementation only usable within Wicket viewer
 
 
-|xref:../rgsvc/rgsvc.adoc#_rgsvc_api_EmailService[`o.a.i.applib.` +
+|xref:../rgsvc/rgsvc.adoc#_rgsvc_integration-api_EmailService[`o.a.i.applib.` +
 `services.email` +
 `EmailService`]
 |Send a HTML email, optionally with attachments.
@@ -57,7 +57,7 @@ The table below summarizes the integration APIs defined by Apache Isis.  It also
 |
 
 
-|xref:../rgsvc/rgsvc.adoc#_rgsvc_api_GuiceBeanProvider[`o.a.i.applib.` +
+|xref:../rgsvc/rgsvc.adoc#_rgsvc_integration-api_GuiceBeanProvider[`o.a.i.applib.` +
 `services.guice` +
 `GuiceBeanProvider`]
 |Access to internal framework services initialized using Guice DI.
@@ -68,7 +68,7 @@ The table below summarizes the integration APIs defined by Apache Isis.  It also
 
 
 
-|xref:../rgsvc/rgsvc.adoc#_rgsvc_api_JaxbService[`o.a.i.applib.` +
+|xref:../rgsvc/rgsvc.adoc#_rgsvc_integration-api_JaxbService[`o.a.i.applib.` +
 `services.jaxb` +
 `JaxbService`]
 |Marshal and unmarshal JAXB-annotated view models to/from XML.
@@ -78,17 +78,17 @@ The table below summarizes the integration APIs defined by Apache Isis.  It also
 |
 
 
-|xref:../rgsvc/rgsvc.adoc#_rgsvc_api_MementoService[`o.a.i.applib.` +
+|xref:../rgsvc/rgsvc.adoc#_rgsvc_integration-api_MementoService[`o.a.i.applib.` +
 `services.memento` +
 `MementoService`]
-|Capture a serializable memento of a set of primitives or xref:../rgsvc/rgsvc.adoc#_rgsvc_api_BookmarkService[bookmarks].  Primarily used internally, eg in support of commands/auditing.
+|Capture a serializable memento of a set of primitives or xref:../rgsvc/rgsvc.adoc#_rgsvc_integration-api_BookmarkService[bookmarks].  Primarily used internally, eg in support of commands/auditing.
 |`MementoServiceDefault` +
 ``o.a.i.core`` +
 ``isis-core-runtime``
 |
 
 
-|xref:../rgsvc/rgsvc.adoc#_rgsvc_api_XmlSnapshotService[`o.a.i.applib.` +
+|xref:../rgsvc/rgsvc.adoc#_rgsvc_integration-api_XmlSnapshotService[`o.a.i.applib.` +
 `services.xmlsnapshot` +
 `XmlSnapshotService`]
 |Generate an XML representation of an object and optionally a graph of related objects.
@@ -112,10 +112,10 @@ Key:
 
 
 
-include::_rgsvc_api_BookmarkService.adoc[leveloffset=+1]
-include::_rgsvc_api_DeepLinkService.adoc[leveloffset=+1]
-include::_rgsvc_api_EmailService.adoc[leveloffset=+1]
-include::_rgsvc_api_GuiceBeanProvider.adoc[leveloffset=+1]
-include::_rgsvc_api_JaxbService.adoc[leveloffset=+1]
-include::_rgsvc_api_MementoService.adoc[leveloffset=+1]
-include::_rgsvc_api_XmlSnapshotService.adoc[leveloffset=+1]
+include::_rgsvc_integration-api_BookmarkService.adoc[leveloffset=+1]
+include::_rgsvc_integration-api_DeepLinkService.adoc[leveloffset=+1]
+include::_rgsvc_integration-api_EmailService.adoc[leveloffset=+1]
+include::_rgsvc_integration-api_GuiceBeanProvider.adoc[leveloffset=+1]
+include::_rgsvc_integration-api_JaxbService.adoc[leveloffset=+1]
+include::_rgsvc_integration-api_MementoService.adoc[leveloffset=+1]
+include::_rgsvc_integration-api_XmlSnapshotService.adoc[leveloffset=+1]

http://git-wip-us.apache.org/repos/asf/isis/blob/20b83ae7/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_BookmarkService.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_BookmarkService.adoc b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_BookmarkService.adoc
new file mode 100644
index 0000000..4a286b8
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_BookmarkService.adoc
@@ -0,0 +1,125 @@
+[[_rgsvc_integration-api_BookmarkService]]
+= `BookmarkService2`
+: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 `BookmarkService2` API 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/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/rgsvc.adoc#_rgsvc_persistence-layer-spi_AuditerService[`AuditerService`] 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 `BookmarkService2` is:
+
+[source,java]
+----
+public interface BookmarkService2 {
+    enum FieldResetPolicy {                                                     // <1>
+        RESET,
+        DONT_RESET
+    }
+    Object lookup(BookmarkHolder bookmarkHolder, FieldResetPolicy policy);
+    Object lookup(Bookmark bookmark, FieldResetPolicy policy);
+    <T> T lookup(Bookmark bookmark, FieldResetPolicy policy, Class<T> cls);     // <2>
+    Bookmark bookmarkFor(Object domainObject);
+    Bookmark bookmarkFor(Class<?> cls, String identifier);
+}
+----
+<1> if the object has already been loaded from the database, then whether to reset its fields.  The default it to `RESET`.
+<2> 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.BookmarkServiceInternalDefault`
+
+
+== `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]
+----
+@DomainService(nature=NatureOfService.DOMAIN)
+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/rgsvc.adoc#_rgsvc_api_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/rgsvc.adoc#_rgsvc_persistence-layer-spi_PublishingService[`PublishingService`], and by the
+(non-ASF) http://github.com/isisaddons/isis-module-auditing[Isis addons' auditing] module's implementation of
+xref:../rgsvc/rgsvc.adoc#_rgsvc_persistence-layer-spi_AuditerService[`AuditerService`].
+
+
+
+
+== Registering the Service
+
+Assuming that the `configuration-and-annotation` services installer is configured (implicit if using the
+`AppManifest` to xref:../rgcms/rgcms.adoc#_rgcms_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/rgant.adoc#_rgant-DomainServiceLayout_menuOrder[`@DomainServiceLayout#menuOrder()`] (as explained
+in the xref:../rgsvc/rgsvc.adoc#__rgsvc_intro_overriding-the-services[introduction] to this guide).
+
+

http://git-wip-us.apache.org/repos/asf/isis/blob/20b83ae7/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_DeepLinkService.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_DeepLinkService.adoc b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_DeepLinkService.adoc
new file mode 100644
index 0000000..816d4a2
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_DeepLinkService.adoc
@@ -0,0 +1,56 @@
+[[_rgsvc_integration-api_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/ugvw.adoc#[Wicket viewer] this provides an implementation for accessing the representation through this viewer.  (For the xref:../ugvro/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/rgsvc.adoc#_rgsvc_integration-api_BookmarkService[`BookmarkService`]).
+
+
+
+== Usage within the framework
+
+The xref:../rgsvc/rgsvc.adoc#_rgsvc_presentation-layer-spi_EmailNotificationService[`EmailNotificationService`] uses this service in order to generate emails as part of xref:../ugvw/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:../rgcms/rgcms.adoc#_rgcms_classes_AppManifest-bootstrapping[bootstrap the app]), _and_ that the
+xref:../ugvw/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/rgant.adoc#_rgant-DomainServiceLayout_menuOrder[`@DomainServiceLayout#menuOrder()`] (as explained
+in the xref:../rgsvc/rgsvc.adoc#__rgsvc_intro_overriding-the-services[introduction] to this guide).

http://git-wip-us.apache.org/repos/asf/isis/blob/20b83ae7/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_EmailService.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_EmailService.adoc b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_EmailService.adoc
new file mode 100644
index 0000000..fd91997
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_EmailService.adoc
@@ -0,0 +1,122 @@
+[[_rgsvc_integration-api_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 {
+    boolean send(                                                   // <1>
+        List<String> to, List<String> cc, List<String> bcc,         // <2>
+        String subject,
+        String body,                                                // <3>
+        DataSource... attachments);
+    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:../rgcfg/rgcfg.adoc#_rgcfg_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/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
+
+
+In addition the following properties can be set:
+
+* `isis.service.email.throwExceptionOnFail` +
++
+Whether to throw an exception if there the email cannot be sent (probably because of some misconfiguration).
+This behaviour is (now) the default; the old behaviour (of just returning `false` from the `send()` method) can be re-enabled by setting this property to `false`.
+
+* `isis.service.email.override.to` +
++
+Intended to simplify testing, if specified then the email's `to` address will be that specified (rather than the email address(es) passed in as an argument to `EmailService#send(...)`).
+
+* `isis.service.email.override.cc` +
++
+Similarly, to override the `cc` email address.
+
+* `isis.service.email.override.to` +
++
+Similarly, to override the `bcc` email address.
+
+* `isis.service.email.socketTimeout` +
++
+The socket timeout, defaulting to 2000ms.
+
+* `isis.service.email.socketConnectionTimeout` +
++
+The socket connection timeout, defaulting to 2000ms.
+
+
+== 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/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:../rgcms/rgcms.adoc#_rgcms_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/rgant.adoc#_rgant-DomainServiceLayout_menuOrder[`@DomainServiceLayout#menuOrder()`] (as explained in the xref:../rgsvc/rgsvc.adoc#__rgsvc_intro_overriding-the-services[introduction] to this guide).
+
+
+== Related Services
+
+The email service is used by the xref:../rgsvc/rgsvc.adoc#_rgsvc_presentation-layer-spi_EmailNotificationService[`EmailNotificationService`] which is, in turn, used by xref:../rgsvc/rgsvc.adoc#_rgsvc_persistence-layer-spi_UserRegistrationService[`UserRegistrationService`].
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/20b83ae7/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_GuiceBeanProvider.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_GuiceBeanProvider.adoc b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_GuiceBeanProvider.adoc
new file mode 100644
index 0000000..ea9c36e
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_GuiceBeanProvider.adoc
@@ -0,0 +1,91 @@
+[[_rgsvc_integration-api_GuiceBeanProvider]]
+= `GuiceBeanProvider`
+: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 `GuiceBeanProvider` domain service acts as a bridge between Apache Isis' xref:../ugvw/ugvw.adoc#[Wicket viewer] internal bootstrapping using link:https://github.com/google/guice[Google Guice].
+
+This service operates at a very low-level, and you are unlikely to have a need for it.  It is used internally by the framework, in the default implementation of the xref:../rgsvc/rgsvc.adoc#_rgsvc_integration-api_DeepLinkService[`DeepLinkService`].
+
+[NOTE]
+====
+Currently Apache Isis uses a combination of Guice (within the Wicket viewer only) and a home-grown dependency injection framework.  In future versions we intended to refactor the framework to use CDI throughout.  At that time this service is likely to become redundant because we will allow any of the internal components of Apache Isis to be injected into your domain object code.
+====
+
+
+== API & Implementation
+
+The API defined by this service is:
+
+[source,java]
+----
+public interface GuiceBeanProvider {
+    @Programmatic
+    <T> T lookup(Class<T> beanType);
+    @Programmatic
+    <T> T lookup(Class<T> beanType, final Annotation qualifier);
+}
+----
+
+The xref:../ugvw/ugvw.adoc#[Wicket viewer] this provides an implementation of this service.
+
+
+
+== Usage
+
+Using the xref:../ugvw/ugvw.adoc#[Wicket viewer] requires subclassing of `IsisWicketApplication`.  In the subclass it is commonplace to override `newIsisWicketModule()`, for example:
+
+[source,java]
+----
+@Override
+protected Module newIsisWicketModule() {
+    final Module isisDefaults = super.newIsisWicketModule();
+    final Module overrides = new AbstractModule() {
+        @Override
+        protected void configure() {
+            bind(String.class).annotatedWith(Names.named("applicationName"))
+                              .toInstance("ToDo App");
+            bind(String.class).annotatedWith(Names.named("applicationCss"))
+                              .toInstance("css/application.css");
+            bind(String.class).annotatedWith(Names.named("applicationJs"))
+                              .toInstance("scripts/application.js");
+            ...
+        }
+    };
+    return Modules.override(isisDefaults).with(overrides);
+}
+----
+
+This "module" is in fact a Guice module, and so the `GuiceBeanProvider` service can be used to lookup any of the components bound into it.
+
+For example:
+
+[source,java]
+----
+public class SomeDomainObject {
+    private String lookupApplicationName() {
+        return guiceBeanProvider.lookup(String.class, Names.named("applicationName"));
+    }
+    @Inject
+    GuiceBeanProvider guiceBeanProvider;
+}
+----
+
+should return "ToDo App".
+
+
+
+== Registering the Services
+
+Assuming that the `configuration-and-annotation` services installer is configured (implicit if using the
+`AppManifest` to xref:../rgcms/rgcms.adoc#_rgcms_classes_AppManifest-bootstrapping[bootstrap the app]), _and_ that the
+xref:../ugvw/ugvw.adoc#[Wicket viewer] is being used, then an implementation of `GuiceBeanProvider` is
+automatically registered and injected (it is annotated with `@DomainService`) so no further configuration is required.
+
+To use an alternative implementation, use
+xref:../rgant/rgant.adoc#_rgant-DomainServiceLayout_menuOrder[`@DomainServiceLayout#menuOrder()`] (as explained
+in the xref:../rgsvc/rgsvc.adoc#__rgsvc_intro_overriding-the-services[introduction] to this guide).
+
+

http://git-wip-us.apache.org/repos/asf/isis/blob/20b83ae7/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_JaxbService.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_JaxbService.adoc b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_JaxbService.adoc
new file mode 100644
index 0000000..b6fa3b4
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_JaxbService.adoc
@@ -0,0 +1,68 @@
+[[_rgsvc_integration-api_JaxbService]]
+= `JaxbService`
+: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 `JaxbService` allows instances of JAXB-annotated classes to be marshalled to XML and
+unmarshalled from XML back into domain objects.
+
+
+
+
+
+[[__rgsvc_integration-api_JaxbService_api-and-implementation]]
+== API & Implementation
+
+The API defined by `JaxbService` is:
+
+[source,java]
+----
+public interface JaxbService {
+    @Programmatic
+    <T> T fromXml(Class<T> domainClass, String xml);                                            // <1>
+    @Programmatic
+    public String toXml(final Object domainObject);                                             // <2>
+    public enum IsisSchemas {                                                                   // <3>
+        INCLUDE, IGNORE
+    }
+    @Programmatic
+    public Map<String, String> toXsd(final Object domainObject, final IsisSchemas isSchemas);} // <4>
+}
+----
+<1> unmarshalls the XML into an instance of the class.
+<2> marshalls the domain object into XML
+<3> whether to include or exclude the Isis schemas in the generated map of XSDs.  Discussed further below.
+<4> generates a map of each of the schemas referenced; the key is the schema namespace, the value is the XML of the schema itself.
+
+With respect to the `IsisSchemas` enum: a JAXB-annotated domain object will live in its own XSD namespace and may
+reference multiple other XSD schemas.  In particular, many JAXB domain objects will reference the
+xref:../rgcms/rgcms.adoc#_rgcms_schema[common Isis schemas] (for example the `OidDto` class that represents a reference to
+a persistent entity).  The enum indicates whether these schemas should be included or excluded from the map.
+
+Isis provides a default implementation of the service, `o.a.i.schema.services.jaxb.JaxbServiceDefault`.
+
+
+
+== Usage within the framework
+
+This service is provided as a convenience for applications, but is also used internally by the framework to
+xref:../rgant/rgant.adoc#_rgant-XmlRootElement[`@XmlRootElement`]-annotated
+xref:../ugfun/ugfun.adoc#_ugfun_building-blocks_types-of-domain-objects_view-models[view models].  The functionality to download XML and XSD schemas is also
+exposed in the UI through mixins to xref:../rgcms/rgcms.adoc#_rgcms_classes_mixins_Dto[`Dto`] interface.
+
+
+
+== Registering the Service
+
+Assuming that the `configuration-and-annotation` services installer is configured (implicit if using the
+`AppManifest` to xref:../rgcms/rgcms.adoc#_rgcms_classes_AppManifest-bootstrapping[bootstrap the app]) then Apache Isis' core
+implementation of `JaxbService` 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/rgant.adoc#_rgant-DomainServiceLayout_menuOrder[`@DomainServiceLayout#menuOrder()`] (as explained
+in the xref:../rgsvc/rgsvc.adoc#__rgsvc_intro_overriding-the-services[introduction] to this guide).
+

http://git-wip-us.apache.org/repos/asf/isis/blob/20b83ae7/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_MementoService.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_MementoService.adoc b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_MementoService.adoc
new file mode 100644
index 0000000..8fa90ec
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_MementoService.adoc
@@ -0,0 +1,146 @@
+[[_rgsvc_integration-api_MementoService]]
+= `MementoService` (deprecated)
+: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 `MementoService` was originally introduced to simplify the implementation of
+xref:../ugfun/ugfun.adoc#_ugfun_building-blocks_types-of-domain-objects_view-models[ViewModel]s which are required by the framework to return string representation of
+all of their backing state, moreover which is safe for use within a URL.  This usage is deprecated; use xref:../ugfun/ugfun.adoc#_ugfun_programming-model_view-models_jaxb[JAXB view models] instead.
+
+The service can also be used to create a memento of arbitrary objects, however this usage is also deprecated.  (Prior
+to `1.13.0` it was used internally by the core implementation of
+xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-api_BackgroundService[`BackgroundService`] to capture the state of action invocations so that
+they can be executed by a background process; this is now done using
+xref:../rgfis/rgfis.adoc#_rgfis_application-layer_CommandDtoServiceInternal[`CommandDtoServiceInternal`]).
+
+
+[NOTE]
+====
+As of `1.13.0` this service is deprecated, replaced by internal domain services.
+====
+
+
+
+
+== API & Implementation
+
+The API defined by `MementoService` is:
+
+[source,java]
+----
+@Deprecated
+public interface MementoService {
+    @Deprecated
+    public static interface Memento {
+        public Memento set(String name, Object value);
+        public <T> T get(String name, Class<T> cls);
+        public String asString();
+        public Set<String> keySet();
+    }
+    public Memento create();
+    public Memento parse(final String str);
+    public boolean canSet(Object input);
+}
+----
+
+The core framework provides a default implementation of this API, namely
+`o.a.i.c.r.services.memento.MementoServiceDefault`.  The string returned (from `Memento#asString()`) is a base-64 URL
+encoded representation of the underlying format (an XML string).
+
+[NOTE]
+====
+In fact, the `MementoServiceDefault` implementation does provide a mechanism to disable the URL encoding, but this is
+not part of the `MementoService` public API. Note also that the encoding method is not pluggable.
+====
+
+The types of objects that are supported by the `MementoService` are implementation-specific, but would typically
+include all the usual value types as well as Apache Isis' `Bookmark` class (to represent references to arbitrary
+entities). Nulls can also be set.
+
+In the case of the default implementation provided by the core framework, the types supported are:
+
+* `java.lang.String`
+* `java.lang.Boolean`, `boolean`
+* `java.lang.Byte`, `byte`
+* `java.lang.Short`, `short`
+* `java.lang.Integer`, `int`
+* `java.lang.Long`, `long`
+* `java.lang.Float`, `float`
+* `java.lang.Double`, `double`
+* `java.lang.Character`, `char`
+* `java.math.BigDecimal`
+* `java.math.BigInteger`
+* `org.joda.time.LocalDate`
+* `org.apache.isis.applib.services.bookmark.Bookmark`
+
+If using another implementation, the `canSet(...)` method can be used to check if the candidate object's type is supported.
+
+
+
+== Usage
+
+As noted in the introduction, a common use case for this service is in the implementation of the xref:../rgcms/rgcms.adoc#_rgcms_classes_super_AbstractViewModel[`ViewModel`] interface.
+
+[TIP]
+====
+Rather than implementing `ViewModel`, it's usually easier to annotate your view models with xref:../rgant/rgant.adoc#_rgant-ViewModel[`@ViewModel`] (or equivalently xref:../rgant/rgant.adoc#_rgant-DomainObject_nature[`@DomainObject#nature=EXTERNAL_ENTITY`] or xref:../rgant/rgant.adoc#_rgant-DomainObject_nature[`@DomainObject#nature=INMEMORY_ENTITY`].
+====
+
+For example, suppose you were implementing a view model that represents an external entity in a SOAP web service.  To access this service the view model needs to store (say) the hostname, port number and an id to the object.
+
+Using an injected `MementoService` the view model can roundtrip to and from this string, thus implementing the `ViewModel` API:
+
+[source,java]
+----
+public class ExternalEntity implements ViewModel {
+    private String hostname;
+    private int port;
+    private String id;
+    public String viewModelMemento() {                      // <1>
+        return mementoService.create()
+                .set("hostname", hostname)
+                .set("port", port)
+                .set("id", id)
+                .asString();
+    }
+    public void viewModelInit(String mementoStr) {          // <2>
+        Memento memento = mementoService.parse(mementoStr);
+        hostname = memento.get("hostname", String.class);
+        port = memento.get("port", int.class);
+        id = memento.get("id", String.class);
+    ...
+    @Inject
+    MementoService mementoService;
+}
+----
+<1> part of the `ViewModel` API
+<2> part of the `ViewModel` API
+
+
+
+
+
+== Related Services
+
+(Prior to `1.13.0`), the memento service was used by the xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-api_CommandContext[`CommandContext`]
+service and also
+xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-spi_BackgroundCommandService[`BackgroundCommandService`]. These both use a memento to capture a
+representation of an action invocation.  This is now done using
+xref:../rgfis/rgfis.adoc#_rgfis_application-layer_CommandDtoServiceInternal[`CommandDtoServiceInternal`].
+
+
+
+
+== Registering the Service
+
+Assuming that the `configuration-and-annotation` services installer is configured (implicit if using the
+`AppManifest` to xref:../rgcms/rgcms.adoc#_rgcms_classes_AppManifest-bootstrapping[bootstrap the app]) then Apache Isis' core
+implementation of `MementoService` 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/rgant.adoc#_rgant-DomainServiceLayout_menuOrder[`@DomainServiceLayout#menuOrder()`] (as explained
+in the xref:../rgsvc/rgsvc.adoc#__rgsvc_intro_overriding-the-services[introduction] to this guide).

http://git-wip-us.apache.org/repos/asf/isis/blob/20b83ae7/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_XmlSnapshotService.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_XmlSnapshotService.adoc b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_XmlSnapshotService.adoc
new file mode 100644
index 0000000..8b8bdd1
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_integration-api_XmlSnapshotService.adoc
@@ -0,0 +1,219 @@
+[[_rgsvc_integration-api_XmlSnapshotService]]
+= `XmlSnapshotService`
+: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 `XmlSnapshotService` provides the capability to generate XML snapshots (and if required corresponding XSD schemas) based on graphs of domain objects.
+
+Typical use cases include creating mementos for business-focused auditing, such that a report could be generated as to which end-user performed a business action (perhaps for legal reasons).  For one system that we know of, a digest of this snapshot of data is signed with the public encryption key so as to enforce non-repudiation.
+
+Another use case is to grab raw data such that it could be merged into a report template or communication.
+
+The service offers a basic API to create a snapshot of a single object, and an more flexible API that allows the size of the graph to be customized.
+
+The core framework provides an implementation of this service (`o.a.i.core.runtime.services.xmlsnapshot.XmlSnapshotServiceDefault`).
+
+
+
+== Standard API
+
+The (basic) API of `XmlSnapshotService` is:
+
+[source]
+----
+public interface XmlSnapshotService {
+    public interface Snapshot {
+        Document getXmlDocument();
+        Document getXsdDocument();
+        String getXmlDocumentAsString();
+        String getXsdDocumentAsString();
+    }
+    @Programmatic
+    public XmlSnapshotService.Snapshot snapshotFor(Object domainObject);
+    ...
+}
+----
+
+
+The most straight-forward usage of this service is simply:
+
+[source,java]
+----
+XmlSnapshot snapshot = xmlsnapshotService.snapshotFor(customer);
+Element customerAsXml = snapshot.getXmlElement();
+----
+
+This will return an XML (document) element that contains the names and values of each of the customer's value properties, along with the titles of reference properties, and also the number of items in collections.
+
+
+As well as obtaining the XML snapshot, it is also possible to obtain an XSD schema that the XML snapshot conforms to.
+
+[source]
+----
+XmlSnapshot snapshot = ...;
+Element customerAsXml = snapshot.getXmlElement();
+Element customerXsd = snapshot.getXsdElement();
+----
+
+This can be useful for some tools.  For example, link:http://www.altova.com/stylevision.html[Altova Stylevision] can use the XML and XSD to transform into reports.  Please note that this link does not imply endorsement (nor even a recommendation that this is a good design).
+
+
+
+
+
+== Builder API
+
+The contents of the snapshot can be adjusted by including "paths" to other references or collections. To do this, the
+builder is used.  The API for this is:
+
+[source,java]
+----
+public interface XmlSnapshotService {
+    ...
+    public interface Builder {
+        void includePath(final String path);
+        void includePathAndAnnotation(String path, String annotation);
+        XmlSnapshotService.Snapshot build();
+    }
+    @Programmatic
+    public XmlSnapshotService.Builder builderFor(Object domainObject);
+}
+----
+
+We start by obtaining a builder:
+
+[source,java]
+----
+XmlSnapshot.Builder builder = xmlsnapshotService.builderFor(customer);
+----
+
+Suppose now that we want the snapshot to also include details of the customer's address, where `address` in this case is a reference property to an instance of the `Address` class. We can "walk-the-graph" by including these references within the builder.
+
+[source,java]
+----
+builder.includePath("address");
+----
+
+We could then go further and include details of every order in the customer's `orders` collection, and details of every
+product of every order:
+
+[source,java]
+----
+builder.includePath("orders/product");
+----
+
+When all paths are included, then the builder can build the snapshot:
+
+[source,java]
+----
+XmlSnapshot snapshot = builder.build();
+Element customerAsXml = snapshot.getXmlElement();
+----
+
+All of this can be strung together in a fluent API:
+
+[source,java]
+----
+Element customerAsXml = xmlsnapshotService.builderFor(customer)
+                        .includePath("address")
+                        .includePath("orders/product")
+                        .build()
+                        .getXmlElement();
+----
+
+
+As you might imagine, the resultant XML document can get quite large very quickly with only a few "include"s.
+
+
+[NOTE]
+====
+If an XSD schema is beng generated (using `snapshot.getXsdElement()` then note that for the XSD to be correct, the object being snapshotted must have non-null values for the paths that are `include()`'d. If this isn't done then the XSD will not be correct reflect for another snapshotted object that does have non-null values.
+====
+
+
+
+
+== Automatic inclusions
+
+If the domain object being snapshotted implements the `SnapshottableWithInclusions` interace, then this moves the
+responsibility for determining what is included within the snapshot from the caller to the snapshottable object itself:
+
+[source]
+----
+public interface SnapshottableWithInclusions extends Snapshottable {
+    List<String> snapshotInclusions();
+}
+----
+
+If necessary, both approaches can be combined.
+
+
+[TIP]
+====
+As an alternative to using `include()`, you might consider building a view model domain object which can reference only the relevant information required for the snapshot. For example, if only the 5 most recent Orders for a Customer were required, a `CustomerAndRecentOrders` view model could hold a collection of just those 5 ``Order``s. Typically such view models would implement `SnapshottableWithInclusions`.
+
+One reason for doing this is to provide a stable API between the domain model and whatever it is that might be consuming the XML. With a view model you can refactor the domain entities but still preserve a view model such that the XML is the same.
+====
+
+
+
+== Convenience API
+
+The `XmlSnapshotService` also provides some API for simply manipulating XML:
+
+[source]
+----
+public interface XmlSnapshotService {
+    ...
+    @Programmatic
+    public Document asDocument(String xmlStr);                          // <1>
+    @Programmatic
+    public <T> T getChildElementValue(                                  // <2>
+                    Element el, String tagname, Class<T> expectedCls);
+    @Programmatic
+    public Element getChildElement(                                     // <3>
+                    Element el, String tagname);
+    @Programmatic
+    public String getChildTextValue(Element el);                        // <4>
+}
+----
+<1> is a convenience method to convert xml string back into a W3C Document
+<2> is a convenience method to extract the value of an XML element, based on its type.
+<3> is a convenience method to walk XML document.
+<4> is a convenience method to obtain value of child text node.
+
+
+
+
+
+
+
+== Registering the Service
+
+Assuming that the `configuration-and-annotation` services installer is configured (implicit if using the
+`AppManifest` to xref:../rgcms/rgcms.adoc#_rgcms_classes_AppManifest-bootstrapping[bootstrap the app]) then Apache Isis' core
+implementation of `XmlSnapshotService` 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/rgant.adoc#_rgant-DomainServiceLayout_menuOrder[`@DomainServiceLayout#menuOrder()`] (as explained
+in the xref:../rgsvc/rgsvc.adoc#__rgsvc_intro_overriding-the-services[introduction] to this guide).
+
+
+
+== Related Services
+
+The xref:../rgsvc/rgsvc.adoc#_rgsvc_integration-api_BookmarkService[`BookmarkService`] provides a mechanism for obtaining a string representations of a single domain object.
+
+The xref:../rgsvc/rgsvc.adoc#_rgsvc_integration-api_MementoService[`MementoService`] also provides a mechanism for generating string representations of domain objects.
+
+The xref:../rgsvc/rgsvc.adoc#_rgsvc_integration-api_JaxbService[`JaxbService`] is a simple wrapper around
+standard JAXB functionality for generating both XMLs and XSDs from JAXB-annotated classes.  Note that there is built-in support for JAXB classes (ie annotated with
+xref:../rgant/rgant.adoc#_rgant-XmlRootElement[`@XmlRootElement`]) to be used as view models.
+
+
+
+