Saturday, June 30, 2007

Spring And Hibernate

Spring can simplify your Hibernate application. Spring's Hibernate integration uses the same generic transaction infrastructure and DAO exception hierarchy that it uses for JDBC, JDO, iBATIS, and TopLink, making it easy to mix and match persistence methodologies if necessary.

There are two approaches to Spring's Hibernate integration:

  1. Inversion of Control with a HibernateTemplate and Callback
  2. Extending HibernateDaoSupport and Applying an AOP Interceptor

The IoC/HibernateTemplate methodology feels a lot like the JdbcTemplate methodology described in the last section. For this example, I will show the HibernateDaoSupport/AOP Interceptor approach.

After you have written your standard Hibernate mappings, there basically three things that you need to do to use Spring's HibernateDaoSupport to implement a DAO:

 

  1. Configure the Hibernate SessionFactory
  2. Extend your DAO Implementation from HibernateDaoSupport
  3. Wire in Transaction Support with AOP

So let's do another implementation of the WidgetDAO using Hibernate. First of all, here is our Hibernate XML mapping for the Widget class:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping SYSTEM
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.sample.springrecipes.model">
  <class name="Widget" table="WIDGETS">
    <id name="id" column="WIDGET_ID" type="long">
      <generator class="native"/>
    </id>
    <property name="name" column="NAME" type="string"/>
    <property name="size" column="SIZE" type="int"/>
  </class>
</hibernate-mapping> 
 

If you've used Hibernate before, there should be nothing tricky here since Widget is a trivial class (there are no collections or other classes to associate to). So now we can wire up the Hibernate SessionFactory

Configuring the Hibernate SessionFactory in Spring

Here is an example Hibernate SessionFactory configured in Spring. You will be using this instead of the typical hibernate-config.xml. All we are doing here is telling Hibernate/Spring what our Hibernate mapping files are:

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  <property name="mappingResources">
    <list>
      <value>com/sample/springrecipes/base/Widget.hbm.xml</value>
    </list>
  </property>
</bean>

If you have a hibernate.properties in your classpath, the Spring LocalSessionFactoryBean will use that file to configure the database connections, dialect and pooling. Alternatively, you can define a DataSource in Spring (any class that implements javax.sql.DataSource) and explicity set all of your Hibernate properties in the LocalSessionFactoryBean:

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  <property name="mappingResources">
    <list>
      <value>com/sample/springrecipes/base/Widget.hbm.xml</value>
    </list>
  </property>
  <property name="hibernateProperties">
    <props>
      <prop key="hibernate.dialect">
        org.hibernate.dialect.HSQLDialect
      </prop>
    </props>
  </property>
  <property name="dataSource">
    <ref bean="dataSource"/>
  </property>
</bean>

<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName">
    <value>org.hsqldb.jdbcDriver</value>
  </property>
  <property name="url">
    <value>jdbc:hsqldb:mem:widgets</value>
  </property>
  <property name="username"><value>sa</value></property>
  <property name="password"><value></value></property>
</bean>

Extending HibernateDaoSupport for the Actual DAO Implementation

The Spring HibernateDaoSupport class provides all kinds of convenience methods for working with Hibernate. Most of these are accessible via the HibernateTemplate object that this class exposes. Please note that Hibernate 2 throws checked HibernateExceptions and Hibernate 3 throws runtime exceptions. I am using Hibernate 3 and am blowing off runtime exceptions that might be thrown, but it might be more appropriate to deal with these exceptions here (this is just a example, not prduction code!) Anyway, here is our WidgetDAO implemented by extending HibernateDaoSupport:
public class WidgetDAOHibernateImpl 
              extends HibernateDaoSupport 
              implements WidgetDAO
{
  /**
   * Returns a java.util.List of all Widgets in the system.
   * @return
   */
  public Collection getWidgets()
  {
    return getHibernateTemplate().loadAll(Widget.class);
  }

  /**
   * Get a Widget Object given the id
   * @param id
   * @return
   */
  public Widget getWidgetById(Long id)
  {
    return (Widget)
            getHibernateTemplate().load(Widget.class, id); 
  }

  /**
   * Save a Widget Object, if the given Widget
   * is not in the data store,it should insert it,
   * if it is in the data store, it should update it.
   * @param widget
   */
  public Widget saveWidget(Widget widget)
  {
    getHibernateTemplate().saveOrUpdate(widget);
    return widget;
  }
}

Using AOP to Wire Up the DAO and Transaction Management

Now we wire up our DAO and weave in the HibernateInterceptor. This interceptor binds a new Hibernate Session to the thread before a method call, closing and removing it afterwards in case of any method outcome. If there already is a pre-bound Session, the interceptor simply participates in it. Note that the actual "widgetDAO" bean is defined as a proxy bean that really points to a bean called "widgetDaoTarget" which is where we wire up our actual implementation.
<!-- THE HIBERNATE INTERCEPTOR -->
<bean id="hibernateInterceptor"
class="org.springframework.orm.hibernate3.HibernateInterceptor">
  <property name="sessionFactory">
    <ref bean="sessionFactory"/>
  </property>
</bean>

<bean id="widgetDaoTarget"
class="com.sample.springrecipes.hibernate.WidgetDAOHibernateImpl">
  <property name="sessionFactory">
    <ref bean="sessionFactory"/>
  </property>
</bean>

<bean id="widgetDAO"
  class="org.springframework.aop.framework.ProxyFactoryBean">
  <property name="proxyInterfaces">
    <value>com.sample.springrecipes.base.WidgetDAO</value>
  </property>
  <property name="interceptorNames">
    <list>
      <value>hibernateInterceptor</value>
      <value>widgetDaoTarget</value>
    </list>
  </property>
</bean>

Summary

Spring can simplify your Hibernate code. Transactions can be wired in with AOP services provided by Spring.

More fun with Spring scopes / Java

Previous blog about custom scopes has shown an example of the thread-bound scopes (conversations that hold state per thread and live longer then request). This time I would like to show another interesting application for the custom bean scopes. In this case conversation is bound to the page in web application (or even to each unique set of request parameters for that page). Practical examples include per-page caching of the static data (i.e. for Ajax use), allow page visitors to interact or edit page content together and many others... Note that this post should be used as a starting point and may require some additional tweaking for more specific scenarios. Now let's look at the implementation.

First step is to capture the conversation identity. In general, several page urls may need to be mapped to the same scope identity, or even require special mapping from request url to the view. But for the sake of this illustration I will assume that each request url uniquely identifying the scope. Then I can use servlet Filter, which can be registered in web.xml and run before, Spring's own DispatcherServlet. This filter will store requestURI in thread local and provide static accessor method for retrieving that value.

public class PageScopeFilter implements Filter {
  private static ThreadLocal conversation = new ThreadLocal();
  
  public void doFilter(ServletRequest request, ServletResponse response,
      FilterChain chain) throws IOException, ServletException {
    String conversationId = null;
    if (request instanceof HttpServletRequest) {
      conversationId = ((HttpServletRequest) request).getRequestURI();
    }
    conversation.set(conversationId);
    try {
      chain.doFilter(request, response);
    } finally {
      conversation.remove();
    }
  }

  public void init(FilterConfig config) throws ServletException {
  }

  public void destroy() {
  }
}  

Now, the PageScope implementation is rather trivial. Just maintain scope map of bean names to actual instances.

public class PageScope implements Scope {
  private final Map scope = new HashMap();
  
  private static final ObjectFactory MAP_FACTORY = new ObjectFactory() {
      public Object getObject() {
        return new HashMap();
      }
    };

  public String getConversationId() {
    return PageScopeFilter.getConversationId();
  }

  public synchronized Object get(String name, 
      ObjectFactory objectFactory) {
    Map beanMap = (Map) get(scope, getConversationId(), MAP_FACTORY);
    return get(beanMap, name, objectFactory);
  }

  public synchronized Object remove(String name) {
    Map beanMap = (Map) scope.get(getConversationId());
    return beanMap==null ? null : beanMap.remove(name);
  }
  
  public void registerDestructionCallback(String name, Runnable callback) {
    //
  }
  
  private Object get(Map map, String name, ObjectFactory factory) {
    Object bean = map.get(name);
    if(bean==null) {
      bean = factory.getObject();
      map.put(name, bean);
    }
    return bean;
  }
}

Note how ObjectFactory is used to construct a place holder for new conversation.

That is basically it. My first blog already shown how to register custom scopes, please refer there if you need more details, or feel free to ask question in comments for this post. Obvious enhancement of the above PageScope implementation could be to make it implement DisposableBean and hook with registered destruction callbacks, but I leave that exercise to the reader curiosity.

There is one more thing worth to mention. In case if page-bound data is mutable, in clustered environment, one may need to make it consistent across all cluster nodes. The one easy way to achieve that could be to use Terracotta for Spring, which has been recently open sourced.


Original article by Eugene Kuleshov

Implementing an efficient Id generator with Spring framework / Java

Unique identity generators are heavily used in the enterprise applications. Most often applications rely on the database features, such as sequences or auto incremented columns. Unfortunately, that requite extra trips to the database and as a result have impact on performance. The good news that there are few simple optimizations that can be used to significantly reduce this overhead. Let's see how we can use Spring framework to assemble high performance id generator. I'll introduce a basic abstraction for id generator. Note a "granularity" parameter, that will be explained shortly.

public interface IdGenerator {
  
  public long getNextId(int granularity);
  
}

A naïve in-memory IdGenerator implementation may look something like one below and it would perform extremely well in a multi threaded environment.

public class SimpleIdGenerator implements IdGenerator {

  private AtomicLong id = new AtomicLong(0L);
  
  public long getNextId(int granularity) {
    return id.getAndAdd(granularity);
  }
}

In a real world application, generators rely on the id feed generated by relational database database. That affects performance because of transactional requirements and round trips to the database. As mentioned above, those issues can be worked around using well known optimizations that are used by application server providers and supported by most of the database vendors. So, instead of requesting new id from the database on every call, we can request a range of ids and save on database calls. Here is when we can make use of the "granularity" parameter passed to the getNextId() method. This logic can be factored out into a separate component and applied to the original generator using Spring AOP or delegation/proxy pattern. Using spring XML configuration we can assemble these beans together:

  <bean id="idGenerator" class="org.javatx.spring.BatchingIdGenerator">
    <constructor-arg ref="simpleIdGenerator"/>
  </bean>

  <bean id="simpleIdGenerator" class="org.javatx.spring.SimpleIdGenerator"/>

A very naïve implementation of BatchingIdGenerator may look something like this.

public class BatchingIdGenerator implements IdGenerator {

  private IdGenerator generator;
  private int batchSize = 100;
  
  private long current = 0;
  private long max;
  
  public BatchingIdGenerator(IdGenerator generator) {
    this.generator = generator;
  }

  public void setBatchSize(int batchSize) {
    this.batchSize = batchSize;
  }
  
  public long getNextId(int granularity) {
    current += granularity;
    if(current>max) {
      current = generator.getNextId(batchSize);
      max = current + batchSize;
    }
    return current;
  }

}

At minimum, above IdGenerator implementation require synchronization on getNextId() method in order to work properly in multi threaded environment. Unfortunately, that will introduce locking contention and will not perform well under load. However there is a simple solution for this issue. With Spring 2.0 we can use custom bean scope for idGenerator bean. If we make this custom scope bound to the thread, it will completely eliminate needs for locking, because each thread will use its own batch of ids. I opened JIRA issue SPR-2581 to provide "out of the box" implementation for the thread scope in Spring framework. In a mean time the thread-bound scope can be implemented using ThreadLocal.

public class ThreadScope implements Scope {

  private final ThreadLocal threadScope = new ThreadLocal() {
      protected Object initialValue() {
        return new HashMap();
      }
    };
  
  public Object get(String name, ObjectFactory objectFactory) {
    Map scope = (Map) threadScope.get();
    Object object = scope.get(name);
    if(object==null) {
      object = objectFactory.getObject();
      scope.put(name, object);
    }
    return object;
  }

  public Object remove(String name) {
    Map scope = (Map) threadScope.get();
    return scope.remove(name);
  }

  public void registerDestructionCallback(String name, Runnable callback) {
  }
}

The last piece of this puzzle is to assemble everything in Spring config.

<beans 
  xmlns="http://www.springframework.org/schema/beans" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:aop="http://www.springframework.org/schema/aop"
  xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

  <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
    <property name="scopes">
      <map>
        <entry key="thread" value="org.javatx.spring.ThreadScope"/>
      </map>
    </property>
  </bean>

  <bean id="idGenerator" class="org.javatx.spring.BatchingIdGenerator" scope="thread">
    <constructor-arg ref="simpleIdGenerator"/>
    <aop:scoped-proxy/>
  </bean>

  <bean id="simpleIdGenerator" class="org.javatx.spring.SimpleIdGenerator"/>

</beans>

Custom "thread" scope is registered using CustomScopeConfigurer factory bean and then assigned to the idGenerator bean using "scope" attribute in the bean definition. Also note that "aop:scoped-proxy" element is used to wrap bean into the scope-aware proxy in order to make it work when idGenerator bean is injected into the other beans as dependency.


By Eugene Kuleshov

Twelve Best Practices For Spring XML Configurations

Spring is a powerful Java application framework, used in a wide range of Java applications. It provides enterprise services to Plain Old Java Objects (POJOs). Spring uses dependency injection to achieve simplification and increase testability. Spring beans, dependencies, and the services needed by beans are specified in configuration files, which are typically in an XML format. The XML configuration files, however, are verbose and unwieldy. They can become hard to read and manage when you are working on a large project where many Spring beans are defined.

In this article, I will show you 12 best practices for Spring XML configurations. Some of them are more necessary practices than best practices. Note that other factors, such as domain model design, can impact the XML configuration, but this article focuses on the XML configuration's readability and manageability.

1. Avoid using autowiring


Spring can autowire dependencies through introspection of the bean classes so that you do not have to explicitly specify the bean properties or constructor arguments. Bean properties can be autowired either by property names or matching types. Constructor arguments can be autowired by matching types. You can even specify the autodetect autowiring mode, which lets Spring choose an appropriate mechanism. As an example, consider the following:

<bean id="orderService" class="com.lizjason.spring.OrderService" autowire="byName"/>

The property names of the OrderService class are used to match a bean instance in the container. Autowiring can potentially save some typing and reduce clutter. However, you should not use it in real-world projects because it sacrifices the explicitness and maintainability of the configurations. Many tutorials and presentations tout autowiring as a cool feature in Spring without mentioning this implication. In my opinion, like object-pooling in Spring, it is more a marketing feature. It seems like a good idea to make the XML configuration file smaller, but this will actually increase the complexity down the road, especially when you are working on a large project where many beans are defined. Spring allows you mix autowiring and explicit wiring, but the inconsistency will make the XML configurations even more confusing.

2. Use naming conventions


This is the same philosophy as for Java code. Using clear, descriptive, and consistent name conventions across the project is very helpful for developers to understand the XML configurations. For bean ID, for example, you can follow the Java class field name convention. The bean ID for an instance of OrderServiceDAO would be orderServiceDAO.For large projects, you can add the package name as the prefix of the bean ID.

3. Use shortcut forms


The shortcut form is less verbose, since it moves property values and references from child elements into attributes. For example, the following:

<bean id="orderService" class="com.lizjason.spring.OrderService">
<property name="companyName">
<value>lizjason</value>
</property>
<constructor-arg>
<ref bean="orderDAO">
</constructor-arg>
</bean>

can be rewritten in the shortcut form as:

<bean id="orderService" class="com.lizjason.spring.OrderService">
<property name="companyName" value="lizjason"/>
<constructor-arg ref="orderDAO"/>
</bean>

The shortcut form has been available since version 1.2. Note that there is no shortcut form for <ref local="...">.

The shortcut form not only saves you some typing, but also makes the XML configuration files less cluttered. It can noticeably improve readability when many beans are defined in a configuration file.

4. Prefer type over index for constructor argument matching


Spring allows you to use a zero-based index to solve the ambiguity problem when a constructor has more than one arguments of the same type, or value tags are used. For example, instead of:

<bean id="billingService" class="com.lizjason.spring.BillingService">
<constructor-arg index="0" value="lizjason"/>
<constructor-arg index="1" value="100"/>
</bean>

It is better to use the type attribute like this:

<bean id="billingService" class="com.lizjason.spring.BillingService">
<constructor-arg type="java.lang.String" value="lizjason"/>
<constructor-arg type="int" value="100"/>
</bean>

Using index is somewhat less verbose, but it is more error-prone and hard to read compared to using the type attribute. You should only use index when there is an ambiguity problem in the constructor arguments.

5. Reuse bean definitions, if possible


Spring offers an inheritance-like mechanism to reduce the duplication of configuration information and make the XML configuration simpler. A child bean definition can inherit configuration information from its parent bean, which essentially serves as a template for the child beans. This is a must-use feature for large projects. All you need to do is to specify abstract=true for the parent bean, and the parent reference in the child bean. For example:

<bean id="abstractService" abstract="true" class="com.lizjason.spring.AbstractService">
<property name="companyName" value="lizjason"/>
</bean>

<bean id="shippingService" parent="abstractService" class="com.lizjason.spring.ShippingService">
<property name="shippedBy" value="lizjason"/>
</bean>

The shippingService bean inherits the value lizjason for the companyName property from the abstractService bean. Note that if you do not specify a class or factory method for a bean definition, the bean is implicitly abstract.

6. Prefer assembling bean definitions through ApplicationContext over imports


Like imports in Ant scripts, Spring import elements are useful for assembling modularized bean definitions. For example:

<beans>
<import resource="billingServices.xml"/>
<import resource="shippingServices.xml"/>
<bean id="orderService" class="com.lizjason.spring.OrderService"/>
<beans>

However, instead of pre-assembling them in the XML configurations using imports, it is more flexible to configure them through the ApplicationContext. Using ApplicationContext also makes the XML configurations easy to manage. You can pass an array of bean definitions to the ApplicationContext constructor as follows:

String[] serviceResources = {"orderServices.xml", "billingServices.xml",
    "shippingServices.xml"};
ApplicationContext orderServiceContext = new ClassPathXmlApplicationContext(serviceResources);

7. Use ids as bean identifiers


You can specify either an id or name as the bean identifier. Using ids will not increase readability, but it can leverage the XML parser to validate the bean references. If ids cannot be used due to XML IDREF constraints, you can use names as the bean identifiers. The issue with XML IDREF constraints is that the id must begin with a letter (or one of a few punctuation characters defined in the XML specification) followed by letters, digits, hyphens, underscores, colons, or full stops. In reality, it is very rare to run into the XML IDREF constraint problem.

8. Use dependency-check at the development phase


You can set the dependency-check attribute on a bean definition to a value other than the default none, such as simple, objects, or all, so that the container can do the dependency validation for you. It is useful when all of the properties (or certain categories of properties) of a bean must be set explicitly, or via autowiring.

<bean id="orderService" class="com.lizjason.spring.OrderService" dependency-check="objects">
<property name="companyName" value="lizjason"/>
<constructor-arg ref="orderDAO"/>
</bean>

In this example, the container will ensure that properties that are not primitives or collections are set for the orderService bean. It is possible to enable the default dependency check for all of the beans, but this feature is rarely used because there can be beans with properties that don't need to be set.

9. Add a header comment to each configuration file


It is preferred to use descriptive ids and names instead of inline comments in the XML configuration files. In addition, it is helpful to add a configuration file header, which summarizes the beans defined in the file. Alternatively, you can add descriptions to the description element. For example:

<beans>
<description>
This file defines billing service
related beans and it depends on
baseServices.xml,which provides
service bean templates...
</description>
...
</beans>

One advantage of using the description element is that it is easy to for tools to pick up the description from this element.

10. Communicate with team members for changes


When you are refactoring Java source code, you need to make sure to update the configuration files accordingly and notify team members. The XML configurations are still code, and they are critical parts of the application, but they are hard to read and maintain. Most of the time, you need to read both the XML configurations and Java source code to figure out what is going on.

11. Prefer setter injection over constructor injection


Spring provides three types of dependency injection: constructor injection, setter injection, and method injection. Typically we only use the first two types.

<bean id="orderService" class="com.lizjason.spring.OrderService">
<constructor-arg ref="orderDAO"/>
</bean>

<bean id="billingService" class="com.lizjason.spring.BillingService">
<property name="billingDAO" ref="billingDAO">
</bean>

In this example, the orderService bean uses constructor injection, while the BillingService bean uses setter injection. Constructor injection can ensure that a bean cannot be constructed in an invalid state, but setter injection is more flexible and manageable, especially when the class has multiple properties and some of them are optional.

12. Do not abuse dependency injection


As the last point, Spring ApplicationContext can create Java objects for you, but not all Java objects should be created through dependency injection. As an example, domain objects should not be created through ApplicationContext. Spring is an excellent framework, but, as far as the readability and manageability are concerned, the XML-based configuration can become an issue when many beans are defined. Overuse of dependency injection will make the XML configuration more complicated and bloated. Remember, with powerful IDEs, such as Eclipse and IntelliJ, Java code is much easier to read, maintain, and manage than XML files!

Conclusion


XML is the prevailing format for Spring configurations. XML-based configuration can become verbose and unwieldy when many beans are defined. Spring provides a rich set of configuration options. Appropriately using some of the options can make the XML configurations less cluttered, but other options, like autowiring, may reduce readability and maintainability. Following good practices discussed in the article may help you to create clean and readable XML configuration files!

 


By Jason Zhicheng Li

Tuesday, June 26, 2007

Configuration-hell remedy with Singleton injection

One of the most heard complaints about Spring projects is the seemingly unavoidable configuration-hell that silently creeps in every bigger project after some time.
Singleton injection is a simple practice that can significantly reduce configuration and corresponding injection code. Besides that, it provides possibilities you might not have been aware of enabling you to get most out of Spring. In this blog you will learn which advantages Singleton injection provides. It illustrates how to implement it and specifies clear guidelines in which circumstances it is applied best.
Where applicable, Singleton injection can be an elegant solution that provides significant code and configuration simplification.
At the beginning of a Spring project, when the applicationContext.xml(s) resemble a fallow field, it is easy to keep the overview of your beans. As time goes by most of us have been facing the configuration-hell growing out of proportion, making it difficult to find your way in the bean jungle. There are several commonly applied best-practices to postpone this problem as long as possible, such as the usage of abstract declarations, splitting up the bean configuration in several subconfigurations or Eclipse’s Spring IDE.
Besides that I have come across another way, which can significantly contribute to reduce spring configuration, eliminate superfluous code and provide other interesting advantages you might not have been aware of before. The way to achieve that is called Singleton injection.

The familiar way

Consider the following piece of code and configuration:
public class AnyService {
    private Logger log = Logger.getLogger(AnyService.class);
    private MessageResource messageResouce;

    public setMessageResource(MessageResource messageResouce) {
        this.messageResouce = messageResouce;
    }
    public void execute() {
        if(condition)
            log.error(messageResource.getMessage("error.msg.key.1"));
        //  more code 
    }
}

public class AnyDAO {
    private Logger log = Logger.getLogger(AnyDAO.class);
    private MessageResource messageResouce;

    public setMessageResource(MessageResource messageResouce) {
        this.messageResouce = messageResouce;
    }

    public List findAll() {
        if(condition)
            log.warn(messageResource.getMessage("error.msg.key.2"));
        //more code
    }
}
<!-- configuration -->
<!-- message resource implementation -->
<bean id="messageResource" class="com.xebia.example.MessageResourceImpl">
    property name="resourceLocation" value="classpath:/bundle.properties"/>
</bean>

<!-- classes using the message resource -->
<bean id="aService" class="AnyService">
    <property name="messageResource" ref="messageResource"/>
</bean>
<bean id="aDAO" class="AnyDAO">
    <property name="messageResource" ref="messageResource"/>
</bean>
<!-- ...and many more -->
Apparently, the MessageResource class is used throughout the application, actually by each class that needs to log something. Since we want to initialize the MessageResource class with the proper configuration with the BeanFactory facilities, we configure the MessageResource class as a spring bean and inject it in every class that makes use of it. The latter is followed by tedious instance variable/setter code and injection configuration. This should sound familiar to you.

The alternative: Singleton injection

Fortunately, there is an easier way. Consider the following piece of code:
public class AnyService {
    private Logger log = Logger.getLogger(AnyService.class);

    public void execute() {
        if(condition)
            Log.error(MessageResourceSingleton.getInstance().getMessage(“error.msg.key.1”));
        //  more code 
    }
}
As you can see, most of the spring-related injection hassle seems to have disappeared. At least, that might be the first impression. Instead of cumbersomely injecting the MessageResource bean in all classes that use it, we take a slightly different approach:
1. We write a wrapper class applying the Singleton pattern (here MessageResourceSingleton) that wraps an implementation of the MessageResource class
2. Then add configuration that injects the implementation (MessageResource) into the Singleton wrapper (MessageResourceSingleton)
The following code and configuration illustrates the Singleton injection approach:
public class MessageResourceSingleton implements MessageResource{

    /** MessageResource implementation to be injected  */
    private MessageResource messageResource;
   
    /** singleton instance */
    private static MessageResourceSingleton singleton = new MessageResourceSingleton();
    /**
     * Gets singleton
     * @return singleton
     */
    public static MessageResourceSingleton getInstance(){
        return singleton;
    }
    /**
     * Setter for the MessageResource implementation used to inject
     * the implementation
     * @param messageResource
     */
    public void setMessageResource(MessageResource messageResource) {
        this.messageResource = messageResource;
    }
    /**
     * Delegates the call to the injected implementation
     * @param args arguments
     * @return message
     */
    public String getMessage(String key) {
        return messageResource.getMessage(key);
    }
}
<!-- configuration -->
<!--  Singleton that gets the message resource implementation injected. Note the usage of factory-method. The factory-method calls the static method getInstance() of the singleton returning the singleton instance -->
<bean id="singleton" class="com.xebia.example.MessageResourceSingleton" factory-method="getInstance">
    <property name="messageResource" ref="messageResource"/>
</bean>

<!-- message resource implementation -->
<bean id="messageResource" class="com.xebia.example.MessageResourceImpl">
    <property name="resourceLocation" value="classpath:/bundle.properties"/>
</bean>


Any class that wants to use the MessageResource implementation simply calls:
MessageResourceSingleton.getInstance().getMessage(“any.key”);

By doing so, we can use all the configuration power spring provides when defining the implementation bean. The code, which uses the implementation, is not only freed of superfluous injection code and corresponding configuration but is – as the IoC principle demands –totally unaware that Spring is pulling the strings (or beans ;-) ).

Your gains with Singleton injection

So, when using Singleton injection these are your gains:
  • Reduced configuration and less code (inject once use everywhere)
  • Injected Singletons can be used in classes that are not part of the beanwiring chain
  • Static methods can use injected Singletons
  • Injected Singletons can serve as beanwiring starting points
  • Increased productivity (instant usage of injected code)

Since it all seems so simple, practical and advantageous, why not use Singleton injection everywhere in you code?

When to use Singleton injection

The tradeoff when considering Singleton injection is simplicity versus flexibility. The constraint is that the Singleton can only wrap one specific implementation. Therefore, every class that makes use of the Singleton wrapper will have to stick with this particular implementation. You still can have several implementations available (for unittesting, mocking etc.) but at runtime only one of these can be used throughout the application.
In other words, when you face a “one size fits all” scenario you have a case for a Singleton injection. In more detail, the following preconditions have to be present in order to make Singleton injection a useful choice:
  • A spring bean is used in various, peripheral parts of the application
  • A spring bean has the characteristics of an utility class that needs to be initialized with external resources or other parameters
  • A spring bean has to be accessible by classes that are not part of the beanwiring chain
  • It is sufficient that at runtime only one specific implementation of the spring bean is used throughout the application

Real world cases for Singleton injection

I have used Singleton injection on various projects. The following type of classes have proven to be an excellent candidate for Singleton injection:
  • MessageResource utility like the one used in this example
  • Logger utility that needs to perform logging to a database or queue
  • IDGenerator that gets id’s used for logging or messaging from a database
  • CodeMapper that maps technical codes to a description
  • Business Delegate, which can be used as startingpoint of the beanwiring
  • Any utility you want to use in a framework or component, which does not provide hooks to inject spring beans (in case they are still out there…)

Conclusion

Where applicable Singleton injection can be an elegant solution that provides significant code and configuration simplification. Additionally, it enables you to profit from “Spring injection power” outside the standard beanwiring chain. All this can be achieved with such a simple thing like Singleton injection. It enables you to do more with less – isn’t this what programming is all about?
By Urs Peter

Sunday, June 24, 2007

Practices on Using Groovy, Beanshell and JRuby in Spring 2.0

I am using Spring 2.0 dynamic language support in my current project, including both Beanshell, Groovy, JRuby and Java. I want to share my experience learnt from my project with others and wish my experience can help them to solve their problems.

Use springframework 2.0.3


The previous version has some problems which are fixed in version 2.0.3. If you only use Groovy, then previous version is ok. But I still recommend to use version 2.0.3.

Great Decopuling and standardize


The most amazing feature of spring 2.0 dynamic language support is decoupling. The client program is decoupled from the implementation programming language of the spring bean class. For example:
...
Validator validator = (Validator)context.getBean("validator") ;
...
The spring bean "validator" can be implemented in either Groovy, Beanshell, JRuby or Java. In Spring 2.0, beans written in Java and beans written in Groovy, Beanshell or JRuby are equal. Client programs use the same getBean method to retrieve both types of bean. You may need to change the implementation language of your bean, but you don't need to change your client program. In my project, there are some legacy Beanshell programs and I am migrating these Beanshell program to Groovy. During migration, the Beanshell programs are replaced by Groovy programs one by one. But I DON'T need to change any client code. Please note the above sample code also can be used in Groovy, Beanshell or JRuby script.

Scripting bean "scope" problem


There is one VERY IMPORTANT attribute of the dynamic language support you must remember. The "scope" of the Groovy, Beanshell and JRuby bean is "singleton" and there is no way to change the scope of the the scripting beans in the application context xml. It can ONLY be "singleton". What wrong with scope "singleton"? Your class variable values will be OVERRIDE or some previous values are still stored in the scripting bean. In the web module my project, it becomes a problem in a multi thread environment. I have submited a request to springframework JIRA for adding a new attribute "script-scope" to allow setting the scope of any script bean and it is assigned to Rick Evan. I don't know whether there is solution or when will the solution be available. At this moment, you must remember the "scope" of all scripting bean is "singleton". Be careful with all the class variables especially in web application.

Autowire the scripting bean requirement


If you want to autowire any scripting bean, Your scripting bean MUST implements a Java Interface. Please note the word "MUST". If your scripting beans do not implements any java interface and you try to inject one scripting bean into another scripting bean as property, your program will throw Exception because springframework cannot use reflection to find the proper set method. Please note that this rule does not apply when inject a pure java object to any scripting bean.

Why Interface for scripting bean is Good


My project requires to use Groovy, Beanshell and JRuby. Interface for scripting bean is my really god blessing. Without the interface for scripting bean, I cannot inject a Groovy script bean to JRuby bean. Without the interface, I cannot use my Groovy script in my Java program. etc... If you only want to use Groovy only, what is the benefit of inteface for scripting bean? Would you like to try to save your Groovy bean into database using Hibernate? It works with some trick. Would you like to use iBatis to load record from database? It works. I have not tested everything but most work. But you must pay the price of creating a java interface.


Beware the catch of loading process of the scripting bean


I will describe the logical process of loading a scripting bean in application context in the following paragraph. It is not the actual program logic. The actual program logic is much much much compilcated.
When ClassPathXmlApplicationContext enounters a scripting bean definition. It will create the script factory. Then setup all the property of the script factory. After the factory is setup, execute the script to create a script object and store this script as singleton. There is a catch in the above process. If your script object incorrectly contains code which will indirectly trigger the creation of application context. Your program will be in an infinite loop and DIE. In the springframework support forum, I had seen a message from Rod Johnson who mentions that the future script factory may use Bean Scripting Factory as the factory. Will this solve this problem? No from my experiment. Beside I found out some strange problem with JRuby BSFEngine. JRuby BSFEngine will return a Java object after execute the script. If the require return class is int, it will always return long and force my program to throw exception.

Lazy-init does not work with scripting bean


No attribute in lang namespace allows lazy-init. So please don't try to lazy-init a scripting bean.

Global settings


Global settings like default-autowire are not inherited by the scripting bean. Need furthur investigate.

Saturday, June 23, 2007

Spring: simple, not simplistic…

During a training last week, for the first time, I used the first Release Candidate of Spring Web Services. It's hardly been two weeks since Arjen release RC1 of his precious, so it was very nice to show some of the attendees this new product.


Right before the web services part we did a little JMX and remoting, showing Spring's exporter functionality. As you might know, this allows you to export any Spring-managed bean to a remote endpoint or JMX registry, with just a very little amount of declarative configuration:



<bean id="myService" class="com.mycompany.MyServiceImpl">

    <property name="myDao" ref="myDao"/>
</bean>

<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
        <property name="serviceName" value="myService"/>
        <property name="serviceInterface" value="com.mycompany.MyService"/>
        <property name="service" ref="myService"/>
</bean>

This is all very easy and is very much in line with what the audience usually thinks about Spring up until now: Spring is making all the stuff that used be very hard so much simpler; it just requires a few lines of XML (or some of the other configuration options that we currently are implementing) and done you are. This is of course true, but it's not the impression that I'd like to see people leaving a Core Spring training with.


Fortunately, in the form of Spring Web Services, Arjen gave me some excellent material to once and for all tell that the way we would like to have you think about Spring is entirely different from 'it's just about adding a few lines of XML and then we're done'. It's not like that!


To get back to the training I conducted last week; we were just done with JMX when I started my usual talk about web services. The short version basically says: web services != remoting, you'd better learn to live with the fact that this means that the amount of stuff you have to do to implement a web service != the amount of stuff you have to do to export a service to an RMI endpoint (I suspect it's very likely that != can in all cases be replaced by >).


What (very pleasantly) surprised me last week however was that one attendee to the training all of a sudden interrupted me and said: 'hey I get it know, the Spring approach is not necessarily about simplifying my code or reducing the amount of code, it's about taking away unnecessary complexity and allowing me to focus on what's important.'.


Dependency Injection and AOP are focused on providing a clean yet powerful approach to injecting dependencies and implementing cross-custting behavior. Modularity and separation of concerns are things that should be easy to achieve and are very important issues. Spring's DI container and the AOP facilities are focused on allowing you to achieve modularity and good separation of concerns. They're not primarily focused on simplifying your code.


Spring's remote exporters are meant to provide a nearly transparent way of calling server-side code from remote locations. When wanting to implement an RMI-based remote endpoint, we're implicitly saying that we want to tightly couple our service to our client. Spring's remote exporters are not designed to do this in just four lines of XML. They were designed to get this nearly transparent programming experience. The fact that it can be done in just four lines of XML, again, is a nice side-effect.

And now the kicker… when we are implementing a web service, implicitly we are saying that we want to loosely couple our service from any potential client that might be using our service. We are not (or should not be) looking for a transparent way to issue method calls using <soap:Envelope> and <soap:Body> tags. Version management, flexibility and the ability to remain backward compatible are key to implementing robust web services that stand the test of time and loosely couple our clients to our service. Spring Web Services was designed to address these issues and to allow you to address them very easily. It was not meant to simplify your code! Although I am very sure that in many scenarios that code that you'll end up with when using Spring Web Services is as simple and understandable as it could possibly be!


I walked to my car with a big smile on my face last Friday. We had ended this training understanding the most important lesson: Spring was not designed to simplify code; it was designed to let you focus on what matters. The code simplification that you get as a side-effect, of course that's something we can all appreciate I am sure!
By Alef Arendsen

So what's the deal with Spring-OSGi?

In this entry, I'd like you give you a glimpse at what Spring 1.0 M1 provides at the moment; I'll skip introducing OSGi since there is plenty of excellent material available on the internet (see the links at the bottom).
The basic idea behind Spring-OSGi is to make it easy to build/write/deploy Spring applications in an OSGi environment. That is, to have the comprehensive POJO based programming model that Spring offers (IoC, AOP, service abstractions) working transparently in a dynamic execution environment which is focused on versioning and modularity.
One of the biggest challenges when adopting OSGi is dealing with its dynamic nature. Services (which are are simple object instances) come and go and your application has to deal with that. The solution is not straight forward, depends from case to case and requires an application-wide scope just like exception handling and transaction do. Classloading restrictions, enforced by the modularity mentioned, combined with AOP can cause a lot of grief and force the developer to create hacks, thus throwing out the window the benefits OSGi provides.
These are just a few examples of the things we are addressing in Spring-OSGi which in the end, should allow a smooth adoption path to OSGi.
Let's take a look at some of the features you'll find in 1.0 M1:

OSGi Application Context


OSGi is based on bundles which are nothing more then jars with some dedicated manifest entries. They are modules, units that export and import class packages and/or services.

An application can be composed of one or multiple bundles. Spring-OSGi provides an application context which builds on top of a bundle and its lifecycle, giving you access to the OSGi context in which the application lives, an OSGi custom scope as well as an extra Aware interface. As the rest of its ilk, the interface provides the ability to do dependency lookup, something you should think twice before using as OSGi service dependency injection is fully supported.

Resource abstraction


Classloading is not what is used to be in OSGi - the classpath for example has a different meaning since it can be assembled from multiple bundles (which in turn, can be used in more then one classpath). Thus getClass().getResource() can have a different outcome as the environment in which are running has changed quite a lot. Here is an example of what you might get in case you are looking for a class:

Equinox: bundleentry://5/my/package/MyClass.class (can be also bundleresource://)
Knopflerfish: bundle://13/my/package/MyClass.class
Felix: bundle://18.0/0/my/package/MyClass.class
Relying on URL schemes is not portable thus one of the first things done in Spring OSGi was to encapsulate low-level access through the simple, yet effective Resource interface, so no matter what OSGi implementation you are using, you can find your files. Moreover, pattern style lookups such as myFolder/* are possible (in fact we are using /META-INF/spring/* to detect 'spring powered' bundles).

Dynamic service support


Suppose you have the following application context:
<!– service layer–>
<bean id="myService" class="ServiceClass">

    <property name="dao" ref="dao"/>
</bean>
<!– dao layer –>

<bean id="dao" class="poorPerformerDAO">
    <property name="dataSource" ref="someDataSource"/>

</bean>


Most of the application have several layers which are excellent candidates for OSGi bundles since one can simply put the DAO classes in one bundle (the dao bundle), the service layer in another (service bundle) so when the DAOs implementations are updated (for example poorPerformerDAO above is replaced with excellentPerformerDAO) or a different version of the application is being deploy, no application restarts are required: one of the best reasons to choose OSGi!
However, to take advantage of the OSGi capabilities, the objects have to become services - that is, they have to be registered with the OSGi platform before being 'consumed' while the consumer (client) has to look for them. It's an SOA-like approach which avoids tight coupling between modules so when a bundle is shut down, the services published by it disappear. Which means that one first has to use the OSGi APIs to do the registration and lookup but also has to deal with failure as services can come and go.
Spring-OSGi greatly helps in this area by allowing literally any type of object to be exported and imported in your application without any code change.
Service Bundle:


<!– service layer–>
<bean id="myService" class="ServiceClass">
    <property name="dao>
       <osgi:reference interface="daoInterface"/>

    </property>
</bean></code> 

DAO Bundle:

<!– dao layer –>
<bean id="dao" class="goodPerformerDAO">

    <property name="dataSource" ref="someDataSource"/>
</bean>
<osgi:service ref="dao"/>

With Spring-OSGi to accomodate to the OSGI environment, two lines of configurations have to be added:

  1. <osgi:reference ..=""></osgi:reference> to instruct the framework what OSGi service to look for

  2. <osgi:service ..=""></osgi:service> to export an existing bean as an OSGi service


Obviously the same can be done for the dataSource dependency - externalize it into an OSGi bundle and just replace the straight refwith an osgi:reference. No new APIs to deal with, no exceptions to try/catch/finally for and especially built-in lookup behavior.

Spring-OSGi can be instructed so that the application context does not start unless a service implementating daoInterface is found - that is, the dao dependency can be satisfied. Moreover, at runtime if the service goes away, Spring-OSGi will automatically look for a new implementation based on your configuration (number of retries and timeout): if a call is invoked on 'dao' bean exactly when the owning bundle is updated (for example to upgrade goodPerformerDAO to excellentPerformerDAO) instead of getting a nasty, apparently inexplicable exception, one will get an imperceptible delay caused by new service lookup. As always, the behavior is fully configured.
To some degree the exporter/importer functionality resembles Spring remoting with the big difference that there is no remoting involved - everything is running in the same VM and there is no serialization involved what so ever.

Integration testing


Testing is important (even crucial) especially when migrating an application to a new environment, as a lot of things taken for granted can simply fail: we experienced this ourselves quite early on in development. This has been a big issue since testing was anything but easy or automated when talking about OSGi since the execution environment (the OSGi platform or container if you'd like) has to be started (no standardized API) and setup (install the bundles your test depends on). However the tricky part is that the test itself has to be OSGified - placed along side a manifest which declares the dependencies, into a bundle which has to be installed and started into the OSGi platform.

Meet AbstractOsgiTests & co:
public class SimpleIntegrationTests extends AbstractConfigurableBundleCreatorTests

{
  public void testInstalledBundles() {
    // get access to the OSGi bundle context

     Bundle[] bundles = getBundleContext().getBundles();
     getBundleContext().installBundle(someBundleLocation);

     assertEquals(bundles.length()+1, getBundleContext().getBundles().length());

  }
  // specify the bundles to install 
  protected String[] getBundles() {

        return new String[] {
                "org.springframework.osgi, commons-collections.osgi, 3.2-SNAPSHOT",

                "org.springframework.osgi, org.springframework.osgi.test.simple.service,1.0-SNAPSHOT"};
    }
}
AbstractOsgiTests builds on top of JUnit so you can write and run OSGi integration tests directly from your IDE. The entire setup is handled by the testing infrastructure so you don't have to: no need to write a MANIFEST.MF for your test, to do any packaging or deployment - everything is handled automatically. And it's fast, extremely fast! In fact, less then 10% percent of the startup time is spent inside Spring-OSGi code - the rest is used by the OSGi platform itself. Most of our integration tests are fully executed in 1-3 seconds each. Equinox, Knopflerfish and Felix are all supported.
Well, I think that's enough for a first entry… I'll write more about Spring-OSGi features in future entries. I hope I've made you curios enough to take 1.0 M1 for a spin (please note that it's the first milestone and it has some 'rough edges').

OSGi Alliance which has some nice intros and whitepapers
Wikipedia
EclipseCon OSGi track
Spring-OSGi specification
Javapolis 2006 presentation on Spring-OSGi (by yours truly)
Last, but not least, good ol' Google.
By Costin Leau

Sharing a spring context across multiple Webapps

Last month I gave a Core Spring training in Turkey. At the end of the course I discussed the architecture for an application that some of the participants were going to build after completing the course. This application would consist of an ear file with several war files inside, and the question came up if it was possible to define a single ApplicationContext that could be used as a shared parent to the WebApplicationContexts of all war files. This context would hold bean definitions for services, dao's and other beans that were not specific to a single web module.

Actually, Spring makes it very easy to do this, but neither the course nor the reference manual explain in detail how to use this feature from your web application. I therefore wrote a short sample app that illustrates how this works, which I will discuss here in my first blog entry.

The ContextLoader and SingletonBeanFactoryLocator classes

In a typical Spring web application, you use a ContextLoaderListener (or, if you're using a Servlet 2.2 / 2.3 container, a ContextLoaderServlet) to bootstrap a WebApplicationContext. You configure the ContextLoader used by this class through context parameters in your web.xml. If you've used this, you're probably familiar with the contextConfigLocation parameter, that let's you specify which files make up the WebApplicationContext to construct.

As it turns out, there is another parameter that you can use to get the desired functionality in a declaritive fashion: parentContextKey. Using this, you instruct the ContextLoader to use another class called ContextSingletonBeanFactoryLocator to search for a bean named by the value of parentContextKey, defined in a configuration file whose name matches a certain pattern. By default, this pattern is 'classpath*:beanRefFactory.xml', meaning all files called beanRefFactory on the classpath.
This bean must be an ApplicationContext itself, and this context will become the parent context for the WebApplicationContext created by the ContextLoader. However, if this context already exists then that one will be used and no new context will be created (hence the name SingletonBeanFactoryLocator).

Let's see what this means: first, we need a seperate jar in our ear that holds the code for the services, DAO's, etc. Inside this jar we place a beanRefFactory.xml file that holds a single bean-definition for an ApplicationContext. Typically, this will be a ClassPathXmlApplicationContext. Then that bean definition will refer to one or more 'regular' bean configuration files that contain the service beans and other stuff to be used by the code from your war files; something like this:


<!– contents of beanRefFactory.xml:
     notice that the bean id is the value specified by the parentContextKey param –>
<bean id="ear.context" class="org.springframework.context.support.ClassPathXmlApplicationContext">
    <constructor-arg>
        <list>
            <value>services-context.xml</value>
        </list>
    </constructor-arg>
</bean>

Finally, we need to make this jar available on the classpath of the war files using the Class-Path entry in the MANIFEST.MF file of each war.

Why would you want to use this?

A simpler solution is to skip the parentContextKey and to load the shared bean definition files from each war using the contextConfigLocation parameter. This way, each war will have its own instance of each shared bean. For simple stateless beans, such as typical services, this is actually a fine solution.

However, instantiating a new instance of each shared bean for each war can have several drawbacks: a common example is creating a Hibernate SessionFactory. This is often an expensive process, so to prevent your startup time getting out of hand the described solution will ensure that this is done only once. Another advantage of having a single instance of your SessionFactory is that it can safely act as a second level cache: you don't want multiple copies of that hanging around in a single application!
In general, if you have stateful beans that should really be used as a singleton (in the Spring sense, i.e. one instance per application as opposed to per JVM) you should define them in a single context accessed by the other contexts.

The sample

I've included the sample, both as an ear file and as source. In order to upload the ear, I had to give it a .zip extension: please rename the file to .ear before deploying it!. The source is actually an Eclipse workspace, so you can easily import and review it (it requires WTP and is configured for Spring IDE). All Spring jars needed are included. After you've deployed the app, go to the URLs /web1 and /web2 to see the output of a servlet in the first and the second war file. The toString() of the service will prove that the wars really use the same instance of the shared service.

More info

The best info on this feature is in Spring's excellent API documentation: have a look at the JavaDoc for the ContextLoader.loadParentContext method and the SingletonBeanFactoryLocator class. These docs contain further info on how to configure your web.xml and how to write the beanRefFactory.xml.

By Joris Kuipers

Caching methods result using Spring and EHCache

Introduction


Spring1.1.1 introduced integration for EHCache for general cache use.
I will show here a sample Interceptor that allows for declarative caching of methods results.

Configure EHCache using Spring IoC


Spring makes EHCache configuration very easy. All you need, is to provide a ehcache.xml file where you configure EHCache regions:


<ehcache>

    <!-- Sets the path to the directory where cache .data files are created.

         If the path is a Java System Property it is replaced by
         its value in the running VM.

         The following properties are translated:
         user.home - User's home directory
         user.dir - User's current working directory
         java.io.tmpdir - Default temp file path -->
    <diskStore path="java.io.tmpdir"/>


    <!--Default Cache configuration. These will applied to caches programmatically created through
        the CacheManager.

        The following attributes are required for defaultCache:

        maxInMemory       - Sets the maximum number of objects that will be created in memory
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element
                            is never expired.
        timeToIdleSeconds - Sets the time to idle for an element before it expires.
                            i.e. The maximum amount of time between accesses before an element expires
                            Is only used if the element is not eternal.
                            Optional attribute. A value of 0 means that an Element can idle for infinity
        timeToLiveSeconds - Sets the time to live for an element before it expires.
                            i.e. The maximum time between creation time and when an element expires.
                            Is only used if the element is not eternal.
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache
                            has reached the maxInMemory limit.

        -->

    <cache name="org.sample.cache.METHOD_CACHE"
        maxElementsInMemory="300"
        eternal="false"
        timeToIdleSeconds="500"
        timeToLiveSeconds="500"
        overflowToDisk="true"
        />
</ehcache>


Our Interceptor will use region "org.sample.cache.METHOD_CACHE" to cache methods results.
Now we will use some Spring IoC to make this region accessible to our beans:

<!-- ==============================   CACHE   ============================= -->

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
  <property name="configLocation">
    <value>classpath:ehcache.xml</value>
  </property>
</bean>

<bean id="methodCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
  <property name="cacheManager">
    <ref local="cacheManager"/>
  </property>
  <property name="cacheName">
    <value>org.sample.cache.METHOD_CACHE</value>
  </property>
</bean>

Bean methodCache creates cache region org.sample.cache.METHOD_CACHE.

Creating our MethodCacheInterceptor


The interceptor implements org.aopalliance.intercept.MethodInterceptor. Whenever it kicks-in, it first checks if the intercepted method is configured to be cached. This allows to selectively configure bean methods for caching. If the method call is configured for caching, the interceptor builds the cache key for the method and checks if the method result is in the cache. If so, the cached result is returned, otherwise the intercepted method is called and the result cached for further use.
/*
 * Copyright 2002-2004 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.sample.interceptor;

import java.io.Serializable;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;

/**
 */
public class MethodCacheInterceptor implements MethodInterceptor, InitializingBean {
  private static final Log logger = LogFactory.getLog(MethodCacheInterceptor.class);

  private Cache cache;

  /**
   * sets cache name to be used
   */
  public void setCache(Cache cache) {
    this.cache = cache;
  }

  /**
   * Checks if required attributes are provided.
   */
  public void afterPropertiesSet() throws Exception {
    Assert.notNull(cache, "A cache is required. Use setCache(Cache) to provide one.");
  }

  /**
   * main method
   * caches method result if method is configured for caching
   * method results must be serializable
   */
  public Object invoke(MethodInvocation invocation) throws Throwable {
    String targetName  = invocation.getThis().getClass().getName();
    String methodName  = invocation.getMethod().getName();
    Object[] arguments = invocation.getArguments();
    Object result;

    logger.debug("looking for method result in cache");
    String cacheKey = getCacheKey(targetName, methodName, arguments);
    Element element = cache.get(cacheKey);
    if (element == null) {
      //call target/sub-interceptor
      logger.debug("calling intercepted method");
      result = invocation.proceed();

      //cache method result
      logger.debug("caching result");
      element = new Element(cacheKey, (Serializable) result);
      cache.put(element);
    }
    return element.getValue();
  }

  /**
   * creates cache key: targetName.methodName.argument0.argument1...
   */
  private String getCacheKey(String targetName,
                             String methodName,
                             Object[] arguments) {
    StringBuffer sb = new StringBuffer();
    sb.append(targetName)
      .append(".").append(methodName);
    if ((arguments != null) && (arguments.length != 0)) {
      for (int i=0; i < arguments.length; i++) {
        sb.append(".")
          .append(arguments[i]);
      }
    }

    return sb.toString();
  }
}

MethodCacheInterceptor source shows that:

  • by default, all methods result are cached (methodNames is null)

  • cache region is configured using IoC

  • cacheKey takes in consideration method arguments


Using MethodCacheInterceptor



The following excerpt shows how to configure MethodCacheInterceptor:

<bean id="methodCacheInterceptor" class="org.sample.interceptor.MethodCacheInterceptor">
  <property name="cache">
    <ref local="methodCache" />
  </property>
</bean>

<bean id="methodCachePointCut" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
  <property name="advice">
    <ref local="methodCacheInterceptor"/>
  </property>
  <property name="patterns">
    <list>
      <value>.*methodOne</value>
      <value>.*methodTwo</value>
    </list>
  </property>
</bean>

<bean id="myBean" class="org.springframework.aop.framework.ProxyFactoryBean">
  <property name="target">
   <bean class="org.sample.beans.MyBean"/>
  </property>
  <property name="interceptorNames">
    <list>
      <value>methodCachePointCut</value>
    </list>
  </property>
</bean>


Further improvements:



It will be very helpfull to add the following to MethodCacheInterceptor:

  • refactor the code so that the interceptor no longer depends on EHCache


  • add arguments to methods configuration:
    
    <property name="methodNames">
      <list>
        <value>methodOne(java.lang.String, int)</value>
        <value>methodOne(java.lang.String, java.lang.String)</value>
      </list>
    </property>
    
    

  • add regular expressions to method configuration
    
    <property name="methodNames">
      <list>
        <value>add*</value>
      </list>
    </property>
    
    


By O. Irbouh