Access Spring context from web application

As I am using JSF with Spring, the beans managed by Spring are not accessible in my page, I used this Siegfried Bolz’s blog as a basis and used the facade pattern to hide access to the context.

The Spring context is loaded when the application starts using ContextLoaderListener in the apllication web.xml:

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

We need the following dependency:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>4.0.0.RELEASE</version>
</dependency>

Define the object which will reference the Spring context:

package net.classnotfound.spring.context;

import org.springframework.context.ApplicationContext;

public class AppContext {
    private static ApplicationContext ctx;

    /**
     * Injected from the class "ApplicationContextProvider" which is automatically
     * loaded during Spring-Initialization.
     */
    public static void setApplicationContext(ApplicationContext applicationContext) {
        ctx = applicationContext;
    }

    /**
     * Get access to the Spring ApplicationContext from everywhere in your Application.
     *
     * @return
     */
    public static ApplicationContext getApplicationContext() {
        return ctx;
    }
}

Now, define the object that give you access to it:

package net.classnotfound.spring.context;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
 * This class provides an application-wide access to the 
 * Spring ApplicationContext! The ApplicationContext is 
 * injected in a static method of the class "AppContext". 
 * 
 * Use AppContext.getApplicationContext() to get access 
 * to all Spring Beans. 
 * 
 * @author Siegfried Bolz 
 *
 */
public class ApplicationContextProvider implements ApplicationContextAware {

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        AppContext.setApplicationContext(applicationContext);

    }

}

And now this is the facade object which gives access to the Spring beans:

package net.classnotfound.spring.context;

import org.springframework.context.ApplicationContext;

public class ServiceFacade {

	private static ServiceFacade instance = new ServiceFacade();
	
	private static ApplicationContext applicationContext;

	private ServiceFacade() {
		applicationContext = AppContext.getApplicationContext();
	}

	public static ServiceFacade getInstance() {
		return instance;
	}

	//Add here the method to get the different services available 
	// in the Spring Context
	public SpringBean getMyBean() {
		return (SpringBean) applicationContext.getBean("myBean");
	}
}

Don’t forget to ask Spring to create the bean:

<bean id="contextApplicationContextProvider" 
      class="net.classnotfound.spring.context.ApplicationContextProvider"/>

To use it:

SpringBean bean = ServiceFacade.getInstance().getMyBean();

Done!

MyBatis+Spring+Generics

As I was working on the data access layer of my project, I noted that I have a lot of stuff to do to be able to access the Mapper from my web layer just for some simple CRUD actions.
Lot of stuff and even if I can detect some similarities, it’s not exactly the same, so I can’t just decide to put it in an interface or some abstract class, but lazy one day, lazy allways (it sounds better in french :D)…
After using my unique neurone to find solution, I finally arrive to a solution that I will present here.

To briefly describe my architecture, I have a web layer which access a service layer and then, the service layer can reach the data layer.
A requirement in my application is the user management (firstname, lastname, address, etc…), it’s what I will use to illustrate my solution.
First, I wanted to define a generic Dao to access my User object, to do that, the search all user is the simpler mechanism.
I need a simple POJO:

public class User {
    private Integer usrId;

    private String usrName;

    private String usrFname;
[...]
}

Now, the Dao, it will be responsible of accessing the MyBatis Mapper, and it will need to be able to manage all the Mapper, it’s why I defined a new interface which will contain the CRUD method:

public interface Mapper<T> {

    List<T> findAll();
    int insert(T record);
    T selectByPrimaryKey(Integer id);
    void updateByPrimaryKey(T object);
    void deleteByPrimaryKey(Integer id);

}

The MyBatis interface must now implement this interface specifying the User object:

public interface UserMapper extends Mapper<User>{

    int insert(User record);
    List<User> findAll();
    User selectByPrimaryKey(Integer userId);
    void updateByPrimaryKey(User user);
    void deleteByPrimaryKey(Integer usrId);
}

The Mapper is fine, it can be used by my Dao, in first, I define its interface:

public interface Dao {

    public List findAll();
    public T find(Integer id);
    public T merge(T obj);
    public void delete(T obj);
}

And the implementation which references the generic mapper I want to use:

public class DaoImpl implements Dao{

    protected Mapper mapper;

    public DaoImpl(Mapper mapper) {
        super();
        this.mapper = mapper;
    }

    @Override
    public List findAll() {
        return mapper.findAll();
    }
[...]

there no problem to use the generic T because the real object is only known by the mapper “implementation”

And now the definition of my dao using Spring:

<bean id="userDao" class="net.classnotfound.dao.DaoImpl">
    <constructor-arg index="0" ref= "userMapper"/>
</bean>

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
  <property name="mapperInterface" value="net.classnotfound.mapper.UserMapper" />
  <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

As you can see, the Dao is User agnostic, the Mapper is responsible of accessing the right objet. Now, ma Dao can be used with any Mapper, just by changing the Spring configuration.

But when we speak about CRUD, it’s not only getting the full list of records from the database, we need to be able to insert, update and delete, for that, you often need to add some data as the creation date or update date.
Usually, using JPA/Hibernate, I used a @PreUpdate or @PrePersist, but they are part of the JPA specifications, I cannot use it.
It’s why I decided to create some new interface to be able to acces to this particular fields.
For that, I defined 4 new interfaces, I will just present 2 of them but you can imagine the others:

public interface Identifiable {

    Integer getId();
    void setId(Integer id);
}
public interface Updatable {

    void setUpdateDate(Date date);
}

My user class must now implement these interfaces:

public class User implements Identifiable, Deletable, Updatable, Creatable

I can now add the update method in my DAO:

    @Override
    public T merge(T obj) {
        if(!(obj instanceof Identifiable)) 
            throw new IllegalArgumentException("The object is not instance of Identifiable and cannot be updated!");
        Identifiable idable =  (Identifiable)obj;
        if (idable.getId()==null) {
            if (!(obj instanceof Creatable))
                throw new IllegalArgumentException("The object is not instance of Creatable and cannot be inserted!");
            Creatable creatable = (Creatable) obj;
            creatable.setCreationDate(new Date());
            mapper.insert(obj);
        } else {
            if (!(obj instanceof Updatable))
                throw new IllegalArgumentException("The object is not instance of Updatable and cannot be updated!");
            Updatable updtable = (Updatable) obj;
            updtable.setUpdateDate(new Date());
            mapper.updateByPrimaryKey(obj);
        }
        return obj;
    }

I need to cast the T object to be able to access to the related method.

When it is done for all the CRUD method, I have to use it in my service layer, the problem remains as I want to avoid the duplication of code.
It means that my service must be also

public interface Service<t> {
     
    List<t> findAll();
    T find(Integer id);
    T merge(T t);
    void delete(T t);
    void setDao(Dao<t> dao);
 
    Dao<t> getDao();
}

The service implementation looks like:

public class ServiceImpl<t> implements Service<t>{
 
    private Dao<t> dao;
     
    @Override
    public List<t> findAll() {
        List<t> objects = dao.findAll();
        return objects;
    }
    @Override
    @Transactional
    public T find(Integer id) {
        T user = dao.find(id);
        return user;
    }
    @Override
    @Transactional
    public T merge(T object) {
        dao.merge(object);
         
        return object;
    }
[...]    
    @Override
    public void setDao(Dao<t> dao) {
        this.dao = dao;
         
    }
    @Override
    public Dao<t> getDao() {
        return dao;
    }

And the service declaration, in the Spring configuration:

    <bean id="userService" class="net.classnotfound.ServiceImpl">
        <property name="dao" ref="userDao"/>
    </bean>

In the same way as the Dao, my service in now Dao agnostic, I can create different services just using the Spring configuration, I will now have the time drink a coffee instead of repeating the same code in several classes 🙂

Done!

Bitronix configuration

After a first attempt to configure the JBoss transaction manager including  JMS, I finally decided to try the Bitronix transaction manager.

Here is the detail of the configuration.

First of all, you need to add the bitronix jars to your project, using Maven, it’s done very easily (unlike JBossTS, which needs a lot of different dependencies):

<dependency>
    <groupId>org.codehaus.btm</groupId>
    <artifactId>btm</artifactId>
    <version>2.1.3</version>
</dependency>

Now, the configuration, using Spring, as usual (you can retrieve some elements I used with the Narayana configuration:

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

    <!-- enable transaction demarcation with annotations -->
    <tx:annotation-driven/>
    <tx:jta-transaction-manager/> 

    <!--  Bitronix Transaction Manager embedded configuration -->
    <bean id="btmConfig" factory-method="getConfiguration" class="bitronix.tm.TransactionManagerServices">
        <property name="serverId" value="spring-btm" />
        <property name="DefaultTransactionTimeout" value="300" />
    </bean>

    <!-- create BTM transaction manager -->
    <bean id="bitronixTransactionManager" factory-method="getTransactionManager"
        class="bitronix.tm.TransactionManagerServices" depends-on="btmConfig" destroy-method="shutdown" />

    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" >
        <property name="transactionManager" ref="bitronixTransactionManager"/>
        <property name="userTransaction" ref="bitronixTransactionManager"/>
    </bean>

<!-- Datasource config -->
    <bean id="dataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource" init-method="init" destroy-method="close">
        <property name="className" value="com.informix.jdbcx.IfxXADataSource" />
        <property name="uniqueName" value="expElecCliCoredb" />
        <property name="maxPoolSize" value="5" />
        <property name="driverProperties">
            <props>
                <prop key="user">${user}</prop>
                <prop key="password">${pwd}</prop>
                <prop key="serverName">${serverName}</prop>
                <prop key="databaseName">${database}</prop>
                <prop key="portNumber">${port}</prop>
                <prop key="ifxIFXHOST">${host}</prop>
                <prop key="ifxIFX_LOCK_MODE_WAIT">5</prop>
                <prop key="ifxIFX_XASPEC">Y</prop>
                <prop key="ifxDB_LOCALE">en_us.819</prop>
            </props>
        </property>
    </bean>

    <!-- XA JMS Connection Factory, ensure that the jms server has been yet created (with depends-on or order definitions) 
    otherwise the factory is not available and you will receive an exception 
    (javax.jms.JMSException: error looking up wrapped XAConnectionFactory at /XAConnectionFactory)-->
    <bean id="xaJmsConnectionFactory" class="bitronix.tm.resource.jms.PoolingConnectionFactory"
        init-method="init" destroy-method="close">
        <property name="className" value="bitronix.tm.resource.jms.JndiXAConnectionFactory" />
                <property name="uniqueName" value="jmsConnectionFactory" />
        <property name="minPoolSize" value="10" />
        <property name="maxPoolSize" value="10" />
        <property name="driverProperties">
            <props>
                <prop key="name">/XAConnectionFactory</prop>
            </props>
        </property>
    </bean>

    <!--     The producer sends the messages to be processed on the queue -->
    <bean id="notificationsProducer" class="net.classnotfound.cli.core.service.component.NotificationsProducer">
        <property name="connectionFactory" ref="xaJmsConnectionFactory"/>
        <property name="notificationsQueue" ref="notificationsQueue"/>
    </bean>

    <bean id="notificationService" class="net.classnotfound.core.service.NotificationServiceImpl">
        <property name="authorMapper" ref="authorMapper"/>
        <property name="notificationsProducer" ref="notificationsProducer"/>
    </bean>
</beans>

Concerning this configuration, we can see that the way we configure the datasources is almost the same for database as for JMS. The tricky part comes from HornetQ which creates the JMS connection factory but we cannot access it as a standard Spring bean. It’s why we have to get it from JNDI, resulting in a different configuration using dedicated Bitronix component: bitronix.tm.resource.jms.JndiXAConnectionFactory.

This connection factory is now used by the JMS producer. When we send a JMS message, this call is proxied by Bironix to enlist this action in the transaction.

To start the transaction, we do it as usual using the well-known @Transactional annotation. Doing this, the transaction is automatically started, and when we send the JMS message, it is included in the transaction.

Here an example of its usage:

    public void sendNotification(final String message) throws Exception {
        notificationsQueueConnection = connectionFactory.createConnection();
        notificationsQueueSession = notificationsQueueConnection.createSession(true, 0);
        notificationsQueueProducer = notificationsQueueSession.createProducer(notificationsQueue);

        TextMessage textMessage = notificationsQueueSession.createTextMessage(message);
        notificationsQueueProducer.send(textMessage);
    }

It’s important to note that the session is created in the send method, because following the JMS specification, “Any call to the Connection.createSession method must take place within the transaction”. I tried to create the session in a @PostConstruct, there is no error, you can send your message but… Nothing happens 🙁

Done!

Improve server startup using Informix and MyBatis

Working on a project with an Informix database and using MyBatis as the persistence layer, I noted that the start-up of the server takes a long time (about 2 minutes). It is not really a problem if the performance of the application are good, as you don’t start your server all the day, but when you are in the implementation phase…
After step-by-step execution, I discovered that MyBatis gathers the metadata of the database to adapt its behavior, but this part was responsible of the delay (maybe Informix specific?).
I decided to replace this step, fortunately, using MyBatis with Spring, it’s not really a big deal 🙂
As the main purpose of this step is to identify the database provider, I defined a class which returns always the same information: Informix database.

  1. first, you need to define a new DatabaseIdProvider:
    public class IfxDatabaseIdProvider 
            implements org.apache.ibatis.mapping.DatabaseIdProvider {
      
      private static final Log log = LogFactory.getLog(IfxDatabaseIdProvider.class);
    
      private Properties properties;
      
      public String getDatabaseId(DataSource dataSource) {
        
        return "Informix Dynamic Server";
      }
    
      public void setProperties(Properties p) {
        this.properties = p;
      }
    
      public Properties getProperties() {
        return properties;
      }
    }
    
  2. now, you need to tell to MyBatis to use the new class, your Spring config file looks like:

        <bean id="ifxDatabaseIdProvider" 
            class="myPackage.IfxDatabaseIdProvider"/>
        
        <bean id="sqlSessionFactory" 
            class="org.mybatis.spring.SqlSessionFactoryBean">
          <property name="dataSource" ref="dataSource" />
          <property name="mapperLocations" value="classpath:mapper/*Mapper.xml"/>
          <property name="databaseIdProvider" ref="ifxDatabaseIdProvider"/>
        </bean>
    

Done!