Testing JPA out of a container

One of the main reasons Enterprise JavaBeans (EJB) has been neglected in recent years is because EJB components can’t be easily unit tested. Fortunately, the EJB 3.0 spec greatly changes the programming model make EJB—primarily entities—usable and testable outside the container.

Since we need the EJB 3.0 persistence layer we can use Hibernate or Toplink implementation: for  this article we’ll stick to Hibernate implementation.

Create a Java project

In order to begin, let’s create a Java project and add a class named com.sample.Ticket to it:

package com.sample;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;


@Entity
@Table(name = "NOTE")
 
public class Ticket implements Serializable {
	
	long ticketId;
	String text;
	String actor;
	String attachment;

	@Id
	@GeneratedValue
	public long getTicketId() {
		return ticketId;
	}

	public void setTicketId(long noteId) {
		this.ticketId = noteId;
	}

	public String getActor() {
		return actor;
	}

	public void setActor(String actor) {
		this.actor = actor;
	}

	public String getAttachment() {
		return attachment;
	}

	public void setAttachment(String attachment) {
		this.attachment = attachment;
	}

	public String getText() {
		return text;
	}

	public void setText(String text) {
		this.text = text;
	}
}

As you can see this is a simple POJO but with Entity Beans annotations.

The crucial element that links the annotated classes to a specific database in the case of out-of-container persistence is the persistence.xml. This file is read upon instantation of the EntityManagerFactory. It must be located in the classes/META-INF directory (or in one of the jar-files on the classpath).

In the persistence.xml file, a Persistence Unit is specified, a bundle of Entities that are mapped to the same Database Connection. For my example, persistence.xml maps to tables in my local Oracle database:

<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">   
 <persistence-unit name="persistenceUnit">
 <provider>org.hibernate.ejb.HibernatePersistence</provider>
  <class>model.Customer</class>
  <properties>
   <property name="hibernate.connection.driver_class" value="oracle.jdbc.driver.OracleDriver"/>
   <property name="hibernate.connection.username" value="user"/>
   <property name="hibernate.connection.password" value="password"/>
   <property name="hibernate.connection.url" value="jdbc:oracle:thin:@localhost:1521:ORCL"/>
   <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect" />
   <property name="hibernate.hbm2ddl.auto" value="create-drop"/> 
  </properties>
 </persistence-unit>
</persistence>

As you can see we have added the property “hibernate.hbm2ddl.auto” which will create/drop the tables for us if they are not found in the schema.

Creating a business service

Creating a client is just a matter of minutes. When using a testing framework you probably don’t need it but in a real world application you’d better to isolate our application from persistency details, implementing a Business Service that the application can talk to. The Business service class is very much like the SessionBean facade you would create for in-container deployment.

package com.sample;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class TicketService {
	private EntityManager entityManager;

	public TicketService() {
		EntityManagerFactory emf = Persistence
		.createEntityManagerFactory("persistenceUnit");

		EntityManager em = emf.createEntityManager();
		setEntityManager(em);
	}

	public Ticket createTicket(String text, String actor, String attachment) {
		Ticket t;

		t = new Ticket();
		t.setText(text);
		t.setActor(actor);
		t.setAttachment(attachment);

		this.entityManager.persist(t);
		return t;
	}

	public List <Ticket> findAllTicket() {
		return entityManager.createQuery("select object(o) from Ticket o")
		.getResultList();
	}

	public EntityManager getEntityManager() {
		return entityManager;
	}

	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}
}

The client has only 2 methods: createTicket which is used to persist data and findAllTicket which issues a query on all Tickets.

The client

The client is in charge to connect to the Business service and persist data using the Entity Manager, made available by the business service :

package com.sample;

import java.util.List;

import javax.persistence.EntityTransaction;

public class TicketClient {
    public static void main(String args[]) {
    	TicketService ticketService = new TicketService();
    	
        EntityTransaction tx = ticketService.getEntityManager().getTransaction();       
        tx.begin();       
        // Create a new customer and persist it.       
        ticketService.createTicket("urgent CR","mark spencer","/home/mspencer/data/attachment.txt");
        // Commit the transaction
        tx.commit();
        
        List <Ticket> tickets = ticketService.findAllTicket(); 
        for (Ticket e : tickets) { 
        	System.out.println(e.getTicketId()); 
        	System.out.println(e.getActor());
        	System.out.println(e.getText());
        	System.out.println(e.getAttachment());
        	
        }
    }
}

Conclusion

It turns out to be very straightforward to get EJB 3.0 Persistence to work, outside of a container. The concepts are – not surprisingly- pretty familiar: you create POJO Domain Objects, you specify how they map to table and columns and you make use of some sort of session or service or manager object to invoke persistence services.

Found the article helpful? if so please follow us on Socials