Adding Addresses
So far we have looked at a very simple naked object. The next step is
to add one or more addresses to a person. Here is how:
package com.briancoyner.naked.addressbook;
. . .
import org.nakedobjects.object.collection.InternalCollection;
public class Person extends AbstractNakedObject {
. . .
private InternalCollection addresses;
public Person() {
. . .
addresses = new InternalCollection(Address.class, this);
}
public InternalCollection getAddresses() {
resolve(addresses);
return addresses;
}
. . .
}
The NakedObjects framework contains an
InternalCollection
object that stores objects of a given type. In our case, we are storing
Address objects. We also must supply the collection with
a parent (the owner), creating a one-to-many relationship.
The "getter" method introduces a new method:
resolve(NakedObject). The resolve method is a
static method on AbstractNakedObject that
ensures that the given object exists and is fully formed and in memory
before it is used. This means that we can construct a
Person and lazy-load
the addresses on the first call to
getAddresses(). We will
talk more about persistent object stores in a bit.

Diagram 4. Person with an address
Here is the Address class:
package com.briancoyner.naked.addressbook;
import org.nakedobjects.object.AbstractNakedObject;
import org.nakedobjects.object.Title;
import org.nakedobjects.object.value.TextString;
public class Address extends AbstractNakedObject {
private final TextString description;
private final TextString street;
private final TextString city;
private final TextString state;
private final TextString zip;
public Address() {
description = new TextString();
street = new TextString();
city = new TextString();
state = new TextString();
zip = new TextString();
}
/**
* Indicate primary location, lake house, etc.
*/
public final TextString getDescription() {
return description;
}
public final TextString getStreet() {
return street;
}
public final TextString getCity() {
return city;
}
public final TextString getState() {
return state;
}
public final TextString getZip() {
return zip;
}
public Title title() {
String title = street.isEmpty() ? "" : street.stringValue();
if (!description.isEmpty()) {
title += (title.length() == 0 ? "(" : " (") +
description.stringValue() + ")";
}
return new Title(title);
}
}

Diagram 5. Our simple address
There is nothing new in the
Address class that we have not
already seen, and testing
this class is simple, too, especially using views. Of course, the
integration between a
Person and multiple addresses is
worthy of more detail.
Adding an Address to a Person
Create a new Address object
Drag and drop the
Address object on a
Person's
"Addresses" field.
You should see the field turn green, indicating
it is okay to drop the object. The framework
takes care of validating if an object can be dropped.
(Hint: look at the
InternalCollection
object.) The field turns red if you cannot drop the object.

Diagram 6. Our person has a home
If you want to see all of the attributes from the
Person view,
simply double-click the "Addresses" field.

Diagram 7. Address expanded
To remove an address, simply right-click on the
Person's
"Addresses" field and select "Remove reference".

Diagram 8. Removing an address
Testing One-to-Many Relationships
We have seen how to write and test simple naked objects. We have
also seen how to associate objects by dragging and dropping. Now let's
look at how we can test this behavior. Here is a simple test:
protected void setUp() throws Exception {
init();
registerClass(Person.class);
// Don't forget to register the class registerClass(Address.class);
}
public void testAddAddressToPerson() {
String viewName = NakedClass.getNakedClass(Person.class).getPluralName();
View person = getClassView(viewName).newInstance();
viewName = NakedClass.getNakedClass(Address.class).getPluralName();
View address = getClassView(viewName).newInstance();
person.drop("Addresses", address.drag());
person.assertFieldContains("Addresses", address);
}
Creating a Runnable Application
So far we have seen how to create and test naked objects. Now let's delve
into creating a Naked Objects application. Here is the code
to launch our address book:
package com.briancoyner.naked.addressbook;
import org.nakedobjects.Exploration;
import org.nakedobjects.object.NakedClassList;
import org.nakedobjects.object.NakedObjectStore;
import org.nakedobjects.object.TransientObjectStore;
public class AddressBookApp extends Exploration {
public void classSet(NakedClassList classes) {
classes.addClass(Person.class);
classes.addClass(Address.class);
}
public static void main(String[] args) {
new AddressBookApp();
}
}
When developing a Naked Objects application, you should extend from
Exploration, which is a template for prototyping. An
Exploration contains numerous default configurations. One
piece that you must supply, though, is the objects to expose. This is done by
implementing the abstract method
classSet(NakedClassList).
This method tells the framework which objects to make available to the users.
Once the application stabilizes, you may move the application's configuration
from the
Exploration object to a configuration file. This
allows for complete customization without have to recompile.
Here is a screen shot showing the classes available to user:

Diagram 9. Classes exposed to the application
To create a new person, right-click on a class and select "New Person..."

Diagram 10. Creating a new person
Object Stores
The framework supports multiple types of object stores. Here is a list of
object stores readily available:
-
XML Object Store
Stores each naked object instance in a separate XML file. You
should only use this when you are dealing with a small number of objects.
The XML files are placed in the current working directory:
~/xml/*.xml.
-
Serialized Object Store
Stores each naked object instance in a separate file, using serialization.
You should only use this when you are dealing with a small number of objects.
This is typically faster than using XML files.
-
SQL Object Store
Uses JDBC to store naked objects to a persistent
data store (MySQL, Oracle, etc.).
-
EJB Object Store
Allows naked objects to use EJBs.
- Transient Object Store
This is the default object store, and all objects are stored
in memory and are lost when the application quits.
To facilitate rapid prototyping, the framework defaults to a transient store.
As the application stabilizes, it is appropriate to plug in a persistent
object store, such as XML or a database. We can change the object store
by overriding the installObjectStore() method in our
AddressBookApp.
Here is how we hook up an XML file-based object store:
protected NakedObjectStore installObjectStore() {
return new XmlObjectStore();
}
The complexity of a Naked Objects application grows when
dealing with more complex persistence capabilities. For more information on
creating a robust, persistence-aware application, consult the Naked Objects
documentation.
Other Goodies
The Naked Objects framework relies heavily on reflection, as we have seen
throughout this article. Don't be scared, because there is plenty
of documentation to get you started. You can start by reading the
online book , which
also contains great chapter on object-oriented programming.
Listed below are a few treasures that you'll uncover from the online book.
Changing the Plural Name
By default, the framework adds an "s" to the classname to create the plural
name. Irregular nouns can be changed by implementing this method:
public static String pluralName();
Here is how we change "Persons" to "People"
public static String pluralName() {
return "People";
}
Ordering Objects
How objects are ordered is specific to how
ClassLoaders parse
.class files. Therefore, we need a way to specify the ordering
of objects on the screen. Luckily,
the solution is easy. Simply add this method signature to your naked object:
public static String fieldOrder();
Here is how we might order our objects:
public static String fieldOrder() {
return "First Name, Last Name, Birthdate, Addresses";
}
Changing Icons
Icons are simple to add to your application. Simply create an
images
directory that contains your images and place it on the
CLASSPATH.
Of course, you will need to follow a few naming conventions. We need two
image files for each object (16 and 32 pixels). The 32-pixel image is
used for the class view and the 16-pixel image is used for an instance view.
For example, our
Person needs the following files:
-
images/Person16.gif
-
images/Person32.gif
Summary
Naked objects provide an interesting way to think about developing software.
In this article, we built and tested a simple application using the open source
Naked Objects framework.
Overall, this framework offers a substantial amount of flexibility and structure when
developing GUI applications, and we barely scratched the surface with what
this framework can do. One of the most powerful features of this framework
is its use of views, which allow us to test our objects and their interactions much
like an end user might use them. Finally, even if you never build a Naked Object system,
hopefully you will start thinking in terms of writing behaviorally complete
objects.
Brian Coyner is coauthor of the Java Extreme Programming Cookbook and a Senior Software Engineer with Object Computing, Inc. in St. Louis, MO.