Spring – Engine / Processors pattern

This is a pattern that is very easy to configure and use in Spring. It allows you to map object or any arbitrary key in a map to a service that will process objects of any types.

The Engine delegates calls to each one of the configured processors. Although the example is very simple and shows no real functionality I have used this same pattern to create services that generate thumbnails, process images, extract text from files based on content types, etc…

Once the engine is configured you can smply call engine.process(object) and based on the configuration the engine will delegate to the right processor.

This same pattern with slight modifications can be reused to implement filters and chain of commands/responsibility.
You can base the keys on the map on any other attribute besides the class.

This tutorial is available for download with svn:
svn checkout http://raulrajatutorials.googlecode.com/svn/trunk/ raulrajatutorials-read-only
Comments in the code itself should be self-explanatory if you already have some java + spring experience.

And now to the point.

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
       default-autowire="byName">
 
    <!-- A processor that know about Person objects -->
    <bean id="personProcessor" class="com.raulraja.processor.impl.PersonProcessorImpl"/>
 
    <!-- A processor that knows about Place objects -->
    <bean id="placeProcessor" class="com.raulraja.processor.impl.PlaceProcessorImpl"/>
 
    <!-- A configured processing engine that maps object types to their processors and delegates calls to each one of them -->
    <bean id="processingEngine" class="com.raulraja.processor.impl.DefaultProcessingEngineImpl">
        <property name="processors">
            <map>
                <entry key="com.raulraja.domain.Person" value-ref="personProcessor"/>
                <entry key="com.raulraja.domain.Place" value-ref="placeProcessor"/>
            </map>
        </property>
    </bean>
 
    <!--
        This handler is actually not required but used for demonstrating the tutorial by invoking
        http://localhost:port/tutorialName
    -->
    <bean id="serviceInvokerHandler" class="com.raulraja.util.handler.impl.ServiceInvokerHandlerImpl" autowire="autodetect" />
 
</beans>

ProcessingEngine.java

package com.raulraja.processor;
 
/**
 * A processing engine that you can feed objects to and processes them
 */
public interface ProcessingEngine<Target> {
 
	/**
	 * Processes something
	 * @param target the target object to be processed
	 */
	void process(Target target);
 
}

DefaultProcessingEngineImpl.java

 
package com.raulraja.processor.impl;
 
import com.raulraja.processor.ProcessingEngine;
import com.raulraja.processor.Processor;
import org.apache.log4j.Logger;
 
import java.util.Map;
 
/**
 * Default impl of the processing engine based on a spring configured service.
 * Delegates processing calls to the right processor
 */
public class DefaultProcessingEngineImpl<Target> implements ProcessingEngine<Target> {
 
	private final static Logger log = Logger.getLogger(DefaultProcessingEngineImpl.class);
 
	/**
	 * A map of processor that maps object types to a processor that know how to process it
	 */
	private Map<Class<Target>, Processor<Target>> processors;
 
	public void setProcessors(Map<Class<Target>, Processor<Target>> processors) {
		this.processors = processors;
	}
 
	/**
	 * Processes something
	 *
	 * @param target the target object to be processed
	 */
	public void process(Target target) {
		log.debug("started processing " + target);
		Processor<Target> processor = processors.get(target.getClass());
		if (processor != null) {
			processor.process(target);
		} else {
			log.debug("processor not found for " + target);		
		}
		log.debug("finished processing " + target);
	}
}

Processor.java

package com.raulraja.processor;
 
/**
 * A service that know how to process a type of object
 */
public interface Processor<Target> {
 
	/**
	 * Processes something
	 * @param target the target object to be processed
	 */
	void process(Target target);
 
}

PersonProcessorImpl.java

package com.raulraja.processor.impl;
 
import com.raulraja.domain.Person;
import com.raulraja.processor.Processor;
import org.apache.log4j.Logger;
 
/**
 * Demonstrates how a Person can be processed
 */
public class PersonProcessorImpl implements Processor<Person> {
 
	private final static Logger log = Logger.getLogger(PersonProcessorImpl.class);
 
	/**
	 * Processes something
	 *
	 * @param person the target object to be processed
	 */
	public void process(Person person) {
   		log.debug(person + " something is being done to a person object");
	}
}

PlaceProcessorImpl.java

package com.raulraja.processor.impl;
 
import com.raulraja.domain.Place;
import com.raulraja.processor.Processor;
import org.apache.log4j.Logger;
 
/**
 * Demonstrates how a Person can be processed
 */
public class PlaceProcessorImpl implements Processor<Place> {
 
	private final static Logger log = Logger.getLogger(PlaceProcessorImpl.class);
 
	/**
	 * Processes something
	 *
	 * @param place the target object to be processed
	 */
	public void process(Place place) {
   		log.debug(place + " something is being done to a place object");
	}
}

Person.java

package com.raulraja.domain;
 
/**
 * Represents a person
 */
public class Person {
}

Place.java

package com.raulraja.domain;
 
/**
 * Represents a place
 */
public class Place {
}

ServiceInvokerHandlerImpl.java

package com.raulraja.util.handler.impl;
 
import com.raulraja.processor.ProcessingEngine;
import com.raulraja.domain.Person;
import com.raulraja.domain.Place;
import org.springframework.web.HttpRequestHandler;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
 
/**
 * Frontend entry point for the demo
 */
public class ServiceInvokerHandlerImpl implements HttpRequestHandler {
 
	/**
	 * The engine that processes object types
	 */
	private ProcessingEngine<Object> processingEngine;
 
	/**
	 * sets the engine that processes object types
	 * @param processingEngine the engine
	 */
	public void setProcessingEngine(ProcessingEngine<Object> processingEngine) {
		this.processingEngine = processingEngine;
	}
 
	/**
	 * Process the given request, generating a response.
	 *
	 * @param request  current HTTP request
	 * @param response current HTTP response
	 * @throws javax.servlet.ServletException in case of general errors
	 * @throws java.io.IOException			in case of I/O errors
	 */
	public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Person person = new Person();
		Place place = new Place();
		processingEngine.process(person);
		processingEngine.process(place);
	}
}

Output

07/01 08:53:59 DEBUG com.raulraja.processor.impl.DefaultProcessingEngineImpl – started processing com.raulraja.domain.Person@53fb687a
07/01 08:53:59 DEBUG com.raulraja.processor.impl.PersonProcessorImpl – com.raulraja.domain.Person@53fb687a something is being done to a person object
07/01 08:53:59 DEBUG com.raulraja.processor.impl.DefaultProcessingEngineImpl – finished processing com.raulraja.domain.Person@53fb687a
07/01 08:53:59 DEBUG com.raulraja.processor.impl.DefaultProcessingEngineImpl – started processing com.raulraja.domain.Place@a427a0b
07/01 08:53:59 DEBUG com.raulraja.processor.impl.PlaceProcessorImpl – com.raulraja.domain.Place@a427a0b something is being done to a place object
07/01 08:53:59 DEBUG com.raulraja.processor.impl.DefaultProcessingEngineImpl – finished processing com.raulraja.domain.Place@a427a0b

Spring – Exposing a bean as both REST (xml, json, …) and SOAP WebServices

Often times you have Spring services that you want to expose as web-services. In this small tutorial I’ll just show a few configuration files and code that demonstrate how a service and its implementation can accommodate both REST and SOAP access to the same backbone.

Thanks Justin for the REST part.

This tutorial is available for download with svn:
svn checkout http://raulrajatutorials.googlecode.com/svn/trunk/ raulrajatutorials-read-only
Comments in the code itself should be self-explanatory if you already have some java + spring experience.
I have not included the dependencies on CXF for simplicity but you can take a look at them and some for the other tutorials here.

And now to the point.

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:cxf="http://cxf.apache.org/core"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:jaxrs="http://cxf.apache.org/jaxrs"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://cxf.apache.org/core
       http://cxf.apache.org/schemas/core.xsd
       http://cxf.apache.org/jaxws
       http://cxf.apache.org/schemas/jaxws.xsd
       http://cxf.apache.org/jaxrs
       http://cxf.apache.org/schemas/jaxrs.xsd"
       default-autowire="byName">
 
    <!-- Load CXF modules from cxf.jar -->
    <import resource="classpath:META-INF/cxf/cxf.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml"/>
 
    <cxf:bus>
        <cxf:features>
            <cxf:logging/>
        </cxf:features>
    </cxf:bus>
 
    <!-- The hello world service -->
    <bean id="helloWorldService" class="com.raulraja.ws.impl.HelloWorldServiceImpl" autowire="autodetect"/>
 
    <!-- Exposing the Helloworld service as a rest service -->
    <jaxrs:server id="restServer" address="/rest/">
        <jaxrs:serviceBeans>
            <ref bean="helloWorldService"/>
        </jaxrs:serviceBeans>
        <jaxrs:extensionMappings>
            <entry key="feed" value="application/atom+xml"/>
            <entry key="json" value="application/json"/>
            <entry key="xml" value="application/xml"/>
            <entry key="html" value="text/html"/>
        </jaxrs:extensionMappings>
    </jaxrs:server>
 
 
    <!-- Exposing the HelloWorld service as a SOAP service -->
    <bean id="jaxbBean"
          class="org.apache.cxf.jaxb.JAXBDataBinding"
          scope="prototype"/>
 
    <bean id="jaxws-and-aegis-service-factory"
          class="org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean"
          scope="prototype">
        <property name="dataBinding" ref="jaxbBean"/>
        <property name="serviceConfigurations">
            <list>
                <bean class="org.apache.cxf.jaxws.support.JaxWsServiceConfiguration"/>
                <bean class="org.apache.cxf.aegis.databinding.AegisServiceConfiguration"/>
                <bean class="org.apache.cxf.service.factory.DefaultServiceConfiguration"/>
            </list>
        </property>
    </bean>
 
 
    <jaxws:endpoint id="helloWorldServiceEndpoint"
                    serviceName="HelloWorld"
                    implementorClass="com.raulraja.ws.HelloWorldService"
                    implementor="#helloWorldService"
                    address="/helloWorldService">
        <jaxws:serviceFactory>
            <ref bean="jaxws-and-aegis-service-factory"/>
        </jaxws:serviceFactory>
    </jaxws:endpoint>
 
</beans>

HelloWorldService.java

package com.raulraja.ws;
 
import javax.ws.rs.Path;
import javax.ws.rs.GET;
import javax.jws.WebService;
import javax.jws.WebMethod;
 
/**
 * The hello world service interface exposed as soap and rest
 *
 * @ WebService is for soap
 * @ Path is for the rest top path
 */
@Path("/helloWorldService/")
@WebService(serviceName = "HelloWorld", name = "HelloWorldService", targetNamespace = "http://ws.raulraja.com")
public interface HelloWorldService {
 
	/**
	 * Simple methods that says hello
	 *
	 * @return hello world rest and soap!!!
	 * @ WebMethod is for soap
	 * @ GET is for REST
	 * @ Path is for the REST service path
	 */
	@WebMethod
	@GET
	@Path("/")
	HelloWorld sayHello();
 
}

HelloWorldServiceImpl.java

package com.raulraja.ws.impl;
 
import com.raulraja.ws.HelloWorld;
import com.raulraja.ws.HelloWorldService;
 
/**
 * Implementation of the hello world web service.
 */
public class HelloWorldServiceImpl implements HelloWorldService {
 
	/**
	 * Simple methods that says hello
	 *
	 * @return hello world rest and soap!!!
	 */
	public HelloWorld sayHello() {
		HelloWorld helloWorld = new HelloWorld();
		helloWorld.setMessage("Hello world rest and soap!!!");
		return helloWorld;
	}
}

HelloWorld.java

package com.raulraja.ws;
 
import javax.xml.bind.annotation.XmlRootElement;
 
/**
 * Hello world object that demonstrates the service
 */
@XmlRootElement
public class HelloWorld {
 
	/**
	 * the message
	 */
	private String message;
 
	/**
	 * @return the message
	 */
	public String getMessage() {
		return message;
	}
 
	/**
	 * @param message sets the message
	 */
	public void setMessage(String message) {
		this.message = message;
	}
}

And here is some screen captures for the results…

Soap Services list

CXF exposed soap services

CXF exposed soap services

Hello World Service WSDL (autogenerated)

Hello World Service WSDL

Hello World Service WSDL

Hello World Service REST XML Result (add .json or .xml, … at the end of the service path to get results in the different format exposed)

Hello World REST xml result

Hello World REST xml result

Mero Gigante en la Azohia, Cartagena

This is real, a while ago very close to were I was born. People, friends of my grandpa.

Mero Azohia 1967

Mero Azohia 1967

Single

Ursula’s new record

One of the band that I used to be part of back in Spain has just released a new album. http://www.ursulaweb.es
I visited the site and found a nice pic back when we played at the FIB in Benicassim back in ’02.
The dude in the middle in this pic its me, good times!!!

Ursula FIB 2002

Ursula FIB 2002

Patterns – Extended MVC for SOA

There are cases when your code base grows and the functionality and purpose of your business services and components needs to extend beyond what they were originally intended for, and just MVC may not be enough.

In this post I will try to show an extension of the MVC pattern meant to scale up and provide more separation of concerns in an enterprise system that might be composed of multiple layers / applications / components.

Here is an example of how a request can be service in a multi tier environment following a MVC like pattern with a couple of extra layers…

Extended MVC

Extended MVC

VIEW: A UI client, website, mobile, or any other requester launches a request against the app. All View Managers are exposed as web services / rest interfaces to the outside world.
VIEW: The View manager receives some data transfer object for a given operation.
CONTROLLER: The View manager delegates the data to the appropriate business service.
CONTROLLER / SERVICE: The transaction starts, the business service applies the application logic to the current request.
MODEL : The business service delegates state change in domain objects to the appropriate model manager.
MODEL : The model manager performs state change and acts as factory for domain objects if necessary.
MODEL : If the domain objects is persistent the model manager delegates persistence operations to the appropriate persistence adapter.
PERSISTENCE : The persistence adapter is specific to the technology that is being used to persist the objects, ej: database, LDAP…
MODEL: The Model manager receives Persistent Objects that may in fact be domain objects like in a hibernate based implementation.
MODEL : The model returns the domain objects to the business service.
CONTROLLER / SERVICE: The business service applies the application logic to the returned domain objects if necessary.
VIEW: The transaction ends, The View manager receives some data back from the business service as a read only facade, impeding further modification of the state.
VIEW : The view manager turns the read-only data into the appropriate view objects that are served back to the client.

And the question is… Why a couple of extra layers, can I just do all that in the controller?

In my opinion this type of architecture allows you to….

1. Scale up any layer as needed since the DTOs between layers are Serializable and you can actually partition the layers and place load balancers in between and deploy layers in different servers by converting each service layer in web services.
2. Since each service on each layer is based on an interface implementation you can deploy different view, business and persistence strategies for different clients and the same application or vice-versa.
3. Layers can be reused in different applications with different business logic.
4. All operations in your application are agnostic to the persistence mechanism used.
5. Method bodies are smaller and all parts in your app are very well structured which help you to easily navigate code without getting lost in 1000+ line methods.

The bad part is…

1. It takes you to build a couple of operations to realize that it is actually easier this way than writing long methods that do everything from constructing your objects to connect to the database and applying the right business rules.
2. Some devs think less files is better.

No, seriously, this is a pattern that I personally like for most projects but I understand in can be overkill for small things.
If you have any comments or know a better way, I’d love to hear your opinion.

An example of this pattern implemented with Java + Spring is available for download at…

svn checkout http://raulrajatutorials.googlecode.com/svn/trunk/ raulrajatutorials-read-only

Comments in the code itself should be self-explanatory if you already have some java + spring experience.

In the following pages you can see actually log output that demonstrate how the request travels through the layers and how exception handling at the view level intercepts any Throwable and turns it into the right View Object.

Deployment – Spring – Overriding properties when deploying in a multi-server environment

I found myself wanting to have certain property values in my Spring projects differ based on what server the app is being deployed.

For example your company has dev, test, qa, prod boxes etc… But there are certain properties in your app such as default db username and passwords, database name, thread pool configurations, etc… that are specific to the server or environment where the app is running.

The technique presented in this tutorial allows you to place all common and default properties in a properties file and provide overrides based on the hostname of the server where the app is running.

For example you can have a application.myDevBoxHostName.properties that will allow you to load property values associated to your own local environment versus a application.myCompany.com.properties that will load the right set of properties in production servers. Also you can have simply application.properties to load all properties that are common or with default values for all environments that do not override properties

This tutorial is available for download with svn:

svn checkout http://raulrajatutorials.googlecode.com/svn/trunk/ raulrajatutorials-read-only

Comments in the code itself should be self-explanatory if you already have some java + spring experience

And now to the point.

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 
    <!--
    This service allows loading of properties based on hostname supporting default values in application.properties and allowing
    other servers to override the default property values in their own server specific application._HOST_NAME_.properties
    -->
    <bean id="applicationProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="systemPropertiesMode" value="1"/>
        <property name="locations">
            <list>
                <value>/WEB-INF/conf/application.properties</value>
                <!--
                    In deployments servers: /WEB-INF/conf/application._HOST_NAME_.properties will override properties in application.properties.
                    based on the hostname in the deployed server
                -->
                <bean class="com.raulraja.util.deployment.CompositeStringResourceProvider" factory-method="getReplacedResource">
                    <constructor-arg>
                        <bean class="com.raulraja.util.deployment.impl.SpringInjectedServletContextProviderImpl" />
                    </constructor-arg>
                    <constructor-arg value="/WEB-INF/conf/application._HOST_NAME_.properties"/>
                </bean>
            </list>
        </property>
        <property name="ignoreResourceNotFound" value="true"/>
    </bean>
 
    <!-- This is a sample service that will get properties injected and will display its values on initialization -->
    <bean id="sampleService" class="com.raulraja.util.deployment.impl.SampleServiceImpl" init-method="init">
        <property name="firstProperty" value="${first.property.placeholder}" />
        <property name="secondProperty" value="${second.property.placeholder}" />
    </bean>
 
</beans>

application.properties

#In this file live all common properties and default property values for all servers
first.property.placeholder=this value was declared in application.properties
second.property.placeholder=this value was declared in application.properties

application.yourHostNameHere.properties

# This file contains properties overriden for the host name were the app is being deployed
second.property.placeholder=this value is overriden in a specific server config declared in application.properties

CompositeStringResourceProvider.java

package com.raulraja.util.deployment;
 
import org.apache.log4j.Logger;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.context.support.ServletContextResource;
 
import java.net.UnknownHostException;
import java.net.InetAddress;
 
/**
 * A service that provides a resource based on the host name
 */
public class CompositeStringResourceProvider {
 
    private final static Logger log = Logger.getLogger(CompositeStringResourceProvider.class);
 
    private final static String HOSTNAME_PLACEHOLDER = "_HOST_NAME_";
 
	/**
	 * This method is invoked by the container at startup
	 * @param servletContextProvider a servlet context provider
	 * @param baseResource the base resource
	 * @return the resource assigned to the current running server
	 * @throws UnknownHostException if the host is unknown
	 */
    public static Resource getReplacedResource(ServletContextProvider servletContextProvider, String baseResource) throws UnknownHostException {
        InetAddress localhost = InetAddress.getLocalHost();
        baseResource = baseResource.replaceAll(HOSTNAME_PLACEHOLDER, localhost.getHostName());
        Resource resource = null;
        if (servletContextProvider.getServletContext() != null) {
            resource = new ServletContextResource(servletContextProvider.getServletContext(), baseResource);
            if (resource.exists()) {
                log.debug("Loading override for common properties: " + resource.getFilename());
            }
        } else {
            resource = new ClassPathResource(baseResource);
        }
 
        return resource;
    }
 
}

ServletContextProvider.java

package com.raulraja.util.deployment;
 
import javax.servlet.ServletContext;
 
/**
 * Provides a servlet context
 */
public interface ServletContextProvider {
 
	/**
	 * @return the servlet context
	 */
    ServletContext getServletContext();
 
}

SpringInjectedServletContextProviderImpl.java

package com.raulraja.util.deployment.impl;
 
 
import com.raulraja.util.deployment.ServletContextProvider;
import org.springframework.web.context.ServletContextAware;
 
import javax.servlet.ServletContext;
 
/**
 * Spring based impl of the ServletContextProvider
 */
public class SpringInjectedServletContextProviderImpl implements ServletContextProvider, ServletContextAware {
 
	/**
	 * the servlet context
	 */
    private ServletContext servletContext;
 
	/**
	 * @return the servlet context
	 */
    public ServletContext getServletContext() {
        return servletContext;
    }
 
	/**
	 * sets the servlet context, invoked by the container at startup since this service implements ServletContextAware 
	 * @param servletContext the servlet context
	 */
    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;
    }
}

SampleServiceImpl.java

package com.raulraja.util.deployment.impl;
 
import org.apache.log4j.Logger;
 
/**
 * Demonstrates how values of properties are injected based on a specific hostname config
 */
public class SampleServiceImpl {
 
	private final static Logger log = Logger.getLogger(SampleServiceImpl.class);
 
	/**
	 * the first prperty
	 */
	private String firstProperty;
 
	/**
	 * the second property
	 */
	private String secondProperty;
 
	/**
	 * service initialization method
	 */
	public void init() {
		log.debug("first property: " + firstProperty);
		log.debug("second property: " + secondProperty);
	}
 
	/**
	 * sets the first property
	 * @param firstProperty the first property
	 */
	public void setFirstProperty(String firstProperty) {
		this.firstProperty = firstProperty;
	}
 
	/**
	 * sets the second property
	 * @param secondProperty the second property
	 */
	public void setSecondProperty(String secondProperty) {
		this.secondProperty = secondProperty;
	}
}

Now notice that my local machine hostname is raul-raja-martinezs-macbook.local

Before application.raul-raja-martinezs-macbook.local.properties existed:

06/13 17:49:52 WARN org.springframework.beans.factory.config.PropertyPlaceholderConfigurer – Could not load properties from ServletContext resource [/WEB-INF/conf/application.raul-raja-martinezs-macbook.local.properties]: Could not open ServletContext resource [/WEB-INF/conf/application.raul-raja-martinezs-macbook.local.properties]
06/13 18:00:47 DEBUG com.raulraja.util.deployment.impl.SampleServiceImpl – first property: this value was declared in application.properties
06/13 18:00:47 DEBUG com.raulraja.util.deployment.impl.SampleServiceImpl - second property: this value was declared in application.properties

After application.raul-raja-martinezs-macbook.local.properties existed:

06/13 18:03:52 DEBUG com.raulraja.util.deployment.CompositeStringResourceProvider – Loading override for common properties: application.raul-raja-martinezs-macbook.local.properties
06/13 18:03:52 DEBUG com.raulraja.util.deployment.impl.SampleServiceImpl – first property: this value was declared in application.properties
06/13 18:03:52 DEBUG com.raulraja.util.deployment.impl.SampleServiceImpl – second property: this value is overriden in a specific server config declared in application.properties

AOP – Spring – Hibernate Sessions for background threads / jobs

Getting your persistence access right when working with background jobs in Spring can be tricky. Most people rely on the Open Session In View pattern using Filters or Interceptors that act on the regular app server threads and close and open sessions for each request.

This technique is not available when you need access to your persistence context from a Quartz Scheduled Job or a TimerTask. The purpose of this tutorials is to show you how you can use Spring AOP proxies to wire a hibernate interceptor that gives you access to the persistence context and it takes cares of closing and opening the sessions for you.

This tutorial is available for download with svn:

svn checkout http://raulrajatutorials.googlecode.com/svn/trunk/ raulrajatutorials-read-only

Comments in the code itself should be self-explanatory if you already have some java + spring experience

And now to the point.

ApplicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns: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-2.5.xsd">
 
 
    <!-- The datasource -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
			<property name="driverClass" value="org.postgresql.Driver" />
			<property name="jdbcUrl" value="jdbc:postgresql://localhost:5432/tutorials?autoReconnect=true" />
			<property name="user" value="tutorials" />
			<property name="password" value="tutorials" />
	</bean>
 
    <!-- The hibernate session factory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="configLocations">
            <list>
                <value>WEB-INF/conf/hibernate.cfg.xml</value>
            </list>
        </property>
        <property name="configurationClass">
            <value>org.hibernate.cfg.AnnotationConfiguration</value>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
        <property name="dataSource">
            <ref bean="dataSource"/>
        </property>
    </bean>
 
    <!-- The Hibernate interceptor, which takes care of opening and closing hibernate session around method calls. -->
    <bean id="hibernateInterceptor" class="org.springframework.orm.hibernate3.HibernateInterceptor">
        <property name="sessionFactory">
            <ref bean="sessionFactory"/>
        </property>
    </bean>
 
    <!-- The quartz scheduler in charge of running background jobs -->
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean" destroy-method="destroy">
        <property name="triggers">
            <list>
               <ref bean="testBackgroundJobTrigger"/>
            </list>
        </property>
        <property name="quartzProperties">
            <props>
                <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
                <prop key="org.quartz.threadPool.threadCount">20</prop>
                <prop key="org.quartz.threadPool.threadPriority">2</prop>
            </props>
        </property>
    </bean>
 
    <!-- A trigger bean with config info on how to run the background job -->
    <bean id="testBackgroundJobTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
        <property name="jobDetail" ref="testBackgroundJobDetail"/>
        <property name="startDelay" value="10000"/>
        <property name="repeatInterval" value="10000" />
    </bean>
 
    <!-- The actual background job impl that we're going to run -->
    <bean id="testBackgroundJob" class="com.raulraja.util.jobs.impl.TestBackgroundJobImpl" autowire="autodetect" />
 
    <!-- A proxy with the hibernate interceptor wired in so it can access the persistent context -->
    <bean id="testBackgroundJobProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target">
            <ref bean="testBackgroundJob"/>
        </property>
        <property name="proxyInterfaces">
            <value>java.lang.Runnable</value>
        </property>
        <property name="interceptorNames">
            <value>hibernateInterceptor</value>
        </property>
    </bean>
 
    <!-- Detail info about the job -->
    <bean id="testBackgroundJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="testBackgroundJobProxy"/>
        <property name="targetMethod" value="run"/>
        <property name="concurrent" value="false"/>
    </bean>
 
</beans>

TestBackgroundJobImpl.java

package com.raulraja.util.jobs.impl;
 
import org.apache.log4j.Logger;
 
/**
 * Test job that runs on the background
 */
public class TestBackgroundJobImpl implements Runnable {
 
	private final static Logger logger = Logger.getLogger(TestBackgroundJobImpl.class);
 
	/**
	 * Do something in the background
	 */
	public void run() {
		logger.debug("doing something in the background");
	}
}

Output


06/13 15:05:00 DEBUG org.springframework.orm.hibernate3.SessionFactoryUtils - Opening Hibernate Session
06/13 15:05:00 DEBUG com.raulraja.util.jobs.impl.TestBackgroundJobImpl - doing something in the background
06/13 15:05:00 DEBUG org.springframework.orm.hibernate3.HibernateInterceptor - Eagerly flushing Hibernate session
06/13 15:05:00 DEBUG org.springframework.orm.hibernate3.SessionFactoryUtils - Closing Hibernate Session

Amores que matan – 1966 Mustang

This 66 Mustang is pocking a hole on my pocket. Lots of money spent since I bought it a couple of years ago.
The beauty next to it reminds me every day that I deserve it for buying a 43 years old car.
Pero como dice mi prima Irene, Antes muerto que sencillo!!!

cimg1846

cimg1847

cimg1853

AOP – Spring – Intercepting method calls using annotations

Sometimes when using Spring in your app you want to profile your methods to see how long it takes for a method to complete. If you don’t have access to software like JProfiler you can accomplish this quickly with some AOP magic in Spring.
Notice that what’s important about this tutorial is not actually to profile time for methods calls. The real power is to use your custom annotations following the same pattern for this and other purposes such as Security, Cacheing of method return types, Transaction management, you name it…

This tutorial is available for download with svn:

svn checkout http://raulrajatutorials.googlecode.com/svn/trunk/ raulrajatutorials-read-only

Comments in the code itself should be self-explanatory if you already have some java + spring experience

And now to the point.

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns: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-2.5.xsd">
 
    <!-- A Service that performs some work -->
    <bean id="businessService" class="com.raulraja.service.impl.BusinessServiceImpl"/>
 
    <!-- A service interceptor that intercepts other services with methods annotated with @Profile -->
    <bean id="methodTimeProfiler" class="com.raulraja.util.aop.profile.MethodProfiler"/>
    <aop:config>
        <aop:aspect ref="methodTimeProfiler">
            <aop:pointcut id="profiledMethods" expression="@annotation(com.raulraja.util.aop.profile.Profile)"/>
            <aop:around pointcut-ref="profiledMethods" method="profileMethod"/>
        </aop:aspect>
    </aop:config>
 
    <!--
        This handler is actually not required but used for demonstrating the tutorial by invoking
        http://localhost:port/tutorialName
    -->
    <bean id="serviceInvokerHandler" class="com.raulraja.util.handler.impl.ServiceInvokerHandlerImpl" autowire="autodetect" />
 
</beans>

BusinessServiceImpl.java

package com.raulraja.service.impl;
 
import com.raulraja.service.BusinessService;
import com.raulraja.util.aop.profile.Profile;
import org.apache.log4j.Logger;
 
/**
 * This a very important service impl with methods that is doing something slow and needs to be profiled
 */
public class BusinessServiceImpl implements BusinessService {
 
	private final static Logger logger = Logger.getLogger(BusinessServiceImpl.class);
 
	/**
	 * Do some work , by adding the @Profile annotation the interceptor provides advice
	 */
	@Profile
	public void doSomething() {
		logger.debug("nothing done for simplicity");
	}
}

Profile.java

package com.raulraja.util.aop.profile;
 
/**
 * Marker for methods that will be profiled, By placing this annotation on a method spring will proxy the service and
 * call the interceptor that provides advice to the real method call
 */
public @interface Profile {
}

MethodProfiler.java

package com.raulraja.util.aop.profile;
 
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
 
public class MethodProfiler {
 
	private final static Logger logger = Logger.getLogger(MethodProfiler.class);
 
	/**
	 * Intercepts methods that declare com.company.project.util.aop.profiler.Profile and prints out the time it takes to complete
	 * @param pjp proceeding join point
	 * @return the intercepted method returned object
	 * @throws Throwable in case something goes wrong in the actual method call
	 */
	public Object profileMethod(ProceedingJoinPoint pjp) throws Throwable {
		try {
			final boolean DEBUG = logger.isDebugEnabled();
			long start = System.currentTimeMillis();
			// Parse out the first arg
			String arg1 = "";
			Object[] pjpArgs = pjp.getArgs();
			if ((pjpArgs != null) &amp;&amp; (pjpArgs.length &gt; 0) &amp;&amp; (pjpArgs[0] != null)) {
				arg1 = pjpArgs[0].toString();
			}
			String logPrefix = null;
			if (DEBUG) {
				logPrefix = pjp.getSignature().getDeclaringTypeName() + "." + pjp.getSignature().getName() + " " + arg1;
				logger.debug(logPrefix + " START");
			}
			Object retVal = pjp.proceed();
			long end = System.currentTimeMillis();
			long differenceMs = end - start;
			if (DEBUG) {
				logger.debug(logPrefix + " RETURN in " + differenceMs + " ms");
			}
			return retVal;
		}
		catch (Throwable t) {
			logger.error("Interceptor caught error: " + t, t);
			throw t;
		}
	}
}

And here it is actually running…

picture-8