Author: orudyy
Date: Fri Jul 10 08:31:17 2015
New Revision: 1690225
URL: http://svn.apache.org/r1690225
Log:
QPID-6635: Introduce separate JNDI ObjectFactory to allow construction of Qpid
client object from JNDI References objects
Add support for Address syntax in JNDI objects constructed from
References
Allow registering PolledConnectionFactory in external JNDI
Use user-friendly name for specifying Connection URLs, Binding URLs,
Address for construction of Qpid client objects from References
Added:
qpid/java/trunk/client/src/main/java/org/apache/qpid/jndi/ObjectFactory.java
qpid/java/trunk/client/src/test/java/org/apache/qpid/jndi/ObjectFactoryTest.java
Modified:
qpid/java/trunk/client/src/main/java/org/apache/qpid/client/AMQConnection.java
qpid/java/trunk/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java
qpid/java/trunk/client/src/main/java/org/apache/qpid/client/AMQDestination.java
qpid/java/trunk/client/src/main/java/org/apache/qpid/client/PooledConnectionFactory.java
qpid/java/trunk/doc/book/src/jms-client-0-8/JMS-Client-Appendix-Tomcat-JNDI-Integration.xml
Modified:
qpid/java/trunk/client/src/main/java/org/apache/qpid/client/AMQConnection.java
URL:
http://svn.apache.org/viewvc/qpid/java/trunk/client/src/main/java/org/apache/qpid/client/AMQConnection.java?rev=1690225&r1=1690224&r2=1690225&view=diff
==============================================================================
---
qpid/java/trunk/client/src/main/java/org/apache/qpid/client/AMQConnection.java
(original)
+++
qpid/java/trunk/client/src/main/java/org/apache/qpid/client/AMQConnection.java
Fri Jul 10 08:31:17 2015
@@ -57,6 +57,7 @@ import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
+import org.apache.qpid.jndi.ObjectFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -87,9 +88,11 @@ import org.apache.qpid.url.URLSyntaxExce
public class AMQConnection extends Closeable implements CommonConnection,
Referenceable
{
+ public static final String JNDI_ADDRESS_CONNECTION_URL = "connectionURL";
+
private static final Logger _logger =
LoggerFactory.getLogger(AMQConnection.class);
- private static final AtomicLong CONN_NUMBER_GENERATOR = new AtomicLong();
+ private static final AtomicLong CONN_NUMBER_GENERATOR = new AtomicLong();
private static final long DEFAULT_CLOSE_TIMEOUT =
Long.getLong(ClientProperties.QPID_CLOSE_TIMEOUT,
ClientProperties.DEFAULT_CLOSE_TIMEOUT);
@@ -1599,8 +1602,8 @@ public class AMQConnection extends Close
public Reference getReference() throws NamingException
{
- return new Reference(AMQConnection.class.getName(), new
StringRefAddr(AMQConnection.class.getName(), toURL()),
- AMQConnectionFactory.class.getName(), null); //
factory location
+ return new Reference(AMQConnection.class.getName(), new
StringRefAddr(JNDI_ADDRESS_CONNECTION_URL, toURL()),
+ ObjectFactory.class.getName(), null); // factory
location
}
public String getDefaultTopicExchangeName()
Modified:
qpid/java/trunk/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java
URL:
http://svn.apache.org/viewvc/qpid/java/trunk/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java?rev=1690225&r1=1690224&r2=1690225&view=diff
==============================================================================
---
qpid/java/trunk/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java
(original)
+++
qpid/java/trunk/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java
Fri Jul 10 08:31:17 2015
@@ -20,8 +20,11 @@
*/
package org.apache.qpid.client;
+import static org.apache.qpid.client.AMQConnection.JNDI_ADDRESS_CONNECTION_URL;
+
import org.apache.qpid.client.util.JMSExceptionHelper;
import org.apache.qpid.jms.ConnectionURL;
+import org.apache.qpid.jndi.ObjectFactory;
import org.apache.qpid.url.AMQBindingURL;
import org.apache.qpid.url.URLSyntaxException;
@@ -44,7 +47,6 @@ import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
-import javax.naming.spi.ObjectFactory;
import java.io.Serializable;
import java.net.InetAddress;
@@ -54,11 +56,11 @@ import java.util.UUID;
public class AMQConnectionFactory implements ConnectionFactory,
QueueConnectionFactory, TopicConnectionFactory,
- ObjectFactory, Referenceable,
XATopicConnectionFactory,
+ javax.naming.spi.ObjectFactory,
Referenceable, XATopicConnectionFactory,
XAQueueConnectionFactory,
XAConnectionFactory, Serializable
{
protected static final String NO_URL_CONFIGURED = "The connection factory
wasn't created with a proper URL, the connection details are empty";
-
+ private final static ObjectFactory OBJECT_FACTORY = new ObjectFactory();
private ConnectionURL _connectionDetails;
@@ -215,55 +217,13 @@ public class AMQConnectionFactory implem
* @return AMQConnection,AMQTopic,AMQQueue, or AMQConnectionFactory.
*
* @throws Exception
+ *
+ * @Deprecated Use {@link ObjectFactory} instead
*/
+ @Deprecated
public Object getObjectInstance(Object obj, Name name, Context ctx,
Hashtable env) throws Exception
{
- if (obj instanceof Reference)
- {
- Reference ref = (Reference) obj;
-
- if (ref.getClassName().equals(AMQConnection.class.getName()))
- {
- RefAddr addr = ref.get(AMQConnection.class.getName());
-
- if (addr != null)
- {
- return new AMQConnection((String) addr.getContent());
- }
- }
-
- if (ref.getClassName().equals(AMQQueue.class.getName()))
- {
- RefAddr addr = ref.get(AMQQueue.class.getName());
-
- if (addr != null)
- {
- return new AMQQueue(new AMQBindingURL((String)
addr.getContent()));
- }
- }
-
- if (ref.getClassName().equals(AMQTopic.class.getName()))
- {
- RefAddr addr = ref.get(AMQTopic.class.getName());
-
- if (addr != null)
- {
- return new AMQTopic(new AMQBindingURL((String)
addr.getContent()));
- }
- }
-
- if
(ref.getClassName().equals(AMQConnectionFactory.class.getName()))
- {
- RefAddr addr = ref.get(AMQConnectionFactory.class.getName());
-
- if (addr != null)
- {
- return new AMQConnectionFactory((String)
addr.getContent());
- }
- }
-
- }
- return null;
+ return OBJECT_FACTORY.getObjectInstance(obj, name, ctx, env);
}
@@ -271,8 +231,8 @@ public class AMQConnectionFactory implem
{
return new Reference(
AMQConnectionFactory.class.getName(),
- new StringRefAddr(AMQConnectionFactory.class.getName(),
_connectionDetails.getURL()),
- AMQConnectionFactory.class.getName(), null);
// factory location
+ new StringRefAddr(JNDI_ADDRESS_CONNECTION_URL,
_connectionDetails.getURL()),
+ ObjectFactory.class.getName(), null); //
factory location
}
//
---------------------------------------------------------------------------------------------------
Modified:
qpid/java/trunk/client/src/main/java/org/apache/qpid/client/AMQDestination.java
URL:
http://svn.apache.org/viewvc/qpid/java/trunk/client/src/main/java/org/apache/qpid/client/AMQDestination.java?rev=1690225&r1=1690224&r2=1690225&view=diff
==============================================================================
---
qpid/java/trunk/client/src/main/java/org/apache/qpid/client/AMQDestination.java
(original)
+++
qpid/java/trunk/client/src/main/java/org/apache/qpid/client/AMQDestination.java
Fri Jul 10 08:31:17 2015
@@ -34,6 +34,7 @@ import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
+import org.apache.qpid.jndi.ObjectFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -51,6 +52,8 @@ import org.apache.qpid.url.URLHelper;
public abstract class AMQDestination implements Destination, Referenceable,
Externalizable
{
+ public static final String JNDI_ADDRESS_DESTINATION_ADDRESS = "address";
+
private static final Logger _logger =
LoggerFactory.getLogger(AMQDestination.class);
private static final long serialVersionUID = -3152767926421156400L;
@@ -149,6 +152,11 @@ public abstract class AMQDestination imp
" should be one of
{BURL|ADDR}");
}
}
+
+ public String asPrefix()
+ {
+ return name() + ":";
+ }
}
public enum AddressOption {
@@ -740,8 +748,9 @@ public abstract class AMQDestination imp
{
return new Reference(
this.getClass().getName(),
- new StringRefAddr(this.getClass().getName(), toURL()),
- AMQConnectionFactory.class.getName(),
+ new StringRefAddr(JNDI_ADDRESS_DESTINATION_ADDRESS,
+ _destSyntax == DestSyntax.ADDR ?
getAddress().toString() : DestSyntax.BURL.asPrefix() + toURL()),
+ ObjectFactory.class.getName(),
null); // factory location
}
Modified:
qpid/java/trunk/client/src/main/java/org/apache/qpid/client/PooledConnectionFactory.java
URL:
http://svn.apache.org/viewvc/qpid/java/trunk/client/src/main/java/org/apache/qpid/client/PooledConnectionFactory.java?rev=1690225&r1=1690224&r2=1690225&view=diff
==============================================================================
---
qpid/java/trunk/client/src/main/java/org/apache/qpid/client/PooledConnectionFactory.java
(original)
+++
qpid/java/trunk/client/src/main/java/org/apache/qpid/client/PooledConnectionFactory.java
Fri Jul 10 08:31:17 2015
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.client;
+import static org.apache.qpid.client.AMQConnection.JNDI_ADDRESS_CONNECTION_URL;
+
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -52,6 +54,7 @@ import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
+import org.apache.qpid.jndi.ObjectFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -62,6 +65,10 @@ import org.apache.qpid.url.URLSyntaxExce
public class PooledConnectionFactory implements ConnectionFactory,
QueueConnectionFactory, TopicConnectionFactory
{
+
+ public static final String JNDI_ADDRESS_MAX_POOL_SIZE = "maxPoolSize";
+ public static final String JNDI_ADDRESS_CONNECTION_TIMEOUT =
"connectionTimeout";
+
private static final Logger LOGGER =
LoggerFactory.getLogger(PooledConnectionFactory.class);
private static final AtomicInteger POOL_ID = new AtomicInteger();
@@ -388,10 +395,14 @@ public class PooledConnectionFactory imp
public Reference getReference() throws NamingException
{
- return new Reference(
+ Reference reference = new Reference(
PooledConnectionFactory.class.getName(),
- new StringRefAddr(PooledConnectionFactory.class.getName(),
_connectionDetails.get().getURL()),
- PooledConnectionFactory.class.getName(), null); //
factory location
+ new StringRefAddr(JNDI_ADDRESS_CONNECTION_URL,
_connectionDetails.get().getURL()),
+ ObjectFactory.class.getName(), null); // factory
location
+
+ reference.add(new StringRefAddr(JNDI_ADDRESS_MAX_POOL_SIZE,
String.valueOf(getMaxPoolSize())));
+ reference.add(new StringRefAddr(JNDI_ADDRESS_CONNECTION_TIMEOUT,
String.valueOf(getMaxPoolSize())));
+ return reference;
}
private CommonConnection proxyConnection(CommonConnection underlying,
ConnectionDetailsIdentifier identifier) throws JMSException
Added:
qpid/java/trunk/client/src/main/java/org/apache/qpid/jndi/ObjectFactory.java
URL:
http://svn.apache.org/viewvc/qpid/java/trunk/client/src/main/java/org/apache/qpid/jndi/ObjectFactory.java?rev=1690225&view=auto
==============================================================================
---
qpid/java/trunk/client/src/main/java/org/apache/qpid/jndi/ObjectFactory.java
(added)
+++
qpid/java/trunk/client/src/main/java/org/apache/qpid/jndi/ObjectFactory.java
Fri Jul 10 08:31:17 2015
@@ -0,0 +1,229 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.jndi;
+
+import static org.apache.qpid.client.AMQConnection.JNDI_ADDRESS_CONNECTION_URL;
+import static
org.apache.qpid.client.PooledConnectionFactory.JNDI_ADDRESS_MAX_POOL_SIZE;
+import static
org.apache.qpid.client.PooledConnectionFactory.JNDI_ADDRESS_CONNECTION_TIMEOUT;
+import static
org.apache.qpid.client.AMQDestination.JNDI_ADDRESS_DESTINATION_ADDRESS;
+
+import java.net.URISyntaxException;
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.RefAddr;
+import javax.naming.Reference;
+
+import org.apache.qpid.QpidException;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQConnectionFactory;
+import org.apache.qpid.client.AMQDestination;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.AMQTopic;
+import org.apache.qpid.client.PooledConnectionFactory;
+import org.apache.qpid.messaging.Address;
+import org.apache.qpid.url.AMQBindingURL;
+import org.apache.qpid.url.URLSyntaxException;
+
+public class ObjectFactory implements javax.naming.spi.ObjectFactory
+{
+ @Override
+ public Object getObjectInstance(Object object, Name name, Context nameCtx,
Hashtable<?, ?> environment) throws Exception
+ {
+ if (object instanceof Reference)
+ {
+ Reference reference = (Reference)object;
+ String referenceClassName = reference.getClassName();
+
+ if
(referenceClassName.equals(AMQConnectionFactory.class.getName()))
+ {
+ return createAMQConnectionFactory(reference);
+ }
+ else if
(referenceClassName.equals(PooledConnectionFactory.class.getName()))
+ {
+ return createPooledConnectionFactory(reference);
+ }
+ else if (referenceClassName.equals(AMQConnection.class.getName()))
+ {
+ return createAMQConnection(reference);
+ }
+ else if (referenceClassName.equals(AMQQueue.class.getName()))
+ {
+ return createAMQQueue(reference);
+ }
+ else if (referenceClassName.equals(AMQTopic.class.getName()))
+ {
+ return createAMQTopic(reference);
+ }
+
+ }
+ return null;
+ }
+
+ private PooledConnectionFactory createPooledConnectionFactory(Reference
reference) throws URLSyntaxException
+ {
+ Object connectionURL = getRefAddressContent(reference,
JNDI_ADDRESS_CONNECTION_URL);
+ if (connectionURL instanceof String)
+ {
+ PooledConnectionFactory connectionFactory = new
PooledConnectionFactory();
+
connectionFactory.setConnectionURLString(String.valueOf(connectionURL));
+
+ Object maxPoolSize = getRefAddressContent(reference,
JNDI_ADDRESS_MAX_POOL_SIZE);
+ if (maxPoolSize != null)
+ {
+ connectionFactory.setMaxPoolSize(maxPoolSize instanceof Number
? ((Number) maxPoolSize).intValue() :
Integer.parseInt(String.valueOf(maxPoolSize)));
+ }
+
+ Object connectionTimeout = getRefAddressContent(reference,
JNDI_ADDRESS_CONNECTION_TIMEOUT);
+ if (connectionTimeout != null)
+ {
+ connectionFactory.setConnectionTimeout(connectionTimeout
instanceof Number ? ((Number) connectionTimeout).longValue() :
Long.parseLong(String.valueOf(connectionURL)));
+ }
+
+ return connectionFactory;
+ }
+
+ return null;
+ }
+
+ private AMQConnection createAMQConnection(Reference reference) throws
URLSyntaxException, QpidException
+ {
+ Object connectionURL = getRefAddressContent(reference,
JNDI_ADDRESS_CONNECTION_URL);
+
+ if (connectionURL == null)
+ {
+ // for backward compatibility
+ connectionURL = getRefAddressContent(reference,
AMQConnection.class.getName());
+ }
+
+ if (connectionURL instanceof String)
+ {
+ return new AMQConnection((String) connectionURL);
+ }
+
+ return null;
+ }
+
+ private AMQTopic createAMQTopic(Reference reference) throws
URISyntaxException
+ {
+ return (AMQTopic)createAMQDestination(reference, AMQTopic.class);
+ }
+
+ private AMQQueue createAMQQueue(Reference reference) throws
URISyntaxException
+ {
+ return (AMQQueue)createAMQDestination(reference, AMQQueue.class);
+ }
+
+ private AMQConnectionFactory createAMQConnectionFactory(Reference
reference) throws URLSyntaxException
+ {
+ Object connectionURL = getRefAddressContent(reference,
JNDI_ADDRESS_CONNECTION_URL);
+
+ if (connectionURL == null)
+ {
+ // for backward compatibility
+ connectionURL = getRefAddressContent(reference,
AMQConnectionFactory.class.getName());
+ }
+
+ if (connectionURL instanceof String)
+ {
+ return new AMQConnectionFactory((String) connectionURL);
+ }
+
+ return null;
+ }
+
+ private Object getRefAddressContent(Reference reference, String
addressType)
+ {
+ RefAddr refAddr = reference.get(addressType);
+ if (refAddr != null)
+ {
+ return refAddr.getContent();
+ }
+ return null;
+ }
+
+ private AMQDestination createAMQDestination(Reference reference, Class<?
extends AMQDestination> destinationClass) throws URISyntaxException
+ {
+ AMQDestination.DestSyntax addressSyntax =
AMQDestination.DestSyntax.ADDR;
+
+ Object address = getRefAddressContent(reference,
JNDI_ADDRESS_DESTINATION_ADDRESS);
+ if (address == null)
+ {
+ // for backward compatibility
+ address = getRefAddressContent(reference,
destinationClass.getName());
+ if (address instanceof String)
+ {
+ addressSyntax = AMQDestination.DestSyntax.BURL;
+ }
+ }
+
+ if (address instanceof String)
+ {
+ String addressString = (String)address;
+ if
(addressString.startsWith(AMQDestination.DestSyntax.BURL.asPrefix()))
+ {
+ addressSyntax = AMQDestination.DestSyntax.BURL;
+ addressString =
addressString.substring(AMQDestination.DestSyntax.BURL.asPrefix().length());
+ }
+ else if
(addressString.startsWith(AMQDestination.DestSyntax.ADDR.asPrefix()))
+ {
+ addressSyntax = AMQDestination.DestSyntax.ADDR;
+ addressString =
addressString.substring(AMQDestination.DestSyntax.BURL.asPrefix().length());
+ }
+
+ return createAMQDestination(destinationClass, addressSyntax,
addressString);
+ }
+
+ return null;
+ }
+
+ private AMQDestination createAMQDestination(Class<? extends
AMQDestination> destinationClass, AMQDestination.DestSyntax addressSyntax,
String addressString) throws URISyntaxException
+ {
+ if (destinationClass == AMQQueue.class)
+ {
+ if (addressSyntax == AMQDestination.DestSyntax.ADDR)
+ {
+ return new AMQQueue(Address.parse(addressString));
+ }
+ else
+ {
+ return new AMQQueue(new AMQBindingURL(addressString));
+ }
+ }
+ else if (destinationClass == AMQTopic.class)
+ {
+ if (addressSyntax == AMQDestination.DestSyntax.ADDR)
+ {
+ return new AMQTopic(Address.parse(addressString));
+ }
+ else
+ {
+ return new AMQTopic(new AMQBindingURL(addressString));
+ }
+ }
+ else
+ {
+ throw new IllegalStateException("Unsupported destination " +
destinationClass);
+ }
+ }
+
+}
Added:
qpid/java/trunk/client/src/test/java/org/apache/qpid/jndi/ObjectFactoryTest.java
URL:
http://svn.apache.org/viewvc/qpid/java/trunk/client/src/test/java/org/apache/qpid/jndi/ObjectFactoryTest.java?rev=1690225&view=auto
==============================================================================
---
qpid/java/trunk/client/src/test/java/org/apache/qpid/jndi/ObjectFactoryTest.java
(added)
+++
qpid/java/trunk/client/src/test/java/org/apache/qpid/jndi/ObjectFactoryTest.java
Fri Jul 10 08:31:17 2015
@@ -0,0 +1,305 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.jndi;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import static org.apache.qpid.client.AMQConnection.JNDI_ADDRESS_CONNECTION_URL;
+import static
org.apache.qpid.client.AMQDestination.JNDI_ADDRESS_DESTINATION_ADDRESS;
+import static
org.apache.qpid.client.PooledConnectionFactory.JNDI_ADDRESS_CONNECTION_TIMEOUT;
+import static
org.apache.qpid.client.PooledConnectionFactory.JNDI_ADDRESS_MAX_POOL_SIZE;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.RefAddr;
+import javax.naming.Reference;
+
+import junit.framework.TestCase;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQConnectionFactory;
+import org.apache.qpid.client.AMQConnectionURL;
+import org.apache.qpid.client.AMQDestination;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.AMQTopic;
+import org.apache.qpid.client.PooledConnectionFactory;
+import org.apache.qpid.messaging.Address;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class ObjectFactoryTest extends QpidTestCase
+{
+ private static final String TEST_CONNECTION_URL =
"amqp://:@clientid/test?brokerlist='tcp://localhost:5672'";
+ private static final String TEST_QUEUE_BINDING_URL =
"direct://amq.direct/myQueue/myQueue?routingkey='myQueue'&durable='true'";
+ private static final String TEST_TOPIC_BINDING_URL =
"topic://amq.topic/myTopic/myTopic?routingkey='myTopic'&exclusive='true'&autodelete='true'";
+ private static final String TEST_QUEUE_ADDRESS = "myQueue; {create:
always, node:{ type: queue }}";
+ private static final String TEST_TOPIC_ADDRESS = "myTopic; {create:
always, node:{ type: topic }}";
+
+ private ObjectFactory _objectFactory;
+ private Name _name;
+ private Context _context;
+ private Hashtable<?, ?> _environment;
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _objectFactory = new ObjectFactory();
+
+ _name = mock(Name.class);
+ _context = mock(Context.class);
+ _environment = mock(Hashtable.class);
+ }
+
+ public void testGetObjectInstanceReturnsNullIfNotReference() throws
Exception
+ {
+ Object factory = _objectFactory.getObjectInstance(new Object(), _name,
_context, _environment);
+ assertNull("Null should be returned for non Reference object",
factory);
+ }
+
+ public void testGetObjectInstanceReturnsNullForUnsupportedClassName()
throws Exception
+ {
+ Reference reference = createMockReference(Object.class.getName(),
"test", "test");
+
+ Object factory = _objectFactory.getObjectInstance(reference, _name,
_context, _environment);
+ assertNull("Null should be returned for unsupported class name",
factory);
+ }
+
+ public void
testGetObjectInstanceReturnsNullForSupportedClassButUnsupportedAddress() throws
Exception
+ {
+ Reference reference =
createMockReference(AMQConnectionFactory.class.getName(), "test", 1);
+
+ Object factory = _objectFactory.getObjectInstance(reference, _name,
_context, _environment);
+ assertNull("Null should be returned for unsupported content", factory);
+ }
+
+ public void
testGetObjectInstanceOfAMQConnectionFactoryUsingLegacyAddress() throws Exception
+ {
+ Reference reference =
createMockReference(AMQConnectionFactory.class.getName(),
+ AMQConnectionFactory.class.getName(), TEST_CONNECTION_URL);
+
+ Object factory = _objectFactory.getObjectInstance(reference, _name,
_context, _environment);
+ assertTrue("Unexpected object type : " + factory , factory instanceof
AMQConnectionFactory);
+ assertEquals("Unexpected connection URL", new
AMQConnectionURL(TEST_CONNECTION_URL),
+ ((AMQConnectionFactory) factory).getConnectionURL());
+ }
+
+ public void
testGetObjectInstanceOfAMQConnectionFactoryUsingConnectionURLAddress() throws
Exception
+ {
+ Reference reference =
createMockReference(AMQConnectionFactory.class.getName(),
+ JNDI_ADDRESS_CONNECTION_URL, TEST_CONNECTION_URL);
+
+ Object factory = _objectFactory.getObjectInstance(reference, _name,
_context, _environment);
+ assertTrue("Unexpected object type : " + factory , factory instanceof
AMQConnectionFactory);
+ TestCase.assertEquals("Unexpected connection URL", new
AMQConnectionURL(TEST_CONNECTION_URL),
+ ((AMQConnectionFactory) factory).getConnectionURL());
+ }
+
+ public void testGetObjectInstanceOfAMQQueueUsingLegacyAddress() throws
Exception
+ {
+ Reference reference = createMockReference(AMQQueue.class.getName(),
AMQQueue.class.getName(), TEST_QUEUE_BINDING_URL);
+
+ Object queue = _objectFactory.getObjectInstance(reference, _name,
_context, _environment);
+ assertTrue("Unexpected object type : " + queue, queue instanceof
AMQQueue);
+ assertEquals("Unexpected binding URL", TEST_QUEUE_BINDING_URL,
((AMQQueue) queue).toURL());
+ }
+
+ public void testGetObjectInstanceOfAMQQueueUsingBindingUrlAddress() throws
Exception
+ {
+ Reference reference = createMockReference(AMQQueue.class.getName(),
JNDI_ADDRESS_DESTINATION_ADDRESS,
+ AMQDestination.DestSyntax.BURL.asPrefix() +
TEST_QUEUE_BINDING_URL);
+
+ Object queue = _objectFactory.getObjectInstance(reference, _name,
_context, _environment);
+ assertTrue("Unexpected object type : " + queue , queue instanceof
AMQQueue);
+ assertEquals("Unexpected binding URL", TEST_QUEUE_BINDING_URL,
((AMQQueue) queue).toURL());
+ }
+
+ public void testGetObjectInstanceOfAMQQueueUsingAddressBasedAddress()
throws Exception
+ {
+ Reference reference = createMockReference(AMQQueue.class.getName(),
JNDI_ADDRESS_DESTINATION_ADDRESS,
+ TEST_QUEUE_ADDRESS);
+
+ Object queue = _objectFactory.getObjectInstance(reference, _name,
_context, _environment);
+ assertTrue("Unexpected object type : " + queue, queue instanceof
AMQQueue);
+ assertTrue("Unexpected address " + ((AMQQueue) queue).getAddress(),
+ equals(Address.parse(TEST_QUEUE_ADDRESS), ((AMQQueue)
queue).getAddress()));
+ }
+
+ public void
testGetObjectInstanceOfAMQQueueUsingPrefixedAddressBasedAddress() throws
Exception
+ {
+ Reference reference = createMockReference(AMQQueue.class.getName(),
JNDI_ADDRESS_DESTINATION_ADDRESS,
+ AMQDestination.DestSyntax.ADDR.asPrefix() +
TEST_QUEUE_ADDRESS);
+
+ Object queue = _objectFactory.getObjectInstance(reference, _name,
_context, _environment);
+ assertTrue("Unexpected object type : " + queue, queue instanceof
AMQQueue);
+ assertTrue("Unexpected address " + ((AMQQueue) queue).getAddress(),
+ equals(Address.parse(TEST_QUEUE_ADDRESS), ((AMQQueue)
queue).getAddress()));
+ }
+
+ public void testGetObjectInstanceOfAMQTopicUsingLegacyAddressType() throws
Exception
+ {
+ Reference reference = createMockReference(AMQTopic.class.getName(),
AMQTopic.class.getName(), TEST_TOPIC_BINDING_URL);
+
+ Object topic = _objectFactory.getObjectInstance(reference, _name,
_context, _environment);
+ assertTrue("Unexpected object type : " + topic , topic instanceof
AMQTopic);
+ assertEquals("Unexpected binding URL", TEST_TOPIC_BINDING_URL,
((AMQTopic) topic).toURL());
+ }
+
+ public void testGetObjectInstanceOfAMQTopicUsingBindingURLAddress() throws
Exception
+ {
+ Reference reference = createMockReference(AMQTopic.class.getName(),
JNDI_ADDRESS_DESTINATION_ADDRESS,
+ AMQDestination.DestSyntax.BURL.asPrefix() +
TEST_TOPIC_BINDING_URL);
+
+ Object queue = _objectFactory.getObjectInstance(reference, _name,
_context, _environment);
+ assertTrue("Unexpected object type : " + queue , queue instanceof
AMQTopic);
+ assertEquals("Unexpected binding URL", TEST_TOPIC_BINDING_URL,
((AMQTopic) queue).toURL());
+ }
+
+ public void testGetObjectInstanceOfAMQTopicUsingAddressBasedAddress()
throws Exception
+ {
+ Reference reference = createMockReference(AMQTopic.class.getName(),
JNDI_ADDRESS_DESTINATION_ADDRESS,
+ TEST_TOPIC_ADDRESS);
+
+ Object queue = _objectFactory.getObjectInstance(reference, _name,
_context, _environment);
+ assertTrue("Unexpected object type : " + queue , queue instanceof
AMQTopic);
+ assertTrue("Unexpected address " + ((AMQTopic) queue).getAddress(),
+ equals(Address.parse(TEST_TOPIC_ADDRESS), ((AMQTopic)
queue).getAddress()));
+ }
+
+ public void
testGetObjectInstanceOfAMQTopicUsingPrefixedAddressBasedAddress() throws
Exception
+ {
+ Reference reference = createMockReference(AMQTopic.class.getName(),
JNDI_ADDRESS_DESTINATION_ADDRESS,
+ AMQDestination.DestSyntax.ADDR.asPrefix() +
TEST_TOPIC_ADDRESS);
+
+ Object queue = _objectFactory.getObjectInstance(reference, _name,
_context, _environment);
+ assertTrue("Unexpected object type : " + queue , queue instanceof
AMQTopic);
+ assertTrue("Unexpected address " + ((AMQTopic) queue).getAddress(),
+ equals(Address.parse(TEST_TOPIC_ADDRESS), ((AMQTopic)
queue).getAddress()));
+ }
+
+ public void testGetObjectInstanceOfAMQConnectionUsingLegacyAddressType()
throws Exception
+ {
+ Reference reference =
createMockReference(AMQConnection.class.getName(),
AMQConnection.class.getName(), TEST_CONNECTION_URL + "&failover='unsupported'");
+
+ // in order to prevent establishing of TCP connection
+ // testing AMQConnection creation indirectly relying on IAE thrown for
unsupported failover method
+ try
+ {
+ _objectFactory.getObjectInstance(reference, _name, _context,
_environment);
+ fail("Exception is expected");
+ }
+ catch(IllegalArgumentException e)
+ {
+ assertEquals("Unknown failover method:unsupported",
e.getMessage());
+ }
+ }
+
+ public void testGetObjectInstanceOfAMQConnectionUsingAddressTypeAddress()
throws Exception
+ {
+ Reference reference =
createMockReference(AMQConnection.class.getName(), JNDI_ADDRESS_CONNECTION_URL,
TEST_CONNECTION_URL + "&failover='unsupported'");
+
+ // in order to prevent establishing of TCP connection
+ // testing AMQConnection creation indirectly relying on IAE thrown for
unsupported failover method
+ try
+ {
+ _objectFactory.getObjectInstance(reference, _name, _context,
_environment);
+ fail("Exception is expected");
+ }
+ catch(IllegalArgumentException e)
+ {
+ assertEquals("Unknown failover method:unsupported",
e.getMessage());
+ }
+ }
+
+ public void testGetObjectInstanceOfPooledConnectionFactory() throws
Exception
+ {
+ Reference reference =
createMockReference(PooledConnectionFactory.class.getName(),
+ JNDI_ADDRESS_CONNECTION_URL, TEST_CONNECTION_URL);
+
+ Name name = mock(Name.class);
+ Context context = mock(Context.class);
+ Hashtable<?, ?> environment = mock(Hashtable.class);
+
+ Object factory = _objectFactory.getObjectInstance(reference, name,
context, environment);
+ assertTrue("Unexpected object type : " + factory, factory instanceof
PooledConnectionFactory);
+ assertEquals("Unexpected connection URL", TEST_CONNECTION_URL,
((PooledConnectionFactory)factory).getConnectionURL().getURL());
+ }
+
+ public void
testGetObjectInstanceOfPooledConnectionFactoryWithMaxPoolSizeAndConnectionTimeout()
throws Exception
+ {
+ Reference reference =
createMockReference(PooledConnectionFactory.class.getName(),
+ JNDI_ADDRESS_CONNECTION_URL, TEST_CONNECTION_URL);
+
+ RefAddr maxPoolSizeRefAddr = mock(RefAddr.class);
+
when(reference.get(JNDI_ADDRESS_MAX_POOL_SIZE)).thenReturn(maxPoolSizeRefAddr);
+ when(maxPoolSizeRefAddr.getContent()).thenReturn(20);
+
+ RefAddr connectionTimeoutRefAddr = mock(RefAddr.class);
+
when(reference.get(JNDI_ADDRESS_CONNECTION_TIMEOUT)).thenReturn(connectionTimeoutRefAddr);
+ when(connectionTimeoutRefAddr.getContent()).thenReturn(2000l);
+
+ Object factory = _objectFactory.getObjectInstance(reference, _name,
_context, _environment);
+ assertTrue("Unexpected object type : " + factory, factory instanceof
PooledConnectionFactory);
+ PooledConnectionFactory pooledConnectionFactory =
(PooledConnectionFactory) factory;
+ assertEquals("Unexpected max pool size", 20,
pooledConnectionFactory.getMaxPoolSize());
+ assertEquals("Unexpected timeout", 2000l,
pooledConnectionFactory.getConnectionTimeout());
+ }
+
+ private Reference createMockReference(String className, String
addressType, Object content)
+ {
+ Reference reference = mock(Reference.class);
+ when(reference.getClassName()).thenReturn(className);
+ RefAddr mockedRefAddr = mock(RefAddr.class);
+ when(reference.get(addressType)).thenReturn(mockedRefAddr);
+ when(mockedRefAddr.getContent()).thenReturn(content);
+ return reference;
+ }
+
+ private boolean equals(Address address1, Address address2)
+ {
+ if (address1 == address2)
+ {
+ return true;
+ }
+
+ if ((address1 == null && address2 != null) || (address1 != null &&
address2 == null))
+ {
+ return false ;
+ }
+
+ if (address1.getClass() != address2.getClass())
+ {
+ return false;
+ }
+
+ if (address1.getName() != null ?
!address1.getName().equals(address2.getName()) : address2.getName() != null)
+ {
+ return false;
+ }
+
+ if (address1.getSubject() != null ?
!address1.getSubject().equals(address2.getSubject()) : address2.getSubject() !=
null)
+ {
+ return false;
+ }
+
+ return !(address1.getOptions() != null ?
!address1.getOptions().equals(address2.getOptions()) : address2.getOptions() !=
null);
+ }
+}
Modified:
qpid/java/trunk/doc/book/src/jms-client-0-8/JMS-Client-Appendix-Tomcat-JNDI-Integration.xml
URL:
http://svn.apache.org/viewvc/qpid/java/trunk/doc/book/src/jms-client-0-8/JMS-Client-Appendix-Tomcat-JNDI-Integration.xml?rev=1690225&r1=1690224&r2=1690225&view=diff
==============================================================================
---
qpid/java/trunk/doc/book/src/jms-client-0-8/JMS-Client-Appendix-Tomcat-JNDI-Integration.xml
(original)
+++
qpid/java/trunk/doc/book/src/jms-client-0-8/JMS-Client-Appendix-Tomcat-JNDI-Integration.xml
Fri Jul 10 08:31:17 2015
@@ -32,53 +32,70 @@
Qpid client destinations and connection factories can be registered in
external JNDI containers, for example, Tomcat JNDI implementation.
</para>
<para>
- <literal>AMQConnectionFactory</literal> implements
+ <literal>org.apache.qpid.jndi.ObjectFactory</literal> implements
<ulink
url="&oracleJdkDocUrl;javax/naming/spi/ObjectFactory.html">javax.naming.spi.ObjectFactory</ulink>
- allowing it to create instances of
<literal>AMQConnectionFactory</literal>, <literal>AMQConnection</literal>,
- <literal>AMQQueue</literal> and <literal>AMQTopic</literal> in external
JNDI container from
+ allowing it to create instances of
<literal>AMQConnectionFactory</literal>,
<literal>PolledConnectionFactory</literal>,
+ <literal>AMQConnection</literal>, <literal>AMQQueue</literal> and
<literal>AMQTopic</literal> in external JNDI container from
<ulink
url="&oracleJdkDocUrl;javax/naming/Reference.html">javax.naming.Reference</ulink>s.
- Both <literal>AMQConnectionFactory</literal> and
<literal>AMQDestination</literal> (parent of
+ </para>
+ <para>Additionally,
+ <literal>AMQConnectionFactory</literal>,
<literal>PooledConnectionFactory</literal> and
<literal>AMQDestination</literal> (parent of
<literal>AMQQueue</literal> and <literal>AMQTopic</literal>) implement
<ulink
url="&oracleJdkDocUrl;javax/naming/Referenceable.html">javax.naming.Referenceable</ulink>
- allowing creation of <ulink
url="&oracleJdkDocUrl;javax/naming/Reference.html">javax.naming.Reference</ulink>
- to itself for binding in external JNDI implementations.
+ allowing creation of <ulink
url="&oracleJdkDocUrl;javax/naming/Reference.html">javax.naming.Reference</ulink>
objects
+ for binding in external JNDI implementations.
</para>
<para>
- <literal>AMQConnectionFactory</literal> allows the creation of:
+ <literal>org.apache.qpid.jndi.ObjectFactory</literal> allows the creation
of:
<itemizedlist>
<listitem>
<para>
an instance of <literal>ConnectionFactory</literal> from a
<literal>Reference</literal> containing reference
- address (<ulink
url="&oracleJdkDocUrl;javax/naming/RefAddr.html">javax.naming.RefAddr</ulink>)
of type
- <literal>org.apache.qpid.client.AMQConnectionFactory</literal> with
content set to a
+ address (<ulink
url="&oracleJdkDocUrl;javax/naming/RefAddr.html">javax.naming.RefAddr</ulink>)
+ <literal>connectionURL</literal> with content set to a
+ <link linkend="JMS-Client-0-8-Connection-URL">Connection URL</link>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ an instance of <literal>PolledConnectionFactory</literal> from a
<literal>Reference</literal> containing reference
+ address (<ulink
url="&oracleJdkDocUrl;javax/naming/RefAddr.html">javax.naming.RefAddr</ulink>)
+ <literal>connectionURL</literal> with content set to a
<link linkend="JMS-Client-0-8-Connection-URL">Connection URL</link>.
</para>
</listitem>
<listitem>
<para>
an instance of <literal>AMQConnection</literal> from a
<literal>Reference</literal> containing reference
- address (<ulink
url="&oracleJdkDocUrl;javax/naming/RefAddr.html">javax.naming.RefAddr</ulink>)
of type
- <literal>org.apache.qpid.client.AMQConnection</literal> with content
set to a
+ address (<ulink
url="&oracleJdkDocUrl;javax/naming/RefAddr.html">javax.naming.RefAddr</ulink>)
+ <literal>connectionURL</literal> with content set to a
<link linkend="JMS-Client-0-8-Connection-URL">Connection URL</link>.
</para>
</listitem>
<listitem>
<para>
an instance of <literal>AMQQueue</literal> from a
<literal>Reference</literal> containing reference
- address (<ulink
url="&oracleJdkDocUrl;javax/naming/RefAddr.html">javax.naming.RefAddr</ulink>)
of type
- <literal>org.apache.qpid.client.AMQQueue</literal> with content set
to a
+ address (<ulink
url="&oracleJdkDocUrl;javax/naming/RefAddr.html">javax.naming.RefAddr</ulink>)
+ <literal>address</literal> with content set to either <ulink
url="&qpidProgrammingBook;">Address</ulink> or
<link linkend="JMS-Client-0-8-Binding-URL">Binding URL</link>.
</para>
</listitem>
<listitem>
<para>
an instance of <literal>AMQTopic</literal> from a
<literal>Reference</literal> containing reference
- address (<ulink
url="&oracleJdkDocUrl;javax/naming/RefAddr.html">javax.naming.RefAddr</ulink>)
of type
- <literal>org.apache.qpid.client.AMQTopic</literal> with a content
set to
+ address (<ulink
url="&oracleJdkDocUrl;javax/naming/RefAddr.html">javax.naming.RefAddr</ulink>)
+ <literal>address</literal> with content set to either <ulink
url="&qpidProgrammingBook;">Address</ulink> or
<link linkend="JMS-Client-0-8-Binding-URL">Binding URL</link>.
</para>
</listitem>
</itemizedlist>
+ <note>
+ <para>
+ For <literal>AMQQueue</literal> and <literal>AMQTopic</literal>
prefix <literal>BURL:</literal> need
+ to be specified for <link linkend="JMS-Client-0-8-Binding-URL">Binding
URL</link>. Otherwise, client will try
+ to parse content using <ulink
url="&qpidProgrammingBook;">Address</ulink> format.
+ </para>
+ </note>
</para>
<para>An example below demonstrates how to create JNDI resources in the
Tomcat container using Resource declarations in context.xml
(A Tomcat specific web application configuration file usually added into
war under /META-INF/context.xml).
@@ -92,24 +109,33 @@
<Resource name="jms/connectionFactory" auth="Container"
type="org.apache.qpid.client.AMQConnectionFactory"
- factory="org.apache.qpid.client.AMQConnectionFactory"
-
org.apache.qpid.client.AMQConnectionFactory="amqp://guest:guest@clientid/?brokerlist='localhost:5672'"/>
+ factory="org.apache.qpid.jndi.ObjectFactory"
+
connectionURL="amqp://guest:guest@clientid/?brokerlist='localhost:5672'"/>
+
+ <Resource name="jms/polledConnectionFactory" auth="Container"
+ type="org.apache.qpid.client.PooledConnectionFactory"
+ factory="org.apache.qpid.jndi.ObjectFactory"
+
connectionURL="amqp://guest:guest@clientid/?brokerlist='localhost:5672'"
+ maxPoolSize="20" connectionTimeout="60000"/>
<Resource name="jms/queue" auth="Container"
type="org.apache.qpid.client.AMQQueue"
- factory="org.apache.qpid.client.AMQConnectionFactory"
-
org.apache.qpid.client.AMQQueue="direct://amq.direct//myDurableQueue?durable='true'"/>
+ factory="org.apache.qpid.jndi.ObjectFactory"
+ address="BURL:direct://amq.direct//myQueue?durable='true'"/>
<Resource name="jms/topic" auth="Container"
type="org.apache.qpid.client.AMQTopic"
factory="org.apache.qpid.client.AMQConnectionFactory"
-
org.apache.qpid.client.AMQTopic="topic://amq.topic?routingkey='myTopic'"/>
+ address="BURL:topic://amq.topic//myTopic?routingkey='myTopic'"/>
</Context>]]></programlisting>
</example>
- <para>In the example above <literal>ConnectionFactory</literal> would be
registered under JNDI name "jms/connectionFactory",
- <literal>Queue</literal> "myDurableQueue" would be registered under JNDI
name "jms/queue" and JMS <literal>Topic</literal>
+ <para>In the example above <literal>AMQConnectionFactory</literal> would be
registered under JNDI name "jms/connectionFactory",
+ <literal>PooledConnectionFactory</literal> would be registered under JNDI
name "jms/polledConnectionFactory",
+ <literal>Queue</literal> "myQueue" would be registered under JNDI name
"jms/queue" and JMS <literal>Topic</literal>
destination "myTopic" would be registered under JNDI name "jms/topic". (All
resources will be bound under "java:comp/env").
+ On declaration of <literal>PooledConnectionFactory</literal> optional
maxPoolSize and connectionTimeout are set to
+ 20 and 60000 milliseconds accordingly.
</para>
<para>
The client application can find the resources declared in Tomcat
context.xml using the code below:
@@ -129,8 +155,38 @@
</example>
<note>
<para>
- Note, that only BURL-based destinations can be registered in external
JNDI container. Address based destinations cannot be used.
+ In order to support backward compatibility
<literal>AMQConnectionFactory</literal> continues to implement
+ <ulink
url="&oracleJdkDocUrl;javax/naming/spi/ObjectFactory.html">javax.naming.spi.ObjectFactory</ulink>
+ and can be used to instantiate JNDI resources from
+ <ulink
url="&oracleJdkDocUrl;javax/naming/Reference.html">javax.naming.Reference</ulink>s.
+ However, its method <literal>getObjectInstance</literal> is marked as
<literal>Deprecated</literal> and will be
+ removed in future version of client. For backward compatibility, Qpid
JNDI resources can be declared using fully
+ qualified class names as addresses. That will became unsupported in
future version as well.
+ An example of Tomcat context.xml with declarations of JNDI resources
using deprecated factory and addresses is provided below.
+ <example>
+ <title>An example of Tomcat context.xml declaring Qpid JNDI resources
using deprecated <literal>ObjectFactory</literal> and deprecated
addresses</title>
+ <programlisting language="xml"><![CDATA[
+<?xml version='1.0' encoding='utf-8'?>
+<!DOCTYPE xml>
+<Context>
+
+ <Resource name="jms/queue" auth="Container"
+ type="org.apache.qpid.client.AMQQueue"
+ factory="org.apache.qpid.client.AMQConnectionFactory"
+
org.apache.qpid.client.AMQQueue="direct://amq.direct//myDurableQueue?durable='true'"/>
+
+ <Resource name="jms/topic" auth="Container"
+ type="org.apache.qpid.client.AMQTopic"
+ factory="org.apache.qpid.client.AMQConnectionFactory"
+
org.apache.qpid.client.AMQTopic="topic://amq.topic//myTopic?routingkey='myTopic'"/>
+
+ <Resource name="jms/connectionFactory" auth="Container"
+ type="org.apache.qpid.client.AMQConnectionFactory"
+ factory="org.apache.qpid.client.AMQConnectionFactory"
+
org.apache.qpid.client.AMQConnectionFactory="amqp://guest:guest@clientid/?brokerlist='localhost:5672'"/>
+
+</Context>]]></programlisting>
+ </example>
</para>
</note>
-
</appendix>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]