Showing posts with label spring. Show all posts
Showing posts with label spring. Show all posts

Using Spring message pojo

The Spring Framework has concept of message driven pojo's which are similar to MDB that you can use for receiving messages asynchronously. I wanted to try that out so i changed the sample application that i developed in Using amq namespace for building Spring JMS application for ActiveMQ post. In my sample application i did create a simple MessageListener class that gets called whenever there is a message, you can download the source code for sample application from here First i did create a simple MessageListener POJO class like this

package com.webspherenotes.jms;

public class MessageListener {

  public void handleMessage(String message){
    System.out.println("Inside MessageListener.handleMessage() " 
 + message);
  }
}
The handleMessage() method of the MessageListener will get called whenever the message is available. Next define the message listener class in the spring configuration like this.

<?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:jms="http://www.springframework.org/schema/jms"
  xmlns:amq="http://activemq.apache.org/schema/core"
  xsi:schemaLocation="http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core-5.5.0.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms-3.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

  <amq:connectionFactory id="connectionFactory"
    brokerURL="tcp://localhost:61616" />

  <bean id="jmsTemplate" 
  class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="connectionFactory" />
    <property name="defaultDestinationName" value="queue1" />

  </bean>


  <bean id="messageListener" 
  class="com.webspherenotes.jms.MessageListener" />
  
  <jms:listener-container connection-factory="connectionFactory">
    <jms:listener destination="queue1" ref="messageListener" 
 method="handleMessage"/>
  </jms:listener-container>
</beans>

Now when you run the publisher mvn exec:java -Dexec.mainClass=com.webspherenotes.jms.MessagePublisher it will initialize the spring context and as part of that process it will create MessageListner class and attach it as listener to the destination, so when the message gets published your MessageListner will get called automatically to handle/consume the message.

Maven build file(pom.xml) for Spring Active MQ JMS application

In the Using amq namespace for building Spring JMS application for ActiveMQ entry i built a sample Spring Active MQ JMS application, this is the maven pom.xml file for it.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.webspherenotes.jms</groupId>
  <artifactId>HelloSpringActiveMQ</artifactId>
  <version>1.0</version>
  <name>HelloSpringActiveMQ</name>
  <description>Sample Spring ActiveMQ JMS application</description>
  <dependencies>
    <dependency>
      <groupId>org.apache.activemq</groupId>
      <artifactId>activemq-core</artifactId>
      <version>5.5.0</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.5.11</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jms</artifactId>
      <version>3.0.3.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.apache.xbean</groupId>
      <artifactId>xbean-spring</artifactId>
      <version>3.9</version>
    </dependency>
  </dependencies>
</project>
Once my pom.xml is ready i can use following commands to run MessagePublisher.java and MessageReceiver.java
  1. mvn exec:java -Dexec.mainClass=com.webspherenotes.jms.MessagePublisher
  2. mvn exec:java -Dexec.mainClass=com.webspherenotes.jms.MessageReceiver

Using amq namespace for building Spring JMS application for ActiveMQ

Using amq namespace makes developing Spring application for ActiveMQ very easy, i wanted to try that so i built this sample application, This is how my applicationContext.xml file looks like

<?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:jms="http://www.springframework.org/schema/jms"
  xmlns:amq="http://activemq.apache.org/schema/core"
  xsi:schemaLocation="http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core-5.5.0.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms-3.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

  <amq:connectionFactory id="connectionFactory"
    brokerURL="tcp://localhost:61616" />

  <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="connectionFactory" />
    <property name="defaultDestinationName" value="queue1" />
  </bean>

</beans>
As you can see i have only two beans one for ConnectionFactory and other for JmsTemplate. This is how my MessagePublisher.java looks like

package com.webspherenotes.jms;

import java.util.Date;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;

public class MessagePublisher {
  public static void main(String[] args)throws Exception {
    ApplicationContext context = 
 new ClassPathXmlApplicationContext("applicationContext.xml");
    JmsTemplate jmsTemplate =(JmsTemplate) context.getBean("jmsTemplate");
    MessageCreator message = new MessageCreator() {
      public Message createMessage(Session session) throws JMSException {
        TextMessage textMessage = session.createTextMessage();
        String messageStr = "This message is sent using MessageCreator" + new Date();
        textMessage.setText(messageStr);
        return textMessage;
      }
    };
    jmsTemplate.send(message);
  }
}
This is how my MessageReceiver class looks like

package com.webspherenotes.jms;

import javax.jms.TextMessage;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jms.core.JmsTemplate;

public class MessageReceiver {
  public static void main(String[] args)throws Exception {
    ApplicationContext context = 
    new ClassPathXmlApplicationContext("applicationContext.xml");
    JmsTemplate jmsTemplate =(JmsTemplate) context.getBean("jmsTemplate");
    TextMessage message = (TextMessage)jmsTemplate.receive();
    System.out.println("Message received " + message.getText());
  }
}
This is sample of how to wait for message synchronously.

Spring Web Application, loading classes from classpath

Recently i had to break my big Spring Portlet Application into smaller pieces and move some of the code to shared library so that it can be used by multiple web application. Actually in my case Portlet Skin, which is part of wps.war needed access to same beans as that of my portlet.

What i did to solve this problem is i created a new Java Project and moved my DAO classes along with the Spring configuration for DAO classes to that java project, the jar file built by that java project would go in shared lib. Since the spring configuration files were copied to root of the shared library my Skin could load those classes by using ClassPathXmlApplicationContext like this


new ClassPathXmlApplicationContext(new String[]{"dao.xml","dao1.xml","dao2.xml"})


But how do i include the dao.xmls while creating WebApplicationContext. In Spring Portlet MVC framework the org.springframework.web.context.ContextLoaderListener is used for reading value of contextConfigLocation Web Application Context parameter and then reads all those Spring configuration files into Web Application COntext. Normally WebApplication Context looks for the configuration files in WEB-INF directory. In my case dao.xml is not part of web application so it was throwing file not found error.

I was able to solve that problem by appending classpath: instead of file name. When i do that the Spring framework starts using ClasspathResourceLoader instead of WebApplicationResourceLoader for loading configuration file. And ClasspathResourceLoader is capable of reading files from the classpath, which is shared lib

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:dao.xml,classpath:dao1.xml,classpath:dao2.xml</param-value>
</context-param>

Sharing ApplicationContext in Spring MVC and Non Spring MVC Portlet

In my project i had this interesting problem that i have one Portlet Application, which has 4 portlets now 3 of the portlets are using Spring MVC framework but the fourth portlet does not use Spring Portlet MVC framework instead it extends GenericPortlet. All my 4 portlets use same DAO and other classes and i am using Spring for wiring my DAOs

Problem was that how do i obtain ApplicationContext for the portlet that is not Spring Portlet MVC or how do i get access to ApplicationContext object.


PortletApplicationContextUtils.getWebApplicationContext(getPortletContext())


You can use PortletApplicationContextUtils.getWebApplicationContext() method, which is static method anywhere in your web application code to get access to ApplicationContext created by the ContextLoaderListener in your class.