Lingo is a POJO based remoting and messaging framework. So the steps are:
1. Create a class (POJO) which will act as a MDP.
package test.mdp;
public interface Hello {
public void greet(String name);
}
package test.mdp;
public class HelloImpl implements Hello {
public void greet(String name) {
System.out.println("Hello " + name);
}
}
Here we have created an interface Hello which is implemented by HelloImpl. The point to notice here is that out POJO HelloImpl does not implement any external listener.
2. Convert your POJO to MDP:
To do this we are using Lingo's JMS exporter. Spring supports exporter.
Create a spring context file service.xml. Add the following contents:
<bean id="server" class="org.logicblaze.lingo.jms.JmsServiceExporter">
<property name="service">
<bean class="test.mdp.HelloImpl"/>
</property>
<property name="serviceInterface" value="test.mdp.Hello"/>
<property name="connectionFactory">
<ref bean="connectionFactory" />
</property>
<property name="destination">
<ref bean="destination" />
</property>
</bean>
Assuming that ActiveMQ will be running on the localhost, listening on port 61616
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
<bean id="destination" class="org.apache.activemq.message.ActiveMQQueue">
<constructor-arg index="0" value="MyQueue" />
</bean>
3. Start the MDP:
public class StartHello {
public static void main(String[] args) {
new FileSystemXmlApplicationContext("service.xml");
}
}
Make sure ActiveMQ is running, and run StartHello. Your MDP will be added as a new client to ActiveMQ and will be ready to service requests.
4. Send a message:
Create a spring context say client.xml. Add the following contents:
<bean id="client" class="org.logicblaze.lingo.jms.JmsProxyFactoryBean">
<property name="serviceInterface" value="test.mdp.Hello"/>
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="destination" />
</bean>
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
<bean id="destination" class="org.apache.activemq.message.ActiveMQQueue">
<constructor-arg index="0" value="MyQueue" />
</bean>
Now create your HelloClient,
public class MDPojoClient {
public static void main(String[] args) {
ApplicationContext ctx = new FileSystemXmlApplicationContext("client.xml");
Hello client = (Hello)ctx.getBean("client");
client.greet("Tommy");
}
}
Here greet() is called synchronously.
4.b. both server and client can be merged into one as
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- client side proxy-->
<bean id="client" class="org.logicblaze.lingo.jms.JmsProxyFactoryBean">
<property name="serviceInterface" value="test.mdp.Hello"/>
<property name="connectionFactory" ref="jmsFactory"/>
<property name="destination" ref="destination"/>
</bean>
<!-- the server side -->
<bean id="server" class="org.logicblaze.lingo.jms.JmsServiceExporter">
<property name="service" ref="helloImpl"/>
<property name="serviceInterface" value="test.mdp.Hello"/>
<property name="connectionFactory" ref="jmsFactory"/>
<property name="destination" ref="destination"/>
</bean>
<!-- the actual implementation of the service - which is only made public for testing purposes -->
<bean id="helloImpl" class="test.mdp.HelloImpl" singleton="true"/>
<!-- JMS ConnectionFactory to use -->
<bean id="jmsFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
</bean>
<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg index="0" value="MyQueue"/>
</bean>
</beans>
5. Required Jars:
spring.jar
log4j-.jar
commons-logging-.jar
activemq-core-.jar
concurrent-.jar
geronimo-spec-jms-.jar
geronimo-spec-j2ee-management-.jar
lingo-1.1.jar (http://logicblaze.com)
6. How to make our MDP asynchronous:
Lingo decides whether a method is synchronous or asynchronous by consulting a Metadata Strategy. The default metadata strategy is SimpleMetadataStrategy. By default, SimpleMetadataStrategy assumes that all calls are synchronous. But by configuring LingoRemoteInvocationFactory with your JmsProxyFactoryBean, you can change the behavior. You just need to register LingoRemoteInvocationFactory bean in client.xml.
<bean id="invocationFactory" class="org.logicblaze.lingo.LingoRemoteInvocationFactory">
<constructor-arg>
<bean class="org.logicblaze.lingo.SimpleMetadataStrategy">
<constructor-arg value="true" />
</bean>
</constructor-arg>
</bean>
Here Spring will instantiate LingoRemoteInvocationFactory using a single argument constructor, passing a SimpleMetadataStrategy instance. The SimpleMetadataStrategy itself is declared as an inner-bean. Its "oneWayForVoidMethods" property is set to "true" to indicate that void methods are one-way and should not block.
Now change you client.xml, change the following
<bean id="client" class="org.logicblaze.lingo.jms.JmsProxyFactoryBean">
<property name="serviceInterface" value="com.habuma.mdpojo.lingo.HelloService"/>
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="destination" />
<property name="remoteInvocationFactory" ref="invocationFactory" />
</bean>
To test its working, you can put a Thread.sleep(10000) in the greet() method.
Note:
1. If the method being invoked returns something, the client must wait for the return value.So it wont be asynchronous.
2. Lingo will work fine with Websphere MQ.
Lingo with WebSphere MQ:
1. Removed ActiveMQ and Geronimo jars, and add following jars from Websphere MQ
com.ibm.mq.jar
com.ibm.mqbind.jar
com.ibm.mqjms.jar
com.ibm.mqpcf.jar
mqcontext.jar
fscontext.jar
jms.jar
jndi.jar
providerutil.jar
2. Change your service.xml and client.xml for below
<bean id="connectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
</bean>
<bean id="Queue" class="com.ibm.mq.jms.MQQueue">
<constructor-arg index="0" value="queue://QMGR/QUEUE" />
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate102">
<property name="connectionFactory">
<ref local="connectionFactory"/>
</property>
</bean>
OR if you want to use JNDI the use the below tags
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">
com.ibm.mq.jms.context.WMQInitialContextFactory
</prop>
<prop key="java.naming.provider.url">
localhost:1414/SYSTEM.DEF.SVRCONN
</prop>
</props>
</property>
</bean>
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate"/>
</property>
<property name="jndiName">
<value>MyCFJNDI
</property>
</bean>
<bean id="destination" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate"/>
</property>
<property name="jndiName">
<value>MyQueueJNDI</value>
</property>
</bean>
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment