Skip to main content
Software View

Main navigation

  • Home
  • Trainer Profile
  • Blog
  • Contact
User account menu
  • Log in

Breadcrumb

  1. Home
  2. Blog

Spring JPA web applications (JTA transactions, JBoss 5)

By Kamal Wickramanayake, 13 June, 2010

With Spring 3.x, you can develop JPA applications very easily. Here you find guidelines in creating such an application with the following features:

  1. Use JTA for transaction management (with very little modifications you can use resource local transactions as well).
  2. Make sure the same JPA EntityManager instance is used across multiple DAOs so that a single business method can use multiple DAO method calls within the same transactional context.
  3. Make sure the same EntityManager instance is available for multiple DAOs in a thread safe manner.

Environment used is given below. You may use other versions of software with minor changes (for example Spring 3.0.1 and so on).

  1. Spring 3.0.0
  2. JBoss 5.1.0 (JDK 1.6 version)
  3. JDK 1.6.0.11
  4. Hibernate (the one packaged with JBoss 5.1.0)
  5. Database used: MySQL 5.1.37
  6. Development environment: Eclipse Galileo

Here are the steps:

1. Define the Spring configuration file in the web.xml file

	
<context-param>
        <description>Spring configuration file</description>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

2. Define the Spring loader in the web.xml file

	
<listener>
        <description>Spring Loader</description>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
</listener>

3. Define the persistence unit reference in the web.xml file:

	
<persistence-unit-ref>
        <description>
            Persistence unit for the bank application.
        </description>
        <persistence-unit-ref-name>persistence/BankAppPU</persistence-unit-ref-name>
        <persistence-unit-name>BankAppPU</persistence-unit-name>       
</persistence-unit-ref>

4. Here's the persistence.xml file. Make the changes to the <jta-data-source> as you have defined in your system (for example in a file like JBOSS_HOME/server/default/deploy/bank-ds.xml - See JBOSS_HOME/docs/examples/jca/ for templates).

	
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
     http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
  <persistence-unit name="BankAppPU" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>java:BankAppDS</jta-data-source>
    <properties>
      <!-- Auto-detect entity classes -->
      <property name="hibernate.archive.autodetection" value="class, hbm"/>

      <!-- Print sql executed - useful for debugging -->
      <property name="hibernate.show_sql" value="true"/>
      <property name="hibernate.format_sql" value="true"/>

      <property name="hibernate.transaction.manager_lookup_class" 
          value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>

      <property name="hibernate.hbm2ddl.auto" value="create"/>
    </properties>
  </persistence-unit>
</persistence>

5. Here's a sample Spring configuration file (applicationContext.xml):

	
<?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:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="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.xsd
    http://www.springframework.org/schema/jee
    http://www.springframework.org/schema/jee/spring-jee.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- JPAAccountDAO has JPA annotations to access EntityManager -->
    <context:annotation-config/>

    <!-- Access the EntityManagerFactory like this - if ever you need -->
    <jee:jndi-lookup id="emf" jndi-name="persistence/BankAppPU"/>

    <!-- Here's a DAO that we will be using -->
    <bean id="accountDAO" class="bank.dao.jpa.JPAAccountDAO"/>

    <!-- Will be using the DAO in a business logic class AccountManager -->
    <bean id="accountManager" class="bank.AccountManagerImpl">
        <property name="accountDAO" ref="accountDAO"></property>
    </bean>

    <!-- Configure Transaction Support - Access the JTA transaction manager -->
    <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager">
          <property name="transactionManagerName" value="java:/TransactionManager"/>
        <property name="userTransactionName" value="UserTransaction"/>
    </bean>

    <!-- Use Spring AOP capabilities to manage transactions -->
    <aop:config>
      <aop:pointcut id="accountTransactions" 
               expression="execution(* bank.AccountManager.*(..))"/>
      <aop:advisor pointcut-ref="accountTransactions" advice-ref="txAdvice" />
    </aop:config>

    <tx:advice id="txAdvice" transaction-manager="txManager">
      <tx:attributes>
        <tx:method name="create" propagation="REQUIRED"/>
        <tx:method name="withdraw*" propagation="REQUIRED"/>
        <tx:method name="deposit*" propagation="REQUIRED"/>
        <tx:method name="chargeForLowBalance*" propagation="REQUIRED"/>
        <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
      </tx:attributes>
    </tx:advice>
</beans>

6. Here's the sample AccountManagerImpl:

	
package bank;

import java.util.Iterator;
import java.util.List;

import bank.dao.AccountDAO;

public class AccountManagerImpl implements AccountManager {

    private AccountDAO accountDAO;
    public AccountDAO getAccountDAO() {
        return accountDAO;
    }
    public void setAccountDAO(AccountDAO accountDAO) {
        this.accountDAO = accountDAO;
    }

    @Override
    public void chargeForLowBalance(double minimumBalance, double amount) {
        List<Account> accounts = accountDAO.findAccountsWithLowBalance(minimumBalance);
        for (Iterator<Account> iterator = accounts.iterator(); iterator.hasNext();) {
            Account account = (Account) iterator.next();
            // Check if the balance will go beyond 0. If yes, set the balance to 0
            account.setBalance(account.getBalance() - amount);
            accountDAO.update(account);
        }
    }

    @Override
    public Account create() {
        return accountDAO.createAccount();
    }

    @Override
    public void delete(int accountNumber) {
        accountDAO.delete(accountNumber);
    }

    @Override
    public void deposit(Account account, double amount) {
        //Account a = accountDAO.getAccount(accountNumber);
        account.setBalance(account.getBalance() + amount);
        accountDAO.update(account);
    }

    public void deposit(int accountNumber, double amount) {
        Account account = accountDAO.getAccount(accountNumber);
        deposit(account, amount);
    }
    

    @Override
    public void withdraw(int accountNumber, double amount) {
        Account account = accountDAO.getAccount(accountNumber);
        withdraw(account, amount);
    }    
    
    @Override
    public void withdraw(Account account, double amount) {
        if (account.getBalance() >= amount) {
            account.setBalance(account.getBalance() - amount);
            accountDAO.update(account);
        }   
        // Throw an exception (InsufficientBalanceException)?
    }
}

7.  Here's the JPAAccountDAO class:

package bank.dao.jpa;

import java.util.List;

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

import bank.Account;
import bank.dao.AccountDAO;

public class JPAAccountDAO implements AccountDAO {

    @PersistenceContext
    private EntityManager em;

    
    @Override
    public Account createAccount() {
        Account a = new Account();
        em.persist(a);
        return a;
    }

    @Override
    public void delete(int accountNumber) {
        em.remove(em.find(Account.class, accountNumber));
    }

    @Override
    public List<Account> findAccountsWithLowBalance(double lessThanAmount) {
        return em.createQuery("select a from Account a where a.balance < :amount")
                .setParameter("amount", lessThanAmount).getResultList();
    }

    @Override
    public List<Account> findAllAccounts() {
        return em.createQuery("select a from Account a").getResultList();
    }

    @Override
    public Account getAccount(int accountNumber) {
        return em.find(Account.class, accountNumber);
    }

    @Override
    public void update(Account account) {
        em.merge(account);
    }

}

Note that I haven't gone into placing all the classes and interfaces I used in my demo app. Purpose of the above is for you to see the critical configurations that are needed.

Here's the summary:

  1. A data source is configured in the application server.
  2. A persistence unit is configured (with JTA transaction management).
  3. Spring configuration file is written to process annotations in classes.
  4. The DAO depends on PersistenceContext annotation to access an EntityManager.
  5. Spring is configured to use the JTA transaction manager (of the application server).

You can follow the same style in writing all the DAOs you need. Even though EntityManager instances are not thread safe (but EntityManagerFactory instances are) in general, here you find Spring injecting a an EntityManager instance which is thread safe. In fact, this EntityManager injected is not a real EntityManager instance, but a proxy implementing the same (EntityManager) interface.

When a method (like withdraw) in the AccountManager (business logic) is invoked, we have configured Spring to start a transaction. When a method of DAO is invoked within this transactional context, the proxy EntityManager in DAO receives the method call and goes into searching for a real EntityManager instance associated with the transactional context. If found, that EntityManager instance is used. If not found, the proxy EntityManager will go about creating a new "real" EntityManager instance and associate it with the current transaction. This makes the same "real" EntityManager instance available in multiple DAOs within the same transactional context.

Given that a transaction is associated with a thread, the above configuration also makes sure that the "real" EntityManager instances are correctly used in a thread-safe manner in a multi-threaded environment. That is, a certain "real" EntityManager instance created while processing a request is used only within that thread.

The created "real" EntityManager instances are closed automatically when the transactions are committed or rolled back. Spring automatically does this.

Java

Highlights

  • O'Reilly Book "97 Things Every Software Architect Should Know" Accepts A Write Up From Kamal
  • "Service Oriented Architecture - Making IT Infrastructure Speaks Business" - Presentation At The ISACA 4th Annual Conference
  • The Second Bacth Of ICTA Nanasala e-Society Members Receives Trainings On HTML/CSS and GIMP
  • GIMP Training For ICTA Nanasala Project
  • Agile Processes Training For PPSL (Pvt) Ltd
  • Computer Society of Sri Lanka (CSSL) - Talk on "Introduction to IT Governance and Enterprise Architecture"
  • Motorola Sends A Second Batch Through Software Patterns Training
  • Kamal To Act As The Marketing Director - ISACA Sri Lanka Chapter
  • ISACA Sri Lanka Chapter Invites Kamal To Join As A Board Member
  • Epic Lanka Technologies (Pvt) Ltd Receives Java SE And Java EE Trainings From Software View
  • Patterns Training For PPSL (Pvt) Ltd
  • ISACA Members Day Presentation On "Introduction To IT Governance And Enterprise Architecture"
  • Opening Lecture On Information Technology For SLIDA Master Of Public Management Course Delivered By Kamal
  • Customized Java Enterprise Edition Training For SLIDA
  • No One To Beat Software View - Epic Lanka Technologies (Pvt) Ltd
  • Motorola Receives Software Patterns Training From Software View
  • Custom Java Enterprise Edition Training for ICTA/SLIDA - Only from Software View!
  • Java EE 5, JavaServer Faces, Hibernate And Spring For PPSL (Pvt) Ltd
  • "Brain Trust" For Linux Journal Weekly Newsletter From Kamal
  • Java Platform, Enterprise Edition 5 Training At The CEIT, University Of Peradeniya
  • Another Group Of Around 100 Sri Lanka Telecom Engineers And Managers Were Service Oriented!
  • Java Platform, Enterprise Edition 5 Training Will Be Held At The CEIT, University Of Peradeniya
  • Service Oriented Architecture: Another Two Sessions Conducted at SLT
  • Photos of IET Monthly Forum at the Peradeniya University
RSS feed
Copyright © 2007 - 2023 Software View