2 Replies Latest reply on Aug 16, 2007 3:03 PM by sgrenholm

    Best practices for inter-server JNDI lookup

    sgrenholm

      Hello, I'm looking for best practices in communicating over JNDI (Remote EJB lookup and JMS) between two app servers. Ideas and gotchas are welcome!

      My current testing topology involves 2 JBoss app servers, non-clustered, on the same machine. I expect in the future either app server will need to be clustered, but that isn't my main concern right now.

      At present app server 1 runs 4.0.5.GA. App server 2 runs 4.0.3SP1, because it runs a 3rd party program that sadly requires that version - and business concerns require a separate app server (in deployment, they won't run on the same machine.)

      Here's what I need to do: App server 2 needs to invoke both EJB and write to JMS queues on App server 1. App server 2 needs to write to queues on AS1.

      Here's what I have. It works [woo-hoo...], after making sure there are no port conflicts in each app server. But I'd like to know if what I've done seems reasonable and robust. In particular, I defined an alias (LinkRefPair) to the XA Connection Factory on AS2 and made sure it was visible to AS1 - otherwise, AS1 couldn't connect to the new queue defined on AS2, even though it could see its name in JNDI (NameNotFoundException).

      It feels wrong to have AS1 use AS2's Connection Factory, but it works.


      On App Server 2, I've placed the following xml file in default/deploy:

      <server>
       <!-- Define a queue on AS2 as an endpoint for AS1, used by AS2 MDBs -->
       <mbean code="org.jboss.mq.server.jmx.Queue"
       name="jboss.mq.destination:service=Queue,name=FromAS1Queue">
       <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
       </mbean>
      
       <!-- export an alias to the transactional connection factory
       and scope it to qualified name (here, reusing AS2's JNDI 'queue/' )
       so that AS1 can use this connection factory
       without bringing in everything else at the top JNDI level.
       It appears that the AS1 needs the connection factory in
       order to use the FromAS1Queue defined above -->
       <mbean code="org.jboss.naming.LinkRefPairService"
       name="jboss.jms:alias=AS1QueueConnectionFactory">
       <attribute name="JndiName">queue/QueueConnectionFactory</attribute>
       <attribute name="RemoteJndiName">ConnectionFactory</attribute>
       <attribute name="LocalJndiName">java:/JmsXA</attribute>
       <depends>jboss:service=Naming</depends>
       </mbean>
      
       <!-- Addition of an external context MBean for AS2->AS1 EJB integration
       ejb-jar and jboss xml defines ejbs under ejb/myremotes
       AS1 is on port 1099, AS2 is at 21099
       -->
       <mbean code="org.jboss.naming.ExternalContext"
       name="jboss.jndi:service=ExternalContext,jndiName=external/as1beans">
       <attribute name="JndiName">external/as1beans</attribute>
       <attribute name="Properties">
       java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
       java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
       java.naming.provider.url=jnp://localhost:1099/ejb/myremotes
       </attribute>
       <attribute name="InitialContext">javax.naming.InitialContext</attribute>
       <attribute name="RemoteAccess">true</attribute>
       <depends>jboss:service=Naming</depends>
       </mbean>
      
       <!-- Addition of an external context MBean for JMS integration -->
       <mbean code="org.jboss.naming.ExternalContext"
      name="jboss.jndi:service=ExternalContext,jndiName=external/as1queues">
       <attribute name="JndiName">external/as1queues</attribute>
       <attribute name="Properties">
       java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
       java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
       java.naming.provider.url=jnp://localhost:1099/queue
       </attribute>
       <attribute name="InitialContext">javax.naming.InitialContext</attribute>
       <attribute name="RemoteAccess">true</attribute>
       <depends>jboss:service=Naming</depends>
       </mbean>
      </server>
      

      And on App Server 1, a parallel xml file defines an external context JMX bean pointing to the queues - and the aliased connection factory - on AS2:
       <mbean code="org.jboss.naming.ExternalContext" name="jboss.jndi:service=ExternalContext,jndiName=as2/AS2server">
       <attribute name="JndiName">as2/AS2server</attribute>
       <attribute name="Properties">
       java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
       java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
       java.naming.provider.url=jnp://localhost:21099/queue
       </attribute>
       <attribute name="InitialContext">javax.naming.InitialContext</attribute>
       <attribute name="RemoteAccess">true</attribute>
       <depends>jboss:service=Naming</depends>
       </mbean>
      

      With this, AS1 can write to the queue on AS2 - and could probably listen using an MDB:
       Context initialContext = new InitialContext();
       QueueConnectionFactory queueConFac = (QueueConnectionFactory) initialContext.lookup("as2/AS2server/QueueConnectionFactory");
      
       connection = queueConFac.createQueueConnection();
       QueueSession queueSession = connection.createQueueSession(true, Session.AUTO_ACKNOWLEDGE);
       Queue queue = (Queue) initialContext.lookup("as2/AS2server/FromAS1Queue");
      

      Many thanks for your comments, Stephen

        • 1. Re: Best practices for inter-server JNDI lookup

          Hello !

          I tried your example but I have the following exception :
          javax.naming.CommunicationException: Failed to retrieve stub from server myserver:1200 [Root exception is java.io.StreamCorruptedException: unexpected block data]

          Do you know ow to resolve it ?

          Thanks in advance !

          Delphine

          • 2. Re: Best practices for inter-server JNDI lookup
            sgrenholm

            Sorry - I have no experience with that exception. At first, I was surprised that any stub errors would appear in a JMS context, but to be truthful I'm less than familiar with all the handshaking that JBoss does using JNDI.

            Although in the general case I'd starting looking at the network traffic (is it busy) and your initial marshaling of data, if applicable, I believe that in your situation something possibly JBoss-specific is going on.

            Some of the Jboss forums mention this sort of error happening when a non-clustered JBoss instance is contacting a clustered instance - so the first question is how have you setup your instances - are they clustered, which configuration are they using ("default", "all", your own config...)

            I'd suggest verifying your configuration, and post the relevant information. Maybe someone (...) will have an answer, or maybe I'll have time to look at the source and experiment [uh, don't hold your breath!]

            But whatever it is, it seems interesting! Stephen