How to create EJB3 MDB Queue project in Eclipse (JBoss 6.1)

4 June 2012 By Nithya Vasudevan 17,106 views 16 Comments
6 Flares Twitter 0 Facebook 0 Google+ 6 6 Flares ×

Environment Used

  • JDK 6 (Java SE 6)
  • JMS Sender/Client – Java Application Client (main())
  • JMS Consumer – EJB 3.0 Message Driven Bean (MDB)
  • Eclipse Indigo IDE for Java EE Developers (3.7.1)
  • JBoss Tools – Core 3.3.0 M5 for Eclipse Indigo (3.7.1)
  • JBoss Application Server (AS) 6.1.0 Final

Setting up development environment:

Read this page for installing and setting up the environment for developing and deploying EJB 3.0 on JBoss application server.

Project Description

  • We are going to create a simple EJB 3 Message Driven Bean and a Java Application client (main()) which sends messages to the Queue destination.
  • This example explains how to develop, deploy and run EJB3 MDB as a message consumer in JBoss application server.
  • For testing this MDB listener, we write a Java Application Client (main()) as a message producer which sends a simple text message and an object message.
  • The message driven bean (message consumer) is created in a EJB project and the Java Application Client (message producer) is created in a separate Java project. To make this work, client needs required JAR file in its classpath.

Creating New EJB Project

  • Open Eclipse IDE and create a new EJB project which can be done in three ways,
    • Right click on Project Explorer -> New -> EJB Project
    • File menu -> New -> EJB Project
    • Click on the down arrow on New icon on toolbar -> EJB Project
  • Enter the project name as “FirstMDBProject” and make sure the JBoss 6.x Runtime has been selected with the EJB 3.0 Module version.

Creating object message class

  • Right click on ejbModule -> New -> Class
  • Enter the Java package name as com.theopentutorials.mdb.to
  • Enter the Class name as Employee
  • Click “Finish

Copy the following code:

package com.theopentutorials.mdb.to;
import java.io.Serializable;
public class Employee implements Serializable {
	private int id;
	private String name;
	private String designation;
	private double salary;
	
	public Employee() {	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getDesignation() {
		return designation;
	}
	public void setDesignation(String designation) {
		this.designation = designation;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	
	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + 
				", designation=" + designation + 
				", salary=" + salary + "]";
	}
}

Creating Message Driven Bean Consumer

  • Right click on ejbModule -> New -> Message-Driven Bean (EJB 3.x)
  • Enter the Java package name as com.theopentutorials.mdb
  • Enter the Class name as QueueListenerMDB
  • Select the Destination type as Queue
  • Click “Finish

Copy the following code:

package com.theopentutorials.mdb;
import java.util.Date;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.TextMessage;
import com.theopentutorials.mdb.to.Employee;

@MessageDriven(activationConfig = {
		@ActivationConfigProperty(
				propertyName = "destinationType", 
				propertyValue = "javax.jms.Queue"),
		@ActivationConfigProperty(
				propertyName = "destination", 
				propertyValue = "queue/MyQueue") })
public class QueueListenerMDB implements MessageListener {
	public QueueListenerMDB() {
	}

	public void onMessage(Message message) {
		try {
			if (message instanceof TextMessage) {
				System.out.println("Queue: I received a TextMessage at "
						+ new Date());
				TextMessage msg = (TextMessage) message;
				System.out.println("Message is : " + msg.getText());
			} else if (message instanceof ObjectMessage) {
				System.out.println("Queue: I received an ObjectMessage at "
						+ new Date());
				ObjectMessage msg = (ObjectMessage) message;
				Employee employee = (Employee) msg.getObject();
				System.out.println("Employee Details: ");
				System.out.println(employee);
			} else {
				System.out.println("Not valid message for this Queue MDB");
			}
		} catch (JMSException e) {
			e.printStackTrace();
		}
	}
}
  • The activationConfig property of @MessageDriven is an array of ActivationConfigProperty and it should specify the destinationType (Queue or Topic) and destination (Queue/Topic’s JNDI name).
  • In the onMessage() we are receiving two types of message, TextMessage and ObjectMessage.

Configuring messaging services on JBoss AS 6

  • JBoss AS 6 uses HornetQ instead of JBoss Messaging.
  • To configure this we must create a “*-hornetq-jms.xml” file.
  • This file can be placed either inside
    • application’s META-INF folder (Specific for this application)
    • or JBossAS_Home/server/default/deploy (can be used by any application inside this server).
  • The *-hornetq-jms.xml files are picked up by JBoss AS and the queue/topics defined in that file will be deployed.
  • Create a new XML file in META-INF folder and name it as “mdb-hornetq-jms.xml” and copy the following:
<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="urn:hornetq"
    xsi:schemaLocation="urn:hornetq /schema/hornetq-jms.xsd" >

    <queue name="MyQueue2" >
        <entry name="/queue/MyQueue" />
    </queue>

</configuration>

The queue’s entry name “queue/MyQueue” should match destination activation config property in @MessageDriven.

EJB Project Folder Structure

The complete folder structure of EJB project is shown below:

Deploying EJB project

  • Now we need to deploy the EJB project “FirstMDBProject” on server..
  • Deploying the project can be done in two ways,
    • Right click on the EJB project -> Run As -> Run On Server. Select the existing “JBoss 6.x Runtime Server” and click Finish.
    • Right click on “JBoss 6.x Runtime Server” available in Servers view -> Add and Remove… -> Select the EJB JAR file from the left pane and click Add-> and then Finish.

Start/Restart the Server

Right click on “JBoss 6.x Runtime Server” from Servers view and click on Start if it has not yet been started.

Creating Client Project

  • Create a new Java Project and name it as “FirstMDBClient”.

Creating JAR file

Since EJB and Client are in different project, to send the object message client needs to know the definition of Employee class. Let’s create a JAR file containing Employee.class and place it in Client’s classpath.

  • Right click on Employee.java file in FirstMDBProject -> Export.
  • Expand Java folder and select “JAR file” and click Next.
  • Click on Browse… and enter the file name and Finish.

Adding required JAR files

You can add the required JAR files in Build path (Right click on your client Project (FirstMDBClient)->Properties, select Java Build Path from left side pane and select Libraries from right side and click on Add External JARs)

Add the following JAR files.

JAR nameWhere to find
jbossall-client.jarJBossAS_Home/client
Employee.jarCreated in the above step

Creating ClientUtility class

  • Java Application Client uses JNDI API to look up EJB components in a network.
  • This is a utility class which can be reused in all applications. Otherwise the code written in this class should be repeated in all clients.
  • Right click on src folder -> New -> Class
  • Enter the package name as com.theopentutorials.utility
  • Enter the Class name as ClientUtility
  • Click on Finish

Copy the following code:

package com.theopentutorials.utility;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class ClientUtility {

	private static final String PROVIDER_URL = 
		"jnp://localhost:1099";

	private static final String JNP_INTERFACES = 
		"org.jboss.naming:org.jnp.interfaces";

	private static final String INITIAL_CONTEXT_FACTORY = 
		"org.jnp.interfaces.NamingContextFactory";

	private static Context initialContext;

	public static Context getInitialContextForClient()
			throws NamingException {
		if (initialContext == null) {
			Properties prop = new Properties();
			prop.put(Context.INITIAL_CONTEXT_FACTORY, 
					INITIAL_CONTEXT_FACTORY);
			prop.put(Context.URL_PKG_PREFIXES, 
					JNP_INTERFACES);
			prop.put(Context.PROVIDER_URL, PROVIDER_URL);
			initialContext = new InitialContext(prop);
		}
		return initialContext;
	}
}

Creating Client class

  • Now lets create a client class which sends messages to the queue destination.
  • Right click on src folder -> New -> Class
  • Enter the package name as com.theopentutorials.client
  • Enter the Class name as QueueSenderDemo
  • Click on Finish

Copy the following code

package com.theopentutorials.client;
  
import javax.jms.JMSException;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.NamingException;
import com.theopentutorials.mdb.to.Employee;
import com.theopentutorials.utility.ClientUtility;

public class QueueSenderDemo {
	private static final String QUEUE_LOOKUP = "queue/MyQueue";
	private static final String CONNECTION_FACTORY = "ConnectionFactory";

	public static void main(String[] args) {
		sendMessageToQueue();
		sendObjectMessageToQueue();
	}

	public static void sendMessageToQueue() {
		try {
			Context context = ClientUtility.getInitialContextForClient();
			QueueConnectionFactory factory = (QueueConnectionFactory) context
					.lookup(CONNECTION_FACTORY);
			QueueConnection connection = factory.createQueueConnection();
			QueueSession session = connection.createQueueSession(false,
					QueueSession.AUTO_ACKNOWLEDGE);
			Queue queue = (Queue) context.lookup(QUEUE_LOOKUP);

			QueueSender sender = session.createSender(queue);
			TextMessage message = session.createTextMessage();
			message.setText("Welcome to EJB3");
			sender.send(message);
			session.close();
		} catch (NamingException e) {
			e.printStackTrace();
		} catch (JMSException e) {
			e.printStackTrace();
		}
	}

	public static void sendObjectMessageToQueue() {
		try {
			Context context = ClientUtility.getInitialContextForClient();
			QueueConnectionFactory factory = (QueueConnectionFactory) context
					.lookup(CONNECTION_FACTORY);
			QueueConnection connection = factory.createQueueConnection();
			QueueSession session = connection.createQueueSession(false,
					QueueSession.AUTO_ACKNOWLEDGE);
			Queue queue = (Queue) context.lookup(QUEUE_LOOKUP);

			QueueSender sender = session.createSender(queue);
			ObjectMessage message = session.createObjectMessage();
			Employee emp = new Employee();
			emp.setDesignation("Developer");
			emp.setSalary(25000);
			emp.setName("ABC");
			emp.setId(1);
			message.setObject(emp);
			sender.send(message);
			session.close();
		} catch (NamingException e) {
			e.printStackTrace();
		} catch (JMSException e) {
			e.printStackTrace();
		}
	}
}

Client project folder structure

Run the client

Use Ctrl + F11 to run the client (QueueSenderDemo).
JBoss Runtime Server Console will display the following output.

[STDOUT] Queue: I received a TextMessage at Mon Jun 04 11:43:41 IST 2012
[STDOUT] Message is : Welcome to EJB3
[STDOUT] Queue: I received an ObjectMessage at Mon Jun 04 11:43:41 IST 2012
[STDOUT] Employee Details:
[STDOUT] Employee [id=1, name=ABC, designation=Developer, salary=25000.0]

Tags: , , , , , , , , , , ,

  • Pingback: JavaPins

  • Bhaskar

    Among of the very good tutorial i came across.It is very much intutive.Worth to go through this.

  • Chamila

    Excellent tutorial. Works. Great tutorial

  • Shabna

    Great tutorial.Simple and Straightforward and it works at single shot.!!

  • pavan

    very good tutorial… keep up the good work

  • Srinivas

    Excellent post about MDB. Best found on the web. Great work Nitya…..

  • Srinivas

    Hi Nithya. Can you please provide Download link for project as war or jar rather than copying each class?

  • nadia

    hi…
    i followed all the instructions above but why when i run i get this error

    Cannot run program “C:UsersmdabdulkDocumentseclipse-jee-indigo-SR2-win32-x86_64eclipsejreinjavaw.exe” (in directory “C:UsersmdabdulkworkspaceFirstMDBProject”): CreateProcess error=206, The filename or extension is too long

  • Fabio

    Congratulations is a great example, very simple and very util.

  • Kalai

    Nice Tutorial to Start with MDB …Thank u So Much Nithya…

  • gp

    I followed all the steps.
    Some reason getting below error. Please advise

    log4j:WARN No appenders could be found for logger (org.jnp.interfaces.TimedSocketFactory).
    log4j:WARN Please initialize the log4j system properly.
    log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
    javax.naming.NameNotFoundException: MyQueue not bound
    at org.jnp.server.NamingServer.getBinding(NamingServer.java:771)
    at org.jnp.server.NamingServer.getBinding(NamingServer.java:779)
    at org.jnp.server.NamingServer.getObject(NamingServer.java:785)
    at org.jnp.server.NamingServer.lookup(NamingServer.java:443)
    at org.jnp.server.NamingServer.lookup(NamingServer.java:399)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
    at sun.rmi.transport.Transport$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Unknown Source)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
    at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Unknown Source)
    at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source)
    at sun.rmi.server.UnicastRef.invoke(Unknown Source)
    at org.jnp.server.NamingServer_Stub.lookup(Unknown Source)
    at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:728)
    at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:688)
    at javax.naming.InitialContext.lookup(Unknown Source)
    at com.theopentutorials.client.QueueSenderDemo.sendMessageToQueue(QueueSenderDemo.java:33)
    at com.theopentutorials.client.QueueSenderDemo.main(QueueSenderDemo.java:21)
    javax.naming.NameNotFoundException: MyQueue not bound
    at org.jnp.server.NamingServer.getBinding(NamingServer.java:771)
    at org.jnp.server.NamingServer.getBinding(NamingServer.java:779)
    at org.jnp.server.NamingServer.getObject(NamingServer.java:785)
    at org.jnp.server.NamingServer.lookup(NamingServer.java:443)
    at org.jnp.server.NamingServer.lookup(NamingServer.java:399)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
    at sun.rmi.transport.Transport$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Unknown Source)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
    at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Unknown Source)
    at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source)
    at sun.rmi.server.UnicastRef.invoke(Unknown Source)
    at org.jnp.server.NamingServer_Stub.lookup(Unknown Source)
    at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:728)
    at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:688)
    at javax.naming.InitialContext.lookup(Unknown Source)
    at com.theopentutorials.client.QueueSenderDemo.sendObjectMessageToQueue(QueueSenderDemo.java:55)
    at com.theopentutorials.client.QueueSenderDemo.main(QueueSenderDemo.java:22)

  • Darren

    Hi Nithya, thank you for the concise tutorial, was very helpful.

  • Vijay

    Urgent: I follwed the same but JBoss server is not showing any output. MDB is not triggering during Client access….pls guide me.

  • kumar shorav

    Hi NIthya,

    I have a Restful service API developed with JAX-RS and jersey. I have deployed
    the same in TOMCAT 7. Now I would like to implement Activemq so that I would
    keep all request in a queue and process the request resource. How to do this
    and integrate with tomcat7. How to integrate ActiveMq with Tomcat7 or my rest
    service webapp. How to call the service.

    Important
    :- Inside the Rest Api, I am using FilterChaining concept for security concern
    and after verification of the calling party, I am simply forwarding the request
    to the resource. For this I have added in web.xml.

    Basically
    I want a asynchronous communication and do not want to miss any request. Please
    suggest some way. I would like to keep all httprequest in queue and then get
    the result and forward to the client as usual.

    Right
    now I am calling the service and getting the xml or json result. It should work
    like same but in between ActiveMq should work that will provide queue service.
    I am very new in this. Please Help!!!!!!

    Thanks
    a lot for your time.

  • Gokul

    Hi,

    I tried the above example. I using JBOSS 6 and JDK 1.6.0_24. and I’m getting the below exception. Can Anyone help me to resolve this issue?

    javax.naming.CommunicationException: Could not obtain connection to any of these urls: localhost:1099 and discovery failed with error: javax.naming.CommunicationException: Receive timed out [Root exception is java.net.SocketTimeoutException: Receive timed out] [Root exception is javax.naming.CommunicationException: Failed to connect to server localhost/127.0.0.1:1099 [Root exception is javax.naming.ServiceUnavailableException: Failed to connect to server localhost/127.0.0.1:1099 [Root exception is java.net.ConnectException: Connection refused: connect]]]

    at org.jnp.interfaces.NamingContext.checkRef(NamingContext.java:1763)

    at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:693)

    at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:686)

    at javax.naming.InitialContext.lookup(InitialContext.java:392)

    at com.theopentutorials.client.QueueSenderDemo.sendMessageToQueue(QueueSenderDemo.java:29)

    at com.theopentutorials.client.QueueSenderDemo.main(QueueSenderDemo.java:21)

    Caused by: javax.naming.CommunicationException: Failed to connect to server localhost/127.0.0.1:1099 [Root exception is javax.naming.ServiceUnavailableException: Failed to connect to server localhost/127.0.0.1:1099 [Root exception is java.net.ConnectException: Connection refused: connect]]

    at org.jnp.interfaces.NamingContext.getServer(NamingContext.java:335)

    at org.jnp.interfaces.NamingContext.checkRef(NamingContext.java:1734)

    … 5 more

    Caused by: javax.naming.ServiceUnavailableException: Failed to connect to server localhost/127.0.0.1:1099 [Root exception is java.net.ConnectException: Connection refused: connect]

    at org.jnp.interfaces.NamingContext.getServer(NamingContext.java:305)

    … 6 more

    Caused by: java.net.ConnectException: Connection refused: connect

    at java.net.PlainSocketImpl.socketConnect(Native Method)

    at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)

    at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)

    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)

    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)

    at java.net.Socket.connect(Socket.java:529)

    at org.jnp.interfaces.TimedSocketFactory.createSocket(TimedSocketFactory.java:97)

    at org.jnp.interfaces.TimedSocketFactory.createSocket(TimedSocketFactory.java:82)

    at org.jnp.interfaces.NamingContext.getServer(NamingContext.java:301)

    … 6 more

    javax.naming.CommunicationException: Could not obtain connection to any of these urls: localhost:1099 and discovery failed with error: javax.naming.CommunicationException: Receive timed out [Root exception is java.net.SocketTimeoutException: Receive timed out] [Root exception is javax.naming.CommunicationException: Failed to connect to server localhost/127.0.0.1:1099 [Root exception is javax.naming.ServiceUnavailableException: Failed to connect to server localhost/127.0.0.1:1099 [Root exception is java.net.ConnectException: Connection refused: connect]]]

    at org.jnp.interfaces.NamingContext.checkRef(NamingContext.java:1763)

    at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:693)

    at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:686)

    at javax.naming.InitialContext.lookup(InitialContext.java:392)

    at com.theopentutorials.client.QueueSenderDemo.sendObjectMessageToQueue(QueueSenderDemo.java:51)

    at com.theopentutorials.client.QueueSenderDemo.main(QueueSenderDemo.java:22)

    Caused by: javax.naming.CommunicationException: Failed to connect to server localhost/127.0.0.1:1099 [Root exception is javax.naming.ServiceUnavailableException: Failed to connect to server localhost/127.0.0.1:1099 [Root exception is java.net.ConnectException: Connection refused: connect]]

    at org.jnp.interfaces.NamingContext.getServer(NamingContext.java:335)

    at org.jnp.interfaces.NamingContext.checkRef(NamingContext.java:1734)

    … 5 more

    Caused by: javax.naming.ServiceUnavailableException: Failed to connect to server localhost/127.0.0.1:1099 [Root exception is java.net.ConnectException: Connection refused: connect]

    at org.jnp.interfaces.NamingContext.getServer(NamingContext.java:305)

    … 6 more

    Caused by: java.net.ConnectException: Connection refused: connect

    at java.net.PlainSocketImpl.socketConnect(Native Method)

    at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)

    at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)

    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)

    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)

    at java.net.Socket.connect(Socket.java:529)

    at org.jnp.interfaces.TimedSocketFactory.createSocket(TimedSocketFactory.java:97)

    at org.jnp.interfaces.TimedSocketFactory.createSocket(TimedSocketFactory.java:82)

    at org.jnp.interfaces.NamingContext.getServer(NamingContext.java:301)

    … 6 more

  • davehu

    try Long Path Tool