13 Replies Latest reply on Feb 10, 2010 2:54 PM by ben.cotton2

    Remote vs. Local client lookup of same JNDI object

    ben.cotton2

      We are experiencing a problem when a remote desktop Java client  attempts to lookup an object by name that is hosted in a JBoss AS 5.1 server's JNDI global namespace.

       

      The JBoss admin console displays the following for the name 'IVTCF' in the JNDI global namespace (and it shows a correct and expected value).

       


      Global JNDI Namespace


      +- IVTCF (class: com.ibm.mq.connector.outbound.ConnectionFactoryImpl)
        • 1. Re: Remote vs. Local client lookup of same JNDI object
          ben.cotton2

          We are experiencing a problem when a remote desktop Java client  attempts to lookup an object by name that is hosted in a JBoss AS 5.1 server's JNDI global namespace.

           

          The JBoss admin console displays the following for the name 'IVTCF' in the JNDI global namespace (and it shows a correct and expected value).

           


          Global JNDI Namespace


          +- IVTCF (class: com.ibm.mq.connector.outbound.ConnectionFactoryImpl)

           

          If we code the following from a JBoss-deployed servlet, everything works perfectly ... the JBoss hosted JNDI references correctly uses the IBM JCA resource adapter to bridge to WSMQ implementations of Queue and QueueConnectionFactory.

           

                      InitialContext ic = new InitialContext();
                 
                      javax.jms.ConnectionFactory cf = (javax.jms.ConnectionFactory) ic.lookup("IVTCF");
                      log.info("'IVTCF' javax.jms.ConnectionFactory found: [" + cf + "]");
                     
                      Queue q = (Queue) ic.lookup("IVTQueue");
                      log.info("'IVTQueue' javax.jms.Queue found: [" + q +"]");
                    
                     

          However, If I code the following from a standalone Java client app on a remote dektop machine, the ConnectionFactory lookup always results with 'factory' == NULL.  .

           

           Properties props = new Properties();
          props.setProperty(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
          props.setProperty(Context.PROVIDER_URL,"jnp://10.4.164.105:11099");
          props.setProperty(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");


          Context ctx = new InitialContext(props);


          javax.jms.ConnectionFactory factory = (javax.jms.ConnectionFactory)ctx.lookup("IVTCF");

          // 'factory' always value = NULL at his time, why?
          System.out.println("'IVTCF' ConnectionFactory established! IVTCF=["+factory+"]");

           

          Any ideas as to why the remote client lookup always returns a fatcory == NULL value, when the locally deployed servlet's lookup is always able to successfully return a correct value (for the exact same JNDI object name)?

           

           

          We have tried other JBoss forums suggested remedies ( http://community.jboss.org/thread/129674 ) but have not had success.

           

          We would like a confirmation that, given the first block of code works correctly, we should reasonably expect the second block of code to also work correctly.  It is our belief that the fact that the second block of code does not work may be an indication of a JBoss bug.  Agree?

          • 2. Re: Remote vs. Local client lookup of same JNDI object
            jaikiran

            Perhaps the connection factory isn't meant to be used outside the JVM where it's hosted. I remember seeing some discussion about this some years back, but cant located that thread now.

            1 of 1 people found this helpful
            • 3. Re: Remote vs. Local client lookup of same JNDI object
              brian.stansberry

              If you can put your remote client in a debugger and put a breakpoint in the org.jnp.interfaces.NamingContext.lookup(Name) method, that's probably your best approach to figuring out what's going on.

               

              I don't know what version you're using so won't quote line numbers, but a breakpoint here would be good:

               

                                   res = naming.lookup(n);
              

               

              That shouldn't return null. Then the code drops out of a try/catch block and goes through a bunch of if tests to deal with various types of objects that can be returned, resolve javax.naming.Reference etc. What will happen here very much depends on what was bound into JNDI.


              1 of 1 people found this helpful
              • 4. Re: Remote vs. Local client lookup of same JNDI object
                ben.cotton2

                Thanks for this quick reply .... very interesting ... and, I think you might be correct.

                 

                Consider the following Java client code (modified slightly from what was posted earlier above).  The 'factory' lookup() still returns NULL every time.  But, the 'q' lookup() returns the correct value of a remotely hosted JBoss  JNDI object reference named 'IVTQueue' (that also uses IBM's JCA adapter to bridge to a WSMQ implementation of javax.jms.Queue)

                 

                          Properties props = new Properties();
                            props.setProperty(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
                            props.setProperty(Context.PROVIDER_URL,"jnp://10.4.164.105:11099");  //Linux dndcor3autw001.aur.lehman.com
                            props.setProperty(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
                       
                           
                            Context ctx = new InitialContext(props);
                           
                           
                            javax.naming.Reference factory = (javax.naming.Reference) ctx.lookup("IVTCF");

                            // 'factory' always returned value 'NULL' ... why?
                            System.out.println("looked up 'IVTCF' javax.jms.QueueConnectionFactory established! 'factory'=["+    factory    +"]");
                           

                           
                            javax.jms.Queue q = (javax.jms.Queue) ctx.lookup("IVTQueue");

                            // 'q' returned CORRECT non-NULL value from same remote JBoss JNDI tree .... why?  must not be remoteness issue?
                            System.out.println("'IVTQueue' javax.jms.Queue found: [" + q +"]");

                           

                 

                Output:

                 

                looked up 'IVTCF' javax.jms.QueueConnectionFactory established! 'factory'=[null]
                'IVTQueue' javax.jms.Queue found: [queue://CapMktsQM/SYSTEM.DEFAULT.LOCAL.QUEUE]

                 

                So this success, suggests that remoteness has nothing to do with the failure of the ConnectionFactory lookup.

                 

                I am contacting the author of IBM's WSMQ JCA resource apapter for comment and confirmation re: IBM MQ ConnectionFactoryImpl

                 

                Thank you very much, Jaikiran!


                • 5. Re: Remote vs. Local client lookup of same JNDI object
                  ben.cotton2

                  Thanks for this idea Brian, going  to single-step debug this right now.

                   

                  I can't seem  find any file = NamingContext.java under the JBoss AS 5.1 SVN source code tree ... where does one get the .java source for org.jnp.interfaces.*

                   

                  ?

                  • 7. Re: Remote vs. Local client lookup of same JNDI object
                    ben.cotton2

                    Thanks Brian.

                     

                    Single step debugging from my client code statement ...

                     

                    javax.naming.Reference factory = (javax.naming.Reference) ctx.lookup("IVTCF");

                     

                    .... our thread stack enters into org.jnp.interfaces.NamingContext.java (line 726) and executes

                                         res = naming.lookup(n);

                     

                    That assignment is INDEED non-NULL  ... the 'res' identifier is correctly assigned a reference to an IBM WSMQ javax.jms.ConnectionFactory implementation class.  (see attached screen shot for details of assignment).

                     

                    The lookup() looks great at this stage.

                     

                    The logical flow proceeds from line 726 in NamingContext.java andexecutes the follwoing code (lines 819-827).

                     

                             else if (res instanceof Reference)  //true
                             {
                                // Dereference object
                               res = getObjectInstanceWrapFailure(res, name, refEnv);  // assigned NULL here
                                if (res instanceof LinkRef)
                                   res = resolveLink(res, refEnv);  // returned NULL value here ... which is assigned to 'factory' in client code.
                             }

                             return res;

                     

                    So my lookup() at one time had a desired reference to my IBM WSMQ implementation of javax.jms.ConnectionFactory ... but lost it because that reference is an instanceof  Reference.

                     

                    Any ideas on how I can overcome this?

                     

                    .

                    • 8. Re: Remote vs. Local client lookup of same JNDI object
                      brian.stansberry

                      If you step into the call to getObjectInstanceWrapFailure and then step into it's call to getObjectInstance, I expect you'll end up at this:

                       

                      return NamingManager.getObjectInstance(obj, name, this, env);
                      

                       

                      That's a call into a JDK class; the JDK javadocs for javax.naming.spi.NamingManager describe what goes on there. At that point it's really out of the hands of JBoss' code; the NamingManager uses the javax.naming.Reference object IBM binds to figure out how to construct the object, generally delegating to a javax.naming.spi.ObjectFactory implementation specified by the Reference. You call step into the NamingManager.getObjectInstance() call to get a better idea of exactly what's happening.

                      • 9. Re: Remote vs. Local client lookup of same JNDI object
                        ben.cotton2

                        OK, thank you very much Brian.  I will continue debugging.

                         

                        I find the following particularly curious:  when I execute the following code from a servlet, deployed locally to the same JBoss AS 5.1 instance hosting the 'IVTCF' and 'IVTQueue' JNDI names,  my lookup() assignments always  get 100% correct non-NULL references to the IBM WSWMQ implementation classes.  It is only when remote clients do the lookup() ... and only in the 'IVTCF' lookup() case ... that I get a NULL returned.

                         

                        That leads me to believe that the following is likely true:

                         

                         

                        jaikiran wrote:

                         

                        Perhaps the connection factory isn't meant to be used outside the JVM where it's hosted. I remember seeing some discussion about this some years back, but cant located that thread now.

                         

                        Still waiting on the IBM WSMQ JCA adapter developer (ben.ritchie@uk.ibm.com) to comment.

                         

                        Thanks again Brian and Jaikiran for your stellar support.

                        • 10. Re: Remote vs. Local client lookup of same JNDI object
                          ben.cotton2

                          Just as an FYI, my dialog with senior technical staff at IBM resulted in the following personal musings:

                           

                          1.  This is not a JBoss AS 5.1 lookup "bug".  No where does the JCA specification address the requirement that JCA compatible application servers accommodate a remote client lookup of a JNDI bound ConnectionFactory name that bridges to a provider's ConnectionFactory implementation via a resource adapter.

                           

                          2.  This is not an IBM resource adapter "bug".  The exact same thing happens, in the exact same way, when my remote client does a lookup of a JNDI bound ConnectionFactory name ('JmsXA') that bridges to a JBoss provided ConnectionFactory implementation via a JBoss provided resource adapter. (see below for details).  Like IBM's RA ConnectionFactory, the jBoss RA ConnectionFactory lookup works perfect when the client code is locally deployed to JBoss AS.

                           

                          3.  Though theres are  not "bugs", we still suffer from not realizing an ideal  (remote_client-->JBoss JNDI lookup-->IBM JCA RA bridge-->WSMQ) capability.

                           

                          4.  NOTE:  The following bridge works ideally (remote_client-->Apache Geronimo JNDI lookup-->IBM JCA RA bridge--> WSMQ).

                          5.  NOTE:  The following bridge works ideally (remote_client-->GlassFish JNDI lookup-->IBM JCA RA bridge-->WSMQ).

                          6.  NOTE:  The following bridge has a (not ideal) functional work-around  (remote_client-->WebLogic-->non-JCA WLS:MQ bridge-->WSMQ)

                           

                          7.  Though not a JBoss "bug", it may be appropriate to create a JBoss "feature enhancement" JIRA that requests that a capabilty similar to #4-#6 above be provided in JBoss AS.  Agree?

                           

                          Here are details for confirming #2.

                           

                               (i)     Change the default $JBOSS_HOME/server/default/deploy/messaging/jms-ds.xml as follows

                           

                          <?xml version="1.0" encoding="UTF-8"?>

                          <connection-factories>

                            <!-- ==================================================================== -->
                            <!-- JMS Stuff                                                            -->
                            <!-- ==================================================================== -->

                             <!--
                                 The JMS provider loader. Currently pointing to a non-clustered ConnectionFactory. Need to
                                 be replaced with a clustered non-load-balanced ConnectionFactory when it becomes available.
                                 See http://jira.jboss.org/jira/browse/JBMESSAGING-843.
                             -->
                             <mbean code="org.jboss.jms.jndi.JMSProviderLoader"
                                    name="jboss.messaging:service=JMSProviderLoader,name=JMSProvider">
                                <attribute name="ProviderName">DefaultJMSProvider</attribute>
                                <attribute name="ProviderAdapterClass">org.jboss.jms.jndi.JNDIProviderAdapter</attribute>
                                <attribute name="FactoryRef">java:/XAConnectionFactory</attribute>
                                <attribute name="QueueFactoryRef">java:/XAConnectionFactory</attribute>
                                <attribute name="TopicFactoryRef">java:/XAConnectionFactory</attribute>
                             </mbean>

                             <!-- JMS XA Resource adapter, use this to get transacted JMS in beans -->
                             <tx-connection-factory>
                                <jndi-name>JmsXA</jndi-name>
                                <xa-transaction/>
                                <rar-name>jms-ra.rar</rar-name>
                               <use-java-context>false</use-java-context> <!-- add this line to "out of the box" config -->
                                <connection-definition>org.jboss.resource.adapter.jms.JmsConnectionFactory</connection-definition>
                                <config-property name="SessionDefaultType" type="java.lang.String">javax.jms.Topic</config-property>
                                <config-property name="JmsProviderAdapterJNDI" type="java.lang.String">java:/DefaultJMSProvider</config-property>
                                <max-pool-size>20</max-pool-size>
                                <security-domain-and-application>JmsXARealm</security-domain-and-application>
                                <depends>jboss.messaging:service=ServerPeer</depends>
                             </tx-connection-factory>

                          </connection-factories>

                          (ii)  reboot JBoss AS 5.1 process

                          (iii)  confirm (from JMX consoleJNDIView) that the 'JmsXA' ConnectionFactory name is bound in JBoss' global JNDI tree, referencing the JBoss resource adapter ConnectionFactory implementation

                          +- JmsXA (class: org.jboss.resource.adapter.jms.JmsConnectionFactoryImpl)

                          (iv)  execute the followng lookup code from remote client Java application  (sorry this code is listed as image, text cut/paste stopped working for me for this "Post reply" session)

                          Untitled.jpg

                          (v)  Confirm from the stdout that this code's lookup() of the JBoss apapter's ConnectionFactory invoke returned NULL (exactly like the lookup() of the IBM adapter's ConnectionFactory)

                           

                          JmsXaConnectionFacotry=NULL.jpg

                           

                           

                           


                          • 11. Re: Remote vs. Local client lookup of same JNDI object
                            jaikiran

                            ben.cotton@rutgers.edu wrote:

                             


                             

                            2.  This is not an IBM resource adapter "bug".  The exact same thing happens, in the exact same way, when my remote client does a lookup of a JNDI bound ConnectionFactory name ('JmsXA') that bridges to a JBoss provided ConnectionFactory implementation via a JBoss provided resource adapter. (see below for details).  Like IBM's RA ConnectionFactory, the jBoss RA ConnectionFactory lookup works perfect when the client code is locally deployed to JBoss AS.

                             

                            OK, now that reminds me of where i had seen this discussion earlier http://community.jboss.org/thread/72803?tstart=0

                            • 12. Re: Remote vs. Local client lookup of same JNDI object
                              ben.cotton2

                              The screenshots of the code and its stdout are terribly blurry.  If you click on the image, however, a much more focused view pops up in a seperate window.

                              • 13. Re: Remote vs. Local client lookup of same JNDI object
                                ben.cotton2

                                Yep.  That is exactly the issue.

                                 

                                Thanks for the reference link Jaikiran ... I will try to use Weston M. Price's reply to your post as a starting point for a workaround.