SyntaxHighlighter

Thursday, December 16, 2010

Spring Remoting Over JMS

JMS is one of the robust and widely used application integration style.
In this era of building loosely coupled service component based enterprise application; we often need to communicate with other application..exchange data...invoke operations.

Such inter JVM communication is made simpler and more robust by Spring's remoting support over JMS.
Its as simple as invoking a local object method.

Spring does it very transparently, with the help of JmsInvokerServiceExporter ,SimpleMessageListenerContainer and JmsInvokerProxyFactoryBean.
You just need to aware of these 3 classes and off course JMS connectionFactory and queue /topic definition.
First will define JMS related beans such as connectionFactory and Queue as follows:
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://localhost:61616"/>
bean>

<bean id="salaryQueue" class="org.apache.activemq.command.ActiveMQQueue">
     <constructor-arg value="salaryCalculatorQueue"/>
 bean>


Now how to expose a pojo Calculator.java service for remoting over JMS using JMSInvokerServiceExporter
<bean id="calculatorService"    class="com.patkard.spring.remoting.service.impl.SalaryCalculator">
bean>
     
<bean id="remoteCalculatorService" class="org.springframework.jms.remoting.JmsInvokerServiceExporter">
        <property name="service" >
              <bean   class="com.patkard.spring.remoting.service.impl.SalaryCalculator">bean>
        property>
        <property name="serviceInterface"   value="com.patkard.spring.remoting.service.Calculator" />
bean>
Above JMSInvokerServiceExporter exposes Calculator service for remoting over JMS;  here you can also specific method which you wish to expose for remoting.

Define a listener for the queue and provide service bean reference for listener as follows


<bean class="org.springframework.jms.listener.SimpleMessageListenerContainer">
       <property name="connectionFactory" ref="connectionFactory"/>
       <property name="destination" ref="salaryQueue"/>
       <property name="concurrentConsumers" value="3"/>
       <property name="messageListener" ref="remoteCalculatorService"/>
   bean> 
On the client Side; there will be a JmsInvokerProxyFactoryBean definition which will invoke remote method / basically acts as event sender
 
<bean id="remoteCalculatorService" class="org.springframework.jms.remoting.JmsInvokerProxyFactoryBean">
     <property name="serviceInterface" value="com.patkard.spring.remoting.service.Calculator" />
     <property name="connectionFactory" ref="connectionFactory">property>
     <property name="queue" ref="salaryQueue">property>
 bean>          
 The connection Factory and Queue bean definitions are shared by both the client and server configurations


Before running client / server main programs ..start up Active MQ server.

write a simple main program to start up server like below..just load server side bean definitions


ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/remoting/jms/remoting-context-server.xml");
System.out.println("Started Server application...");

write simple client program..look up Calculator bean and invoke a method on bean as if your invoking a local object method.

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/remoting/jms/remoting-context-client.xml");
Calculator calculator = (Calculator)applicationContext.getBean("remoteCalculatorService");
Employee employee = new Employee(12,”Dhananjay”);
employee.setGrade(1);
long sal = calculator.calculateSalary(employee);
System.out.println("Salary Returned "+sal);    
Simple isn't it?


Cheers,
Dhananjay

















Friday, December 10, 2010

Spring Quartz Priority Job Queue

Following post describes how to build a Priority Quartz Job queue.

Basic and most important factor in this is to define (Spring's SchedulerFactory bean )Quartz scheduler with single worker thread.

This can be defined in spring configuration as follows
 <bean id="springScheduler"
                class="org.springframework.scheduling.quartz.SchedulerFactoryBean" destroy-method="destroy">
                <property name="applicationContextSchedulerContextKey" value="applicationContext">property>
                <property name="quartzProperties">
                        <props>
                                <prop key="org.quartz.threadPool.threadCount"> 1 prop>
                        props>
                property>bean> 

As worker thread count is 1; this scheduler can run a one job at a time.

Now will write a Queue Job; which will be taking care of priority while executing individual jobs.

QueueJobBean.java is extension to spring's QuartzJobBean and internally maintains a TreeMap containing job names (spring bean names) with priorities.

<bean name="jobQueue" class="org.springframework.scheduling.quartz.JobDetailBean">
        <property name="jobClass" value="scheduler.QueueJobBean" />
        <property name="jobDataAsMap" ref="prioMap">property>
bean>

We can build a Priority Job map within spring bean configuration as below
<bean id="noOperation" class="scheduler.jobs.NoOpJob" >
    bean>
   
    <util:map id="prioMap" map-class="java.util.TreeMap">
        <entry key="1" value="noOperation"/>
        <entry key="2" value="noOperation"/>
        <entry key="3" value="noOperation"/>
    util:map>

Cheers,
Dhananjay