Search code examples
javajbossjmsejbwildfly

Wildfly jms configuration


I'm having troubles with migration from old JBoss to Wildfly 14 (or some other latest version).
Currently I'm stuck with JMS configuration.
Here is the configuration:

  • In <subsystem xmlns="urn:jboss:domain:messaging-activemq:4.0">I have added two queue definitions with the following code
    <jms-queue name="MyQueue" entries="java:/jms/queue/MyQueue"/> <jms-queue name="OtherQueue" entries="java:/jms/queue/OtherQueue"/>
  • In mentioned above subsystem definition I've added the following connection factory definition <connection-factory name="InVmConnectionFactory" entries="java:/ConnectionFactory" connectors="in-vm" />
  • In my application initialization code I have code which instantiates these jms queues.

In my class I have the following fields

private static final String JMS_CONNECTION_FACTORY_JNDI_NAME = "java:/ConnectionFactory";
@Resource(mappedName=JMS_CONNECTION_FACTORY_JNDI_NAME)
ConnectionFactory factory;

and in this class I have the following method:

public void openJmsSession() {
    try {
        connection = factory.createConnection();
        Context jndiContext = getInitialContext();
        queue =(Queue) jndiContext.lookup(JMS_MAIL_QUEUE_NAME);
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    } catch (NamingException e) {
        logger.error("Naming exception during opening JMS session", e);
    } catch (JMSException e) {
        logger.error("JMS exception during opening JMS session", e);
    }
}

Line connection = factory.createConnection(); throws NPE because factory is null.


Solution

  • The following approaches worked for me:

    • Solution via EJB
      To do this via EJB you should mark your bean with @Stateless and @LocalBean annotations. After adding this your bean will become a container-managed object and you can rely on it. Also while initial context creation you shouldn't specify any properties. Initial context creation should look like:
      private static Context getInitialContext() throws NamingException { return new InitialContext(); }
    • Solution without EJB or other magic

    Add wildfly-ejb-client-bom, wildfly-jms-client-bom, wildfly-naming to your maven dependencies. In your client code use full JNDI names of JMS queues and connection factories. For example:

    1. JMS queue: before queue/MySuperJMSQueue, after: java:/jms/queue/MySuperJMSQueue
    2. JMS connection factory: before ConnectionFactory, after: java:/ConnectionFactory

    Change your configuration file (in my case it's standalone-full.xml) by adding new JMS queue via the following line:

    <jms-queue name="MySuperJMSQueue" entries="java:/jms/queue/MySuperJMSQueue"/>
    

    Change parameters which have been used for initial context instantiation:

    private static Context getInitialContext() throws NamingException {
        Properties props = new Properties();
        props.put( Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory");
        props.put( Context.URL_PKG_PREFIXES, "org.jboss.as.naming.interfaces:org.jboss.ejb.client.naming");
        return new InitialContext(props);
    }
    

    After this manipulations you can do work with JMS. Just the example of opening JMS session:

            Context jndiContext = getInitialContext();
            ConnectionFactory factory = (ConnectionFactory) jndiContext.lookup(JMS_CONNECTION_FACTORY_JNDI_NAME);
            connection = factory.createConnection();
            queue =(Queue) jndiContext.lookup(JMS_QUEUE_NAME);
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    

    For more details check the doc which is located by the following path: <WildFly 14 home folder>\bin\client\README-EJB-JMS.txt