Skip to content

Domain Model Classes

Stoyan Rachev edited this page Aug 26, 2012 · 1 revision

Overview

The domain model classes represent entities from our problem domain. Domain model classes in Todor are Todo items and documents. Todo items have an id, text, status, priority, creation and last update dates. Documents are just collections of Todo items of particular users, and they also track the last time the collection was saved to the backend.

The model classes in Todor are shared between the client and the server. Being able to use the same domain model on the client and the server is a major advantage of GWT over other frameworks for creating rich internet applications, as it eliminates the redundant code and additional complexity from expressing and maintaining the same domain model more than once, potentially even using different programming languages.

This capability is not completely granted, however, as GWT model classes are subject to various requirements coming from:

  • being able to compile the model to JavaScript for use on the client
  • being able to serialize model objects for use in RPC client / server communication
  • being able to persist model objects via JDO

Due to the above, one should follow certain guidelines in order to gain this capability. This is explained in more details in the following sections.

See:

Client Side Code

The target language of any GWT application client side is ultimately JavaScript. Therefore, any classes to be used on the client have to follow the guidelines and restrictions outlined in Coding Basics - Compatibility with the Java Language and Libraries. However, since domain model classes are usually just simple POJOs, these guidelines are usually very easy to follow. The model classes in Todor are just normal POJOs with fields, constructors, and getter / setter methods.

Serialization

The model classes in Todor are used also to transfer data to and from the server via RPC calls. The DocumentService interface and its asynchronous counterpart DocumentServiceAsync have methods for loading and saving entire Document objects.

@RemoteServiceRelativePath("document")
public interface DocumentService extends RemoteService {
    Document loadDocument();
    Document saveDocument(Document document) throws IllegalArgumentException;
}

In order for this to be possible, model classes have to be serializable in the GWT sense of this term, as explained in Serializable Types, which means that:

  • They implement the Serializable interface.
  • All their instance fields are themselves serializable.
  • They have a default (zero argument) constructor.

See:

JDO Persistence

Finally, the model classes are used also on the server side to persist data via Java Data Objects (JDO). In order for this to be possible, model classes have to fulfill certain requirements and are annotated with JDO annotations which tell JDO how to store and recreate instances of these classes, as explained in Defining Data Classes with JDO:

  • The model classes themselves are annotated with @PersistenceCapable.
  • All persistent fields are annotated with @Persistent.
  • Primary key fields are annotated with @PrimaryKey.
  • All fields are of supported types, i.e. either of one of the core types supported by the datastore, a collection or an array of values of such a type, or an instance or collection of instances of another @PersistenceCapable class.
  • Primary key fields follow one of the four strategies explained in Creating, Getting and Deleting Data in JDO- Keys.
  • Entity relationships, such as one-to-one, one-to-many are expressed appropriately as explained in Entity Relationships in JDO.

The last two points deserve special attention as they are perhaps the most difficult to handle. In Todor, there is a one-to-many owned relationsip from the Document to the Item entity, i.e. one document contains multiple items. In the Document class, this relationship is represented just by a List of Item instances:

    @Persistent(defaultFetchGroup = "true")
    private List<Item> items;

The Item class is much more interesting. In JDO terms, this class is an entity group child as instances of this class should be retrievable together with their parent Document instance. Therefore, it has to use either the Key or the Key as Encoded String strategy for its key field. However, the first strategy is not appropriate as JDO Key instances can't be used on the client. Therefore, only the Key as Encoded String strategy can be used in this particular case, which results in the following code in the Item class:

    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    @Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
    private String key;
    @Persistent
    @Extension(vendorName = "datanucleus", key = "gae.pk-name", value = "true")
    private String id;

Here, the key field serves as a server-side composite key which is based both on the id of the document and the id of the item within the document. This key is not used on the client, but nevertheless transported to the client and back to ensure that Item instances have the same representation on both sides.

Clone this wiki locally