• No results found

Creating a Message Driven EJB

In document NetBeans IDE 8 Cookbook (Page 186-193)

A Message Driven EJB is a special type of EJB that is responsible for listening to messages sent to JMS queues and acting upon them. Message Driven EJBs provide an easy way of interfacing with JMS queues and make full use of Java annotations to define queue settings.

In this recipe, we'll see how we can send a message to a JMS queue hosted on WildFly, and then how a Message Driven Bean will respond to the message.

Getting ready

In order to complete this recipe, we need to have an instance of WildFly installed locally and configured within NetBeans. We will be using the Enterprise download bundle of NetBeans as this provides all of the necessary plugins required to work with EJBs.

To send messages to a JMS queue, we first need to create the queue within WildFly.

Since the WildFly plugin for NetBeans can't currently create message queues, we'll need to create a message queue using the WildFly command-line interface.

Start WildFly from NetBeans within the Services explorer.

The WildFly CLI is located within the WildFly\bin folder, so open a command prompt (or terminal), change to the WildFly\bin folder of your local distribution and start the CLI:

jboss-cli.bat (for Windows users) or ./jboss-cli.sh (for Mac OS X and Linux users).

Once the CLI has started, you need to connect to the running instance of WildFly. This is achieved with the connect command with the CLI:

[disconnected /] connect

Now that we're connected to WildFly, execute the following command to create a message queue called cookbookQueue:

[standalone@localhost:9990 /] jms-queue add –queue-address=cookbookQueue –entries=java:/jms/queue/cookbookQueue

Once the queue has been added via the CLI, we can verify that it has been deployed correctly by opening up the JMS Destinations node within the WildFly Application Server node in the Services explorer:

How to do it…

Perform the following steps:

1. Click on File and then New Project….

2. In the New Project dialog, select Java Web from the list of Categories, and Web Application from the list of Projects.

3. Click on Next.

4. Enter Project Name as MessageBeans. 5. Click on Next.

6. Ensure that Add to Enterprise Application is not set, and that the Server is set to WildFly Application Server, Java EE Version is set to Java EE 7 Web, and the Context Path is set to /MessageBeans.

7. Click on Finish.

8. Right-click on the MessageBeans project within the Projects explorer and click on New and then Other….

9. In the New File dialog, select Enterprise JavaBeans from the list of Categories and Message-Driven Bean from the list of File Types.

10. Click on Next.

11. In the New Message-Driven Bean dialog, specify EJB Name as

CookbookQueueListenerBean and the Package name as com.davidsalter.

cookbook.messagebeans.

12. Select the cookbookQueue queue from the dropdown by the Server Destinations radio button.

13. Click on the Next button.

14. The Activation Config Properties dialog will now be shown. Since we don't need to change any of the defaults here, click on Finish.

A basic Message Driven Bean has now been created by NetBeans. Let's add some basic logging to the bean so that we can see what messages are sent to it. Perform the following steps:

Ensure that the CookbookQueueListenerBean.java file is open for editing, and change the onMessage() method to the following:

@Override

public void onMessage(Message message) { try {

if (message instanceof TextMessage) {

TextMessage txtMessage = (TextMessage) message;

System.out.println("I've got a message:" + txtMessage.

getText());

}

} catch (JMSException e) {

throw new RuntimeException(e);

} }

This is a very simplistic implementation of what to do when a Message Driven Bean receives a message, but it does show how to get the text contents out of TextMessage and that we need to be catching JMSExceptions just in case of any runtime errors.

That's all we need to do to define a Message Driven Bean. Let's now create a servlet that will post messages to the bean. Perform the following steps:

1. Right-click on the MessageBeans project within the Projects explorer and select New and then Other….

2. In the New File dialog, select Web from the Categories list and Servlet from the list of File Types.

3. Click on Next.

4. In Class Name, enter SendMessageServlet and in the Package name, enter com.

davidsalter.cookbook.messagebeans. 5. Click on Next.

6. In this recipe, we are not going to define the servlet via the web.xml file, so click on Finish. NetBeans will register the servlet via annotations instead of XML.

A servlet called SendMessageServlet has now been created and opened within NetBeans for editing. Let's change the servlet so that it sends a message to our message queue when the servlet is invoked. Perform the following steps:

1. Inject a reference to JMSContext and the message queue into the servlet by adding the following code to the beginning of the SendMessageServlet class:

@Inject

private JMSContext context;

@Resource(mappedName="java:/jms/queue/cookbookQueue") private Queue queue;

2. Send a message to the message queue by changing the processRequest() method body to read:

response.setContentType("text/html;charset=UTF-8");

String message = "Message sent at: " + new Date();

context.createProducer().send(queue, message);

try (PrintWriter out = response.getWriter()) { out.println("<!DOCTYPE html>");

out.println("<title>Servlet SendMessageServlet</title>");

out.println("</head>");

out.println("<body>");

out.println("<p>" + message + "</p>");

out.println("</body>");

out.println("</html>");

}

As we are using Contexts and Dependency Injection (CDI), we need to add a beans.xml file into our project; otherwise, @Inject will not resolve correctly and the context variable will be set to null. Perform the following steps:

1. Right-click on the MessageBeans project within the Projects explorer and click on New and then Other….

2. Select Contexts and Dependency Injection from the list of Categories and beans.

xml (CDI Configuration File) from the list of File Types.

3. Click on Next.

4. Click on Finish to create the file.

The application is now complete, so we can run it and test it out. Right-click on the SendMessageServlet.java file in the Projects explorer and then select Run File.

As we have no request parameters to add to the URL, click on OK to launch your default browser and invoke the servlet.

The default browser will now open. Open the http://localhost:8080/MessageBeans/

SendMessageServlet URL to access the servlet and send a message to the message queue.

The date and time of the message will be displayed in the browser, as shown in the following screenshot:

The date and time of the message will also be shown in the WildFly Application Server Output window, as shown in the following screenshot:

How it works…

The first task in this recipe was to create a Message Driven Bean. In Java EE 7, a Message Driven Bean is simply a POJO that is annotated with the @MessageDriven annotation.

Our Message Driven Bean was annotated as follows:

@MessageDriven(activationConfig = {

These annotations declare the Message Driven Bean as well as stating that the bean will listen to a javax.jms.Queue and that the cookbookQueue queue will be called.

If we'd wanted to listen to a topic instead, we would simply have specified destinationType as javax.jms.Topic.

A message sent to a JMS queue will be received by only one listener. Only one Message Driven Bean can receive a message sent to a queue. A topic, on the other hand, works more like a publish/subscribe model where a message sent to a topic can be received by zero or more listeners.

Within Message Driven Beans, messages are delivered to the onMessage() method.

In our implementation, we checked to see if the message was of the type TextMessage (we had foreknowledge that it would always be of this type!) and if it was, we cast the received message into TextMessage and then extracted the message using the .getText() method.

To send a message to the Message Driven Bean, we used CDI to make things a lot easier. We injected a JMSContext into a servlet. We injected a reference to our queue into the servlet as well using the @Resource annotation to specify the queue we wanted to use. Finally, we sent a text message by calling the context.createProoducer().send() method.

There's more

What if we wanted to send more than a simple text to a message queue? Is that possible?

It certainly is. The send() method of the JMSProducer class allows us to send a Map, a Message, a Serializable, or a byte[] as well as sending a String. If we are to send objects of these types to the Message Driven Bean, then we must remember that the type of message received by the OnMessage() method will be either BytesMessage, MapMessage, ObjectMessage, or StreamMessage. For further information about sending different types of messages, check out the Oracle Message documentation at http://docs.oracle.

com/javaee/7/api/javax/jms/Message.html.

Manually injecting JMSContext and Queue involved too much typing! Can NetBeans make this any easier? It certainly can. Right-clicking within the body of a class (for example in a session bean) and selecting the Insert code… menu item provides the option to Send JMS Message…. From this dialog, we can specify queues and topics to send messages to and then automatically generate the required code.

In document NetBeans IDE 8 Cookbook (Page 186-193)