ARTEMIS-1516 - Ensure JNDI via Tomcat Resource works

Apply fix so that when using JNDI via tomcat resource it works. 
Replace original extract of JNDIStorable taken from Qpid, and use ActiveMQ5's as fits better to address this issue. (which primary use case is users migrating from 5.x)
Refactored ActiveMQConnectionFactory to externalise and turn into reference by StringRefAddr's instead of custom RefAddr which isnt standard.
Refactored ActiveMQDestinations similar
Refactored ActiveMQDestination to remove redundent and duplicated name field and ensured getters still behave the same
This commit is contained in:
Michael André Pearce 2017-11-04 02:26:39 +00:00 committed by Clebert Suconic
parent 03ed49e6e9
commit 3ef98044f8
32 changed files with 953 additions and 201 deletions

View File

@ -19,12 +19,14 @@ package org.apache.activemq.artemis.utils.uri;
import java.beans.PropertyDescriptor; import java.beans.PropertyDescriptor;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.net.URI; import java.net.URI;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties;
import java.util.Set; import java.util.Set;
import org.apache.commons.beanutils.BeanUtilsBean; import org.apache.commons.beanutils.BeanUtilsBean;
@ -69,6 +71,38 @@ public class BeanSupport {
return obj; return obj;
} }
public static <P> P setProperties(P bean, Properties properties)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
synchronized (beanUtils) {
PropertyDescriptor[] descriptors = beanUtils.getPropertyUtils().getPropertyDescriptors(bean);
for (PropertyDescriptor descriptor : descriptors) {
if (descriptor.getReadMethod() != null && isWriteable(descriptor, null)) {
String value = properties.getProperty(descriptor.getName());
if (value != null) {
beanUtils.setProperty(bean, descriptor.getName(), value);
}
}
}
}
return bean;
}
public static <P> Properties getProperties(P bean, Properties properties)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
synchronized (beanUtils) {
PropertyDescriptor[] descriptors = beanUtils.getPropertyUtils().getPropertyDescriptors(bean);
for (PropertyDescriptor descriptor : descriptors) {
if (descriptor.getReadMethod() != null && isWriteable(descriptor, null)) {
String value = beanUtils.getProperty(bean, descriptor.getName());
if (value != null) {
properties.put(descriptor.getName(), value);
}
}
}
}
return properties;
}
public static void setData(URI uri, public static void setData(URI uri,
HashMap<String, Object> properties, HashMap<String, Object> properties,
Set<String> allowableProperties, Set<String> allowableProperties,

View File

@ -30,17 +30,17 @@ import javax.jms.XAConnectionFactory;
import javax.jms.XAJMSContext; import javax.jms.XAJMSContext;
import javax.jms.XAQueueConnection; import javax.jms.XAQueueConnection;
import javax.jms.XATopicConnection; import javax.jms.XATopicConnection;
import javax.naming.NamingException; import javax.naming.Context;
import javax.naming.Reference;
import javax.naming.Referenceable;
import java.io.Externalizable; import java.io.Externalizable;
import java.io.IOException; import java.io.IOException;
import java.io.InvalidObjectException; import java.io.InvalidObjectException;
import java.io.ObjectInput; import java.io.ObjectInput;
import java.io.ObjectOutput; import java.io.ObjectOutput;
import java.lang.reflect.InvocationTargetException;
import java.net.URI; import java.net.URI;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.util.Properties;
import org.apache.activemq.artemis.api.core.DiscoveryGroupConfiguration; import org.apache.activemq.artemis.api.core.DiscoveryGroupConfiguration;
import org.apache.activemq.artemis.api.core.TransportConfiguration; import org.apache.activemq.artemis.api.core.TransportConfiguration;
@ -51,18 +51,18 @@ import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.api.jms.ActiveMQJMSConstants; import org.apache.activemq.artemis.api.jms.ActiveMQJMSConstants;
import org.apache.activemq.artemis.api.jms.JMSFactoryType; import org.apache.activemq.artemis.api.jms.JMSFactoryType;
import org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl; import org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl;
import org.apache.activemq.artemis.jms.referenceable.ConnectionFactoryObjectFactory; import org.apache.activemq.artemis.jndi.JNDIStorable;
import org.apache.activemq.artemis.jms.referenceable.SerializableObjectRefAddr;
import org.apache.activemq.artemis.spi.core.remoting.ClientProtocolManagerFactory; import org.apache.activemq.artemis.spi.core.remoting.ClientProtocolManagerFactory;
import org.apache.activemq.artemis.uri.ConnectionFactoryParser; import org.apache.activemq.artemis.uri.ConnectionFactoryParser;
import org.apache.activemq.artemis.uri.ServerLocatorParser; import org.apache.activemq.artemis.uri.ServerLocatorParser;
import org.apache.activemq.artemis.utils.ClassloadingUtil; import org.apache.activemq.artemis.utils.ClassloadingUtil;
import org.apache.activemq.artemis.utils.uri.BeanSupport;
/** /**
* <p>ActiveMQ Artemis implementation of a JMS ConnectionFactory.</p> * <p>ActiveMQ Artemis implementation of a JMS ConnectionFactory.</p>
* <p>This connection factory will use defaults defined by {@link DefaultConnectionProperties}. * <p>This connection factory will use defaults defined by {@link DefaultConnectionProperties}.
*/ */
public class ActiveMQConnectionFactory implements ConnectionFactoryOptions, Externalizable, Referenceable, ConnectionFactory, XAConnectionFactory, AutoCloseable { public class ActiveMQConnectionFactory extends JNDIStorable implements ConnectionFactoryOptions, Externalizable, ConnectionFactory, XAConnectionFactory, AutoCloseable {
private static final long serialVersionUID = -7554006056207377105L; private static final long serialVersionUID = -7554006056207377105L;
@ -206,10 +206,14 @@ public class ActiveMQConnectionFactory implements ConnectionFactoryOptions, Exte
this(DefaultConnectionProperties.DEFAULT_BROKER_URL); this(DefaultConnectionProperties.DEFAULT_BROKER_URL);
} }
public ActiveMQConnectionFactory(String url) { public ActiveMQConnectionFactory(String brokerURL) {
setBrokerURL(brokerURL);
}
private void setBrokerURL(String brokerURL) {
ConnectionFactoryParser cfParser = new ConnectionFactoryParser(); ConnectionFactoryParser cfParser = new ConnectionFactoryParser();
try { try {
URI uri = cfParser.expandURI(url); URI uri = cfParser.expandURI(brokerURL);
serverLocator = ServerLocatorImpl.newLocator(uri); serverLocator = ServerLocatorImpl.newLocator(uri);
cfParser.populateObject(uri, this); cfParser.populateObject(uri, this);
} catch (Exception e) { } catch (Exception e) {
@ -380,8 +384,36 @@ public class ActiveMQConnectionFactory implements ConnectionFactoryOptions, Exte
} }
@Override @Override
public Reference getReference() throws NamingException { protected void buildFromProperties(Properties props) {
return new Reference(this.getClass().getCanonicalName(), new SerializableObjectRefAddr("ActiveMQ-CF", this), ConnectionFactoryObjectFactory.class.getCanonicalName(), null); String url = props.getProperty(Context.PROVIDER_URL);
if (url == null || url.isEmpty()) {
url = props.getProperty("brokerURL");
}
if (url != null && url.length() > 0) {
setBrokerURL(url);
}
if (url == null || url.isEmpty()) {
throw new IllegalArgumentException(Context.PROVIDER_URL + " or " + "brokerURL is required");
}
try {
BeanSupport.setProperties(this, props);
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
@Override
protected void populateProperties(Properties props) {
try {
URI uri = toURI();
if (uri != null) {
props.put(Context.PROVIDER_URL, uri.toASCIIString());
props.put("brokerURL", uri.toASCIIString());
}
BeanSupport.getProperties(this, props);
} catch (IOException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
throw new RuntimeException(e);
}
} }
public boolean isHA() { public boolean isHA() {

View File

@ -19,21 +19,18 @@ package org.apache.activemq.artemis.jms.client;
import javax.jms.Destination; import javax.jms.Destination;
import javax.jms.JMSException; import javax.jms.JMSException;
import javax.jms.JMSRuntimeException; import javax.jms.JMSRuntimeException;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import java.io.Serializable; import java.io.Serializable;
import java.util.Properties;
import java.util.UUID; import java.util.UUID;
import org.apache.activemq.artemis.api.core.Pair; import org.apache.activemq.artemis.api.core.Pair;
import org.apache.activemq.artemis.api.core.SimpleString; import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.jms.referenceable.DestinationObjectFactory; import org.apache.activemq.artemis.jndi.JNDIStorable;
import org.apache.activemq.artemis.jms.referenceable.SerializableObjectRefAddr;
/** /**
* ActiveMQ Artemis implementation of a JMS Destination. * ActiveMQ Artemis implementation of a JMS Destination.
*/ */
public class ActiveMQDestination implements Destination, Serializable, Referenceable { public class ActiveMQDestination extends JNDIStorable implements Destination, Serializable {
// Constants ----------------------------------------------------- // Constants -----------------------------------------------------
// Static -------------------------------------------------------- // Static --------------------------------------------------------
@ -78,27 +75,27 @@ public class ActiveMQDestination implements Destination, Serializable, Reference
case TEMP_TOPIC: case TEMP_TOPIC:
return new ActiveMQTopic(name, true); return new ActiveMQTopic(name, true);
case DESTINATION: case DESTINATION:
return new ActiveMQDestination(name, name, TYPE.DESTINATION, null); return new ActiveMQDestination(name, TYPE.DESTINATION, null);
default: default:
throw new IllegalArgumentException("Invalid default destination type: " + defaultType); throw new IllegalArgumentException("Invalid default destination type: " + defaultType);
} }
} }
public static Destination fromPrefixedName(final String address) { public static Destination fromPrefixedName(final String name) {
if (address.startsWith(ActiveMQDestination.QUEUE_QUALIFIED_PREFIX)) { if (name.startsWith(ActiveMQDestination.QUEUE_QUALIFIED_PREFIX)) {
String name = address.substring(ActiveMQDestination.QUEUE_QUALIFIED_PREFIX.length()); String address = name.substring(ActiveMQDestination.QUEUE_QUALIFIED_PREFIX.length());
return createQueue(name); return createQueue(address);
} else if (address.startsWith(ActiveMQDestination.TOPIC_QUALIFIED_PREFIX)) { } else if (name.startsWith(ActiveMQDestination.TOPIC_QUALIFIED_PREFIX)) {
String name = address.substring(ActiveMQDestination.TOPIC_QUALIFIED_PREFIX.length()); String address = name.substring(ActiveMQDestination.TOPIC_QUALIFIED_PREFIX.length());
return createTopic(name); return createTopic(address);
} else if (address.startsWith(ActiveMQDestination.TEMP_QUEUE_QUALIFED_PREFIX)) { } else if (name.startsWith(ActiveMQDestination.TEMP_QUEUE_QUALIFED_PREFIX)) {
String name = address.substring(ActiveMQDestination.TEMP_QUEUE_QUALIFED_PREFIX.length()); String address = name.substring(ActiveMQDestination.TEMP_QUEUE_QUALIFED_PREFIX.length());
return new ActiveMQTemporaryQueue(name, name, null); return new ActiveMQTemporaryQueue(address, null);
} else if (address.startsWith(ActiveMQDestination.TEMP_TOPIC_QUALIFED_PREFIX)) { } else if (name.startsWith(ActiveMQDestination.TEMP_TOPIC_QUALIFED_PREFIX)) {
String name = address.substring(ActiveMQDestination.TEMP_TOPIC_QUALIFED_PREFIX.length()); String address = name.substring(ActiveMQDestination.TEMP_TOPIC_QUALIFED_PREFIX.length());
return new ActiveMQTemporaryTopic(name, name, null); return new ActiveMQTemporaryTopic(address, null);
} else { } else {
return new ActiveMQDestination(address, address, TYPE.DESTINATION, null); return new ActiveMQDestination(name, TYPE.DESTINATION, null);
} }
} }
@ -191,58 +188,48 @@ public class ActiveMQDestination implements Destination, Serializable, Reference
return new SimpleString(TOPIC_QUALIFIED_PREFIX + name); return new SimpleString(TOPIC_QUALIFIED_PREFIX + name);
} }
public static ActiveMQQueue createQueue(final String name) { public static ActiveMQQueue createQueue(final String address) {
return new ActiveMQQueue(name); return new ActiveMQQueue(address);
} }
public static ActiveMQTopic createTopic(final String name) { public static ActiveMQTopic createTopic(final String address) {
return new ActiveMQTopic(name); return new ActiveMQTopic(address);
} }
public static ActiveMQTemporaryQueue createTemporaryQueue(final String name, final ActiveMQSession session) { public static ActiveMQTemporaryQueue createTemporaryQueue(final String address, final ActiveMQSession session) {
return new ActiveMQTemporaryQueue(name, name, session); return new ActiveMQTemporaryQueue(address, session);
} }
public static ActiveMQTemporaryQueue createTemporaryQueue(final String name) { public static ActiveMQTemporaryQueue createTemporaryQueue(final String address) {
return createTemporaryQueue(name, null); return createTemporaryQueue(address, null);
} }
public static ActiveMQTemporaryQueue createTemporaryQueue(final ActiveMQSession session) { public static ActiveMQTemporaryQueue createTemporaryQueue(final ActiveMQSession session) {
String name = UUID.randomUUID().toString(); String address = UUID.randomUUID().toString();
return createTemporaryQueue(name, session); return createTemporaryQueue(address, session);
} }
public static ActiveMQTemporaryTopic createTemporaryTopic(final ActiveMQSession session) { public static ActiveMQTemporaryTopic createTemporaryTopic(final ActiveMQSession session) {
String name = UUID.randomUUID().toString(); String address = UUID.randomUUID().toString();
return createTemporaryTopic(name, session); return createTemporaryTopic(address, session);
} }
public static ActiveMQTemporaryTopic createTemporaryTopic(String name, final ActiveMQSession session) { public static ActiveMQTemporaryTopic createTemporaryTopic(String address, final ActiveMQSession session) {
return new ActiveMQTemporaryTopic(name, name, session); return new ActiveMQTemporaryTopic(address, session);
} }
public static ActiveMQTemporaryTopic createTemporaryTopic(String name) { public static ActiveMQTemporaryTopic createTemporaryTopic(String address) {
return createTemporaryTopic(name, null); return createTemporaryTopic(address, null);
} }
// Attributes ---------------------------------------------------- // Attributes ----------------------------------------------------
/**
* The JMS name
*/
protected final String name;
/** /**
* The core address * The core address
*/ */
private final String address; private SimpleString simpleAddress;
/**
* SimpleString version of address
*/
private final SimpleString simpleAddress;
private final TYPE type; private final TYPE type;
@ -251,25 +238,34 @@ public class ActiveMQDestination implements Destination, Serializable, Reference
// Constructors -------------------------------------------------- // Constructors --------------------------------------------------
protected ActiveMQDestination(final String address, protected ActiveMQDestination(final String address,
final String name,
final TYPE type, final TYPE type,
final ActiveMQSession session) { final ActiveMQSession session) {
this.address = address; this.simpleAddress = SimpleString.toSimpleString(address);
this.name = name;
simpleAddress = new SimpleString(address);
this.type = type; this.type = type;
this.session = session; this.session = session;
} }
// Referenceable implementation --------------------------------------- protected ActiveMQDestination(final SimpleString address,
final TYPE type,
final ActiveMQSession session) {
this.simpleAddress = address;
@Override this.type = type;
public Reference getReference() throws NamingException {
return new Reference(this.getClass().getCanonicalName(), new SerializableObjectRefAddr("ActiveMQ-DEST", this), DestinationObjectFactory.class.getCanonicalName(), null); this.session = session;
}
public void setAddress(String address) {
setSimpleAddress(SimpleString.toSimpleString(address));
}
public void setSimpleAddress(SimpleString address) {
if (address == null) {
throw new IllegalArgumentException("address cannot be null");
}
this.simpleAddress = address;
} }
public void delete() throws JMSException { public void delete() throws JMSException {
@ -293,7 +289,7 @@ public class ActiveMQDestination implements Destination, Serializable, Reference
// Public -------------------------------------------------------- // Public --------------------------------------------------------
public String getAddress() { public String getAddress() {
return address; return simpleAddress.toString();
} }
public SimpleString getSimpleAddress() { public SimpleString getSimpleAddress() {
@ -301,7 +297,7 @@ public class ActiveMQDestination implements Destination, Serializable, Reference
} }
public String getName() { public String getName() {
return name; return simpleAddress.toString();
} }
public boolean isTemporary() { public boolean isTemporary() {
@ -324,12 +320,22 @@ public class ActiveMQDestination implements Destination, Serializable, Reference
ActiveMQDestination that = (ActiveMQDestination) o; ActiveMQDestination that = (ActiveMQDestination) o;
return address.equals(that.address); return simpleAddress.equals(that.simpleAddress);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return address.hashCode(); return simpleAddress.hashCode();
}
@Override
protected void buildFromProperties(Properties props) {
setAddress(props.getProperty("address"));
}
@Override
protected void populateProperties(Properties props) {
props.put("address", getAddress());
} }
// Package protected --------------------------------------------- // Package protected ---------------------------------------------

View File

@ -18,8 +18,6 @@ package org.apache.activemq.artemis.jms.client;
import javax.jms.Queue; import javax.jms.Queue;
import org.apache.activemq.artemis.api.core.SimpleString;
/** /**
* ActiveMQ Artemis implementation of a JMS Queue. * ActiveMQ Artemis implementation of a JMS Queue.
* <br> * <br>
@ -32,35 +30,30 @@ public class ActiveMQQueue extends ActiveMQDestination implements Queue {
// Static -------------------------------------------------------- // Static --------------------------------------------------------
public static SimpleString createAddressFromName(final String name) {
return new SimpleString(name);
}
// Attributes ---------------------------------------------------- // Attributes ----------------------------------------------------
// Constructors -------------------------------------------------- // Constructors --------------------------------------------------
public ActiveMQQueue() {
public ActiveMQQueue(final String name) { this(null);
super(name, name, TYPE.QUEUE, null);
} }
public ActiveMQQueue(final String name, boolean temporary) { public ActiveMQQueue(final String address) {
super(name, name, temporary ? TYPE.TEMP_QUEUE : TYPE.QUEUE, null); super(address, TYPE.QUEUE, null);
}
public ActiveMQQueue(final String address, boolean temporary) {
super(address, temporary ? TYPE.TEMP_QUEUE : TYPE.QUEUE, null);
} }
/** /**
* @param address * @param address
* @param name
* @param temporary * @param temporary
* @param session * @param session
*/ */
public ActiveMQQueue(String address, String name, boolean temporary, ActiveMQSession session) { public ActiveMQQueue(String address, boolean temporary, ActiveMQSession session) {
super(address, name, temporary ? TYPE.TEMP_QUEUE : TYPE.QUEUE, session); super(address, temporary ? TYPE.TEMP_QUEUE : TYPE.QUEUE, session);
} }
public ActiveMQQueue(final String address, final String name) {
super(address, name, TYPE.QUEUE, null);
}
// Queue implementation ------------------------------------------ // Queue implementation ------------------------------------------
@ -68,12 +61,12 @@ public class ActiveMQQueue extends ActiveMQDestination implements Queue {
@Override @Override
public String getQueueName() { public String getQueueName() {
return name; return getAddress();
} }
@Override @Override
public String toString() { public String toString() {
return "ActiveMQQueue[" + name + "]"; return "ActiveMQQueue[" + getAddress() + "]";
} }
@Override @Override

View File

@ -37,19 +37,21 @@ public class ActiveMQTemporaryQueue extends ActiveMQQueue implements TemporaryQu
// TemporaryQueue implementation ------------------------------------------ // TemporaryQueue implementation ------------------------------------------
// Public -------------------------------------------------------- // Public --------------------------------------------------------
public ActiveMQTemporaryQueue() {
this(null, null);
}
/** /**
* @param address * @param address
* @param name
* @param session * @param session
*/ */
public ActiveMQTemporaryQueue(String address, String name, ActiveMQSession session) { public ActiveMQTemporaryQueue(String address, ActiveMQSession session) {
super(address, name, true, session); super(address, true, session);
} }
@Override @Override
public String toString() { public String toString() {
return "ActiveMQTemporaryQueue[" + name + "]"; return "ActiveMQTemporaryQueue[" + getAddress() + "]";
} }
@Override @Override

View File

@ -29,9 +29,12 @@ public class ActiveMQTemporaryTopic extends ActiveMQTopic implements TemporaryTo
// Static -------------------------------------------------------- // Static --------------------------------------------------------
// Constructors -------------------------------------------------- // Constructors --------------------------------------------------
public ActiveMQTemporaryTopic() {
this(null, null);
}
protected ActiveMQTemporaryTopic(final String address, final String name, final ActiveMQSession session) { public ActiveMQTemporaryTopic(final String address, final ActiveMQSession session) {
super(address, name, true, session); super(address, true, session);
} }
// Public -------------------------------------------------------- // Public --------------------------------------------------------

View File

@ -18,8 +18,6 @@ package org.apache.activemq.artemis.jms.client;
import javax.jms.Topic; import javax.jms.Topic;
import org.apache.activemq.artemis.api.core.SimpleString;
/** /**
* ActiveMQ Artemis implementation of a JMS Topic. * ActiveMQ Artemis implementation of a JMS Topic.
* <br> * <br>
@ -31,44 +29,42 @@ public class ActiveMQTopic extends ActiveMQDestination implements Topic {
private static final long serialVersionUID = 7873614001276404156L; private static final long serialVersionUID = 7873614001276404156L;
// Static -------------------------------------------------------- // Static --------------------------------------------------------
public static SimpleString createAddressFromName(final String name) {
return new SimpleString(name);
}
// Attributes ---------------------------------------------------- // Attributes ----------------------------------------------------
// Constructors -------------------------------------------------- // Constructors --------------------------------------------------
public ActiveMQTopic() {
public ActiveMQTopic(final String name) { this(null);
this(name, false);
} }
public ActiveMQTopic(final String name, boolean temporary) { public ActiveMQTopic(final String address) {
super(name, name, TYPE.TOPIC, null); this(address, false);
}
public ActiveMQTopic(final String address, boolean temporary) {
super(address, TYPE.TOPIC, null);
} }
/** /**
* @param address * @param address
* @param name
* @param temporary * @param temporary
* @param session * @param session
*/ */
protected ActiveMQTopic(String address, String name, boolean temporary, ActiveMQSession session) { protected ActiveMQTopic(String address, boolean temporary, ActiveMQSession session) {
super(address, name, temporary ? TYPE.TEMP_TOPIC : TYPE.TOPIC, session); super(address, temporary ? TYPE.TEMP_TOPIC : TYPE.TOPIC, session);
} }
// Topic implementation ------------------------------------------ // Topic implementation ------------------------------------------
@Override @Override
public String getTopicName() { public String getTopicName() {
return name; return getName();
} }
// Public -------------------------------------------------------- // Public --------------------------------------------------------
@Override @Override
public String toString() { public String toString() {
return "ActiveMQTopic[" + name + "]"; return "ActiveMQTopic[" + getName() + "]";
} }
@Override @Override

View File

@ -19,14 +19,13 @@ package org.apache.activemq.artemis.jndi;
import javax.naming.Context; import javax.naming.Context;
import javax.naming.Name; import javax.naming.Name;
import javax.naming.NamingException; import javax.naming.NamingException;
import javax.naming.RefAddr;
import javax.naming.Reference; import javax.naming.Reference;
import javax.naming.StringRefAddr; import javax.naming.StringRefAddr;
import javax.naming.spi.ObjectFactory; import javax.naming.spi.ObjectFactory;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Map; import java.util.Properties;
/** /**
* Converts objects implementing JNDIStorable into a property fields so they can be * Converts objects implementing JNDIStorable into a property fields so they can be
@ -63,12 +62,7 @@ public class JNDIReferenceFactory implements ObjectFactory {
Class<?> theClass = loadClass(this, reference.getClassName()); Class<?> theClass = loadClass(this, reference.getClassName());
if (JNDIStorable.class.isAssignableFrom(theClass)) { if (JNDIStorable.class.isAssignableFrom(theClass)) {
JNDIStorable store = (JNDIStorable) theClass.newInstance(); JNDIStorable store = (JNDIStorable) theClass.newInstance();
Map<String, String> properties = new HashMap<>(); store.setProperties(getProperties(reference));
for (Enumeration<RefAddr> iter = reference.getAll(); iter.hasMoreElements();) {
StringRefAddr addr = (StringRefAddr) iter.nextElement();
properties.put(addr.getType(), (addr.getContent() == null) ? "" : addr.getContent().toString());
}
store.setProperties(properties);
result = store; result = store;
} }
} else { } else {
@ -77,6 +71,15 @@ public class JNDIReferenceFactory implements ObjectFactory {
return result; return result;
} }
public static Properties getProperties(Reference reference) {
Properties properties = new Properties();
for (Enumeration iter = reference.getAll(); iter.hasMoreElements();) {
StringRefAddr addr = (StringRefAddr)iter.nextElement();
properties.put(addr.getType(), (addr.getContent() == null) ? "" : addr.getContent());
}
return properties;
}
/** /**
* Create a Reference instance from a JNDIStorable object * Create a Reference instance from a JNDIStorable object
* *
@ -92,10 +95,10 @@ public class JNDIReferenceFactory implements ObjectFactory {
public static Reference createReference(String instanceClassName, JNDIStorable po) throws NamingException { public static Reference createReference(String instanceClassName, JNDIStorable po) throws NamingException {
Reference result = new Reference(instanceClassName, JNDIReferenceFactory.class.getName(), null); Reference result = new Reference(instanceClassName, JNDIReferenceFactory.class.getName(), null);
try { try {
Map<String, String> props = po.getProperties(); Properties props = po.getProperties();
for (Map.Entry<String, String> entry : props.entrySet()) { for (Enumeration iter = props.propertyNames(); iter.hasMoreElements();) {
StringRefAddr addr = new StringRefAddr(entry.getKey(), entry.getValue()); String key = (String)iter.nextElement();
result.add(addr); result.add(new StringRefAddr(key, props.getProperty(key)));
} }
} catch (Exception e) { } catch (Exception e) {
throw new NamingException(e.getMessage()); throw new NamingException(e.getMessage());

View File

@ -16,32 +16,27 @@
*/ */
package org.apache.activemq.artemis.jndi; package org.apache.activemq.artemis.jndi;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import java.io.Externalizable;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectInput; import java.io.ObjectInput;
import java.io.ObjectOutput; import java.io.ObjectOutput;
import java.util.LinkedHashMap; import java.util.Properties;
import java.util.Map;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;
/** /**
* Facilitates objects to be stored in JNDI as properties * Facilitates objects to be stored in JNDI as properties
*
* @since 1.0
*/ */
public abstract class JNDIStorable implements Referenceable, Externalizable { public abstract class JNDIStorable implements Referenceable {
/** /**
* Set the properties that will represent the instance in JNDI * Set the properties that will represent the instance in JNDI
* *
* @param props * @param props
* The properties to use when building the new isntance. * The properties to use when building the new isntance.
*
* @return a new, unmodifiable, map containing any unused properties, or empty if none were.
*/ */
protected abstract Map<String, String> buildFromProperties(Map<String, String> props); protected abstract void buildFromProperties(Properties props);
/** /**
* Initialize the instance from properties stored in JNDI * Initialize the instance from properties stored in JNDI
@ -49,7 +44,7 @@ public abstract class JNDIStorable implements Referenceable, Externalizable {
* @param props * @param props
* The properties to use when initializing the new instance. * The properties to use when initializing the new instance.
*/ */
protected abstract void populateProperties(Map<String, String> props); protected abstract void populateProperties(Properties props);
/** /**
* set the properties for this instance as retrieved from JNDI * set the properties for this instance as retrieved from JNDI
@ -59,8 +54,8 @@ public abstract class JNDIStorable implements Referenceable, Externalizable {
* *
* @return a new, unmodifiable, map containing any unused properties, or empty if none were. * @return a new, unmodifiable, map containing any unused properties, or empty if none were.
*/ */
public synchronized Map<String, String> setProperties(Map<String, String> props) { synchronized void setProperties(Properties props) {
return buildFromProperties(props); buildFromProperties(props);
} }
/** /**
@ -68,8 +63,8 @@ public abstract class JNDIStorable implements Referenceable, Externalizable {
* *
* @return the properties * @return the properties
*/ */
public synchronized Map<String, String> getProperties() { synchronized Properties getProperties() {
Map<String, String> properties = new LinkedHashMap<>(); Properties properties = new Properties();
populateProperties(properties); populateProperties(properties);
return properties; return properties;
} }
@ -87,30 +82,29 @@ public abstract class JNDIStorable implements Referenceable, Externalizable {
} }
/** /**
* @see Externalizable#readExternal(ObjectInput) * Method for class's implementing externalizable to delegate to if not custom implementing.
*
* @param in
* @throws IOException
* @throws ClassNotFoundException
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
*/ */
@SuppressWarnings("unchecked") public void readObject(ObjectInput in) throws IOException, ClassNotFoundException {
@Override Properties props = (Properties)in.readObject();
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
Map<String, String> props = (Map<String, String>) in.readObject();
if (props != null) { if (props != null) {
setProperties(props); setProperties(props);
} }
} }
/** /**
* @see Externalizable#writeExternal(ObjectOutput) * Method for class's implementing externalizable to delegate to if not custom implementing.
*
* @param out
* @throws IOException
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
*/ */
@Override public void writeObject(ObjectOutput out) throws IOException {
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(getProperties()); out.writeObject(getProperties());
} }
protected String getProperty(Map<String, String> map, String key, String defaultValue) { }
String value = map.get(key);
if (value != null) {
return value;
}
return defaultValue;
}
}

View File

@ -19,6 +19,7 @@ package org.apache.activemq.artemis.protocol.amqp.converter.jms;
import javax.jms.JMSException; import javax.jms.JMSException;
import javax.jms.Queue; import javax.jms.Queue;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.jms.client.ActiveMQDestination; import org.apache.activemq.artemis.jms.client.ActiveMQDestination;
/** /**
@ -27,8 +28,12 @@ import org.apache.activemq.artemis.jms.client.ActiveMQDestination;
*/ */
public class ServerDestination extends ActiveMQDestination implements Queue { public class ServerDestination extends ActiveMQDestination implements Queue {
public ServerDestination(String name) { public ServerDestination(String address) {
super(name, name, TYPE.DESTINATION, null); super(address, TYPE.DESTINATION, null);
}
public ServerDestination(SimpleString address) {
super(address, TYPE.DESTINATION, null);
} }
@Override @Override

View File

@ -139,7 +139,7 @@ public class ServerJMSMessage implements Message {
public final Destination getJMSReplyTo() throws JMSException { public final Destination getJMSReplyTo() throws JMSException {
SimpleString reply = MessageUtil.getJMSReplyTo(message); SimpleString reply = MessageUtil.getJMSReplyTo(message);
if (reply != null) { if (reply != null) {
return new ServerDestination(reply.toString()); return new ServerDestination(reply);
} else { } else {
return null; return null;
} }
@ -148,7 +148,6 @@ public class ServerJMSMessage implements Message {
@Override @Override
public final void setJMSReplyTo(Destination replyTo) throws JMSException { public final void setJMSReplyTo(Destination replyTo) throws JMSException {
MessageUtil.setJMSReplyTo(message, replyTo == null ? null : ((ActiveMQDestination) replyTo).getSimpleAddress()); MessageUtil.setJMSReplyTo(message, replyTo == null ? null : ((ActiveMQDestination) replyTo).getSimpleAddress());
} }
@Override @Override
@ -158,7 +157,7 @@ public class ServerJMSMessage implements Message {
if (sdest == null) { if (sdest == null) {
return null; return null;
} else { } else {
return new ServerDestination(sdest.toString()); return new ServerDestination(sdest);
} }
} }

View File

@ -0,0 +1,25 @@
/*
* 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.activemq.artemis.jms.referenceable;
/**
* Done for back compatibility with the package/class move.
*
* Should be removed on next major version change.
*/
public class ConnectionFactoryObjectFactory extends org.apache.activemq.artemis.ra.referenceable.ActiveMQRAConnectionFactoryObjectFactory {
}

View File

@ -6,7 +6,7 @@
* (the "License"); you may not use this file except in compliance with * (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
@ -16,29 +16,16 @@
*/ */
package org.apache.activemq.artemis.jms.referenceable; package org.apache.activemq.artemis.jms.referenceable;
import javax.naming.Context; import javax.naming.NamingException;
import javax.naming.Name;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;
import java.util.Hashtable;
/** /**
* A DestinationObjectFactory. * Done for back compatibility with the package/class move.
* *
* Given a Reference - reconstructs an ActiveMQDestination * Should be removed on next major version change.
*/ */
public class DestinationObjectFactory implements ObjectFactory { public class SerializableObjectRefAddr extends org.apache.activemq.artemis.ra.referenceable.SerializableObjectRefAddr {
@Override public SerializableObjectRefAddr(final String type, final Object content) throws NamingException {
public Object getObjectInstance(final Object ref, super(type, content);
final Name name,
final Context ctx,
final Hashtable<?, ?> props) throws Exception {
Reference r = (Reference) ref;
byte[] bytes = (byte[]) r.get("ActiveMQ-DEST").getContent();
// Deserialize
return SerializableObjectRefAddr.deserialize(bytes);
} }
} }

View File

@ -35,8 +35,8 @@ import javax.resource.ResourceException;
import javax.resource.spi.ConnectionManager; import javax.resource.spi.ConnectionManager;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory; import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.jms.referenceable.ConnectionFactoryObjectFactory; import org.apache.activemq.artemis.ra.referenceable.ActiveMQRAConnectionFactoryObjectFactory;
import org.apache.activemq.artemis.jms.referenceable.SerializableObjectRefAddr; import org.apache.activemq.artemis.ra.referenceable.SerializableObjectRefAddr;
/** /**
* The connection factory * The connection factory
@ -118,7 +118,7 @@ public class ActiveMQRAConnectionFactoryImpl implements ActiveMQRAConnectionFact
} }
if (reference == null) { if (reference == null) {
try { try {
reference = new Reference(this.getClass().getCanonicalName(), new SerializableObjectRefAddr("ActiveMQ-CF", this), ConnectionFactoryObjectFactory.class.getCanonicalName(), null); reference = new Reference(this.getClass().getCanonicalName(), new SerializableObjectRefAddr("ActiveMQ-CF", this), ActiveMQRAConnectionFactoryObjectFactory.class.getCanonicalName(), null);
} catch (NamingException e) { } catch (NamingException e) {
ActiveMQRALogger.LOGGER.errorCreatingReference(e); ActiveMQRALogger.LOGGER.errorCreatingReference(e);
} }

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.activemq.artemis.jms.referenceable; package org.apache.activemq.artemis.ra.referenceable;
import javax.naming.Context; import javax.naming.Context;
import javax.naming.Name; import javax.naming.Name;
@ -27,7 +27,7 @@ import java.util.Hashtable;
* *
* Given a reference - reconstructs an ActiveMQRAConnectionFactory * Given a reference - reconstructs an ActiveMQRAConnectionFactory
*/ */
public class ConnectionFactoryObjectFactory implements ObjectFactory { public class ActiveMQRAConnectionFactoryObjectFactory implements ObjectFactory {
@Override @Override
public Object getObjectInstance(final Object ref, public Object getObjectInstance(final Object ref,

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.activemq.artemis.jms.referenceable; package org.apache.activemq.artemis.ra.referenceable;
import javax.naming.NamingException; import javax.naming.NamingException;
import javax.naming.RefAddr; import javax.naming.RefAddr;

View File

@ -56,6 +56,7 @@
* [REST Interface](rest.md) * [REST Interface](rest.md)
* [Embedding Apache ActiveMQ Artemis](embedding-activemq.md) * [Embedding Apache ActiveMQ Artemis](embedding-activemq.md)
* [Apache Karaf](karaf.md) * [Apache Karaf](karaf.md)
* [Apache Tomcat](tomcat.md)
* [Spring Integration](spring-integration.md) * [Spring Integration](spring-integration.md)
* [CDI Integration](cdi-integration.md) * [CDI Integration](cdi-integration.md)
* [Intercepting Operations](intercepting-operations.md) * [Intercepting Operations](intercepting-operations.md)

View File

@ -0,0 +1,39 @@
# Apache ActiveMQ Artemis - Apache Tomcat Support
##Apache Tomcat resource context client configuration
Apache ActiveMQ Artemis provides support for configuring the client, in the tomcat resource context.xml of Tomcat container.
This is very similar to the way this is done in ActiveMQ 5.x so anyone migrating should find this familiar.
Please note though the connection url and properties that can be set for ActiveMQ Artemis are different please see [Migration Documentation](https://activemq.apache.org/artemis/migration/)
#### Example of Connection Factory
````
<Context>
...
<Resource name="jms/ConnectionFactory" auth="Container" type="org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory" description="JMS Connection Factory"
factory="org.apache.activemq.artemis.jndi.JNDIReferenceFactory" brokerURL="tcp://localhost:61616" />
...
</Context>
````
#### Example of Destination (Queue and Topic)
````
<Context>
...
<Resource name="jms/ExampleQueue" auth="Container" type="org.apache.activemq.artemis.jms.client.ActiveMQQueue" description="JMS Queue"
factory="org.apache.activemq.artemis.jndi.JNDIReferenceFactory" address="ExampleQueue" />
...
<Resource name="jms/ExampleTopic" auth="Container" type="org.apache.activemq.artemis.jms.client.ActiveMQTopic" description="JMS Topic"
factory="org.apache.activemq.artemis.jndi.JNDIReferenceFactory" address="ExampleTopic" />
...
</Context>
````
#### Example Tomcat App
A sample tomcat app with the container context configured as an example can be seen here:
/examples/features/sub-modules/tomcat

View File

@ -50,7 +50,8 @@ under the License.
<id>release</id> <id>release</id>
<modules> <modules>
<module>artemis-ra-rar</module> <module>artemis-ra-rar</module>
<module>inter-broker-bridge</module> <module>inter-broker-bridge</module>
<module>tomcat</module>
</modules> </modules>
</profile> </profile>
</profiles> </profiles>

View File

@ -0,0 +1,21 @@
# Apache ActiveMQ Artemis Tomcat Integration JNDI Resources Sample
This is a Sample Tomcat application showing JNDI resource in tomcat context.xml for ConnectionFactory
and Destination for Apache ActiveMQ Artemis.
The sample context.xml used by the tomcat in this example can be found under:
/src/tomcat7-maven-plugin/resources/context.xml
To run
start Apache ActiveMQ Artemis on port 61616
then
mvn clean install tomcat7:exec-war
then to send message
http://localhost:8080/tomcat-sample/send
this will cause a "hello world" message to send, and the consumer should consume and output it to sysout.

View File

@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.activemq.examples.modules</groupId>
<artifactId>broker-modules</artifactId>
<version>2.5.0-SNAPSHOT</version>
</parent>
<artifactId>artemis-tomcat-jndi-resources-sample</artifactId>
<packaging>war</packaging>
<name>Artemis Tomcat JNDI Resources Example</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<projectBaseUri>${project.baseUri}</projectBaseUri>
<java.version>1.6</java.version>
<servlet-api.version>3.0-alpha-1</servlet-api.version>
</properties>
<dependencies>
<!-- Spring Dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-jms-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${servlet-api.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<contextFile>${project.basedir}\src\tomcat7-maven-plugin\resources\context.xml</contextFile>
</configuration>
<executions>
<execution>
<id>tomcat-war-exec</id>
<goals>
<goal>exec-war</goal>
</goals>
<phase>package</phase>
<configuration>
<warRunDependencies>
<warRunDependency>
<dependency>
<groupId>org.apache.activemq.examples.modules</groupId>
<artifactId>artemis-tomcat-jndi-resources-sample</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
</warRunDependency>
</warRunDependencies>
</configuration>
</execution>
</executions>
<!--<configuration>-->
<!--<port>9090</port>-->
<!--<path>/</path>-->
<!--</configuration>-->
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,48 @@
/**
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.activemq.artemis.example.tomcat.sample;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SendMessageController {
@Autowired
private JmsTemplate jmsTemplate;
@RequestMapping("/send")
public @ResponseBody String send(@RequestParam(value="text", defaultValue="hello world") final String text) {
jmsTemplate.send(new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(text);
}
});
return "sent: " + text;
}
}

View File

@ -0,0 +1,28 @@
/**
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.activemq.artemis.example.tomcat.sample;
import javax.jms.Message;
import javax.jms.MessageListener;
public class SystemOutPrintLnMessageListener implements MessageListener {
@Override
public void onMessage(Message message) {
System.out.println(message);
}
}

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed 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.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee.xsd">
<jee:jndi-lookup id="connectionFactory" jndi-name="java:comp/env/jms/connectionFactory" />
<jee:jndi-lookup id="InputQueue" jndi-name="java:comp/env/jms/InputQueue" />
<bean id="InputListener" class="org.apache.activemq.artemis.example.tomcat.sample.SystemOutPrintLnMessageListener" />
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate" >
<property name="connectionFactory">
<bean class="org.springframework.jms.connection.CachingConnectionFactory" >
<property name="targetConnectionFactory" ref="connectionFactory" />
</bean>
</property>
<property name="defaultDestination" ref="InputQueue" />
</bean>
<bean id="messageListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="InputQueue" />
<property name="messageListener" ref="InputListener" />
</bean>
</beans>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed 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.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="org.apache.activemq.artemis.example.tomcat.sample" />
<mvc:annotation-driven />
</beans>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed 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.
-->
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/application-context.xml</param-value>
</context-param>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

View File

@ -0,0 +1,28 @@
<!--
Licensed 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.
-->
<Context>
<Resource name="jms/connectionFactory"
auth="Container"
type="org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory"
description="JMS Connection Factory"
factory="org.apache.activemq.artemis.jndi.JNDIReferenceFactory"
brokerURL="(tcp://localhost:61616)?ha=true&amp;useKQueue=false&amp;useEpoll=false"/>
<Resource name="jms/InputQueue"
auth="Container"
type="org.apache.activemq.artemis.jms.client.ActiveMQQueue"
factory="org.apache.activemq.artemis.jndi.JNDIReferenceFactory"
address="InputQueue"/>
</Context>

View File

@ -25,6 +25,7 @@ import javax.jms.Session;
import javax.jms.TextMessage; import javax.jms.TextMessage;
import javax.naming.Reference; import javax.naming.Reference;
import javax.naming.Referenceable; import javax.naming.Referenceable;
import javax.naming.spi.ObjectFactory;
import java.io.Serializable; import java.io.Serializable;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory; import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
@ -32,8 +33,6 @@ import org.apache.activemq.artemis.jms.client.ActiveMQDestination;
import org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory; import org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory;
import org.apache.activemq.artemis.jms.client.ActiveMQQueue; import org.apache.activemq.artemis.jms.client.ActiveMQQueue;
import org.apache.activemq.artemis.jms.client.ActiveMQTopic; import org.apache.activemq.artemis.jms.client.ActiveMQTopic;
import org.apache.activemq.artemis.jms.referenceable.ConnectionFactoryObjectFactory;
import org.apache.activemq.artemis.jms.referenceable.DestinationObjectFactory;
import org.apache.activemq.artemis.jms.tests.util.ProxyAssertSupport; import org.apache.activemq.artemis.jms.tests.util.ProxyAssertSupport;
import org.junit.Test; import org.junit.Test;
@ -81,7 +80,7 @@ public class ReferenceableTest extends JMSTestCase {
Class<?> factoryClass = Class.forName(factoryName); Class<?> factoryClass = Class.forName(factoryName);
ConnectionFactoryObjectFactory factory = (ConnectionFactoryObjectFactory) factoryClass.newInstance(); ObjectFactory factory = (ObjectFactory) factoryClass.newInstance();
Object instance = factory.getObjectInstance(cfRef, null, null, null); Object instance = factory.getObjectInstance(cfRef, null, null, null);
@ -100,7 +99,7 @@ public class ReferenceableTest extends JMSTestCase {
Class<?> factoryClass = Class.forName(factoryName); Class<?> factoryClass = Class.forName(factoryName);
DestinationObjectFactory factory = (DestinationObjectFactory) factoryClass.newInstance(); ObjectFactory factory = (ObjectFactory) factoryClass.newInstance();
Object instance = factory.getObjectInstance(queueRef, null, null, null); Object instance = factory.getObjectInstance(queueRef, null, null, null);
@ -121,7 +120,7 @@ public class ReferenceableTest extends JMSTestCase {
Class factoryClass = Class.forName(factoryName); Class factoryClass = Class.forName(factoryName);
DestinationObjectFactory factory = (DestinationObjectFactory) factoryClass.newInstance(); ObjectFactory factory = (ObjectFactory) factoryClass.newInstance();
Object instance = factory.getObjectInstance(topicRef, null, null, null); Object instance = factory.getObjectInstance(topicRef, null, null, null);

View File

@ -0,0 +1,138 @@
/**
* 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.activemq.artemis.tests.unit.jms.jndi;
import static org.junit.Assert.assertEquals;
import javax.naming.Reference;
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.jms.client.ActiveMQDestination;
import org.apache.activemq.artemis.jndi.JNDIReferenceFactory;
import org.apache.activemq.artemis.utils.RandomUtil;
import org.junit.Assert;
import org.junit.Test;
public class ObjectFactoryTest {
@Test(timeout = 1000)
public void testConnectionFactory() throws Exception {
// Create sample connection factory
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://0");
String clientID = RandomUtil.randomString();
String user = RandomUtil.randomString();
String password = RandomUtil.randomString();
long clientFailureCheckPeriod = RandomUtil.randomPositiveLong();
long connectionTTL = RandomUtil.randomPositiveLong();
long callTimeout = RandomUtil.randomPositiveLong();
int minLargeMessageSize = RandomUtil.randomPositiveInt();
int consumerWindowSize = RandomUtil.randomPositiveInt();
int consumerMaxRate = RandomUtil.randomPositiveInt();
int confirmationWindowSize = RandomUtil.randomPositiveInt();
int producerMaxRate = RandomUtil.randomPositiveInt();
boolean blockOnAcknowledge = RandomUtil.randomBoolean();
boolean blockOnDurableSend = RandomUtil.randomBoolean();
boolean blockOnNonDurableSend = RandomUtil.randomBoolean();
boolean autoGroup = RandomUtil.randomBoolean();
boolean preAcknowledge = RandomUtil.randomBoolean();
String loadBalancingPolicyClassName = RandomUtil.randomString();
boolean useGlobalPools = RandomUtil.randomBoolean();
int scheduledThreadPoolMaxSize = RandomUtil.randomPositiveInt();
int threadPoolMaxSize = RandomUtil.randomPositiveInt();
long retryInterval = RandomUtil.randomPositiveLong();
double retryIntervalMultiplier = RandomUtil.randomDouble();
int reconnectAttempts = RandomUtil.randomPositiveInt();
factory.setClientID(clientID);
factory.setUser(user);
factory.setPassword(password);
factory.setClientFailureCheckPeriod(clientFailureCheckPeriod);
factory.setConnectionTTL(connectionTTL);
factory.setCallTimeout(callTimeout);
factory.setMinLargeMessageSize(minLargeMessageSize);
factory.setConsumerWindowSize(consumerWindowSize);
factory.setConsumerMaxRate(consumerMaxRate);
factory.setConfirmationWindowSize(confirmationWindowSize);
factory.setProducerMaxRate(producerMaxRate);
factory.setBlockOnAcknowledge(blockOnAcknowledge);
factory.setBlockOnDurableSend(blockOnDurableSend);
factory.setBlockOnNonDurableSend(blockOnNonDurableSend);
factory.setAutoGroup(autoGroup);
factory.setPreAcknowledge(preAcknowledge);
factory.setConnectionLoadBalancingPolicyClassName(loadBalancingPolicyClassName);
factory.setUseGlobalPools(useGlobalPools);
factory.setScheduledThreadPoolMaxSize(scheduledThreadPoolMaxSize);
factory.setThreadPoolMaxSize(threadPoolMaxSize);
factory.setRetryInterval(retryInterval);
factory.setRetryIntervalMultiplier(retryIntervalMultiplier);
factory.setReconnectAttempts(reconnectAttempts);
// Create reference
Reference ref = JNDIReferenceFactory.createReference(factory.getClass().getName(), factory);
// Get object created based on reference
ActiveMQConnectionFactory temp;
JNDIReferenceFactory refFactory = new JNDIReferenceFactory();
temp = (ActiveMQConnectionFactory)refFactory.getObjectInstance(ref, null, null, null);
// Check settings
Assert.assertEquals(clientID, temp.getClientID());
Assert.assertEquals(user, temp.getUser());
Assert.assertEquals(password, temp.getPassword());
Assert.assertEquals(clientFailureCheckPeriod, temp.getClientFailureCheckPeriod());
Assert.assertEquals(connectionTTL, temp.getConnectionTTL());
Assert.assertEquals(callTimeout, temp.getCallTimeout());
Assert.assertEquals(minLargeMessageSize, temp.getMinLargeMessageSize());
Assert.assertEquals(consumerWindowSize, temp.getConsumerWindowSize());
Assert.assertEquals(consumerMaxRate, temp.getConsumerMaxRate());
Assert.assertEquals(confirmationWindowSize, temp.getConfirmationWindowSize());
Assert.assertEquals(producerMaxRate, temp.getProducerMaxRate());
Assert.assertEquals(blockOnAcknowledge, temp.isBlockOnAcknowledge());
Assert.assertEquals(blockOnDurableSend, temp.isBlockOnDurableSend());
Assert.assertEquals(blockOnNonDurableSend, temp.isBlockOnNonDurableSend());
Assert.assertEquals(autoGroup, temp.isAutoGroup());
Assert.assertEquals(preAcknowledge, temp.isPreAcknowledge());
Assert.assertEquals(loadBalancingPolicyClassName, temp.getConnectionLoadBalancingPolicyClassName());
Assert.assertEquals(useGlobalPools, temp.isUseGlobalPools());
Assert.assertEquals(scheduledThreadPoolMaxSize, temp.getScheduledThreadPoolMaxSize());
Assert.assertEquals(threadPoolMaxSize, temp.getThreadPoolMaxSize());
Assert.assertEquals(retryInterval, temp.getRetryInterval());
Assert.assertEquals(retryIntervalMultiplier, temp.getRetryIntervalMultiplier(), 0.0001);
Assert.assertEquals(reconnectAttempts, temp.getReconnectAttempts());
}
@Test(timeout = 1000)
public void testDestination() throws Exception {
// Create sample destination
ActiveMQDestination dest = (ActiveMQDestination) ActiveMQJMSClient.createQueue(RandomUtil.randomString());
// Create reference
Reference ref = JNDIReferenceFactory.createReference(dest.getClass().getName(), dest);
// Get object created based on reference
ActiveMQDestination temp;
JNDIReferenceFactory refFactory = new JNDIReferenceFactory();
temp = (ActiveMQDestination)refFactory.getObjectInstance(ref, null, null, null);
// Check settings
assertEquals(dest.getAddress(), temp.getAddress());
}
}

View File

@ -0,0 +1,119 @@
/**
* 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.activemq.artemis.tests.unit.jms.jndi;
import static org.junit.Assert.assertEquals;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.naming.spi.ObjectFactory;
import java.util.Enumeration;
import java.util.Properties;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.jms.client.ActiveMQQueue;
import org.apache.activemq.artemis.jms.client.ActiveMQTopic;
import org.apache.activemq.artemis.jndi.JNDIReferenceFactory;
import org.junit.Test;
/**
* Test to simulate JNDI references created using String properties in containers such as Apache Tomcat.
*/
public class StringRefAddrReferenceTest {
private static final String FACTORY = "factory";
private static final String TYPE = "type";
@Test(timeout = 10000)
public void testActiveMQQueueFromPropertiesJNDI() throws Exception {
Properties properties = new Properties();
properties.setProperty(TYPE, ActiveMQQueue.class.getName());
properties.setProperty(FACTORY, JNDIReferenceFactory.class.getName());
String address = "foo.bar.queue";
properties.setProperty("address", address);
Reference reference = from(properties);
ActiveMQQueue object = getObject(reference, ActiveMQQueue.class);
assertEquals(address, object.getAddress());
}
@Test(timeout = 10000)
public void testActiveMQTopicFromPropertiesJNDI() throws Exception {
Properties properties = new Properties();
properties.setProperty(TYPE, ActiveMQTopic.class.getName());
properties.setProperty(FACTORY, JNDIReferenceFactory.class.getName());
String address = "foo.bar.topic";
properties.setProperty("address", address);
Reference reference = from(properties);
ActiveMQTopic object = getObject(reference, ActiveMQTopic.class);
assertEquals(address, object.getAddress());
}
@Test(timeout = 10000)
public void testActiveMQConnectionFactoryFromPropertiesJNDI() throws Exception {
Properties properties = new Properties();
properties.setProperty(TYPE, ActiveMQConnectionFactory.class.getName());
properties.setProperty(FACTORY, JNDIReferenceFactory.class.getName());
String brokerURL = "vm://0";
String connectionTTL = "1000";
String preAcknowledge = "true";
properties.setProperty("brokerURL", brokerURL);
properties.setProperty("connectionTTL", connectionTTL);
properties.setProperty("preAcknowledge", preAcknowledge);
Reference reference = from(properties);
ActiveMQConnectionFactory object = getObject(reference, ActiveMQConnectionFactory.class);
assertEquals(Long.parseLong(connectionTTL), object.getConnectionTTL());
assertEquals(Boolean.parseBoolean(preAcknowledge), object.isPreAcknowledge());
}
private <T> T getObject(Reference reference, Class<T> tClass) throws Exception {
String factoryName = reference.getFactoryClassName();
Class<?> factoryClass = Class.forName(factoryName);
ObjectFactory factory = (ObjectFactory) factoryClass.newInstance();
Object o = factory.getObjectInstance(reference, null, null, null);
if (tClass.isAssignableFrom(tClass)) {
return tClass.cast(o);
} else {
throw new IllegalStateException("Expected class, " + tClass.getName());
}
}
public Reference from(Properties properties) {
String type = (String) properties.remove("type");
String factory = (String) properties.remove("factory");
Reference result = new Reference(type, factory, null);
for (Enumeration iter = properties.propertyNames(); iter.hasMoreElements();) {
String key = (String)iter.nextElement();
result.add(new StringRefAddr(key, properties.getProperty(key)));
}
return result;
}
}

View File

@ -43,6 +43,9 @@ public class ConnectionFactoryPropertiesTest extends ActiveMQTestBase {
UNSUPPORTED_CF_PROPERTIES.add("discoveryGroupName"); UNSUPPORTED_CF_PROPERTIES.add("discoveryGroupName");
UNSUPPORTED_CF_PROPERTIES.add("incomingInterceptorList"); UNSUPPORTED_CF_PROPERTIES.add("incomingInterceptorList");
UNSUPPORTED_CF_PROPERTIES.add("outgoingInterceptorList"); UNSUPPORTED_CF_PROPERTIES.add("outgoingInterceptorList");
UNSUPPORTED_CF_PROPERTIES.add("user");
UNSUPPORTED_CF_PROPERTIES.add("userName");
UNSUPPORTED_CF_PROPERTIES.add("password");
UNSUPPORTED_RA_PROPERTIES = new TreeSet<>(); UNSUPPORTED_RA_PROPERTIES = new TreeSet<>();
UNSUPPORTED_RA_PROPERTIES.add("HA"); UNSUPPORTED_RA_PROPERTIES.add("HA");
@ -62,6 +65,7 @@ public class ConnectionFactoryPropertiesTest extends ActiveMQTestBase {
UNSUPPORTED_RA_PROPERTIES.add("useMaskedPassword"); UNSUPPORTED_RA_PROPERTIES.add("useMaskedPassword");
UNSUPPORTED_RA_PROPERTIES.add("useAutoRecovery"); UNSUPPORTED_RA_PROPERTIES.add("useAutoRecovery");
UNSUPPORTED_RA_PROPERTIES.add("useLocalTx"); UNSUPPORTED_RA_PROPERTIES.add("useLocalTx");
UNSUPPORTED_RA_PROPERTIES.add("user");
UNSUPPORTED_RA_PROPERTIES.add("userName"); UNSUPPORTED_RA_PROPERTIES.add("userName");
UNSUPPORTED_RA_PROPERTIES.add("jgroupsChannelLocatorClass"); UNSUPPORTED_RA_PROPERTIES.add("jgroupsChannelLocatorClass");
UNSUPPORTED_RA_PROPERTIES.add("jgroupsChannelRefName"); UNSUPPORTED_RA_PROPERTIES.add("jgroupsChannelRefName");

View File

@ -14,13 +14,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.activemq.artemis.tests.unit.jms.referenceable; package org.apache.activemq.artemis.tests.unit.ra.referenceable;
import javax.naming.Reference; import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient; import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
import org.apache.activemq.artemis.jms.client.ActiveMQDestination; import org.apache.activemq.artemis.jms.client.ActiveMQDestination;
import org.apache.activemq.artemis.jms.referenceable.DestinationObjectFactory;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase; import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.utils.RandomUtil; import org.apache.activemq.artemis.utils.RandomUtil;
import org.junit.Assert; import org.junit.Assert;
@ -41,8 +41,9 @@ public class DestinationObjectFactoryTest extends ActiveMQTestBase {
public void testReference() throws Exception { public void testReference() throws Exception {
ActiveMQDestination queue = (ActiveMQDestination) ActiveMQJMSClient.createQueue(RandomUtil.randomString()); ActiveMQDestination queue = (ActiveMQDestination) ActiveMQJMSClient.createQueue(RandomUtil.randomString());
Reference reference = queue.getReference(); Reference reference = queue.getReference();
String factoryName = reference.getFactoryClassName();
DestinationObjectFactory factory = new DestinationObjectFactory(); Class<?> factoryClass = Class.forName(factoryName);
ObjectFactory factory = (ObjectFactory) factoryClass.newInstance();
Object object = factory.getObjectInstance(reference, null, null, null); Object object = factory.getObjectInstance(reference, null, null, null);
Assert.assertNotNull(object); Assert.assertNotNull(object);
Assert.assertTrue(object instanceof ActiveMQDestination); Assert.assertTrue(object instanceof ActiveMQDestination);