Enterprise Integration Zone is brought to you in partnership with:

Shashank has posted 15 posts at DZone. View Full User Profile

Integrating Flex and Spring based JMS applications

09.28.2009
| 45832 views |
  • submit to reddit

Modifying Configuration for Spring Flex Integration

The first file you want to modify is web.xml, which resides in the WebContent/WEB-INF/ folder of your project. The web.xml file is a file all Java web developers are familiar with. If you aren’t a Java web developer, let me in a single statement attempt to explain what this file does. The web.xml file is an essential piece of configuration, often referred to as the deployment descriptor, that defines how a web application should be deployed in a servlet container. When you create a Flex project with a Java EE (J2EE) server side, connected via LCDS or BlazeDS, a default web.xml file is created for you. To make your application work with Spring you need to modify this file. The new entries in the file should be as shown in Listing 1.

Listing 1: web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">

<display-name>Spring Flex Remoting Example</display-name>

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/config/web-application-config.xml
/WEB-INF/config/web-application-security.xml
</param-value>
</context-param>

<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

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

<servlet>
<servlet-name>springflex</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>springflex</servlet-name>
<url-pattern>/messagebroker/*</url-pattern>
</servlet-mapping>

<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>main.html</welcome-file>
</welcome-file-list>

</web-app>

 The salient configurations in the listed web.xml are:

  • The Spring MVC DispatcherServlet is configured. The DispatcherServlet acts as a front controller that dispatches incoming requests to commands. The DispatcherServlet in Spring BlazeDS dispatches all relevant requests to the BlazeDS MessageBroker.
  • All requests that include “/messagebroker/” in the URL are handled by the DispatcherServlet
  • The context loader loads a couple of config files in the /WEB-INF/config folder. These configure the Spring web application
  • Both index.html and main.html are treated as the starting point if no explicit html file is specified as a part of the URL. You may recall that I named my Flex applications’s main application as main.mxml. The html-temnplate generates a corresponding main.html file that wraps the Flex application within it. Therefore pointing the browser to http://localhost:8080/FlexSpringJMSExample will load the Flex application.

In Spring MVC applications each servlet with a name “servlet-name” has a corresponding configuration file named “servlet-name-servlet.xml” in its WEB-INF folder. This is a convention. However, as in the example you can choose not to put any configuration in this file and keep it fairly empty except the XSD defintions.
The primary Spring and Spring BlazeDS related configuration for the example application is in /WEB-INF/config/web-application-config.xml. The BlazeDS xml files remain in addition to this configuration. The values in the BlazeDS services-config.xml and its included xml files is left to its default entries.

Listing 2 shows the contents of web-application-config.xml. This file contains the Spring beans definition to instantiate and configure the following:

  • BlazeDS MessageBroker bootstrapped by Spring container.  Default configuration is applied, which is why a couple of lines alone do the job.
  • Connection to the ActiveMQ broker, which was setup with JBoss AS
  • JMS topic to allow messages exchanges
  • Spring Flex JMS destination for the defined JMS topic  to allow conversation between Flex and the server side JMS entities

 Listing 2: web-application-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:flex="http://www.springframework.org/schema/flex"
xmlns:security="http://www.springframework.org/schema/security"
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.5.xsd
http://www.springframework.org/schema/flex
http://www.springframework.org/schema/flex/spring-flex-1.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">

<!-- Embedded ActiveMQ broker-->
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp:(broker:(tcp://localhost:61616)?persistent=false)?marshal=false"/>
</bean>

<!-- JMS Topic -->
<bean id="jmsTopic" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="sampletopic.inbound"/>
</bean>

<flex:message-broker>
<flex:secured />
</flex:message-broker>

<flex:jms-message-destination id="jmsMsgDestination" jms-destination="jmsTopic" />

</beans>

 That’s pretty much it! A few more details of the configuration are discussed in the section titled: “Message Service Integration”, later in this article.

With all the configuration done for now, there is one more step before you are ready to exchanges some messages using this setup. The missing step is to copy all the Spring and Spring Flex related JAR files to allow all the Spring beans based configuration to work.

Copying the Spring and Spring Flex JAR files

The following files in WEB-INF/lib are part of the regular BlazeDS distribution:

  • backport-util-concurrent.jar
  • cfgatewayadapter.jar
  • commons-codec-1.3.jar
  • commons-httpclient-3.0.1.jar
  • commons-logging.jar
  • concurrent.jar
  • flex-messaging-common.jar
  • flex-messaging-core.jar
  • flex-messaging-opt.jar
  • flex-messaging-proxy.jar
  • flex-messaging-remoting.jar
  • xalan.jar

In addition to these, add at minimum following JAR files to the WEB-INF/lib folder:

  • spring-framework-2.5.6.SEC01/dist/spring.jar
  • spring-flex-1.0.0.RELEASE/dist/org.springframework.flex-1.0.0.RELEASE.jar

For a smooth and quick start, I recommend you also add all the dependent spring module JAR files. Without all dependencies your application will not deploy and work. An alternative to bulk import of all Spring dependency JAR files is to selectively identify the required dependencies and add them in. In some cases, the dependencies are not obvious and you will only realize what’s required when you deploy the application to an application server (in my case JBoss) and the application server complains of the missing files.

With all setup and configuration done, you are ready to now exchange a few messages between Flex and JMS server side elements using your new infrastructure.

Simple Exchange of Messages

To exchange messages using our new installation, I will create a simple Java server side standalone program and a Flex based client. The Java program will send simple messages to a JMS topic and the Flex client will subscribe to the same topic. The messages will therefore flow from the Standalone program to the Flex application.

Messages can be sent either way and Java programs that act as JMS message producers and consumers can be managed entirely by Spring but for simplicity I will stick to a one way communication from a standalone Java producer to a Flex consumer. On the way the interception and transfer is enabled by BlazeDS, which is managed and configured with the help of Spring.

The Flex client includes a simple message consumer and adds all incoming messages to a simple TextArea. The code for the Flex client is shown in Listing 3.

Listing 3: Simple Flex JMS Consumer

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
applicationComplete="consumer.subscribe()">

<mx:Script>
<![CDATA[

import mx.messaging.messages.IMessage;

private function messageHandler(message:IMessage):void
{
messageLog.text += message.body + "\n";
}

]]>
</mx:Script>

<mx:ChannelSet id="channelSet">
<mx:AMFChannel url="http://localhost:8080/messagebroker/amflongpolling"/>
<mx:AMFChannel url="http://localhost:8080/messagebroker/amfpolling"/>
</mx:ChannelSet>

<mx:Consumer id="consumer" destination="jmsMsgDestination" channelSet="{channelSet}" message="messageHandler(event.message)"/>

<mx:Panel title="JMS Consumer" width="100%" height="100%">
<mx:TextArea id="messagelog" width="100%" height="100%"/>
</mx:Panel>

</mx:Application>

 

The JMS producer is equally simple. It connects to the same JMS topic as the consumer and sends simple text messages on it. The JMS provider in our case is ActiveMQ. Include the activemq-all-5.2.0.jar in your standalone Java program’s classpath to make the JMS and ActiveMQ classes available to it.

 Listing 4: TopicProducer.java

package com.treasuryofideas;

import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.TextMessage;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.Topic;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQMapMessage;


public class TopicProducer {

private final String url = "tcp://localhost:61616";

    private Connection connection;

    private Session session;

    private Topic topic;

    private MessageProducer producer;
/**
* @param args
*/
public static void main(String[] args) {
new TopicProducer();
// TODO Auto-generated method stub
}

public TopicProducer() {
try {

            ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(this.url);
            this.connection = factory.createConnection();
            this.session = this.connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            this.topic = this.session.createTopic("sampletopic.inbound");

            this.producer = this.session.createProducer(this.topic);
            this.producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
            this.connection.start();
            
            for(int i=0; i<1000; i++) {
            
             TextMessage textMessage = this.session.createTextMessage("test message");
                MapMessage message = this.session.createMapMessage();
                message.setString("userId", "user");
                message.setString("chatMessage", "passoword");
                this.producer.send(message);
                this.producer.send(textMessage);
            
                System.out.println("Message sent" + i);

            }

        } catch (JMSException e) {
            e.printStackTrace();
        }
       
}
}


To run your example, first deploy the Flex Spring BlazeDS application and access the Flex client and then start the JMS producer. This sequence is necessary as the Flex client sets itself up as a consumer only on the creationComplete event of the application.

Although the example is elementary, it shows clearly how simple and easy Spring BlazeDS makes the JMS interactions between Flex and Spring. In the next section a brief survey of the message service integration provides additional details on how message exchanges could be established effectively between Flex and a Spring based application.

Message  Service Integration

Spring BlazeDS defines the following three message service components on the server side:

  • Native built-in BlazeDS AMF messaging
  • JMS messaging using the Spring-specific JMS components
  • Spring BlazeDS messaging integration

The messaging infrastructure in the Flex framework imposes little restriction on the messaging protocol or messaging domain on the server side. Therefore multiple types of messaging services, as enumerated above, can be used. Let’s explore the three types of message service components a bit more to understand what they bring to the table.

Native built-in BlazeDS AMF messaging

BlazeDS supports an ActionScriptAdapter for simple message routing between two or more Flex clients. The communication between the two or more Flex clients happens via a server-side destination. This messaging adapter is limited in its functionality. The core of the messaging adapter is the two methods that help route messages. These two methods are:

  • pushMessageToClients — Delivers message to all clients connected to a server
  • sendPushMessageFromPeer — Delivers messages to peer servers in the cluster, which in turn deliver the message to connected clients

To use this adapter, you will typically configure a server-side destination and assign the ActionScriptAdapter as the adapter to use. In addition, you would also configure a messaging channel, probably a polling AMF channel. In standard BlazeDS such configuration resides in the messaging-config.xml configuration file. The messaging-config.xml file is included in the services-config.xml file by reference.

In Spring BlazeDS such a messaging adapter is configured with only a few lines of configuration as follows:

<flex:message-destination 
id="myTopic"
message-broker="messageServiceBroker"
channels="my-polling-amf, my-secure-amf"
subscription-timeout-minutes="0"
allow-subtopics="true"
message-time-to-live="0"
subtopic-separator="."/>

Just <flex:message-destination id="myTopic" /> is enough if you are using the default adapter and the default channel.

JMS messaging using Spring specific JMS components

The Spring framework defines a couple of components to interact with JMS message domains: queues and topics. It includes a template-based solution, JmsTemplate, to send and receive JMS messages. The JmsTemplate eliminates much of the boilerplate code associated with opening and closing connections and sessions and sending and receiving messages. It also transforms the JMSException into part of Spring’s runtime exception hierarchy. JMSException is converted to org.springframework.jms.JmsException. Spring simplifies access to and programming with many resources such as JDBC, JNDI, and JMS by defining templates that help eliminate much of the boilerplate code and let you focus on core tasks.

While a JmsTemplate simplifies sending and receiving messages, receiving messages using the JmsTemplate is synchronous. Synchronous message listeners are not efficient, as they involve blocking operations. Resources like threads wait until a message arrives. In asynchronous operations such threads could gainfully carry out other operations in this waiting time. To address this situation (where synchronous messaging listeners blocked resources), MessageDriveBeans (MDBs) were introduced into Java EE. EJB containers could then listen to JMS destinations and trigger an MDB when a message arrived. The Spring framework extended this concept to POJOs and, therefore, makes it easy to have asynchronous message listeners without the need for EJB containers. Spring’s counterparts of a MDB are a Message Driven POJO (or MDP). You can also write an asynchronous JMS message listener without Spring, although MDPs are a robust set of asynchronous message listeners that you could readily use.

You have seen a simple usage of the Spring BlazeDS JMS configuration in the simple example earlier in this article.

Spring BlazeDS Messaging Integration

Spring BlazeDS defines org.springframework.flex.messaging.integration.IntegrationAdapter, which enables sending and receiving of messages via Spring BlazeDS’s message channels. Complicated message routing could be established using this adapter. You will also be able to connect to FTP and email endpoints using the integration adapter.

As an example a Spring extension project, called SESIA, provides an FTP adapter that works with the integration adapter. You can get more information on the SESIA project online at http://opensource.atlassian.com/confluence/spring/display/INTEGRATE/SESIA.

Conclusion

With a brief overview of the available message exchange options its time to wrap this article up. I assume this article has familiarized you with the way you could combine Flex and Spring JMS applications. With your whetted appetite you may be enthusiastic to learn more and explore the advanced configuration. Many interesting details are covered in my book Professional BlazeDS (Wiley, 2009) that you may want to get hold of. In addition, keep an eye on more articles on the topic that I intend to write as my time permits.

 

AttachmentSize
flex_and_spring_jms_figure_1.png88.21 KB
flex_and_spring_jms_figure_2.png53.4 KB
flex_and_spring_jms_figure_3.png10.28 KB
Published at DZone with permission of its author, Shashank Tiwari.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)