9 Replies Latest reply on Jun 19, 2012 11:35 PM by ktfan

    JMS host not populated to remote client on JNDI lookup for jms/RemoteConnectionFactory

    jw

      Hi all

       

      When I do a jndi lookup on a remote client for 'jms/RemoteConnectionFactory' I get a connection factory that connects always to the localhost regardless of the host definition in the InitialContext.

      I would expect a connection factory that connects to the host as it is specified in the initial context.

       

       

      Code snipped of the remote client:

       

      {code:java}

       

      env.put(...)

      env.put( InitialContext.PROVIDER_URL, "remote://myHost:4447");

      ctx = new InitialContext(env)

       

      ctx.lookup("jms/RemoteConnectionFactory"); // this connection factory connects always to the localhost

      {code}

       

       

      This code works if myHost is localhost but not if myHost is not the localhost.

       

      Is this a configuration issue or a bug? If not, for what should this RemoteConnectionFactory be used for?

       

       

      Thanks for your help

        • 1. Re: JMS host not populated to remote client on JNDI lookup for jms/RemoteConnectionFactory
          jbertram

          Can you elaborate on what you mean by, "When I do a jndi lookup on a remote client for 'jms/RemoteConnectionFactory' I get a connection factory that connects always to the localhost regardless of the host definition in the InitialContext"?  Are you saying that if your client is running on hostA and JBoss AS is running on hostB and the client looks up 'jms/RemoteConnectionFactory' on hostB it will get a connection to 'localhost' (i.e. hostA)?  If so, is the client on hostA running in an instance of JBoss AS?

           

          Also, what is the full 'env' you are passing to the lookup?

          • 2. Re: JMS host not populated to remote client on JNDI lookup for jms/RemoteConnectionFactory
            jw
            • Client and JBoss are running on the same host works
            • Client runs on hostA and JBoss runs on hostB: the connection factory connects to hostA (expect it connects to hostB where JBoss is running).

             

            I've tested this by running JBoss on both hosts (hostA and hostB) and I see in the log file that hostA is connected. Messages sent are received on hostA.

             

             

            Initial context on client is

             

            {code}

            java.naming.factory.initial=org.jboss.naming.remote.client.InitialContextFactory

            java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces

            jboss.naming.client.connect.options.org.xnio.Options.SSL_ENABLED=FALSE

            jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=true

            jboss.naming.client.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS=JBOSS-LOCAL-USER

            jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT=false

            jboss.naming.client.security.callback.handler.class=test.UsernamePasswordCallbackHandler

            java.naming.provider.url=remote://hostB:4447

            {code}

             

            Lookups for EJB's are working fine; the EJB methods are executed on hostB.

             

             

            If so, is the client on hostA running in an instance of JBoss AS?

             

            No, it's a standalone client.

            • 3. Re: JMS host not populated to remote client on JNDI lookup for jms/RemoteConnectionFactory
              jbertram

              Is the client on hostA running in an instance of JBoss AS?

               

              Can you post your messaging subsystem configuration?

              • 4. Re: JMS host not populated to remote client on JNDI lookup for jms/RemoteConnectionFactory
                jw

                Is the client on hostA running in an instance of JBoss AS?

                 

                No, it's a standalone client, running in a separete vm.

                 

                 

                Messaging subsystem configuration is

                 

                 

                {code:xml}

                        <subsystem xmlns="urn:jboss:domain:messaging:1.1">

                            <hornetq-server>

                                <persistence-enabled>false</persistence-enabled>

                                <security-domain>my-security-domain</security-domain>

                                <security-enabled>true</security-enabled>

                                <journal-file-size>102400</journal-file-size>

                                <journal-min-files>2</journal-min-files>

                 

                 

                                <connectors>

                                    <netty-connector name="netty" socket-binding="messaging"/>

                                    <netty-connector name="netty-throughput" socket-binding="messaging-throughput">

                                        <param key="batch-delay" value="50"/>

                                    </netty-connector>

                                    <in-vm-connector name="in-vm" server-id="0"/>

                                </connectors>

                 

                 

                                <acceptors>

                                    <netty-acceptor name="netty" socket-binding="messaging"/>

                                    <netty-acceptor name="netty-throughput" socket-binding="messaging-throughput">

                                        <param key="batch-delay" value="50"/>

                                        <param key="direct-deliver" value="false"/>

                                    </netty-acceptor>

                                    <in-vm-acceptor name="in-vm" server-id="0"/>

                                </acceptors>

                 

                 

                                <security-settings>

                                    <security-setting match="#">

                                        <permission type="send" roles="MEMBER"/>

                                        <permission type="consume" roles="MEMBER"/>

                                        <permission type="createNonDurableQueue" roles="MEMBER"/>

                                        <permission type="deleteNonDurableQueue" roles="MEMBER"/>

                                    </security-setting>

                                </security-settings>

                 

                 

                                <address-settings>

                                    <address-setting match="#">

                                        <dead-letter-address>jms.queue.DLQ</dead-letter-address>

                                        <expiry-address>jms.queue.ExpiryQueue</expiry-address>

                                        <redelivery-delay>0</redelivery-delay>

                                        <max-size-bytes>10485760</max-size-bytes>

                                        <address-full-policy>BLOCK</address-full-policy>

                                        <message-counter-history-day-limit>10</message-counter-history-day-limit>

                                    </address-setting>

                                </address-settings>

                 

                 

                                <jms-connection-factories>

                                    <connection-factory name="InVmConnectionFactory">

                                        <connectors>

                                            <connector-ref connector-name="in-vm"/>

                                        </connectors>

                                        <entries>

                                            <entry name="java:/ConnectionFactory"/>

                                        </entries>

                                    </connection-factory>

                                    <connection-factory name="RemoteConnectionFactory">

                                        <connectors>

                                            <connector-ref connector-name="netty"/>

                                        </connectors>

                                        <entries>

                                            <entry name="RemoteConnectionFactory"/>

                                            <entry name="java:jboss/exported/jms/RemoteConnectionFactory"/>

                                        </entries>

                                    </connection-factory>

                                    <pooled-connection-factory name="hornetq-ra">

                                        <transaction mode="xa"/>

                                        <connectors>

                                            <connector-ref connector-name="in-vm"/>

                                        </connectors>

                                        <entries>

                                            <entry name="java:/JmsXA"/>

                                        </entries>

                                    </pooled-connection-factory>

                                </jms-connection-factories>

                 

                 

                                <jms-destinations>

                                    <jms-topic name="MyTopic">

                                        <entry name="topic/MyTopic"/>

                                        <entry name="java:jboss/exported/jms/topic/MyTopic"/>

                                    </jms-topic>

                                </jms-destinations>

                            </hornetq-server>

                        </subsystem>

                {code}

                 

                 

                I also tried to set a host name in the 'netty' connector like this

                 

                {code:xml}

                <netty-connector name="netty" socket-binding="messaging">

                    <param key="host" value="hostB"/>

                </netty-connector>

                {code}

                 

                but it didn't helped.

                • 5. Re: JMS host not populated to remote client on JNDI lookup for jms/RemoteConnectionFactory
                  jw

                  Found a working solution:

                   

                   

                  {code:xml}

                                      <connector name="netty-remote" socket-binding="messaging">

                                          <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class>

                                          <param key="host" value="hostB"/>

                                      </connector>

                   

                                      <connection-factory name="RemoteConnectionFactory">

                                          <connectors>

                                              <connector-ref connector-name="netty-remote"/>

                                          </connectors>

                                          <entries>

                                              <entry name="RemoteConnectionFactory"/>

                                              <entry name="java:jboss/exported/jms/RemoteConnectionFactory"/>

                                          </entries>

                                      </connection-factory>

                  {code}

                   

                  What's confusing is that in this configuration

                   

                  {code:xml}

                                      <connector name="netty-remote" socket-binding="messaging">

                                          <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class>

                                          <param key="host" value="localhost"/>

                                      </connector>

                  {code}

                   

                   

                  'localhost' means the host where the client is running (hostA). I would expect that in this case 'localhost' means the host where AS7 is running (hostB).

                  • 6. Re: JMS host not populated to remote client on JNDI lookup for jms/RemoteConnectionFactory
                    jw

                    Another hack: leave the server config for netty connector as it is and update the wrong host name on client side:

                     

                     

                    {code:java}

                     

                            HornetQJMSConnectionFactory factory

                     

                            factory = (HornetQJMSConnectionFactory)ctx.lookup("jms/RemoteConnectionFactory");

                     

                     

                            // replace the the wrong value (0.0.0.0) for the host with the correct one AS7 is running on

                     

                            ServerLocatorImpl sl;

                            TransportConfiguration[] initialConnectors;

                            Field initialConnectorsField;

                     

                            sl = (ServerLocatorImpl) factory.getServerLocator();

                            initialConnectorsField = ServerLocatorImpl.class.getDeclaredField("initialConnectors");

                            initialConnectorsField.setAccessible(true);

                            initialConnectors = (TransportConfiguration[]) initialConnectorsField.get(sl);

                            initialConnectors[0].getParams().put(TransportConstants.HOST_PROP_NAME, "hostB");

                     

                    {code}

                     

                     

                    I hope this is not needed anymore in later versions and would vote for a bug

                    • 7. Re: JMS host not populated to remote client on JNDI lookup for jms/RemoteConnectionFactory
                      jbertram

                      I'm still a bit confused on why you need to do this.  I just tested this by binding AS 7.1.1.Final to 127.0.0.2 on my local box and then using a standalone client to send a message to it.  That should adequately mimic your scenario as any connection to "localhost" would not have made it to 127.0.0.2.  It worked without any issue.

                       

                      To be clear, the JNDI look-up is 100% independent of the JMS connection.  You get the JMS connection factory from the server by looking it up in JNDI, but once you have the reference to the connection factory and use it to create a connection the final destination of those connections had nothing to do with the java.naming.provider.url you used in your JNDI lookup.

                       

                      When looking up a connection factory in JNDI the client basically gets a connector which is a simple stub telling the client where its connections should go.  Take, for example, the default standalone-full.xml and a remote JMS client which looks up "jms/RemoteConnectionFactory".  Here is the definition of that connection factory:

                       

                      <connection-factory name="RemoteConnectionFactory">
                         <connectors>
                            <connector-ref connector-name="netty"/>
                         </connectors>
                         <entries>
                            <entry name="RemoteConnectionFactory"/>
                            <entry name="java:jboss/exported/jms/RemoteConnectionFactory"/>
                         </entries>
                      </connection-factory>
                      

                       

                      It is configured to use the "netty" connector so when a client looks up this connection factory it will receive this "netty" connector which will tell the client where to connect.  Here is the configuration of that "netty" connector:

                       

                      <connectors>
                         <netty-connector name="netty" socket-binding="messaging"/>
                         ...
                      </connectors>
                      

                       

                      The "netty" connector is configured to use the "messaging" socket-binding.  Here is the configuration of the "messaging" socket-binding:

                       

                      <socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
                          ...
                          <socket-binding name="messaging" port="5445"/>
                          ...
                      </socket-binding-group>
                      

                       

                      Notice that the socket-binding-group of which the "messaging" socket-binding is a part uses the "public" interface (i.e. the "default-interface").  Here is the definition of that "public" interface:

                       

                      <interfaces>
                          ...
                          <interface name="public">
                              <inet-address value="${jboss.bind.address:127.0.0.1}"/>
                          </interface>
                          ...
                      </interfaces>
                      

                       

                      This interface defaults to "127.0.0.1" (i.e. localhost) if no jboss.bind.address is specified.  However, if a user starts AS 7 with the "-b" command-line parameter then the "public" interface will be bound to the interface the user specifies.  For example:

                       

                      ./standalone.sh -c standalone-full.xml -b 127.0.0.2
                      

                       

                      Assuming that a user has done this then the AS 7 "public" interface will be on 127.0.0.2 which means the "messaging" socket-binding will be bound to 127.0.0.2:5445 which means that the "netty" connector will point clients to 127.0.0.2:5445 which means that any remote JMS client looking up "jms/RemoteConnectionFactory" will be pointed to 127.0.0.2:5445.

                       

                      Now, you can do some tricks with the connector like this:

                       

                      <connector name="netty">
                         <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class>
                         <param key="host" value="192.168.1.107"/>
                         <param key="port" value="5445"/>
                      </connector>
                      

                       

                      Assuming our server is still bound to 127.0.0.2 any client using "jms/RemoteConnectionFactory" will actually get a connection to 192.168.1.107:5445.  This flexibility allows the server to work behind NAT setups.

                       

                      Keep in mind that these values are just strings which the client uses to connect.  I mention this because previously you indicated that you thought using <param key="host" value="localhost"/> on hostB would cause a client on hostA to connect to hostB, but the "localhost" value would be passed to the client on hostA and it would therefore try to connect to "localhost" (i.e. hostA).

                       

                      At the end of the day, all this should "just work" if it is configured properly, and you shouldn't need any tricks or hacks.

                      • 8. Re: JMS host not populated to remote client on JNDI lookup for jms/RemoteConnectionFactory
                        jw

                        Thanks for your clarification.

                         

                        Keep in mind that these values are just strings which the client uses to connect.

                         

                        That's the key.

                        • 9. Re: JMS host not populated to remote client on JNDI lookup for jms/RemoteConnectionFactory
                          ktfan

                          I managed to send the JMS queue from one JBOSS AS7 to another remote JBOSS AS7 with this setup:

                           

                          standalone-full.xml for sender

                           

                          <connectors>

                               <connector name="remote-jms">

                                    <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class>

                                     <param key="host" value="192.168.2.110"/>

                                     <param key="port" value="5445"/>

                               </connector>

                               <netty-connector name="netty" socket-binding="messaging"/>                       

                               <netty-connector name="netty-throughput" socket-binding="messaging-throughput">

                                    <param key="batch-delay" value="50"/>

                                </netty-connector>

                                <in-vm-connector name="in-vm" server-id="0"/>

                          </connectors>

                           

                           

                          <security-settings>

                                  <security-setting match="#">

                                  <permission type="send" roles="developer"/>

                                  <permission type="consume" roles="developer"/>

                                  <permission type="createNonDurableQueue" roles="developer"/>

                                  <permission type="deleteNonDurableQueue" roles="developer"/>

                                  </security-setting>

                          </security-settings>

                           

                          <connection-factory name="RemoteConnectionFactory">

                                 <connectors>

                                    <connector-ref connector-name="remote-jms"/>

                                 </connectors>

                                 <entries>

                                    <entry name="RemoteConnectionFactory"/>

                                    <entry name="java:jboss/exported/jms/RemoteConnectionFactory"/>

                                 </entries>

                          </connection-factory>

                           

                          <jms-destinations>

                                <jms-queue name="testQueue">

                                     <entry name="queue/test"/>

                                     <entry name="java:jboss/exported/jms/queue/test"/>

                                </jms-queue>

                                <jms-topic name="testTopic">

                                      <entry name="topic/test"/>

                                      <entry name="java:jboss/exported/jms/topic/test"/>

                                      </jms-topic>

                          </jms-destinations>

                           

                          sender code

                           

                             String destinationName = "java:jboss/exported/jms/queue/test";

                                                 Context ic = null;

                                                 ConnectionFactory cf = null;

                                                 Connection connection =  null;                      

                                        

                                                           ic = new InitialContext();                                

                                                           cf = (ConnectionFactory)ic.lookup("java:jboss/exported/jms/RemoteConnectionFactory");                                

                                                           Queue queue = (Queue)ic.lookup(destinationName);                    

                              connection = cf.createConnection("user", "user1234");    //This user's role is developer

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

                                                           MessageProducer publisher = session.createProducer(queue);                                

                                                           connection.start();

                                                           TextMessage message = session.createTextMessage("Hello AS 7 !");

                                                           publisher.send(message);

                              connection.close();

                           

                           

                          MDB on remote JBOSS AS 7

                          import javax.ejb.MessageDriven;

                          import javax.ejb.ActivationConfigProperty;

                          import javax.jms.JMSException;

                          import javax.jms.Message;

                          import javax.jms.MessageListener;

                          import javax.jms.TextMessage;


                          @MessageDriven(name = "MessageMDBSample" , activationConfig = {

                                        @ActivationConfigProperty(propertyName = "destinationType" , propertyValue = "javax.jms.Queue" ),            

                                        @ActivationConfigProperty(propertyName = "destination" , propertyValue = "queue/test" ),

                                        @ActivationConfigProperty(propertyName = "acknowledgeMode" , propertyValue = "Auto-acknowledge" ) })



                          public class MDBSample implements MessageListener

                          {      

                                 public void onMessage(Message message)

                                  {

                                       

                                        TextMessage tm = (TextMessage) message;

                                       

                                        try

                                        {            

                                               System. out.println("Received message " +tm.getText());

                                       

                                        }

                                        catch (JMSException e)

                                        {

                                               e.printStackTrace();      

                                        }            

                                  }

                          }

                           

                           

                          Everything is working fine, the remote JBOSS AS 7 is able to receive the message "Hello AS 7 !".

                          Thanks for all the pointers provided. However I still prefer to set the remote JBOSS host IP programmatically, is that possible? Any pointer to the reference/documentation/sample is very much appreciated.