3 Replies Latest reply on Apr 13, 2015 11:22 PM by jaikiran pai

    JMS semi-newbie - "simplified" interface with ejb-jar.xml

    Scott Dunbar Newbie

      Hello,

      I converted a JMS 1 application to JMS 2 recently.  This is under Wildfly 8.2.0.  I've got a JMS topic that I want to publish and subscribe to and I'm a bit stuck.  I want to use ejb-jar.xml for some of the configuration as I want to have a virtual host environment with many almost duplicate WAR files.  I originally started down the annotation route but got stuck because I had "global" JMS topics.  So now I want to externalize the configuration.

       

      I have a JMS topic named, in JNDI, "java:/jms/myTopic".  I created this globally via jboss-cli.sh with "jms-topic add --topic-address=myTopic --entries=java:/jms/myTopic".  My MDB looks like:

       

      @MessageDriven(activationConfig = {
          @ActivationConfigProperty(propertyName = "destination", propertyValue = "doesntmatter"),
          @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic") })
      public class MyListener implements MessageListener {
          @Override
          public void onMessage(Message message) {
          }
      }

       

      My ejb-jar.xml (in WEB-INF) looks like:

       

      <message-driven>
          <ejb-name>MyListener</ejb-name>
          <ejb-class>a.b.c.MyListener</ejb-class>
      
          <activation-config>
              <activation-config-property>
                  <activation-config-property-name>destination</activation-config-property-name>
                  <activation-config-property-value>/jms/myTopic</activation-config-property-value>
              </activation-config-property>
          </activation-config>
      </message-driven> 

       

      On the MDB side, this works fine.

       

      Now, I'd like to "fix" the publisher side.

       

      My code looks like:

       

      @Stateless
      public class MessageProducer {
          @Resource(name = "jms/myTopic")
          private Topic topic;
          @Inject
          private JMSContext context;
      
          public void sendMessage(String msg) {
              ObjectMessage message = context.createObjectMessage();
              message.setObject(msg);
              context.createProducer().send(topic, message);
          } 

       

      And I've tried like heck to figure out what to put into ejb-jar.xml.  I currently have:

       

      <session>
          <ejb-name>ProjectMessageProducer</ejb-name>
          <ejb-class>a.b.c.MessageProducer</ejb-class>
                  
          <message-destination-ref>
              <message-destination-ref-name>jms/myTopic</message-destination-ref-name>
              <message-destination-type>javax.jms.Topic</message-destination-type>
                  
              <injection-target>
                  <injection-target-class>a.b.c.MessageProducer</injection-target-class>
                  <injection-target-name>topic</injection-target-name>
              </injection-target>
          </message-destination-ref>
      </session>

       

      I know that it tries to inject it because I get:

       

      15:31:01,217 WARN  [org.jboss.as.ee] (MSC service thread 1-3) JBAS011001: Could not resolve message-destination-ref java:comp/env/jms/myTopic

       

      But trying to rename this and create the destination as specified cannot be done.  On startup Wildfly tells me

       

      Caused by: java.lang.RuntimeException: JBAS011846: Illegal context in name: java:comp/env/jms/myTopic

       

      plus I wouldn't know how to change the MDB side.

       

      So if this makes any sense, can someone give me some pointers?  I'm more than happy to change my code or architecture on this.  I just need some pointers.

        • 1. Re: JMS semi-newbie - "simplified" interface with ejb-jar.xml
          jaikiran pai Master

          @Resource(name = "jms/myTopic")

              private Topic topic;

          That should be:

           

          @Resource(lookup = "java:/jms/myTopic")
              private Topic topic;
          
          • 2. Re: JMS semi-newbie - "simplified" interface with ejb-jar.xml
            Scott Dunbar Newbie

            Thanks Jaikiran - my question was how to get this from ejb-jar.xml.

             

            And to answer my own question:

             

            In the Java code, do something like:

             

            @Resource(name = "myTopic")
            private Topic topic;

             

            In ejb-jar.xml do:

             

            <session>
              <ejb-name>MessageProducer</ejb-name>
              <ejb-class>a.b.c.MessageProducer</ejb-class>
              <resource-ref>
                <res-ref-name>myTopic</res-ref-name>
                <lookup-name>java:/jms/myTopic</lookup-name>
              </resource-ref>
            </session>
            

             

            The only hassle here is that the "receiver" side is mapped differently than the "producer" side as the sender needs the entire JNDI name.  I'm sure there is a better way but this got me past it for now.  Honestly, CDI reminds me of the old X11 criticism sometimes:

             

            If the designers of X-Windows built cars, there would be no fewer than five steering wheels hidden about the cockpit, none of which followed the same principles -- but you'd be able to shift gears with your car stereo. Useful feature, that.

            - Marus J. Ranum, Digital Equipment Corporation

             

            Thanks for your help.

            • 3. Re: JMS semi-newbie - "simplified" interface with ejb-jar.xml
              jaikiran pai Master

              The only hassle here is that the "receiver" side is mapped differently than the "producer" side as the sender needs the entire JNDI name.

               

              I think you are talking about this value, isn't it:

               

               

               

              <activation-config-property>

                          <activation-config-property-name>destination</activation-config-property-name>

                          <activation-config-property-value>/jms/myTopic</activation-config-property-value>

                      </activation-config-property>

               

               

              Actually that value too is expected to be the full JNDI name. However, although you haven't specified the java:/ namespace, JBoss AS7, by default prefixes it in this specific case, giving you the impression that the full JNDI name isn't required. If for example the JNDI name was java:jboss/foo/bar and you had instead specified /foo/bar as the value there, then it would have failed to deploy.