3

This code for a Java EE 7 message driven bean receives messages as expected, but fails to send replies, as the JMSContext is always null. What could cause the injection to fail?

I have tried different ways to inject the context, with and without the additional @JMSConnectionFactory annotation:

@JMSConnectionFactory("java:comp/DefaultJMSConnectionFactory")

or

@JMSConnectionFactory("java:/ConnectionFactory")

The latter is the value shown in the JNDI screen of the admin web interface.

package com.example.wf10mdb;

import javax.annotation.Resource;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.inject.Inject;
import javax.jms.JMSConnectionFactory;
import javax.jms.JMSContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import javax.jms.Topic;

@MessageDriven(activationConfig
        = {
            @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
            @ActivationConfigProperty(propertyName = "destination", propertyValue = "java:app/jms/topic/ExampleTopic")
        })
public class ChatMessageBean implements MessageListener {

    @Override
    public void onMessage(Message message) {
        try {

            final TextMessage textMessage = (TextMessage) message;
            final String question = textMessage.getText();

            System.out.println(question);

            if (null != question) {
                switch (question) {
                    case "Hello World!":
                        respond("Hello, Test Case!");
                        break;
                    case "How are you?":
                        respond("I'm doing well.");
                        break;
                    case "Still spinning?":
                        respond("Once every day, as usual.");
                        break;
                }
            }
        } catch (JMSException e) {
            throw new IllegalStateException(e);
        }
    }

    @Resource(mappedName = "java:/jms/topic/ExampleTopic")
    private Topic answerTopic;

    @Inject
    @JMSConnectionFactory("java:/ConnectionFactory")
    JMSContext context;

    public void respond(String txt) {
        if (context == null) {
            System.out.println("context is null");
            return;
        }

        try {
            context.createProducer().send(answerTopic, txt);
        } catch (Exception exc) {
            exc.printStackTrace(System.out);
        }
    }
}
mjn
  • 36,362
  • 28
  • 176
  • 378

3 Answers3

2

You have two options here:

  1. When your beans are annotated with a scope type, the server recognizes the application as a bean archive and no additional configuration is required.

  2. CDI uses an optional deployment descriptor named beans.xml. An archive must contain the beans.xml deployment descriptor only in certain limited situations (explicit bean archive), for example when POJO class does not have CDI annotations.

For a web application, the beans.xml deployment descriptor, if present, must be in the WEB-INF directory: webapp/WEB-INF/beans.xml For EJB modules or JAR files, the beans.xml deployment descriptor, if present, must be in the META-INF directory: resources/META-INF/beans.xml

This file can be empty: what is the purpose of including empty beans.xml in CDI implemenations projects?

Packaging CDI Applications: https://docs.oracle.com/javaee/7/tutorial/cdi-adv001.htm

Community
  • 1
  • 1
Alexandr
  • 9,213
  • 12
  • 62
  • 102
2

Wildfly 10 did not activate the JMS component per default. This configuration is only part of the 'standalone-full.xml' file. If you run Wildfly with the standard 'standalone.xml' you should switch to the standalone-full.xml configuration. Wildfly is using Apache ActiveMQ.

This is an example of a messagin-activemq configuration with a custom test queue:

    ....
         <profile>
        .....
        <subsystem xmlns="urn:jboss:domain:messaging-activemq:1.0">
                    <server name="default">
                        <security-setting name="#">
                            <role name="guest" send="true" consume="true" create-non-durable-queue="true" delete-non-durable-queue="true"/>
                        </security-setting>
                        <address-setting name="#" dead-letter-address="jms.queue.DLQ" expiry-address="jms.queue.ExpiryQueue" max-size-bytes="10485760" page-size-bytes="2097152" message-counter-history-day-limit="10"/>
                        <http-connector name="http-connector" socket-binding="http" endpoint="http-acceptor"/>
                        <http-connector name="http-connector-throughput" socket-binding="http" endpoint="http-acceptor-throughput">
                            <param name="batch-delay" value="50"/>
                        </http-connector>
                        <in-vm-connector name="in-vm" server-id="0"/>
                        <http-acceptor name="http-acceptor" http-listener="default"/>
                        <http-acceptor name="http-acceptor-throughput" http-listener="default">
                            <param name="batch-delay" value="50"/>
                            <param name="direct-deliver" value="false"/>
                        </http-acceptor>
                        <in-vm-acceptor name="in-vm" server-id="0"/>
                        <jms-queue name="ExpiryQueue" entries="java:/jms/queue/ExpiryQueue"/>
                        <jms-queue name="DLQ" entries="java:/jms/queue/DLQ"/>
                        <connection-factory name="InVmConnectionFactory" connectors="in-vm" entries="java:/ConnectionFactory"/>
                        <connection-factory name="RemoteConnectionFactory" connectors="http-connector" entries="java:jboss/exported/jms/RemoteConnectionFactory"/>
                        <pooled-connection-factory name="activemq-ra" transaction="xa" connectors="in-vm" entries="java:/JmsXA java:jboss/DefaultJMSConnectionFactory"/>

                      <jms-queue name="testQueue"  entries="jms/queue/test java:jboss/exported/jms/queue/test" />
                    <jms-topic name="testTopic" entries="jms/topic/test java:jboss/exported/jms/topic/test" />
                    </server>
                </subsystem>
        ....
Ralph
  • 4,500
  • 9
  • 48
  • 87
  • I'd like to add [How to configure jms in jboss eap 7](https://stackoverflow.com/questions/40015829/how-to-configure-jms-in-jboss-eap-7) as it shows how to do it without using standalone-full.xml which people might not want to use, instead it just updates standalone.xml to support JMS – JGlass Feb 08 '18 at 16:31
1

The answer is simple: the container will does not inject dependencies within a message driven bean by default. When I add the @ApplicationScoped annotation to the bean class, the JMSContext will be injected.

mjn
  • 36,362
  • 28
  • 176
  • 378