Chapter 3. Writing Domains Object in Groovy

Table of Contents

3.1. (Optional) Superclass
3.2. Properties and Collections
3.3. Title & Icon
3.4. Creating and Persisting Objects
3.5. Callbacks
3.6. Annotations
3.7. Supporting Methods

Abstract

Naked Objects uses convention over configuration and annotations to build the metamodel of the domain objects. This chapter explains what those conventions look like, and where annotations should be applied, when developing domain objects in Groovy.

Naked Objects allows validation and other business constraints to expressed either declaratively (using annotations) and/or imperatively (using supporting methods). For a given class member (property, collection or action) we can specify whether the member:

  1. is visible, and if so, is it

  2. is usable, and if modified, whether the proposed change

  3. is valid

Or, slightly more pithily, can you see it, can you use it, can you do it.

Any public methods that don't represent properties or collections are interpreted as being actions. These are surfaced in the UI (as menu items or buttons) to provide arbitrary business behaviour (this is what makes Naked Objects applications more than a simple CRUD framework).

There are also a number of reserved method names that are used either as rendering hints or to define lifecycle callbacks.

Collectively these conventions and annotations define the Naked Objects Programming Model. This chapter should give you a good flavour of what it's like to writing applications for this programming model; but refer to the Naked Objects documentation for the complete reference.

The code fragments that follow are taken from the Groovy Objects' own test application (see the Groovy Objects subversion repository).

3.1. (Optional) Superclass

Typically domain objects subclass from AbstractDomainObject (in the Naked Objects applib, transitively referenced from Groovy Objects' own applib); for example:

class Claim extends AbstractDomainObject {
   ...
}

It isn't mandatory to subclass from AbstractDomainObject. All that Naked Objects requires is that it can inject its DomainObjectContainer into the domain object to support lazy loading and dirty tracking (the resolve() and objectChanged() methods, normally called by CgLib proxies). The DomainObjectContainer also allows your domain object to be able to instantiate and persist new instances (using the newTransientInstance() and persist() methods).

In practical terms, then, if you aren't able or don't want to subclass from AbstractDomainObject, just make sure you push down the above methods into your own objects (probably by way of a project-specific superclass).