-
1. Re: JMS host not populated to remote client on JNDI lookup for jms/RemoteConnectionFactory
jbertram Mar 7, 2012 9:19 AM (in response to jw)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 Mar 7, 2012 9:48 AM (in response to jbertram)- 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 Mar 7, 2012 9:53 AM (in response to jw)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 Mar 8, 2012 2:20 AM (in response to jbertram)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 Mar 9, 2012 4:44 AM (in response to 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 Mar 9, 2012 9:28 AM (in response to 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 Mar 23, 2012 8:59 AM (in response to jw)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 Mar 23, 2012 2:44 AM (in response to jbertram)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 Jun 19, 2012 11:35 PM (in response to jbertram)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.