JMS (Java Messagin Service) with Wildfly

Integration solution in JAVA EE, there are web services (JAX-WS, JAX-RS) and Java Message Service. Java Message Service provide asynchronize communication. Asynchronize communication allow communication any point of time between server and client. In this post I will show how to use Java Messaging Service in Wildfly.

Enable JMS(Activemq) in Wildfly


In Wildfly JMS, Activemq is used for message broker. In order to enable message broker in Wildfly. You need to use standalone-full.xml instead of standalone.xml. To use use standalone-full.xml, you need to change currently standalone.xml to other file name like (standalone.xml.org), then you rename the standalone-full.xml to standalone.xml.

$cd $JBOSS_HOME/standalone/configuration
$mv standalone.xml standalone.xml.org
$mv standalone-full.xml standalone.xml

Next is to restart your server.
$cd $JBOSS_HOME/bin
$bash startup.sh
To create message queue, you can use admin console to create queue by configuration ----> Subsystems ----> Messaging- ActiveMQ

Go to Messagin ActiveMQ
Create Messaging Provider
Create Messaging Provider
Create Message Queue
Add Queue
Finish
Restart Server

Now you have your message queue for asynchronized communication.

Create Message Producer

Next is to create your Message Producer (message sender or generator). To create message producer you just create an EJB project.
Select EJB Project
Put EJB Project
Click Next
Finish
Then you need to create messages sender class
Create Class
Create class as below.
package pro.itstikk.wildfly;

import javax.annotation.Resource;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.jms.JMSContext;
import javax.jms.Queue;

/**
 * Session Bean implementation class MessageSender
 */
@Stateless(mappedName = "messageSender")
@LocalBean
public class MessageSender {

    /**
     * Default constructor.
     */
    public MessageSender() {
        super();
    }
   
    @Resource(mappedName = "java:/queue/test")
    private Queue testQueue;
    @Inject
    private JMSContext jmsContext;

    public void enqueue(final String message) {
        jmsContext.createProducer().send(testQueue, message);
    }
}
Now you have message sender

Message Consumer

Next is to create message receiver (Message Driven Bean).

Create Message Driven Bean
Finish
Inside this class add below
package pro.itstikk.wildfly;

import java.util.logging.Logger;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;


/**
 * Message-Driven Bean implementation class for: MessageReciever
 */
@MessageDriven(
activationConfig = { @ActivationConfigProperty(
propertyName = "destination", propertyValue = "testQueue"), @ActivationConfigProperty(
propertyName = "destinationType", propertyValue = "javax.jms.Queue")
},
mappedName = "testQueue")
public class MessageReciever implements MessageListener {
private final static Logger LOGGER = Logger.getLogger(MessageReciever.class.toString());
    /**
     * Default constructor.
     */
    public MessageReciever() {
        super();
    }

/**
     * @see MessageListener#onMessage(Message)
     */
    public void onMessage(Message message) {
    if (message instanceof TextMessage) {
            try {
                final String text = ((TextMessage) message).getText();
                LOGGER.info(() -> "Received: " + text);
            } catch (final JMSException e) {
                throw new RuntimeException(e);
            }
        }
    }

}

Test your messaging class, you can create web dynamic project. I have create my web project and create MessageBean class and send.xhtml file.
package com.jsf.bean;

import javax.ejb.EJB;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

import pro.itstikk.wildfly.MessageSender;

@Named("messageBean")
@RequestScoped
public class MesssageBean {
@EJB
private MessageSender messageSender;
private String message;

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public String send() {
messageSender.enqueue(message);
return "save.xhtml";
}
}
Next is to create send.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:rich="http://richfaces.org/rich"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:a4j="http://richfaces.org/a4j"
      xmlns:h="http://java.sun.com/jsf/html">

<h:head></h:head>
<body>
    <rich:panel>
        <f:facet name="header">
        Write your own custom rich components with built-in AJAX support
        </f:facet>
<h:form>
<p>
<h:outputLabel value="firstname: " />
<rich:inplaceInput value="#{messageBean.message}" defaultLabel="firstname"/>
</p>
<h:commandButton action="#{messageBean.send}" value="send" />
</h:form>
</rich:panel>
</body>
</html>
Now you can see as below.

Input Message
Message Show Here

Connecting and Send message to remote Message Queue

In order to send to and/or receiver message from remote queue in Wildfly Messaging service, you need to

  1. create user to access JMS Queue.
  2. export your message.
  3. Create message sender to and receiver from target queue.
First, you need to create user to access remote queue.
$cd $JBOSS_HOME/bin
$bash add-user.sh -a -u 'jms-user' -p 'P@assword1!' -g 'guest' 
Next is to export queue. In order to export your queue for remote connection, you need to edit your configuration file (standalone-full.xml)
$cd $JBOSS_HOME/standalone/configuration
$vim standalone-full.xml
And edit as below.
 <server name="testQueue">
    <security enabled="false"/>
        <jms-queue name="testQueue" entries="java:/queue/test java:/jboss/exported/jms/queue/test"/>
  </server>
Then you just restart your wildfly server. and you can see as below.
Export queue
Now you can connect to the queue be create producer as below.
package pro.itstikk.jms.app;

import static org.junit.Assert.assertEquals;

import java.util.Properties;

import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSConsumer;
import javax.jms.JMSContext;
import javax.naming.Context;
import javax.naming.InitialContext;

import org.junit.Test;

public class TestJMSProducer {
private String MESSAGE = "Hello, Wildfly 10 Queue, this is test message";
    private String CONNECTION_FACTORY = "jms/RemoteConnectionFactory";
    private String DESTINATION = "jms/queue/test";
    //jms/queue/ExampleQueue
    @Test
    public void testSendReceive() throws Exception {

        Context namingContext = null;
        JMSContext context = null;

        try {

            // Set up the namingContext for the JNDI lookup
            final Properties env = new Properties();
            env.put(Context.INITIAL_CONTEXT_FACTORY,
                    "org.jboss.naming.remote.client.InitialContextFactory");
            env.put(Context.PROVIDER_URL, "http-remoting://wildfly.itstikk.pro:8080");
            env.put(Context.SECURITY_PRINCIPAL, "jms-user");
            env.put(Context.SECURITY_CREDENTIALS, "P@ssword1!");
            namingContext = new InitialContext(env);

            ConnectionFactory connectionFactory = (ConnectionFactory) namingContext
                    .lookup(CONNECTION_FACTORY);
            System.out.println("Got ConnectionFactory " + CONNECTION_FACTORY);

            Destination destination = (Destination) namingContext
                    .lookup(DESTINATION);
            System.out.println("Got JMS Endpoint " + DESTINATION);

            // Create the JMS context
            context = connectionFactory.createContext("jms-user", "P@ssword1!");

            for (int i=0;i<1000;i++) {
            context.createProducer().send(destination, MESSAGE+" # "+i);
            }
            System.out.println("Sent message " + MESSAGE);

            System.out.println("==================================================== ");
            System.out.println("Finished !");
           
            assert(true);

        } catch (Exception e) {
            System.out.println(e.getMessage());
            throw e;
        } finally {
            if (namingContext != null) {
                namingContext.close();
            }

            // closing the context takes care of consumer too
            if (context != null) {
                context.close();
            }
        }
    }
}
For consumer which remotely consume message from the queue you can create as below
package pro.itstikk.jms.app;

import static org.junit.Assert.assertEquals;

import java.util.Properties;

import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSConsumer;
import javax.jms.JMSContext;
import javax.naming.Context;
import javax.naming.InitialContext;

import org.junit.Test;

public class TestJMSConsumer {

    private String CONNECTION_FACTORY = "jms/RemoteConnectionFactory";
    private String DESTINATION = "jms/queue/test";
    //jms/queue/ExampleQueue
    @Test
    public void testSendReceive() throws Exception {

        Context namingContext = null;
        JMSContext context = null;

        try {

            // Set up the namingContext for the JNDI lookup
            final Properties env = new Properties();
            env.put(Context.INITIAL_CONTEXT_FACTORY,
                    "org.jboss.naming.remote.client.InitialContextFactory");
            env.put(Context.PROVIDER_URL, "http-remoting://wildfly.itstikk.pro:8080");
            env.put(Context.SECURITY_PRINCIPAL, "jms-user");
            env.put(Context.SECURITY_CREDENTIALS, "P@ssword1!");
            namingContext = new InitialContext(env);

            ConnectionFactory connectionFactory = (ConnectionFactory) namingContext
                    .lookup(CONNECTION_FACTORY);
            System.out.println("Got ConnectionFactory " + CONNECTION_FACTORY);

            Destination destination = (Destination) namingContext
                    .lookup(DESTINATION);
            System.out.println("Got JMS Endpoint " + DESTINATION);

            // Create the JMS context
            context = connectionFactory.createContext("jms-user", "P@ssword1!");

            // Create the JMS consumer
            JMSConsumer consumer = context.createConsumer(destination);
            //Then receive the same number of messages that were sent

            String text = consumer.receiveBody(String.class, 5000);
            if (text == null) System.out.println("No message Received! Maybe another Consumer listening on the Queue ??");
            System.out.println("Received message with content " + text);
            //assertEquals(text,MESSAGE);
            assert(true);

        } catch (Exception e) {
            System.out.println(e.getMessage());
            throw e;
        } finally {
            if (namingContext != null) {
                namingContext.close();
            }

            // closing the context takes care of consumer too
            if (context != null) {
                context.close();
            }
        }
    }
}
For your maven pom.xml, you can add
<properties>
  <version.wildfly>10.0.0.Final</version.wildfly>
  </properties>
  <dependencies>
  <dependency>
        <groupId>org.wildfly</groupId>
        <artifactId>wildfly-jms-client-bom</artifactId>
        <version>${version.wildfly}</version>
        <type>pom</type>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
    </dependency>
  </dependencies>

After you execute program you could see as below.






Reference



No comments:

Post a Comment

Feature Recently

Running Wildfly Application Server in Domain Mode

  Wildfly application server provides two modes of how to run application one wildfly application server. It is very simple if you run your ...

Most Views