Archive

Posts Tagged ‘JPA’

Spring + JTA + JPA + JMS

April 8th, 2010 13 comments

I recently worked on a Spring application that used Hibernate as JPA provider and JTA for transaction demarcation. In this post I will create a simple Order Processing Message Driven Bean that showcases this integration. I will be using an Oracle database and deploy the application on a WebLogic 10.3 server.

To keep things manageable, the Message Driven Bean is designed to consume messages from a Queue. When a new message gets added to the Queue, the Application Server delivers it to the MDB. The MDB then uses a Spring Managed Service/Repository to persist a new “Order” JPA Entity in the database. The application is configured such that this entire process runs in a container managed transaction. I will be using the Blog Queue I created in a previous post.

Step 1: The first step is to create an Order Entity and the corresponding database table to store the newly created orders.

 
package com.inflinx.blog.orderprocessing.domain;

import java.util.Date;

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

@Entity
@Table(name="ORDER_TABLE", schema="BLOGDEMO")
public class Order 
{
	@Id
	@Column(name="ORDER_ID")
	private Long id;
	
	@Column(name="NAME")
	private String name;
	
	@Column(name="CREATED_DATE")
	private Date createdDate;

	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Date getCreatedDate() {
		return createdDate;
	}
	public void setCreatedDate(Date createdDate) {
		this.createdDate = createdDate;
	}
}

I have created the ORDER_TABLE in an Oracle database under the BLOGDEMO schema:

Order Table

Order Table

Step 2: In the WebLogic console, create a XA datasource to the database with the JNDI name jdbc.blgods.

XA Blog Data Source

XA Blog Data Source

The XA datasource is necessary for Hibernate to participate in a JTA global transaction. WebLogic also provides an option to emulate XA with the Emulate Two-Phase Commit.

Step 3: The next step is to create an OrderRepository that deals with persistence logic such as creating a new Order.

package com.inflinx.blog.orderprocessing.repository;

import com.inflinx.blog.orderprocessing.domain.Order;

public interface OrderRepository 
{
	public void createOrder(Order order);
}
package com.inflinx.blog.orderprocessing.repository;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Repository;

import com.inflinx.blog.orderprocessing.domain.Order;

@Repository("orderRepository")
public class OrderRepositoryImpl implements OrderRepository 
{
	// Spring injected EntityManager
	@PersistenceContext
    private EntityManager entityManager;
	
	@Override
	public void createOrder(Order order) 
	{
		 entityManager.persist(order);
	}
}

Step 4: Following the principles of layered architecture, the next step is to create an OrderService and its implementation.

package com.inflinx.blog.orderprocessing.service;

import com.inflinx.blog.orderprocessing.domain.Order;

public interface OrderService {
	public void createOrder(Order order);
}
package com.inflinx.blog.orderprocessing.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.inflinx.blog.orderprocessing.domain.Order;
import com.inflinx.blog.orderprocessing.repository.OrderRepository;

@Service("orderService")
@Transactional
public class OrderServiceImpl implements OrderService {

	@Autowired
	@Qualifier("orderRepository")
	private OrderRepository orderRepository;
	
	@Override
	public void createOrder(Order order) {
		// Simply delegate the call to repository layer
		orderRepository.createOrder(order);
	}
}

As you can see, the implementation is annotated with @Transactional to make the service call transactional.

Step 5: The next step is to create a persistence.xml file without any JPA provider information.

 

	
		
			com.inflinx.blog.orderprocessing.domain.Order
		

		

Step 6: The next step is to create a Spring configuration application-context.xml file to hold bean and transaction definition. In addition, the file also holds the JPA provider information.


       
	     
    
     
    
    
    
	
	
	
	
    
	    
    
    			
    				
    					
    					
    				
    			
    			
    				
    					hibernate.transaction.factory_class=org.hibernate.transaction.JTATransactionFactory
					hibernate.transaction.manager_lookup_class=org.hibernate.transaction.WeblogicTransactionManagerLookup
					hibernate.current_session_context_class=jta
					hibernate.transaction.flush_before_completion=true						
					hibernate.connection.release_mode=auto
    				
    			
    			
    	
             

Step 7: With the above configuration in place, the next step is to create a Message Driven Bean that processes incoming messages. The MDB is annotated to use container managed transactions:

 
package com.inflinx.blog.mdb;

import java.util.Date;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.interceptor.Interceptors;
import javax.jms.Message;
import javax.jms.MessageListener;

import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor;

import com.inflinx.blog.orderprocessing.domain.Order;
import com.inflinx.blog.orderprocessing.service.OrderService;


@MessageDriven(
		mappedName = "jndi.blogQueue",
		name="orderProcessor",
		activationConfig = { @ActivationConfigProperty(
				propertyName = "destinationType", propertyValue = "javax.jms.Queue"
		)}
)
@Interceptors(SpringBeanAutowiringInterceptor.class)
@TransactionManagement(TransactionManagementType.CONTAINER)
public class OrderProcessor implements MessageListener
{
	@Autowired
	@Qualifier("orderService")
	private OrderService orderService;
	
    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void onMessage(Message message) 
	{
    	// Create a new Order
    	Order order = new Order();
    	order.setId(System.currentTimeMillis());
    	order.setName(RandomStringUtils.randomAlphabetic(5));
    	order.setCreatedDate(new Date());
    	
    	// Save the order
    	orderService.createOrder(order);
	}
	
}

Step 8: The SpringBeanAutowiringInterceptor by default looks for a beanRefContext.xml file to create a spring context. So the final step in the process is to create a beanRefContext.xml with a reference to the application-context.xml.




			 
		
							
				application-context.xml
			
		 		
	
	 

Now when a new message gets added to the Queue, the onMessage method will run inside a transaction and will create a new Order. Here is a new Order record in the database:

Order Table Populated

Order Table Populated

Categories: JMS, JPA, JTA, Spring Tags: , , ,

Hibernate Ldap bridge

August 19th, 2008 5 comments

It is not uncommon for enterprises to store their employee information in LDAP. Now this poses an interesting challenge for building ORM applications that need access to employee information. For example, consider writing an application that tracks the projects an employee is currently working on. Such an application would have the following simple domain model:

An ORM mapping tool such as Hibernate can easily map this domain model to a database backend. However, since the employee data comes from LDAP, hibernate out of box cannot create the mapping between Project and Employee domain objects. One way to solve this problem would be to implement a custom EntityPersister. In this post I will show a simple hack for achieving this using JPA EntityListeners.

First let us create Java objects and relationships between them. Here is some minimal code:

public class Employee implements Serializable
{
  private Long id;
  private String firstName;
  private String lastName;
  
  // Other fields, getters, setters and other logic
}

public class Project implements Serializable
{
  private Long Id;
  private String name;
  private String description;
  
  private Employee employee;
  
  // Getters, setters and other logic  
}

The next step is to define tables in the database. Here is the table structure:

PROJECT
———–
PROJECT_ID | NAME | DESCRIPTION | EMPLOYEE_ID |

EMPLOYEE
—————-
EMPLOYEE_ID |
Since all the employee information (including EMPLOYEE_ID) is available in LDAP, this table simply holds the unique id of an employee.

Then, create mappings for the domain objects using JPA. The mapping for Application is straightforward:

@Entity
@Table(name="PROJECT")
public class Project implements Serializable 
{
  @Id
  @Column(name="PROJECT_ID")
  // Sequence generator declarations
  private Long Id;
  
  @Column(name="NAME")
  private String name;
  
  @Column(name="DESCRIPTION")
  private String description;
  
  @ManyToOne(cascade= {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
  @JoinColumn(name="EMPLOYEE_ID")
  private Employee employee;

  // Getters, setters and other logic  
}

@Entity
@Table(name="EMPLOYEE")
public class Employee implements Serializable
{
  @Id
  @GeneratedValue(generator="assigned")
  @GenericGenerator(name="assigned", strategy="assigned")
  @Column(name="EMPLOYEE_ID")
  private Long id;
  
  @Transient
  private String firstName;
  
  @Transient
  private String lastName;
  
  // Getters, setters and other logic
}

With these mappings in place, hibernate can easily load the Project
object and the corresponding Employee object. To populate the
transient fields in the Employee object, an EntityListener needs to be
created. Here is a simple implementation for the entity listener:

public class EmployeeEntityListener
{
  @PostLoad
  public void loadEmployee(Employee employee)
  {
    Map<String, String> employeeData = // Read the employee data from LDAP using the employee Id as the key
    employee.setFirstName(employeeData.get("FIRST_NAME"));
    employee.setLastName(employeeData.get("LAST_NAME"));
  }
}

Finally register this entitylistener:

@Entity
@Table(name="EMPLOYEE")
@EntityListeners(EmployeeEntityListener.class)
public class Employee implements Serializable
{
  ——-

Categories: Hibernate Tags: , ,