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/06/16 07:42:25 UTC
[37/45] isis git commit: ISIS-1133: breaking out reference guide and
devenv guide;
moving appendices' release notes and migration notes to other docs;
improving the documentation page.
http://git-wip-us.apache.org/repos/asf/isis/blob/9c5dafab/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved.adoc
new file mode 100644
index 0000000..9416dd5
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved.adoc
@@ -0,0 +1,58 @@
+[[_rg_methods_reserved]]
+= Reserved Methods
+: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 table below lists the reserved methods that are recognized as part of Apache Isis' default programming model.
+
+.Reserved Methods
+[cols="1,4a", options="header"]
+|===
+
+|Method
+|Description
+
+|xref:rg.adoc#_rg_methods_reserved_manpage-cssClass[`cssClass()`]
+|Provides a CSS class for this object instance. In conjunction with xref:ug.adoc#_ug_runtime_application-specific_application-css[`application.css`], can therefore provide custom styling of an object instance wherever it is rendered. +
+
+See also xref:rg.adoc#_rg_methods_reserved_manpage-title[`title()`] and xref:rg.adoc#_rg_methods_reserved_manpage-iconName[`iconName()`].
+
+|xref:rg.adoc#_rg_methods_reserved_manpage-disable[`disable(...)`]
+|Disable all or some of an object's properties
+
+|xref:rg.adoc#_rg_methods_reserved_manpage-getId[`getId()`]
+|Provides an optional unique identifier of a service. +
+
+If not provided, the service's fully-qualified class name is used.
+
+|xref:rg.adoc#_rg_methods_reserved_manpage-hide[`hide(...)`]
+|Hide all or some of an object's properties
+
+|xref:rg.adoc#_rg_methods_reserved_manpage-iconName[`iconName()`]
+|Provides the name of the image to render, usually alongside the title, to represent the object. If not provided, then the class name is used to locate an image. +
+
+See also xref:rg.adoc#_rg_methods_reserved_manpage-title[`title()`] and xref:rg.adoc#_rg_methods_reserved_manpage-cssClass[`cssClass()`]
+
+|xref:rg.adoc#_rg_methods_reserved_manpage-title[`title()`]
+|Provides a title for the object. +
+
+See also xref:rg.adoc#_rg_methods_reserved_manpage-iconName[`iconName()`] and xref:rg.adoc#_rg_methods_reserved_manpage-cssClass[`cssClass()`]
+
+|xref:rg.adoc#_rg_methods_reserved_manpage-validate[`validate()`]
+|Validate the object's state prior to persisting.
+
+|===
+
+
+
+
+include::_rg_methods_reserved_manpage-cssClass.adoc[leveloffset=+1]
+include::_rg_methods_reserved_manpage-disable.adoc[leveloffset=+1]
+include::_rg_methods_reserved_manpage-getId.adoc[leveloffset=+1]
+include::_rg_methods_reserved_manpage-hide.adoc[leveloffset=+1]
+include::_rg_methods_reserved_manpage-iconName.adoc[leveloffset=+1]
+include::_rg_methods_reserved_manpage-title.adoc[leveloffset=+1]
+include::_rg_methods_reserved_manpage-validate.adoc[leveloffset=+1]
http://git-wip-us.apache.org/repos/asf/isis/blob/9c5dafab/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-cssClass.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-cssClass.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-cssClass.adoc
new file mode 100644
index 0000000..b6a0c22
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-cssClass.adoc
@@ -0,0 +1,46 @@
+[[_rg_methods_reserved_manpage-cssClass]]
+= `cssClass()`
+: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 `cssClass()` returns a CSS class for a particular object instance.
+
+The xref:ug.adoc#_ug_wicket-viewer[Wicket viewer] wraps the object's representation in a containing `<div>` with the class added. This is done both for rendering the object either in a table or when rendering the object on its own page.
+
+In conjunction with xref:ug.adoc#_ug_runtime_application-specific_application-css[`application.css`], can therefore provide custom styling of an object instance wherever it is rendered. +
+
+
+For example, the (non-ASF) http://github.com/isisaddons/isis-app-todoapp[Isis addons' todoapp] uses this technique to add a strikethrough for completed todo items. This is shown on the home page:
+
+image::{_imagesdir}reference-methods/reserved/cssClass/strikethrough.png[width="800px",link="{_imagesdir}reference-methods/reserved/cssClass/strikethrough.png"]
+
+
+The code to accomplish this is straightforward:
+
+[source,java]
+----
+public class ToDoItem ... {
+ public String cssClass() {
+ return !isComplete() ? "todo" : "done";
+ }
+ ...
+}
+----
+
+In the xref:ug.adoc#_ug_runtime_application-specific_application-css[application.css], the following styles were then added:
+
+[source,css]
+----
+tr.todo {
+}
+tr.done {
+ text-decoration: line-through;
+ color: #d3d3d3;
+}
+----
+
+
+See also xref:rg.adoc#_rg_methods_reserved_manpage-title[`title()`] and xref:rg.adoc#_rg_methods_reserved_manpage-iconName[`iconName()`].
http://git-wip-us.apache.org/repos/asf/isis/blob/9c5dafab/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-disable.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-disable.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-disable.adoc
new file mode 100644
index 0000000..acf457d
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-disable.adoc
@@ -0,0 +1,102 @@
+[[_rg_methods_reserved_manpage-disable]]
+= `disable()`
+: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/
+
+
+One use case that Isis supports is that of a domain object with a lifecycle whereby at some stage it should become immutable: all its properties/collections should be disabled, and/or its actions become not invokable.
+
+It would be painful to have to write a separate xref:rg.adoc#_rg_methods_prefixes_manpage-disable[`disable...()`] method for each and every member, so instead Isis allows a single `disable...(...)` method to be implemented that is applied to all members.
+
+The signature of the method is:
+
+[source,java]
+----
+public String disable(Identifier.Type identifierType) { ... }
+----
+
+where `Identifier.Type` is part of the Isis applib (nested static class of `o.a.i.applib.Identifier`) to distinguish between an interaction with an action, a property or an action.
+
+Note that Isis' xref:ug.adoc#_ug_more-advanced_i18n[i18n support] extends this so that the returned reason can also be internationalized.
+
+For example:
+
+[source,java]
+----
+public String disable(Identifier.Type identifierType) {
+ return !calendarService.isOfficeHours(clock.today()
+ ? "Cannot modify objects outside of office hours"
+ : null;
+}
+----
+
+See also the similar methods to xref:rg.adoc#_rg_methods_reserved_manpage-hide[`hide()`] object members en-masse.
+
+
+== Alternatives
+
+An alternative design -- and one that could be easily argued is actually more flexible -- is to leverage domain events with vetoing subscribers.
+
+With this approach we define, for a given domain class, a base `PropertyDomainEvent`, `CollectionDomainEvent` and `ActionDomainEvent`. A good pattern is to make these nested static classes. For example:
+
+[source,java]
+----
+public class ToDoItem ... {
+ public static abstract class PropertyDomainEvent<T>
+ extends ToDoAppDomainModule.PropertyDomainEvent<ToDoItem, T> {
+ ...
+ }
+ ...
+}
+----
+
+where in turn:
+
+[source,java]
+----
+public final class ToDoAppDomainModule {
+ private ToDoAppDomainModule(){}
+ public abstract static class PropertyDomainEvent<S,T>
+ extends org.apache.isis.applib.services.eventbus.PropertyDomainEvent<S,T> {
+ ...
+ }
+ ...
+}
+----
+
+Then, each property/collection/action emits either these base domain events or their own subclass:
+
+[source,java]
+----
+public class ToDoItem ... {
+ public static class DescriptionDomainEvent
+ extends PropertyDomainEvent<String> {
+ ...
+ }
+ @Property(
+ domainEvent = DescriptionDomainEvent.class
+ )
+ public String getDescription() { ... }
+ ...
+}
+----
+
+A vetoing subscriber can then subscribe to the domain events and veto access, eg:
+
+[source,java]
+----
+@DomainObject
+public class VetoOutOfOfficeHours {
+ @Subscribe
+ public void on(ToDoItem.PropertyDomainEvent ev) {
+ if(!calendarService.isOfficeHours(clock.today()) {
+ ev.veto("Cannot modify objects outside of office hours");
+ }
+ }
+ ...
+}
+----
+
+Obviously there's an awful lot more boilerplate here, but there's also a lot more flexibility.
+
http://git-wip-us.apache.org/repos/asf/isis/blob/9c5dafab/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-getId.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-getId.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-getId.adoc
new file mode 100644
index 0000000..026a756
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-getId.adoc
@@ -0,0 +1,19 @@
+[[_rg_methods_reserved_manpage-getId]]
+= `getId()`
+: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 `getId()` method applies only to domain services, and allows a unique identifer to be provided for that service.
+
+This identifier corresponds in many ways to the xref:rg.adoc#_rg_annotations_manpage-DomainObject_objectType[`objectType()`] attribute for domain objects; it is used as an internal identifier but also appears in URLs within the xref:ug.adoc#_ug_restfulobjects-viewer[RestfulObjects viewer]'s REST API.
+
+If the identifier is omitted, the services fully qualified class name is used.
+
+[TIP]
+====
+Unlike domain objects, where the use of an object type is strongly encouraged (eg using xref:rg.adoc#_rg_annotations_manpage-PersistenceCapable[`@PersistenceCapable`]), it matters much less if an id is specified for domain services. The principle benefit is shorter URLs in the REST API.
+====
+
+
http://git-wip-us.apache.org/repos/asf/isis/blob/9c5dafab/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-hide.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-hide.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-hide.adoc
new file mode 100644
index 0000000..594005c
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-hide.adoc
@@ -0,0 +1,39 @@
+[[_rg_methods_reserved_manpage-hide]]
+= `hide()`
+: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/
+
+
+
+One use case that Isis supports is that of a domain object with a lifecycle whereby at some stage some number of the object's members should be hidden. For example, for an object that at some stage is logically immutable, we might want to make all its properties/collections unmodifiable and hide all its actions.
+
+While we could write a separate xref:rg.adoc#_rg_methods_prefixes_manpage-hide[`hide...()`] method for each and every action, this could become painful. So instead Isis allows a single `hide...(...)` method to be implemented that is applied to all members.
+
+The signature of the method is:
+
+[source,java]
+----
+public boolean hide(Identifier.Type identifierType) { ... }
+----
+
+where `Identifier.Type` is part of the Isis applib (nested static class of `o.a.i.applib.Identifier`) to distinguish between an interaction with an action, a property or an action.
+
+For example:
+
+[source,java]
+----
+public boolean hide(Identifier.Type identifierType) {
+ return identifierType == Identifier.Type.ACTION && isFrozen();
+}
+----
+
+See also the similar method to xref:rg.adoc#_rg_methods_reserved_manpage-disable[`disable()`] object members en-masse.
+
+
+== Alternatives
+
+An alternative design -- and one that could be easily argued is actually more flexible -- is to leverage domain events with vetoing subscribers.
+
+There is further discussion on this approach in xref:rg.adoc#_rg_methods_reserved_manpage-disable[here].
+
http://git-wip-us.apache.org/repos/asf/isis/blob/9c5dafab/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-iconName.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-iconName.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-iconName.adoc
new file mode 100644
index 0000000..5c79721
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-iconName.adoc
@@ -0,0 +1,36 @@
+[[_rg_methods_reserved_manpage-iconName]]
+= `iconName()`
+: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/
+
+
+Every object is represented by an icon; this is based on the domain object's simple name. The xref:ug.adoc#_ug_wicket-viewer[Wicket viewer] searches for the image in the same package as the `.class` file for the domain object.
+
+The `iconName()` allows the icon that to be used to change for individual object instances. These are usually quite subtle, for example to reflect the particular status of an object. The value returned by the `iconName()` method is added as a suffix to the base icon name.
+
+For example, the (non-ASF) http://github.com/isisaddons/isis-app-todoapp[Isis addons' todoapp] uses this technique to add an overlay for todo items that have been completed:
+
+image::{_imagesdir}reference-methods/reserved/iconName/differing.png[width="200px",link="{_imagesdir}reference-methods/reserved/iconName/differing.png"]
+
+
+
+The screenshot below shows the location of these png icon files:
+
+image::{_imagesdir}reference-methods/reserved/iconName/png-files.png[width="200px",link="{_imagesdir}reference-methods/reserved/iconName/png-files.png"]
+
+
+
+The code to accomplish this is straightforward:
+
+[source,java]
+----
+public class ToDoItem ... {
+ public String iconName() {
+ return !isComplete() ? "todo" : "done";
+ }
+ ...
+}
+----
+
+See also xref:rg.adoc#_rg_methods_reserved_manpage-title[`title()`] and xref:rg.adoc#_rg_methods_reserved_manpage-cssClass[`cssClass()`]
http://git-wip-us.apache.org/repos/asf/isis/blob/9c5dafab/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-title.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-title.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-title.adoc
new file mode 100644
index 0000000..fc3793d
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-title.adoc
@@ -0,0 +1,65 @@
+[[_rg_methods_reserved_manpage-title]]
+= `title()`
+: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/
+
+
+
+Every object is represented by a title. This appears both as a main header for the object when viewed as well as being used as a hyperlink within properties and collections. It therefore must contain enough information for the end-user to distinguish the object from any others.
+
+This is most commonly done by including some unique key within the title, for example a customer's SSN, or an order number, and so forth. However note that Isis itself does _not_ require the title to be unique; it is merely recommended in most cases.
+
+An object's title can be constructed in various ways, but the most flexible is to use the `title()` method. The signature of this method is usually:
+
+[source,java]
+----
+public String title() { ... }
+----
+
+Note that Isis' xref:ug.adoc#_ug_more-advanced_i18n[i18n support] extends this so that titles can also be internationalized.
+
+For example, the (non-ASF) http://github.com/isisaddons/isis-app-todoapp[Isis addons' todoapp] uses this technique to add an overlay for todo items that have been completed:
+
+[source,java]
+----
+public String title() {
+ final TitleBuffer buf = new TitleBuffer(); // <1>
+ buf.append(getDescription());
+ if (isComplete()) { // <2>
+ buf.append("- Completed!");
+ } else {
+ try {
+ final LocalDate dueBy = wrapperFactory.wrap(this).getDueBy(); // <3>
+ if (dueBy != null) {
+ buf.append(" due by", dueBy);
+ }
+ } catch(final HiddenException ignored) { // <4>
+ }
+ }
+ return buf.toString();
+}
+----
+<1> simple xref:rg.adoc#_rg_classes_utility_manpage-TitleBuffer[tility class] to help construct the title string
+<2> imperative conditional logic
+<3> using the xref:rg.adoc#_rg_services-api_manpage-WrapperFactory[`WrapperFactory`] to determine if the `dueBy` field is visible for this user ...
+<4> ... but ignore if not
+
+As the example above shows, the implementation can be as complex as you like.
+
+In many cases, though, you may be able to use the xref:rg.adoc#_rg_annotations_manpage-Title[`@Title`] annotation.
+
+
+See also xref:rg.adoc#_rg_methods_reserved_manpage-iconName[`iconName()`] and xref:rg.adoc#_rg_methods_reserved_manpage-cssClass[`cssClass()`]
+
+
+
+
+
+
+
+
+
+
+
+
http://git-wip-us.apache.org/repos/asf/isis/blob/9c5dafab/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-validate.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-validate.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-validate.adoc
new file mode 100644
index 0000000..3f50754
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_methods_reserved_manpage-validate.adoc
@@ -0,0 +1,27 @@
+[[_rg_methods_reserved_manpage-validate]]
+= `validate()`
+: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 `validate()` method is used to specify that invariants pertaining to an object's state are enforced.
+
+
+[WARNING]
+====
+(As of 1.8.0) there are known limitations with this functionality. Invariants are enforced when an object is initially created and when it is edited, however invariants are currently _not_ enforced if an action is invoked.
+====
+
+
+The signature of the method is:
+
+[source,java]
+----
+public String validate() { ... }
+----
+
+where the returned string is the reason that the invocation is vetoed.
+
+Note that Isis' xref:ug.adoc#_ug_more-advanced_i18n[i18n support] extends this so that the returned reason can also be internationalized.
http://git-wip-us.apache.org/repos/asf/isis/blob/9c5dafab/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout.adoc
new file mode 100644
index 0000000..bbe7e58
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout.adoc
@@ -0,0 +1,20 @@
+[[_rg_object-layout]]
+= Object Layout
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+:_basedir: ../
+:_imagesdir: images/
+
+
+
+
+In implementing the http://en.wikipedia.org/wiki/Naked_objects[naked objects pattern], Apache Isis aims to infer as much information from the domain classes as possible. Nevertheless, some metadata relating solely to the UI is inevitably required.
+
+
+This chapter describes how this is done both for domain objects -- statically or dynamically -- and for the application menu bar (containing domain service' actions).
+
+include::_rg_object-layout_static.adoc[leveloffset=+1]
+include::_rg_object-layout_dynamic.adoc[leveloffset=+1]
+include::_rg_object-layout_application-menu.adoc[leveloffset=+1]
+include::_rg_object-layout_static-vs-dynamic.adoc[leveloffset=+1]
+
+
http://git-wip-us.apache.org/repos/asf/isis/blob/9c5dafab/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout_application-menu.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout_application-menu.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout_application-menu.adoc
new file mode 100644
index 0000000..3843f46
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout_application-menu.adoc
@@ -0,0 +1,171 @@
+[[_rg_object-layout_application-menu]]
+= Application Menu Layout
+: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 actions of domain services are made available as an application menu bar. By default each domain service
+corresponds to a single menu on this menu bar, with its actions as the drop-down menu items. This is rarely exactly
+what is required, however. The `@MemberOrder` and `@DomainServiceLayout` annotations can be used to rearrange the
+placement of menu items.
+
+The screenshots below are taken from http://github.com/estatio/estatio[Estatio], an open source estate management
+application built using Apache Isis.
+
+== @DomainServiceLayout
+
+Menus for domain services can be placed either on a primary, secondary or tertiary menu bar.
+
+image::{_imagesdir}wicket-viewer/application-menu/layout-menus.png[width="800px",link="{_imagesdir}wicket-viewer/application-menu/layout-menus.png"]
+
+Within a single top-level menu (eg "Fixed Assets") there can be actions from multiple services. The Wicket viewer
+automatically adds a divider between each:
+
+image::{_imagesdir}wicket-viewer/application-menu/dividers.png[width="400px",link="{_imagesdir}wicket-viewer/application-menu/dividers.png"]
+
+In the example above the top-level menu combines the actions from the `Properties`, `Units` and `FixedAssetRegistrations`
+services. The `Properties` service is annotated:
+
+[source,java]
+----
+@DomainServiceLayout(
+ named="Fixed Assets",
+ menuBar = DomainServiceLayout.MenuBar.PRIMARY,
+ menuOrder = "10.1"
+)
+public class Properties ... { ... }
+----
+
+while the `Units` service is annotated:
+
+[source,java]
+----
+@DomainServiceLayout(
+ named="Fixed Assets",
+ menuBar = DomainServiceLayout.MenuBar.PRIMARY,
+ menuOrder = "10.2"
+)
+public class Units ... { ... }
+----
+
+and similarly `FixedAssetRegistrations` is annotated:
+
+[source,java]
+----
+@DomainServiceLayout(
+ named="Fixed Assets",
+ menuBar = DomainServiceLayout.MenuBar.PRIMARY,
+ menuOrder = "10.3"
+)
+public class FixedAssetRegistrations ... { ... }
+----
+
+Note that in all three cases the value of the `named` attribute and the `menuBar` attribute is the same: "Fixed Assets"
+and PRIMARY. This means that all will appear on a "Fixed Assets" menu in the primary menu bar.
+
+Meanwhile the value of `menuOrder` attribute is significant for two reasons:
+
+* for these three services on the same ("Fixed Assets") top-level menu, it determines the relative order of their sections (`Properties` first, then `Units`, then `FixedAssetRegistrations`)
+* it determines the placement of the top-level menu itself ("Fixed Assets") with respect to other top-level menus on the menu bar.
+
+To illustrate this latter point, the next top-level menu on the menu bar, "Parties", is placed after "Fixed Assets"
+ because the `menuOrder` of the first of its domain services, namely the `Parties` service, is higher than that for
+ "Fixed Assets":
+
+[source,java]
+----
+@DomainServiceLayout(
+ named="Parties",
+ menuBar = DomainServiceLayout.MenuBar.PRIMARY,
+ menuOrder = "20.1"
+)
+public class Parties ... { ... }
+----
+
+Note that only the `menuOrder` of the _first_ domain service is significant in placing the menus along the menu bar;
+thereafter the purpose of the `menuOrder` is to order the menu services sections on the menu itself.
+
+== Ordering of a service's actions within a menu
+
+For a given service, the actions within a section on a menu is determined by the `@MemberOrder` annotation. Thus, for
+the `Units` domain service, its actions are annotated:
+
+[source,java]
+----
+public class Units extends EstatioDomainService<Unit> {
+
+ @MemberOrder(sequence = "1")
+ public Unit newUnit( ... ) { ... }
+
+ @MemberOrder(sequence = "2")
+ public List<Unit> findUnits( ... ) { ... }
+
+ @ActionLayout( prototype = true )
+ @MemberOrder(sequence = "99")
+ public List<Unit> allUnits() { ... }
+ ...
+}
+----
+
+Note that the last is also a prototype action (meaning it is only displayed in SERVER_PROTOTYPE (=Wicket Development) mode).
+In the UI it is rendered in italics.
+
+(It is possible to override this place of a given action by specifying `@MemberOrder(name="...")` where the name is
+that of a top-level menu. Prior to 1.8.0 this was the only way of doing things, as of 1.8.0 its use
+is not recommended).
+
+== Tertiary menubar
+
+The tertiary menu bar consists of a single unnamed menu, rendered underneath the user's login, top right. This is
+intended primarily for actions pertaining to the user themselves, eg their account, profile or settings:
+
+image::{_imagesdir}wicket-viewer/application-menu/tertiary.png[width="300px",link="{_imagesdir}wicket-viewer/application-menu/tertiary.png"]
+
+Domain services' actions can be associated with the tertiary menu using the same `@DomainServiceLayout` annotation. For
+example, the `updateEpochDate(...)` and `listAllSettings(...)` actions come from the following service:
+
+[source,java]
+----
+@DomainServiceLayout(
+ menuBar = DomainServiceLayout.MenuBar.TERTIARY,
+ menuOrder = "10.1"
+)
+public class EstatioAdministrationService ... {
+
+ @MemberOrder(sequence = "1")
+ public void updateEpochDate( ... ) { ... }
+
+ @MemberOrder(sequence = "2")
+ public List<ApplicationSetting> listAllSettings() { ... }
+ ...
+}
+----
+
+Because the number of items on the tertiary menu is expected to be small and most will pertain to the current user, the
+viewer does _not_ place dividers between actions from different services on the tertiary menu.
+
+
+== Isis Add-on modules
+
+Some of the (non-ASF) link:http://isisaddons.org[Isis Addons] modules also provide services whose actions appear in top-level menus.
+
+The http://github.com/isisaddons/isis-module-security[security]'s module places its domain service menus in three
+top-level menus:
+
+* its `ApplicationUsers`, `ApplicationRoles`, `ApplicationPermission`, `ApplicationFeatureViewModels` and
+ `ApplicationTenancies` domain services are all grouped together in a single "Security" top-level menu, on the
+ SECONDARY menu bar
+
+* its `SecurityModuleAppFixturesService` domain service, which allows the security modules' fixture scripts to be run,
+ is placed on a "Prototyping" top-level menu, also on the SECONDARY menu bar
+
+* its `MeService` domain service, which provides the `me()` action, is placed on the TERTIARY menu bar.
+
+Meanwhile the http://github.com/isisaddons/isis-module-devutils[devutils] module places its actions - to download layouts and
+so forth - on a "Prototyping" top-level menu, on the SECONDARY menu bar.
+
+Currently there is no facility to alter the placement of these services. However, their UI can be suppressed
+using security or using a xref:ug.adoc#_ug_more-advanced_decoupling_vetoing-visibility[vetoing subscriber].
+
http://git-wip-us.apache.org/repos/asf/isis/blob/9c5dafab/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout_dynamic.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout_dynamic.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout_dynamic.adoc
new file mode 100644
index 0000000..8bc6c02
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout_dynamic.adoc
@@ -0,0 +1,113 @@
+[[_rg_object-layout_dynamic]]
+= Dynamic Object Layout
+: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/
+
+
+
+Metadata providing UI hints can be specified either statically, using annotations, or dynamically, using a `.layout.json` file. This section describes the dynamic approach, using the file.
+
+
+== JSON layout file
+
+The JSON layout file for class `Xxx` takes the name `Xxx.layout.json`, and resides in the same package as the class.
+The format of the file is:
+
+[source,javascript]
+----
+{
+ "columns": [ // list of columns
+ {
+ "span": 6, // span of the left-hand property column
+ "memberGroups": { // ordered map of member (property) groups
+ "General": { // member group name
+ "members": {
+ "description": { // property, no associated actions, but with UI hint
+ "propertyLayout": {
+ "typicalLength": 50 // UI hint for size of field (no longer used in ISIS 1.8.0)
+ }
+ },
+ "category": {},
+ "complete": { // property, with associated actions
+ "propertyLayout": {
+ "describedAs": "Whether this todo item has been completed"
+ },
+ "actions": {
+ "completed": {
+ "actionLayout": {
+ "named": "Done", // naming UI hint
+ "cssClass": "x-highlight" // CSS UI hint
+ }
+ },
+ "notYetCompleted": {
+ "actionLayout": {
+ "named": "Not done"
+ }
+ }
+ }
+ }
+ },
+ "Misc": {
+ "members": {
+ "notes": {
+ "propertyLayout": {
+ "multiLine": 5 // UI hint for text area
+ }
+ },
+ "versionSequence": {}
+ }
+ }
+ }
+ }
+ },
+ {
+ "span": 6, // span of the middle property column
+ "memberGroups": { ... }
+ },
+ {
+ "span": 0 // span of the right property column (if any)
+ },
+ {
+ "span": 6,
+ "collections": { // ordered map of collections
+ "dependencies": { // collection, with associated actions
+ "collectionLayout": {
+ "paged": 10, // pagination UI hint
+ "render": "EAGERLY" // lazy-loading UI hint
+ },
+ "actions": {
+ "add":{},
+ "delete": {}
+ },
+ },
+ "similarItems": {} // collection, no associated actions
+ }
+ }
+ ],
+ "actions": { // actions not associated with any member
+ "delete": {},
+ "duplicate": {
+ "actionLayout": {
+ "named": {
+ "value": "Clone"
+ }
+ }
+ }
+ }
+}
+----
+
+Although advisable, it is not necessary to list all class members in this file. Any members not listed with be
+ordered according either to annotations (if present) or fallback/default values.
+
+Note also that the layout file may contain entries for xref:ug.adoc#_ug_how-tos_contributed-members[contributed associations and actions]; this allows each contributee classes to define their own layout for their contributions, possibly overriding any static metadata on the original domain service contributor.
+
+
+
+== Downloading an initial layout file
+
+The fastest way to get started is to use the (non-ASF) link:http://github.com/isisaddons/isis-module-devutils[Isis addons' devutils] module to download the layout file (derived from any existing static metadata defined by annotations).
+
+
+
http://git-wip-us.apache.org/repos/asf/isis/blob/9c5dafab/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout_static-vs-dynamic.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout_static-vs-dynamic.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout_static-vs-dynamic.adoc
new file mode 100644
index 0000000..cb0d610
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout_static-vs-dynamic.adoc
@@ -0,0 +1,26 @@
+[[_rg_object-layout_static-vs-dynamic]]
+= Static vs Dynamic Layouts
+: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/
+
+
+
+
+Using xref:rg.adoc#_rg_object-layout_dynamic[dynamic object layout]s using JSON has the huge benefit that the layout can be updated without requiring a recompile of the code and redeploy of the app. Many developers also find it easier to rationalize about layout when all the hints are collated together in a single place (rather than scattered across the class members as annotations).
+
+Another benefit of dynamic layout is that UI hints can be provided for xref:ug.adoc#_ug_how-tos_contributed-members[contributed associations and actions] that are synthesised at runtime.
+
+The main downsides of using dynamic layouts are a lack of typesafety (a typo will result in the metadata not being picked up for the element) and syntactic fragility (an invalid JSON document will result in no metadata for the entire class).
+
+Also, dynamic layouts have no notion of inheritance, whereas the dewey-decimal format `@MemberOrder` annotation allows the metadata of the subclass its superclasses to fit together relatively seamlessly.
+
+
+
+== Best of both worlds?
+
+Using the (non-ASF) link:http://github.com/isisaddons/isis-jrebel-plugin[Isis addons' jrebel] plugin comes close to getting the best of both words: metadata is specified in a type-safe way using annotations, but can be reloaded automatically.
+
+The downsides are licensing cost, and also the fact that metadata for contributed actions in the contributee class cannot be specified.
+
+Another open source alternative that you might also like to explore is DCEVM; there's a good write-up on the link:http://blog.jetbrains.com/idea/2013/07/get-true-hot-swap-in-java-with-dcevm-and-intellij-idea/[IntelliJ blog].
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/9c5dafab/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout_static.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout_static.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout_static.adoc
new file mode 100644
index 0000000..e8952d0
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_object-layout_static.adoc
@@ -0,0 +1,159 @@
+[[_rg_object-layout_static]]
+= Static Object Layout
+: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/
+
+
+Metadata providing UI hints can be specified either statically, using annotations, or dynamically, using a `.layout.json` file. This section describes the static approach, using annotations.
+
+
+
+== `@MemberOrder`
+
+The `@MemberOrder` annotation is used to specify the relative order of domain class properties, collections and actions.
+
+The annotation defines two attributes, `name()` and `sequence()`. Their usage depends on the member type:
+
+* for properties, the `name()` is used to group properties together. The `sequence()` then orders properties within these groups. If no `name()` is specified then the property is placed in a fallback "General" group, called "General". +
++
+The name of these "member groups" are then referenced by xref:rg.adoc#_rg_annotations_manpage-MemberGroupLayout[`@MemberGroupLayout`].
+
+* for collections, the `name()` attribute is (currently) unused. The `sequence()` orders collections relative to one another
+
+* for actions, the `name()` attribute associates an action with either a property or with a collection. +
++
+If the `name()` attribute matches a property name, then the action's button is rendered close to the property, according to xref:rg.adoc#_rg_annotations_manpage-ActionLayout_position[`@ActionLayout#position()`] attribute. +
++
+On the other hand if the `name() attribute matches a collection name, then the action's button is rendered on the collection's header. +
++
+If there is no `name()` value, then the action is considered to pertain to the object as a whole, and its button is rendered close to the object's icon and title.
++
+Within any of these, the `sequence()` then determines the relative ordering of the action with respect to other actions that have been similarly associated with properties/collections or left as "free-standing".
+
+
+For example:
+
+[source,java]
+----
+public class ToDoItem {
+ @MemberOrder(sequence="1")
+ public String getDescription() { ... }
+ @MemberOrder(sequence="2")
+ public String getCategory() { ... }
+ @MemberOrder(sequence="3")
+ public boolean isComplete() { ... }
+ @MemberOrder(name="Detail", sequence="1")
+ public LocalDate getDueBy() { ... }
+ @MemberOrder(name="Detail", sequence="2")
+ public BigDecimal getCost() { ... }
+ @MemberOrder(name="Detail", sequence="4")
+ public String getNotes() { ... }
+ @MemberOrder(name="Misc", sequence="99")
+ public Long getVersionSequence() { ... }
+ ...
+}
+----
+
+This defines three property (or member) groups, "General", "Detail" and "Misc"; "General" is the default if no `name` attribute is specified. Properties in the same member group are rendered together, as a fieldset.
+
+In addition, actions can optionally be associated (rendered close to) either properties or actions. This is done by overloading the `@MemberOrder`'s `name` attribute, holding the value of the property or collection.
+
+For example:
+
+[source,java]
+----
+public class ToDoItem {
+ @MemberOrder(sequence="3")
+ public boolean isComplete() { ... }
+ @MemberOrder(name="complete", sequence="1")
+ public ToDoItem completed() { ...}
+ @MemberOrder(name="complete", sequence="2")
+ public ToDoItem notYetCompleted() { ...}
+
+ @MemberOrder(sequence="1")
+ public SortedSet<ToDoItem> getDependencies() { ... }
+ @MemberOrder(name="dependencies", sequence="1")
+ public ToDoItem add(ToDoItem t) { ...}
+ @MemberOrder(name="dependencies", sequence="2")
+ public ToDoItem remove(ToDoItem t) { ...}
+ ...
+}
+----
+
+will associate the `completed()` and `notYetCompleted()` actions with the `complete` property, and will associate the `add()` and `remove()` actions with the `dependencies` collection.
+
+
+The value of `sequence()` is a string. The simplest convention (as shown in the example above) is to use numbers -- 1, 2, 3 -- though it is a better idea to leave gaps in the numbers -- 10, 20, 30 perhaps -- such that a new member may be added without having to edit existing numbers. A useful alternative is to adopt the 'dewey-decimal' notation -- 1, 1.1, 1.2, 2, 3, 5.1.1, 5.2.2, 5.2, 5.3 -- which allows for an indefinite amount of future insertion. It also allows subclasses to insert their class members as required.
+
+
+
+
+== `@MemberGroupLayout`
+
+The `@MemberGroupLayout` annotation specifies the relative positioning of property groups as being either in a left column, a middle column or in a right column. The annotation also specifies the relative width of the columns.
+
+The property groups in this case are those that are inferred from the `@MemberOrder#name()` attribute.
+
+For example:
+
+[source,java]
+----
+@MemberGroupLayout(
+ columnSpans={3,3,0,6},
+ left={"General", "Misc"},
+ middle="Detail"
+ )
+public class ToDoItem {
+ ...
+}
+----
+
+Four values are given in the `columnSpans` attribute. The first three are the relative widths of the three columns of property groups. The fourth, meanwhile, indicates the width of a final column that holds all the collections of the object.
+
+The values of these spans are taken as proportions of 12 virtual columns across the page (this taken from the link:http://getbootstrap.com/2.3.2/[Bootstrap] library).
+
+For example:
+
+* `{3,3,0,6}` indicates:
+** a left column of properties taking up 25% of the width
+** a middle column of properties taking up 25% of the width
+** a right column of collections taking up 50% of the width
+* `{2,6,0,4}` indicates:
+** a left column of properties taking up ~16% of the width
+** a middle column of properties taking up 50% of the width
+** a right column of collections taking up ~33% of the width
+* `{2,3,3,4}` indicates:
+** a left column of properties taking up ~16% of the width
+** a middle column of properties taking up 25% of the width
+** a right column of properties taking up 25% of the width
+** a far right column of collections taking up ~33% of the width
+
+If the sum of all the columns exceeds 12, then the collections are placed underneath the properties, taking up the full span. For example:
+
+* {4,4,4,12} indicates:
+** a left column of properties taking up ~33% of the width
+** a middle column of properties taking up ~33% of the width
+** a right column of properties taking up ~33% of the width
+** the collections underneath the property columns, taking up the full width
+
+== Example Layouts
+
+Below are sketches for the layout of the https://github.com/apache/isis/blob/f38fdb92941172eabb12e0943509f239e6d5925f/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java[ToDoItem] class of the Isis addons example https://github.com/isisaddons/isis-app-todoapp/[todoapp] (not ASF):
+
+The first divides the properties into two equal sized columns (6-6-0) and puts the collections underneath (12):
+
+image::{_imagesdir}reference-layout/6-6-0-12.png[width="720px",link="{_imagesdir}reference-layout/6-6-0-12.png"]
+
+The next divides the collections into three equal sized columns (4-4-4) and again puts the collections underneath (12):
+
+image::{_imagesdir}reference-layout/4-4-4-12.png[width="720px",link="{_imagesdir}reference-layout/4-4-4-12.png"]
+
+The last puts the properties into a single column (4-0) and places the collections into the other larger column (8-0):
+
+image::{_imagesdir}reference-layout/4-0-8-0.png[width="720px",link="{_imagesdir}reference-layout/4-0-8-0.png"]
+
+
+== Other Annotations
+
+As of 1.8.0, all the layout annotations have been consolidated into the various `XxxLayout` annotations: xref:rg.adoc#_rg_annotations_manpage-ActionLayout, [`@ActionLayout`] xref:rg.adoc#_rg_annotations_manpage-CollectionLayout[`@CollectionLayout`], xref:rg.adoc#_rg_annotations_manpage-DomainObjectLayout[`@DomainObjectLayout`], xref:rg.adoc#_rg_annotations_manpage-DomainServiceLayout[`@DomainServiceLayout`], xref:rg.adoc#_rg_annotations_manpage-ParameterLayout[`@ParameterLayout`], xref:rg.adoc#_rg_annotations_manpage-PropertyLayout[`@PropertyLayout`], and xref:rg.adoc#_rg_annotations_manpage-ViewModelLayout[`@ViewModelLayout`]
http://git-wip-us.apache.org/repos/asf/isis/blob/9c5dafab/adocs/documentation/src/main/asciidoc/guides/_rg_services-api.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_services-api.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_services-api.adoc
new file mode 100644
index 0000000..1e9b436
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_services-api.adoc
@@ -0,0 +1,282 @@
+[[_rg_services-api]]
+= Domain 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/
+
+
+Apache Isis includes an extensive number of domain services for your domain objects to use; simply define the service as an annotated field and Isis will inject the service into your object. These services' API are all defined in Isis' applib (`o.a.i.core:isis-core-applib` module); this minimizes the coupling between your code and Isis. It also allows you to easily mock out these services in your unit tests.
+
+[NOTE]
+====
+In addition there are a number of domain services that constitute an SPI; if present they are used by Isis itself rather than by your domain objects. A good example of this is the xref:rg.adoc#_rg_services-spi_manpage-AuditingService[`AuditingService3`] service. The SPI services are covered in the xref:rg.adoc#_rg_services-spi[Domain Services (SPI) chapter].
+====
+
+
+
+The table below summarizes all the APIs defined by Apache Isis. It also lists their corresponding implementation, either a default implementation provided by Isis itself, or provided by one of the in (non-ASF) link:http://www.isisaddons.org[Isis Addons] modules.
+
+.Domain Services
+[cols="3,3a,3a,3a", options="header"]
+|===
+
+|API
+|Description
+|Implementation
+|Notes
+
+
+|xref:rg.adoc#_rg_services-api_manpage-ActionInvocationContext[`o.a.i.applib.` +
+`services.actinv` +
+`ActionInvocation-` +
+`Context`]
+|Request-scoped access to whether action is invoked on object and/or on collection of objects
+|`ActionInvocationContext` +
+``o.a.i.core`` +
+``isis-core-applib``
+|API is also concrete class
+
+
+|xref:rg.adoc#_rg_services-api_manpage-BackgroundService[`o.a.i.applib.` +
+`services.background` +
+`BackgroundService`]
+|Programmatic persistence of commands to be persisted (so can be executed by a background mechanism, eg scheduler)
+|`BackgroundServiceDefault` +
+``o.a.i.core`` +
+``isis-core-runtime``
+|depends on: +
+xref:rg.adoc#_rg_services-spi_manpage-BackgroundCommandService[`BackgroundCommand-Service`]
+
+
+|xref:rg.adoc#_rg_services-api_manpage-BookmarkService[`o.a.i.applib.` +
+`services.bookmark` +
+`BookmarkService`]
+|Convert object reference to a serializable "bookmark", and vice versa
+|`BookmarkServiceDefault` +
+``o.a.i.core`` +
+``isis-core-metamodel``
+|related services:
+`BookmarkHolder-` +
+`ActionContributions`,
+`BookmarkHolder-` +
+`Association-` +
+`Contributions`
+
+
+|xref:rg.adoc#_rg_services-api_manpage-ClockService[`o.a.i.applib.` +
+`services.clock` +
+`ClockService`]
+|Access the current time (and for testing, allow the time to be changed)
+|`ClockService` +
+``o.a.i.core`` +
+``isis-core-applib``
+|API is also a concrete class.
+
+
+|xref:rg.adoc#_rg_services-api_manpage-CommandContext[`o.a.i.applib.` +
+`services.command` +
+`CommandContext`]
+|Request-scoped access the current action that is being invoked, represented as a command object
+|`CommandContext` +
+``o.a.i.core`` +
+``isis-core-applib``
+|API is also a concrete class. +
+depends on: +
+xref:rg.adoc#_rg_services-spi_manpage-CommandService[`CommandService`] for persistent `Command`, else in-memory impl. used
+
+|xref:rg.adoc#_rg_services-api_manpage-DeepLinkService[`o.a.i.applib` +
+`services.deeplink` +
+`DeepLinkService`]
+|Obtain a URL to a domain object (eg for use within an email or report)
+|`DeepLinkServiceWicket` +
+``o.a.i.viewer`` +
+``isis-viewer-wicket-impl``
+|Implementation only usable within Wicket viewer
+
+
+|xref:rg.adoc#_rg_services-api_manpage-DomainObjectContainer[`o.a.i.applib` +
+`DomainObjectContainer`]
+|Generic repository to search, create and delete objects. Also miscellaneous other functions, eg obtain title of object.
+|`DomainObjectContainer-` +
+`Default` +
+``o.a.i.core`` +
+``isis-core-metamodel``
+|
+
+
+|xref:rg.adoc#_rg_services-api_manpage-EmailService[`o.a.i.applib.` +
+`services.email` +
+`EmailService`]
+|Send a HTML email, optionally with attachments.
+|`EmailServiceDefault` +
+``o.a.i.core`` +
+``isis-core-runtime``
+|
+
+
+|xref:rg.adoc#_rg_services-api_manpage-EventBusService[`o.a.i.applib.` +
+`services.eventbus` +
+`EventBusService`]
+|Programmatically post events to the internal event bus. Also used by Isis itself to broadcast domain events:
+
+* xref:rg.adoc#_rg_annotations_manpage-Action_domainEvent[`Action#domainEvent()`]
+* xref:rg.adoc#_rg_annotations_manpage-Property_domainEvent[`Property#domainEvent()`]
+* xref:rg.adoc#_rg_annotations_manpage-Collection_domainEvent[`Collection#domainEvent()`]
+|`EventBusServiceJdo` +
+``o.a.i.core`` +
+``isis-core-objectstore-jdo-datanucleus``
+|
+
+
+|xref:rg.adoc#_rg_services-api_manpage-GuiceBeanProvider[`o.a.i.applib.` +
+`services.guice` +
+`GuiceBeanProvider`]
+|Access to internal framework services initialized using Guice DI.
+|`GuiceBeanProviderWicket` +
+``o.a.i.core`` +
+``isis-viewer-wicket-impl``
+|
+
+
+|xref:rg.adoc#_rg_services-api_manpage-IsisJdoSupport[`o.a.i.applib.` +
+`services.jdosupport` +
+`IsisJdoSupport`]
+|Lower level access to the JDO Persistence API.
+|`IsisJdoSupportImpl` +
+``o.a.i.core`` +
+``isis-core-objectstore-jdo-datanucleus``
+|
+
+
+|xref:rg.adoc#_rg_services-api_manpage-MementoService[`o.a.i.applib.` +
+`services.memento` +
+`MementoService`]
+|Capture a serializable memento of a set of primitives or xref:rg.adoc#_rg_services-api_manpage-BookmarkService[bookmarks]. Primarily used internally, eg in support of commands/auditing.
+|`MementoServiceDefault` +
+``o.a.i.core`` +
+``isis-core-runtime``
+|
+
+
+|xref:rg.adoc#_rg_services-api_manpage-MetaModelService[`o.a.i.applib.` +
+`services.metamodel` +
+`MetaModelService`]
+|Access to certain information from the Isis metamodel.
+|`MetaModelServiceDefault` +
+``o.a.i.core`` +
+``isis-core-metamodel``
+|
+
+
+|xref:rg.adoc#_rg_services-api_manpage-QueryResultsCache[`o.a.i.applib.` +
+`services.` +
+`queryresultscache` +
+`QueryResultsCache`]
+|Request-scoped caching of the results of queries (or any data set generated by a given set of input arguments).
+|`QueryResultsCache` +
+``o.a.i.core`` +
+``isis-core-applib``
+|API is also a concrete class
+
+
+|xref:rg.adoc#_rg_services-api_manpage-ScratchPad[`o.a.i.applib.` +
+`services.scratchpad` +
+`Scratchpad`]
+|Request-scoped service for interchanging information between and aggregating over multiple method calls; in particular for use by "bulk" actions (invoking of an action for all elements of a collection)
+|`Scratchpad` +
+``o.a.i.core`` +
+``isis-core-applib``
+|API is also a concrete class
+
+
+|xref:rg.adoc#_rg_services-api_manpage-SudoService[`o.a.i.applib.` +
+`services.sudo` +
+`SudoService`]
+|For use in testing while running xref:rg.adoc#_rg_classes_super_manpage-FixtureScripts[fixture scripts], allows a block of code to run as a specified user account.
+|`SudoServiceDefault` +
+``o.a.i.core`` +
+``isis-core-runtime``
+|API is also a concrete class
+
+
+|xref:rg.adoc#_rg_services-api_manpage-WrapperFactory[`o.a.i.applib.` +
+`services.wrapper` +
+`WrapperFactory`]
+|Interact with another domain object "as if" through the UI (enforcing business rules, firing domain events)
+|`WrapperFactoryDefault` +
+``o.a.i.core`` +
+``isis-core-wrapper``
+|
+
+
+|xref:rg.adoc#_rg_services-api_manpage-XmlSnapshotService[`o.a.i.applib.` +
+`services.xmlsnapshot` +
+`XmlSnapshotService`]
+|Generate an XML representation of an object and optionally a graph of related objects.
+|`XmlSnapshotServiceDefault` +
+``o.a.i.core`` +
+``isis-core-runtime``
+|
+
+|===
+
+Key:
+
+* `o.a.i` is an abbreviation for `org.apache.isis`
+* `o.ia.m` is an abbreviation for `org.isisaddons.module`
+
+
+
+
+
+There is also a number of deprecated domain services.
+
+.Deprecated Domain Services
+[cols="3,3a,3a,3a", options="header"]
+|===
+
+|API
+|Description
+|Implementation
+|Notes
+
+|`o.a.i.applib.` +
+`annotation`
+`Bulk.InteractionContext`
+|Request-scoped access to whether action is invoked on object and/or on collection of objects
+|`Bulk.InteractionContext` +
+``o.a.i.core`` +
+``isis-core-applib``
+|Replaced by xref:rg.adoc#_rg_services-api_manpage-ActionInvocationContext[`ActionInvocationContext`]
+
+
+
+|===
+
+Key:
+
+* `o.a.i` is an abbreviation for `org.apache.isis`
+* `o.ia.m` is an abbreviation for `org.isisaddons.module`
+
+
+
+include::_rg_services-api_manpage-ActionInvocationContext.adoc[leveloffset=+1]
+include::_rg_services-api_manpage-BackgroundService.adoc[leveloffset=+1]
+include::_rg_services-api_manpage-BookmarkService.adoc[leveloffset=+1]
+include::_rg_services-api_manpage-ClockService.adoc[leveloffset=+1]
+include::_rg_services-api_manpage-CommandContext.adoc[leveloffset=+1]
+include::_rg_services-api_manpage-DeepLinkService.adoc[leveloffset=+1]
+include::_rg_services-api_manpage-DomainObjectContainer.adoc[leveloffset=+1]
+include::_rg_services-api_manpage-EmailService.adoc[leveloffset=+1]
+include::_rg_services-api_manpage-EventBusService.adoc[leveloffset=+1]
+include::_rg_services-api_manpage-GuiceBeanProvider.adoc[leveloffset=+1]
+include::_rg_services-api_manpage-IsisJdoSupport.adoc[leveloffset=+1]
+include::_rg_services-api_manpage-MementoService.adoc[leveloffset=+1]
+include::_rg_services-api_manpage-MetamodelService.adoc[leveloffset=+1]
+include::_rg_services-api_manpage-QueryResultsCache.adoc[leveloffset=+1]
+include::_rg_services-api_manpage-ScratchPad.adoc[leveloffset=+1]
+include::_rg_services-api_manpage-SudoService.adoc[leveloffset=+1]
+include::_rg_services-api_manpage-WrapperFactory.adoc[leveloffset=+1]
+include::_rg_services-api_manpage-XmlSnapshotService.adoc[leveloffset=+1]
+
+
http://git-wip-us.apache.org/repos/asf/isis/blob/9c5dafab/adocs/documentation/src/main/asciidoc/guides/_rg_services-api_manpage-ActionInvocationContext.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_services-api_manpage-ActionInvocationContext.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_services-api_manpage-ActionInvocationContext.adoc
new file mode 100644
index 0000000..e7c7119
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_services-api_manpage-ActionInvocationContext.adoc
@@ -0,0 +1,98 @@
+[[_rg_services-api_manpage-ActionInvocationContext]]
+= `ActionInvocationContext`
+: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 `ActionInvocationContext` domain service is a xref:rg.adoc#_rg_annotations_manpage-RequestScoped[`@RequestScoped`] service intended to support the implementation of "bulk" actions annotated with xref:rg.adoc#_rg_annotations_manpage-Action_invokeOn[`@Action#invokeOn()`]. This allows the user to select multiple objects in a table and then invoke the same action against all of them.
+
+When an action is invoked in this way, this service allows each object instance to "know where it is" in the collection; it acts a little like an iterator. In particular, an object can determine if it is the last object to be called, and so can perform special processing, eg to return a summary calculated result.
+
+== API
+
+The API defined by the service is:
+
+[source,java]
+----
+@DomainService(nature = NatureOfService.DOMAIN)
+@RequestScoped // <1>
+public static class ActionInvocationContext {
+ public InvokedOn getInvokedOn() { ... } // <2>
+ public List<Object> getDomainObjects() { ... } // <3>
+ public int getSize() { ... }
+ public int getIndex() { ... } // <4>
+ public boolean isFirst() { ... }
+ public boolean isLast() { ... }
+}
+----
+<1> is xref:rg.adoc#_rg_annotations_manpage-RequestScoped[`@RequestScoped`], so this domain service instance is scoped to a particular request and is then destroyed
+<2> an enum set to either `OBJECT` (if action has been invoked on a single object) or `COLLECTION` (if has been invoked on a collection).
+<3> returns the list of domain objects which are being acted upon
+<4> is the 0-based index to the object being acted upon.
+
+
+
+== Usage
+
+For actions that are void or that return null, Isis will return to the list once executed. But for bulk actions that are non-void, Isis will render the returned object/value from the last object invoked (and simply discards the object/value of all actions except the last).
+
+One idiom is for the domain objects to also use the xref:rg.adoc#_rg_services-api_manpage-Scratchpad[`Scratchpad`] service to share information, for example to aggregate values. The `ActionInvocationContext#isLast()` method can then be used to determine if all the information has been gathered, and then do something with it (eg derive variance across a range of values, render a graph etc).
+
+More prosaically, the `ActoinInvocationContext` can be used to ensure that the action behaves appropriately depending on how it has been invoked (on a single object and/or a collection) whether it is called in bulk mode or regular mode. Here's a snippet of code from the bulk action in the Isis addon example https://github.com/isisaddons/isis-app-todoapp/[todoapp] (not ASF):
+
+[source,java]
+----
+public class ToDoItem ... {
+ @Action(invokeOn=InvokeOn.OBJECTS_AND_COLLECTIONS)
+ public ToDoItem completed() {
+ setComplete(true);
+ ...
+ return actionInteractionContext.getInvokedOn() == InvokedOn.OBJECT
+ ? this // <1>
+ : null; // <2>
+ }
+ @Inject
+ ActionInteractionContext actionInteractionContext;
+}
+----
+<1> if invoked as a regular action, return this object;
+<2> otherwise (if invoked on collection of objects), return null, so that the xref:ug.adoc#_ug_wicket-viewer[Wicket viewer] will re-render the list of objects
+
+
+
+
+== Registering the Service
+
+Assuming that the `configuration-and-annotation` services installer is configured:
+
+[source,ini]
+----
+isis.services-installer=configuration-and-annotation
+----
+
+then Isis' default implementation of `ActionInvocationContext` class is automatically registered (it is annotated with `@DomainService`) so no further configuration is required.
+
+
+
+== Unit testing support
+
+The `ActionInvocationContext` class also has a couple of static factory methods intended to support unit testing:
+
+[source,java]
+----
+@DomainService(nature = NatureOfService.DOMAIN)
+@RequestScoped
+public class ActionInvocationContext {
+ public static ActionInvocationContext onObject(final Object domainObject) {
+ return new ActionInvocationContext(InvokedOn.OBJECT, Collections.singletonList(domainObject));
+ }
+ public static ActionInvocationContext onCollection(final Object... domainObjects) {
+ return onCollection(Arrays.asList(domainObjects));
+ }
+ public static ActionInvocationContext onCollection(final List<Object> domainObjects) {
+ return new ActionInvocationContext(InvokedOn.COLLECTION, domainObjects);
+ }
+ ...
+}
+----
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/9c5dafab/adocs/documentation/src/main/asciidoc/guides/_rg_services-api_manpage-BackgroundService.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_services-api_manpage-BackgroundService.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_services-api_manpage-BackgroundService.adoc
new file mode 100644
index 0000000..7af9a1f
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_services-api_manpage-BackgroundService.adoc
@@ -0,0 +1,123 @@
+[[_rg_services-api_manpage-BackgroundService]]
+= `BackgroundService`
+: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 `BackgroundService`, and the companion xref:rg.adoc#_rg_services-spi_manpage-BackgroundCommandService[`BackgroundCommandService`] SPI service (used by Isis itself), enable action invocations to be persisted such that they may be invoked in the background.
+
+The `BackgroundService` is responsible for capturing a memento representing the action invocation in a typesafe way, and persisting it rather than executing it directly.
+
+The default `BackgroundServiceDefault` implementation (provided by isis-core) works by using a proxy wrapper around the target so that it can capture the action to invoke and its arguments using (a private copy of) xref:rg.adoc#_rg_services-api_manpage-MementoService[`MementoService`]. The persistence delegates the persistence of the memento to an appropriate implementation of the companion `BackgroundCommandService`. One such implementation of `BackgroundCommandService` is provided by (non-ASF) http://github.com/isisaddons/isis-module-command[Isis addons' command] module.
+
+The persisting of commands is only half the story; there needs to be a separate process to read the commands and execute them. The `BackgroundCommandExecution` abstract class (discussed xref:rg.adoc#_rg_services-api_manpage-BackgroundService_BackgroundCommandExecution[below]) provides infrastructure to do this; the concrete
+implementation of this class depends on the configured `BackgroundCommandService` (in order to query for the persisted (background) ``Command``s.
+
+
+
+== API & Implementation
+
+Returns a proxy around the object which is then used to obtain the signature of the action to be invoked in the background.
+
+[source,java]
+----
+public interface BackgroundService {
+ @Programmatic
+ <T> T execute(final T object);
+}
+----
+
+The default implementation is provided by core (`o.a.i.core.runtime.services.background.BackgroundServiceDefault`).
+
+
+
+== Usage
+
+Using the service is very straight-forward; wrap the target domain object using `BackgroundService#execute(...)` and invoke the method on the object returned by that method.
+
+For example:
+
+[source,java]
+----
+public void submitCustomerInvoices() {
+ for(Customer customer: customerRepository.findCustomersToInvoice()) {
+ backgroundService.execute(customer).submitInvoice();
+ }
+ container.informUser("Calculating...");
+}
+----
+
+This will create a bunch of background commands executing the `submitInvoice()` action for each of the customers returned from the customer repository.
+
+The action method invoked must be part of the Isis metamodel, which is to say it must be public, accept only scalar arguments, and must not be annotated with xref:rg.adoc#_rg_annotations_manpage-Programmatic[`@Programmatic`] or `@Ignore`. However, it may be annotated with xref:rg.adoc#_rg_annotations_manpage-Action_hidden[`@Action#hidden()`] or xref:rg.adoc#_rg_annotations_manpage-ActionLayout_hidden[`@ActionLayout#hidden()`] and it will still be invoked.
+
+In fact, when invoked by the background service, no business rules (hidden, disabled, validation) are enforced; the action method must take responsibility for performing appropriate validation and error checking.
+
+[TIP]
+====
+If you want to check business rules, you can use xref:rg.adoc#_rg_annotations_manpage-WrapperFactory[`@WrapperFactory#wrapNoExecute(...)`].
+====
+
+
+
+== End-user experience
+
+For the end-user, executing an action that delegates work off to the `BackgroundService` raises the problem of how does the user know the work is complete?
+
+One option is for the background jobs to take responsibility to notify the user themselves. In the above example, this would be the `submitInvoice()` method called upon each customer. One could imagine more complex designs where only the final command executed notifies the user.
+
+However, an alternative is to rely on the fact that the `BackgroundService` will automatically hint that the `Command` representing the original interaction (to `submitCustomerInvoices()` in the example above) should be persisted. This will be available if the related xref:rg.adoc#_rg_services-api_manpage-CommandContext[`CommandContext`] and xref:rg.adoc#_rg_services-spi_manpage-CommandService[`CommandService`] domain services are configured, and the `CommandService` supports persistent commands. Note that (non-ASF) http://github.com/isisaddons/isis-module-command[Isis addons' command] module does indeed provide such an implementation of `CommandService` (as well as of the required `BackgroundCommandService`).
+
+Thus, the original action can run a query to obtain it corresponding `Command`, and return this to the user. The upshot is that the child ``Command``s created by the `BackgroundService` will then be associated with `Command` for the original action.
+
+We could if we wanted write the above example as follows:
+
+[source,java]
+----
+public Command submitCustomerInvoices() {
+ for(Customer customer: customerRepository.findCustomersToInvoice()) {
+ backgroundService.execute(customer).submitInvoice();
+ }
+ return commandContext.getCommand();
+}
+@Inject
+CommandContext commandContext; // <1>
+----
+<1> the injected xref:rg.adoc#_rg_services-api_manpage-CommandContext[`CommandContext`] domain service.
+
+The user would be returned a domain object representing their action invocation.
+
+
+
+
+== Registering the Services
+
+Assuming that the `configuration-and-annotation` services installer is configured:
+
+[source,ini]
+----
+isis.services-installer=configuration-and-annotation
+----
+
+then Isis' core implementation of `BackgroundService` is automatically registered (it is annotated with `@DomainService`) so no further configuration is required.
+
+
+
+== Related Services
+
+This service is closely related to the xref:rg.adoc#_rg_services-api_manpage-CommandContext[`CommandContext`] and also that service's supporting xref:rg.adoc#_rg_services-spi_manpage-CommandService[`CommandService`] service.
+
+The `CommandContext` service is responsible for providing a parent `Command` with which the background ``Command``s can then be associated as children, while the `CommandService` is responsible for persisting those parent `Command`s. The latter is analogous to the way in which the `BackgroundCommandService` persists the child background `Command`s.
+
+The implementations of `CommandService` and `BackgroundCommandService` go together; typically both parent `Command`s and child background `Command`s will be persisted in the same way. The (non-ASF) http://github.com/isisaddons/isis-module-command[Isis addons' command] module provides implementations of both (see xref:rg.adoc#_rg_services-spi_manpage-CommandService[`CommandService`] and xref:rg.adoc#_rg_services-spi_manpage-BackgroundCommandService[`BackgroundCommandService`]).
+
+
+include::_rg_services-api_manpage-BackgroundService_BackgroundCommandExecution.adoc[leveloffset=+1]
+include::_rg_services-api_manpage-BackgroundService_Quartz.adoc[leveloffset=+1]
+
+
+
+
+
+
http://git-wip-us.apache.org/repos/asf/isis/blob/9c5dafab/adocs/documentation/src/main/asciidoc/guides/_rg_services-api_manpage-BackgroundService_BackgroundCommandExecution.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_services-api_manpage-BackgroundService_BackgroundCommandExecution.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_services-api_manpage-BackgroundService_BackgroundCommandExecution.adoc
new file mode 100644
index 0000000..971c6c8
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_services-api_manpage-BackgroundService_BackgroundCommandExecution.adoc
@@ -0,0 +1,25 @@
+[[_rg_services-api_manpage-BackgroundService_BackgroundCommandExecution]]
+= `BackgroundCommandExecution` abstract class
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+:_basedir: ../
+:_imagesdir: images/
+
+
+The `BackgroundCommandExecution` (in isis-core) is an abstract template class provided by isis-core that defines an abstract hook method to obtain background `Command`s to be executed:
+
+[source,java]
+----
+public abstract class BackgroundCommandExecution
+ extends AbstractIsisSessionTemplate {
+ ...
+ protected abstract List<? extends Command> findBackgroundCommandsToExecute();
+ ...
+}
+----
+
+The developer is required to implement this hook method in a subclass.
+
+
+
+
+
http://git-wip-us.apache.org/repos/asf/isis/blob/9c5dafab/adocs/documentation/src/main/asciidoc/guides/_rg_services-api_manpage-BackgroundService_Quartz.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_services-api_manpage-BackgroundService_Quartz.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_services-api_manpage-BackgroundService_Quartz.adoc
new file mode 100644
index 0000000..3802803
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_services-api_manpage-BackgroundService_Quartz.adoc
@@ -0,0 +1,162 @@
+[[_rg_services-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>
+----
+