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 2014/02/12 00:31:41 UTC

[44/51] [partial] ISIS-694: mothballing the docbkx folders.

http://git-wip-us.apache.org/repos/asf/isis/blob/7a7836e3/component/viewer/wicket/src/docbkx/guide/isis-wicket-viewer.md
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/src/docbkx/guide/isis-wicket-viewer.md b/component/viewer/wicket/src/docbkx/guide/isis-wicket-viewer.md
deleted file mode 100644
index f9728be..0000000
--- a/component/viewer/wicket/src/docbkx/guide/isis-wicket-viewer.md
+++ /dev/null
@@ -1,2976 +0,0 @@
-<!--
-  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.
--->
-Preface
-=======
-
-The *Apache Isis Wicket Viewer* provides a customizable web-based viewer
-for *Apache Isis* implemented using the [Apache
-Wicket](http://wicket.apache.org) framework. This user guide is written
-for developers looking to write *Apache Isis* applications and deploy
-them using the *Wicket Viewer*. It assumes familiarity with writing
-*Isis* applications, but that is all that is needed to get an
-application up-and-running with the generic OOUI.
-
-Familiarity with *Apache Wicket* is useful to understand how the wicket
-viewer fits together, but is essential unless you want to start
-customizing the UI. If you're interested in learning more about *Wicket*
-itself, then [Wicket In Action](http://www.manning.com/dashorst/)
-(Martijn Dashort & Eelco Hillenius) is definitely worth reading.
-
-Introduction
-============
-
-> This introductory chapter describes the objective of the *Wicket
-> Viewer*, and the target audience for this guide.
-
-Introducing the Apache Isis Wicket Viewer
------------------------------------------
-
-The *Wicket Viewer* provides a generic OOUI web-based viewer for *Apache
-Isis* domain models, using [Apache Wicket](http://wicket.apache.org) as
-the underlying web framework.
-
-What this means for you, the developer, is that you can build a web
-application solely by developing the domain model as pojos. The *Wicket
-Viewer* will then render your domain objects in a web UI using ready
-provided *Wicket* Components.
-
-This generic UI provides a lot of functionality out-of-the-box:
-
--   Each domain entity is rendered as a form, with the appropriate
-    individual component type for its values. This entity form also
-    allows editable references to other objects, too.
-
--   Moreover, any collections of a domain entity (eg Order /
-    OrderDetail) are also automatically rendered as a list, a table, or
-    in any other appropriate representation. Both the scalar and
-    collection references let the end-user easily "walk the graph"
-    around your domain model.
-
--   Finally, the vuewer also renders actions (commands/behaviors) for
-    your domain objects, and lets these actions to be invoked. This is
-    what makes *Apache Isis*-based applications that much more than
-    simple CRUD applications.
-
-You can see examples of the UI in ?.
-
-Over and above this generic interface, you are then free to customize
-this interface in various ways. Your customizations can be general (eg
-providing a way to render a collection of Locatable objects in a
-google-maps mashup) or targetted (eg a particular way to render a
-ShoppingCartWizard). Generally these customizations take the form of
-bespoke *Wicket* Components, though simple customizations can be
-performed just by modifying the CSS. Again you can see some examples of
-these customizations in ?.
-
-*Apache Isis* webapps that use the *Wicket Viewer* are bootstrapped in
-the same as vanilla *Wicket* applications, with the *Wicket Viewer*
-providing an implementation of *Wicket*'s `WebApplication` class that
-additionally bootstraps the *Apache Isis* runtime. Authentication is
-performed using *Apache Isis*' own security mechanism (which itself is
-pluggable).
-
-The Wicket Viewer compared to other Wicket RAD Frameworks
----------------------------------------------------------
-
-### Differences in Capability
-
-There are several frameworks that aim either to provide a back-end to
-*Wicket* and/or that aim to eliminate some of the boilerplate; notable
-examples are [Wicketopia](http://wicketopia.sourceforge.net), [Wicket
-RAD](http://sites.google.com/site/wicketrad) and
-[DataBinder](http://databinder.net/wicket/show/overview). There are also
-precanned archetypes, such as jWeekEnd's
-[LegUp](http://jweekend.co.uk/dev/LegUp) archetypes and
-[IoLite](http://wicketstuff.org/confluence/display/STUFFWIKI/Wicket-Iolite),
-that do some of the wiring for back-end technologies like
-[Spring](http://springframework.org) and
-[Hibernate](http://hibernate.org). So, how does *Wicket Viewer* for
-*Apache Isis* compare to them?
-
-Well, compared to *Wicketopia* for example, *Wicket Viewer* shares the
-following ideas:
-
--   both frameworks support pluggable editors for Javabean properties
-
--   both frameworks allow the metamodel to be enhanced declaratively
-    using annotations (eg @Length); these are picked up by the editors
-
--   both frameworks support (or aspire to support) the metamodel being
-    built from various sources, including for example *Hibernate* or
-    JSR-303 annotations etc. In the case of the *Wicket Viewer* this is
-    done by using *Apache Isis*' own metamodel.
-
-But there are some differences too; through *Wicket Viewer*'s use of the
-*Apache Isis* it:
-
--   allows the metamodel to be enhanced imperatively as well as
-    declaratively; naming conventions are used to associate supporting
-    methods with the properties
-
--   supports user-defined value types (using *Apache Isis*' @Value
-    annotation); important for domain-driven applications
-
--   supports three level of business rule (both declaratively and
-    imperatively): is the entity class member visible, is it usable, is
-    the value proposed valid. For most other frameworks, only the last
-    of these (validation of proposed values) is typically supported
-
--   supports properties which are references to other entities, not just
-    simple value types. In particular, the *Wicket Viewer*'s property
-    editor for references allows instances to be found by invoking
-    repositories in-situ
-
--   renders entity collections as well as entity properties
-
--   renders entity actions (commands), allowing more than simple CRUD
-    behavior to be exposed. Indeed, it's possible for the domain entity
-    to be immutable except through the invocation of actions
-
-The flip side of the *Wicket Viewer*'s more extensive metamodel support
-is that it uses *Apache Isis*' own metamodel API. In contrast,
-*Wicketopia* (only supporting properties and not collections or actions)
-can get by using java.bean.PropertyDescriptor from the JDK.
-
-Compared to frameworks and archetypes that use *Hibernate* for the
-backend, the *Wicket Viewer* (again by leveraging the rest of the
-*Apache Isis* framework) is more general here too. So, it has a Session
-concept that is analogous to a *Hibernate* session (and if using the
-*JPA ObjectStore* as a backend, the *Apache Isis*' Session just wraps
-the JPA provider's PersistenceContext *e*'s). But it also supports other
-back-end persistence stores too. Indeed, *Apache Isis*' default to
-support rapid development we usually use an in-memory object store.
-
-The *Wicket Viewer* can also handle non-persisted objects as well as
-persisted objects; with every managed object is stored in an identity
-map. This support for non-persisted objects is important because it is
-central to supporting specialized use cases, including managing
-workflows for entering data, and dashboards for analyzing data.
-
-A few other points worthy of mention:
-
--   The *Wicket Viewer* will automatically serialize both persisted and
-    non-persisted objects, irrespective of whether the pojo itself is
-    serializable. This is important if deploying on a cluster.
-
--   Through the *Apache Isis* core framework, every managed object also
-    automatically has any domain service dependencies automatically
-    injected into it),
-
--   Again, courtesy of *Apache Isis* core, every persisted object has a
-    unique, immutable and serializable object Id (OID). This can be a
-    very useful resource when integrating with external services such as
-    REST and ESBs.
-
--   *Apache Isis* core also provides automatic dirty tracking, and
-    optimistic locking.
-
-Downsides? Currently *Apache Isis* does not support some of the
-Enterprise Java APIs such as JTA, so interactions with domain services
-that ultimately delegate to transaction stores (such as JMS) cannot be
-enlisted in the same transaction as the persistence store. And,
-obviously, it introduces a dependency on the *Apache Isis* framework
-over and above technologies such as the JPA provider implementation.
-
-### Differences in Philosophy
-
-Aside from differences in capability, there's also a difference in
-philosophy.
-
-Frameworks such as *Wicketopia* make it easy to render a form to edit
-the properties of an entity, but the application developer remains in
-control of the rest of the application service layer, and in wiring the
-various pages together.
-
-With the *Wicket Viewer*, though, it is the framework that is in control
-of this layer too, because the links between pages are ultimately
-rendered by the property editor Components provided by the viewer, and -
-in rendering the links representing references - controls . What that
-also means is that every page rendered by the *Wicket Viewer* is always
-of either an object (typical case), or an action parameter dialog, or of
-a collection (the result of invoking an action).
-
-Within this constraint, there is a lot of flexibility, though, because
-every element of the page can be customized. Internally the *Wicket
-Viewer* uses the chain of responsibility pattern to determine how which
-Component type to use to render a page element. This works at a
-fine-grained level (eg a date editor) and also at a larger-scale, (eg
-rendering a collection of Locatable entities on a google maps). See ?
-for more on this.
-
-### Part of the *Apache Isis* framework
-
-The *Wicket Viewer* is only one of a number of viewers available for
-*Apache Isis*. What that means is that you can take your same domain
-objects model and deploy them in other architectures. For example, the
-DnD viewer is a rich, desktop GUI that employs a drag-n-drop metaphor
-(hence its name). It can be run as a standalone single-user application
-or in client/server mode. Even if you don't deploy this viewer in
-production, the way that it displays domain objects makes for a very
-good development tool: something akin to a UML design tool, only
-animated.
-
-*Apache Isis* also supports a number of different ways to test your
-application. Domain objects written to the *Apache Isis* programming
-model are just pojos, and so can easily be unit tested using frameworks
-such as [JUnit](http://junit.org) and [JMock](http://jmock.org). As a
-step up from that, *Apache Isis* provides its own integrations with
-JUnit, providing a "headless" programming model that wraps your domain
-objects in proxies. This allows unit testing as if through the lens of a
-GUI; trying to invoke an action that is disabled will throw an
-exception.
-
-Moving up to story testing/BDD, *Apache Isis* integrates with
-[Concordion](http://concordion.org). The business analyst specifies the
-behavior of the system in HTML, and then the developer wire up this
-specification to the domain model using a set of fixtures that interact
-with the domain objects following the same rules as the viewers. This
-allows application-level testing without the hassle of using a GUI
-testing framework such as *Selenium*.
-
-One final point: *Apache Isis* has a strong separation between its
-programming model and the framework that understands that programming
-model. So, your domain objects depend only on the *Apache Isis* applib
-(which defines annotations such as @RegEx), not the framework itself.
-This allows you to take your domain objects and deploy them on other
-frameworks later, if need be. The *Wicket Viewer* maintains this strong
-separation, defining its own applib for annotations and features unique
-to the *Wicket Viewer*.
-
-The *Wicket Viewer* compared to other *Apache Isis* viewers
------------------------------------------------------------
-
-Because the *Wicket Viewer* renders your domain model within a webapp,
-it is to some extent similar to the HTML viewer that is provided
-out-of-the-box by *Apache Isis* itself. However, unlike the HTML viewer,
-the *Wicket Viewer* is highly customizable. The *Wicket Viewer* itself
-essentially consists of a set of [Wicket](http://wicket.apache.org)
-Components that are used to render domain objects, individual member
-elements of domain objects, and indeed collections of domain objects.
-The components provided are sufficient to render any *Apache Isis*
-domain model. However, any developer with experience of *Wicket* can
-easily write their own components and register them with the *Wicket
-Viewer*. In this way, custom renderings of domain objects can be
-achieved.
-
-Typical Flow for Developing a Wicket Objects Application
---------------------------------------------------------
-
-There are, of course, lots of ways to skin any given cat, but here's how
-you might go about developing an *Apache Isis* application to be
-deployed using the *Wicket Viewer*:
-
--   use the *Apache Isis* application archetype to create an outline
-    domain model, running against the in-memory object store. The
-    structure of a *Apache Isis* application is reviewed in ?.
-
--   (optionally) use the DnD viewer to define some of the basic domain
-    services and entities. Or, you might want to skip this step and
-    develop solely using Wicket.
-
--   run your application under *Wicket*, either using a built-in Jetty
-    web server (see ?) or as a regular webapp (see ?).
-
--   customize the look-n-feel to use your preferred fonts and logos by
-    updating the CSS (see ?). You can also use CSS to fine-tune the
-    layout for selected objects or object members (see ?).
-
--   continue to develop your domain application, identifying properties,
-    collections and defining behavior through actions. Also, define
-    fixtures to represent pre-canned scenarios to explore with your
-    domain expert. Check out the core *Apache Isis* documentation for
-    more on developing domain objects.
-
--   fine tune the set of Components used to render your entities. The
-    *Wicket Viewer* provides built-in Components to render every element
-    of your domain objects, and in some cases provides more than one
-    Component. When the *Wicket Viewer* provides a number of alternate
-    views like this, you might prefer only one. Or, you might use an
-    existing Component and adapt it into your own Component. In either
-    case, you'll need to fine-tune the set of ComponentFactorys (see ?).
-
--   implement custom representations of some entities (or collections of
-    entities), where it makes sense. For example, you might want to
-    display objects that have a location in a google maps mashup, or
-    objects that have a date/time in a calendar. Ultimately these custom
-    representations are also just ComponentFactorys. A number of
-    Components (including one for google maps and one for charting) are
-    described in ?; use these directly or use them as inspiration for
-    your own.
-
--   support specialized use cases, if you have any. That is, rather than
-    require the end-user to interact directly with persisted entities,
-    introduce transient process objects to manage workflow and bulk
-    input, or write transient report objects to provide dashboards
-
--   as you continue to develop your application, you may need to
-    integrate with external services. For example, you might want to
-    send out an email, or invoke a web service exposed by some other
-    system in your enterprise. Define an interface for these domain
-    services, and register their implementation in the *Apache Isis*
-    configuration file. See the main *Apache Isis* documentation for
-    more details on this.
-
--   ultimately your application will be ready to deploy. Before you do,
-    though, remember that you'll need to sort out persistence and
-    security (see ?)
-
-Enough verbiage. The next chapter is a run through of a simple
-application, screenshot by screenshot, so you can quickly assess whether
-the *Wicket Viewer* fits your needs.
-
-Application Walkthrough
-=======================
-
-> This chapter is a collection of screenshots to give you an idea of
-> what the
-> Wicket Viewer
-> can do.
-
-Most of the screenshots in this chapter require no specific GUI code; in
-fact the first six sections require no specialized code other than the
-domain objects. The GUI that you see is generated by the *Wicket Viewer*
-at runtime, directly from the domain model. You can find all the code
-for the domain objects in ?.
-
-Logging on, and the Application Services Menu
----------------------------------------------
-
-The *Wicket Viewer* integrates with *Apache Isis* authentication
-mechanism (which is itself pluggable); so we start off with a login
-screen:
-
-![](images/010-login.png)
-
-The initial home page shows a welcome message and more importantly a
-menu bar for each of the registered services defined in the domain
-application. These application services are the start points for the
-user, allowing them to find existing objects and to create new ones. For
-example the `Employees` menu item corresponds to the EmployeeRepository
-class.
-
-![](images/020-services-bar.png)
-
-From the menu bar we can get to the menu items for each service. So, for
-example, the `Employees` domain service provides two actions,
-`All Employees` and `Find
-      Employees`. These are generated automatically from corresponding
-methods - allEmployees() and findEmployees() - in the EmployeeRepository
-service.
-
-![](images/030-services-action.png)
-
-Viewing Entities and Collections of Entities
---------------------------------------------
-
-Because the `All Employees` action takes no arguments, invoking it just
-returns its results. In this case the action returns a collection (of
-Employees), and so the viewer renders the collection as a table. If the
-action had returned a single object, then that would have been rendered
-instead.
-
-![](images/040-action-result.png)
-
-Clicking on one of the links takes us to a page rendering that object,
-in this case an Employee. There is a form for the entity's properties on
-the left, and summary details on the right. In this particular case the
-entity has no collections; we'll see one that does shortly.
-
-![](images/050-entity-form.png)
-
-In the summary section we an image, a title and the entity actions. All
-these are rendered directly from a metamodel built by inspecting the
-entity's class. Just as we can invoke actions on the services, we can
-also invoke actions on the entities; for example, to view this
-Employee's Claims with the `Claims For,,,` action.
-
-![](images/060-entity-actions.png)
-
-As before, this action returns a collection (of Claims) and so is
-rendered as a table.
-
-![](images/070-entity-action-results.png)
-
-Clicking on a link to a Claim again renders the entity. This is rendered
-in a similar manner to the Employee entity seen earlier. However, the
-Claim entity also has a collection (of ClaimItems), so these are also
-rendered.
-
-![](images/080-entity-form-and-collections.png)
-
-Editing Objects
----------------
-
-In *Apache Isis* applications, we modify objects either by invoking
-actions on them or by editing them directly. Which properties are
-editable is determined by the entity itself, with the *Wicket Viewer*
-providing an appropriate editor for each property type. In the following
-screenshot we see the Claim entity being edited.
-
-![](images/090-entity-editing-scalars.png)
-
-As well as supporting the editing of properties with value types
-(boolean, String, Date etc), the viewer also allows properties
-representing references to other entities to be edited. For example,
-each Claim has an `approver` (of type Approver, and implemented by
-Employee). Thus, the viewer gives us the ability to find an Employee
-from the `Employees` repository:
-
-![](images/100-entity-editing-references.png)
-
-Leaving us with the `approver` reference set up:
-
-![](images/110-entity-editing-references-result.png)
-
-Invoking Actions
-----------------
-
-Being able to edit entities makes it easy to build CRUD-style
-(create/read/update/delete) applications. The *Wicket Viewer* also
-allows arbitrary actions to be performed on entities. In the screenshot
-below, we see the `Add Item` action (corresponding to addItem() method
-on the Claim class) being called:
-
-![](images/120-entity-action.png)
-
-Because this action takes parameters, the viewer renders a dialog form
-for the user to complete. Just as with the entity editor, we can specify
-parameters of any type, including references to other entities if we
-wish). In this particular case the parameter types are just numbers and
-strings:
-
-![](images/130-entity-action-parameters.png)
-
-When the action is complete, the entity is modified, by adding a new
-ClaimItem into the Claim's `items` collection.
-
-![](images/140-entity-modified.png)
-
-Admittedly, this `Add Item` action just a CRUD-style action. But the
-business logic in the action could be arbitrarily complex. The other
-action in Claim is `Submit`, which could perform lots of business
-processing:
-
-![](images/150-entity-action-more-complex.png)
-
-This action also takes an argument, being a reference to an Approver:
-
-![](images/160-entity-action-reference-parameters.png)
-
-When the action is performed, the object's state is updated, along with
-any other processing. For example, a message could have been sent via an
-enterprise service bus to the processing department. Note the title of
-the Claim entity has also been updated:
-
-![](images/170-entity-title-updated.png)
-
-Business Rules
---------------
-
-In addition to actions, we can also capture business rules by means of
-validation. For example, a Claim, once submitted, cannot be submitted
-again. With the *Wicket Viewer*, this is shown by a tooltip:
-
-![](images/180-entity-validation.png)
-
-*Apache Isis* supports three different types of validation: whether the
-class member (property, collection or action) is visible; whether it is
-usable, and, whether the proposed value or arguments are valid. Or, more
-pithily, "can you see it, can you use it, can you do it". The viewer
-surfaces all of these different validation rules in the GUI.
-
-View Components
----------------
-
-The pages rendered by the *Wicket Viewer* are built from multiple
-*Apache Wicket* Components. For example, the application service menu
-bar has its own Component:
-
-![](images/200-view-components-application-service.png)
-
-Likewise, there's a Component to render an entire entity:
-
-![](images/205-view-components-entity-simple.png)
-
-And there's a Component to display the properties of an entity:
-
-![](images/210-view-components-entity-properties.png)
-
-And in turn there's a Component for every entity property:
-
-![](images/220-view-components-entity-property.png)
-
-There are Components such as these for every class member, including
-collections, actions and, indeed, action parameters. In fact, you can
-think of the *Wicket Viewer* as basically a collection of pre-canned
-Components that know how to render the *Apache Isis* metamodel.
-
-Note, by the way, the CSS classes. Each HTML element can be targetted
-either by its type (a string scalar), or by its class member (the
-Claim's `description` property), or both. The viewer therefore makes it
-easy to contribute custom CSS that applies to every page.
-
-Alternate Views
----------------
-
-As we've seen already, there's a Component to render an entire entity.
-In fact, it's possible to provide more than one Component to do this. We
-could also view the entity in a tabbed view:
-
-![](images/230-multiple-views-for-entities.png)
-
-When there is more than one Component capable of rendering the object,
-the viewer allows the view to be selected:
-
-![](images/230-multiple-views-for-entities.png)
-
-This works for collections too; using the selector we can view a
-collection of Employees in a variety of ways:
-
-![](images/240-multiple-views-for-collections.png)
-
-Selecting the `icons` view shows the collection of Employees as icons:
-
-![](images/270-customize-ui-icons.png)
-
-So far all the screenshots we've seen have been generated from a basic
-domain application, with no custom GUI coding (see ?). But the *Wicket
-Viewer* is also extensible. So, we can write custom views/components,
-provide a corresponding ComponentFactory and then plug them into the
-*Wicket Viewer*'s registry of ComponentFactorys. For example, if we make
-Employee implement a view-specific Locatable interface, then we can
-render them on a google-maps mashup:
-
-![](images/280-customize-ui-maps-mashup.png)
-
-The selector, by the way, is actually implemented as yet another
-view/component, capable of rendering the entity or collection. It
-queries the ComponentFactory registry to determine how many other
-ComponentFactorys there are capable of rendering the entity or
-collection; if more than one then it provides a drop-down and then
-delegates to the other Components to do the work.
-
-Specialized Use Cases
----------------------
-
-Being able to easily render entities and collection of entities without
-any custom UI coding is great for being able to develop an understanding
-of the problem domain. However, it doesn't always make sense to let the
-user interact directly with the domain objects. For example, if the
-domain objects are very fine-grained such that clicking into them would
-be tedious for the user to do, it makes sense to introduce another
-object that collect the required data and walk the graph of domain
-objects on the users behalf. Or, more straight forwardly, the use case
-might be particularly complex or subtle, and we want to provide the user
-with additional guidance.
-
-The *Wicket Viewer* therefore lets us work with objects designed to
-guide the user through the use case. Because they represent a particular
-solution to help the user achieve their objective, you can think of them
-as being part of the solution space (whereas regular domain objects
-belong to the problem space). Another name also given for objects of
-this type is "process objects"; they take the user through a particular
-process.
-
-For example, we might have a wizard that takes the user through the
-process of making a new Claim:
-
-![](images/300-process-objects.png)
-
-The object this action returns is not a Claim, instead it is a
-ClaimWizard. Unlike Claim, this is not persisted; its state is bound to
-a particular users' session. The design of the ClaimWizard is like any
-other wizard, taking the user through a number of pages; first an
-introductory page:
-
-![](images/310-wizard-intro-page.png)
-
-After that we are taken through pages for each of the properties; For
-example the next page prompts for the Claim's `claimant`:
-
-![](images/320-wizard-claimant-page.png)
-
-The Claim's `approver` and `description` properties likewise have the
-own pages, for example:
-
-![](images/330-wizard-approver-page.png)
-
-The final page allows the user to review details, then confirm:
-
-![](images/340-wizard-finish-page.png)
-
-On finish, the ClaimWizard will create and persists the Claim.
-
-Process objects like wizards are primarily concerned with inputting
-data. We can also have objects that are tailored towards the output of
-data, eg for reporting. For example, we could have a (non-persisted)
-ClaimSummary object that sums up Claim amounts by Claimant:
-
-![](images/400-analyze-claim-summary.png)
-
-We can then combine this with custom views, eg to represent a collection
-of such ClaimExpenseSummarys as a pie chart:
-
-![](images/410-analyze-summary-piechart.png)
-
-There's some guidance on writing application code to deal with such
-specialized use cases in ?.
-
-Running the Application
-=======================
-
-> This chapter describes how to take an *Apache Isis* application and
-> get it running using the *Wicket Viewer*, with the non-customized,
-> generic OOUI.
-
-Applications deployed to run with the *Wicket Viewer* are, ultimately
-just *Wicket* webapps that happen to boot up *Apache Isis*. As such,
-they are bootstrapped with a `web.xml` that is structured the same as
-any other *Wicket* application.
-
-This chapter describes how to run up such a webapp starting with a
-regular *Apache Isis* application.
-
-Structure of an Apache Isis Application
----------------------------------------
-
-We recommend that you use *Apache Isis*' Maven application archetype to
-set up your application. Doing so will result in a multi-module project
-that contains the following modules:
-
--   `app`
-
-    Main (parent) module, whose `pom.xml` references the submodules
-
--   `app/dom`
-
-    Domain object model, plus interfaces for services, repositories and
-    factories
-
--   app/domsvc
-
-    Implementation of domain services (not repositories/factories)
-
--   `app/objectstore-default`
-
-    Implementation of repositories/factories for the default object
-    store
-
--   `app/fixture`
-
-    Fixtures, used to seed (in-memory) object store when running in
-    exploration/prototype mode
-
--   `app/commandline`
-
-    Bootstrap for running from the command line (typically, the DnD
-    viewer or HTML viewer)
-
--   `app/viewer-wicket`
-
-    The application set up to be run using wicket, and packaged up as a
-    webapp.
-
-You will see that the archetypes creates a number of other
-`app/viewer-xxx` and `app/objectstore-xxx` modules. You can delete those
-modules that aren't relevant to your final deployment (probably the
-`app/viewer-xxx` modules and most of the `app/objectstore-xxx` modules,
-or you can just ignore them. If you do delete any modules, remember to
-remove their reference from the parent `app/pom.xml` file'a \<modules\>
-section).
-
-### The viewer-wicket module's web.xml
-
-The `viewer-wicket` module aready contains a `web.xml` file to define
-the web app, in the `src/main/webapp` directory. The contents of this is
-largely boilerplate, and will be very familiar if you already know the
-*Apache Wicket* framework:
-
-    <?xml version="1.0" encoding="ISO-8859-1"?>
-    <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
-     version="2.4">
-
-      <display-name>claims</display-name>
-      <filter>
-        <filter-name>wicket.app</filter-name>
-        <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
-        <init-param>
-          <param-name>applicationClassName</param-name>
-          <param-value>org.apache.isis.viewer.wicket.viewer.IsisWicketApplication</param-value>
-        </init-param>
-      </filter>
-
-      <filter-mapping>
-        <filter-name>wicket.app</filter-name>
-        <url-pattern>/*</url-pattern>
-      </filter-mapping>
-
-    </web-app>
-
-The IsisWicketApplication is a subclass of *Wicket*'s own WebApplication
-that bootstraps *Apache Isis*, handles authentication and sets up
-sessions and transactions.
-
-### Deployment Mode
-
-*Apache Wicket* webapps can be run in one of two "configuration type"s,
-either in the `development` configuration type or in the `deployment`
-configuration type. In Wicket, the configuration type can be specified
-as either:
-
-1.  A system property: `-D
-                wicket.configuration`
-
-2.  as a servlet specific `<init-param>`
-
-3.  as a context specific `<context-param>`
-
-Setting this value changes various properties, such as whether templates
-are reloaded. Wicket's Application\#configure() method is the place to
-look for all the differences.
-
-For its part, *Apache Isis* defines various "deployment mode"s. For
-example, `exploration` and `prototype` mode are both intended for
-single-user development, with the former requiring no login and also
-including any actions annotated as `@Exploration`. For multi-user
-(production) use, *Apache Isis* provides the `server` deployment mode,
-associating a separate *Apache Isis* runtime (IsisContext) to each
-thread (ie bound to a `ThreadLocal`).
-
-The *Wicket Viewer* maps *Wicket*'s `development` configuration type to
-*Apache Isis*' `prototype` deployment mode. However, the `server`
-deployment mode provided by *Apache Isis* is not quite appropriate for a
-*Wicket* webapp, because there could be multiple concurrent requests for
-a given user (originating from the same browser/user agent). The *Wicket
-Viewer* therefore defines a custom deployment mode which binds the
-*Apache Isis* runtime to the *Wicket* session (see the
-IsisContextForWicket class if you're interested in such things).
-
-What all this means is that selecting between *Apache Isis* deployment
-modes is done just by specifying the *Apache Wicket* configuration type.
-If you're already familiar with Wicket there's therefore nothing new to
-learn: just configure the webapp to run in either `development` or
-`deployment` mode.
-
-### Security
-
-Since both of the deployment modes supported by *Wicket Objects* require
-a login, it means we need to set up security. The IsisWicketApplication
-class provided by the *Wicket Viewer* subclasses from *Wicket*'s own
-AuthenticatedWebApplication, and serves up a sign-in page. To ensure
-that this sign-in page appears, every web page served up by the *Wicket
-Viewer* is annotated with
-`@AuthorizeInstantiation("org.apache.isis.viewer.wicket.roles.USER")`,
-which requires that every login has a role called
-`org.apache.isis.viewer.wicket.roles.USER`.
-
-*Apache Isis* deployment modes provide a couple of ways of avoiding
-login during development. For example, in `exploration` mode the viewers
-automatically login, while in `exploration` mode and `prototype` mode
-specifying a `LogonFixture` will means an automatic logon using the
-details provided within that fixture. The *Wicket Viewer* does not
-support `exploration` mode, however, and does not currently support
-LogonFixture. What that means is that it's always necessary to login.
-
-The *Wicket Viewer* delegates to *Apache Isis* to authentication.
-*Apache Isis*' default authentication mechanism is a no-op and requires
-no configuration. If you decide to a different authentication mechanism
-(eg file-based security, org.apache.isis.alternatives.security:file, or
-LDAP-based security, org.apache.isis.alternatives.security:ldap) then
-refer to the appropriate documentation for that module.
-
-The *Wicket Viewer* simply always places each login into the
-`org.apache.isis.viewer.wicket.roles.USER` role, to ensure that once the
-sign-in page is navigated past, that the user can access each web page.
-
-One consequence of this design is that the roles cannot currently be
-used by the *Apache Isis* domain objects nor the authorization
-mechanism; every user is simply in the USER role. This will be addressed
-in the future.
-
-Running as a WAR
-----------------
-
-The most straightforward approach for running a *Wicket
-Viewer*application is to build a WAR archive from the `viewer-wicket`
-module. Most IDEs will then allow this WAR to be deployed on an external
-servlet container, for debugging. For example, in Eclipse this is done
-by Run As \> Server:
-
-![](images/RunAsServer.png)
-
-and then select the external servlet container to deploy against:
-
-![](images/RunAsServer-dialog.png)
-
-If deploying this way, then the web browser URL may be slightly
-different. For example with Eclipse the URL to specify is
-<http://localhost:8080/webappname>.
-
-Running using *Isis*' WebServer class
--------------------------------------
-
-As an alternative to deploying as a webapp, you can use Isis' WebServer
-class. This class has its own main() to bootstraps Jetty and configures
-a webapp from the `web.xml` file. If using Eclipse, for example, then yo
-can create a `.launch` configuration to run your application using
-WebServer.
-
-### Adding Dependency to Bootstrap
-
-The only thing you need to do is to edit the `viewer-wicket` module's
-`pom.xml`; add/comment in:
-
-    <dependency>
-     <groupId>org.apache.isis.core</groupId>
-     <artifactId>webserver</artifactId>
-    </dependency>
-
-### Running the Application
-
-Running the application is just a matter of running the
-org.apache.isis.WebServer. For example, in Eclipse the following launch
-configuration should suffice:
-
-![](images/WebServer-launch.png)
-
-Running this will boot strap a Jetty webserver:
-
-![](images/WebServer-running.png)
-
-You can then log on using <http://localhost:8080>:
-
-![](images/WicketObjects-logon-page.png)
-
-Customizing the Startup
------------------------
-
-Most of the remaining chapters address various means by which the UI
-generated by the *Wicket Viewer* can be customized. Before we go any
-further, though, we should mention that the viewer uses dependency
-injection provided by [Guice](http://google-guice.googlecode.com). It
-comes with default bindings, so customizing the *Wicket Viewer* requires
-overriding these default bindings.
-
-Note: this usage of Guice is likely to be replaced by JSR-299 based
-dependency mechanism.
-
-Specifically, in IsisWicketApplication, there's a method
-newIsisWicketModule():
-
-    public class IsisWicketApplication extends AuthenticatedWebApplication {
-      ...
-      protected Module newIsisWicketModule() {
-        return new IsisWicketModule();
-      }
-    }
-
-This method can be overridden in your own subclass of
-IsisWicketApplication, providing a new implementation of *Guice*'s
-Module interface. Typically you'll just want to override one or two of
-the bindings, so you should use the Modules helper class:
-
-    public class MyApplication extends IsisWicketApplication {
-      ...
-      protected Module newIsisWicketModule() {
-        return Modules.override(super.newIsisWicketModule()).with(
-          new AbstractModule() {
-            @Override
-            protected void configure() {
-              // override bindings here
-            }
-          }
-        );
-      }
-    }
-
-To pick up your subclass of IsisWicketApplication, just update the
-`web.xml` file.
-
-Customizing CSS
-===============
-
-> This chapter describes how to customize the UI generated by the
-> *Wicket Viewer* by providing application-specific CSS.
-
-CSS is used heavily by the *Wicket Viewer*, with the HTML of each
-Component using CSS classes for the styling. But you can override the
-default styling by supplying an application-level CSS file.
-
-By default this file should be called `application.css` and should
-reside within `WEB-INF` directory.
-
-There are two levels at which we can override the default styling,
-either generically or specific to a particular domain. Let's look at
-both.
-
-Generic CSS
------------
-
-The name of each class indicates the nature of what is being rendered,
-and each Component provides some default styling so that the
-out-of-the-box UI is usable. For example, an entity icon, title and
-actions are rendered as:
-
-![](images/EntitySummary.png)
-
-The icon and title for this are rendered as:
-
-    <div class="entitySummary">
-      <img src="?wicket:interface=:4:entity:entity:entitySummary:entityImage:1:IResourceListener::"
-           class="entityImage" wicket:id="entityImage">
-      <label class="entityTitle" wicket:id="entityTitle">Fred Smith</label>
-      ...
-    </div>
-
-So, to change the font, you could use:
-
-    div.entitySummary > label.entityTitle {
-      color: maroon;
-      font-size: xx-large;
-      font-weight: bolder;
-    }
-
-This would render the entity icon and title as:
-
-![](images/EntitySummary-Css.png)
-
-In this way you can develop a look-n-feel for the application (or
-perhaps your organization).
-
-Specific CSS
-------------
-
-As well as targetting HTML elements generically, individual class
-members can also be targetted for a particular domain model.
-
-For example, the properties of a Claim object might be rendered as:
-
-![](images/Claim-properties.png)
-
-The HTML for the description property is:
-
-    <div class="Claim-description" wicket:id="scalar">
-      <wicket:panel>
-        <div class="string scalarPanel">
-          <label wicket:id="scalarIfRegular" for="scalarValue3d">
-            <span class="scalarName" wicket:id="scalarName">description</span>
-            <span class="scalarValue">
-              <input type="text" title="" size="25" disabled="disabled"
-                 value="Meeting at clients" wicket:id="scalarValue"
-                 id="scalarValue3d"
-                 name="properties:1:scalar:scalarIfRegular:scalarValue">
-            </span>
-          </label>
-          <span wicket:id="feedback">
-            <wicket:panel>
-            </wicket:panel>
-          </span>
-        </div>
-      </wicket:panel>
-    </div>
-
-To change the label of this specific element, we could use:
-
-    .Claim-description .scalarName {
-      color: maroon;
-      font-weight: bolder;
-    }
-
-which would give us:
-
-![](images/Claim-properties-CSS.png)
-
-This is a slightly trite example, but demonstrates the point.
-
-Changing the location/name of the application CSS file
-------------------------------------------------------
-
-As already mentioned, the default for the application CSS file is in
-`WEB-INF/application.css`. If for any reason you want to change this,
-you can do so by subclassing IsisWicketApplication and overriding the
-newIsisWicketModule() method.
-
-For example, to use `css/myapp.css` (under `WEB-INF`) you would write:
-
-    public class MyApplication extends IsisWicketApplication {
-      ...
-      protected Module newIsisWicketModule() {
-        return Modules.override(super.newIsisWicketModule()).with(
-          new AbstractModule() {
-            @Override
-            protected void configure() {
-              bindConstant().annotatedWith(ApplicationCssUrl.class).to("css/myapp.css");
-            }
-          }
-        );
-      }
-    }
-
-Your custom application should then be registered in `web.xml`, as
-described in ?.
-
-Using the Wicket Viewer AppLib
-==============================
-
-> This chapter explains how to use certain viewer-specific features in
-> your domain application.
-
-Many *Isis* components have their own application library, the *Wicket
-Viewer* included. This allows you to specify additional viewer-specific
-semantics within your domain model; the viewer can then render them
-appropriately.
-
-Configuring the Project Modules
--------------------------------
-
-In order to use the viewer-specific features, the `dom` module must
-reference the applib, and the `viewer-wicket` module must be configured
-appropriately.
-
-### Referencing the AppLib
-
-In the dom project, add in a `<dependency>` to the *Wicket Viewer*
-applib:
-
-    <dependencies>
-      ...
-
-      <!-- Wicket Viewer -->
-      <dependency>
-        <groupId>org.apache.isis.viewer.wicket</groupId>
-        <artifactId>applib</artifactId>
-      </dependency>
-
-      ...
-    </dependencies>
-
-This will allow you to use the *Wicket Viewer*'s annotations etc. in
-your domain objects.
-
-### Configuring the *Wicket Viewer* Facets
-
-In addition, you must also configure your application so that the *Isis*
-metamodel contains the information to be picked up by the *Wicket
-Viewer*.
-
-In the `viewer-wicket` module, add the following to `isis.properties`:
-
-    isis.reflector.facets.include=\
-        org.apache.isis.viewer.wicket.metamodel.wizardpagedesc.WizardPageDescriptionAnnotationFacetFactory\
-       ,org.apache.isis.viewer.wicket.metamodel.cssclass.CssClassAnnotationFacetFactory
-
-This basically instructs *Apache Isis* to capture additional information
-(facets) in its metamodel. Now let's look at what these facets are used
-for.
-
-@CssClass
----------
-
-The @CssClass annotation allows you to specify an additional CSS class
-(or classes) applied on any object type, property, collection or action.
-This CSS will be added verbatim to any CSS classes that are normally
-applied by the *Wicket Viewer* itself.
-
-\*\*\* TODO: complete.
-
-There is further discussion on
-
-@WizardPageDescription
-----------------------
-
-It's common for wizards to have a description explaining what the user
-is expected to do. This can be modeled as a String property annotated
-with @WizardPageDescription, for example:
-
-    @NotPersistable
-    public class ClaimWizard extends AbstractDomainObject {
-
-        ...
-
-        @WizardPageDescription
-        @MemberOrder(sequence = "1")
-        public String getPageDescription() { ... }
-
-        ...
-    }
-
-Adding this annotation causes the *Wicket Viewer* to select a different
-Component to be used to render this property; specifically, one that
-renders the value as a large label. You can see the result of this
-annotation in below (the label above the claimant).
-
-![](images/320-wizard-claimant-page.png)
-
-Note that this annotation only affects the description; the three
-buttons shown in the above screenshot are as a result of the wizard
-being implemented as a custom component. For more on that topic, see ?.
-
-Customizing the Component Set
-=============================
-
-> This chapter describes the how to customize the UI by modifying the
-> set of components used to render objects, properties, collections or
-> actions.
-
-The *Wicket Viewer* offers several ways in which the UI rendered can be
-customized, from simply tweaking the CSS (see ?) through to the use of
-custom components for mashups and wizards. This chapter explains how to
-use pre-existing custom components; ? explains how to write your own
-components, and lists some components that have already been developed.
-
-There are more details provided in each of the sections that follow.
-
-Component Factories
--------------------
-
-### ComponentFactory interface
-
-At its heart the *Wicket Viewer* consists of a set of *Wicket*
-`Component`s and corresponding IModel\<?\>s that are used to render
-entities, collections of elements and indeed individual members of
-elements. Each Components is created by a corresponding
-ComponentFactory, with the factory to use discovered using a
-chain-of-responsibility pattern.
-
-The Components created by the *Wicket Viewer* vary in size from
-rendering an entire collection of entities all the way down to a single
-property of an entity. You can find the full set of built-in Components
-by searching for implementations of ComponentFactory:
-
-![](images/ComponentFactory-hierarchy.png)
-
-For example, the CollectionContentsAsAjaxTableFactory class is used to
-render a collection of entities (eg returned from an action invocation)
-as, erm, an ajax table;
-
-    public class CollectionContentsAsAjaxTableFactory extends ComponentFactoryAbstract {
-      private static final long serialVersionUID = 1L;
-      private static final String NAME = "styled";
-
-      public CollectionContentsAsAjaxTableFactory() {
-        super(ComponentType.COLLECTION_OF_ENTITIES, NAME);
-      }
-
-      @Override
-      public boolean appliesTo(IModel<?> model) {
-        return model instanceof EntityCollectionModel;
-      }
-
-      public Component createComponent(String id, IModel<?> model) {
-        EntityCollectionModel collectionModel = (EntityCollectionModel) model;
-        return new CollectionContentsAsAjaxTable(id, collectionModel);
-      }
-    }
-
-The selection of the ComponentFactory is based on two criteria: the
-ComponentType, and the IModel\<?\>. Broadly speaking the ComponentType
-standardizes the `wicket:id` used in the HTML fragment (so
-`<div wicket:id="collectionContents"/>` would map onto the
-ComponentType.COLLECTION\_CONTENTS, while the IModel\<?\> is the
-corresponding information used for the rendering of that component. But
-there's a semi-formal relationship between these two concepts; the
-ComponentType effectively acting as a power-type for the subclass of
-IModel\<?\> that is supplied.
-
-The superclass ComponentFactoryAbstract takes responsibility for
-checking that the ComponentType matches the `wicket:id`, while
-delegating the checking of the IModel to its subtype:
-
-    public abstract class ComponentFactoryAbstract implements ComponentFactory ... {
-      ...
-      public final boolean appliesTo(ComponentType componentType, IModel<?> model) {
-        return componentType == getComponentType() && appliesTo(model);
-      }
-
-      protected abstract boolean appliesTo(IModel<?> model);
-      ...
-    }
-
-The subclass then refines this check by overriding appliesTo() to also
-check the model; returning true indicates that the ComponentFactory is
-able to render that model, after which the createComponent() method is
-then called to actually create the instance. So in
-CollectionContentsAsAjaxTableFactory, its implementation simply checks
-if the supplied model is an EntityCollectionModel. More
-sophisticated/less generic ComponentFactory might also make additional
-checks; you can find some examples of these in ?.
-
-### Registering ComponentFactorys using META-INF Services
-
-The easiest way to register new ComponentFactorys is using the JDK's own
-ServiceLoader capability.
-
-All that is needed is for your ComponentFactory to be registered in a
-file on the classpath call
-`META-INF/services/org.apache.isis.viewer.wicket.ui.ComponentFactory`.
-The contents of this file should be the fully qualified class name of
-your ComponentFactory implementation. And that's it! Registering the
-ComponentFactory is done automatically just by virtue of updating the
-classpath. You'll find that the custom components described in ? all use
-this technique.
-
-Note that this technique does not allow you to remove existing
-ComponentFactorys, only add new ones. So if you do want to exclude any
-of the built-in ComponentFactorys, then you will still need to use the
-ComponentFactoryList method.
-
-> **Note**
->
-> This capability is provided by the ComponentFactoryRegistry component,
-> which is also bound in the IsisWicketModule. If you wanted to, you
-> could replace this higher-level registry component with your own
-> implementation. There's probably very little need to do this though,
-> given that you can just as easily customize using ComponentFactoryList
-> or `META-INF` services.
-
-### Registering ComponentFactorys using a custom ComponentFactoryList
-
-The set of ComponentFactorys that are provided with the *Wicket Viewer*
-are specified by the ComponentFactoryList interface.
-
-If you only want to add new factories, we recommend using the technique
-described in ?. But if you want to remove support for any of the default
-factories, or perhaps change the order in which factories are
-registered, you'll need to do use write and the bind in your own
-implementation of ComponentFactoryList.
-
-To write your implementation of ComponentFactoryList, start with the
-default implementation, ComponentFactoryListDefault. You'll see that it
-is written so that it can be easily subclassed and overridden on an
-as-needed basis. Worst case scenario, you can copy-and-paste code as
-necessary.
-
-Then, you need to override the binding in newIsisWicketModule(), eg:
-
-    public class MyApplication extends IsisWicketApplication {
-      ...
-      protected Module newIsisWicketModule() {
-        return Modules.override(super.newIsisWicketModule()).with(
-          new AbstractModule() {
-            @Override
-            protected void configure() {
-              bind(ComponentFactoryList.class).to(MyComponentFactoryList.class);
-            }
-          }
-        );
-      }
-    }
-
-You should also ensure that your MyComponentFactoryList is annotated
-with @Singleton.
-
-And, do remember to update `web.xml` to reference your subclass of
-IsisWicketApplication.
-
-Advanced Customization
-----------------------
-
-This section covers a couple of more advanced customization topics.
-
-### Page Registry
-
-While the content of any given web page rendered by the *Wicket Viewer*
-is made up of multiple Components, there are in fact only a small number
-of WebPages:
-
--   WelcomePage displays the initial home page with a welcome message
-
--   EntityPage displays a single entity
-
--   ActionPage displays an action dialog or the results of invoking an
-    action.
-
-Each of these has a corresponding HTML page which defines the content of
-that page. In many cases the look-n-feel of these pages can be adjusted
-simply using CSS, as described in ?. If necessary though an entirely
-different page layout can be specified, for example to put the menubar
-on the left rather than at the top.
-
-The easiest approach to define a new page is to subclass PageAbstract
-superclass and then provide a different implementation of PageRegistry.
-As for ComponentFactorys, this is done by providing a new
-implementation, and then overriding a binding in newIsisWicketModule().
-
-The default pages are specified by PageClassListDefault:
-
-    public class PageClassListDefault implements PageClassList  {
-
-      @Override
-      pulic void registerPages(PageRegistrySpi pageRegistry) {
-        pageRegistry.registerPage(PageType.SIGN_IN, WicketSignInPage.class);
-        pageRegistry.registerPage(PageType.SIGN_OUT, WicketSignOutPage.class);
-        pageRegistry.registerPage(PageType.ENTITY, EntityPage.class);
-        pageRegistry.registerPage(PageType.HOME, HomePage.class);
-        pageRegistry.registerPage(PageType.ACTION, ActionPage.class);
-      }
-    }
-
-You can easily copy-n-paste this to create your own implementation. Note
-though that there must be a registered page for every PageType instance,
-otherwise the *Wicket Viewer* will fail fast on boot time.
-
-Overriding the binding is done in the usual way:
-
-    public class MyApplication extends IsisWicketApplication {
-      ...
-      protected Module newIsisWicketModule() {
-        return Modules.override(super.newIsisWicketModule()).with(
-          new AbstractModule() {
-            @Override
-            protected void configure() {
-              bind(PageClassList.class).to(MyPageClassList.class);
-            }
-          }
-        );
-      }
-    }
-
-Don't forget to update the web.xml to specify your subclass of
-IsisWicketApplication.
-
-> **Note**
->
-> If all you want is to provide a custom rendering of a particular
-> interface or class, then you should instead write and register a
-> ComponentFactory, with a ComponentType.ENTITY and filtering the
-> EntityModel. The custom components described in ? do this, as does the
-> component registered in the test application to render a wizard (see
-> ?).
-
-### Subclassing IsisWicketApplication
-
-As we've seen, you can also customize *Wicket Objects* in various ways
-by subclassing the IsisWicketApplication bootstrap. The most common
-reason for doing so is to override the default implementation of
-ComponentFactoryList.
-
-This design follows the general style of *Wicket*; in fact, you'll see
-that IsisWicketApplication itself overrides a number of other methods
-(such as newRequestCycle() and newConverterLocator()), in order to hook
-*Apache Isis* into the rest of Wicket.
-
-In general it's unlikely that you'll need to alter the behavior of these
-hook methods; but it's useful to know that *Wicket Objects* doesn't
-particularly interfere with the way in which you may be used to
-customizing regular *Wicket* applications.
-
-Writing Custom Components
-=========================
-
-> This chapter provides some further guidance on objects designed to
-> support specialized use cases.
-
-Back in the application walkthrough (see ?) we saw that the *Wicket
-Viewer* has support for non-persisted objects that are designed to
-support specialized use cases. Whereas regular persisted domain objects
-can be thought of as part of the problem space, such non-persisted
-objects can be thought of as being part of the solution space because
-they offer a particular solution to a particular user objective. We call
-these objects *process objects* because objects they help a user perform
-a particular process.
-
-This chapter provides some general guidance on writing such process
-objects, and outlines the support that exists in *Wicket Objects* for
-writing custom components for such objects.
-
-Custom Components for Process Objects
--------------------------------------
-
-Because process objects are there to guide the user, they often go
-hand-in-hand with custom components so that they can be rendered in a
-particular way.
-
-For example, in the application walkthrough we saw that a ClaimWizard
-process object is rendered with its previous(), next() and finish()
-actions as regular buttons:
-
-![](images/320-wizard-claimant-page.png)
-
-Similarly, the ClaimExpenseSummary object (or rather, a collection of
-them) hooks into the capabilities of the googlecharts component
-(discussed in ?):
-
-![](images/410-analyze-summary-piechart.png)
-
-You can use any of the *Wicket Viewer*'s built-in Components that are
-used to build the generic views for your own custom views; search down
-the ComponentFactory inheritance hierarchy and there's a good chance
-you'll find something of use. For example, you can easily add components
-to represent properties in a wizard (the custom Component for
-ClaimWizard does precisely this; you can inspect the code in ?).
-
-The *Wicket Viewer* also has a small number of Components intended for
-writing custom views.
-
-### ProcessObjectPanelAbstract
-
-The ProcessObjectPanelAbstract is intended to be used as the superclass
-for any panel-like Component that will render a process object. Its
-model is intended to be an EntityModel, which wraps the process object.
-
-This adapter class contains a number of convenience methods to help
-build panels:
-
--   addProperties(Form\<?\> form, String id)
-
-    This adds the currently visible properties from the process object
-    to the provided form
-
--   isValid(Form\<?\> form)
-
-    This validates the process object, where the form holds the
-    properties
-
--   executeNoArgAction(String actionId)
-
-    Executes the indicated action on the process object (expected to
-    take no-arguments).
-
-Although minimal, these methods are sufficient to build a basic wizard.
-The executeNoArgAction() method, for example, allows `Previous`, `Next`
-and `Finish` buttons to be added.
-
-### Help Wanted!
-
-As you can see, the level of support provided by the *Wicket Viewer* for
-custom views is, admittedly, quite limited. There's nothing to prevent
-you from writing your own, of course, but to do so you'll need to use
-with the *Apache Isis* metamodel APIs.
-
-We hope to extend the components available as *Wicket Objects* continues
-to be developed. But in the meantime, if you build a Component that you
-think would be generally useful, please consider contributing it back to
-this project for the benefit of others.
-
-Use a Page enum for Wizards
----------------------------
-
-Here's just a bit of good old-fashioned advice; consider using an enum
-to track the state of your wizards.
-
-For example, the ClaimWizard in the example app has the following enum
-defined:
-
-    @NotPersistable
-    public class ClaimWizard extends AbstractDomainObject {
-
-        public enum Page {
-            INTRO("This wizard will take you through the process of creating a claim"),
-            CLAIMANT("Enter the claimant that is making this claim"),
-            APPROVER("By default, the claimant's own approver will approve this claim.  " +
-              "Update here if another approver will approve this claim."),
-            DESCRIPTION("Update the description if required."),
-            SUMMARY("Confirm all details, or go back and amend if needed");
-
-            private String description;
-            private Page(String description) {
-                this.description = description;
-            }
-
-            public String getDescription() {
-                return description;
-            }
-
-            public boolean hasPrevious() {
-                return ordinal() > 0;
-            }
-            public Page previous() {
-                if (hasPrevious()) {
-                    return values()[ordinal() - 1];
-                } else {
-                    return this;
-                }
-            }
-
-            public boolean hasNext() {
-                return ordinal() < values().length - 1;
-            }
-            public Page next() {
-                if (hasNext()) {
-                    return values()[ordinal() + 1];
-                } else {
-                    return this;
-                }
-            }
-
-            @Ignore
-            public boolean is(Page... pages) {
-                for (Page page : pages) {
-                    if (page == this) {
-                        return true;
-                    }
-                }
-                return false;
-            }
-        }
-
-        ...
-    }
-
-This not only defines the descriptions of each Page, it also includes
-some logic for the previous() and next() actions to delegate to:
-
-    @NotPersistable
-    public class ClaimWizard extends AbstractDomainObject {
-
-        // {{ Page
-        private Page page;
-        @Hidden
-        public Page getPage() { ... }
-        public void setPage(final Page page) { ... }
-        // }}
-
-
-        // {{ Page Description
-        @WizardPageDescription
-        @MemberOrder(sequence = "1")
-        public String getPageDescription() { ... }
-
-        // {{ previous
-        @MemberOrder(sequence = "1")
-        public void previous() {
-            setPage(getPage().previous());
-        }
-        public String disablePrevious() {
-            return coalesce(noPreviousPage(), confirmIfOnSummaryPage());
-        }
-        private String noPreviousPage() {
-            return !getPage().hasPrevious() ? "no previous page" : null;
-        }
-        // }}
-
-        // {{ next
-        @MemberOrder(sequence = "2")
-        public void next() {
-            setPage(getPage().next());
-        }
-        public String disableNext() {
-            return coalesce(noNextPage(), confirmIfOnSummaryPage());
-        }
-        private String noNextPage() {
-            return !getPage().hasNext() ? "no next page" : null;
-        }
-        // }}
-
-        ...
-    }
-
-Custom Components in isis-contrib
-=================================
-
-> This chapter describes a number of custom components for the *Wicket
-> Viewer*. Some of these integrate third party components and/or
-> experimental.
-
-As was described in ?, the *Wicket Viewer* is designed to be extensible,
-allowing you to plug in more sophisticated renderings of the domain
-objects that make up your application. This chapter describes a number
-of custom components that demonstrate this capability, most of which are
-basically wrappers around functionality within the *Wicket*'s companion
-[WicketStuff](http://wicketstuff.org) project.
-
-The components here are probably best considered as examples rather than
-formally part of the *Wicket Viewer*, if only because we want the
-*Wicket Viewer* to depend just on core *Wicket*, not *WicketStuff*. But
-what you will find is that all the components here follow a similar
-layout, so you can easily adapt copy them into your own projects and
-adapt them as you feel fit.
-
-About the Components
---------------------
-
-The source for these components is available at \*\*\*.
-
-### Common Layout
-
-Most of the components define their own interfaces or annotations; these
-are then implemented or annotated on the domain classes so that the
-component knows whether it applies or not (see discussion on
-ComponentFactory, in ?).
-
-To minimize the coupling between the domain objects and the component
-implementation, we separate out the interfaces/annotations into an
-applib.
-
-![](images/views-common-layout.png)
-
-The naming convention for these modules is:
-
--   `org.starobjects.wicket:view-xxx` for the parent module for view
-    'xxx'
-
--   `org.starobjects.wicket:view-xxx-applib` for the applib submodule
-
--   `org.starobjects.wicket:view-xxx-view` for the view submodule (that
-    contains the actual ComponentFactory and Component implementations)
-
-### Adding Dependency Management for Custom Views
-
-In the parent project's `pom.xml`, specify the modules of the custom
-views that you want to use, along with the version:
-
-    <dependencyManagement>
-      <dependencies>
-        ...
-
-        <!-- Wicket Viewer view extensions -->
-        <dependency>
-          <groupId>org.apache.isis.viewer.wicket</groupId>
-          <artifactId>view-gmap2-applib</artifactId>
-          <version>${wicketobjects.version}</version>
-        </dependency>
-
-        <dependency>
-          <groupId>org.apache.isis.viewer.wicket</groupId>
-          <artifactId>view-gmap2-view</artifactId>
-          <version>${wicketobjects.version}</version>
-        </dependency>
-
-        <dependency>
-          <groupId>org.apache.isis.viewer.wicket</groupId>
-          <artifactId>view-googlecharts-applib</artifactId>
-          <version>${wicketobjects.version}</version>
-        </dependency>
-
-        <dependency>
-          <groupId>org.apache.isis.viewer.wicket</groupId>
-          <artifactId>view-googlecharts-view</artifactId>
-          <version>${wicketobjects.version}</version>
-        </dependency>
-
-        <dependency>
-          <groupId>org.apache.isis.viewer.wicket</groupId>
-          <artifactId>view-calendarviews-applib</artifactId>
-          <version>${wicketobjects.version}</version>
-        </dependency>
-
-        <dependency>
-          <groupId>org.apache.isis.viewer.wicket</groupId>
-          <artifactId>view-calendarviews-view</artifactId>
-          <version>${wicketobjects.version}</version>
-        </dependency>
-
-        <dependency>
-          <groupId>org.apache.isis.viewer.wicket</groupId>
-          <artifactId>view-cooldatasoftmenu-view</artifactId>
-          <version>${wicketobjects.version}</version>
-        </dependency>
-
-        ...
-      <dependencies>
-    </dependencyManagement>
-
-### Adding the Custom View's AppLibs as Dependencies
-
-\*\*\* Again, if you intend to use any of the custom components (see ?),
-then also add in dependencies to their respective applibs (if they have
-one):
-
-    <dependencies>
-      ...
-
-      <!-- Wicket Viewer view extensions -->
-      <dependency>
-        <groupId>org.starobjects.wicket</groupId>
-        <artifactId>view-calendarviews-applib</artifactId>
-      </dependency>
-
-      <dependency>
-        <groupId>org.starobjects.wicket</groupId>
-        <artifactId>view-gmap2-applib</artifactId>
-      </dependency>
-
-      <dependency>
-        <groupId>org.starobjects.wicket</groupId>
-        <artifactId>view-googlecharts-applib</artifactId>
-      </dependency>
-
-      ...
-    </dependencies>
-
-### Update Classpath
-
-The classpath for both the `dom` submodule and the `commandline` /
-`webapp` submodule each need to be updated (see ? for an overview of the
-typical structure of an *Apache Isis* application):
-
--   the `dom` submodule should be updated to reference the
-    view-xxx-applib submodule for each custom component
-
--   the `commandline` / `webapp` module should be updated to reference
-    the `view-xxx-view` submodule for each custom component
-
-Gmap2
------
-
-The gmap2 component renders a collection of objects in a Google map:
-
-![](images/280-customize-ui-maps-mashup.png)
-
-All that is required is for the object to implement Locatable interface,
-which in turn returns a Location value object:
-
-    package org.apache.isis.viewer.wicket.view.gmap2.applib;
-
-    public interface Locatable {
-        Location getLocation();
-    }
-
-If deploying on localhost, no API key is required. However, internet
-deployments do require an key, which should be specified as an
-init-parameter for the *Wicket* filter in `web.xml`:
-
-    <?xml version="1.0" encoding="ISO-8859-1"?>
-    <web-app ... >
-
-      ...
-
-      <filter>
-        <filter-name>wicket.app</filter-name>
-        <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
-        <init-param>
-          <param-name>applicationClassName</param-name>
-          <param-value>org.apache.isis.viewer.wicket.viewer.app.IsisWicketApplication</param-value>
-        </init-param>
-        <init-param>
-          <param-name>GOOGLE_MAPS_API_KEY</param-name>
-          <param-value>(key here)</param-value>
-        </init-param>
-      </filter>
-
-    </web-app>
-
-Google Charts
--------------
-
-The googlechart component provides basic charting capabilities. It
-currently supports a single chart type; to render a collection as a pie
-chart:
-
-![](images/410-analyze-summary-piechart.png)
-
-All that is required is for the object to implement the (horribly named)
-PieChartable:
-
-    package org.apache.isis.viewer.wicket.view.googlecharts.applib;
-
-    public interface PieChartable {
-
-      double getPieChartValue();
-      String getPieChartLabel();
-    }
-
-The label is used to point to each sector on the pie chart, the value
-determines the size of each sector relative to the other sectors.
-
-CoolDataSoft Application Services Menu
---------------------------------------
-
-The CoolDataSoft application services menu provides a different
-look-n-feel for the application services menu, using Ajax instead of
-CSS:
-
-![](images/cooldatasoft-appmenu.png)
-
-The implementation is based upon code lifted from the
-[wicket-menu](http://code.google.com/p/wicket-menu/) project, hosted on
-code.google.com. Please note that this code is GPLv3 and so cannot be
-used freely in commercial applications.
-
-Deployment Topics
-=================
-
-> This chapter touches on various topics that should be addressed prior
-> to deployment.
-
-Before you can deploy your application into production there are a
-number of things to be addressed. Most significantly of these is
-persistence, but security is another important topic.
-
-Because the *Wicket Viewer* runs on top of *Apache Isis*, many of the
-deployment tasks are based on the way in which *Apache Isis* tackles
-them.
-
-This chapter briefly outlines the main tasks from a *Wicket Objects*
-perspective. You might, though, want to dig out my book, [Domain Driven
-Design using Naked Objects](http://pragprog.com/titles/dhnako), for more
-in-depth coverage of the *Apache Isis* side-of-things (it covers *Apache
-Isis*' predecessor, *Naked Objects*, but is still broadly applicable).
-
-Running in a WebApp
--------------------
-
-When developing *Apache Isis* applications you can run from either the
-`commandline` project or from the `webapp` project (see ?). If you've
-been using the former, then you'll need to switch to running from the
-latter so that your application can be built as a WAR for deployment.
-Take care to ensure that:
-
--   the classpath dependencies are the same (so that any custom
-    components you're using or have written are picked up)
-
--   that the `isis.properties` config file is the same
-
-Persistence
------------
-
-If you've been using the in-memory object store for development,
-obviously you'll need to switch to a persistent object store before you
-deploy.
-
-Going into the details of that is outside the scope of this guide, but
-it's worth noting that you have a number of options:
-
--   the simplest persistence mechanism (albeit still only really for
-    prototyping) is to use the XML object store. You can specify this in
-    `isis.properties`:
-
-        isis.persistor=xml
-        isis.xmlos.dir=/tmp/xml
-
--   more likely though you'll want to use a relational database. One
-    option is [JPA Objects](http://jpaobjects.sourceforge.net), another
-    sister project to *Apache Isis* (like *Wicket Objects* itself, in
-    fact). There's reasonable coverage in the
-    [DDDuNO](http://pragprog.com/titles/dhnako) book.
-
--   *Apache Isis* also has (will have) a JDBC-based object store, SQL
-    Object Store
-
--   If relational databases aren't your thing, *Apache Isis* also has
-    (will have) a BerkeleyDB Object Store
-
-Security
---------
-
-By default, *Wicket Objects* is configured to use *Apache Isis*' default
-authentication and authorization. This are both file-based, with a
-simple passwords file to define users, and a similar file to define
-authorization. *Apache Isis* does though provide an implementation for
-both that use LDAP. This is discussed in the other *Apache Isis*
-documentation and in Dan Haywood's book. Alternatively, you could always
-write your own implementations to hook into your own security
-infrastructure.
-
-See also ?.
-
-Wicket DEPLOYMENT mode
-----------------------
-
-Finally, you'll also want to switch into Wicket deployment mode (ie for
-production). This is done in the normal way, by modifying *web.xml*:
-
-    <?xml version="1.0" encoding="ISO-8859-1"?>
-    <web-app ... >
-
-      ...
-
-      <filter>
-        <filter-name>wicket.app</filter-name>
-        <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
-        <init-param>
-          <param-name>applicationClassName</param-name>
-          <param-value>org.apache.isis.viewer.wicket.viewer.app.IsisWicketApplication</param-value>
-        </init-param>
-        <init-param>
-          <param-name>configuration</param-name>
-          <param-value>deployment</param-value>
-        </init-param>
-      </filter>
-
-    </web-app>
-
-Doing this also disables *Apache Isis* "exploration" actions (any action
-annotated with @Exploration will no longer be visible).
-
-Example Application
-===================
-
-> This appendix contains (almost) all the code that makes up the example
-> application shown in the screenshots in ?. The purpose in including
-> these listings is just to give you an idea of what it takes to write a
-> *Wicket Objects* application; this isn't a full tutorial on what it
-> all means.
-
-If you're interested in trying out the application, you'll find it at
-<https://wicketobjects.svn.sourceforge.net/svnroot/wicketobjects/trunk/testapp/claims>.
-
-Domain Application (Problem Space / Persisted Objects)
-------------------------------------------------------
-
-Most of the application shown in the screenshots (see ?) requires only
-the domain model. This is made up of three main entities, Employee,
-Claim and ClaimItem. The dependency between employee and claims package
-is acyclic; every Claim has a Claimant and an Approver, and Employee
-implements both the Approver and Claimant interfaces.
-
-### claims package
-
-#### Claim
-
-The Claim class is by far the largest domain class. Below is a listing
-of all the methods; the body of the getters and setters and some of the
-validation methods have been omitted.
-
-    package org.apache.isis.examples.claims.dom.claim;
-
-    import java.util.ArrayList;
-    import java.util.List;
-
-    import org.apache.isis.applib.AbstractDomainObject;
-    import org.apache.isis.applib.annotation.Disabled;
-    import org.apache.isis.applib.annotation.Ignore;
-    import org.apache.isis.applib.annotation.MaxLength;
-    import org.apache.isis.applib.annotation.MemberOrder;
-    import org.apache.isis.applib.annotation.Named;
-    import org.apache.isis.applib.annotation.Optional;
-    import org.apache.isis.applib.value.Date;
-    import org.apache.isis.applib.value.Money;
-    import org.apache.isis.viewer.wicket.applib.CalendarEvent;
-    import org.apache.isis.viewer.wicket.applib.Calendarable;
-
-    public class Claim extends AbstractDomainObject implements Calendarable {
-
-        // {{ Title
-        public String title() {
-            return getStatus() + " - " + getDate();
-        }
-        // }}
-
-        // {{ Lifecycle
-        public void created() {
-            status = "New";
-            date = new Date();
-        }
-        // }}
-
-        // {{ Rush
-        private boolean rush;
-        @MemberOrder(sequence = "1.2")
-        public boolean getRush() { ... }
-        public void setRush(final boolean flag) { ... }
-        // }}
-
-        // {{ Description
-        private String description;
-        @MemberOrder(sequence = "1")
-        public String getDescription() { ... }
-        public void setDescription(String description) { ... }
-        public String validateDescription(final String description) { ... }
-        // }}
-
-        // {{ Date
-        private Date date;
-        @MemberOrder(sequence = "2")
-        public Date getDate() { ... }
-        public void setDate(Date date) { ... }
-        public String disableDate() { ... }
-        // }}
-
-        // {{ Status
-        private String status;
-        @Disabled
-        @MemberOrder(sequence = "3")
-        @MaxLength(5)
-        public String getStatus() { ... }
-        public void setStatus(String status) { ... }
-        // }}
-
-        // {{ Claimant
-        private Claimant claimant;
-        @Disabled
-        @MemberOrder(sequence = "4")
-        public Claimant getClaimant() { ... }
-        public void setClaimant(Claimant claimant) { ... }
-        // }}
-
-        // {{ Approver
-        private Approver approver;
-        @MemberOrder(sequence = "5")
-        @Optional
-        public Approver getApprover() { ... }
-        public void setApprover(Approver approver) { ... }
-        public String disableApprover() { ... }
-        public String validateApprover(final Approver approver) {
-            if (approver == null)
-                return null;
-            return approver == getClaimant() ? "Can't approve own claims" : null;
-        }
-        // }}
-
-        // {{ Items
-        private List<ClaimItem> items = new ArrayList<ClaimItem>();
-        @MemberOrder(sequence = "6")
-        public List<ClaimItem> getItems() { ... }
-        public void addToItems(ClaimItem item) { ... }
-        // }}
-
-        // {{ action: Submit
-        public void submit(Approver approver) { ... }
-        public String disableSubmit() {
-            return getStatus().equals("New") ? null
-                    : "Claim has already been submitted";
-        }
-        public Object default0Submit() {
-            return getClaimant().getApprover();
-        }
-        // }}
-
-        // {{ action: addItem
-        public void addItem(@Named("Days since") int days,
-                @Named("Amount") double amount,
-                @Named("Description") String description) {
-            ClaimItem claimItem = newTransientInstance(ClaimItem.class);
-            Date date = new Date();
-            date = date.add(0, 0, days);
-            claimItem.setDateIncurred(date);
-            claimItem.setDescription(description);
-            claimItem.setAmount(new Money(amount, "USD"));
-            persist(claimItem);
-            addToItems(claimItem);
-        }
-        public String disableAddItem() { ... }
-            return "Submitted".equals(getStatus()) ? "Already submitted" : null;
-        }
-        // }}
-
-        // object-level validation
-        public String validate() { ... }
-    }
-
-Some points worth noting:
-
--   Although Claim is inheriting from *Apache Isis*'
-    AbstractDomainObject class, this isn't mandatory.
-
--   Claim has reference properties of type Claimant and Approver. As
-    we'll see below these are interfaces. References to both interface
-    and classes is supported in *Apache Isis*.
-
--   The Claim uses a Money class, a value type provided by *Apache
-    Isis*. It's also possible to write ones own value types (or indeed
-    use third-party value types such as JodaTime).
-
-#### ClaimItem
-
-A Claim has a collection of ClaimItems. A ClaimItem is somewhat simpler
-than Claim, and doesn't have any particular behavior itself:
-
-    package org.apache.isis.examples.claims.dom.claim;
-
-    import org.apache.isis.applib.AbstractDomainObject;
-    import org.apache.isis.applib.annotation.MemberOrder;
-    import org.apache.isis.applib.value.Date;
-    import org.apache.isis.applib.value.Money;
-
-    public class ClaimItem extends AbstractDomainObject {
-
-        // {{ Title
-        public String title() {
-            return getDescription();
-        }
-        // }}
-
-        // {{ DateIncurred
-        private Date dateIncurred;
-        @MemberOrder(sequence = "1")
-        public Date getDateIncurred() { ... }
-        public void setDateIncurred(Date dateIncurred) { ... }
-        // }}
-
-        // {{ Description
-        private String description;
-        @MemberOrder(sequence = "2")
-        public String getDescription() { ... }
-        public void setDescription(String description) { ... }
-        // }}
-
-        // {{ Amount
-        private Money amount;
-        @MemberOrder(sequence = "3")
-        public Money getAmount() { ... }
-        public void setAmount(Money price) { ... }
-        // }}
-    }
-
-#### Approver and Claimant
-
-The Approver and Claimant interfaces decouple Claim from any classes
-outside the claims package. The Approver interface is, in fact, empty:
-
-    package org.apache.isis.examples.claims.dom.claim;
-
-    public interface Approver {
-
-    }
-
-There's not a lot more to Claimant:
-
-    package org.apache.isis.examples.claims.dom.claim;
-
-    public interface Claimant {
-
-        Approver getApprover();
-
-        String title();
-    }
-
-#### ClaimRepository
-
-The ClaimRepository interface is one of the two domain services (as
-appearing in the menu bar), and is defined as:
-
-    package org.apache.isis.examples.claims.dom.claim;
-
-    import java.util.List;
-
-    import org.apache.isis.applib.annotation.Named;
-    import org.apache.isis.applib.value.Date;
-
-    @Named("Claims")
-    public interface ClaimRepository {
-
-        public List<Claim> allClaims();
-
-        public List<Claim> findClaims(@Named("Description") String description);
-
-        public List<Claim> claimsFor(Claimant claimant);
-
-        public List<Claim> claimsSince(Claimant claimant, Date since);
-
-        public ClaimWizard newClaim(Claimant claimant);
-
-        public List<ClaimantExpenseSummary> analyseClaimantExpenses();
-    }
-
-### employee package
-
-The employee package depends on the claim package in that the Employee
-class implements the Claimant and Approver interfaces. Among other
-things, this allows the actions of the ClaimRepository to be
-"contributed" to the Employee class (appear in a "claims" submenu for
-each Employee).
-
-#### Employee
-
-The Employee class is the other main class in this app:
-
-    package org.apache.isis.examples.claims.dom.employee;
-
-    import org.apache.isis.applib.AbstractDomainObject;
-    import org.apache.isis.applib.annotation.Disabled;
-    import org.apache.isis.applib.annotation.MemberOrder;
-    import org.apache.isis.examples.claims.dom.claim.Approver;
-    import org.apache.isis.examples.claims.dom.claim.Claimant;
-    import org.apache.isis.viewer.wicket.applib.Locatable;
-    import org.apache.isis.viewer.wicket.applib.Location;
-
-    public class Employee extends AbstractDomainObject implements Claimant,
-            Approver, Locatable {
-
-        // {{ Title
-        public String title() {
-            return getName();
-        }
-
-        // }}
-
-        // {{ Icon
-        public String iconName() {
-            return getName().replaceAll(" ", "");
-        }
-        // }}
-
-        // {{ Name
-        private String name;
-        @MemberOrder(sequence = "1")
-        public String getName() { ... }
-        public void setName(String lastName) { ... }
-        // }}
-
-        // {{ Approver
-        private Approver approver;
-        @MemberOrder(sequence = "2")
-        public Approver getApprover() { ... }
-        public void setApprover(Approver approver) { ... }
-        // }}
-
-        // {{ Location
-        private Location location;
-        @Disabled
-        @MemberOrder(sequence = "1")
-        public Location getLocation() { ... }
-        public void setLocation(final Location location) { ... }
-        // }}
-    }
-
-A couple points worth noting:
-
--   The Employee class has an iconName() method. This is used to render
-    Employees with a customized image for each instance.
-
--   Employee also implements Locatable. This is used to render the
-    Employee in the gmap2 (google maps mashup) view (see ?).
-
-#### EmployeeRepository
-
-The EmployeeRepository interface defines the other domain service (on
-the services menu):
-
-    package org.apache.isis.examples.claims.dom.employee;
-
-    import java.util.List;
-
-    import org.apache.isis.applib.annotation.Named;
-
-    @Named("Employees")
-    public interface EmployeeRepository {
-
-        public List<Employee> allEmployees();
-        public List<Employee> findEmployees(@Named("Name") String name);
-    }
-
-Specialized Use Cases
----------------------
-
-Domain objects to support specialized use cases (solution space objects)
-are not persisted; instead their state is serialized into the *Wicket*
-page components.
-
-### ClaimWizard
-
-The ClaimWizard uses an internal `page` field (of type Page enum) to
-determine which page the user is on; from this we determine which
-properties should be visible, and whether the `previous()`, `next()` and
-`finish()` actions are available.
-
-    package org.apache.isis.examples.claims.dom.claim;
-
-    import java.util.Calendar;
-    import java.util.List;
-
-    import org.apache.isis.applib.AbstractDomainObject;
-    import org.apache.isis.applib.annotation.Disabled;
-    import org.apache.isis.applib.annotation.Hidden;
-    import org.apache.isis.applib.annotation.Ignore;
-    import org.apache.isis.applib.annotation.MemberOrder;
-    import org.apache.isis.applib.annotation.NotPersistable;
-    import org.apache.isis.applib.annotation.TypicalLength;
-    import org.apache.isis.applib.clock.Clock;
-    import org.apache.isis.examples.claims.dom.employee.EmployeeRepository;
-    import org.apache.isis.viewer.wicket.applib.WizardPageDescription;
-
-    @NotPersistable
-    public class ClaimWizard extends AbstractDomainObject {
-
-        public enum Page {
-            INTRO("This wizard will take you through the process of creating a claim"),
-            CLAIMANT("Enter the claimant that is making this claim"),
-            APPROVER("By default, the claimant's own approver will approve this claim.  " +
-                     "Update here if another approver will approve this claim."),
-            DESCRIPTION("Update the description if required."),
-            SUMMARY("Confirm all details, or go back and amend if needed");
-
-            private String description;
-            private Page(String description) {
-                this.description = description;
-            }
-
-            public String getDescription() {
-                return description;
-            }
-
-            public boolean hasPrevious() {
-                return ordinal() > 0;
-            }
-            public Page previous() {
-                if (hasPrevious()) {
-                    return values()[ordinal() - 1];
-                } else {
-                    return this;
-                }
-            }
-
-            public boolean hasNext() {
-                return ordinal() < values().length - 1;
-            }
-            public Page next() {
-                if (hasNext()) {
-                    return values()[ordinal() + 1];
-                } else {
-                    return this;
-                }
-            }
-
-            @Ignore
-            public boolean is(Page... pages) {
-                for (Page page : pages) {
-                    if (page == this) {
-                        return true;
-                    }
-                }
-                return false;
-            }
-        }
-
-        // {{ Lifecycle
-        public void created() {
-            setPag

<TRUNCATED>