Showing posts with label Spring. Show all posts
Showing posts with label Spring. Show all posts

Wednesday, February 14, 2007

Using JMS with Spring: Message Driven POJO

The previous post described how to implement a JMS messaging client using Spring JMS. This post will describe how to implement the Message listener as a spring Message driven POJO. Follow these steps to implement the Message driven POJO
1. Create the Message Driven POJO: the Message-Driven POJO (MDP) acts as a receiver for JMS messages. The one restriction on an MDP is that it must implement the javax.jms.MessageListener interface. Please also be aware that in the case where your POJO will be receiving messages on multiple threads, it is important to ensure that your implementation is thread-safe. The following listing shows the code for the MDP
SpringMDP.java

public class SpringMDP implements MessageListener {
public void onMessage(Message message) {
try {
System.out.println(((TextMessage) message).getText());
} catch (JMSException ex) {
throw new RuntimeException(ex);
}
}
}


2. Once you've implemented your MessageListener, it's time to create a message listener container.
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="autodetect">

<!-- this is the Message Driven POJO (MDP) -->
<bean id="messageListener" class="jms.SpringMDP"/>

<!-- and this is the message listener container -->
<bean id="listenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="concurrentConsumers" value="5" />
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="queue" />
<property name="messageListener" ref="messageListener" />
</bean>

Find above an example of how to define and configure one of the message listener containers that ships with Spring (in this case the DefaultMessageListenerContainer)
Reference: JMS on Spring

Tuesday, February 13, 2007

Using JMS with Spring: Messaging Client

In this post and the next, I will describe how to implement JMS using Spring and Message Driven POJOs. This post will describe how to create a Messaging client using Spring. The next post will describe how to implement a Message driven POJO. For this I used a simple servlet that, when invoked will send a text message "hello", to a destination queue. The Message driven pojo, listening on the queue will then receive and print the message. Follow these steps to run the example

1. Setup the JMS environment as described in the Configuring Weblogic JMS post
2.
Create the Messaging client: This is a simple Java class which uses the spring JmsTemplate to send a message to the queue. The JmsTemplate can be used for message production and synchronous message reception. For asynchronous reception, Spring provides a number of message listener containers that are used to create Message-Driven POJOs (MDPs). The MessageCreator callback to create a text message from the supplied Session object
QueueSender.java

public class QueueSender {
private JmsTemplate jmsTemplate;
public void setJmsTemplate(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
public void sendMesage() {
jmsTemplate.send("jms/testQueue", new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage("Hello");
}
});

}
}

3. Configure the Bean in the applicationContext.xml file:
applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
<prop key="java.naming.provider.url">t3://localhost:20001</prop>
</props>
</property>
</bean>

<bean id="queueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>jms/connectionFactory</value>
</property>
</bean>

<bean id="jmsDestinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="cache">
<value>true</value>
</property>
</bean>

<bean id="queueTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref bean="queueConnectionFactory" />
</property>
<property name="destinationResolver">
<ref bean="jmsDestinationResolver" />
</property>
</bean>

<bean id="jmsSender" class="jms.QueueSender">
<property name="jmsTemplate">
<ref bean="queueTemplate" />
</property>

</bean>
</beans>
The JndiDestinationResolver class can be used to obtain the Queue destinations using the JNDI Name. The send method in JmsTemplate (see QueueSender), uses the JNDI name, which is used by the JndiDestinationResolver to obtain the appropriate destination.
4. Create a servlet to invoke the Message Sender: The following servlet is used to invoke the QueueSender:

QueueSenderServlet.java

public class QueueSenderServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServletContext());
QueueSender sender = (QueueSender)ctx.getBean("jmsSender");
sender.sendMesage();
}
}


5.Update the web.xml file to add the servlet and spring application context:
web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID">
<display-name>SpringJMSClientWeb</display-name>
<servlet>
<description></description>
<display-name>QueueSenderServlet</display-name>
<servlet-name>QueueSenderServlet</servlet-name>
<servlet-class>jms.QueueSenderServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>QueueSenderServlet</servlet-name>
<url-pattern>/QueueSenderServlet</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>

References: Spring with JMS

Monday, January 29, 2007

Data Access with Spring 2

In "Struts 2 and Spring Communication" described how to make a struts application ready to use spring and how does Struts Action works in Spring. In this post, we will see how to implement spring data access.
Add: applicationContext.xml, Database-context.xml, TestDAODB2-config.xml, Manager-context.xml
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans default-autowire="autodetect">
<import resource="Database-context.xml"/>
<import resource= "TestDAODB2-context.xml"/>
<import resource= "Manager-context.xml"/>
</beans>



Database-context.xml
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans default-autowire="autodetect">
<bean id="dataSource"
class= "org.springframework.jdbc.datasource.DriverManagerDataSource">

<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:XE" />
<property name="username" value="hr"/>
<property name="password" value="hr"/>
</beans>
TestDAODB2-context.xml
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans default-autowire="autodetect">
<bean id="testDAODB2" class="example.dao.TestDAODB2">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="baseFindSQL" value="SELECT EMAIL, LAST_NAME FROM EMPLOYEES" />
<property name="findByUserAndPasswordWhere"value=" WHERE ID = ? AND PASSWORD= ? "/>
</beans>

Note: In above configration, I am injecting SQL query in the DAO class because quries will also be managed from XML file.
TestManager-context.xml
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans default-autowire="autodetect">
<bean id="testManagerBean" class="example.manager.TestManager">
<property name="testDAO"/>
<ref bean="testDAODB2"/>
</property>
</beans>

Create Data Access Object: The database access object uses Spring's MappingSQLQuery class to query the database. This class is a reusable query in which concrete subclass must implement the abstract mapRow(..) method to convert each row of supplied Result set into an object.
Alternatively, JdbcTemplate class can be use to query the database.
Common tasks:
* Retrieves connections from the datasource.
* Prepares statement object.
* Executes SQL CRUD operations.
* Iterates over result sets and populates the results in standard collection objects.
* Handles SQLException and translates it into a more explicit exception in the spring exception hierarchy.

TestDAODB2.java

package example.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Collection;
import java.util.ArrayList;

import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.object.MappingSqlQuery;

public class TestDAODB2{

private DataSource ds;
private String baseFindSql;
private String findByUserAndPasswordWhere;
private FindByUserIDQuery findByUserIDQuery;

public Collection find(String empID, String password){

if (findByUserIDQuery == null)
findByUserIDQuery = new FindByUserIDQuery(baseFindSql +
findByUserAndPasswordWhere);
Object[] params=new Object[2];
params[0] = empID;
params[1] = password;
Collection coll = findByUserIDQuery.execute(params);
return coll;
}

protected class FindByUserIDQuery extends MappingSqlQuery{
public FindByUserIDQuery(){
super();
setDataSource(ds);
}
public FindByUserIDQuery(String sql) {
super(ds, sql);
declareParameter(new SqlParameter(Types.CHAR));
declareParameter(new SqlParameter(Types.CHAR));
compile();
}
protected Object mapRow(ResultSet rs, int rownum) throws SQLException {

ArrayList list=new ArrayList();
list.add(rs.getString("LAST_NAME"));
list.add(rs.getString("EMAIL"));
return list;
}
}

public void setFindByUserAndPasswordWhere(String findByUserAndPasswordWhere) {
this.findByUserAndPasswordWhere = findByUserAndPasswordWhere;
}

public void setBaseFindSql(String s){
baseFindSql = s;
}
public void setDataSource(DataSource datasource){
ds = datasource;
}
}

TestManager.java

package example.manager;

import example.dao.TestDAO;

import java.util.Collection;
import java.util.Iterator;

public class TestManager {

protected TestDAO testDAO;

public String userAuthentication(String empID, String empName)
{
Collection coll= testDAO.find(empID, empName);
Iterator iterator = coll.iterator();
if(iterator!=null){
return "Succesfull";
}else{
return "Failure";
}
}
public void setTestDAO(TestDAO testDAODB2) {
this.testDAO = testDAODB2;
}
}


This example is executed on Tomcat Server and used follwoing jar files.
JAR Files: In order for you to run this example, you must have the following jar files in your class path: commons-collections.jar || commons-lang.jar || commons-logging.jar || ojdbc14.jar || oro-2.0.8.jar || spring.jar || struts-core-1.3.5.jar || struts-taglib-1.3.5.jar
Learn more about how Spring interacts with database

Struts 2 and Spring Communication

The Spring plugin allows Actions, Interceptors, and Results to be created and/or autowired by Spring.

It works by overriding the Struts ObjectFactory to enhance the creation of core framework objects. When an object is to be created, it uses the class attribute in the Struts configuration to correspond to the id attribute in the Spring configuration.

Features
* Allow Actions, Interceptors, and Results to be created by Spring
* Struts-created objects can be autowired by Spring after creation
* Provides two interceptors that autowire actions, if not using the Spring ObjectFactory

USAGE
To enable Spring integration, simply include struts2-spring-plugin-x-x-x.jar in your application.


struts.properties
struts.objectFactory = springAutowiring

The framework enables "autowiring" by default. (Autowiring means to look for objects defined in Spring with the same name as your object property). To change the wiring mode, modify the spring.autowire property.
Wiring Mode
struts.objectFactory.spring.autoWire = type
Enabling Spring integration for other application objects is a two-step process.
  • Configure the Spring listener
web.xml

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

  • Register your objects via the Spring configuration
applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd" >

<beans default-autowire="autodetect">
<bean id="personManagerBean" class="com.acme.PersonManager"/>
<bean id="LoginAction" class="example.Login" singleton="false">
<property name="testManager" ref="personManagerBean"></property>
</bean>
</beans>

Initializing Actions from Spring
Normally, in struts.xml you specify the class for each Action. When using the default SpringObjectFactory, the framework will ask Spring to create the Action and wire up dependencies as specified by the default auto-wire behavior. To do this, all you have to do is configure the bean in your Spring applicationContext.xml and then change the class attribute from your Action in the struts.xml to use the bean name defined in Spring instead of the class name.
struts.xml

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>

<include file="struts-default.xml"/>

<package name="default" extends="struts-default">
<action name="foo" class="com.acme.Foo">

<result>foo.ftl</result>
</action>
</package>

<package name="secure" namespace="/secure" extends="default">

<action name="Login" class="LoginAction">
<result>/jsp/HelloWorld.jsp</result>
</action>
</package>

</struts>
Where you have a Spring bean defined in your applicationContext.xml named "LoginAction". Note that the example.Login Action did not need to be changed, because it can be autowired.

References:
* Spring Plugin
* Struts 2 + Spring 2 + JPA + AJAX