Using Session EJB to Send JMS Messages

Discussions

EJB programming & troubleshooting: Using Session EJB to Send JMS Messages

  1. Using Session EJB to Send JMS Messages (8 messages)

    I am unsuccessfully trying to use a session EJB to send JMS. I always get a ClassCastException when I do a JNDI lookup of the Queue Factory. I use Webphere MQ as a JMS server and try to run it under WebSphere studio using the EJB Client Test. Has anyone had any experience in this area?

    Thanks,
    Richard

    Threaded Messages (8)

  2. Using Session EJB to Send JMS Messages[ Go to top ]

    Hi Richard,

      I can successfully use a Session Bean to send message over to my MQ Server (running on the same machine)...so I can say that it is definately possible. I am using WSAD 4.1, Windows 2000, and MQ Series 5.2.1 (pretty sure), I started with point to point (Queues), but have decided on using pub/sub (Topics).

      I would probably need additional information on your error and what you have/have not attempted before I could provide any real assistance...but...

      In general, you need to make sure that when using the WSAD that the JMSAdmin tool (with your MQ JNDI info) is run *each* time you restart the server as the JNDI is not persistent.
     
      Have you installed the "MA88 MQSeries classes for Java and MQSeries classes for Java Message Service" support pack from IBM?

      There are a couple of really helpful articles from IBM also, in particular:

    1:
    Writing Java Message Service programs using WebSphere MQ and
    WebSphere Studio Application Developer, Part 1: Installing the software and running your first programs
    March 2002

    and part 2
    2:
    Writing Java Message Service programs using WebSphere MQ and
    WebSphere Studio Application Developer, Part 2
    April 2002

    By
    Willy Farrell

      Ryan Cox has also written a couple of helpful articles, but I do not have the titles handy...


      Does the method for your session bean display on the "JNDI Explorer" page? On the same page, you should be able to browse the JNDI information that you have added via the JMSAdmin tool, to further verify that it is all "there".


    Don
  3. Using Session EJB to Send JMS Messages[ Go to top ]

    Hi Don,

    It's reassuring to know that you succeeded.
    I am also using WSAD 4.1, Windows 2000 and MQ Series (the trial version, I think it's now called Websphere MQ 5.2.1 or 5.2.2 (not entirely sure of the version)). I have also installed the MA88 MQSeries classes. I also do re-run the JMSAdmin each time the server is restarted. In fact I have successfully run the example described in Willy Farrell's article (part 1). For now, only do point to point.

    I use WDAD EJB Test Client to test the bean. The method from my bean does show up. It crashes when I invoke it.
    With the JNDI explorer, I can see the queue factory and the queue that I added using JMSAdmin. I notice that the queue factory stored in JNDI is of type:
    com.ibm.mq.jms.MQQueueConnectionFactory
    and of type com.ibm.mq.jms.MQQueue
    for the queue.
    But, in my bean, when I do a lookup for the queue factory and queue, I cast into
    javax.jms.QueueConnectionFactory and javax.jms.Queue
    respectively. Could this be the problem? I do get a ClassCastException in the console.

    This is the code that I have in my session bean to do a lookup:


    public void ejbCreate() throws javax.ejb.CreateException {

    try {
    initC = new InitialContext();
    }
    catch (NamingException exc) {
    exc.printStackTrace();
    }
    try {
    QueueConnectionFactory factory = (QueueConnectionFactory) initC.lookup("mq/MyQCF");
    connection = factory.createQueueConnection();
    session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
    }
    catch (NamingException e) {
    e.printStackTrace();
    }
    catch (JMSException e) {
    e.printStackTrace();
    }

    try {
    Queue queue = (Queue) initC.lookup("mq/MyQueue");
    sender = session.createSender(queue);
    sender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
    sender.setPriority(4);
    sender.setTimeToLive(0);
    connection.start();
    }
    catch (NamingException e) {
    e.printStackTrace();
    }
    catch (JMSException e) {
    e.printStackTrace();
    }
    }

    Thanks for your help,
    Richard
  4. Using Session EJB to Send JMS Messages[ Go to top ]

    Hi Richard,

      Everything looks "familiar"...
    :)

      I would definately try changing to the MQQueueConnectionFactory (I am using the MQTopicConnectionFactory)...but I do not remember if this was "critical". I had so many errors that I had to "fight through" that I do not even remember them all (probably a subconscious block). I am using the "regular" Topic, instead of the MQTopic, so you should be okay there.

      I would also suggest (after the above) moving the code out of the EJBCreate. I am using a separate class "sendMessage" that actually does the work. In theory, this decouples the messaging from the EJB/Session bean "default" methods. But I really do not know if this is important/matters. It is possible that the EJB test harness is trying to create the EJB and start the connection and causing a timing issue of some sort, but it seems a bit remote...
     
      The only other thing that I appear to have different is that I am specifying the InitialContext using a Hashtable, as below:

      private void setInitialContext () throws NamingException
      {
    Hashtable h = new Hashtable ();

    h.put (Context.INITIAL_CONTEXT_FACTORY, sInitialContextFactory);
    h.put (Context.PROVIDER_URL, sProviderUrl);
    ctx = new InitialContext(h);

      }
    (where the "sInitialContextFactory" is "com.ibm.websphere.naming.WsnInitialContextFactory" and the "sProviderUrl" is "iiop://<my machine name, rather than localhost>")

      An important side note to the above is that I am targeting a Java Client Application, which is going to be needing the MQ Client "stuff" installed and using the Client Transport (hence the machine name).

      My "Non-WSAD/Bean" code is just using "ctx = new InitialContext();"...so I may have had to switch to using the "Hashtable method" when I switched to WSAD.

      The only other thing that I would try is to verify that you have correctly registered the the objects in the JMSAdmin (just in case). It is pretty simple:
    1) Start the JMSAdmin tool,
    2) Type "display ctx" (this will display all contexts),
    3) Type "chg ctx(mq)",
    4) Type "display ctx".

      Let me know how you make out...

    HTH,
    Don
  5. Using Session EJB to Send JMS Messages[ Go to top ]

    Hi Don,
    Thanks for replying so quickly.
    I moved the code out of the ejbCreate() by creating a seperate class. I also changee to MQQueueConnectionFactory (instead of QueueConnectionFactory). Everything compiles without errors. I have added the com.ibm.mq.jar and com.ibm.mqjms.jar files to the project in WSAD (Properties > Java Build Path > Libraries). At runtime, I get a
    java.lang.NoClassDefFoundError: com/ibm/mq/jms/MQQueueConnectionFactory
    It seems that the the server does not find those jar files at runtime. (I also have the same error when all the code is in ejbCreate()). I am sorry, this might be a silly question, but how do I tell the server where to find those jar files? (I am pretty new with WSAD).

    Other than that, I also tried to get the InitialContext with a hashtable with the same results. I also verified that my objects are correctly registered by using the JMSAdmin commands.

    Richard
  6. Using Session EJB to Send JMS Messages[ Go to top ]

    Hi Richard,

      The "quick reply" was simply because I was still in the office...unfortunately, I am just getting back to the office...

      Not to worry about being "new" to WSAD...I was just 2 months ago, and I still have "difficulties".
    ;)

      I believe that the path "NoClassDefFoundError" error can be fixed by setting the Class Path for the server:
    1) Switch to server perspective (you may need to select, from the menu, Perspective, Open, then Other, then find Server in the list),
    2) In the Server Configuration "pane" (it should be lower left by default) you should see the Server Instances and Server Configurations,
    3) Expand the Server Instances,
    4) Double-click on the entry (mine is "WebSphere v4.0 Test Environment"),
    5) This should open a properties page,
    6) Select the Paths tab at the bottom and add your jar files here (this should be the "only" place you need them specified).

      I do not have the Build Path set for the EJB Project (well except for the com.ibm.mqjms.jar file as this will cause compile errors without it, for the rest of the dev. team).

      Here is what I have in my server properties class path:
    (<path> ='s "e:/wsmq/java/lib" - for me)

    <path>/jms.jar
    <path>/com.ibm.mqjms.jar
    <path>/connector.jar
    <path>/com.ibm.mq.jar
    <path>/jta.jar
    <path> (this is just the directory)
    <path>/fscontext.jar

      Add the above to the server properties path tab and IF it is still not working, I will try and run your "exact" code on my machine.

    Good Luck,
    Don
  7. Using Session EJB to Send JMS Messages[ Go to top ]

    Don, you are a GENIUS! It works!
    I've been with WSAD for about 1 month. I guess I still have a lot to learn.
    Adding the jar files to the class path in the server configuration fixed the problem.
    I am now using MQQueueConnectionFactory and MQQueue. Does that mean that my code is tied to the JMS Server? I thought the JMS implementation was independant from the JMS Server.

    Thanks again, Don.

    Richard
  8. Using Session EJB to Send JMS Messages[ Go to top ]

    Hi Richard,

      No Problem, you are quite welcome...I am glad that you were able to get it working.

      While I would not go so far as to say "genius"...I do not mind hearing it.
    ;-)

      Mostly, it was a lot of trial and error along the way on my part...You just got "lucky" to find someone else who already had it working (where I could/did not)...

      I am glad that I was able to provide assistance and that I am not the only person who is attempting to send JMS Messages from an EJB/Session Bean (at least pre-Message Driven Beans).

      My overall impression is that there is a ton of "stuff" to learn when it comes to WSAD...due to it being an all-in-one development environment. I know that I still have a lot to learn, as well.
    :)

      As far as being tied to using WebSphere MQ, my understanding is that what you/we have done is to implement JMS Messaging in a WebSphere MQ specific "way".

      It is something that I am still pondering, in general...but I do *know* that I will need to deploy in/to a WebSphere MQ Server, so I believe that I am okay (for now).

      My understanding of JMS is that the implementation itself is meant to be generic, leaving the specifics to the implementor (WebSphere MQ, in this case)...which does tie you into that JMS implementation.

      What I did do, as a precaution, is to have ALL of the WebSphere MQ specific implementation code live in a separate class/module. This way IF I did have to change it, I would only have to modify this one class for whatever JMS Provider I needed to target.

      I hope that makes "enough" sense...as it is currently all that I have.
    LOL

    Take care,
    Don
  9. Using Session EJB to Send JMS Messages[ Go to top ]

    Hi Don,
    I will follow your suggestion to have the MQ specific code in a seperate class to make it easier in case I have to change for another JMS server.
    My next goal will be to try the publish/subscribe model (with Topic).

    Thanks again,
    Take care,

    Richard