Tuesday, February 8, 2011

All Things Spring

Spring Property Configurer

As a java/j2ee developer you must have dealt with your share of property files. If you did then your are familiar with java Property implemation that makes it easy to load proerties from a file. If you want to be able to realod property file on change (dynamic reload) you can use apache commons configuration

You might say why spring  PropertyConfigurer, I think it is has to do with varied configuration that it supports (no code required to load the property files) and if you need property overriding you can use PropertyOverrideConfigurer

I have listed the application cotext with property place holder configurer that should support any size j2ee project.  I think the simplest of property configurer put (service.properties) in classpath and conatiner will find properties are avilable for any spring bean in the context.

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

 <!--  Simple property configuration -->
 <bean id="serviceProps" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <!--  file should be available in class path -->
  <property name="location" value="classpath:service.properties"></property>
 </bean>

 <bean id="emailSender" class="prasanna.service.EmailSender">
  <constructor-arg name="host" value="${email.host}"/>
  <constructor-arg name="port"  value="${emai.port}"/>
  <constructor-arg name="emailGroup"  value="${email.group}"/>
 </bean>

 <!--  Simple bean to verify the configuration in a test -->
 <bean class="prasanna.service.PropertyHolderBean">
  <constructor-arg name="prop1" value="$one{one.property1}"/>
  <constructor-arg name="prop2" value="$one{one.property2}"/>
  <constructor-arg name="prop3" value="$one{one.property3}"/>
  <property name="jdcbcUrl" value="$jdbc{url}"/>
  <property name="userId" value="$jdbc{user}"/>
  <property name="password" value="$jdbc{password}"/>
 </bean>

 <!-- Property Configuration prefix with file easy to read the code -->
 <bean id="one" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="location" value="classpath:one.properties"/>
  <property name="placeholderPrefix" value="$one{"/>
  <property name="placeholderSuffix" value="}"/>
 </bean>

 <bean id="jdbc" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="location" value="classpath:jdbc.properties"/>
  <property name="placeholderPrefix" value="$jdbc{"/>
  <property name="placeholderSuffix" value="}"/>
 </bean>

 <!--  This will enable spring to ignore if this property file is not found -->
 <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
     <property name="ignoreResourceNotFound" value="true"/>
     <property name="location" value="classpath:notexists.properties"/>
  </bean>

</beans>

I think if you confiugre your properties this way you can prefix the property file name, It would make the code easier to read and maintain. You can reference a property with file prefix ($one{one.property1})

<bean id="one" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

I think my favorite is the property that property conifigurer offers (ignoreResourceNotFound and ignoreUnresolvablePlaceholders), I think it is useful when the property file is only optional, I found this very useful when deploying code in different environments (dev, qa, prod  etc)

You can down load complete source code from  here

Application Context Aware

I found this interface to be very useful on legacy projects with spring managed beans. In our poject we intorduced spring for new devlopment but did not covert the exsisting POJO's to spring beans. It means we are left with a problem with no DI (communication from non spring POJO to spring POJO)

That is where this spring framewrok interface (ApplicationContextAware) helped us quite a bit. If you implement this interface you have access to spring ApplicationContext and there by acees to any resource managed by the context. I am listing the POJO we have used in our project here.

public class SpringApplicationContext implements ApplicationContextAware
{

 private static ApplicationContext APPLICATION_CONTEXT;

 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
 {
  APPLICATION_CONTEXT = applicationContext;
 }

 /**
  * This method must be called statically to gain an access to the Spring-managed beans by name.
  * 
  * @param beanName
  * @return
  */
 public static Object getBean(String beanName)
 {
  return APPLICATION_CONTEXT.getBean(beanName);
 }
}
 
I would like to bring your attention to static getBean method (In a non spring managed you can just do this)
SpringApplicationContext.getBean("blah")

Schedule Task (@Scheduled)
In a project I worked, I needed to monitor a table for errors, When I was searching for a solution I found out that how trivial it was to do it with spring task scheduler. Here are the two steps that you need to do

  • define this annotation tag in your application context file <task:annotation-driven/> 
  • Create a Spring manged bean with a method and annotate the method with @Scheduled

I have listed the code below with a simple task,  The first listing is complete application context file and second listing is a Spring managed bean with a method that executes every 5 seconds

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

<context:component-scan base-package="prasanna"></context:component-scan>
<task:annotation-driven/>
</beans>


@Component
public class MonitorService 
{
 @Scheduled(fixedDelay=50000)
 public void montor()
 {
   //Run this code at a fixedDelay of (5000 milliseconds / 5 seconds)
  }
}
Although my example provides a fixed delay task, But you can also configure a cron trigger for the task scheduler.