Building a Naked Objects application with Maven

Creating new applications using Maven archetypes

Using Maven archetype plugin we can generate a new Naked Objects application very quickly. These are multi-moduled projects with separate sections for the domain code, fixtures, web interfaces and so on.

One option is to create the archetype from the commandline. Note that if you are using Eclipse and have installed the m2eclipse plugin then it provides a dialog to create the project from an archetype; this is discussed below.

TODO: update the listing below, it is out of date. The archetype to use is called 'org.nakedobjects:application-archetype'.

[rcm@localhost ~]$ mvn archetype:generate -DarchetypeCatalog=http://nakedobjects.org
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'archetype'.
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Default Project
[INFO]    task-segment: [archetype:generate] (aggregator-style)
[INFO] ------------------------------------------------------------------------
[INFO] Preparing archetype:generate
[INFO] No goals needed for project - skipping
[INFO] Setting property: classpath.resource.loader.class => 'org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader'.
[INFO] Setting property: velocimacro.messages.on => 'false'.
[INFO] Setting property: resource.loader => 'classpath'.
[INFO] Setting property: resource.manager.logwhenfound => 'false'.
[INFO] [archetype:generate]
[INFO] Generating project in Interactive mode
[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)
Choose archetype:
1: local -> nakedobjects-application (Naked Objects Application (Archetype))
2: local -> nakedobjects-icons (Naked Objects Icons (Archetype))
3: local -> htmlviewer-war (Naked Objects WAR (Archetype))
4: local -> hibernate-support (Hibernate Support (Archetype))
5: local -> remoting-support (Naked Objects Remoting Support (Archetype))
Choose a number:  (1/2/3/4/5): 1

To create a project from an archetype you must specify a groupId and artifactId, a version and a Java package.

After choosing the archetype number and pressing enter you are prompted for the project's details. The groupId is an identifier representing your company/group; ours would typically be "org.nakedobjects" for the domain followed by a name for the group of products. The artifactId identifies the projects that we are creating. The version indicates how mature the project is, and should be left as the default, e.g. 1.0-SNAPSHOT. Finally, the package is the base package name used for all Java files. After these have been entered you are prompted to confirm by entering Y, as shown below.

Be wary of using invalid names. The groupId should be alphanumeric with dots to separate the words. The artifactId should also be alphanumeric, with '-' (hyphens) to separate the words. The package name should be a valid Java package name, i.e. should have no spaces or dashes. Maven does little to check these things.

Define value for groupId: : org.example
Define value for artifactId: : expenses
Define value for version:  1.0-SNAPSHOT: : 
Define value for package: : org.example.expenses
Confirm properties configuration:
groupId: org.example
artifactId: expenses
version: 1.0-SNAPSHOT
package: org.example.expenses
 Y: : y
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1 minute 13 seconds
[INFO] Finished at: Thu Oct 02 20:42:50 BST 2008
[INFO] Final Memory: 13M/247M
[INFO] ------------------------------------------------------------------------

This will create a new directory with the name of the artifactId. So in this example this is expenses as shown below.

expenses
|-- pom.xml
|-- dom
|   |-- pom.xml
|   `-- src
|-- commandline
|   |-- config
|   |-- ide
|   |-- pom.xml
|   `-- src
|-- fixture
|   |-- pom.xml
|   `-- src
|-- service
|   |-- pom.xml
|   `-- src
`-- webapp
    |-- pom.xml
    `-- src

Building a Naked Objects application

Once an archetype is created it can be built using Maven and run. Build using the install goal as shown here.

[rcm@localhost expenses]$ mvn clean install
[INFO] Scanning for projects...
[INFO] Reactor build order: 
[INFO]   Naked Object Application
[INFO]   Domain Model
[INFO]   Services
[INFO]   Fixtures
[INFO]   Exploration
[INFO] ------------------------------------------------------------------------
[INFO] Building Naked Object Application
[INFO]    task-segment: [clean, install]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean]
[INFO] [site:attach-descriptor]
[INFO] [install:install]
[INFO] Installing /home/rcm/tmp/bearingpoint/expenses/pom.xml to /home/rcm/.m2/repository/org/example/expenses/1.0-SNAPSHOT/expenses-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] Building Domain Model
[INFO]    task-segment: [clean, install]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean]
[INFO] Deleting directory /home/rcm/tmp/bearingpoint/expenses/dom/target
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Compiling 7 source files to /home/rcm/tmp/bearingpoint/expenses/dom/target/classes
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
:
:
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] No sources to compile
[INFO] [surefire:test]
[INFO] No tests to run.
[INFO] [jar:jar]
[INFO] Building jar: /home/rcm/tmp/bearingpoint/expenses/exploration/target/expenses.jar
[INFO] [assembly:attached {execution: default}]
[INFO] Reading assembly descriptor: src/main/assembly/descriptor.xml
[INFO] Processing DependencySet (output=lib)
[INFO] Copying files to /home/rcm/tmp/bearingpoint/expenses/exploration/target/expenses-exploration-1.0-SNAPSHOT-prototype.dir
[WARNING] Assembly file: /home/rcm/tmp/bearingpoint/expenses/exploration/target/expenses-exploration-1.0-SNAPSHOT-prototype.dir is not a regular file (it may be a directory). It cannot be attached to the project build for installation or deployment.
[INFO] [install:install]
[INFO] Installing /home/rcm/tmp/bearingpoint/expenses/exploration/target/expenses.jar to /home/rcm/.m2/repository/org/example/expenses-exploration/1.0-SNAPSHOT/expenses-exploration-1.0-SNAPSHOT.jar
[INFO] 
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] ------------------------------------------------------------------------
[INFO] Naked Object Application .............................. SUCCESS [6.087s]
[INFO] Domain Model .......................................... SUCCESS [8.711s]
[INFO] Services .............................................. SUCCESS [2.432s]
[INFO] Fixtures .............................................. SUCCESS [2.283s]
[INFO] Commandline ........................................... SUCCESS [10.774s]
[INFO] ------------------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 31 seconds
[INFO] Finished at: Tue Mar 03 11:59:50 GMT 2009
[INFO] Final Memory: 40M/495M
[INFO] ------------------------------------------------------------------------
[rcm@localhost expenses]$ 

Once the project is built the results can be found in the exploration/target directory, which contains both a zipped distribution (in this example expenses-exploration-1.0-SNAPSHOT-prototype.zip) and an expanded distribution (again for this example, expenses-exploration-1.0-SNAPSHOT). Using the contained script files the application can be run from the command line.

exploration
|-- config
|-- ide
|-- pom.xml
|-- src
`-- target
    |-- archive-tmp
    |-- classes
    |-- expenses-exploration-1.0-SNAPSHOT-prototype.dir
    |   `-- expenses-exploration-1.0-SNAPSHOT
    |       |-- config
    |       |-- images
    |       |-- expenses.jar
    |       |-- nakedobjects.bat
    |       |-- nakedobjects.sh
    |       |-- lib
    |-- expenses-exploration-1.0-SNAPSHOT-prototype.zip
    |-- expenses.jar
    `-- maven-archiver

Using Eclipse for development

There are two approaches for using Eclipse in development.

The recommended approach is to use the Eclipse's Maven plug-in, m2eclipse, obtainable from http://m2eclipse.sonatype.org/. This then allows the Maven projects to be imported directly using File > Import > Maven Projects.

TODO: would be good to have some screenshots of using m2eclipse to import projects here.

In fact, you can use m2eclipse to create the project from the archetype in a single go:

TODO: would be good to have a screenshot of using m2eclipse to generate project using archetype here.

Alternatively you can use Maven's Eclipse plug-in to generate .project and .classpath files. These can then be imported into Eclipse using File > Import > Existing Projects. The remainder of this section discusses this alternative approach; to reiterate the m2eclipse approach is more straightforward and generally preferred.

[rcm@localhost ~]$ cd expenses/
[rcm@localhost expenses]$ mvn eclipse:eclipse
[INFO] Scanning for projects...
[INFO] Reactor build order: 
[INFO]   Naked Object Application
[INFO]   Domain Model
[INFO]   Fixtures
[INFO]   Services
[INFO]   Exploration
[INFO]   Hibernate Object Store
[INFO]   Web App
[INFO]   Client Distribution
[INFO]   Server Distribution
[INFO] Searching repository for plugin with prefix: 'eclipse'.
[INFO] ------------------------------------------------------------------------
[INFO] Building Naked Object Application
[INFO]    task-segment: [eclipse:eclipse]
[INFO] ------------------------------------------------------------------------
[INFO] Preparing eclipse:eclipse
:
:
:
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1 minute 22 seconds
[INFO] Finished at: Thu Oct 02 20:44:41 BST 2008
[INFO] Final Memory: 32M/247M
[INFO] ------------------------------------------------------------------------

This downloads all the required libraries and creates .project and .classpath files for Eclipse to use. After this is complete we can start up Eclipse and import the projects.

[rcm@localhost expenses]$ eclipse -data .

The workspace starts off empty as this is a new project. First we need to import the modules using the File/Import... menu. On the first page of this dialog select the Existing Project into Workspace option.

After selecting the same directory that we are running in, then you select all the modules in the list as Eclipse projects to import.

All the libraries are referenced using a the variable M2_REPO, so this needs to be set up in the Classpath variables in the main preferences. In the Classpath Variable tab press the New... button.

Enter the name M2_REPO and find the path to .m2/repository.

Now to run the application select Run/Run Configuration... on the commandline project and browse for the class org.nakedobjects.runtime.NakedObjects. With that selected press the Run button.

After a short while the login dialog should appear. Logon with a valid user name and password, like sven and pass.

When the application has finished starting up you should the services on the DnD user interface.