问题
I have a client run in JBoss
(JB_Client) and it needs to send messages to a remote Jboss server (JB_Server) HornetQ
. And Remote jboss server (JB_server) needs to send the response message back to it's HornetQ
. So JB_Client MDB
is listening to remote HorentQ
for the responses.
I am using Jboss AS6
for my client and server. This system works perfectly in local environment which is client and server both in same Jboss
. But now I need to separate client and server in to two machines.
here is my test client configuration.
Properties prop = new Properties();
prop.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
prop.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
prop.put(Context.PROVIDER_URL, "jnp://localhost:1099");
ictx = new InitialContext(prop);
conFactory = (ConnectionFactory)ictx.lookup("/ConnectionFactory");
qcon = (QueueConnection)conFactory.createConnection();
qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
Server does not have special settings except queues defined.
What configuration I need to do in server and client side to make this work?
回答1:
I was able to connect to remote server and get the response from the remote queue. Both my client and server running in two separate computers, JBossAS [6.1.0.Final "Neo"]. My client is a simple web app ( a war file)
Client side queue sender class.
private static void prepareContext() {
logger.debug("Loading Context");
try {
Properties prop = new Properties();
prop.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
prop.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
prop.put(Context.PROVIDER_URL, "jnp://10.1.4.48:1099");
ictx = new InitialContext(prop);
conFactory = (ConnectionFactory)ictx.lookup("/ConnectionFactory");
qcon = (QueueConnection)conFactory.createConnection();
qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
}
catch (NamingException er) {
logger.fatal("Error ", er);
}
catch (JMSException er) {
logger.fatal("Error ", er);
}
}
public static boolean sendToQueue(String xml, String sendQ) {
logger.warn("Sending to queue: " + xml);
try {
prepareContext();
Queue queue = getQueue(sendQ);
if (null == queue) {
throw new JMSException("Queue not defined at the end point");
}
qcon.start();
QueueSender qsender = qsession.createSender(queue);
TextMessage tmsg = qsession.createTextMessage();
tmsg.setText(xml);
qsender.send(tmsg);
return true;
}
catch (JMSException er) {
logger.fatal("Error ", er);
}
finally {
try { qsession.close(); } catch (Exception er) {/**/}
try { qcon.close(); } catch (Exception er) {/**/}
}
return false;
}
Above is client side sender code.
Now let's see how client side message receiver.
I used MDB
to listen remote server queue.
public class MessageReceiverBean implements MessageListener {
public void onMessage(Message message) {
try {
if (message instanceof TextMessage) {
TextMessage textMsg = (TextMessage) message;
logger.info("Inside onMessage of client app MessageReceiverBean : " + textMsg.getText());
}
}
catch (Exception er) {
logger.error("Error while retrieving message from Service provider", er);
}
}
}
MDB configuration is in ejb-jar.xml in the META-INF folder of my war file.
<message-driven>
<ejb-name>User1</ejb-name>
<ejb-class>com.my.MessageReceiverBean</ejb-class>
<messaging-type>javax.jms.MessageListener</messaging-type>
<transaction-type>Container</transaction-type>
<activation-config>
<activation-config-property>
<activation-config-property-name>destinationType</activation-config-property-name>
<activation-config-property-value>javax.jms.Queue</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>destination</activation-config-property-name>
<activation-config-property-value>queue/User4</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>ConnectorClassName</activation-config-property-name>
<activation-config-property-value>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>ConnectionParameters</activation-config-property-name>
<activation-config-property-value>host=10.1.4.48;port=5445</activation-config-property-value>
</activation-config-property>
</activation-config>
</message-driven>
Above last two activation-config-properties is additionally added to connect to the remote server. So client java coding is over now.
Bonus !!!. Above is just call it through JNDI in a simple java class. But you might interest to do it through EJB CDI injection without using context properties etc. For that you need to modify below settings in client jboss side.
There are two settings I changed in the client Jboss node.
hornetq-configuration.xml
in client Jboss node.
<connector name="netty">
<factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class>
<param key="host" value="${MY_IP:10.1.4.48}"/> <!-- For MY_IP you can put any word. Doesn't matter. -->
<param key="port" value="${hornetq.remoting.netty.port:5445}"/>
</connector>
ra.xml
file injms-ra.rar
(deploy folder) in client Jboss node. Comment the below settings like this.<!--<config-property> <description>The transport configuration. These values must be in the form of key=val;key=val;, if multiple connectors are used then each set must be separated by a comma i.e. host=host1;port=5445,host=host2;port=5446. Each set of params maps to the connector classname specified. </description> <config-property-name>ConnectionParameters</config-property-name> <config-property-type>java.lang.String</config-property-type> <config-property-value>server-id=0</config-property-value> </config-property>-->
Ok. Jboss settings are over. Now let's see EJB bean. We need to inject the above connection through annotation.
@Resource(mappedName = "/ConnectionFactory")
private QueueConnectionFactory qConnectionFactory;
If you check your hornetq-jms.xml
you can see under <connection-factory name="NettyConnectionFactory">
above mappedName is defined ( <entry name="/ConnectionFactory"/>
).
This is the JNDI name you should look in your EJB, to find the connectionFactory in the remote HornetQ server. That's it if you need to use EJB CDI injection rather than JNDI lookup.
Restart the client jboss then you should be able to send the messages from client to Server. (No special settings in starting the jboss)
You can verify where is it connecting, if you go to jmx-console of the client and go to org.hornetq
then click on module=JMS,name="NettyConnectionFactory",type=ConnectionFactory
. In StaticConnectors
you see where this NettyConnector is connecting.
Now server side Jboss HornetQ settings.
Edit the hornetq-configuration.xml in Server Jboss and change the section.
<acceptor name="netty">
<factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
<param key="host" value="${jboss.esb.bind.address:10.1.4.48}"/> <!-- Here I add the server IP and esb. May be you can remove the esb and use "jboss.bind.address:10.1.4.48" -->
<param key="port" value="${hornetq.remoting.netty.port:5445}"/>
</acceptor>
So this is server Jboss settings. And I start the server with run.bat -b 10.1.4.48 option.
Hope this helps.
来源:https://stackoverflow.com/questions/25397138/jboss-client-send-message-to-remote-hornetq-in-jboss