How to lookup a remote jms queue on Wildfly 10 - java

It's amazing that i can't find a working example of how to send a message to a Wildfly 10 jms queue. It seems every version of Jboss had a different way of doing this so i can find a few examples but each one addresses a different version and none for Wildfly 10.
what I'm trying to do is send a message from a master wildfly instance (running on machine 1) to a JMS queue hosted on a slave wildfly instance (running on machine 2-n). In other words, i may have several slave wildfly instances.
I've added to the standalone-full.xml of each slave instance the following:
1) In the global-modules element
<module name="org.jboss.remote-naming" slot="main"/>
2) The queue is defined as
<jms-queue name="JobTaskMDB" entries="queue/JobTaskExecuterQueue java:jboss/exported/queue/JobTaskExecuterQueue"/>
3) Every slave has the guest user
The only thing I've added to the standalone-full.xml of the master instance is (1) above
Given a machine name, such as "WILDD250148-8C9", how can i selectively send a message from the master Wildfly instance to the queue of the specified machine hosting one of the slave instances?
So far I can't even get passed the lookup of the queue.
I've tried the following code:
String server = "WILDD250148-8C9";
final Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, org.jboss.naming.remote.client.InitialContextFactory.class.getName());
env.put(Context.SECURITY_PRINCIPAL, "guest"); //has been added to all slaves
env.put(Context.SECURITY_CREDENTIALS, "guest");
String url =
//"queue/JobTaskExecuterQueue";
//"http-remoting://" + server + ":8080";
//"tcp://" + server + ":5445";
"jnp://" + server + ":1099";
env.put(Context.PROVIDER_URL, url);
env.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
remoteContext = new InitialContext(env);
String lookupName =
//"java:jboss/exported/queue/JobTaskExecuterQueue";
//"JobTaskMDB";
"queue.queue/JobTaskExecuterQueue";
Object x = remoteContext.lookup(lookupName);
I always get "javax.naming.CommunicationException: Failed to connect to any server", for example
javax.naming.CommunicationException: Failed to connect to any server. Servers tried: [jnp://WILDD250148-8C9:1099 (No connection provider for URI scheme "jnp" is installed)]
or
javax.naming.CommunicationException: Failed to connect to any server. Servers tried: [tcp://WILDD250148-8C9:5445 (No connection provider for URI scheme "tcp" is installed)]
when I used the url "http-remoting://" + server + ":8080" I got the exception:
javax.naming.CommunicationException: Failed to connect to any server. Servers tried: [http-remoting://WILDD250148-8C9:8080 (Operation failed with status WAITING after 5000 MILLISECONDS)] [Root exception is java.net.ConnectException: Operation failed with status WAITING after 5000 MILLISECONDS]
Obviously i don't even know which provider URL to use.
what am i missing here?

The correct URL provider for WildFly 10 is http-remoting.
This works for me with Wildfly 10.1:
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
props.put(Context.PROVIDER_URL, "http-remoting://127.0.0.1:8080");
props.put(Context.SECURITY_PRINCIPAL, "user");
props.put(Context.SECURITY_CREDENTIALS, "password");
InitialContext ctx = new InitialContext(props);
ActiveMQConnectionFactory cf = (ActiveMQConnectionFactory) ctx.lookup("jms/RemoteConnectionFactory");
ActiveMQQueue queue = (ActiveMQQueue) ctx.lookup("queue/JobTaskExecuterQueue");
If the JNDI name of the queue is java:jboss/exported/queue/JobTaskExecuterQueue then from the client, use queue/JobTaskExecuterQueue (it's relative to the java:jboss/exported/ namespace)
Remove this line, this is not needed:
env.put(Context.URL_PKG_PREFIXES,"org.jboss.naming:org.jnp.interfaces");
If you're getting
Operation failed with status WAITING after 5000 MILLISECONDS
then it means that the connection got stuck for more than 5 seconds for some probably different reason, like a firewall, slow network or something - the client code is probably correct.

Related

Java client using JMS for connecting to IBM MQ Channel of TCP/IP throwing error

We have a IBM MQ Server 7.5 running on a Windows server machine. Till now we had an IBM MQ JMS client (written in groovy) on Windows for reading messages on a TCP channel.
My problem now is we have to move the Client to a Debian machine.
I have downloaded the IBM MQ Client 7 for Debian.
I am writting a sample code to connect to the Server to read the messages.
I am using the JmsPutGet.java example from the IBM site.
The environment is as follows:
Java 8
com.ibm.mq.allclient-9.0.4.0.jar
javax.jms-api-2.0.1
The error I get is
The value specified for the property is not supported.
Modify the value to be within the range of accepted values.
FAILURE
I tried using connection mode Client as well, it gives a different error as below:
com.ibm.msg.client.jms.DetailedJMSException: JMSWMQ0018: Failed to connect to queue manager 'VIMSRRI10' with connection mode 'Client' and host name '172.18.21.5(1415)'.
Check the queue manager is started and if running in client mode, check there is a listener running. Please see the linked exception for more information.
Inner exception(s):
com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2539' ('MQRC_CHANNEL_CONFIG_ERROR').
com.ibm.mq.jmqi.JmqiException: CC=2;RC=2539;AMQ9204: Connection to host '172.18.21.5(1415)' rejected. [1=com.ibm.mq.jmqi.JmqiException[CC=2;RC=2539;AMQ9547: Type of remote channel not suitable for action requested. [3=IRRICI10.VIMSRRI10]],3=172.18.21.5(1415),5=RemoteConnection.analyseErrorSegment]
com.ibm.mq.jmqi.JmqiException: CC=2;RC=2539;AMQ9547: Type of remote channel not suitable for action requested. [3=IRRICI10.VIMSRRI10]
FAILURE
Sample java code is:
JmsFactoryFactory ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
JmsConnectionFactory cf = ff.createConnectionFactory();
// Set the properties
cf.setStringProperty(WMQConstants.WMQ_HOST_NAME, HOST);
cf.setIntProperty(WMQConstants.WMQ_PORT, PORT);
cf.setStringProperty(WMQConstants.WMQ_CHANNEL, CHANNEL);
cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_DIRECT_TCPIP);
cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, QMGR);
cf.setStringProperty(WMQConstants.WMQ_APPLICATIONNAME, "JmsPutGet (JMS)");
//cf.setBooleanProperty(WMQConstants.USER_AUTHENTICATION_MQCSP, true);
//cf.setStringProperty(WMQConstants.USERID, APP_USER);
//cf.setStringProperty(WMQConstants.PASSWORD, APP_PASSWORD);
// Create JMS objects
context = cf.createContext();
System.out.println("After Context\n");
destination = context.createQueue("queue:///" + QUEUE_NAME);
System.out.println("After Queue\n");
long uniqueNumber = System.currentTimeMillis() % 1000;
TextMessage message = context.createTextMessage("Your lucky number today is " + uniqueNumber);
producer = context.createProducer();
producer.send(destination, message);
System.out.println("Sent message:\n" + message);
consumer = context.createConsumer(destination); // autoclosable
String receivedMessage = consumer.receiveBody(String.class, 15000); // in ms or 15 seconds
System.out.println("\nReceived message:\n" + receivedMessage);
The channel you connect to must be a SVRCONN.
The error reason '2539' ('MQRC_CHANNEL_CONFIG_ERROR') indicates that the channel you are connecting to is not a SVRCONN.
This is spelled out clearer in the next line of the error which also provides the the name of the channel you are attempting to connect to IRRICI10.VIMSRRI10:
AMQ9547: Type of remote channel not suitable for action requested. [3=IRRICI10.VIMSRRI10]
The name of the channel itself is in a format common for a SDR or RCVR channels which are used between two queue managers, not for a MQ client app to connect to.

Qpid receiver on Azure EventHub

I have already working application based on Azure EventHub. Now I need write java receiver that connects to the existing infrastructure.
Existing configuration:
Event Hub > SomeName > Consumer Group > SomeGroupName
In the administrative console I cannot see any QUEUE or TOPIC definitions. Analyzing working c# code I can see that hub-name + group-name is enough to connect.
I have reconstructed url that allows me to connect over java (and connection works so far).
amqps://SomeName.servicebus.windows.net
So my questions:
1) When instead of queue /topic I specify group-name then I get exception The messaging entity 'sb://SomeName.servicebus.windows.net/SomeGroupName' could not be found. What is the model used there instead of queue/topic?
2) How to work with such infrastructure from Apache-qpid?
Are you using the Event Hub created in the old portal or one created using the new portal?
EventHub is not a Message Bus, so there are no Queues or Topics, that is correct.
The consumer group is not a part of the address. The address is build using the namespace and the name of the eventhub in that namespace.
So the address becomes:
sb://SomeNameSpaceName.servicebus.windows.net/SomeEventHubName
Can you post the c# code you've analyzed? Since you have an already working application maybe we can workout the differences that prevents it from working now.
The greatest hint for resolve the question gave me following link: http://theitjourney.blogspot.com/2015/12/sendreceive-messages-using-amqp-in-java.html
So No queue neither topic in this model. You need to connect to specific provider and specify correct EventHub as following:
application.properties:
connectionfactory.SBCF=amqps://<PolicyName>:<PolicyKey>#<DomainName>.servicebus.windows.net
queue.EventHub=<EventHubName>/ConsumerGroups/$Default/Partitions/0
Where:
After that following code allowed me to create MessageConsumer:
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.qpid.amqp_1_0.jms.jndi.PropertiesFileInitialContextFactory");
env.put(Context.PROVIDER_URL,
getClass().getResource("/application.properties").toString());
Context context = null;
context = new InitialContext(env);
// Look up ConnectionFactory
ConnectionFactory cf = (ConnectionFactory) context.lookup("SBCF");
Destination queue = (Destination) context.lookup("EventHub");
// Create Connection
Connection connection = cf.createConnection();
// Create receiver-side Session, MessageConsumer
Session receiveSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer receiver = receiveSession.createConsumer(queue);

ERROR when creating a connectioFactory JMS websphere MQ

The native JNI library 'mqjbnd64' not found.
please some one can help me to get mqjbnd64
this is my code
ConnectionFactory connectionFactory=null;
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
env.put(Context.PROVIDER_URL, "file:/C:/CWMQv75-POT/JMS/JNDI Namespace");
try{
Context ctx = new InitialContext(env);
// MQQueueManager qm = (MQQueueManager)ctx.lookup("QM");
MQConnectionFactory cf = (MQConnectionFactory) ctx.lookup("CF1");
// cf.createConnection().start();
MQQueue q = (MQQueue) ctx.lookup("JMS1");
connectionFactory = (ConnectionFactory)ctx.lookup("CF1");
System.out.println("succes "+q.getBaseQueueManagerName().toString() + " " + q.getBaseQueueName()+" " +" " + cf.getChannel() );
} catch (NamingException e)
{
System.err.println(e.getLocalizedMessage());
e.printStackTrace();
}
Connection connection = connectionFactory.createConnection();
}
The native JNI library 'mqjbnd64' not found
Questions:
1) Are you running your JMS application on the SAME serer as the queue manager or a different server?
2) When you defined your QCF, did you include host, port #, channel name?
3) Do you understand the difference between connecting to a queue manager in bindings mode vs client mode?
You can ONLY connect in bindings mode if your application is running on the same server as the queue manager. When connecting in bindings mode the JMS/Java MQ library uses the native MQ library, hence, it needs the mqjbnd64 shared library or DLL on Windows to perform the MQ API calls.
Most MQ applications do NOT reside on the same server as the queue manager and they will use client mode to connect to the remote queue manager and your QCF would look something like:
DEFINE QCF(MYQCF) QMANAGER(MQWL1) CHANNEL(TESTCHL) HOSTNAME(10.10.10.10) PORT(1414) TRANSPORT(CLIENT) FAILIFQUIESCE(YES)
One other thing I noticed:
env.put(Context.PROVIDER_URL, "file:/C:/CWMQv75-POT/JMS/JNDI Namespace");
that should be:
env.put(Context.PROVIDER_URL, "file://C:/CWMQv75-POT/JMS/JNDI Namespace");
You should have 2 forward slashes "//" after "file:".

Too much time to send mail with MS exchange SMTP server

Hi all and thanks for your help
I use javamail to send mail throhght office365 SMTP server ( smtp.office365.com) , but for some reason it keeps about 60-80 seconds to send mail.
stringaHost = "mail.smtp.host";
stringaUser = "mail.smtp.user";
Security.setProperty("ssl.SocketFactory.provider","com.ibm.jsse2.SSLSocketFactoryImpl");
Security.setProperty("ssl.ServerSocketFactory.provider","com.ibm.jsse2.SSLServerSocketFactoryImpl");
InitialContext initialContext = null;
initialContext = new InitialContext();
session = (Session)initialContext.lookup(nomeJndi);
session.getProperties().put("mail.smtp.auth", "true");
session.getProperties().put("mail.smtp.socketFactory.port", 465);
session.getProperties().put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
MimeMessage MsgEmail = new MimeMessage( session );
com.sun.mail.smtp.SMTPTransport t =(com.sun.mail.smtp.SMTPTransport)session.getTransport("smtp");
t.setStartTLS(true);
t.connect( smtp.office365.com,myUser,myPassword);
t.sendMessage( MsgEmail, MsgEmail.getAllRecipients());
t.close();
java mail spend more than 60 sec to evaluate instruction : t.connect(....) .
Any clue about what can happen and how can this time interval can be reduced ?
P.S. i tried to use t.connect() without parameters, by system technical says that this instruction use SMTP transport protocol from operating system and don't use Office365 server transport protocol
thanks
First, you shouldn't need all those socket factory properties.
If the delay is on the connect call, the possibilities are:
Your name service is slow in looking up the IP address for the server's host name.
The SSL negotiation is slow, perhaps due to certificate management on the client or server.
The server is slow authenticating you.
You can test #1 by seeing how long it takes InetAddress to look up the host name for your server.
You can test #2 by seeing how long it takes SSLSocket to make a connection to the server.
You can test #3 by either watching the JavaMail debug output in real time to see where the delay is, or getting time-stamped log messages from JavaMail.

Java (and JBoss) JNDI and RMI ports

I have JBoss running on a couple of Linux machines. If I want to send a JMS message from box 1 to a queue on box2, I may do something like this:
Hashtable<String,String> jndiProperties = new Hashtable<String,String>();
jndiProperties.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
jndiProperties.put(javax.naming.Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
jndiProperties.put(javax.naming.Context.PROVIDER_URL, "jnp://<ip of box2>:1099"); //
InitialContext context = new InitialContext(m_jndiProperties);
Queue queue = (Queue)context.lookup("queue/myqueue");
and then put a message on the queue. Clearly port 1099 needs to be open on box2, but I am curious what other ports are involved in that communication?
Thank You.
Others I have off top of my head:
Rmi: 1098.
HornetQ acceptors / connectors: 5446 / 5445. Both configurable in JBOSS_HOME/server/default/deploy/hornetq/hornetq-configuration.xml

Categories