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 2010/11/28 13:49:01 UTC
svn commit: r1039874 [4/5] - in /incubator/isis/trunk: ./
alternatives/remoting/src/docbkx/guide/
alternatives/security/file/src/docbkx/guide/
alternatives/security/ldap/src/docbkx/guide/ applib/src/docbkx/guide/
core/metamodel/src/test/java/org/apache...
Modified: incubator/isis/trunk/core/src/docbkx/guide/isis-core.xml
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/core/src/docbkx/guide/isis-core.xml?rev=1039874&r1=1039873&r2=1039874&view=diff
==============================================================================
--- incubator/isis/trunk/core/src/docbkx/guide/isis-core.xml (original)
+++ incubator/isis/trunk/core/src/docbkx/guide/isis-core.xml Sun Nov 28 12:49:00 2010
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-"file:./src/docbkx/dtd-4.5/docbookx.dtd">
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"file:./src/docbkx/dtd-4.5/docbookx.dtd">
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -66,82 +66,5470 @@
url="http://www.apache.org/licenses/LICENSE-2.0.html">Apache Software
License v2</ulink>.</para>
- <para>This guide is written for programmers looking to use
- <emphasis>Apache Isis</emphasis> to develop domain-driven applications.
- Since Isis is also extensible, it also explains all the
- <acronym>API</acronym>s in the core framework and their default
- implementations, as well as the mechanics of deploying an Isis
- application.</para>
+ <para>This guide is written for programmers looking to understand how
+ <emphasis>Apache Isis</emphasis> fits together, what APIs it defines, what
+ the default implementations are. It also explains the principles of
+ deploying an Isis application and describes how to do so as a standalone
+ or as a webapp.</para>
</preface>
<!-- main content -->
<part>
- <title>Programmers Guide</title>
+ <title>Introduction and Architecture</title>
+
+ <partintro>
+ <para>*** part intro.</para>
+
+ <para></para>
+
+ <para></para>
+ </partintro>
<chapter id="chp.Intro">
- <title>Introduction</title>
+ <title>Overview</title>
<abstract>
- <para>*** yada yada</para>
+ <para>This chapter gives an overview of the main principles and
+ patterns that underly the Apache Isis approach.</para>
</abstract>
- <sect1>
- <title>***</title>
+ <sect1>
+ <title>Introduction</title>
+
+ <para><emphasis>Apache Isis</emphasis> is a full-stack open source
+ application development framework, designed to let you rapidly develop
+ enterprise business applications following a domain-driven philosophy.
+ Developing an application in Isis is - at least initially - about
+ focusing on the bit that matters to the business, the core domain
+ logic.</para>
+
+ <para></para>
+
+ <para></para>
+ </sect1>
+
+ <sect1>
+ <title>Principles</title>
+
+ <para><emphasis></emphasis></para>
+
+ <para><emphasis></emphasis><note>
+ <para>TODO: distill some of the material on the trunk site.</para>
+
+ <para></para>
+ </note></para>
+
+ <sect2>
+ <title>Ubiquitous Language</title>
+
+ <para></para>
+
+ <para></para>
+
+ <para></para>
+
+ <para></para>
+ </sect2>
+
+ <sect2>
+ <title>Rapid Application Development</title>
+
+ <para></para>
+
+ <para></para>
+
+ <note>
+ <para>TODO: discuss</para>
+ </note>
+
+ <para>feedback loop</para>
+
+ <para>requirements traceability</para>
+
+ <para></para>
+ </sect2>
+
+ <sect2>
+ <title>Problem Solver, not Process Follower</title>
+
+ <para></para>
+
+ <para></para>
+
+ <note>
+ <para>TODO: discuss</para>
+ </note>
+
+ <para>Sovereign Applications vs Transient Applications</para>
+
+ <para></para>
+
+ <para>for sovereign applications</para>
+
+ <para></para>
+
+ <para>incredible machine</para>
+
+ <para></para>
+
+ <para></para>
+ </sect2>
+
+ <sect2>
+ <title>Commonly Trodden Paths</title>
+
+ <para></para>
+
+ <para></para>
+
+ <note>
+ <para>TODO: discuss</para>
+ </note>
+
+ <para>for transient apps</para>
+
+ <para></para>
+
+ <para>Civil engineering analogy.... put in the paths
+ afterwards</para>
+
+ <para></para>
+
+ <para>Christopher Alexander - cardboard cutouts of where the windows
+ go</para>
+
+ <para></para>
+
+ <para>Database denormalization</para>
+
+ <para></para>
+
+ <para>MVVM</para>
+
+ <para></para>
+
+ <para>Process Object</para>
+
+ <para></para>
+ </sect2>
+
+ <sect2>
+ <title>Opinionated</title>
+
+ <para></para>
+
+ <para></para>
+
+ <note>
+ <para>TODO: discuss</para>
+ </note>
+
+ <para></para>
+
+ <para>convention over configuration</para>
+
+ <para></para>
+
+ <para>framework, domain services, dependency injection</para>
+
+ <para></para>
+
+ <para>JSR-299</para>
+
+ <para>don't want too many degrees of freedom. Work out of the box,
+ specify alternates later as needed</para>
+
+ <para></para>
+ </sect2>
+ </sect1>
+
+ <sect1>
+ <title>Patterns</title>
+
+ <para>The framework is designed around two patterns:</para>
+
+ <para></para>
+
+ <sect2>
+ <title>Naked Objects Pattern</title>
+
+ <para>The first architectural pattern is the naked objects pattern,
+ whereby the framework automatically generates an object-oriented
+ user interface (OOUI) for your domain objects. If required, this
+ OOUI can then be customized.</para>
+
+ <para></para>
+ </sect2>
+
+ <sect2>
+ <title>Hexagonal Architecture</title>
+
+ <para>The second core pattern implemented by <emphasis>Apache
+ Isis</emphasis> is the hexagonal architecture. This means it allows
+ the same domain model to be run with different viewers, either as a
+ desktop app or as a webapp. Equally, you can choose which object
+ store to use in order to persist your domain objects. The diagram
+ below shows the hexagonal architecture as it is implemented by
+ Apache Isis.</para>
+
+ <para></para>
+
+ <para></para>
+
+ <note>
+ <para>TODO: discuss</para>
+ </note>
+
+ <para>*** picture of the hexagonal architecture here.</para>
+
+ <para></para>
+
+ <para></para>
+ </sect2>
+
+ <sect2>
+ <title>Dependency Injection</title>
+
+ <para></para>
+
+ <para></para>
+
+ <para></para>
+ </sect2>
+ </sect1>
+
+ <sect1>
+ <title>Benefits and Consequences</title>
+
+ <para></para>
+
+ <para><note>
+ <para>TODO: review stuff below, copied-n-pasted from site
+ docs.</para>
+ </note></para>
+
+ <para>As you might imagine, not needing to write any GUI code
+ substantially speeds up development, and shortens the feedback loop to
+ allow you to improve your core domain model without lots of GUI code
+ slowing you down.</para>
+
+ <para>The OOUIs generated by Apache Isis are especially suitable to
+ "expert" users, typically those internal to your organization who have
+ a good understanding of the domain and just want to get their job
+ done. But for less expert users (or for a webapp deployed on the
+ internet), a more scripted UI may be called for. Isis therefore lets
+ you customize the user interface according to your users'
+ needs.</para>
+
+ <para>Alternatively, you might want to just use Isis as a design tool.
+ The framework goes to a lot of trouble to ensure that the domain
+ objects you build have no dependencies on the framework: they are
+ basically annotated pojos that follow a number of straightforward
+ programming conventions. So, you can use Isis to rapidly evolve your
+ domain objects, and then deploy them within some other runtime
+ framework if you wish.</para>
+
+ <para></para>
+
+ <para></para>
+
+ <note>
+ <para>TODO: include some of the benefits cited for NO pattern, from
+ website: faster development cycle, greater agility, empowering style
+ of UI, requirements analysis/traceability; play to developer
+ strengths</para>
+ </note>
+
+ <para></para>
+
+ <sect2>
+ <title>Playing to Developer Strengths</title>
+
+ <para></para>
+
+ <para></para>
+
+ <note>
+ <para>TODO: discuss</para>
+ </note>
+
+ <para>domain programmer/business analyst</para>
+
+ <para></para>
+
+ <para>application integration expert (domain services)</para>
+
+ <para></para>
+
+ <para>customizer (UI expert)</para>
+
+ <para></para>
+
+ <para>architectural integration</para>
+
+ <para></para>
+ </sect2>
+ </sect1>
+ </chapter>
+
+ <chapter>
+ <title>Running the QuickApp Archetype</title>
+
+ <para>*** talk through using the "quickapp" archetype, which generates a
+ read-to-run app.</para>
+
+ <para></para>
+
+ <para></para>
+
+ <sect1>
+ <title>Run Archetype</title>
+
+ <para></para>
+
+ <para></para>
+
+ <para></para>
+
+ <para>Using Maven archetype plugin we can generate a new [[NAME]]
+ application very quickly. These are multi-moduled projects with
+ separate sections for the domain code, fixtures, web interfaces and so
+ on.</para>
+
+ <para>One option is to create the archetype from the commandline. Note
+ that if you are using Eclipse and have installed the m2eclipse plugin
+ then it provides a dialog to create the project from an archetype;
+ this is discussed below.</para>
+
+ <remark>TODO: update the listing below, it is out of date. The
+ archetype to use is called
+ 'org.apache.isis:application-archetype'.</remark>
+
+ <screen>[rcm@localhost ~]$ <emphasis role="bold">mvn archetype:generate -DarchetypeCatalog=http://isis.apache.org</emphasis>
+[INFO] Scanning for projects...
+[INFO] Searching repository for plugin with prefix: 'archetype'.
+[INFO] ------------------------------------------------------------------------
+[INFO] Building Maven Default Project
+[INFO] task-segment: [archetype:generate] (aggregator-style)
+[INFO] ------------------------------------------------------------------------
+[INFO] Preparing archetype:generate
+[INFO] No goals needed for project - skipping
+[INFO] Setting property: classpath.resource.loader.class => 'org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader'.
+[INFO] Setting property: velocimacro.messages.on => 'false'.
+[INFO] Setting property: resource.loader => 'classpath'.
+[INFO] Setting property: resource.manager.logwhenfound => 'false'.
+[INFO] [archetype:generate]
+[INFO] Generating project in Interactive mode
+[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)
+Choose archetype:
+1: local -> isis-application ([[NAME]] Application (Archetype))
+2: local -> isis-icons ([[NAME]] Icons (Archetype))
+3: local -> htmlviewer-war ([[NAME]] WAR (Archetype))
+4: local -> hibernate-support (Hibernate Support (Archetype))
+5: local -> remoting-support ([[NAME]] Remoting Support (Archetype))
+Choose a number: (1/2/3/4/5): <emphasis role="bold">1</emphasis></screen>
+
+ <para>To create a project from an archetype you must specify a
+ <emphasis>groupId</emphasis> and <emphasis>artifactId</emphasis>, a
+ <emphasis>version</emphasis> and a <emphasis>Java
+ package</emphasis>.</para>
+
+ <para>After choosing the archetype number and pressing enter you are
+ prompted for the project's details. The <emphasis>groupId</emphasis>
+ is an identifier representing your company/group; ours would typically
+ be "org.apache.isis" for the domain followed by a name for the group
+ of products. The <emphasis>artifactId</emphasis> identifies the
+ projects that we are creating. The <emphasis>version</emphasis>
+ indicates how mature the project is, and should be left as the
+ default, e.g. 1.0-SNAPSHOT. Finally, the <emphasis>package</emphasis>
+ is the base package name used for all Java files. After these have
+ been entered you are prompted to confirm by entering Y, as shown
+ below.</para>
+
+ <para>Be wary of using invalid names. The <emphasis>groupId</emphasis>
+ should be alphanumeric with dots to separate the words. The
+ <emphasis>artifactId</emphasis> should also be alphanumeric, with '-'
+ (hyphens) to separate the words. The <emphasis>package</emphasis> name
+ should be a valid Java package name, i.e. should have no spaces or
+ dashes. Maven does little to check these things.</para>
+
+ <screen>Define value for groupId: : <emphasis role="bold">org.example</emphasis>
+Define value for artifactId: : <emphasis role="bold">expenses</emphasis>
+Define value for version: 1.0-SNAPSHOT: :
+Define value for package: : <emphasis role="bold">org.example.expenses</emphasis>
+Confirm properties configuration:
+groupId: org.example
+artifactId: expenses
+version: 1.0-SNAPSHOT
+package: org.example.expenses
+ Y: : <emphasis role="bold">y</emphasis>
+[INFO] ------------------------------------------------------------------------
+[INFO] BUILD SUCCESSFUL
+[INFO] ------------------------------------------------------------------------
+[INFO] Total time: 1 minute 13 seconds
+[INFO] Finished at: Thu Oct 02 20:42:50 BST 2008
+[INFO] Final Memory: 13M/247M
+[INFO] ------------------------------------------------------------------------
+</screen>
+
+ <para>This will create a new directory with the name of the
+ <emphasis>artifactId</emphasis>. So in this example this is
+ <filename>expenses</filename> as shown below.<screen>expenses
+|-- pom.xml
+|-- dom
+| |-- pom.xml
+| `-- src
+|-- commandline
+| |-- config
+| |-- ide
+| |-- pom.xml
+| `-- src
+|-- fixture
+| |-- pom.xml
+| `-- src
+|-- service
+| |-- pom.xml
+| `-- src
+`-- webapp
+ |-- pom.xml
+ `-- src</screen></para>
+
+ <para></para>
+ </sect1>
+
+ <sect1>
+ <title>Building the application</title>
+
+ <para>Once an archetype is created it can be built using Maven and
+ run. Build using the <emphasis>install</emphasis> goal as shown
+ here.</para>
+
+ <screen>[rcm@localhost expenses]$ <emphasis role="bold">mvn clean install</emphasis>
+[INFO] Scanning for projects...
+[INFO] Reactor build order:
+[INFO] [[NAME]] Application
+[INFO] Domain Model
+[INFO] Services
+[INFO] Fixtures
+[INFO] Exploration
+[INFO] ------------------------------------------------------------------------
+[INFO] Building [[NAME]] Application
+[INFO] task-segment: [clean, install]
+[INFO] ------------------------------------------------------------------------
+[INFO] [clean:clean]
+[INFO] [site:attach-descriptor]
+[INFO] [install:install]
+[INFO] Installing /home/rcm/tmp/bearingpoint/expenses/pom.xml to /home/rcm/.m2/repository/org/example/expenses/1.0-SNAPSHOT/expenses-1.0-SNAPSHOT.pom
+[INFO] ------------------------------------------------------------------------
+[INFO] Building Domain Model
+[INFO] task-segment: [clean, install]
+[INFO] ------------------------------------------------------------------------
+[INFO] [clean:clean]
+[INFO] Deleting directory /home/rcm/tmp/bearingpoint/expenses/dom/target
+[INFO] [resources:resources]
+[INFO] Using default encoding to copy filtered resources.
+[INFO] [compiler:compile]
+[INFO] Compiling 7 source files to /home/rcm/tmp/bearingpoint/expenses/dom/target/classes
+[INFO] [resources:testResources]
+[INFO] Using default encoding to copy filtered resources.
+:
+:
+[INFO] [resources:testResources]
+[INFO] Using default encoding to copy filtered resources.
+[INFO] [compiler:testCompile]
+[INFO] No sources to compile
+[INFO] [surefire:test]
+[INFO] No tests to run.
+[INFO] [jar:jar]
+[INFO] Building jar: /home/rcm/tmp/bearingpoint/expenses/exploration/target/expenses.jar
+[INFO] [assembly:attached {execution: default}]
+[INFO] Reading assembly descriptor: src/main/assembly/descriptor.xml
+[INFO] Processing DependencySet (output=lib)
+[INFO] Copying files to /home/rcm/tmp/bearingpoint/expenses/exploration/target/expenses-exploration-1.0-SNAPSHOT-prototype.dir
+[WARNING] Assembly file: /home/rcm/tmp/bearingpoint/expenses/exploration/target/expenses-exploration-1.0-SNAPSHOT-prototype.dir is not a regular file (it may be a directory). It cannot be attached to the project build for installation or deployment.
+[INFO] [install:install]
+[INFO] Installing /home/rcm/tmp/bearingpoint/expenses/exploration/target/expenses.jar to /home/rcm/.m2/repository/org/example/expenses-exploration/1.0-SNAPSHOT/expenses-exploration-1.0-SNAPSHOT.jar
+[INFO]
+[INFO]
+[INFO] ------------------------------------------------------------------------
+[INFO] Reactor Summary:
+[INFO] ------------------------------------------------------------------------
+[INFO] [[NAME]] Application .............................. SUCCESS [6.087s]
+[INFO] Domain Model .......................................... SUCCESS [8.711s]
+[INFO] Services .............................................. SUCCESS [2.432s]
+[INFO] Fixtures .............................................. SUCCESS [2.283s]
+[INFO] Commandline ........................................... SUCCESS [10.774s]
+[INFO] ------------------------------------------------------------------------
+[INFO] ------------------------------------------------------------------------
+[INFO] BUILD SUCCESSFUL
+[INFO] ------------------------------------------------------------------------
+[INFO] Total time: 31 seconds
+[INFO] Finished at: Tue Mar 03 11:59:50 GMT 2009
+[INFO] Final Memory: 40M/495M
+[INFO] ------------------------------------------------------------------------
+[rcm@localhost expenses]$ </screen>
+
+ <para>Once the project is built the results can be found in the
+ <filename>exploration/target</filename> directory, which contains both
+ a zipped distribution (in this example
+ <filename>expenses-exploration-1.0-SNAPSHOT-prototype.zip</filename>)
+ and an expanded distribution (again for this example,
+ <filename>expenses-exploration-1.0-SNAPSHOT</filename>). Using the
+ contained script files the application can be run from the command
+ line.<screen>exploration
+|-- config
+|-- ide
+|-- pom.xml
+|-- src
+`-- target
+ |-- archive-tmp
+ |-- classes
+ |-- expenses-exploration-1.0-SNAPSHOT-prototype.dir
+ | `-- expenses-exploration-1.0-SNAPSHOT
+ | |-- config
+ | |-- images
+ | |-- expenses.jar
+ | |-- isis.bat
+ | |-- isis.sh
+ | |-- lib
+ |-- expenses-exploration-1.0-SNAPSHOT-prototype.zip
+ |-- expenses.jar
+ `-- maven-archiver</screen></para>
+ </sect1>
+
+ <sect1>
+ <title>Running with the DnD Viewer</title>
+
+ <para>*** below was taken from the tutorial on running the old
+ expenses demo</para>
+
+ <para></para>
+
+ <para>The executable version of the Expenses demo application exists
+ within the <filename class="directory"
+ moreinfo="none">demos</filename> directory of the [[NAME]]
+ distribution.</para>
+
+ <para>Run the batch file <filename class="directory"
+ moreinfo="none">ExpensesDND.bat</filename> file either by
+ double-clicking on the icon (in Windows) or using the following
+ commands on the command line. In Windows the commands are</para>
+
+ <programlisting>> cd demos\expenses
+> ExpensesDND.bat</programlisting>
+
+ <para>while on the Mac or when using Unix/Linux they are:</para>
+
+ <programlisting>> cd demos/expenses
+> ./ExpensesDND.sh</programlisting>
+
+ <para>After seeing the [[NAME]] splash screen, you'll be presented
+ with a Login screen:</para>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata contentwidth="40%" fileref="images/log-on-dnd.png"
+ format="PNG" />
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <para>Log in as 'sven' and a password of 'pass'. The application will
+ then open like this:</para>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata contentwidth="40%" fileref="images/home-dnd.png"
+ format="PNG" />
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <para>When an application is started an application window is opened
+ and the user's services are displayed on the left hand side. These
+ icons typically give the user access to the domain objects held and
+ used by the system, and provide a way for to create new instances. Any
+ other object that subsequently appears on the screen represents one of
+ those objects.</para>
+
+ <remark>TODO replace with up-to-date shot using current
+ example</remark>
+
+ <screenshot>
+ <screeninfo></screeninfo>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata contentwidth="40%" fileref="images/dnd-example.png" />
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <para>The service and objects can be manipulated as follows:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Object actions can be invoked by
+ <emphasis>right-clicking</emphasis> on an icon and selecting one
+ of the options from the menu.</para>
+ </listitem>
+
+ <listitem>
+ <para>Resource actions can be invoked by
+ <emphasis>right-clicking</emphasis> on a resource icon.To inspect
+ an object (when only an icon is shown)
+ <emphasis>double-click</emphasis> it - this normally opens up the
+ object in a new window.</para>
+ </listitem>
+
+ <listitem>
+ <para>Objects can be dragged by
+ <emphasis>click-dragging</emphasis> on the icons and dropped by
+ releasing the mouse button.</para>
+ </listitem>
+
+ <listitem>
+ <para>Dragged objects can be dropped on an empty object field
+ (identified by the grey hole; the label to the right of the hole
+ specifies what type of object can be dropped). If the object can
+ be dropped into that field then it will flash green. If the object
+ cannot be dropped - either because it is the wrong type or that
+ specific object is disallowed for some other reason - then the
+ field will flash red. Dropping an object into a field sets up that
+ field, effectively associating the two objects.</para>
+ </listitem>
+
+ <listitem>
+ <para>Dragged objects can be dropped on to other object icons. If
+ the object that you attempting to drop onto accepts that type of
+ object then if will flash green. If that object does not accept
+ that kind of object, or disallows that specific object, then it
+ will flash red. Dropping one object on to another invokes a
+ specific object action, for example: add this product to that
+ order.</para>
+ </listitem>
+
+ <listitem>
+ <para>To quit the application, or access other application related
+ options right-click on the desktop to bring up the system
+ menu.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para></para>
+ </sect1>
+
+ <sect1>
+ <title>Running with the HTML Viewer</title>
+
+ <para>*** below was taken from the tutorial on running the old
+ expenses demo</para>
+
+ <para></para>
+
+ <para>2</para>
+
+ <para>To run the expenses demo with the HTML user interface, run the
+ batch file <filename class="directory"
+ moreinfo="none">ExpensesHTML.bat</filename> either by double-clicking
+ on the icon (in Windows) or using the following commands on the
+ command line. In Windows the commands are.</para>
+
+ <programlisting>> cd demos\expenses
+> ExpensesHTML.bat</programlisting>
+
+ <para>while on the Mac or when using Unix/Linux they are:</para>
+
+ <programlisting>> cd demos/expenses
+> ./ExpensesHTML.sh</programlisting>
+
+ <para>Allowing a few seconds for the application to start up, you then
+ need to launch a browser and point it to <filename class="directory"
+ moreinfo="none">http://localhost:8080/logon.app</filename> and you'll
+ be presented with a Login screen.</para>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata contentwidth="40%" fileref="images/html-login.png"
+ format="PNG" />
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <para>Log in as 'sven' and a password of 'pass'. This will direct you
+ to the start page of the application, a welcome page is displayed and
+ links to the application resources are shown across the top. In the
+ same ways as for dnd these links give the user access to the objects
+ held and used by the system and provide a way for to create new
+ objects. Any other object that subsequently appears on the screen
+ represents one of those objects.</para>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata contentdepth="40%" fileref="images/html-start.png"
+ format="PNG" />
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <para>For example if the claims link is clicked on within the expenses
+ demo the claims service page is shown with the resource actions
+ available in a menu on the left hand side of the screen.</para>
+
+ <screenshot>
+ <screeninfo></screeninfo>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata contentwidth="40%"
+ fileref="images/html-exampl-claims.png" />
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <itemizedlist>
+ <listitem>
+ <para>Object actions can be invoked by clicking on one of the of
+ the options from the left hand menu.</para>
+ </listitem>
+
+ <listitem>
+ <para>Resource actions can be invoked clicking on a resource icon
+ link in the resource bar and then clicking on a menu item.</para>
+ </listitem>
+
+ <listitem>
+ <para>As objects are created or opened they are shown in an object
+ history beneath the resource bar.</para>
+ </listitem>
+
+ <listitem>
+ <para>Similarly the current context, i.e. the current nesting of
+ actions is shown beneath the object history.</para>
+ </listitem>
+ </itemizedlist>
+ </sect1>
+
+ <sect1>
+ <title>Running with the Scimpi Viewer</title>
+
+ <para></para>
+ </sect1>
+
+ <sect1>
+ <title>Running with the Restful Viewer</title>
+
+ <para></para>
+ </sect1>
+
+ <sect1>
+ <title>Running with the Wicket Viewer</title>
+
+ <para></para>
+ </sect1>
+
+ <sect1>
+ <title>Running the BDD (Concordion) Tests</title>
+
+ <para></para>
+ </sect1>
+ </chapter>
+
+ <chapter>
+ <title>Developing Isis Applications</title>
+
+ <abstract>
+ <para>This chapter describes the general approach to follow that we
+ recommend for developing domain-driven applications on Isis.</para>
+ </abstract>
+
+ <sect1>
+ <title>Where to Start?</title>
+
+ <para>There's quite a lot to <emphasis>Apache Isis</emphasis>, with
+ lots of optional components (which we call alternates, in keeping with
+ JSR-299 terminology). To keep things manageable, the Isis
+ documentation is scoped closest to where it's relevant.</para>
+
+ <para>On the other hand, it can be difficult to know exactly where to
+ go in the first place... hence these notes. If you read them from top
+ to bottom then you'll (a) have a pretty good idea of the general
+ process we recommend for developing domain applications in
+ <emphasis>Apache Isis</emphasis> and (b) know where to look for more
+ detailed documentation.</para>
+ </sect1>
+
+ <sect1 id="sec.ApplicationArchetypes">
+ <title>Application Archetypes</title>
+
+ <para>We tend to structure Apache Isis applications following a
+ standard structure, and you can use the
+ <emphasis>application</emphasis> Maven archetype (in
+ <filename>support/archetypes/application</filename>) to set this up
+ for you. Some of the optional plugins also provide their own Maven
+ archetypes which you can run afterwards, for example to setup a
+ particular new viewer or object store. The idea is that these are run
+ alongside your own application, and provide additional Maven
+ (sub)modules which you can then reference.</para>
+
+ <para>Going back to the application archetype though, this sets up a
+ simple application that can be run out-of-the-box in exploration mode
+ (that is, with the in-memory object store), and using one of the two
+ main viewers:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the Drag-n-Drop (<acronym>DnD</acronym>) viewer is a
+ client-side viewer that renders the domain objects to a desktop
+ metaphor.</para>
+ </listitem>
+
+ <listitem>
+ <para>the <acronym>HTML</acronym> viewer is designed to run within
+ a webapp, and renders a single domain object per page.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Each of these can be run from the command line (the
+ <acronym>HTML</acronym> viewer boots up an instance of Jetty web
+ server); the archetype documentation explains how; there's further
+ documentation on these particular viewers themselves in their
+ respective module documentation (see <xref
+ linkend="sec.Viewers" />).</para>
+
+ <para>Later on you'll want to deploy the application more formally,
+ for example as a <acronym>WAR</acronym> archive (see <xref
+ linkend="sec.DeployingAnIsisApplication" /> for more details).</para>
+ </sect1>
+
+ <sect1>
+ <title>Programming Model</title>
+
+ <para>Once you've got the archetype application running, you're ready
+ to start developing your own domain objects. But no matter what
+ application you are developing, you'll need to understand the
+ <emphasis>Isis programming model</emphasis>.</para>
+
+ <para>The programming model is the set of annotations and programming
+ conventions that Isis recognizes. You'll find the programming model is
+ documented in the Application Library module (in
+ <filename>applib</filename>).</para>
+
+ <para>In addition, the applib contains a small number of utilities
+ which can be useful when writing your application: one such is the
+ ability to create XML snapshots of your domain object graphs.</para>
+
+ <para>The applib documentation also provides pointers to other
+ features that can have an impact on the way in which you write your
+ code, namely the cglib and javassist bytecode providers modules (<xref
+ linkend="sec.BytecodeProviders" />), the
+ <filename>alternates/headless</filename> viewer plugin (<xref
+ linkend="sec.Headless" />), and the <ulink
+ url="http://groovy.codehaus.org">Groovy</ulink> language support
+ (<xref linkend="sec.OtherLanguages" />).</para>
+ </sect1>
+
+ <sect1>
+ <title>Fixtures and Prototyping</title>
+
+ <para>We suggest that the fastest way to develop your application is
+ to start prototyping using the in-memory object store (that is, as set
+ up by the application archetype, see <xref
+ linkend="sec.ApplicationArchetypes" />). The nice thing about working
+ this way is that there is no database schema to slow you down; you can
+ make changes and then rapidly try them out.</para>
+
+ <para>On the other hand, the in-memory object store doesn't persist
+ objects between runs, so you'll soon tire of continually recreating
+ test objects to try out your changes. You should therefore use
+ fixtures: blocks of code that are used to setup objects in the
+ in-memory object store prior to the app running.</para>
+
+ <para>You can find more information about using fixtures in the
+ <filename>applib</filename> module. It's also worth knowing about them
+ because they are used when writing tests for your domain application
+ (see <xref linkend="sec.AgileTesting" />).</para>
+ </sect1>
+
+ <sect1 id="sec.AgileTesting">
+ <title>Agile Testing</title>
+
+ <para><emphasis>Apache Isis</emphasis> is very much aligned to agile
+ development practices, and provides two complementary mechanisms for
+ you to test-drive the development of your application.</para>
+
+ <sect2>
+ <title>Story Testing</title>
+
+ <para>Many agile practitioners use story tests as a means to capture
+ the acceptance (or completion) criteria for high-level user stories.
+ These story tests are typically captured in a non-programmatic form
+ so that is understandable to domain experts as well as
+ programmers.</para>
+
+ <para>Isis provides integrations with two story testing
+ frameworks:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><ulink url="http://fitnesse.org">FitNesse</ulink>, where
+ the story test is captured within a wiki, and</para>
+ </listitem>
+
+ <listitem>
+ <para><ulink url="http://concordion.org">Concordion</ulink>,
+ where the story test is captured as HTML.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>For more information on using these integrations and their
+ supporting archetypes, see the <filename>storytests</filename>
+ module.</para>
+ </sect2>
+
+ <sect2 id="sec.UnitTesting">
+ <title>Unit Testing</title>
+
+ <para>Unlike story tests, unit tests are normally written in a
+ programming language, typically in a framework such as <ulink
+ url="http://junit.org">JUnit</ulink>. <emphasis>A story test ensures
+ that the right system is built, while a unit tests ensures the
+ system is built right</emphasis>.</para>
+
+ <para>When writing unit tests, you have a choice. Since all the
+ business logic in [[NAME]] applications is encapsulated in domain
+ object pojos, you can just write unit tests using nothing more than
+ JUnit and perhaps also a mocking library such as <ulink
+ url="http://jmock.org">JMock</ulink>.</para>
+
+ <para>A slightly more sophisticated approach is to use the JUnit
+ integrations and supporting classes of the (so-called) Headless
+ module (in <filename>alternates/headless</filename>) . The idea of
+ these utilities is to wrap your domain objects in proxies that apply
+ the same rules as an <emphasis>Apache Isis</emphasis> viewer. For
+ example, if you try to change a property or invoke an action that is
+ disabled, then the proxy will throw an exception. You write your
+ test to pass if the exception is thrown, and failed otherwise (eg
+ using <code>@Test(expected=DisabledException.class)</code>).</para>
+ </sect2>
+ </sect1>
+
+ <sect1>
+ <title>A Domain Library</title>
+
+ <para>The idea behind the <filename>domain</filename> module is to
+ provide some off-the-shelf code for you to use and adapt in your own
+ applications. This code is fully tested (comes with tests), and is
+ intended to be well-designed. Using code from the library should give
+ you a kick-start in writing your own domain applications.</para>
+
+ <note>
+ <para>The library is currently very modest, but we hope it might
+ build up in time.</para>
+ </note>
+
+ <para>Of course, there's a limit to the complexity of the code that's
+ included in the library, because every domain is different. But having
+ a full set of tests should allow you to safely refactor the code to
+ your own requirements.</para>
+
+ <para>There's also no guarantee that the library will contain code for
+ your specific requirement. But if you do write some domain logic that
+ you think might be reusable by others, why not consider donating it
+ back to Isis when you've done so?</para>
+
+ <para>The domain library breaks out into three: services, entities and
+ values.</para>
+
+ <sect2>
+ <title>Domain Services</title>
+
+ <para><emphasis>Apache Isis</emphasis> applications use
+ <emphasis>domain service</emphasis>s (a domain-driven design
+ pattern) to allow objects to interact with other domains (or
+ <emphasis>bounded context</emphasis>s, to use the correct term).
+ These domain services are automatically injected into each domain
+ object as it is instantiated.</para>
+
+ <para>Domain services split into two: those that interact with
+ technical domains (such as sending email, or rendering
+ <acronym>PDF</acronym>s), and those that interact with business
+ domains (such as general ledger, <acronym>CRM</acronym>s or legacy
+ systems).</para>
+
+ <para>Obviously domain services that bridge to business domain
+ services are always likely to be specific to each individual
+ application. So the services in the
+ <filename>domain/services</filename> module focus on providing
+ off-the-shelf implementations for some of the more common
+ <emphasis>technical</emphasis> domain services.</para>
+
+ <note>
+ <para>TODO: discuss comments on general style; use of
+ primitives;</para>
+
+ <para></para>
+ </note>
+
+ <note>
+ <para>TODO: discuss fact that different implementations may be
+ required if running client/server (it may not even make sense to
+ have an implementation that does anything on server, eg preview
+ PDF communication in Acrobat Reader)</para>
+
+ <para></para>
+ </note>
+ </sect2>
+
+ <sect2>
+ <title>Domain Values</title>
+
+ <para></para>
+
+ <para>integrating 3rd party libraries such as JodaTime.</para>
+
+ <para></para>
+
+ <note>
+ <para>TODO</para>
+ </note>
+ </sect2>
+
+ <sect2>
+ <title>Domain Entities</title>
+
+ <para></para>
+
+ <para>This should mostly be an x-ref to the applib documentation.
+ However, applib is really just the programming model for the
+ "default" programming model. So also a good place to explain the
+ concept of programming models, and how they can be adjusted.</para>
+
+ <para></para>
+
+ <para>... Programming Model</para>
+
+ <para>x-ref applib docs</para>
+
+ <para></para>
+
+ <para>... Lazy Loading / Dirty Tracking</para>
+
+ <para></para>
+
+ <para></para>
+
+ <note>
+ <para>TODO</para>
+ </note>
+ </sect2>
+ </sect1>
+
+ <sect1>
+ <title>Object Stores</title>
+
+ <para>Although you can go a long way in developing your application
+ using only fixtures and the in-memory object store, eventually you
+ will need to integrate with a "real" object store that persists object
+ to some sort of serialized store.</para>
+
+ <para>There are several object stores to choose from. Some are easy to
+ configure, some more complex; some are only suitable for single-user
+ apps, others for multi-users. Each of the object stores has its own
+ documentation, so you can select the correct object store to
+ choose:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the <acronym>XML</acronym> object store (in
+ <filename>alternates/objectstores/xml</filename>) is designed for
+ single-user systems, and persists to its own internal
+ (proprietary) <acronym>XML</acronym> format;</para>
+ </listitem>
+
+ <listitem>
+ <para>the Berkeley object store (in
+ <filename>alternates/objectstores/berkeley</filename>) is a
+ multi-user object store, persists using <ulink
+ url="http://www.oracle.com/technetwork/database/berkeleydb/overview/index.html">Berkeley
+ DB</ulink>;</para>
+ </listitem>
+
+ <listitem>
+ <para>the <acronym>SQL</acronym> object store (in
+ <filename>alternates/objectstores/sql</filename>) is a multi-user
+ object store that persists to an <acronym>RDBMS</acronym> (direct
+ over <acronym>JDBC</acronym>);</para>
+ </listitem>
+
+ <listitem>
+ <para>the <acronym>JPA</acronym> object store (in
+ <filename>alternates/objectstores/</filename>jpa) is a multi-user
+ object store, persists to an <acronym>RDBMS</acronym> (using a
+ <acronym>JPA</acronym> provider for the heavy lifting);</para>
+ </listitem>
+
+ <listitem>
+ <para>the <acronym>CouchDB</acronym> object store (in
+ <filename>alternates/objectstores/</filename>couchdb) is a
+ multi-user object store that persists to <ulink
+ url="http://couchdb.apache.org">CouchDB</ulink>.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>At the time of writing some of these object stores were still
+ alpha/beta; check the documentation for each of the above object
+ stores to confirm their exact status.</para>
+
+ <para>You'll also find coverage of the object store
+ <acronym>API</acronym> itself in the <filename>core</filename>
+ documentation. Most users of the framework are unlikely to write their
+ own object store, of course, though we hope that over time new
+ implementations will be written by the community.</para>
+ </sect1>
+
+ <sect1 id="sec.Viewers">
+ <title>Viewers</title>
+
+ <para>In the same way that object stores provide pluggability for the
+ "back-end", <emphasis>Apache Isis</emphasis> also offers pluggability
+ on the front-end too.</para>
+
+ <para>We already noted that there are two main viewers, the
+ <acronym>DnD</acronym> viewer and the <acronym>HTML</acronym> viewer
+ (configured by the application archetype, see <xref
+ linkend="sec.ApplicationArchetypes" />). In addition, there are a
+ number of other viewers. Here's the full list:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>The <acronym>DnD</acronym> viewer (in
+ <filename>alternates/viewers/dnd</filename>) is one of the two
+ main viewers setup by the application archetype, and is currently
+ the only viewer designed to run client-side (ie not as a
+ webapp).</para>
+
+ <para>Out-of-the-box it provides a generic view of all domain
+ objects, but provides its own API to allow more sophisticated
+ views to be constructed.</para>
+ </listitem>
+
+ <listitem>
+ <para>The <acronym>HTML</acronym> viewer (in
+ <filename>alternates/viewers/html</filename>) is the second of the
+ two main viewers setup by the application archetype, running as a
+ webapp.</para>
+
+ <para>Other than tweaking <acronym>CSS</acronym>, the views that
+ it provides of objects cannot be customized.</para>
+ </listitem>
+
+ <listitem>
+ <para>Scimpi (in <filename>alternates/viewers/scimpi</filename>)
+ allows your application to be deployed as a webapp.</para>
+
+ <para>Out-of-the-box you get a generic view (very similar to that
+ provided by HTML viewer); you can then customize the view by
+ providing custom pages that use Scimpi tags.</para>
+ </listitem>
+
+ <listitem>
+ <para>The Wicket viewer (in
+ <filename>alternates/viewers/wicket</filename>) uses <ulink
+ url="http://wicket.apache.org">Apache Wicket</ulink> to render
+ generic views of your domain objects in a webapp.</para>
+
+ <para>Like Scimpi, it allows these views to be customized, this
+ time by leveraging the Wicket <classname>Component</classname>
+ <acronym>API</acronym>.</para>
+ </listitem>
+
+ <listitem>
+ <para>The RESTful viewer (in
+ <filename>alternates/viewers/restful</filename>) is designed to
+ expose your domain objects through a <ulink
+ url="http://en.wikipedia.org/wiki/Representational_State_Transfer">RESTful</ulink>
+ interface.</para>
+
+ <para>The intention is to allow programmatic access to your domain
+ objects from other (perhaps non-Java) clients. The viewer does
+ also render as <acronym>XHTML</acronym> for debugging
+ purposes.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>If deploying with the <acronym>DnD</acronym> viewer you also
+ need to decide whether to deploy standalone (ie, each user has their
+ own private object store) or in client/server mode (so all users share
+ a server-based object store). If the latter case then you will need to
+ set up remoting (see <xref linkend="sec.Remoting" />).</para>
+ </sect1>
+
+ <sect1 id="sec.Remoting">
+ <title>Remoting</title>
+
+ <para>If deploying the <acronym>DnD</acronym> viewer in client/server
+ mode then you will need to set up remoting. The main consideration is
+ what transport to use:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>sockets</para>
+
+ <para>In this configuration both client and server run as
+ command-line programs. No plugins are needed, this is the
+ default;</para>
+ </listitem>
+
+ <listitem>
+ <para>http</para>
+
+ <para>In this configuration the server runs as a webapp with a
+ servlet used to listen for client-side requests. The client,
+ meanwhile, is configured to send its requests via
+ <acronym>HTTP</acronym>.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>In addition, you can choose the marshalling mechanism by which
+ objects are serialized across the wire to be varied. There are
+ (again), two options:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>encoding/serialization</para>
+
+ <para>In this configuration <emphasis>Apache Isis</emphasis>
+ encodes/serializes all objects into a succession of bytestreams.
+ This is the default</para>
+ </listitem>
+
+ <listitem>
+ <para>xstream</para>
+
+ <para>In this configuration the <ulink
+ url="http://xstream.codehaus.org">Xstream</ulink> library is used
+ to serialize objects</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>You'll find further coverage of the remoting APIs and how to
+ deploy applications in client/server mode in the
+ <filename>alternatives/remoting</filename> documentation.</para>
+ </sect1>
+
+ <sect1>
+ <title>Authentication and Authorization</title>
+
+ <para><emphasis>Apache Isis</emphasis> provides an
+ <acronym>API</acronym>s for both authentication and
+ authorization.</para>
+
+ <para>The core implementation of these <acronym>API</acronym>s are
+ simple basic noop-based authentication and authorization mechanisms.
+ For deployment into production, you'll need to configure with another
+ alternative implementation.</para>
+
+ <para>One option is the file-based implementation (in
+ <filename>alternatives/security/file</filename>), that stores the
+ security information in flat files. This is simple, but unlikely to be
+ robust enough for enterprise use.</para>
+
+ <para>Another alternative is to use the LDAP implementation (in
+ <filename>alternatives/security/ldap</filename>), which can integrate
+ with an LDAP infrastructure if you have one. If you have a different
+ security infrastructure, then you might consider to write your own
+ implementation (the API is not complex).</para>
+ </sect1>
+
+ <sect1>
+ <title>Running as a Prototype</title>
+
+ <para></para>
+
+ <para></para>
+
+ <para></para>
+
+ <para>A [[NAME]] application is commonly developed in two stages.
+ First it is developed as standalone prototype, running on a single
+ machine, with no security, and with all the objects in memory. Then it
+ is converted into a deployable application i.e. running on a server
+ with multiple clients, with a persistence layer (most commonly in the
+ form of the Hibernate Object Store) and with full authentication and
+ authorization. (Note that these two phases do not have to be
+ sequential, you might prefer to develop your system feature-by-feature
+ right through to a deployable version.) In this section we show you
+ how to run [[NAME]] Objects as prototype; in the next section we show
+ you how to deploy the same domain object model as the real
+ application.</para>
+
+ <para>Running a [[NAME]] application generally requires some
+ configuration files and images. Resources are typically loaded from
+ the working directory, while specific resources can be loaded from the
+ class path. Assuming that we will be running from the development
+ directory the following structure is typical of a [[NAME]]
+ application.</para>
+
+ <screen format="linespecific">project/
+ src/
+ xat/
+ config/
+ isis.properties
+ passwords
+ images/
+ build.xml
+ :</screen>
+
+ <para></para>
+
+ <sect2>
+ <title>Configuration</title>
+
+ <para></para>
+
+ <para></para>
+
+ <para>[[NAME]] loads in one or more properties files during startup.
+ The properties files must contain at least a list of services that
+ the application uses and commonly there is also a list of fixtures
+ that are to be run at startup. In addition to the core properties
+ there may be also other properties that are used by other
+ components. The file <filename class="directory"
+ moreinfo="none">isis.properties</filename> is always loaded up,
+ while other properties files relating to specific components are
+ only loaded up if the component they relate to is to be is used. For
+ example when using the DND viewer the system will also load in the
+ file <filename class="directory"
+ moreinfo="none">viewer_dnd.properties</filename>, and when using the
+ hibernate object store the file <filename class="directory"
+ moreinfo="none">persistor_hibernate.properties</filename> is loaded.
+ While <filename class="directory"
+ moreinfo="none">isis.properies</filename> must exist for the
+ framework to start up properly, all other properties files are
+ optional.</para>
+
+ <para>The example <filename class="directory"
+ moreinfo="none">isis.properties</filename> file below shows a number
+ of service classes being listed along with a generic repository for
+ accessing Location objects. The prefix is prepended to each class
+ name before loading. The second set of properties lists the fixture
+ classes to load and instantiate.</para>
+
+ <programlisting format="linespecific">isis.services.prefix=org.apache.isis.example.ecs
+isis.services=repository#Location,resources.CustomerRepository, \
+ CustomerFactory, BookingFactory, resources.PaymentMethodFactory, \
+ resources.PhoneNumberFactory, LocationFactory
+
+isis.fixtures.prefix=org.apache.isis.example.ecs.fixtures
+isis.fixtures=CitiesFixture, BookingsFixture, ContextFixture</programlisting>
+
+ <para></para>
+ </sect2>
+
+ <sect2>
+ <title>Authentication</title>
+
+ <para></para>
+
+ <para></para>
+
+ <para>By default the authentication mechanism is a username/password
+ challenge with the details stored in a password file called
+ <filename class="directory" moreinfo="none">passwords</filename>.
+ This file is a simple list of user names and their corresponding
+ passwords separated by a colon. The file below shows two users with
+ badly chosen passwords.</para>
+
+ <programlisting format="linespecific">jbrown:pass
+tsmith:pass</programlisting>
+
+ <para></para>
+ </sect2>
+
+ <sect2>
+ <title>Images</title>
+
+ <para></para>
+
+ <para></para>
+
+ <para>The drag and drop and web interfaces both display icons as
+ part of the views for each object. Images for these icons, and for
+ other uses, are sought in the <filename class="directory"
+ moreinfo="none">images</filename> directory. The web interface
+ currently only works with GIF images, while the DnD interface will
+ work with GIF, PNG and JPEG images. The following shows images for
+ the main objects in the ECS example.</para>
+
+ <screen format="linespecific">images
+ Booking.gif
+ City.gif
+ CreditCard.gif
+ Customer.gif
+ Location.gif
+ Telephone.gif
+</screen>
+
+ <para></para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="sec.DeployingAnIsisApplication">
+ <title>Deploying an Isis Application</title>
+
+ <para>*** x-ref isis-remoting.</para>
+
+ <para></para>
+
+ <para>Deploying your application depends on whether it is a webapp,
+ client/server (DnD) or standalone (DnD). With the current set of
+ deployment options it is likely to be one of:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>standalone client running with DnD viewer and a local object
+ store</para>
+ </listitem>
+
+ <listitem>
+ <para>client/server over sockets</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>client running DnD viewer, sockets connection</para>
+ </listitem>
+
+ <listitem>
+ <para>server running as a standalone app, listening on
+ sockets</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>client/server over HTTP</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>client running DnD viewer, HTTP requests</para>
+ </listitem>
+
+ <listitem>
+ <para>server running as a webapp, with HTTP servlet listening
+ for requests</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>webapp, meaning any of:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>HTML viewer</para>
+ </listitem>
+
+ <listitem>
+ <para>Scimpi</para>
+ </listitem>
+
+ <listitem>
+ <para>Wicket</para>
+ </listitem>
+
+ <listitem>
+ <para>RESTful</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+
+ <para>Indeed, it's theoretically possible to combine the various
+ webapp viewers; for example the server-side HTTP, Scimpi and RESTful
+ might all be colocated.</para>
+
+ <para>In all cases you're likely to want to enable authentication and
+ authorization; the exact configuration to use here will depend both on
+ the implementation chosen (file-based, LDAP or some other) and whether
+ running in client/server mode or not.</para>
+
+ <para></para>
+
+ <para></para>
+
+ <para></para>
+ </sect1>
+
+ <sect1>
+ <title>Other Features</title>
+
+ <para></para>
+
+ <para></para>
+
+ <note>
+ <para>TODO: discuss other features, x-ref elsewhere in this
+ doc</para>
+ </note>
+
+ <para></para>
+
+ <sect2 id="sec.BytecodeProviders">
+ <title>Lazy Loading / Dirty Tracking</title>
+
+ <para></para>
+
+ <para></para>
+ </sect2>
+
+ <sect2>
+ <title>Extending the Isis Meta Model</title>
+
+ <para></para>
+ </sect2>
+
+ <sect2 id="sec.Headless">
+ <title>Using the Wrapper Prog Model</title>
+
+ <para></para>
+ </sect2>
+
+ <sect2 id="sec.OtherLanguages">
+ <title>Other Languages</title>
+
+ <para></para>
+ </sect2>
+ </sect1>
+ </chapter>
+
+ <chapter id="building_with_maven">
+ <title>Developing with an IDE</title>
+
+ <sect1>
+ <title>Using Eclipse for development</title>
+
+ <para>There are two approaches for using Eclipse in
+ development.</para>
+
+ <para>The recommended approach is to use the Eclipse's Maven plug-in,
+ m2eclipse, obtainable from <ulink
+ url="???">http://m2eclipse.sonatype.org/</ulink>. This then allows the
+ Maven projects to be imported directly using File > Import >
+ Maven Projects.</para>
+
+ <para></para>
+
+ <remark>TODO: would be good to have some screenshots of using
+ m2eclipse to import projects here.</remark>
+
+ <para></para>
+
+ <para>In fact, you can use m2eclipse to create the project from the
+ archetype in a single go:</para>
+
+ <para></para>
+
+ <para><remark>TODO: would be good to have a screenshot of using
+ m2eclipse to generate project using archetype here.</remark></para>
+
+ <para></para>
+
+ <para>Alternatively you can use Maven's Eclipse plug-in to generate
+ .project and .classpath files. These can then be imported into Eclipse
+ using File > Import > Existing Projects. The remainder of this
+ section discusses this alternative approach; to reiterate the
+ m2eclipse approach is more straightforward and generally
+ preferred.</para>
+
+ <screen>[rcm@localhost ~]$ <emphasis role="bold">cd expenses/</emphasis>
+[rcm@localhost expenses]$ <emphasis role="bold">mvn eclipse:eclipse</emphasis>
+[INFO] Scanning for projects...
+[INFO] Reactor build order:
+[INFO] [[NAME]] Application
+[INFO] Domain Model
+[INFO] Fixtures
+[INFO] Services
+[INFO] Exploration
+[INFO] Hibernate Object Store
+[INFO] Web App
+[INFO] Client Distribution
+[INFO] Server Distribution
+[INFO] Searching repository for plugin with prefix: 'eclipse'.
+[INFO] ------------------------------------------------------------------------
+[INFO] Building [[NAME]] Application
+[INFO] task-segment: [eclipse:eclipse]
+[INFO] ------------------------------------------------------------------------
+[INFO] Preparing eclipse:eclipse
+:
+:
+:
+[INFO] ------------------------------------------------------------------------
+[INFO] BUILD SUCCESSFUL
+[INFO] ------------------------------------------------------------------------
+[INFO] Total time: 1 minute 22 seconds
+[INFO] Finished at: Thu Oct 02 20:44:41 BST 2008
+[INFO] Final Memory: 32M/247M
+[INFO] ------------------------------------------------------------------------</screen>
+
+ <para>This downloads all the required libraries and creates
+ <filename>.project</filename> and <filename>.classpath</filename>
+ files for Eclipse to use. After this is complete we can start up
+ Eclipse and import the projects.</para>
+
+ <screen>[rcm@localhost expenses]$ <emphasis role="bold">eclipse -data .</emphasis></screen>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/eclipse-platform.png" width="40%" />
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <para>The workspace starts off empty as this is a new project. First
+ we need to import the modules using the
+ <guimenu>File/Import...</guimenu> menu. On the first page of this
+ dialog select the <emphasis role="strong">Existing Project into
+ Workspace</emphasis> option.</para>
+
+ <screenshot>
+ <screeninfo></screeninfo>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="???" />
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/eclipse-Import.png" width="40%" />
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <para>After selecting the same directory that we are running in, then
+ you select all the modules in the list as Eclipse projects to
+ import.</para>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/eclipse-Import2.png" width="40%" />
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <para>All the libraries are referenced using a the variable M2_REPO,
+ so this needs to be set up in the Classpath variables in the main
+ preferences. In the <emphasis>Classpath Variable</emphasis> tab press
+ the <guibutton>New...</guibutton> button.</para>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/eclipse-Preferences%20.png"
+ width="40%" />
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <para>Enter the name <emphasis>M2_REPO</emphasis> and find the path to
+ <filename>.m2/repository</filename>.</para>
+
+ <para>Now to run the application select <guimenu>Run/Run
+ Configuration...</guimenu> on the commandline project and browse for
+ the class <classname>org.apache.isis.runtime.Isis</classname>. With
+ that selected press the <guibutton>Run</guibutton> button.</para>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/eclipse-Run%20Configurations%20.png"
+ width="40%" />
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <para>After a short while the login dialog should appear. Logon with a
+ valid user name and password, like <emphasis>sven</emphasis> and
+ <emphasis>pass</emphasis>.</para>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/example-Login.png" width="12%" />
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <para>When the application has finished starting up you should the
+ services on the DnD user interface.</para>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/example-screen.png" width="40%" />
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <para></para>
+ </sect1>
+ </chapter>
+ </part>
+
+ <part>
+ <title>Architecture</title>
+
+ <partintro>
+ <para>*** partinfo...</para>
+ </partintro>
+
+ <chapter>
+ <title>Overview</title>
+
+ <abstract>
+ <para>*** yada yada</para>
+ </abstract>
+
+ <para>***</para>
+
+ <para></para>
+
+ <sect1>
+ <title>Hexagonal Architecture</title>
+
+ <para></para>
+
+ <para>x-ref</para>
+
+ <para></para>
+
+ <para></para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/HexagonalArchitectureOverview.png"
+ scale="50" />
+ </imageobject>
+ </mediaobject>
+
+ <para></para>
+ </sect1>
+ </chapter>
+
+ <chapter>
+ <title>Core, Defaults and Alternatives</title>
+
+ <abstract>
+ <para>*** Explain what each pf the modules are for</para>
+ </abstract>
+
+ <para></para>
+
+ <para></para>
+
+ <para></para>
+
+ <sect1>
+ <title>Core</title>
+
+ <para>x-ref part 2...</para>
+
+ <para>consists of:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>common</para>
+ </listitem>
+
+ <listitem>
+ <para>test support</para>
+ </listitem>
+
+ <listitem>
+ <para>metamodel</para>
+ </listitem>
+
+ <listitem>
+ <para>progmodel</para>
+ </listitem>
+
+ <listitem>
+ <para>runtime</para>
+ </listitem>
+
+ <listitem>
+ <para>webapp</para>
+ </listitem>
+
+ <listitem>
+ <para>webserver</para>
+ </listitem>
+ </itemizedlist>
+
+ <para></para>
+ </sect1>
+ </chapter>
+
+ <chapter>
+ <title>Understanding how an Isis application works</title>
+
+ <abstract>
+ <para>***</para>
+ </abstract>
+
+ <para></para>
+
+ <para>[[NAME]] creates the user interface for an application directly
+ from the definitions of the domain model. In this section we will look
+ at that relationship in more detail, with reference to the Expenses
+ Processing example application supplied as part of the download. As we
+ showed in the previous section, any domain model written for [[NAME]]
+ may be run with any of the viewers - there is no specific coding
+ required, and the domain model has no knowledge of which viewer is being
+ used. However, each viewer will have different gestures or mechanisms
+ for providing the same functionality. To illustrate this, we will show
+ the same objects being accessed through both the DND and the HTML
+ viewers, side by side.</para>
+
+ <para>The application code for the Expenses Processing example, like any
+ [[NAME]] application, consists of two things: domain objects and
+ services. The domain objects form the lion's share of that code, so
+ we'll look at how those work first.</para>
+
+ <para>The code for examples we will be looking at can be found in the
+ directory <filename>examples/expenses/expenses-dom/src</filename> in the
+ downloaded files.</para>
+
+ <sect1>
+ <title>Domain objects</title>
+
+ <para>The domain objects are the entities - the nouns - that represent
+ the application domain: employee, claim, expense item, project code,
+ currency, and so forth. In the course of using the application, a user
+ will view and manipulate many instances of these domain objects. To
+ understand how [[NAME]] handles domain objects, we'll start by looking
+ at an Employee object:</para>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata contentwidth="40%"
+ fileref="images/employee-views.png" format="PNG" />
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <para>Every object presented in the user interface will have a
+ corresponding Java class in the domain model - in this case it is
+ <classname>org.apache.isis.example.expenses.employee.Employee</classname>.
+ Below we can see the code for the <classname>Employee</classname>
+ object, as presented in Eclipse, with the object's list of methods
+ presented on the left hand side.</para>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata contentwidth="40%" fileref="images/employee-code.png"
+ format="PNG" />
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <para>The first thing to note is that the type of the object as shown
+ in the user views is derived directly from the class name in Java. The
+ framework inserts spaces before capital letters, so that the class
+ <classname>TemporaryEmployee</classname> would be presented to the
+ user as 'Temporary Employee'. However we will see later that the name
+ may be over-ridden where necessary, for example if we want the name to
+ include punctuation or other characters not allowed in Java class
+ names. (Note that there is a separate mechanism for dealing with
+ internationalisation).</para>
+
+ <para>Secondly, we can see that <classname>Employee</classname>
+ extends <classname>AbstractDomainObject</classname> - a class provided
+ within the [[NAME]] application library. This is not a requirement:
+ your domain objects may be Plain Old Java Objects (POJOs) - they do
+ not need to extend any class in the framework. However, extending from
+ <literal moreinfo="none">AbstractDomainObject</literal> will save us
+ having to write a few lines of code in each case, as we'll see
+ later.</para>
+
+ <para>Note also that in the body of the object we use 'code folding'
+ (the plug-in used here is <ulink
+ url="http://www.realjenius.com/platform_support">Coffee Bytes</ulink>)
+ to break the object's code into regions, each typically containing one
+ or more related methods that together fulfill a high-level
+ responsibility of the object. This is just a coding convention, not a
+ requirement.</para>
+ </sect1>
+
+ <sect1>
+ <title>Properties</title>
+
+ <para>In both of the user views of an Employee we can see a field
+ called 'Name'. Within the <classname>Employee</classname> class there
+ is a <literal moreinfo="none">Name</literal> region of code, expanded
+ here:</para>
+
+ <programlisting condition="" format="linespecific">// {{ Name
+ private String name;
+
+ @MemberOrder(sequence="1")
+ @Disabled
+ public String getName() {
+ return this.name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+// }}</programlisting>
+
+ <para>The <literal moreinfo="none">Name</literal> region contains a
+ simple property, of type <literal moreinfo="none">String</literal>,
+ defined by a <literal moreinfo="none">getName</literal> and a <literal
+ moreinfo="none">setName</literal> method. This is sufficient
+ information to allow the viewers to display a field containing a
+ textual value. Note that if the property is to be persisted, then it
+ will need both a <literal moreinfo="none">get</literal> and a <literal
+ moreinfo="none">set</literal> method - per the standard JavaBeans
+ convention. If you wish to display a field that is derived
+ automatically from other information in the object, and do not require
+ this to be persisted, then a <literal moreinfo="none">get</literal>
+ alone will suffice.</para>
+
+ <para>As with the name of the object, the field name is derived
+ automatically from the name of the property - though we'll see later
+ that this may be over-ridden if needed.</para>
+
+ <para>The <literal moreinfo="none">getName</literal> has been marked
+ up with two Java annotations, both defined in the [[NAME]] application
+ library. Annotations allow the programmer to enrich the information
+ available to the framework. On properties, any [[NAME]] Objects
+ annotations are always associated with the <literal
+ moreinfo="none">get</literal> method. However, annotations are not
+ mandatory - you can write a simple [[NAME]] application without using
+ any annotations at all.</para>
+
+ <para>By default, any property with both a <literal
+ moreinfo="none">get</literal> and <literal
+ moreinfo="none">set</literal> method will be editable by the user.
+ <literal moreinfo="none">@Disabled</literal> tells the framework that
+ this particular property may never be altered by the user (though it
+ may be altered programmatically). Later we'll see how to make a
+ property modifiable on certain conditions.</para>
+
+ <para><literal moreinfo="none">@MemberOrder(sequence="1")
+ </literal>tells the framework that this property should be the first
+ field displayed in any view of the Employee - irrespective of where it
+ is defined within the code. This ordering information has been
+ observed by both the viewers.</para>
+
+ <para>The next region of the code contains another <literal
+ moreinfo="none">String</literal> property, called <literal
+ moreinfo="none">UserName</literal>:</para>
+
+ <programlisting format="linespecific">// {{ UserName field
+ private String userName;
+
+ @Hidden
+ public String getUserName() {
+ return userName;
+ }
+ public void setUserName(final String variable) {
+ this.userName = variable;
+ }
+// }}</programlisting>
+
+ <para>Note that <literal moreinfo="none">getUserName</literal> has
+ been marked up with <literal moreinfo="none">@Hidden</literal>. This
+ tells the framework that this property should never be shown in user
+ views of the object (check this against the two user views above).
+ Later on we'll see how it is possible to hide a property in certain
+ circumstances.</para>
+
+ <para>Next we'll look at the <literal
+ moreinfo="none">EmailAddress</literal> region:</para>
+
+ <programlisting format="linespecific">// {{ EmailAddress
+ private String emailAddress;
+
+ @MemberOrder(sequence = "2")
+ @Optional
+ @RegEx(validation = "(\\w+\\.)*\\w+@(\\w+\\.)+[A-Za-z]+")
+ public String getEmailAddress() {
+ return this.emailAddress;
+ }
+ public void setEmailAddress(final String emailAddress) {
+ this.emailAddress = emailAddress;
+ }
+ public void modifyEmailAddress(final String emailAddress) {
+ getRecordActionService().recordFieldChange(this, "Email Address", getEmailAddress(), emailAddress);
+ setEmailAddress(emailAddress);
+ }
+ public void clearEmailAddress() {
+ getRecordActionService().recordFieldChange(this, "Email Address", getEmailAddress(), "EMPTY");
+ setEmailAddress(null);
+ }
+ public boolean hideEmailAddress() {
+ return !employeeIsCurrentUser();
+ }
+ private boolean employeeIsCurrentUser() {
+ return getUserFinder().currentUserAsObject() == this;
+ }
+// }}</programlisting>
+
+ <para>As well as <literal moreinfo="none">@MemberOrder</literal>, this
+ property is marked up with <literal
+ moreinfo="none">@Optional</literal> and <literal
+ moreinfo="none">@RegEx</literal> annotations. By default, all
+ properties are taken to be mandatory - if the user creates or edits an
+ object then they will be required to specify the contents of each
+ field. <literal moreinfo="none">@Optional</literal> overrides this
+ default behaviour - indicating here that the object may be saved
+ without an email address.</para>
+
+ <para><literal moreinfo="none">@RegEx</literal> is applicable only to
+ <literal moreinfo="none">String</literal> properties. In this case the
+ annotation specifies a Regular Expression that will be used to
+ validate any value that the user types into the field. In a
+ conventional architecture, this functionality would typically be found
+ in the user interface code. The [[NAME]] argument is that this
+ functionality should apply to any user interface that might want to
+ change the property, so its proper place is in the object. <literal
+ moreinfo="none">@RegEx</literal> may also be used to reformat a String
+ that has been entered by the user.</para>
+
+ <para>The two screens below show how two different viewers make use of
+ the functionality in different ways. In both cases the user has typed
+ in a value that does not match the RegEx specification (they have
+ typed in an email address that contains a space), so the new value has
+ not been accepted or saved.</para>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata contentwidth="40%"
+ fileref="images/employee-email-invalid.png"
+ format="PNG" />
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <para>In addition to <literal
+ moreinfo="none">getEmailAddress</literal> and <literal
+ moreinfo="none">setEmailAddress</literal>, there are <literal
+ moreinfo="none">modifyEmailAddress</literal>, <literal
+ moreinfo="none">clearEmailAddress</literal> and <literal
+ moreinfo="none">hideEmailAddress</literal> methods. [[NAME]]
+ recognises the <literal moreinfo="none">modify</literal>, <literal
+ moreinfo="none">clear</literal> and <literal
+ moreinfo="none">hide</literal> prefixes (and a few others that we
+ shall see later) as specifying additional functionality relating to
+ the <literal moreinfo="none">EmailAddress</literal> property.</para>
+
+ <para>If a property has a corresponding <literal
+ moreinfo="none">modify<propertyName></literal> method, then
+ whenever the user modifies the field, this will be called rather than
+ the <literal moreinfo="none">set</literal>. In this case the <literal
+ moreinfo="none">modify</literal> method uses the <literal
+ moreinfo="none">RecordActionService</literal> to record the details of
+ the change, and then calls <literal
+ moreinfo="none">setEmailAddress</literal> to change the value. The
+ reason for adopting this pattern, rather than including the
+ functionality in the <literal moreinfo="none">set</literal> itself, is
+ that the <literal moreinfo="none">set</literal> will be called by the
+ object store each time the object is retrieved. So we use a <literal
+ moreinfo="none">modify</literal> method where we want to do something
+ (such as add to a total) only when the user changes a field.</para>
+
+ <para><literal moreinfo="none">clearEmailAddress</literal> is called,
+ in a similar manner, if the user clears the contents of the field.
+ Again, it is optional - added where we want to perform some logic only
+ when the user clears the property. On the <literal
+ moreinfo="none">UserName</literal> field we saw that <literal
+ moreinfo="none">@Hidden</literal> hides a property from the user
+ permanently. We may, however, want to hide fields under certain
+ circumstances. The visibility of all classes, properties and methods
+ may be controlled via conventional authorization techniques, based on
+ the user's role(s). In rarer cases, we want to control visibility at
+ an instance level. In this case, for privacy reasons we do not want
+ the email address to be visible, except to that person. This is what
+ the <literal moreinfo="none">hideEmailAddress()</literal>method is
+ doing. If the method returns true, the field will be hidden from the
+ user.</para>
+
+ <para>Next we will look at the <literal
+ moreinfo="none">NormalApprover</literal> region:</para>
+
+ <programlisting format="linespecific">// {{ NormalApprover
+ private Employee normalApprover;
+
+ @MemberOrder(sequence="4")
+ public Employee getNormalApprover() {
+ return this.normalApprover;
+ }
+ public void setNormalApprover(final Employee normalAuthoriser) {
+ this.normalApprover = normalAuthoriser;
+ }
+ public void modifyNormalApprover(final Employee normalAuthoriser) {
+ getRecordActionService().recordFieldChange(this, "Normal Approver", getNormalApprover(), normalApprover);
+ setNormalApprover(normalAuthoriser);
+ }
+ public void clearNormalApprover() {
+ getRecordActionService().recordFieldChange(this, "Normal Approver", getNormalApprover(), "EMPTY");
+ setNormalApprover(null);
+ }
+ public String validateNormalApprover(Employee newApprover) {
+ return newApprover == this ? CANT_BE_APPROVER_FOR_OWN_CLAIMS: null;
+ }
+ public String disableNormalApprover() {
+ return employeeIsCurrentUser() ? null: NOT_MODIFIABLE;
+ }
+
+ public static final String NOT_MODIFIABLE = "Not modifiable by current user";
+ public static final String CANT_BE_APPROVER_FOR_OWN_CLAIMS = "Can't be the approver for your own claims";
+// }}</programlisting>
+
+ <para>The <literal moreinfo="none">NormalApprover</literal> property
+ takes an object of type <literal moreinfo="none">Employee</literal>.
+ Assuming that this field is not disabled, the user may specify an
+ Employee object for this field. [[NAME]] will prevent the user from
+ trying to associate the wrong type of object with this field. This is
+ illustrated in the two screens below:</para>
+
+ <screenshot>
+ <mediaobject>
+ <imageobject>
+ <imagedata contentwidth="40%"
+ fileref="images/employee-approver-views.png"
+ format="PNG" />
+ </imageobject>
+ </mediaobject>
+ </screenshot>
+
+ <para>In the left-hand screen (DND) we can see the user dropping an
+ Employee object into the empty field, and the field is flashing green
+ to indicate that this will succeed. If the user attempted to drop
+ another type of object into the empty field, then the field would
+ flash red, and the drop would not update the field. A successful drop
+ will call the <literal moreinfo="none">set</literal> method, or, if a
+ <literal moreinfo="none">modify<propertyName></literal> method
+ is provided (as it is here), it will call that instead. Note that on
+ the DND viewer, if a field already contains an object, then this may
+ be cleared by right-clicking on that object and selecting 'Clear
+ Association'. This will set the property to <literal
+ moreinfo="none">null</literal>. If there is a <literal
+ moreinfo="none">clear<propertyName></literal> field (as there is
+ in this example) then that will be called rather than the <literal
+ moreinfo="none">set</literal> method. Alternatively a new reference
+ can be dropped on to the field's label, which combines both the
+ clearing and the subsequent setting of the field.</para>
+
+ <para>In the HTML viewer (right-hand screen) drag and drop is not
+ possible. In a reference field such as this one, the user will be
+ given a drop-down list of objects of the appropriate type (i.e.
+ Employees here) that the user has recently viewed. If the required
+ Employee object is not in that list then the user may go and find that
+ object (e.g. from the Employees tab) and then return to the context -
+ this time the newly viewed Employee will have been added to the list
+ automatically. (Note: This is a generic capability provided by the
+ HTML viewer. In other contexts, the programmer may want to specify an
+ explicit list of objects to appear in a drop-down list. This would be
+ achieved by means of a <literal
+ moreinfo="none">choices<propertyName></literal> method).</para>
+
+ <para>The <literal moreinfo="none">validateNormalApprover</literal>
+ method enforces any rules concerning the specific instances of
+ <literal moreinfo="none">Employee</literal> that may be associated
+ with this field. In this particular example, it prevents the user from
+ specifying an Employee as their own approver. Note that this method
+ returns a <literal moreinfo="none">String</literal>. If the specific
+ Employee instance being passed into the method is acceptable, the
+ method should return <literal moreinfo="none">null</literal>; if
+ unacceptable then the method should return a <literal
+ moreinfo="none">String</literal> message that will be made available
+ to the user to advise them why the action will not succeed. (On the
+ DND this appears at the bottom of the screen.)</para>
+
+ <para>The <literal moreinfo="none">disableNormalApprover</literal>
+ method prevents the user from modifying the field in certain
+ circumstances. In this example the method enforces the rule that only
+ the Employee themselves may change this field. Like the <literal
+ moreinfo="none">validate</literal> method, it returns a <literal
+ moreinfo="none">null</literal> if the user may modify the field
+ (subject to the validate rules), or returns a <literal
+ moreinfo="none">String</literal> message if they may not. (Note that
+ this method, along with hide (seen earlier) allow for 'instance-based
+ authorization'. Most applications can manage with 'class-based
+ authorization' - in which the classes, properties and actions made
+ available to a user are based on their roles. Class-based
+ authorization in [[NAME]] is administered externally to the
+ application and does not require any coding within the domain
+ objects.)</para>
+ </sect1>
+
+ <sect1>
+ <title>Title</title>
+
+ <para>In the next screen we will look at the <literal
+ moreinfo="none">title</literal> region of the Employee object.</para>
+
+ <programlisting format="linespecific">// {{ Title
+ public String title() {
+ return getName();
+ }
+// }}</programlisting>
+
+ <para>The <literal moreinfo="none">title</literal> method specifies
+ the title for the object - which, on both the DND and HTML viewers
+ appears next to the icon. The title is there to help the user identify
+ objects. [[NAME]] also provides an easy mechanism to retrieve objects
+ from the object store by their title. Other methods of
+ finding/searching may require repository methods to be written. If no
[... 3944 lines stripped ...]