Table of Contents
Abstract
This chapter provides some further guidance on objects designed to support specialized use cases.
Back in the application walkthrough (see Section 2.8, “Specialized Use Cases”) we saw that Wicket Objects 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.
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:
Similarly, the ClaimExpenseSummary
object
(or rather, a collection of them) hooks into the capabilities of the
googlecharts component (discussed in Section 5.3, “Google Charts”):
You can use any of the Wicket Objects'
built-in Component
s 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 Section A.3, “Custom Views for Specialized Use Cases”).
Wicket Objects also has a small number of
Component
s intended for writing custom
views.
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() { ... } ... }
You can see the result of this annoation in the screenshots of the wizard (see Section 2.8, “Specialized Use Cases”).
In order for this to work, the following line must be added to
Naked Objects' configuration file,
nakedobjects.properties
:
nakedobjects.reflector.facets.include=org.starobjects.wicket.metamodel.facets.WizardPageDescriptionAnnotationFacetFactory
This basically instructs Naked Objects to
capture additional information in its metamodel (specifically, that a
WizardPageDescriptionFacet
is associated to the
property). This then causes a different
Component
to be used to render this property;
specifically, one that renders the value as a large label.
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.
As you can see, the level of support provided by Wicket Objects 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 Naked Objects 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.