1 2 3 Previous Next 30 Replies Latest reply on Sep 15, 2013 8:55 AM by jim_b_o

    Injecting Hornetq resources with CDI

    ron_sigal

      Hi,

       

      I'm trying to inject a HornetQ Queue and Session, and I'm having a problem.  When I call Session.getProducer(Destination destination), using the injected Session and Queue, I get the error:

       

      21:26:56,558 ERROR [stderr] (http-talon-127.0.0.1-8080-12) javax.jms.InvalidDestinationException: Not a HornetQ Destination:HornetQQueue[testQueue]

      21:26:56,559 ERROR [stderr] (http-talon-127.0.0.1-8080-12)     at org.hornetq.jms.client.HornetQSession.createProducer(HornetQSession.java:324)

       

      I've added the code:

       

      log.info("queue: " + bookQueue);

      log.info("class: " + bookQueue.getClass());

      log.info("instanceOf: " + (bookQueue instanceof HornetQDestination));

       

      and I get the output:

       

      21:26:56,557 INFO  [org.jboss.resteasy.cdi.injection.BookResource] (http-talon-127.0.0.1-8080-12) queue: HornetQQueue[testQueue]

      21:26:56,557 INFO  [org.jboss.resteasy.cdi.injection.BookResource] (http-talon-127.0.0.1-8080-12) class: class org.jboss.weldx.jms.Destination$Queue$1195520705$Proxy$_$$_Weld$Proxy$

      21:26:56,558 INFO  [org.jboss.resteasy.cdi.injection.BookResource] (http-talon-127.0.0.1-8080-12) instanceOf: false

       

      It seems that the test

       

      if (destination != null && !(destination instanceof HornetQDestination))

      {

         throw new InvalidDestinationException("Not a HornetQ Destination:" + destination);

      }

       

      in HornetQSession.createProducer() is failing because it's seeing a CDI proxy for the Queue.

       

      Any ideas?

       

      -Ron

        • 1. Re: Hornetq and CDI
          jbertram

          For what it's worth, WebLogic appears to suffer from the same issue.  See https://forums.oracle.com/forums/thread.jspa?threadID=2320522&tstart=105.

           

          It appears we need something more clever than instanceof here, but I don't have any ideas off the top of my head.  Clebert, what do you think?

          • 2. Re: Hornetq and CDI
            jbertram

            Ron, you got any clue where the source code for org.jboss.weldx.jms.Destination is?

            • 3. Re: Hornetq and CDI
              ron_sigal

              Hey Justin,

               

              I suspect that it's nowhere, in the sense that it's a proxy of some sort created by Weld.  But not a regular proxy.  I tried

               

                 log.info("isProxy(): " + Proxy.isProxyClass(bookQueue.getClass()));

               

              and it was false.  I don't know for sure, but maybe it's created here: https://github.com/weld/core/blob/master/impl/src/main/java/org/jboss/weld/bean/proxy/ProxyFactory.java

               

              -Ron

              • 4. Re: Hornetq and CDI
                jmesnil

                Justin Bertram wrote:

                 

                For what it's worth, WebLogic appears to suffer from the same issue.  See https://forums.oracle.com/forums/thread.jspa?threadID=2320522&tstart=105.

                 

                It appears we need something more clever than instanceof here, but I don't have any ideas off the top of my head.  Clebert, what do you think?

                It's a wild guess but we could use Class.isInstance[1] instead of instanceof. This is the dynamic version of instanceof and it might work with Weld proxies.

                 

                [1] http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#isInstance(java.lang.Object)

                • 5. Re: Hornetq and CDI
                  ron_sigal

                  I just added

                   

                       log.info("Class.isInstance(): " + HornetQDestination.class.isInstance(bookQueue));

                   

                  to my test and got

                   

                    Class.isInstance(): false

                   

                  Maybe there's something in Weld that could give the right answer.   Maybe Ales can help.  He's  co-author of ProxyFactory.  I'll ask him to take a look at this thread.

                   

                  Of course, that would mean adding Weld as a dependency. 

                   

                  -Ron

                  • 6. Re: Hornetq and CDI
                    ron_sigal

                    I just tried

                     

                         try
                         {
                               HornetQDestination hqd = HornetQDestination.class.cast(bookQueue);
                               log.info("bookQueue can be cast to HornetQDestination");
                         }
                         catch (Exception e)
                         {
                            l   og.info("bookQueue can't be cast to HornetQDestination");
                         }

                     

                    and got

                     

                      13:24:24,967 INFO  [org.jboss.resteasy.cdi.injection.BookResource] (http--127.0.0.1-8080-12) bookQueue can't be cast to HornetQDestination

                    • 7. Re: Hornetq and CDI
                      clebert.suconic

                      Different classpaths for sure!

                      • 8. Re: Hornetq and CDI
                        clebert.suconic

                        I meant.. different classloaders!

                        • 9. Re: Hornetq and CDI
                          alesj

                          @Ron: how do you get a hold of Destination, I mean, how does CDI / Weld get a hold of it - to wrap it into proxy

                          • 10. Re: Hornetq and CDI
                            ron_sigal

                            Hi Clebert,

                             

                            When I added:

                             

                                 log.info("getClass().getClassLoader():                          " + getClass().getClassLoader());
                                 log.info("HornetQDestination.class.getClassLoader(): " + HornetQDestination.class.getClassLoader()); 

                             

                            to my test code, I got:

                             

                            ...  getClass().getClassLoader():                          ModuleClassLoader for Module "deployment.resteasy-cdi-ejb-test.war:main" from Service Module Loader

                            ...  HornetQDestination.class.getClassLoader(): ModuleClassLoader for Module "org.jboss.resteasy.resteasy-jaxrs:main" from local module loader @4c5e176f (roots: /home/rsigal/git.master/Resteasy/jaxrs/arquillian/resteasy-cdi-ejb-test/target/jboss-as-7.1.1.Final/modules)

                             

                            The first one is the war copied to AS 7 by arquillian.  The second one is explained by the fact that I added hornetq-jms-client-2.2.13.Final.jar and jboss-jms-api_1.1_spec-1.0.0.Final.jar as resources in the resteasy-jaxrs module.  So I took them out of the resteasy-jaxrs module and added them as libraries in the arquillian war, and now I get

                             

                            ...  getClass().getClassLoader():                          ModuleClassLoader for Module "deployment.resteasy-cdi-ejb-test.war:main" from Service Module Loader

                            ...  HornetQDestination.class.getClassLoader(): ModuleClassLoader for Module "deployment.resteasy-cdi-ejb-test.war:main" from Service Module Loader

                             

                            and I still get

                             

                            ...  javax.jms.InvalidDestinationException: Not a HornetQ Destination:HornetQQueue[testQueue]

                             

                            -Ron

                            • 11. Re: Hornetq and CDI
                              ron_sigal

                              Hi Ales,

                               

                              The following utility class generates a Session and a Queue:

                               

                              @Resource(name="queue/test")

                              public class ResourceProducer

                              {

                                 private static Connection connection;

                                 private static Session session;

                                

                                 @Produces

                                 @ResourceBinding

                                 @Resource(mappedName="java:jboss/exported/jms/queue/test")

                                 Queue bookQueue;

                               

                                 @Resource(mappedName="java:jboss/exported/jms/RemoteConnectionFactory")

                                 ConnectionFactory connectionFactory;

                                

                                 @Produces

                                 @ResourceBinding

                                 public Session getSession() throws JMSException

                                 {

                                    if (connection == null)

                                    {

                                       connection = connectionFactory.createConnection("guest", "pass");

                                    }

                                    if (session == null)

                                    {

                                       session =  connection.createSession(false, Session.AUTO_ACKNOWLEDGE); 

                                    }

                                    return session;

                                 }

                              }

                               

                              and they are injected into another class here:

                               

                               

                                 @Inject

                                 @ResourceBinding

                                 private Session session;  

                               

                                 @Inject

                                 @ResourceBinding

                                 private Queue bookQueue;

                               

                              They are used here

                               

                               

                                   MessageProducer producer = session.createProducer(bookQueue);
                                   TextMessage message = session.createTextMessage(book.getName());
                                   producer.send(message);

                               

                              and here:

                               

                               

                                   MessageConsumer consumer = session.createConsumer(bookQueue);
                                   TextMessage message = (TextMessage) consumer.receive();

                               

                              -Ron

                              • 12. Re: Hornetq and CDI
                                gaohoward

                                may be the proxy is really a wrap of a different class. Did you try to print out the proxy's fields and methods?

                                 

                                Howard

                                • 13. Re: Hornetq and CDI
                                  gaohoward

                                  also its class hierarchy?

                                  • 14. Re: Hornetq and CDI
                                    ron_sigal

                                    Hi Howard,

                                     

                                    Here's a snapshot of the proxy.  Look at the fields type and types, towards the bottom.  It looks like a Queue.

                                     

                                    proxy_snapshot_112112.png

                                     

                                    -Ron

                                    1 2 3 Previous Next