Send XML File JMS Queue

Many techniques are available to send XML file using JMS queue as it provides asynchronous communication channel between publisher and subscriber where both don’t know each other still getting required information. One common thing they need to follow is to registered with Queue or Topic to send and receive the messages. Sending text message is simple but sending file over the network is resource intensive. Imagine if you want to send large file over the network then you will have to serialized the data before sending it and serialized object will be loaded into memory before sending it.

To make thing simple without loading large file object into memory just create common location to upload file where both publisher and subscriber have access and send URL link through message so that subscriber could download and process file accordingly. If you are thinking what will happen to the file after subscriber processed it. Well, it’s up to you and your requirement if you want keep file for some time or whatever your purge policy is, otherwise once file process by subscriber successfully it can be deleted immediately or keep it as backup on other location for some time. In this demo I will show you how to crate command location and send file URL through message to process it.

Tools used:

  • JBoss application server jboss-6.1.0.Final community version (You can use any version of JBoss application server which you could download from here). If you are using version other than jboss-6.1.0.Final community version only JMS configuration will be different and use this tutorial to configure Queue and topic.
  • Eclipse Kepler (You could use any version of eclipse above 4.2)

Steps:

  • Configure JMS Queue destination on jboss server : Go to jboss-6.1.0.Final\server\default\deploy\hornetq\hornetq-jms.xml and add below Queue
<queue name="testQueue">
   <entry name="/javahonk/queue"/>
</queue>
  • Now create maven project name JMSSendXMLFile with two class publisher and subscriber where one will publish message on queue and other will consume it (Please note: It’s publisher responsibility to create XML file send its path location through message to the subscriber so that he can consume it).

Send XML File JMS Queue

  • Create publisher class: JMSQueuePublisher.java:
package com.javahonk;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Properties;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;

public class JMSQueuePublisher {
	
	String destinationName = "javahonk/queue";
	Context ic = null;
	ConnectionFactory cf = null;
	Connection connection = null;
	Queue queue = null;
	Session session = null;
	MessageProducer publisher = null;

	public static void main(String[] args) throws Exception {
		
		try {
			
			JMSQueuePublisher jBossJMSTopicPublisher = new JMSQueuePublisher();
			jBossJMSTopicPublisher.initializeConnection();

			// Read from command line
			BufferedReader commandLine = new java.io.BufferedReader(new InputStreamReader(System.in));

			// Loop until the word "exit" is typed
			while (true) {
				String s = commandLine.readLine();
				if (s.equalsIgnoreCase("exit")) {
					jBossJMSTopicPublisher.close(); // close down connection
					System.exit(0);// exit program
				} else{
					jBossJMSTopicPublisher.sendJMSMessageOnTopic(s);					
				}	
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static Context getInitialContext() throws javax.naming.NamingException {

		Properties p = new Properties();
		p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
		p.put(Context.URL_PKG_PREFIXES, " org.jboss.naming:org.jnp.interfaces");
		p.put(Context.PROVIDER_URL, "jnp://localhost:1099");
		return new javax.naming.InitialContext(p);
	}
	
	public void initializeConnection() throws Exception {
		
		ic = getInitialContext();
		cf = (ConnectionFactory) ic.lookup("/ConnectionFactory");
		queue = (Queue) ic.lookup(destinationName);
		connection = cf.createConnection();	
		session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
		publisher = session.createProducer(queue);
		connection.start();
		
	}

	public void sendJMSMessageOnTopic(String s) throws Exception {
		
		TextMessage message = session.createTextMessage(s);
		publisher.send(message);		
	}
	
	/* Close the JMS connection */
	public void close() throws Exception {
		try {
			connection.close();
		} finally {
			if (ic != null) {
				try {
					ic.close();
				} catch (Exception e) {
					throw e;
				}
			}

			try {
				if (connection != null) {
					connection.close();
				}
			} catch (JMSException jmse) {
				System.out.println("Could not close connection " + connection + " exception was " + jmse);
			}
		}
	}

}
  • Create queue subscriber class: JMSQueueSubscriber.java:
package com.javahonk;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Properties;
import java.util.Scanner;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;

public class JMSQueueSubscriber implements MessageListener {
	
	String destinationName = "javahonk/queue";
	Context ic = null;
	ConnectionFactory cf = null;
	Connection connection = null;
	Queue queue = null;
	Session session = null;
	MessageProducer publisher = null;
	
	public static void main(String[] args) throws Exception {
		
		try {
			
			JMSQueueSubscriber jBossJMSTopicSubscriber = new JMSQueueSubscriber();
			jBossJMSTopicSubscriber.initializeConnection();

			// Read from command line
			BufferedReader commandLine = new java.io.BufferedReader(new InputStreamReader(System.in));

			// Loop until the word "exit" is typed
			while (true) {
				String s = commandLine.readLine();
				if (s.equalsIgnoreCase("exit")) {
					jBossJMSTopicSubscriber.close(); // close down connection
					System.exit(0);// exit program
				}	
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static Context getInitialContext() throws javax.naming.NamingException {

		Properties p = new Properties();
		p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
		p.put(Context.URL_PKG_PREFIXES, " org.jboss.naming:org.jnp.interfaces");
		p.put(Context.PROVIDER_URL, "jnp://localhost:1099");
		return new javax.naming.InitialContext(p);
	}
	
	public void initializeConnection() throws Exception {
		
		ic = getInitialContext();
		cf = (ConnectionFactory) ic.lookup("/ConnectionFactory");
		queue = (Queue) ic.lookup(destinationName);
		connection = cf.createConnection();	
		session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
		MessageConsumer subscriber = session.createConsumer(queue);
		subscriber.setMessageListener(this);
		connection.start();
		
	}
	
	/* Close the JMS connection */
	public void close() throws Exception {
		try {
			connection.close();
		} finally {
			if (ic != null) {
				try {
					ic.close();
				} catch (Exception e) {
					throw e;
				}
			}

			try {
				if (connection != null) {
					connection.close();
				}
			} catch (JMSException jmse) {
				System.out.println("Could not close connection " + connection + " exception was " + jmse);
			}
		}
	}

	public synchronized void onMessage(Message message) {
		TextMessage text = (TextMessage) message;
		String filePath = null;
		Charset ENCODING = StandardCharsets.UTF_8;
		try {
			if (null != text) {
				filePath = text.getText();
				System.out.println("\nMessage received: " + filePath+"\n");
				//read file (Note it's XML file you want to parse and read XML please see this documentation
				//http://techiworks.com/read-xml-xalan-java/ or http://techiworks.com/read-xml-file-using-dom-parser/
				Path path = Paths.get(filePath);
				Scanner scanner = new Scanner(path, ENCODING.name());
				while (scanner.hasNextLine()) {
					System.out.println(scanner.nextLine());
				}
				scanner.close();
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}	

}
  • Configure JBoss application server in eclipse using this tutorial
  • To include include all JBoss related jars to to class path: right click project –> properties –> Java build path –> on library tab click add library… –> Server runtime –> if you configured Jboss in eclipse you will see JBoss Runtime server choose it –> click finish.
  • Start JBoss server: Go to %JBOSS_HOME%/bin –> Double click run.bat to start the server. Once server is started it will pick up configured topic automatically.
  • Both class has main method start them separately as java application. Give file path name on publisher console and hit enter:

Send XML File JMS Queue

  • You will see once publisher publish file path message on queue, subscriber will pick up message and process file and print output on console:

Send XML File JMS Queue

download  Download Project:  JMSSendXMLFile

Leave a Reply

Your email address will not be published. Required fields are marked *