Richard Pawson Robert Matthews 2008 Naked Objects Group Ltd.

Permission is granted to make and distribute verbatim copies of this manual provided that the copyright notice and this permission notice are preserved on all copies.

Getting started

The Scimpi framework can be downloaded from the Scimpi project on SourceForge (see http://sourceforge.net/projects/scimpi/). The files are labelled in the format

scimpi-version-type.compression

Where scimpi is the product name and

version
indicates the release version and reflects the maturity and stability of the release
type
is either for-ant, for-maven or source; where the binary versions are ready to deploy or develop with, and the source release can be used to further develop or modify the framework or can be used to build the binary version.
compression
zip or tgz - for uses on Windows or Unix systems respectively.

Once downloaded and exploded a directory named scimpi-version will be placed on your disk, and will contain the following:-

scimpi-0.1
  demo
  docs
  LICENSE.TXT
  README.TXT
  template

Running the demo system

The demo directory contains a number of demo applications and a server to run them on. Within the demo directory run the web server program, on Windows run the batch file:

$ cd scimpi-0.1\demo\
$ webserver.bat

While on Unix/Linux run the shell script:

$ cd scimpi-0.1/demo/
$ ./webserver.sh

Once the server is running open up a browser and use the following URLs to access the demo web applications: http://localhost:8080/catalogue/, http://localhost:8080/cart/ and http://localhost:8080/expenses.

To log on to the web applications use one of the user names sven, dick or bob and the password pass.

When finished use Ctrl-C to terminate the server.

Installing the demos on a web server

An alternative to running the supplied standalone server is to use an existing Servlet enabled web server such a Tomcat. Simply drop the war files from the demo/webapp directory into the deployment directory on the web server (in the case of Tomcat this is the webapp directory). The server should then automatically make the applications available as above.

Building a new web application with Ant

A new web application can be created by making a copy of the template directory and using Ant, or an IDE, to build the war. The following Linux command copies across the complete template directory into a new directory called conference.

$ cp --recursive scimpi-0.1/template/ conference

Once we have changed to the new directory we can use Ant to compile the code and create the war file.

$ cd conference/
$ ant war
Buildfile: build.xml

compile:
    [mkdir] Created dir: /home/rcm/tmp/conference/build
    [mkdir] Created dir: /home/rcm/tmp/conference/build/classes
    [javac] Compiling 8 source files to /home/rcm/tmp/conference/build/classes

war:
      [war] Building war: /home/rcm/tmp/conference/build/scimpi.war

BUILD SUCCESSFUL
Total time: 2 seconds
$

To run the new web application the war file needs to be deployed to a running web server. The following example copies it to a locally installed Tomcat 5.5 server.

$ cp build/scimpi.war ~/usr/apache-tomcat-5.5.23/webapps/.

The web application can now be accessed from a browser using the URL http://localhost:8080/scimpi/.

Once set up the source code for the domain model, in src/, can be replaced or modified, and specific views can be added to webapp/. Rebuild and redeploy through the same process to see the results.

The Ant build configuration uses two useful properties that should be set up: webapp.name, the name of the generated war file and hence the context name of the application, and deploy.dir, the directory that the war file is copied to when the deploy target is used. These can either be changed within the build.xml file, or specified on the command line when running Ant as the example below shows, which will produce a war file called conference.war instead of scimpi.war and will be accessible via the URL http://localhost:8080/conference/ .

$ ant -Dwebapp.name=conference
$ cp build/conference.war ~/usr/apache-tomcat-5.5.23/webapps/.

To get Ant to copy across the war file to the web server ensure the deploy.dir property is correctly set and run ant with the deploy target as the example below shows.

$ ant -Ddeploy.dir=/home/rcm/usr/apache-tomcat-5.5.23/webapps/ deploy

These properties can also be permanently set up by specifying them in the build.xml file.

Building a new web application with Maven

You can use Maven archetypes to quickly set up a Scimpi web application. Run the following command specifying a suitable group and artifact ID. The group ID is typically based on you domain name, while the artifact ID uniquely represents the web application you are creating.

$ mvn org.apache.maven.plugins:maven-archetype-plugin:1.0-alpha-7:create \
  -DarchetypeGroupId=org.scimpi \
  -DarchetypeArtifactId=scimpi-webapp \
  -DarchetypeVersion=0.1-SNAPSHOT \
  -DgroupId=[my group id] \
  -DartifactId=[my artifact id] 

The resulting directory (with the name from the artifact ID) contains a Maven style project for a complete example web application. So assuming that the artifact ID was given as conference then the directory would also be conference.

From within the artifact directory you can build the application by running Maven with

$ mvn install

The newly created target directory contains a war file with the name of the artifact, e.g. conference-1.0-SNAPSHOT.war. This file can then be manually deployed to a suitable web server or Maven can run a web server for you.

$ mvn jetty:run

Once set up the source code for the domain model, in src/main/java/, can be replaced or modified, and specific views can be added to src/main/webapp/. Rebuild and redeploy through the same process to see the results.

Creating a Scimpi web application

When you ran the demos in the previous section (see Link) you where presented with a fully scripted web based application. Scimpi provides some generic template files that give you an application framework to start with. In this section we will look how a scimpi application is created, and specifically how the pages are constructed. The examples here are based on the domain model that provided as part of the template and is provided in the appendix for reference. The first thing to look at is the use of generic views in Scimpi.

Set up an example application as detailed in the previous section. The following example shows the complete create, build and run cycle using Ant and the provided lightweight server.

$ cd scimpi-0.1
$ cp --recursive template example
$ cd example
$ ant deploy -Ddeploy.dir=../demo/webapp/ -Dwebapp.name=example
Buildfile: build.xml

compile:
    [mkdir] Created dir: /home/rcm/tmp/scimpi-0.1/example2/build
    [mkdir] Created dir: /home/rcm/tmp/scimpi-0.1/example2/build/classes
    [javac] Compiling 6 source files to /home/rcm/tmp/scimpi-0.1/example2/build/classes

war:
      [war] Building war: /home/rcm/tmp/scimpi-0.1/example2/build/example.war

deploy:
     [copy] Copying 1 file to /home/rcm/tmp/scimpi-0.1-SNAPSHOT/demo/webapp

BUILD SUCCESSFUL
Total time: 1 second
$ cd ../demo
$ ./webserver.sh
2008-03-17 15:49:16.934::INFO:  Logging to STDERR via org.mortbay.log.StdErrLog
2008-03-17 15:49:16.977::INFO:  jetty-6.1.5
:
:
:

Generic views

Access the main page by entering the http://localhost:8080/example in the address field and pressing the Go button. The opening screen of the browser shows the actions of all the services that the application provides, i.e., the methods defined in the ClaimantRepository and ClaimRepository service classes. As for most web applications this is the welcome page and in this case maps to index.shtml.

Clicking on the links/buttons will invoke the selected method and display a generic view. For example the All Claimants button above generates invokes the allClaimants method on the claimants repository service object, which returns a collection. This displays the list of claimants as shown below. This uses the template generic/collection.shtml to create the page.

Clicking on the select link will use another generic page (generic/object.shtml) to show you detail of the object, while clicking on the edit link will use the template generic/edit.shtml to provide a page containing an HTML form for editing the object. Here you can change the name of the employee.

If we now use the same technique to view all the claims and then open up a specific one using the select link, the claim viewing page (still generic/object.shtml) shows the complete claim including a list of the expense items. Notice that at bottom of the page there is a second link (below edit), this is the action method defined in the Claim class called submit.

Clicking such a link will either invoke the method immediately if it has no parameters or, as in this case, it will open up a generic action form (generic/action.shtml) to allow the user to set the parameters before the method is executed. Below we see the page that we get after pressing the link on the page above. The approver parameter is set to the default value as specified in the domain model.

After pressing the OK button you are returned to the home page as the method return nothing to process. Had the method returned an object then that object would displayed. If you navigate back to the claim you will see that the approver has been set up and the status changed to Submitted.

All the above was achieved through generic views, no HTML or template pages were written. In the next section we will look at how we create our own pages to create a targeted and stylised user interface.

Basic Scimpi pages

If we now create a new page called example.shtml (placed in the example/webapp directory) with the following markup we will be getting Scimpi to run an action and list the results to us. This shows us a number of important things about Scimpi pages. First, all files with the extension shtml are Scimpi files and are processed on the server before being sent to the client. These files are essentially HTML files with addition Scimpi tags that will replaced with dynamic content when processed. Second, all Scimpi tags are of the form <swf:command attributes>.

<html>
<head>
    <link rel="stylesheet" href="style/screen.css" type="text/css"/>
    <title>Claims</title>
</head>

<body>
    <h1>Claims</h1>
    <swf:run-action object="service:claims" method="allClaims" />
    <swf:list type="disc"/>
</body>
</html>

Depending on how you are running Scimpi you may need to rebuild the web application, redeploy it or restart the web server. (Using Ant and the provided web server, as described above, you should run Ant again (to copy the new file across) and restart the web server.)

This example uses two Scimpi tags to interact with Naked Objects and generate some dynamic HTML. The first tag invokes the action allProducts on the service object known as claims, which is the claims repository; the service: prefix indicates the object is a service and claims is the name of the service object as provided by its getId method. The second tag generates an unordered list (OL tag) with a set of list items (within LI tags) from the collection that was returned by the previous tag. The browser shows the following when the example.shtml page is requested.

By replacing tag <swf:list type="disc"/> with <swf:table/> an HTML table will be generated instead of a list.

As well as tags that practically do all the work of generating things likes lists, tables and forms, Scimpi provides tags to allow you to build your own. The next example uses the collection tag in place of table to control the processing of the contained block. This tag will iterate through the collection and for each element will process the contained elements so that the elements title and claimant field is displayed along with a table showing the items field.

    <h1>Claims</h1>
    <swf:run-action object="service:claims" method="allClaims" />
    <swf:collection>
        <div>
            <h3><swf:title icon="off"/>, for <swf:field field="claimant" icon="off"/></h3>
            <swf:table field="items"/>
        </div>
    </swf:collection>

The result of this page are the same three elements as before but the layout and detail have been specified in detail.

Scimpi web applications

Domain model

The only code in a Scimpi is the domain model; there is generally no web application code other than the markup in the pages. Building a domain model is detailed in the manual for the Naked Objects Framework.

In essence a domain model should define classes for each type of object in the system. The classes are written in as standard Java classes that use the getter and setter methods to make the properties of an object available and have a way to inform a container that they have changed their state or still need to load it. The easiest way of creating such classes is to extend AbstractDomainObject object as this provides a simple way notify the container of the requests for dealing with the objects persistence. The following class show a simple but typical domain object that can be used in a Naked Object system. This object represent an employee that has a name and knows it approver.

package org.nakedobject.app.cart;

import org.nakedobjects.applib.AbstractDomainObject;
import org.nakedobjects.applib.annotation.MemberOrder;

public class Employee extends AbstractDomainObject {
    private String name;
    private Employee approver;

    @MemberOrder(sequence="1")
    public String getName() {
        resolve(name);
        return name;
    }
    
    public void setName(String lastName) {
        this.name = lastName;
        objectChanged();
    }

    @MemberOrder(sequence="2")
    public Employee getApprover() {
        resolve(approver);
        return approver;
    }
    
    public void setApprover(Employee approver) {
        this.approver = approver;
        objectChanged();
    }
    
    public String title() {
        return getName();
    }
}

Directory structure

Each Scimpi application builds upon the following directory structure, which is based on the standard layout required by Servlet and JSP based Java web applications.

webapp/
    index.shtml
    login.shtml
    generic/
        action.shtml
        collection.shtml
        edit.shtml
        object.shtml
    images/
        banner.jpg
        bg-button.gif
        Claim.gif
        ClaimItem.gif
        Default.png
        Employee.gif
        logo.png
    style/
        screen.css
        template.shtml
    WEB-INF/
        lib/
        logging.properties
        nakedobjects.properties
        passwords
        web.xml

The file index.shtml is the welcome file for the web application; the welcome file is the file that is served when no files is specified. For example http://localhost:8080/expenses will return the file index.shtml file from expenses webapp directory.

The file login.shtml is a log on page that is used to authenticate the user via Naked Objects.

The images directory is used for both the icons for objects and for images used by the style sheet and templates.

The WEB-INF directory contains all the configuration files.

The generic directory holds default pages for viewing, editing and running actions on objects.

Requested resources

Scimpi processes requests for resources that have the extensions shtml and app specially. All other resources, such images, text files and HTML documents, are assumed to be files and return directly as such. Specially handled request are handled by Scimpi's dispatcher where the resources with the app extension are mapped to Scimpi actions and those with the shtml extension cause the corresponding file to be read in and processed as Scimpi templates containing Scimpi tags that are to be replaced by the processor.

However, when a request is made for a generic page (as _generic.shtml, _generic_edit.shtml and _generic_action.shtml) Scimpi seeks the most suitable file to process the request. The request is based on the object reference held by the RESULT variable. Using this object it first looks for a directory named after the objects class, and if it exists will look for a suitable file. If no such directory exists then a file in the generic directory is used. The file, from either the generic or class named directory, depends on the generic page name. For _generic.shtml a file called objects.shtml or collection.shtml is used depending on whether the referenced object is an object or a collection. For _generic_edit.shtml a file called edit.shtml is used. When the request is _generic_action.shtml Scimpi looks for an shtml file with the same name as requested in the method parameter.

Variables

All web applications are built on HTTP, which is stateless, so Scimpi provides a way maintaining state between requests on your behalf. By asking Scimpi to store values for you, either implicitly or explicitly, your web application can easily refer to objects and other data that were used previously. Without such a capability each request would effectively be the first request and all needed information would have to be encoded within the web page. Every variable in Scimpi is known by its given name and is kept for a set duration, known as its scope. In addition to the variables that are defined by the web application there are others that are automatically provided by the system.

The variable tag allows a variable to be explicitly set up. This tag simply stores the content of the block with the associated name. So the following markup creates a variable called duration and stores the value "1250" within it (note that it is a string, not a number, as it is taken from the HTML page).

<swf:variable name="duration">1250</swf:variable>

Once a variable has been declared it can be used within the HTML, as markup itself or as attribute, by wrapping the name with ${ and }. So now, for example, we can output the value variable in a bold form using the following

<b>${value}</b>

that will result in the following HTML being received by the browser.

<b>1250</b>

Most commonly it is the tags that implicitly set up variables with the results of their actions or with references to objects. The following example shows an action that places its result, a collection of claims, into the claims variable, after which the table tag refers to the collection via the same variable (which is written as ${claims} to show that it is a variable).

<swf:run-action object="service:claims" method="allClaims" result-name="claims"/>
<swf:table collection="${claims}"/>

Note that if you didn't specify a variable for the result to be put in then the default variable RESULT would be used instead. The same applies to the table tag, which would use the variable RESULT to find the claim. This is the same for all other tags the have an attribute for a variable name, or that need to refer to an object or collection.

Scope. In the previous examples the two variables that we declared would only be available while the current page is being prepared and would not exist when the subsequent page is requested. These variable therefore have narrowest scope. From the widest to narrowest the four available scopes are:-

global
exists for the lifetime of the server;
session
exists for the period that the user is logged in;
interaction
spans two requests: the first request prepares a view; and the second is based on data in that first view;
request
exists only for the current request; will not be available during the subsequent request.

To specific a scope when specifying a variable simply add a scope attribute with one of the four scope names.

References

Scimpi provide a mechanism to refer to objects that are held by Naked Objects from within a web page, or as part of a URL. An implementation of ObjectMapping generates a textual string from the object's OID. This can then be used as the object attribute for many of the tags. Most commonly these references are stored in, and used from variables, this is why for tags that produce results you need to specify a variable for the reference to be placed into.

If an object attribute starts with service: Scimpi will find the service object with the identifier as specified after that prefix. The example shows how to run a method on the service identified as Claims, which is the claims repository

<swf:run-action object="service:Claims" method="myRecentClaims" />

Using the RESULT variable. When the object/collection attribute is not specified within a tag that must refer to an object Scimpi uses the reference held by the RESULT variable instead. This special variable is set up when a tag, which produces a results (such as the action tags, collection or link), also has no variable attribute (e.g. result-name or element-name) specified. This allows us to use have code like

<swf:run-action object="service:Claims" method="myRecentClaims" />
<swf:table/>

instead of the more verbose

<swf:run-action object="service:Claims" method="myRecentClaims" result-name="claims" />
<swf:table collection="claims"/>

This special variable is only available during the request and will be replaced by the next tag that produces a result. For example the following will fail on the last line as RESULT will contain the reference to the last element in the collection as set by the collection tag and not the collection as originally set by the run-action tag.

<swf:run-action object="service:claims" method="allClaims" />
<swf:collection>
  <li><swf:title icon="off"/></li>
</swf:collection>
<swf:table/> <!--this line will fail-->

To fix this the run-action should specify a result-name attribute and both the collection and table tags should specify a collection attribute that uses the variable as specified in result-name attribute.

<swf:run-action object="service:claims" method="allClaims" result-name="claims"/>
<swf:collection collection="${claims}">
  <li><swf:title icon="off"/></li>
</swf:collection>
<swf:table collection="${claims}"/>
The alternative fix is to specify an element-name attribute for the collection and use that variable in the object attribute of the title tag.

Page references

As Scimpi has a mechanism for finding the most appropriate page for rendering a view of an object (the generic pages, such as _generic.html) there are some details about page references that you should be aware of. Essentially, because the page that was requested might not be the page that was served, the relative location of referenced files might not be as first expected.

To make this concrete we will use a simple example. Consider a claims page generated in response to a request likehttp://localhost:8080/expenses/Claim/object.shtml?claim=... that contains a list of expenses whose hyper-links are defined as _generic.html so that the most suitable page will be used. When such a link is clicked on the URL used by the browser would, therefore, be something like http://localhost:8080/expenses/Claim/_generic.shtml?_result=.... Now as the page that is returned would be generated from the most suitable template it would use the file object.shtml from the ExpenseItem directory rather than the Claim directory. However, the generated page when displayed by the browser will still have a base URL of http://localhost:8080/expenses/Claim/. An image tag on that page, such as <img src="person.png"/>, will, therefore, result in a request from the browser of http://localhost:8080/expenses/Claim/person.png. This obviously will not find the file as it is ExpenseItem directory; so a URL intended to be relative to the current page ends up being relative to the page in the previous request.

To get round such a problem the URL specified should use the system variables _context and _directory to set up the full path. So returning to our above example img tag should be changed to

<img src="${_context}${_directory}person.png"/>

so that web application context name and the directory that the template file is actually in are appended with the image name creating a path that absolutely identifies the resource as the resultant HTML shows.

<img src="/expenses/Claim/person.png"/>

There are four such system variables that relate to URLs:

_base
the complete URL for the current resource;
_context
the web application context name, used to distinguish one web application from another and forming the first part of the pathname in the URL;
_directory
the directory containing the current resource;
_this
the filename of the current resource.

Such issues can also arise when creating links that are intended to show a particular object or run an action. As you not only have to get the location correct but also pass over the reference to the object to be shown and, for actions, pass over the method name, all by creating a long URL it is simpler to use one of the Scimpi link tags that takes care of all this for you. So instead of an a tag like

<a href="_generic_edit.shtml?_result=${item}">edit</a>

use the Scimpi edit-link tag as follows.

<swf:edit-link object="${item}">edit</swf:edit-link></a>

Other link tags are object-link, action-link and new-action-link.

Configuration

There are a number of configuration files for each web application and these are placed in the WEB-INF directory. This section describes the common settings that are used. Most configuration aspects affect the Naked Objects framework and are detailed in its manual.

Services. The service objects that Naked Objects instantiates and makes available to your web application are listed in the nakedobjects.properties file with the services properties. The example segment below will make the classes org.example.services.ClaimantRepository and org.example.services.ClaimRepository available.

nakedobjects.services.prefix=org.example.services
nakedobjects.services=ClaimantRepository, ClaimRepository

Fixtures. Fixtures are run the first time that your web application is started and can be used to prime the object store with an initial set of domain objects such as reference or demo objects. Fixtures are specified in the nakedobjects.properties file with the fixtures properties. The following snippet loads up the org.nakedobject.app.cart.fixtures.ClaimsFixture class on the first startup.

nakedobjects.fixtures=org.nakedobject.app.cart.fixtures.ClaimsFixture

XML object store. The template code provided is designed to run with the XML object store; other persistence layers can be used and are outlined in the Naked Objects manual. As this is a file based store the place it expects to find its files must remain both consistence and in existence. The problem comes down to the servlet container and the root path it gives its web application. Typically the only reliable system independent place is the web applications extraction directory but this is replaced each time a web application is redeployed. As there are no other guaranteed cross-platform directories we can default to it is best to specify where the object store should be placed. The location of the XML object store files are specified in the nakedobjects.properties file with the xmlos.dir property. The following snippet places the files in the tmp/example-data directory, which on Tomcat will be relative the startup directory (a better option is to use a rooted path that absolutely identifies where the files are to be placed).

nakedobjects.xmlos.dir=tmp/example-data

Passwords. The default authentication for the template code is through a password file, Naked Object's most basic authorisation implementation; other authentication methods can be used and are outlined in the Naked Objects manual. The passwords file contains a set of user names and passwords that Scimpi and Naked Objects will allow user to log in with. The example below defines a set of Naked Objects users; that is the users are users of the system and not just Scimpi.

# username:password
sven:pass
dick:pass
bob:pass

If the users are defined by the web application rather than through Naked Objects then it becomes the domain model's responsibility to identify and authenticate the users. To allow for this the password file must contain a system user, and Scimpi must automatically connect as that user. This is done via servlet initialisation parameters that are set in the web.xml configuration file, which the servlet container processes. In the servlet block two init-parameter blocks are added to specify the user name and password. The following snippet shows the servlet block once the two parameters have been added.

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.nakedobjects.webapp.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <init-param>
        <param-name>username</param-name>
        <param-value>webapp</param-value>
    </init-param>
    <init-param>
        <param-name>password</param-name>
        <param-value>pass</param-value>
    </init-param>
</servlet>

The user name and password specified for auto-login should then be added to the password file so that the system user can be authenticated. This can be done by adding the following line to the password file.

webapp:pass

Scimpi tags

Each tag is used in the form

<swf:tag-name attribute-name="attribute value" />

for an empty tag, while a tag containing other tags will be of the form

<swf:tag-name attribute-name="attribute value">
    enclosed text or tags
</swf:tag-name>

Scimpi markup, being XML embedded in XHTML pages, is case sensitive. All tag and attribute names must be lower case.

Page layout

Scimpi pages can import chunks of markup from other files as well use a template to form the basis of a page. The import tag simply reads in a specified file for inclusion at the point of the tag. If the file has an shtml extension that file is also processed. This is useful for including common elements in file such as a header or footer.

The template tag similarly reads in a specified file, but while it is reading it in it looks for a content tag and suspends reading when it finds one. The remainder of current file is then read in and processed before the reading of the template file is completed. So given the two files, my-template.html and my-page.shtml, as listed here

<hmtl>
<head>
  <title>Scimpi Page</title>
</head>

<body>
  <swf:content />
</body>
</html>
<swf:template  file="my-template.shtml" />
<h1>My new page</h1>

the resultant markup will be as follows,

<hmtl>
<head>
  <title>Scimpi Page</title>
</head>

<body>
  <h1>My new page</h1>
</body>
</html>

where the content tag has been replaced with content of the original file (but without the template tag).

Another tool for minimising page size is move common markup into separate files and import those block into the multiple files when needed using the import tag. When using this technique it is useful to indicate in the segments file name that it is in an import; we place an underscore at beginning of such files.

Form views

Scimpi has a number of tags that allow objects, and parts of objects, to displayed. The whole object can be displayed using the short-form and long-form tags; the difference between these two is the short version does not display properties that are collections while long version shows these as tables.

Linking properties. Each reference property can be marked so it provides a link to a page that shows more details about that object. For each property that requires a link add a link tag to the short-form/long-form block specifying the name of the property in the name attribute. By default the page that you will be linked to is the most appropriate one for that type of object; alternatively you can specify a view attribute so the links is to a specific page. The following example ensures that the approver field is hyper-linked and the user will be taken the generic object view page.

<swf:long-form>
    <swf:link name="approver"/>
</swf:long-form>

Specifying object properties to include. By default all properties are shown for these tags, but an explicit list of properties can be specified using the include and exclude tags. When a include tag is added all other properties that do not also have an include tag will be excluded. The following example shows how the claimant property can be removed by using a exclude tag.

<swf:long-form>
    <swf:exclude name="claimant"/>
</swf:long-form>

Fields and labels. In addition to displaying the complete or partial object using the form tags a property's label and content can also be accessed directly allowing an object's view to be constructed manually. The label tag gets the field's proper name while the field tag get the field's contents. Both take the name of the field in the field attribute. The following example creates a simple colon separated view of the current object, showing the claimant, description and status labels and field contents.

<div class="form">
    <div><swf:label field="claimant"/>: <swf:field field="claimant"/></div>
    <div><swf:label field="description"/>: <swf:field field="description"/></div>
    <div><swf:label field="status"/>: <swf:field field="status"/></div>
</div>

Lists and tables

List and table views of collections can be most simply created using the list and table tags. These tags can be used to create a view from either an explicit collection or a collection property within an object. If the field attribute is specified then a collection is deemed to be an object's property otherwise it is an explicit collection. When no collection or object attribute is specified the RESULT variable is used.

The list tag creates a numbered list of the form

<ol><li>Submitted - Meeting with client</li>
<li>Submitted - Meeting in city office</li>
<li>New - Meeting at clients</li>
</ol>

but it can also show as bulleted form (as a ul block) by specifying the type attribute.

The table tag creates a table with a row for each element and a column for each association/value property; collection properties are not shown. By default each column has a header that shows the name of the property, but this can be prevented via the heading attribute.

Linking collection elements. Within list and tables we can provide links to pages that show or manipulate the individual items. By adding a link attribute Scimpi will create a hyper-link (an a tag) to the specified page that includes a reference to the current element. This Scimpi markup

<swf:list type="circle" link="_generic.shtml"/>

therefore generates the following HTML markup instead of the first element in the example above.

<li><a href="_generic.shtml?_result=Porg.nakedobject.app.cart.Claim@fdzsbkg0">
Submitted - Meeting with client</a></li>

The parameter name can be specified using the element-name attribute and, as can seen in the example, this defaults to RESULT.

As tables can show the element, as a row, and other objects, as the columns, it is possible to make the objects link to other pages instead of the row. For each column that should be linked a link tag should be added to the table block and the name attribute set to identify the property to provide the link on. The following example creates a link that lets us view the approver in detail.

<swf:table>
    <swf:link name="approver" view="_generic.shtml"/>
</swf:table>

Specifying the columns in a table. The columns displayed in a table can be controlled by adding include and exclude tag to the table block. By using an exclude tag you indicate that a named property is not be shown thereby reducing the number of columns shown as needed. The include tag indicates that you want to show a named property but not any others thereby allowing the exact number of columns specified. The following example excludes the approver and claimant columns so all the rest still show.

<swf:table heading="no" >
   <swf:exclude name="approver"/>
   <swf:exclude name="claimant"/>
</swf:table>

Collections

While the list and table tags provide a quick and simple way of displaying a collection the collection tag provides the mechanism for building up your own view of a collection element by element. The collection tag takes the same attributes for determining the collection as the list and table tags do. The content between the opening and closing tags is processed for each element of the collection. By default the element's reference is put in the RESULT variable, but this can be changed by adding the element-name attribute. The following example shows a collection tag used within a ul tag to create a series of li elements from the current collection object.

<ul><swf:collection>
    <li><swf:title icon="off"/></li>
</swf:collection></ul>
<ol>
    <li>Submitted - Meeting with client</li>
    <li>Submitted - Meeting in city office</li>
    <li>New - Meeting at clients</li>
</ol>

Element type

The element-type tag can be used to get hold of the type of elements a collection holds. If the system is configured with internationalization then the name will be localized.

Titles

An object's title can be displayed using the title tag. The default version displays an icon image as well as the title text, but this can be prevented by setting the icon attribute to no. The following example displays an icon and title text as a level three heading.

<h3><swf:title/></h3>
<h3><img class="title-icon" src="/example/images/Default.png" />Submitted - 
Meeting with client</h3>

Edit forms

Using the edit tag we can display an HTML form for an object. Any disabled or uneditable properties are simply shown by title while the fields to be edited have the most suitable input field created for them.

Reference fields won't work particularly well in the default tag as there is no other available references to set the field to unless that field has some options or a default defined for it in the model. To make it possible for the user to select a suitable reference to set the field with the selector tag can be used to create a drop-down or options list with suitable choices. This tag can either take a collection or an object and a method that results in a collection and will create an object selection widget. The following example shows how the default approver field can be replaced by a list showing all the claimants as provided by the claimants repository.

<swf:edit>
    <swf:selector field="approver" object="service:claimants" method="allClaimants" type="list"/>
</swf:edit>

If we want to the give the user some control over what is selectable, instead of providing a long and too comprehensive list, we can first prompt the user for criteria that can be used when calling a method that has one or more parameters. Scimpi then creates a form that collected the parameters for that method and after the user presses the search button it will create a selection list based on the method call using those parameters. In the following example the selector tag uses the findClaimants method that takes a String parameter. This results in a single field form that invokes the search method and generates a drop-down list (the default type of selector).

<swf:edit>
    <swf:selector field="approver" object="service:claimants" method="findClaimants"/>
</swf:edit>

If more control over the entry field is required then you can define your own field within a form-field tag. This tag simply replaces the auto-generated field with contained block of markup leaving you with the responsibility of setting it up correctly. This typically means you need to determine the options and ensure that the HTML field has a name that matches the property in the object. The following simplified example creates a drop-down list for the name property; the field attribute of the Scimpi tag and the name attribute of the HTML tag must have the same field name.

<swf:form-field field="name">
    <select name="name">
         <option>best</option>
         <option>average</option>
         <option>worst</option>
    </select>
</swf:form-field>

Controlling the visible fields. Like the object views, the properties shown in the edit form can be controlled using the include and exclude tags. The exclude tag simply removes the named field from the complete set of fields, while a set of include tags defines the complete list of fields to be shown. It is important to remember that the object cannot be saved if all the required properties are not set, or if entries are invalid. This can happen when you exclude such fields unless they have a default value. The following example removes the status and claimant fields from the property set.

<swf:edit>
    <swf:exclude name="status"/>
    <swf:exclude name="claimant"/>
</swf:edit>

Actions

Two special tags provide access to all actions for an object and for all the actions on all the service objects. These tags - methods and services - are typically used for generic pages but can be used on specific pages as a way of minimising the amount of tags required to make a number of your actions available. The methods tag will, except on service objects, also provide an edit option that will open up an edit view. By default all the actions are displayed, either as buttons or links to action pages, but the list can be controlled using the include and exclude tags. The following example will provide access to all the methods from the claimant service except the allClaimants one; there will be no edit option also as it is for a service.

<swf:methods object="service:claimants" >
    <swf:exclude name="allClaimants"/>
</swf:methods>

Common attributes. All the other action tags target a specific object to run a specific action on. These are specified by the object and method attributes respectively. Also the name of the variable that will hold the results can be specified with the result-name attribute, with its scope being set via the scope attribute. For all the tags that will forward you to another page after executing can specify that page when: the result is returned (the view attribute); when no result is returned (void); and when an error (such as a validation failure) occurs (error).

In-line actions. Actions can be run as they are come across while processing a page using the run-action tag. These are typically used when details are needed for other tags in the page. The following example shows how a table of all the claims can be displayed by running the allClaims method on the claims repository.

<swf:run-action object="service:claims" method="allClaims"/>
<swf:table/>

Immediate actions. Some actions can be invoked by the user immediately while others require input from the user before they can be run (these are covered next). Web users expect links to take them to another page while buttons will make a change to the state of the system, so Scimpi provides the action-link and action-button tags to allow the appropriate rendering. Both tags operate in the same way but while one is rendered as a hyper-link the other is a form with no fields, just a button. These tags are typically used with methods that do not have parameters as the following example shows.

<swf:action-link object="service:claimants" method="allClaimants"/>

If a method has parameters and they either have a suitable default value or you have access to suitable value through the page then these tags can also be used for these parameterised methods. If the tag specifies a method with parameters it will expect a parameter tag to specify the parameter's value or will use the default value as specified by the model. If neither of these exists then an error will be generated. The following example creates a form with a button that runs the one parameter submit method where the parameter value is that held by the approver variable.

<swf:action-button object="${claim}" method="submit">
    <swf:parameter number="1" value="${approver}"/>
</swf:action-button>

Prompted actions. When an action requires input from the user the action-form tag should be used to create an HTML form with fields for the parameters. Each parameter is displayed as an appropriate entry field and, by default, all the parameters made visible but this can be controlled using the include and exclude tags. Using include you can build up a list of all the parameters you want to be shown (any parameter then not specified through an include is excluded by default), while by using exclude, specific parameters can be removed from the full list. Only parameters that are optional or have a default value should, however, be excluded as otherwise the action will not be able to be run.

By default the most suitable HTML field is used for each particular parameter but it is possible to provide your own fields when needed. The simplest option is to use the selector tag to provide a selection option - as a drop-down, list or set of radio buttons - to the user instead of the default field. The use of the selector tag is discussed in the previous section (see Link). The alternative is to create your own input field using the form-field tag, again this is described above (see Link). The following example shows the selector tag in use to provide a list of possible approvers.

<swf:action-form method="submit" view="_generic.shtml" void="../index.shtml">
    <swf:selector field="param0" object="service:claimants" method="allClaimants"/>
</swf:action-form>

Framework development

This chapter looks at setting up a development environment (Eclipse) to allow development of the Scimpi framework itself. This is the setup for developers of the framework, developers who are writing extensions to the framework.

Getting the Source and Setting up Eclipse

Scimpi development requires:-

Java 5 Naked Objects 3.0.2 Subversion Maven 2 Eclipse (3.2 or 3.3) - another IDE can be used but is not covered here.

Check out the code from the Source Forge repository us the following command

$ svn co https://scimpi.svn.sourceforge.net/svnroot/scimpi/trunk scimpi_DEV

This creates the directory scimpi_DEV with the following (approximate) contents

cart-demo
expenses-demo
LICENSE.TXT
pom.xml
README.TXT
release
scimpi-dispatcher
scimpi-docs
scimpi-server
scimpi-servlet
webapp-template

Before importing the code into the IDE we need to set up the IDE's project structure. Through Maven run the following commands to set up projects (creates .project, .classpath and other Eclipse property files) and set the repository variable (M2_REPO) within Eclipse.

$ mvn eclipse:eclipse
$ mvn -Declipse.workspace=. eclipse:add-maven-repo

Using the import wizard in Eclipse (File/Import menu) select Existing Projects into Workspace and press the Next button. Within the second tab of the wizard specify the directory as checked out above. Once a list has appeared in the Projects field, as seen below, press the finish button.

Running the Demos

Eclipse's Web Standard Tools (WST) and J2EE Standard Tools (JST) provides tooling for building and running web applications including running a Servlet Container from within Eclipse.

Before running such a web application is necessary to ensure that related projects are added to the server's classpath. This is done via the properties for the web application project under the J2EE Module Dependencies section. In there tick the projects that are needed to run Scimpi, at the time of writing these are scimpi-dispatcher and scimpi-servlet.

To run the examples with Eclipse right-click on the cart-demo project and from the Run As menu select the Run on Server option. The dialog that pops up should be correctly set for the local server. (If there are no servers set up they can be added via the preferences, see the section Server/Installed Runtimes and use the Add button to add a server that you have installed on your machine.) Press Next to move to the second page where you add all the other projects as web applications, or Finish to run the server.

How Scimpi works

The Scimpi framework is used to build Java web applications that run in a servlet container such Tomcat or JRun. Using the Naked Objects framework to access a Java domain model Scimpi can be used to create dynamic web pages that access and manipulate that domain model.

Pages are generated by Scimpi by processing template files (with the extension shtml) that contain special tags that instruct the framework to do particular things (all other files with extensions other than shtml are passed to the browser unchanged). The template files are essentially HTML files interspersed with Scimpi tags that are processed and will typically generate some HTML code to replace the tag in the file that is passed to browser. Like most other web applications the template files, and all other browser requestable resources are placed in the webapp directory.

webapp/
    generic/
        action.shtml
        collection.shtml
        edit.shtml
        object.shtml
    images/
        Default.png
        logo.png
    style/
        screen.css
        template.shtml
    WEB-INF/
        nakedobjects.properties
        passwords
        web.xml
    index.shtml

Loading Naked Objects. When the servlet container loads the Scimpi based web application it starts off by loading up Naked Objects and introspecting the domain model. This is controlled by the nakedobjects.properties file. A basic configuration, like the one shown below, will list the service objects that Naked Objects should make available and the fixtures that should be run the first time the web application is started to populate the object store with the initial set of domain objects.

nakedobjects.services.prefix=org.nakedobject.app.cart.services
nakedobjects.services=ClaimantRepository, ClaimRepository

nakedobjects.fixtures.prefix=org.nakedobject.app.cart.fixtures
nakedobjects.fixtures=ClaimsFixture

Default security. Naked Objects is user orientated, that is it expects the interactions with it to be on behalf of a user. To this end the system must authorise a user before anything can be done, this is the same principle as a database engine. The passwords file contains a set of user names and passwords for Naked Object's most basic authorisation implementation. The example below defines a set of actual users for applications that will be based on Naked Objects users, and a system user (webapp) for applications that either have no concepts of users or provide for it within the domain model.

# username:password
sven:pass
dick:pass
bob:pass

webapp:pass

web application configuration. The web application configuration file for a Scimpi application is rather simple and varies little from application to application. The change that needs to be made only applies to applications that use Naked Objects users, for which the to parameters for the dispatcher servlet should be removed so that web application does not log-in automatically when a session is started.

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" 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">
    <display-name>example</display-name>

    <welcome-file-list>
        <welcome-file>index.shtml</welcome-file>
    </welcome-file-list>

    <listener>
        <listener-class>org.nakedobjects.webapp.servlet.SystemInitializer</listener-class>
    </listener>

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.nakedobjects.webapp.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>username</param-name>
            <param-value>webapp</param-value>
        </init-param>
        <init-param>
            <param-name>password</param-name>
            <param-value>pass</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.shtml</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.app</url-pattern>
    </servlet-mapping>
</web-app>

Controllers. Scimpi provides a single dispatcher servlet and a set of controllers. Other controllers can be added if needed.

The built-in controllers are:-

logon
processes a username and password parameter and requests a Naked Object Session from the underlying framework.
logout
End the Naked Object Session from the underlying framework, and clears the request context.
debug
creates a debug page displaying internal details and state of the Scimpi and Naked Objects frameworks.
edit
process a set of fields from an HTML form for a specified object and sets those fields of that object held by Naked Objects.
action
process a set of fields from an HTML form for a specified method on a domain object or service object and invokes that method.

Objects

The domain objects handled by Naked Objects are wrapped in adapters that allow those domain objects to be processed transparently by the NOF with the domain objects be redefined to deal with technical aspects of enterprise systems such as security and persistence. Each domain object is given an object identifier (OID) so the it can be referred to across machines. The Scimpi framework works with this mechanism by mapping HTML friendly identifiers to the OIDs.

Tag reference

This section outlines each of the available tags showing what attributes they support and gives examples of their use.

action-button

Creates an empty form with just a button that invokes the specified method when pressed, forwarding the results to the specified view.

action-button attributes

Name Description Required Default
object Identifier for a specific object, or a service identifier prefixed by "service:". no RESULT
method Method on the object or service to invoke when the user presses the submit button. yes
view View to be forwarded to after submission and an object is returned. no _generic.html
void View to be forwarded to after submission and no object is returned. no _generic.html
result-name Name of variable to store the resultant object. no RESULT
scope How long the variable should be kept for. no request
title Title for the submission button. no the action's name

The action-button element can contain one or more parameter elements.

The following example creates an HTML form with no visible fields and a button that invokes the myRecentClaims method on the claims services when the button is pressed.

<swf:action-button object="service:Claims" method="myRecentClaims" />

See also: Link, Link and Link

action-form

Creates a form with entry fields for each of the action's parameters. When the user presses the submit button the action will be invoked, if all the parameter are valid, and the result forwarded to the specified page. If the parameters are invalid control will be forwarded to the specified error page.

If the specified action is not visible or usable no form will be displayed.

action-form attributes

Name Description Required Default
object Identifier for a specific object, or a service identifier prefixed by "service:". no RESULT
method Method on the object or service to invoke when the user has provided the necessary parameters in the generated form and has pressed the submit button. yes
view View to be forwarded to after submission and an object is returned. no _generic.html
void View to be forwarded to after submission and no object is returned. no _generic.html
error View to be forwarded to after validation failure prevents the action from being invoked. no _generic.html
result-name Name of variable to store the resultant object. no RESULT
scope How long the results variable should be kept for. no request
title Title for the submission button. no "OK"
legend Title for the generated form. no the action's name

The action-form element can contain one or more of the following elements

The following example creates an HTML form that will provide fields for each of the parameters of the createNewClaim method on the claims service. When the submit button is pressed the method will be invoked with the provided fields and the generic form will be used (as no view attribute was specified) to display the result.

<swf:action-form object="service:Claims" method="createNewClaim" />

See also: Link, Link and Link

action-link

Creates a hyper-link that will run the specified method, when the user clicks the link, and will forward the result to the specified view. This tag should only be used for actions that do not change the state of the system as hyper-links are for accessing information not processing data.

action-link attributes

Name Description Required Default
object Identifier for a specific object, or a service identifier prefixed by "service:". no RESULT
method Method on the object or service to invoke when the user clicks the link. yes
view View to be forwarded to after the method has be executed. no the current page
result-name Name of variable to store the resultant object. no RESULT
scope How long the variable should be kept for. no request
confirm To be implemented - not in use yet! no

The action-link element can contain one or more parameter elements

The following example creates a hyper-link of the text "Show All Recent Claims", and will execute the method myRecentClaims on the claims service when the user clicks on it.

<swf:action-link object="service:Claims" method="myRecentClaims">Show All Recent Claims</swf:action-link>

See also: Link, Link and Link

action-name

Provides the name of the specified action on an object or service. This will be name derived from the method or a proper name added to the method via the programming model. Additionally, if the system is set to internationalized the name and descriptions then the returned name will be the localized version.

action-name attributes

Name Description Required Default
object Identifier for a specific object, or a service identifier prefixed by "service:". yes
method Method on the object or service to find the name for. yes

The following example finds the name for the createNewExpenseItem method on the object reference by the claim variable.

<swf:action-name object="${claim}" method="createNewExpenseItem" />

collection

The collection element iterates over a collection outputting the contents of the contained block for each element in the collection.

collection attributes

Name Description Required Default
collection Identifier for a specific collection. If the field attribute is set then the collection will be ignored. no RESULT
object Identifier for a specific object. no RESULT
field Name of the field to get the collection from within the specified object. no
element-name The name of the variable to assign the rows object ID to when the row is selected. no RESULT

The collection element can contain one or more of the following

  • text
  • HTML elements
  • scimpi elements

The following example creates an HTML table by creating a row for each element in the collection. The collection that is being used is from the items field in the claim object as referenced by the claim variable. The current element is stored in the variable entry.

<table>
  <swf:collection object="${claim}" field="items" element-name="item">
    <tr>
      <td><swf:field object="${item}" field="date" /></td>
      <td<swf:field object="${item}" field="description" ="180" /></td>
      <td><swf:field object="${item}" field="amout" /></td>
    </tr>
  </swf:collection>
<table>

See also: Link, Link and Link

content

The content element marks the point within a template file (see Link) where the generated content will be placed when it is produced. This element is only processed when a template element is being processed, and should only occur with a template file.

debug

Inserts debug details into the page.

debug attributes

Name Description Required Default
object Identifier of object to display no
variable Name of variable no
value Literal value no
list list the variables, parameters or mappings. no

The following example displays all the variables held by the context for the request, interaction, session and also globally.

<swf:debug list="variables" />

See also: Link and Link

diagnostics

Displays some basic diagnostic information, such as the URI and set variables, when debug flag is set. To set the debug flag append &debug=on to a URL, to turn off append &debug=off.

See also: Link and Link

edit

Creates a form with a set of fields for the properties of an object and a button that updates the object with the entered values.

edit attributes

Name Description Required Default
object Identifier for a specific object. no RESULT
view View to be forwarded to after submission. no _generic.html
error View to be forwarded to if any field does not validate. no the current page
title Title for the submission button. no Save
legend Title for the generated form. no
result-name Name of variable to store the edited object. no RESULT
scope How long the variable should be kept for. no request

The edit element can contain one or more of the following elements

The following example creates a simple edit form for a claimant that does not include the normal approver field.

<swf:edit object="${claimant}" view="my-claims.html">
    <swf:exclude field="normalApprover" />
</swf:edit>

edit-link

Creates a hyper-link to a specified object edit page with the specified object embedded in the URL.

edit-link attributes

Name Description Required Default
object Identity of the object to be passed on to the view. no RESULT
view View to be forwarded to. no _generic_edit.html
param-name Name of parameter to pass the object identifier across as. no RESULT

The edit-link element can contain one or more of the following elements

  • text
  • HTML elements

The following example creates a hyper-link to the page edit-me.html, passing across the identifier for the current object as it does so.

<swf:edit-link view="edit-me.html">Edit claimant</swf:object-link>

See also: Link and Link

element-type

Retrieves the type of element that a collection holds.

element-type attributes

Name Description Required Default
collection Identifier for a specific collection. If the field attribute is set then the collection will be ignored. no RESULT
object Identifier for a specific object. no RESULT
field Name of the field to get the collection from within the specified object. no

The following example gets the type of element that the claimant's items collection holds.

<swf:element-type object="${claimant}" field="items"/>

exclude

Marks a field so that it will not be displayed when displaying a form or table etc.

exclude attributes

Name Description Required Default
name Name of the field to be excluded yes

The exclude element can be placed within following elements

The following example would produce a form that shows all the properties except for the contact from the current object.

<swf:short-form>
  <swf:exclude name="contact"/>
</swf:short-form>

See also: Link and Link

feedback

Displays both collected warnings and messages

See also: Link and Link

field

Retrieves the title of the field within a specified object.

field attributes

Name Description Required Default
object Identifier for a specific object. no RESULT
field Name of the field to be displayed. yes
icon If icon is set to "true", "yes" or "on" an icon will also be displayed as well as the text. If set to "false", "no" or "off" no Icon will be shown. no yes
truncate Limit the text to a specified number of characters. If set to 0 then no truncation occurs. no 0

See also: Link

form-field

Adds the enclosed block alongside the field in an edit or action form.

field attributes

Name Description Required Default
field Name of the field/parameter to be placed with. yes

The following example adds in an HTML select widget (a drop down) that has the three options: alpha, beta and gamma. When the user selects one of the options from the drop-down the grade property will be set with that value.

<swf:edit object="${claimant}">
    <swf:form-field field="grade">
         <select name="grade">
              <option>alpha</option>
              <option>beta</option>
              <option>gamma</option>
         </select>           
    <swf:form-field/>
</swf:edit>

See also: Link

import

Inserts the contents of the specified file.

import attributes

Name Description Required Default
file Name of file to read in yes

The following example will load in the file header.html.

<swf:import file="header.html" />

See also: Link

include

Marks a field so that it will be included when displaying a form or table etc. When a field is included all other fields not also explicitly included will be excluded.

include attributes

Name Description Required Default
name Name of the field to be included yes

The include element can be placed within following elements

The following example would produce a form that only shows the contact and date properties from the current object.

<swf:short-form>
  <swf:include name="contact"/>
  <swf:include name="date"/>
</swf:short-form>

See also: Link and Link

initialize

Conditionally sets up a variable when the current RESULT state is set and matches the specified type. If the RESULT state is not set or the type is not the one specified then the variable is not changed/set.

If the RESULT state is not set or the type is not the one specified then and the a variable already exists for the specified name, but with a different scope, then that value is copied across to a variable with the specified scope.

initialize attributes

Name Description Required Default
name Name of variable to initialize yes
scope How long the variable should be kept for no request
type The class name of the type of object that should be used to initialize the variable. This is used to check that RESULT reference is of the correct type. yes

The following will set up the claim variable for the session if the RESULT is a claim object. If the RESULT is not a claim object then the variable will not be set.

<swf:initialize name="claim" scope="session" type="org.scimpi.example.Claim" />

See also: Link

label

Retrieves the name and description of the field within a specified object, and creates an HTML span element containing the name and a title (rendered as a tool tip) from the description.

label attributes

Name Description Required Default
object Identifier for a specific object. no RESULT
field Name of the field to be display the label for. yes

See also: Link

link

Marks a field so that it is hyper-linked when displaying a form or table.

link attributes

Name Description Required Default
name Name of the field to be hyper-linked yes
view The page to forward to no the current page
reference-name Name of the variable to set up with this field's reference no RESULT

The link element can be placed within following elements

  • table
  • short-form
  • edit

See also: Link and Link

list

Creates an list of an object's collection with the collection's object's title displayed in a list.

list attributes

Name Description Required Default
object Identifier for a specific collection, an object that contains a collection, or a service identifier prefixed by "service:". no RESULT
field Name of the field within an object that will provide a collection. yes
type Bullet type - disc, circle or square. If omitted the list will be a number list (HTML OL tag) otherwise a the bullet type is used (HTML UL tag). no disc
link View to forward to if the line is selected. The row is only given a hyper-link if this attribute was specified. no
element-name The name of the variable to assign the row's object ID to when the row is selected. no RESULT
scope How long the linked variable should be kept for. no request

See also: Link, Link and Link

logon

Creates an logon form prompting for username and password. Form passes control to the logon action, which will attempt to authenticate the user through Naked Objects.

logon attributes

Name Description Required Default
legend Title for form no
title Title used for the submit button. no Log in
view View to be forwarded to once the user has logged on. no
errors View to be forwarded to if the log in fails. By default returns to the same view. no

See also: Link

long-form

As for short-form, except that collections are displayed (as in-line tables)

messages

Displays collected messages

See also: Link and Link

methods

Lists all of the methods for a specified object, where each one is displayed as hyper-link, if it is a zero parameter method, or an action button if it has one or more parameters.

methods attributes

Name Description Required Default
object Identifier for a specific object, or a service identifier prefixed by "service:". no RESULT

The methods element can contain one or more of the following elements

new-action-link

Creates a hyper-link to a specified action page with the specified object and method embedded in the URL.

object-link attributes

Name Description Required Default
object Identity of the object to be passed on to the view. no RESULT
method The method to be executed by the forwarded view. yes
view View to be forwarded to. no _generic.html
param-name Name of parameter to pass the object identifier across as. no RESULT

The object-link element can contain one or more of the following elements

  • text
  • HTML elements

The following example creates a hyper-link to the page exit.shtml, passing across the identifier for the claimant object as it does so.

<swf:object-link object="${claimant}" view="edit.shtml">View claimant</swf:object-link>

See also: Link

object-link

Creates a hyper-link to a specified object viewing page with the specified object embedded in the URL.

object-link attributes

Name Description Required Default
object Identity of the object to be passed on to the view. no RESULT
view View to be forwarded to. no _generic.html
param-name Name of parameter to pass the object identifier across as. no RESULT

The object-link element can contain one or more of the following elements

  • text
  • HTML elements

The following example creates a hyper-link to the page exit.shtml, passing across the identifier for the claimant object as it does so.

<swf:object-link object="${claimant}" view="edit.shtml">View claimant</swf:object-link>

See also: Link and Link

page-title

Sets the variable title from the given body. This variable is typically used by page templates to set up the title element in the head. During the remainder of the request the variable can be accessed via ${title}.

The page-title element can contain one or more of the following elements

  • Text
  • Scimpi tags

The example below causes the title to be set with the text "Claim " and the date of the claim referenced by the claim variable.

<swf:page-title>Claim <swf:field object="${claim}" field="dateCreated" /></swf:page-title>

While this tag process the contained elements it also includes any text and HTML tags. This means that white space and line will appear in your title. Always place the variable start and end tags on the same line and only add spaces and new lines within the title where they are actually needed.

See also: Link

parameter

The parameter element specifies a parameter value or reference to be used when invoking an action method.

parameter attributes

Name Description Required Default
number The parameter number (1 through number-of-parameters). no
value The value for the parameter yes

The parameter element can be placed within following elements

The following example sets up the first parameter to the reference held by the claimant variable when the recentClaims method is invoked.

<swf:run-action object="service:Claims" method="recentClaims" />
    <swf:parameter value="${claimant}" />
</swf:run-action>

run-action

Runs the specified action on an object or service.

Where no parameter elements are specified the default values for that parameter will be used.

run-action attributes

Name Description Required Default
object Identifier for a specific object, or a service identifier prefixed by "service:". no RESULT
method Method on the object or service to invoke when this tag is processed. yes
result-name Name of variable to store the resultant object. no RESULT
scope How long the variable should be kept for no request

The run-action element can contain one or more of the following elements

The following example invokes the myRecentClaims method on the claims service and places the result into the RESULT variable.

<swf:run-action object="service:Claims" method="myRecentClaims" />

See also: Link, Link and Link

scope

Changes the scope on a variable, for example can upgrade a request based variable to session scope.

variable attributes

Name Description Required Default
name Name of file to read in yes
scope How long the variable should be kept for no request

The following example assigns the dateCreated property to the date variable, which will be accessible for the remainder of the request. Within the page the variable can be accessed via ${date}.

See also: Link and Link

services

Lists all of the methods for all of the service objects, where each one is displayed as hyper-link, if it is a zero parameter method, or an action button if it has one or more parameters.

The services element can contain one or more of the following elements

selector

Creates a selection widget within an action form or object edit widget. This allows the user to select a reference object for a specified field. In addition to simply providing an option list the selector can also prompt the user for properties used to build the selection list.

selector attributes

Name Description Required Default
field Name of the field or parameter number (param1, param2 etc) to add the selection list for. no
collection Identifier of collection to build the list of options from. If method is specified then collection will be ignored. no RESULT
object Identifier of object to run the search method on. no RESULT
method Search method to run on the specified object. no
id This attribute is passed to the HTML form element. no
class This attribute is passed to the HTML form element. no selector
type Type of selection widget to create: radio; list; or dropdown no dropdown
size Size of list before it must scroll no 5
error View to be forwarded to when the search fails. no _generic.html
title Title for the submission button. no "Search"
legend Title for the generated search form. no the action's name

The radio-list element can be placed within following elements

The following example will make the normal approver field a drop down list that is populated with the elements of the collection returned from the allClaimants method.

<swf:edit object="${claimant}">
    <swf:selector field="normalApprover" object="service:claimants" method="allClaimants"/>
</swf:edit>

See also: Link

short-form

Creates a view of an object with its fields laid out in two columns showing the label and value. Fields that are collections are not displayed in this version.

short-form attributes

Name Description Required Default
object Identifier for a specific object. no RESULT
title Title to be passed through to the HTML table. no
odd-row HTML class to give each odd row of the form; used by CSS to decorated the odd rows. no odd-row
even-row HTML class to give each even row of the form; used by CSS to decorated the even rows. no even-row
link View to forward to when the hyper-linked row is selected. If no link attribute is specified then the rows are not hyper-linked. no

The short-form element can contain one or more of the following elements

See also: Link

specification

Displays details about the object including the class name and names and types of its fields.

selector attributes

Name Description Required Default
always Set to yes if the specification details are to be always shown no no

See also: Link and Link

table

Creates a table view of a collection with the collection's fields used to determine the columns.

table attributes

Name Description Required Default
collection Identifier for a specific collection. If the field attribute is set then the collection will be ignored. no RESULT
object Identifier for a specific object. no RESULT
field Name of the field to get the collection from within the specified object. no
link View to forward to if the line is selected. The row is only given a hyper-link if the this attribute is specified. no
element-name The name of the variable to assign the row's object ID to when the row is selected. no RESULT
scope How long the linked variable should be kept for. no request
heading Determines if column headers should be displayed. no yes

The table element can contain one or more of the following elements

See also: Link, Link and Link

template

The template element causes the specified file to be read in before the rest of the current file is processed. The rest of the current file is then inserted at the point where the content element (see Link) appears within the imported file.

import attributes

Name Description Required Default
file Name of file to read in yes

See also: Link

title

Retrieves the title of the specified object.

title attributes

Name Description Required Default
object Identifier for a specific object, or a service identifier prefixed by "service:". no RESULT
icon If icon is set to "true", "yes" or "on" an icon will also be displayed as well as the text. If set to "false", "no" or "off" no Icon will be shown. no yes

The following example generates the title for the claimant object, without an image.

<swf:title object="${claimant}" icon="no"/>

unless

Processes the contained block when the specified condition is not met.

One of set, field-editable, field-set, empty, or field-empty should be specified, but no more than one.

unless attributes

Name Description Required Default
set If this attribute is specified but evaluates an empty string then the block will be processed; if non-empty the block is skipped. no
empty If the collection referenced by this attribute contains any elements then the body of this block will not be processed no
object Identifier for a specific object when specifying one of the field- attributes. no _result
field-editable Name of the field within the specified object that should not be editable. no
field-set Name of boolean field within the object to check; the block is processed if the boolean value is false. no
field-empty If the field of the specified object is empty - has no reference or the collection has no elements - this block will not be processed. no

The unless element can contain one or more of the following elements

  • Text
  • HTML tags
  • Scimpi tags

The following example uses the unless element to show a message when no claim exits.

<swf:unless set="${claim}">
    <p>No claim selected</p>
</swf:unless>

See also: Link

user

Manages the login process (into the underlying Naked Objects system rather than within the domain model) by providing either a log in or log out link and showing the current user.

user attributes

Name Description Required Default
login-view View to be forwarded to when the user clicks the logon link. no login.shtml
logout-view View to be forwarded to when the user logs out via the log out link. no logout.shtml

The following example will provide a hyper-links to the default login.shtml page when no user is logged in, and to the home page, index.shtml, for logging out.

<swf:user logout-view="index.shtml" />

See also: Link

variable

The variable element assigns the content of the element to a variable held on the server.

variable attributes

Name Description Required Default
name Name of file to read in yes
scope How long the variable should be kept for no request

The variable element can contain one or more of the following elements

  • Text
  • HTML tags
  • Scimpi tags

The following example assigns the dateCreated property to the date variable, which will be accessible for the remainder of the request. Within the page the variable can be accessed via ${date}.

<swf:variable name="date">
  <swf:field object="${claim}" field="dateCreated" />
</swf:variable>

While this tag processes the contained elements it also includes any text or HTML tags. The text may includes white space and line feeds so care is needed if the variable is to be used in textual context as these characters will be displayed also. To avoid this problem place the variable start and end tags on the same line and only add spaces and new lines where they will be needed when the variable is used.

This is not, however, an issue when the variable is used to reference an object as Scimpi will remove any leading and trailing spaces from the variable first.

See also: Link, Link and Link

warnings

Displays collected warnings

See also: Link and Link

when

Processes the contained block when the specified condition is meet.

One of set, field-editable, field-set, empty, or field-empty should be specified, but no more than one.

when attributes

Name Description Required Default
set If this attribute is specified but evaluates to a non-empty string then the block will be processed; if empty the block is skipped. no
empty If the collection referenced by this attribute contains any elements then the body of this block will be processed. no
object Identifier for a specific object when specifying one of the field- attributes. no _result
field-editable Name of the field within the specified object that should be editable. no
field-set Name of boolean field within the object to check; the block is processed if the boolean value is true. no
field-empty If the field of the specified object is empty - has no reference or the collection has no elements - this block will be processed. no

The when element can contain one or more of the following elements

  • Text
  • HTML tags
  • Scimpi tags

The following example uses the when element to show a title and the claim only when the claim exits.

<swf:when set="${claim}">
    <h2>Claim</h2>
    <swf:short-form object="${claim}"/>
</swf:when>

See also: Link

Example code

Domain objects

Employee

An employee has a name and knows who it approver is.

package org.nakedobject.app.cart;

import org.nakedobjects.applib.AbstractDomainObject;
import org.nakedobjects.applib.annotation.MemberOrder;

public class Employee extends AbstractDomainObject {
    private String name;
    private Employee approver;

    @MemberOrder(sequence="1")
    public String getName() {
        resolve(name);
        return name;
    }
    
    public void setName(String lastName) {
        this.name = lastName;
        objectChanged();
    }

    @MemberOrder(sequence="2")
    public Employee getApprover() {
        resolve(approver);
        return approver;
    }
    
    public void setApprover(Employee approver) {
        this.approver = approver;
        objectChanged();
    }
    
    public String title() {
        return getName();
    }
}

Claim

The main domain class, Claim is for a specific employee and contains a number of expenses (ClaimItem) that are being claimed.

package org.nakedobject.app.cart;

import java.util.ArrayList;
import java.util.List;

import org.nakedobjects.applib.AbstractDomainObject;
import org.nakedobjects.applib.annotation.Disabled;
import org.nakedobjects.applib.annotation.MemberOrder;
import org.nakedobjects.applib.annotation.Named;


public class Claim extends AbstractDomainObject {
    private Employee claimant;
    private Employee approver;
    private String description;
    private String status;
    private List<ClaimItem> items = new ArrayList<ClaimItem>();

    public void created() {
        status = "New";
    }

    @MemberOrder(sequence = "4")
    public String getDescription() {
        resolve(description);
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
        objectChanged();
    }

    @Disabled
    @MemberOrder(sequence = "1")
    public String getStatus() {
        resolve(status);
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
        objectChanged();
    }

    @Disabled
    @MemberOrder(sequence = "2")
    public Employee getClaimant() {
        resolve(claimant);
        return claimant;
    }

    public void setClaimant(Employee claimant) {
        this.claimant = claimant;
        objectChanged();
    }

    @Disabled
    @MemberOrder(sequence = "3")
    public Employee getApprover() {
        resolve(approver);
        return approver;
    }

    public void setApprover(Employee approver) {
        this.approver = approver;
        objectChanged();
    }

    @MemberOrder(sequence = "5")
    public List<ClaimItem> getItems() {
        return items;
    }

    public void addToItems(ClaimItem item) {
        items.add(item);
    }

    public void submit(@Named("Approver") Employee approver) {
        setStatus("Submitted");
        setApprover(approver);
    }

    public String disableSubmit() {
        return getStatus().equals("New") ? null : "Claim has already been submitted";
    }

    public Object[] defaultSubmit() {
        return new Object[] { getClaimant().getApprover() };
    }
    
    public String title() {
        return getStatus() + " - " + getDescription();
    }
}

ClaimItem

The ClaimItem represent an expense incurred on a specific day.

package org.nakedobject.app.cart;

import org.nakedobjects.applib.AbstractDomainObject;
import org.nakedobjects.applib.annotation.MemberOrder;
import org.nakedobjects.applib.value.Date;
import org.nakedobjects.applib.value.Money;


public class ClaimItem extends AbstractDomainObject {
    private Date dateIncurred;
    private String description;
    private Money amount;

    @MemberOrder(sequence="1")
    public Date getDateIncurred() {
        resolve(dateIncurred);
        return dateIncurred;
    }
    
    public void setDateIncurred(Date dateIncurred) {
        this.dateIncurred = dateIncurred;
        objectChanged();
    }
    
    @MemberOrder(sequence="2")
    public String getDescription() {
        resolve(description);
        return description;
    }
    
    public void setDescription(String description) {
        this.description = description;
        objectChanged();
    }
    
    @MemberOrder(sequence="3")
    public Money getAmount() {
        resolve(amount);
        return amount;
    }

    public void setAmount(Money price) {
        this.amount = price;
        objectChanged();
    }

    public String title() {
        return getDescription();
    }
}

Services

Claim repository

package org.nakedobject.app.cart.services;

import java.util.List;

import org.nakedobject.app.cart.Claim;
import org.nakedobject.app.cart.Employee;
import org.nakedobjects.applib.AbstractFactoryAndRepository;
import org.nakedobjects.applib.annotation.Named;


public class ClaimRepository extends AbstractFactoryAndRepository {

    public String getId() {
        return "claims";
    }

    public List<Claim> allClaims() {
        return allInstances(Claim.class, false);
    }

    public List<Claim> findClaims(@Named("Description") String description) {
        return allMatches(Claim.class, description, false);
    }
    
    public List<Claim> claimsFor(@Named("Claimant") Employee claimant) {
        Claim pattern = newTransientInstance(Claim.class);
        pattern.setStatus(null);
        pattern.setClaimant(claimant);
        return allMatches(Claim.class, pattern, false);
    }
}

Claimant repository

The claimant repository allows the user and the DOM to find employee objects

package org.nakedobject.app.cart.services;

import java.util.List;

import org.nakedobject.app.cart.Employee;
import org.nakedobjects.applib.AbstractFactoryAndRepository;
import org.nakedobjects.applib.annotation.Named;


public class ClaimantRepository extends AbstractFactoryAndRepository {

    public String getId() {
        return "claimants";
    }

    public List<Employee> allClaimants() {
        return allInstances(Employee.class, false);
    }

    public List<Employee> findClaimants(@Named("Name") String name) {
        return allMatches(Employee.class, name, false);
    }
}
p

Fixture

This fixture class is used to initialise the system with some demonstration data.

package org.nakedobject.app.cart.fixtures;

import org.nakedobject.app.cart.Claim;
import org.nakedobject.app.cart.ClaimItem;
import org.nakedobject.app.cart.Employee;
import org.nakedobjects.applib.fixtures.AbstractFixture;
import org.nakedobjects.applib.value.Date;
import org.nakedobjects.applib.value.Money;
import org.nakedobjects.nof.reflect.java.value.DateAdapter;


public class ClaimsFixture extends AbstractFixture {
    private final DateAdapter dateAdapter = new DateAdapter();

    @Override
    public void install() {
        Employee fred = createCustomer("Fred Smith", null);
        Employee tom = createCustomer("Tom Brown", fred);
        createCustomer("Sam Jones", fred);

        Claim claim = createClaim(tom, "-2w", "Meeting with client");
        addItem(claim, "-2w -2d", 38.50, "Lunch with client");
        addItem(claim, "-2w -2d", 16.50, "Euston - Mayfair (return)");
        
        claim = createClaim(tom, "-2w 3d", "Meeting in city office");
        addItem(claim, "-2w 2d", 18.00, "Car parking");
        addItem(claim, "-2w 2d", 26.50, "Reading - London (return)");

        claim = createClaim(fred, "-2w", "Meeting at clients");
        addItem(claim, "-2w", 18.00, "Car parking");
        addItem(claim, "-2w", 26.50, "Reading - London (return)");

    }
    
    private Employee createCustomer(String name, Employee approver) {
        Employee claimant;
        claimant = newTransientInstance(Employee.class);
        claimant.setName(name);
        claimant.setApprover(approver);
        makePersistent(claimant);
        return claimant;
    }

    private Claim createClaim(Employee claimant, String date, String description) {
        Claim claim = newTransientInstance(Claim.class);
        claim.setClaimant(claimant);
        claim.setDescription(description);
        makePersistent(claim);
        return claim;
    }

    private void addItem(Claim claim, String date, double amount, String description) {
        ClaimItem claimItem = newTransientInstance(ClaimItem.class);
        claimItem.setDateIncurred(date(date));
        claimItem.setDescription(description);
        claimItem.setAmount(new Money(amount, "USD"));
        makePersistent(claimItem);
        claim.addToItems(claimItem);
    }
    
    private Date date(String date) {
        dateAdapter.parseTextEntry(date);
        return (Date) dateAdapter.getObject();
    }

}