REST Project Digest and Generic Data Repository

Introduction

In this installment we will review the progression made through the previous REST-Jersey-JPA-Spring articles. We will also be extending our sample program in two ways.  First we are going to service two tables with a one-to-many association.  The enhancement will present a few new challenges and provide a stronger base for future developments.  Second we are adding some design elements to our application which will increase the extensibility, manageability and scalability of the solution.

Progression of the Project

Jersey,Spring and JPA

In this article we presented the integration of Jersey, Spring and JPA.  An integration that was worth blogging to illuminate the conflict between jar versions blocking a quick efficient integration.  The client code for this project was a simple webpage or through the user of cURL.

REST CRUD: Jersey, Spring and JPA

Here we extended our original project to include the full CRUD (create, read, update and delete) functionality through REST.  An enhanced web client was introduced to demonstrate the functionality.  The Ajax interaction was provided through a modified Prototype.js library.

Extending the CRUD Example Utilizing JAX-B and Jersey’s JSON

The previous article created json manually by constructing of a string.  In this article we use JAX-B 2′s annotations to mark-up the entity to make these POJO’s available for serialization into XML and onto JSON.

Quality Control: get rid of the CRUD and get REST

Here we added proper unit tests and reporting tools.  Additionally we returned are modified Prototype.js library to it’s prestent state and instead added our own Ajax REST javascripts (albiet heavily based upon Prototype.js).

 

Sample Application

To be more demostrative of the user of the technologies in the application another entity has been added to the model with a one-to-many association.  In business terms a company(Company) can have many employees (Person).  We will be able to interact with these entites through the CompanyDirectoryRest REST resource.

Design Considerations

Currently the project is a straight-up implementation to meet the needs of integrating the technologies of interests with a crude implementation of the core CRUD operations.  Through design the components of the application can be considered with respect to its ability to respond well to service level requirements such as: extensibility, scalability and manageability.

Here are some loose requirements that the application must full fill:

  1. Provide a way to create services for a variety of clients
  2. flexibility in the application design such that it may switch between protocols to the client such as: HTTP and SOAP.
  3. abstract our data source such that we can alter where our data arise from: JPA, Hibernate, JDBC, a Webservice, EJB etc.

J2EE Patterns

First off we leverage a lot of support in providing a component-oriented application through the use of Spring’s dependency injection (DI).  The first two requirements are satisfied through utilizing DI along with the J2EE Pattern Business Object.  In this design the REST resource, CompanyDirectory,  is a consumer of the Business Object.  The Business Object being the object that handles are the association of the datasources and higher level business function.   The REST resource, CompanyDirectoryRest, is a simple GOF Adapter; it modifies the interface of the business object to serve its’ client’s needs.  This same strategy can be applied to extend the application to support other protocols.  It can easily be imagined how one might create a SOAP Adapter to service SOAP Clients. Again the SOAP Adapter would consume the services of the Business Object and provide the SOAP functionaliy for communication of the information to the SOAP clients. 

The third item in the requirements list is about data source abstraction.  Again we are programming to an interface and utilizing DI.  We are also programming with generics which provide a big boost to productivity and provide a point for extension.  There is a very good article by the author of this portion of the code at the Belgium Jugs website. So we have the oportunity here to support other database through the GenericRepository and through newly introduced datasource interfaces we can consider adding alternate datasource such as: EJB’s, webservices, DAO and so on.

Programming to an interface along with DI creates the ability to make configuration changes simple and in turn addressing those interests in: extensibility, scalability and manageability.

 

 diagram Class Diagram of the REST Project

Class Diagram of new project

 

Implementation

For more details on the implementation please see the other articles identified at the top of the document.  In this section we will discuss details which arose in this implementation that differed from the previous projects.

JAXB and Generic Collections

We introduced the Company entity that maintains a collection of employees (Person).  The class is marked-up this class with JAXB Annotations as the Person class was.  There is a difficulty with using Generics with JaxB which needs to be delt with.  The problem arises from the fact that the class types declared in a Generic collection is available only at compile time and is erased at runtime (type erasure).  So when we JAXB utilizes an accessor to a generic collection such as:

@OneToMany(mappedBy = "company", fetch = FetchType.EAGER)
private List<Person> employees = new ArrayList<Person>();

or

	public List<Person> getEmployees() {
		return employees;
	}

at runtime the information with respect to the type Person is no longer available.  So as JAXB attempts to serialize the collection it throws an exception because it can not determine the class type of collection. This will occur whether the class is annotated for access through fields or members.  I don’t know of a way of doing this borth adirect and clean way.  The solution employed in this sample is through the use of the GenericEntity class.  This class is part of javax.ws.rs.core and is used precisely for this purpose.  We have altered the getEmployees() method in Company to the following plus we have annotated the class with XmlAccessType set to PUBLIC_MEMBER so that when the class is transformed by JAXB it will use the method rather than the field.

public GenericEntity<List<Person>> getEmployees() {
	return new GenericEntity<List<Person>>(employees) {};
}

The solution is a little unattractive since it alters are natural use of the entity class and bleeds the jax.ws.rs api into the model which now makes it coupled.

 

GenericRepository (DAO)

As mentioned earlier the DAO or repository for our project is using Generics heavily.  Our implementation is from this Belgium Jugs website the efforts of Jurgen Lush and Stephan Janssen.  The generics remove the code replication that appears among implementation of DAOs.  Coding to the GenericRepository inteface we open the possabilites to many persitent providers.  In the sample a JPA provider GenericJpaRepository is coded.  The generics can make DAO as simple as implement the following class and interface:

@Service("personDS")
public class PersonJpaRepository extends GenericJpaRepository<Person, Long>
		implements PersonDS {
	//we inherit the basic CRUD operations from the GenericRepository
}

 And

public interface PersonRepository extends GenericRepository<Person, Long> {
}

That is a very brief way to construct a DAO.  Note that wehave the PersonJpaRepository implementing the PersonDS (Person Data Source).  This interface gives us the ability to consider options such as EJB’s or Webservices as datasources whcih fall outside the perview of the DAO.

Additionally we have moved the transactional management of the methods out of the class and are apply them through annotation defined in the applicationContext.xml.  The settings are shown below:

<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
	 <!-- the transactional semantics... -->
	<tx:attributes>
		<tx:method name="find*" read-only="true"/>
		<tx:method name="get*" read-only="true"/>
		<tx:method name="count*" read-only="true"/>
		<tx:method name="save*" read-only="false" propagation="REQUIRED" />
		<tx:method name="update*" read-only="false" propagation="REQUIRED" />
		<tx:method name="delete*" read-only="false" propagation="REQUIRED" />
	</tx:attributes>
</tx:advice>
<!--
	ensure that the above transactional advice runs for any execution of
	an interfaces in the com.persistent.repository package
-->
<aop:config>
	<aop:pointcut id="repositoryMethods"
		expression="execution(* com.persistent.repository.util.*.*(..))" />
	<aop:advisor advice-ref="transactionAdvice" pointcut-ref="repositoryMethods" />
</aop:config>

REST Web Client

The web client from the previous projects has been extended to include the Company information as shown below.

 

Performance Improvement

We do have a great inefficiency here with our one-to-many relationship.  We have annotated the relationship as having an eager fetch mode.  This does provide some conveniences for coding but we pay for them through a big performance hit.  For instance when the web page above loads it requests a list of companies and when it is retrieves that list in an eager fetch all the associated employees are also retrieved.  When you have all that information then sent to the web page in JSON format, well its just not a good idea.  Changing our  fetch mode is a simple change.  Our new employee accessor is annotated LAZY:

@OneToMany(mappedBy = "company", fetch = FetchType.LAZY)
private List<Person> employees = new ArrayList<Person>();

Additionally since the data is loaded lazily we will need a query for loading the Company object eagerly. For this we have added a NamedQuery annotation at the the top of the Company class. We have also expanded the CompanyDS to include a method to access data through named queries.  There are other options we could explore that would not expose the method as a JPA/ORM/SQL query which would fascilitate a better interface for non-JPA/ORM/SQL interfaces, such as adding a method to the CompanyJpaRepository class but for now we’ll take the short cut.

A left join of the Company and a Fetch over the employees does the trick.  The query is name Company.EagerFindById for ease of entity association and purpse.

@Table(name = "COMPANY")
@NamedQueries( { @NamedQuery(name = "Company.EagerFindByID", query = "FROM Company c left join fetch c.employees where c.id =?1") })
public class Company {

 Here is the expanded CompanyDS interface:

public interface CompanyDS {
	public List<Company> findAll();
	public Company findById(final Long id);
	public Company save(final Company person);
	public Company update(final Company person);
	public Integer countAll();
	public void delete(final Company person);
	public List<Company> findByNamedQuery(final String name,final Object... params);
}

 This is the new query in action.

List<Company> companies = companyDS.findByNamedQuery("Company.EagerFindByID", companyId);
Company persistedCompany = null;
if(companies.size()>0) {
	persistedCompany= companies.get(0);
}

Conclusion

In conclusion we accomplished a few items to improve our ever evolving project they include:

  • re-structued the code for extensibility, manageablity and scalability.
  • introduced a one-to-many relationship and made adjust must to the entity to accommodate for type erasure with respect to JAXB.
  • added a generic DAO that dramatically reduces the coding required to support a entity
  • switched the application to use AOP for transaction management

 Project Reports

The Source Code

The complete code listing is here.

Installation Instructions

  1. On down loading the source code which is in a jar filed called: general.jar uncompress it:

jar xvf general.jar

There will now be a new directory called general.

  1. Database configuration.  In the directory general/main/resources the file general.properties contains the information regarding your database configuration including: user, password, Driver and database name.  If you are using MySQL locally then all that needs to change would be the username and password.  You will also either need to change the jdbc.url to a database you have already or create the database jpa used by the project.
  1. Go back to the general directory where the pom.xml file is and you are ready to compile and run the program.  Maven2 makes this simple.  To compile and run (the clear command is in here too. It isn’t important for the first build but is important as one begins development with the code).

mvn clean install

In this process the program will run through the JUnit test cases.  If a test fails you will not be able to run the program until the defect is fixed.  You can override the tests (and hope the program will run) by using a flag:

mvn clean install -Dmaven.test.skip=true

  1. Now we are ready to run the program. Enter:

mvn jetty:run

The jetty server will startup and you will then be able to interact with the application’s REST webservice using cURL or the html webpage. To use the html webpage use this URL:

http://localhost:8080/general/

Running Reports

There are three report plugins configured in the pom.xml.  Sample output of these reporting engines can be viewed through the links in the Project Reports section of the article. The simple Maven command to create each of these reports are as follows:

PMD Report

mvn pmd:pmd

Cobertura Report

mvn cobertura:cobertura

Surefire Report

surefire-report:report-only

Eclipse Integration

If you are interested in importing this project into your eclipse environment the following command will create the configuration files required to import the project into eclipse as an existing eclipse project.  This command is run, as the others are, from the root directory general:

mvn eclipse:eclipse

 

About The Author

David Sells is a computer consultant in Toronto, Ontario specializing in Java Enterprise Development. His clients have included companies such as: IBM, Goldman Sachs, Merrill Lynch and Deutsche Bank.

Sun Certified Enterprise Architect for the Java Platform, Enterprise Edition 5

Contact: david@persistentdesigns.com

 

 

 

2 comments to REST Project Digest and Generic Data Repository

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>