JNDI Client
Federated JNDI Context
Overview
The Federated JNDI Context is the default built-in JNDI context that directly communicates with the JNDI Swiftlet of the connected SwiftMQ Router.
InitialContextFactory
Class Name
JNDI uses a factory pattern to create a vendor-specific implementation of InitialContext
. The name of the provider's implementation of this InitialContextFactory
must be set in an environment table before creating an InitialContext object. The name of SwiftMQ's InitialContextFactory
implementation is:
com.swiftmq.jndi.InitialContextFactoryImpl
JNDI Provider URL
The JNDI provider URL is used to set up the internal connection properties. A JNDI connection is internally backed up by a JMS connection. Hereby, any available JMS inbound listener can be used. For details please have a look at the JMS Swiftlet configuration.
The JNDI provider URL specifies the properties of the underlying JMS connection with the following format:
smqp://[<user>[:<password>]@](<host>:<port>)|"intravm"[/[host2=<host2>][;port2=<port2>]
[;reconnect=<boolean>][;retrydelay=<long>][;maxretries=<int>][;type=<type>]
[;timeout=<long>][;keepalive=<long>][;debug=<boolean>][;idleclose=<long>]
Where
smqp ::= Specifies the SwiftMQ Protocol
<user> ::= Username. Default is 'anonymous'
<password> ::= User's password. Default is null.
<host> ::= DNS hostname of the 1st HA instance or the keyword "intravm" to connect intra-VM
<port> ::= JMS listener port of the 1st HA instance
host2 ::= DNS hostname of the 2nd HA instance
port2 ::= JMS listener port of the 2nd HA instance
reconnect ::= Specifies whether an automatic reconnect should be done
retrydelay ::= Amount in milliseconds to wait between reconnect retries
maxretries ::= Max. number of reconnect retries
type ::= Class name of the socket factory used by this JMS listener.
In this release, com.swifmq.net.PlainSocketFactory and
com.swiftmq.net.JSSESocketFactory are available. Default is
com.swifmq.net.PlainSocketFactory. See JMS Swiftlet configuration for details.
timeout ::= Specifies a timeout in milliseconds for lookups. If no JNDI object is
received within this time, the lookup throws a NamingException. Default is no timeout;
lookups are waiting until they receive the requested JNDI objects.
keepalive ::= Specifies a keepalive interval in milliseconds. If this value is greater 0, a
timer is created on the client side to send keepalive messages to detect broken
JNDI connections. Default is 60000 (1 minute)
debug ::= If true, debug information are printed to System.out. Good for testing.
idleclose ::= Specifies the maximum idle time of the underlying JMS connection after which it is
closed. It is re-opened when the context is accessed again (i.e. a new lookup).
Default is 60000 ms. To disable it, set it to -1.
Note: Attributes "host2" and "port2" are reserved when connected to a SwiftMQ HA Router.
Examples
JNDI lookups should be performed via a JMS listener on host localhost
, port 4001
, as user anonymous
. The JMS listener provides access via a com.swiftmq.net.PlainSocketFactory
. No lookup timeout should be set:
smqp://locahost:4001
JNDI lookups should be performed via a JMS listener on host www.swiftmq.com
, port 4020
, as user johnsmith
, password ballaballa
. The JMS inbound listener provides access via a com.swiftmq.net.JSSESocketFactory
. The lookup timeout should be set to 20 secs:
smqp://johnsmith:ballaballa@www.swiftmq.com:4020/type=com.swiftmq.net.JSSESocketFactory;timeout=20000
Connects to host jms1
at port 4001
. If a connection loss is detected, it reconnects with a delay of 1 second between retries. It stops retries after 50 unsuccessful attempts. JNDI lookup timeout is set to 10 seconds.
smqp://jms1:4001/timeout=10000;reconnect=true;retrydelay=1000;maxretries=50
Performing JNDI Lookups
To use JNDI, the following import statement has to be included into the application's import list:
import javax.naming.*;
Furthermore, the JNDI and the SwiftMQ classes must be accessible through the CLASSPATH
.
Before creating an InitalContext
object, two environment properties must be set. These are the names of the InitialContextFactory
implementation and the SwiftMQ JNDI-Provider-URL:
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.swiftmq.jndi.InitialContextFactoryImpl");
env.put(Context.PROVIDER_URL,"smqp://localhost:4001");
Then, the InitialContext
is to be created:
InitialContext ctx = new InitialContext(env);
Now, a JNDI connection has been established and lookups can be performed to fetch the appropriate administered objects:
TopicConnectionFactory tcf = (TopicConnectionFactory)ctx.lookup("plainsocket@router3");
Topic topic = (Topic)ctx.lookup("iit.projects.swiftmq");
// etc pp
Bind/Rebind/Unbind
A JMS client that has created a TemporaryTopic
or a TemporaryQueue
can register this kind of object within SwiftMQ's JNDI implementation. It is not permitted to register other types of objects. After registration, other JMS clients are able to look up these objects under their registered names. This is a rare case because the TopicRequestor resp does the normal handling of this issue. QueueRequestor
helper classes. Here, the temporary destination is set in the message by the message producer as a JMSReplyTo
header. The receiver/subscriber gets this destination and replies to it. In special cases, this procedure is not possible. For these cases, the destinations could be registered within JNDI.
To register a temporary destination, use Context.bind
:
TemporaryQueue tq = queueSession.createTemporaryQueue();
ctx.bind("myTempQueue",tq);
Another client is able to lookup this object and send messages to it:
TemporaryQueue tq = ctx.lookup("myTempQueue");
QueueSender sender = queueSession.createQueueSender(tq);
sender.send(msg);
A client can also change an existing registration with Context.rebind
:
ctx.rebind("myInboundQueue",tq);
And, of course, it can remove the registration with:
ctx.unbind("myInboundQueue");
JNDI registrations of temporary destinations have a lifetime of the temporary destination itself. If the temporary destination will be deleted by the client, for example with tq.delete()
, or the JMS connection that has created the temporary destination will be closed (which deletes implicitly their temporary destinations), all JNDI registrations of these destinations will also be deleted automatically. So, a client does not need to explicitly call unbind for his registrations.
Closing the Context
By closing the InitialContext
, the connection is dropped and all resources on the client and server side are released. Otherwise, the client may not terminate, because there are running threads.
Idle Close (since 12.4.1)
The InitialContext
is backed by an internal JMS connection which is closed after reaching an idle timeout. It is re-opened when new access, i.e. a lookup
, takes place. The default idle timeout is 60000 ms and can be set via the URL attribute idleclose
. It can be disabled by setting it to -1
. It is recommended to stick with the default setting since it is often forgotten to close the InitialContext
resulting in unused JMS connections.
Filesystem JNDI Context
Overview
The Filesystem JNDI Context is a built-in filesystem-based JNDI context which uses a directory at the client to store and lookup JNDI objects.
InitialContextFactory
Class Name
JNDI uses a factory pattern to create a vendor-specific implementation of InitialContext
. The name of the provider's implementation of this InitialContextFactory
must be set in an environment table before creating an InitialContext
object. The name of SwiftMQ's filesystem-based InitialContextFactory
implementation is com.swiftmq.jndi.fs.InitialContextFactoryImpl
.
JNDI Provider URL
The JNDI provider URL is a file URL and must point to the directory where the JNDI objects are stored.
Example:
file:///home/test/myjndi
Storing JNDI Objects
There are 2 ways to store JNDI objects in the directory where the JNDI provider URL points to:
By JNDI replication
By manual creation
JNDI replication can be set up in the JNDI Swiftlet by using the JNDI properties described for the JNDI lookup, see below. It dumps all registered JNDI objects to the directory specified by the JNDI provider URL. This directory then can be transferred to the clients to perform the lookups.
The other way is the manual creation of the JNDI objects. SwiftMQ uses XStream for JNDI object serialization. There are 3 types of administered objects that can be stored: Connection factories, queues, and topics. JNDI objects are stored one file per object with the lookup name as the file name plus a ".xml" extension like "ConnectionFactory.xml".
Connection Factories
Various attributes can be defined. Have a look at the JMS Swiftlet for its meanings. Here is an example, stored in file "ConnectionFactory.xml", of a connection factory that was dumped in a JNDI replication:
<com.swiftmq.jms.v750.ConnectionFactoryImpl>
<listenerName>plainsocket</listenerName>
<socketFactoryClass>com.swiftmq.net.PlainSocketFactory</socketFactoryClass>
<hostname>imac-buero</hostname>
<port>4001</port>
<keepaliveInterval>60000</keepaliveInterval>
<smqpProducerReplyInterval>20</smqpProducerReplyInterval>
<smqpConsumerCacheSize>500</smqpConsumerCacheSize>
<smqpConsumerCacheSizeKB>2048</smqpConsumerCacheSizeKB>
<jmsDeliveryMode>2</jmsDeliveryMode>
<jmsPriority>4</jmsPriority>
<jmsTTL>0</jmsTTL>
<jmsMessageIdEnabled>true</jmsMessageIdEnabled>
<jmsMessageTimestampEnabled>true</jmsMessageTimestampEnabled>
<useThreadContextCL>false</useThreadContextCL>
<inputBufferSize>131072</inputBufferSize>
<inputExtendSize>65536</inputExtendSize>
<outputBufferSize>131072</outputBufferSize>
<outputExtendSize>65536</outputExtendSize>
<intraVM>false</intraVM>
<port2>-1</port2>
<reconnectEnabled>true</reconnectEnabled>
<maxRetries>50</maxRetries>
<retryDelay>10000</retryDelay>
<duplicateMessageDetection>true</duplicateMessageDetection>
<duplicateBacklogSize>30000</duplicateBacklogSize>
</com.swiftmq.jms.v750.ConnectionFactoryImpl>
Queues
An example, stored in file "testqueue@router1.xml", of a queue that was dumped in a JNDI replication (Attribute s
is the name of the queue):
<com.swiftmq.jms.QueueImpl>
<queueName>
<s>testqueue@router1</s>
</queueName>
</com.swiftmq.jms.QueueImpl>
Topics
An example, stored in file "testtopic.xml", of a queue that was dumped in a JNDI replication (Attribute s
is the name of the topic):
<com.swiftmq.jms.TopicImpl>
<topicName>
<s>testtopic</s>
</topicName>
</com.swiftmq.jms.TopicImpl>
Performing JNDI Lookups
To use JNDI, the following import statement has to be included in the application's import list:
import javax.naming.*;
Furthermore, the JNDI and the SwiftMQ classes must be accessible through the CLASSPATH
.
Before creating an InitalContext
object, two environment properties must be set. These are the names of the InitialContextFactory
implementation and the JNDI-Provider-URL:
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.swiftmq.jndi.fs.InitialContextFactoryImpl");
env.put(Context.PROVIDER_URL,"file:///path/to/localjndi");
Then, the InitialContext
is to be created:
InitialContext ctx = new InitialContext(env);
Now lookups can be performed to fetch the JNDI objects:
TopicConnectionFactory tcf = (TopicConnectionFactory)ctx.lookup("plainsocket@router3");
Topic topic = (Topic)ctx.lookup("iit.projects.swiftmq");
// etc pp