Wednesday, October 18, 2006

Integrating Prevayler into Spring: ease your persistence with Prevayler-Template.

System prevalence is a term coined by Klaus Wuestefeld, denoting a transparent persistence solution.

Let me give some more details for understanding what that means.

A prevalent system is a system made of business objects which obey the following rules:

  • They must be serializable.

  • The must be deterministic, that is, given some input to a business method, it must always return the same output.


A prevalent system is always fully kept in RAM and data is persisted through object serialization, by wrapping all business operations into command objects, serializing commands and all contained business objects into a log file, and executing them.
Then, when the system recovers after shutdown, all commands are read from the serialized log and executed again, recreating a perfect replica of the system prior to its shutdown.
This makes your system (and all its business objects):

  • Persistent, thanks to object serialization.

  • Transactional, because each command represent a single transaction and is executed in isolation.

  • Incredibly fast!



This is just a short (and partial) introduction: more details can be found here and here.

Prevayler is a Java, Open Source, implementation of a framework for achieving system prevalence.
It is widely used in environments where classical persistence solutions are not suitable or unwanted.
Moreover, it is simple to use, but requires you to sligthly change the way you code your application, because:

  • Many applications use the well-known Data Access Object (DAO) pattern for implementing persistence layer logic, while Prevayler (as the prevalence concept dictates) uses plain command objects and requires you to wrap your business methods with them, removing the need of a pure data access layer.

  • You have to care about the infamous baptism problem.



The Spring Prevayler-Template project aims at solving these problems, by providing a Prevayler-based implementation of the DAO pattern and the Spring Data Access architecture used for ORM frameworks, which let you create a prevalence system with totally transparent business objects persistence by simply respecting the rules above, common to all prevalence systems, and by:

  • Adding an (automatically managed) identifier property to your business objects.

  • Implementing a standard Data Access Object, as you would do with Hibernate or alike.

  • Configuring it into the Spring application context.


No additional code, no mappings, no annotations ... nothing more.

Let me show you a concrete example.

First, take a bunch of business objects, say a Person, an Employee and a Company:


public interface Person extends Serializable {

public void requestEmployment(Company company);
}


public interface Employee extends Person {

public void workAsAMad();
}


public interface Company extends Serializable {

public void employ(Person person);
}



Then, implement your business objects and assign them a simple identifier property:


public class PersonImpl implements Person {

private Long id;

public void requestEmployment(Company company) {
// ...
}
}


public class EmployeeImpl implements Employee {

private Long id;

public void workAsAMad() {
// ...
}
}


public interface CompanyImpl implements Company {

private Long id;

public void employ(Person person) {
// ...
}
}



That's all you need to do with your business objects.

Now, let us write a Data Access Object using the PrevaylerTemplate.
The classes showed below are a Prevayler-based porting of the well-known Hibernate generic DAO:


public interface IGenericDao<T, PK extends Serializable> {

public PK create(T newEntity);

public void update(T entity);

public void delete(T entity);

public T read(PK id);
}


public class PrevaylerGenericDao<T, PK extends Serializable> implements IGenericDao<T, PK> {

private PrevaylerTemplate prevaylerTemplate;
private Class<T> entityType;

public PrevaylerGenericDao(Class<T> type) {
this.entityType = type;
}

public PK create(T newEntity) {
this.prevaylerTemplate.save(newEntity);
return (PK) newEntity.getId();
}

public void update(T entity) {
this.prevaylerTemplate.update(entity);
}

public void delete(T entity) {
this.prevaylerTemplate.delete(entity);
}

public T read(PK id) {
return (T) this.prevaylerTemplate.get(this.entityType, id);
}

public PrevaylerTemplate getPrevaylerTemplate() {
return prevaylerTemplate;
}

public void setPrevaylerTemplate(PrevaylerTemplate prevaylerTemplate) {
this.prevaylerTemplate = prevaylerTemplate;
}
}



As you may note, the PrevaylerTemplate is used as it were a standard, maybe Hibernate based, data access template.

Finally, you need to configure it:


<bean name="prevalentSystem" class="org.springmodules.prevayler.system.DefaultPrevalentSystem">
<property name="prevalentClasses">
<list>
<value>Person</value>
<value>Company</value>
</list>
</property>
</bean>

<bean name="prevaylerConfiguration" class="org.springmodules.prevayler.configuration.PrevaylerConfiguration">
<property name="prevalentSystem" ref="prevalentSystem"/>
<property name="prevalenceBase" value="classpath:testPrevalenceBase"/>
</bean>

<bean name="prevaylerTemplate" class="org.springmodules.prevayler.PrevaylerTemplate">
<property name="configuration" ref="prevaylerConfiguration"/>
</bean>



There are just three objects to configure:

  • The prevalent system, defining the prevalent system implementation to use for storing your business objects. It requires you to configure the list of prevalent classes in the system, that is, the classes of business objects to persist. Note that if you need to persist a whole hierarchy, you need to specify just the base class, as it is in the sample where we configured just the Person class.

  • The prevayler configuration, defining the prevalent system implementation to use, and the location of the directory where Prevayler logs will be saved.

  • The prevayler template, defining its associated configuration bean.



That's all ... now your business objects are ready to be persisted!
And if you need to persist a new business object, just add its class to the prevalent classes configuration and do no more!

Prevayler-Template is a new born Spring module, currently available here into Spring Modules sandbox.
You can also take a look at Prevayler-PetClinic, the Prevayler-Template sample based on the well known PetClinic web application: you can find it here.

Any feedback is highly appreciated: feel free to comment on this post, or to ask a question through the Spring Modules forum.

Have fun!

No comments: