Build Publish Subscribe Chat Application in Spring JMS

Use JAR files which are listed below:

activemq-core-5.7.0.jar
activemq-spring-5.12.0.jar
antlr-2.7.7.jar
aopalliance-1.0.jar
aspectjrt-1.8.9.jar
aspectjweaver-1.8.9.jar
com.springsource.org.apache.commons.logging-1.1.1.jar
com.springsource.org.apache.log4j-1.2.15.jar
commons-dbcp2-2.1.1.jar
commons-logging-1.1.3.jar
commons-pool2-2.4.2.jar
dom4j-1.6.1.jar
hibernate-commons-annotations-4.0.2.Final.jar
hibernate-core-4.2.5.Final.jar
hibernate-jpa-2.0-api-1.0.1.Final.jar
javassist-3.15.0-GA.jar
javax.jms-api-2.0.1.jar
jboss-logging-3.1.0.GA.jar
jboss-transaction-api_1.1_spec-1.0.1.Final.jar
jmxtools-1.2.1.jar
mysql-connector-java-5.1.36.jar
spring-aop-4.2.0.RELEASE.jar
spring-aspects-4.3.3.RELEASE.jar
spring-beans-4.2.0.RELEASE.jar
spring-context-4.2.0.RELEASE.jar
spring-context-support-5.0.0.RELEASE.jar
spring-core-4.2.0.RELEASE.jar
spring-expression-4.2.0.RELEASE.jar
spring-jdbc-4.2.0.RELEASE.jar
spring-jms-4.2.0.RELEASE.jar
spring-messaging-5.0.3.RELEASE.jar
spring-orm-4.2.0.RELEASE.jar
spring-oxm-4.2.0.RELEASE.jar
spring-tx-4.2.0.RELEASE.jar

Create Java Project in Eclipse. Right click the project select Build Path\Configure Build Path menu. In Libraries tab, select all jar files above to the project. Besides, we need add appserv-rt library in glassfish4\glassfish\lib folder from GlassFish Server as photo below:

This class contains methods to receive messages from destination

package demo.chat;

import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

public class ChatMessageListener implements MessageListener {

	@Override
	public void onMessage(Message message) {

		try {
			if(message instanceof TextMessage) {
				TextMessage textMessage = (TextMessage) message;
				JFrameChat.textAreaMessages.setText(
					JFrameChat.textAreaMessages.getText()
					+ textMessage.getText()
					+ "\n"
				);
			}
		} catch (Exception e) {
			System.err.println(e.getMessage());
		}

	}

}




The Spring configuration shows a context:component-scan that picks up the JMS producer and listener. Then a JMS connection factory is made for the JmsTemplate to use. The template will be used by the producer to send messages.

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jms="http://www.springframework.org/schema/jms"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
						http://www.springframework.org/schema/beans/spring-beans.xsd
						http://www.springframework.org/schema/context
						http://www.springframework.org/schema/context/spring-context-3.0.xsd
						http://www.springframework.org/schema/jms
   						http://www.springframework.org/schema/jms/spring-jms.xsd">

	<context:component-scan base-package="demo.*"></context:component-scan>

	<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
		<property name="environment">
			<props>
				<prop key="java.naming.factory.initial">com.sun.enterprise.naming.SerialInitContextFactory
				</prop>
				<prop key="java.naming.factory.url.pkgs">com.sun.enterprise.naming</prop>
				<prop key="java.naming.factory.state">com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl
				</prop>
				<prop key="org.omg.CORBA.ORBInitialHost">localhost</prop>
				<prop key="org.omg.CORBA.ORBInitialPort">3700</prop>
			</props>
		</property>
	</bean>

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

	<bean id="destination" class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="jndiTemplate" ref="jndiTemplate" />
		<property name="jndiName" value="spring_jms_topic_destination" />
	</bean>

	<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
		<property name="connectionFactory" ref="connectionFactory" />
		<property name="defaultDestination" ref="destination" />
		<!-- Topic setting -->
   		<property name="pubSubDomain" value="true"/>
	</bean>

	<jms:listener-container
		connection-factory="connectionFactory"
		acknowledge="auto"
		destination-type="topic">
		<jms:listener destination="spring_jms_topic_destination"
			ref="chatMessageListener" method="onMessage"/>
	</jms:listener-container>

	<bean id="chatMessageListener" class="demo.chat.ChatMessageListener"></bean>


</beans>

This class contains methods to send messages to destination

package demo.chat;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Component;

@Component("chatMessageBean")
public class ChatMessageBean {

	@Autowired
	private JmsTemplate jmsTemplate;

	public void sendMessage(String content) {
		try {
			jmsTemplate.send(new MessageCreator() {
				@Override
				public Message createMessage(Session session) throws JMSException {
					return session.createTextMessage(content);
				}
			});
		} catch (Exception e) {
			System.err.println(e.getMessage());
		}
	}

}




Create JFrameChat.java class use Swing controls make Chat GUI

package demo.chat;

import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.UIManager;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

public class JFrameChat extends JFrame {

	private JPanel contentPane;
	private JTextField textFieldMessage;
	public static JTextArea textAreaMessages;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		try {
			UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
		} catch (Throwable e) {
			e.printStackTrace();
		}
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					JFrameChat frame = new JFrameChat();
					frame.setVisible(true);
					new ClassPathXmlApplicationContext("applicationContext.xml");
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public JFrameChat() {
		setTitle("Chat");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 450, 282);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);

		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setBounds(6, 6, 422, 199);
		contentPane.add(scrollPane);

		textAreaMessages = new JTextArea();
		textAreaMessages.setEditable(false);
		scrollPane.setViewportView(textAreaMessages);

		textFieldMessage = new JTextField();
		textFieldMessage.addKeyListener(new KeyAdapter() {
			@Override
			public void keyReleased(KeyEvent e) {
				do_textFieldMessage_keyReleased(e);
			}
		});
		textFieldMessage.setBounds(6, 210, 330, 28);
		contentPane.add(textFieldMessage);
		textFieldMessage.setColumns(10);

		JButton buttonSend = new JButton("Send");
		buttonSend.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				do_buttonSend_actionPerformed(e);
			}
		});
		buttonSend.setBounds(338, 210, 90, 28);
		contentPane.add(buttonSend);
	}

	protected void do_buttonSend_actionPerformed(ActionEvent e) {
		sendMessage();
	}

	protected void do_textFieldMessage_keyReleased(KeyEvent e) {
		if (e.getKeyCode() == KeyEvent.VK_ENTER) {
			sendMessage();
		}
	}

	private void sendMessage() {
		try {
			ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
			ChatMessageBean chatMessageBean = context.getBean("chatMessageBean", ChatMessageBean.class);
			chatMessageBean.sendMessage(textFieldMessage.getText());
			textFieldMessage.setText("");
			context.close();
		} catch (Exception e) {
			JOptionPane.showMessageDialog(null, e.getMessage());
		}
	}

}

Run JFrameChat.java 4 times. The program will display 4 windows as 4 users join chat