Enterprise Java

Implementing Active Record Pattern with Spring AOP

During class design we should take decisions about the assignment of responsibilities that will have every class. If we have chosen well, systems tend to be easier to understand, maintain and extend.

Almost all of our projects have a persistence layer, either relational database, document stores, or simply XML files. And typically you will use DAO pattern to implement abstract interface between your business objects and your data store.

In this post but I am going to explain another pattern that can be used instead of DAO pattern. Active record pattern is an architectural pattern that force you to implement CRUD operations on your model class, hence model class itself is responsible for saving, deleting, loading from database.

There are many strategies to follow to implement this pattern, but for me, the best one is using Aspect Oriented Programming, because we are still maintaining separation of concerns favoring isolated unit testing, and not breaking encapsulation.

Aspect-oriented programming entails breaking down program logic into distinct parts. These parts are known as crosscutting concerns because they “cut across” multiple abstractions in a program. Example of crosscutting concerns can be logging, transaction manager, error manager or splitting large datasets. For people that have worked with aspects not much secret here, to use them you simply create an aspect defining the advice and the pointcut, and your aspect is ready to be executed.

I guess most of us use aspects-oriented programming as I have described in previous paragraph, but will be fewer that uses ITD (Inter-type Declarations) feature.

Inter-type Declarations provide a way to express crosscutting concerns affecting the structure of modules enabling programmers to declare members of another class.

As we say in my country “bad said but well understood“, ITD is a way to declare new components (attributes, methods, annotations) of a class from an aspect.

AspectJ is an aspect-oriented extension for Java. AspectJ supports ITD, and for this reason will be used in this post. Moreover I recommend you install AJDT plugin because it will help you develop aspects and having a quick overview of which Java classes are aspecterized.

If you have not understood what ITD is, don’t worry, it is a typical example of concept that is best understood with an example.

Let’s start with simple example:

Imagine having to model a car. You would have a car class, with some attributes, for this example three attributes (vin number, miles drived and model) is enough.

public class Car {

 public void setVin(String vin) {this.vin = vin;}
 public String getVin() {return this.vin;}
 private String vin;

 public void setMileNum(int mileNum) { this.mileNum = mileNum;}
 public int getMileNum() {return this.mileNum;}
 private int mileNum;

 public void setModel(String model) {this.model = model;}
 public String getModel() {return this.model;}
 private String model; 

}

It is a POJO with three attributes and their getters and setters.

Now we want to add persistence layer, but in this case we are going to persist our POJOs in a XML file instead of a database. So Car objects should be transformed to XML stream. For this purpose JAXB annotations will be used. For those who don’t know, JAXB allows developers to map Java classes to XML representations and viceversa.

I am sure that first idea that comes to your brain is annotating Car class with @XmlRootElement (annotation to map root element in JAXB). Don’t do that, use aspects. Your first mission is trying to maintain Car file as simple as possible. To add an annotation using ITD, is as simple as:

public aspect Car_Jaxb {

 declare @type: Car: @XmlRootElement;
}

With @type you are exposing which member is annotated. In this case only class. Other possibilities are @method, @constructor and @field. Then elements pattern that should be annotated, in this case Car class, but you could use any regular expressions like org.alexsotob..*. Finally the annotation.

Next step is using JAXB classes to marshalling/unmarshalling objects. In this example I am using spring-oxm package and briefly you will understand why. Spring-oxm is a part of spring-core that contains classes for dealing with O/X Mapping.

This spring module contains one class for each Xml binding supported. In our case Jaxb2Marshaller is used as marshaller and unmarshaller.

It is possible that you are thinking of creating a service class where you inject Jaxb2Marshaller instance. This service would include two methods (save and load) with Car class as argument or return value. Sorry but, doing this, you are implementing DAO pattern. Let’s implement Active Record pattern approach. And as you may suppose, aspectj comes to rescue you to avoid mixing concepts in same source file.

Let’s update previous aspect file so all required logic by JAXB will be in same file.

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;

public aspect Car_Jaxb {

 declare @type: Car: @XmlRootElement;

 @Autowired
 transient Jaxb2Marshaller Car.marshaller;

 public void Car.save(OutputStream outputStream) throws IOException {
  this.marshaller.marshal(this, new StreamResult(outputStream));
 }

 public Car Car.load(InputStream inputStream) throws IOException {
  return (Car)this.marshaller.unmarshal(new StreamSource(inputStream));
 }

}

See that apart from annotating Car class we are creating two methods, and an annotated attribute. Attributes must follow same rule as methods, <class name> dot (.) and <attribute name>. Note that in this case attribute is transient because should not be bound in XML file.

Last step is configuring marshaller in spring context file.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:oxm="http://www.springframework.org/schema/oxm"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">


 <oxm:jaxb2-marshaller id="marshaller">
  <oxm:class-to-be-bound name="org.alexsotob.itd.Car"/>
 </oxm:jaxb2-marshaller>

</beans>

Not much secret. Now let’s code a unit test.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="/context.xml")
public class CarOxmBehaviour {

 @Test
 public void shouldSaveCarToXml() throws Exception {
  //Given
  Car car = new Car();
  car.setMileNum(1000);
  car.setModel("Ferrari");
  car.setVin("1M8GDM9AXKP042788"); //From http://en.wikipedia.org/wiki/Vehicle_Identification_Number

  //When
  ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
  car.save(byteArrayOutputStream);

  //Then
  String expectedMessage = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><car><mileNum>1000</mileNum><model>Ferrari</model><vin>1M8GDM9AXKP042788</vin></car>";
  String xmlMessage = byteArrayOutputStream.toString("UTF-8");

  assertThat(the(xmlMessage), isEquivalentTo(the(expectedMessage)));  
 }

}

Run junit class and BOOM all red, with an amazing NullPointerException. Marshaller is created in Spring context, but not injected into Car class (Car is not managed by spring container, so is impossible to be injected). And now I suppose you are telling yourself: “I told you a service layer would be better, because it would be managed by Spring and autowired would work perfect.”. But wait and see. How about using spring-aspects module? Spring Aspects contains an annotation-driven aspect (@Configurable) allowing dependency injection of any object, whatever is or not controlled by container. So let’s apply last two changes and the application will run.

First of all is creating a new aspectj file to annotate Car class as Configurable.

import org.springframework.beans.factory.annotation.Configurable;

public aspect Car_Configurable {

 declare @type: Car: @Configurable;

}

And finally modify spring context file to allow @Configurable annotation.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:oxm="http://www.springframework.org/schema/oxm"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">


 <oxm:jaxb2-marshaller id="marshaller">
  <oxm:class-to-be-bound name="org.alexsotob.itd.Car"/>
 </oxm:jaxb2-marshaller>
 <context:spring-configured></context:spring-configured>
</beans>

Adding <context:spring-configured></context:spring-configured> namespace is enough. As a result, any time you instantiate an object (via the “new” keyword), Spring will attempt to perform dependency injection on that object.

Now run unit test again and green will invade your computer :D.

ITD is a really nice solution to design classes with its own responsibilities. It gives you the oportunity of writing maintainable and understandable code, without loosing encapsulation. Of course you should take care of not to have high coupling in aspected classes, and convert them in “God Classes”.

Note that implementing same approach but using relational database, it is as simple as changing Jaxb2Marshaller to EntityManager.

I wish you have found this post useful.

Download Full code

Reference: Implementing Active Record Pattern with Spring AOP from our JCG partner Alex Soto at the One Jar To Rule Them All blog.

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button