Spring Framework

EasyMock Objects Injection using Spring and Annotations

Declaring EasyMock objects as spring beans is easy...

<bean id="mailProcessor"  class="org.easymock.classextension.EasyMock" factory-method="createMock">
        <constructor-arg value="com.myservice.MailProcessor" />
</bean>



However, if the bean you want to test is dynamically proxied, you will get a ClassCastException. To work around this, you can create a custom annotation and bean post processor. This will allow you to annotate fields with @MockObject and Spring will provide the mock object using dependency injection...



Custom Annotation

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
@Documented
public @interface MockObject {}

Custom Spring Bean Post Processor

@Component
public class MockObjectBeanPostProcessor implements BeanPostProcessor
{
        private Log logger = LogFactory.getLog(this.getClass());
       
        /* (non-Javadoc)
         * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization
         */

        public Object postProcessBeforeInitialization(Object bean, String beanName)
                        throws BeansException
        {      
                // get all the fields
                Field[] fields = bean.getClass().getDeclaredFields();
                for(Field field : fields)
                {
                        // check if field is annotated by Environment Property
                        if(field.isAnnotationPresent(MockObject.class))
                        {
                                try
                                {
                                        field.setAccessible(true);
                                        field.set(bean, EasyMock.createMock(field.getType()));
                                } catch (Exception e) {
                                        logger.warn(e);
                                }
                        }
                }
                return bean;
        }
       
       
        /* (non-Javadoc)
         * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization
         */

        public Object postProcessAfterInitialization(Object bean, String beanName)
                        throws BeansException
        {
                // do nothing, return original bean
                return bean;
        }      
}

Sample JUnit Test

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/spring-test.xml"})
public class MailProcessorTest
{
        @MockObject private MailProcessor mailProcessor;
       
        @Test
        public void test()
        {
                // setup test behavior

                EasyMock.replay(mailProcessor);
        }
}

Declarative Caching using Spring, Ehcache and Java 5 Annotations

Java Class

package services.interfaces;

import org.springmodules.cache.annotations.Cacheable;
import services.model.Location;

public interface LocationService {
       
        @Cacheable(modelId="getLocationCacheModel")
        public Location getLocation(String zipcode);
}

ehcache.xml

<ehcache>
        <defaultCache
                maxElementsInMemory="500"
                eternal="true"
                overflowToDisk="false"
                memoryStoreEvictionPolicy="LFU" />
               
        <cache name="getLocationCache"
                maxElementsInMemory="50"
                eternal="true"
                overflowToDisk="false"
                memoryStoreEvictionPolicy="LFU" />
</ehcache>

Spring Configuration File

Add the following namespace definition:
http://www.springmodules.org/schema/ehcache
http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd

<ehcache:config configLocation="classpath:ehcache.xml" />
<ehcache:annotations>
        <ehcache:caching id="getLocationCacheModel"
                cacheName="getLocationCache" />
</ehcache:annotations>

Executing a method when a Spring application starts

This configuration will call the method specified in the init attribute when this bean is created, but it will only work if the method does not require any parameter...

<bean class="com.samples.Echo" init="echo" />

If you need to pass parameters, use the following sample configuration...

<bean id="sampleBean" class="com.samples.Echo"/>

<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
  <property name="targetObject" ref="sampleBean" />
  <property name="targetMethod" value="echo" />
  <property name="arguments">
    <list>
      <value>Hello World!</value>
    </list>
  </property>
</bean>

When dealing with a static method, simply change the targetObject to targetClass and targetMethod to staticMethod...

<property name="targetClass" value="com.samples.Echo" />
<property name="staticMethod" value="echoStatic" />
 

Exposing a Spring POJO as a Web Service using XFire

In your web.xml, add the following configuration:

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
    classpath:org/codehaus/xfire/spring/xfire.xml
  </param-value>
</context-param>
<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

Then, add the following to your Spring context file..

<bean class="org.codehaus.xfire.spring.remoting.XFireExporter">
  <property name="serviceFactory" ref="xfire.serviceFactory" />
  <property name="xfire" ref="xfire" />
  <property name="serviceBean" ref="serviceImpl" />
  <property name="serviceClass" value="com.samples.interface.Service" />
</bean>

Exposing Spring Beans as AJAX methods using DWR

<bean id="echoBean" class="com.samples.Echo">
   <dwr:remote javascript="Ajax">
      <dwr:include method="echo"/>
   </dwr:remote>
</bean>

Spring Message-Driven POJOs

This is probably one of my favorite features of Spring. This simple configuration will enable any method of any class to receive JMS messages asynchonously and send a response, if needed...

<bean id="echoBean" class="com.samples.Echo" />
   
<jms:listener-container
        connection-factory="connectionFactory"
        destination-type="queue"
        concurrency="10">
   <jms:listener destination="com.samples.queue" ref="echoBean" method="echo"/>
</jms:listener-container>

If echo has a return type, it will automatically be converted to a JMS Message and sent to the destination specified in the JMSReplyTo attribute of the incoming message. Sweet!

Exposing a Spring POJO as a Lingo Service

Service Configuration:

<!-- Bean that implements com.samples.interface.Service -->
<bean id="serviceImpl" class="com.samples.impl.Service" />

<!-- Lingo Service Configuration -->
<bean id="lingoService" class="org.logicblaze.lingo.jms.JmsServiceExporter">
  <property name="connectionFactory" ref="connectionFactory"/>
  <property name="destination" ref="lingoQueue"/>
  <property name="service" ref="serviceImpl"/>
  <property name="serviceInterface" value="com.samples.interface.Service"/>
</bean>

Client Configuration:

<!-- Lingo Client Configuration -->
<bean id="lingoClient" class="org.logicblaze.lingo.jms.JmsProxyFactoryBean">
  <property name="connectionFactory" ref="connectionFactory"/>
  <property name="destination" ref="lingoQueue"/>
  <property name="serviceInterface" value="com.samples.interface.Service"/>
  <property name="metadataStrategy" ref="metadataStrategy"/>
</bean>

<!-- define the metadata strategy -->
<bean id="metadataStrategy" class="org.logicblaze.lingo.SimpleMetadataStrategy">
<!-- enable async one ways -->
  <constructor-arg value="true"/>
</bean>

Spring Managed Connection Factory Configuration

<bean id="eciManagedConnectionFactory"
     class="com.sonicsw.sonicmq.j2ee.jmsra.impl.sonic.SonicManagedConnectionFactory">
   <property name="brokerURL"   value="${Broker}"/>
   <property name="username"    value="${BrokerUser}"/>
   <property name="password"    value="${BrokerPassword}"/>
</bean>
       
<bean id="connectionFactory" class="org.springframework.jca.support.LocalConnectionFactoryBean">
   <property name="managedConnectionFactory" ref="eciManagedConnectionFactory"/>
</bean>

Syndicate content (C01 _th3me_)