Confusion about when Solace properties are effective - java

We have a solace broker running in a docker container. When we create a JNDI Connection Factory there are default properties such as
Reconnect Retry Attempts
Connect Retry Attempts
Connect Retry Attempts per Host
and so on
When we establish a producer using JMS we give properties like so
env.put(SupportedProperty.SOLACE_JMS_JNDI_CLIENT_ID, config.getJndiClientID());
env.put(SupportedProperty.SOLACE_JMS_PROP_SENDER_ID, config.getSenderID());
env.put(SupportedProperty.SOLACE_JMS_VPN, config.getVpn());
env.put(SupportedProperty.SOLACE_JMS_JNDI_CONNECT_RETRIES, 0);
env.put(SupportedProperty.SOLACE_JMS_JNDI_RECONNECT_RETRIES, 0);
env.put(SupportedProperty.SOLACE_JMS_JNDI_CONNECT_RETRIES_PER_HOST, 0);
however at the run-time of application and at the point when connection is getting established it seems that these properties that I set on the client side take no effect. Specifically I was able to test that by stopping the docker container of solace and seeing that it is trying to reconnect 3 times which is what happens to be the default is on the broker side.
Therefore, the question, how to force the override of these properties on the client side, if at all possible? Under what circumstances does setting these properties on a client side take affect?

Loading of a JMS ConnectionFactory over JNDI is, per definition, a two step process: first the API connects to JNDI and then loads whatever JMS ConnectionFactory object has been created.
Property SOLACE_JMS_JNDI_CONNECT_RETRIES (note the JNDI) is actually the parameter for the first step ! It defines the #retries for contacting JNDI. If you want to change the definition of the loaded JMS ConnectionFactory, you need to do this in your Solace administrator. For example within admin GUI as shown below.

When you use env.put(), you are trying to set the JMS Property using the Initial Context.
But these properties could also be set through the JNDI properties file as well as the command line.
If you turn on the API debugging, you should be able to see which value is taken from where.
Now, once you are able to connect with the JNDI connection factory on the broker, the values will be taken from the broker side.

Related

Specifying active and failover jms connection through axis2 xml

I have a jms based webservice implemented in axis2 framework. It uses Tibco EMS for JMS queue and connection factory.
Currently I have defined the active EMS server connection in axis2.xml and works fine. However, if this server goes down for some reason, I need to update the ais2.xml manually to point to failover EMS server and then bounce my webservice.
How can I define both active and failover connection such that it switches automatically when active one goes down
Regards,
Rajesh
In TIBCO EMS you can define an FT URL using the following syntax :
tcp://server:port,tcp://server:port
For example :
tcp://server1:7222,tcp://server2:7222
I think you should be able to use such connection URL in your framework.

Load balancing issue while connecting to IBM MQ using JMS + CCDT file

We are trying to connect to IBMMQ using CCDT file and JMS configuration.
We are able to connect to it but we have an issue here:
since we are using spring to set connection factory with CCDT file, this is initialized once at the start of the application, but unfortunately it picks only one queue manager at a time,i.e it sends all the messages to same queue manager and it does not load balance.
Though i observed, if i manually set the CCDT file before every request then its able to load balance the Queue Managers, ideally it looks to me Queue Manager is decided whenever i set the URL to CCDT file. which is wrong practice. My expectation was to initialize the connection factory with CCDT file and then this configuration will be able to load balance on its own.
Can you help me this?
This is the expected behavior. MQ does not load balance clients, it connection balances them. The connection is the single most time consuming API call and in the case of a mutually authenticated TLS connection can take seconds to complete. Therefore a good application design will attempt to connect once, then maintain that connection for the duration of the session. The JMS architecture and Spring framework both expect this pattern.
The way that MQ provides load distribution (again, not true balancing, but rather round-robin distribution) is that the client connects a hop away from a clustered destination queue. A message addressed to that clustered destination queue will round-robin among all the instances of that queue.
If it is a request-reply application, the thing listening for requests on these clustered queue instances addresses the reply message using the Reply-To QMgr and Reply-To Queue name from the requesting message. In this scenario the requestors can fail over QMgr to QMgr if they lose their connection. The systems of record listening on the clustered queues generally do not fail over across queue managers in order to ensure all queue instances are served and because of transaction recovery.
Short answer is that CCDT and MQ client in general are not where MQ load distribution occurs. The client should make a connection and hold it as long as possible. Client reconnect and CCDT are for connection balancing only.
Load distribution is a feature of the MQ cluster. It requires multiple instances of a clustered queue and these are normally a network hop away from the client app that puts the message.

Configuration for Spring stomp multi-application server

I'm developing a realtime notification system in Spring 4 by using a build-in Message Broker, and STOMP over WebSocket.
I would like to handle a case when there is a multi-application server and user destination is unresolved (because user is connected to another server). Spring docs claim there is a solution:
In a multi-application server scenario a user destination may remain
unresolved because the user is connected to a different server. In
such cases you can configure a destination to broadcast unresolved
messages to so that other servers have a chance to try. This can be
done through the userDestinationBroadcast property of the
MessageBrokerRegistry in Java config and the
user-destination-broadcast attribute of the message-broker element in
XML.
But there is no example of such configuration. How can I set servers to recieve these messages and authentification parameters for system channel?
When dealing with multi-node applications using WebSockets over STOMP you must configure and use an external STOMP Broker (such as RabbitMQ) so that different application instances can communicate each other. Are you already doing it, right?
In order to configure the userDestinationBroadcast and the userRegistryBroadcast just assign a destination name to them. When the application starts and the system TCP connection between the app and the broker is established, these destinations will be automatically created and everything will work fine and transparently.
I've coded a Web Chat app using Spring WebSockets, RabbitMQ and much more and its configuration is available here.
I hope this helps.

How to get database connection through websphere ORB call?

i've got a websphere 6.1 cluster environment which is composed of two nodes with 2 appservers each. Let's call NodeA including Server1(2809) & Server2(2810), NodeB including Server3(2811) & Server4(2812). Meanwhile, i created a cluster-scope datasource with JNDI local_db.
Right now i want to get database connection in a java client through WAS ORB call from above environment. The specific part of java code would look like this:
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.ibm.websphere.naming.WsnInitialContextFactory");
env.put(Context.PROVIDER_URL,"iiop://localhost:2809");
javax.sql.DataSource ds = (DataSource)initialContext.lookup("local_db");
Connection cn = ds.getConnection();
If above java client code gets run, will the database connection retrieve request follow load-balancing rule among the four connection pools of all application servers?
Moreover, if my java client gets one database connection successfully and then run a big SQL Query with large result return, as for the memory space occupation, which WAS application server would take care? only server1 due to port 2809 used above or the target server who returns the database connection?
BTW, if i put two server members for that PROVIDER_URL, such as iiop://localhost:2809, localhost:2810, does it mean load-balancing or failover?
Please help explain and correct me if i'm understanding wrongly!
Thanks
Let me start with the easy ones and proceed to the rest
Having two provider URLs' implies failover. If you can't connect to the first naming server, it connects to the second naming server and continues till the end of that list. Notice the Fail over is for connection to the naming server (not to the resource itself)
The look up is done on the server that you connect to. THe local_db represents a datasource (and its connection pool) on that server. You will one work with the server1 (as you are connecting to that NS) and will get connection from the datasource hosted on that server.
You will never get any connection from the other servers. In others words there is no load balancing (one request uses connection from server1, another uses a connection from server 2 etc). I believe this is what you mean by load balancing in your question above.
HTH
A DataSource is neither remotable nor serializable. Therefore, if you look up local_db from the server, it will return a javax.naming.Reference that the client uses to create a new DataSource instance with the same configuration as the one on the server. That also means that once the lookup has been performed, no JDBC method will ever send requests to the WebSphere server.

Cannot connect to Tibco JMS server

I have a java application which does some JMS send&receive work. But I found an interesting problem. For example, I set the following for java.naming.provider.url.
tcp://hostnameA.foo.bar:7222
But I got the error as below. Only hostname in it, not the full qualified domain name.
javax.jms.JMSException: Failed to connect to the server at tcp://hostnameA:7222
Unless I add hostnameA in my hosts file manually, it won't connect to Tibco server.
How can I fix it?
Thanks in advance.
The EMS Server has its own built-in JNDI server. What you're actually doing when you connect is 1) querying the EMS:s JNDI server for a connection factory definition and then 2) creating a connection based on the returned factory. This is implied by the fact that you're using java.naming.provider.url.
Change the connection factory definition (factories.conf) on the EMS server for the connection factory you're using. The default definition for the default factories (e.g. QueueConnectionFactory) on a fresh install is "tcp://7222" which will be replaced by "tcp://hostname:7222" by the server when retrieved. You can change this definition to e.g. "tcp://hostname.myfqdn.com:7222" and things should work.
You could also bypass the JNDI server completely by creating a connection directly, but I wouldn't recommend this since the connection factory definition returned by the server may contain information about load balanced and fault tolerant pairs, SSL settings, or point to a completely different server pair etc. It also allows the EMS administrators to change the definition of connection factories without the clients having to change their code or even their configuration.
I guess this has nothing to do with the programming layer.
Your DNS query for that name is unresolvable, that's why it works when you edit your hosts-file.
Either check your system's DNS settings (or make sure the dns server which is in your system's configuration replies to your name query), or use the IP-address instead.

Categories