JMS annotation-driven endpoints.

This commit adds the support of JMS annotated endpoint. Can be
activated both by @EnableJms or <jms:annotation-driven/> and
detects methods of managed beans annotated with @JmsListener,
either directly or through a meta-annotation.

Containers are created and managed under the cover by a registry
at application startup time. Container creation is delegated to a
JmsListenerContainerFactory that is identified by the containerFactory
attribute of the JmsListener annotation. Containers can be
retrieved from the registry using a custom id that can be specified
directly on the annotation.

A "factory-id" attribute is available on the container element of
the XML namespace. When it is present, the configuration defined at
the namespace level is used to build a JmsListenerContainerFactory
that is exposed with the value of the "factory-id" attribute. This can
be used as a smooth migration path for users having listener containers
defined at the namespace level. It is also possible to migrate all
listeners to annotated endpoints and yet keep the
<jms:listener-container> or <jms:jca-listener-container> element to
share the container configuration.

The configuration can be fine-tuned by implementing the
JmsListenerConfigurer interface which gives access to the registrar
used to register endpoints. This includes a programmatic registration
of endpoints in complement to the declarative approach. A default
JmsListenerContainerFactory can also be specified to be used if no
containerFactory has been set on the annotation.

Annotated methods can have flexible method arguments that are similar
to what @MessageMapping provides. In particular, jms listener endpoint
methods can fully use the messaging abstraction, including convenient
header accessors. It is also possible to inject the raw
javax.jms.Message and the Session for more advanced use cases. The
payload can be injected as long as the conversion service is able to
convert it from the original type of the JMS payload. By
default, a DefaultJmsHandlerMethodFactory is used but it can be
configured further to support additional method arguments or to
customize conversion and validation support.

The return type of an annotated method can also be an instance of
Spring's Message abstraction. Instead of just converting the payload,
such response type allows to communicate standard and custom headers.

The JmsHeaderMapper infrastructure from Spring integration has also
been migrated to the Spring framework. SimpleJmsHeaderMapper is based
on SI's DefaultJmsHeaderMapper. The simple implementation maps all
JMS headers so that the generated Message abstraction has all the
information stored in the protocol specific message.

Issue: SPR-9882
This commit is contained in:
Stephane Nicoll
2014-03-12 17:43:14 +01:00
parent 6cb9a144db
commit 713dd60fa7
71 changed files with 7983 additions and 525 deletions

View File

@@ -0,0 +1,264 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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.
*/
package org.springframework.jms;
import java.util.Enumeration;
import java.util.concurrent.ConcurrentHashMap;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.TextMessage;
/**
* Stub JMS Message implementation intended for testing purposes only.
*
* @author Mark Fisher
* @since 4.1
*/
public class StubTextMessage implements TextMessage {
private String messageId;
private String text;
private int deliveryMode = DEFAULT_DELIVERY_MODE;
private Destination destination;
private String correlationId;
private Destination replyTo;
private String type;
private long timestamp = 0L;
private long expiration = 0L;
private int priority = DEFAULT_PRIORITY;
private boolean redelivered;
private ConcurrentHashMap<String, Object> properties = new ConcurrentHashMap<String, Object>();
public StubTextMessage() {
}
public StubTextMessage(String text) {
this.text = text;
}
public String getText() throws JMSException {
return this.text;
}
public void setText(String text) throws JMSException {
this.text = text;
}
public void acknowledge() throws JMSException {
throw new UnsupportedOperationException();
}
public void clearBody() throws JMSException {
this.text = null;
}
public void clearProperties() throws JMSException {
this.properties.clear();
}
public boolean getBooleanProperty(String name) throws JMSException {
Object value = this.properties.get(name);
return (value instanceof Boolean) ? ((Boolean) value).booleanValue() : false;
}
public byte getByteProperty(String name) throws JMSException {
Object value = this.properties.get(name);
return (value instanceof Byte) ? ((Byte) value).byteValue() : 0;
}
public double getDoubleProperty(String name) throws JMSException {
Object value = this.properties.get(name);
return (value instanceof Double) ? ((Double) value).doubleValue() : 0;
}
public float getFloatProperty(String name) throws JMSException {
Object value = this.properties.get(name);
return (value instanceof Float) ? ((Float) value).floatValue() : 0;
}
public int getIntProperty(String name) throws JMSException {
Object value = this.properties.get(name);
return (value instanceof Integer) ? ((Integer) value).intValue() : 0;
}
public String getJMSCorrelationID() throws JMSException {
return this.correlationId;
}
public byte[] getJMSCorrelationIDAsBytes() throws JMSException {
return this.correlationId.getBytes();
}
public int getJMSDeliveryMode() throws JMSException {
return this.deliveryMode;
}
public Destination getJMSDestination() throws JMSException {
return this.destination;
}
public long getJMSExpiration() throws JMSException {
return this.expiration;
}
public String getJMSMessageID() throws JMSException {
return this.messageId;
}
public int getJMSPriority() throws JMSException {
return this.priority;
}
public boolean getJMSRedelivered() throws JMSException {
return this.redelivered;
}
public Destination getJMSReplyTo() throws JMSException {
return this.replyTo;
}
public long getJMSTimestamp() throws JMSException {
return this.timestamp;
}
public String getJMSType() throws JMSException {
return this.type;
}
public long getLongProperty(String name) throws JMSException {
Object value = this.properties.get(name);
return (value instanceof Long) ? ((Long) value).longValue() : 0;
}
public Object getObjectProperty(String name) throws JMSException {
return this.properties.get(name);
}
public Enumeration<?> getPropertyNames() throws JMSException {
return this.properties.keys();
}
public short getShortProperty(String name) throws JMSException {
Object value = this.properties.get(name);
return (value instanceof Short) ? ((Short) value).shortValue() : 0;
}
public String getStringProperty(String name) throws JMSException {
Object value = this.properties.get(name);
return (value instanceof String) ? (String) value : null;
}
public boolean propertyExists(String name) throws JMSException {
return this.properties.containsKey(name);
}
public void setBooleanProperty(String name, boolean value) throws JMSException {
this.properties.put(name, value);
}
public void setByteProperty(String name, byte value) throws JMSException {
this.properties.put(name, value);
}
public void setDoubleProperty(String name, double value) throws JMSException {
this.properties.put(name, value);
}
public void setFloatProperty(String name, float value) throws JMSException {
this.properties.put(name, value);
}
public void setIntProperty(String name, int value) throws JMSException {
this.properties.put(name, value);
}
public void setJMSCorrelationID(String correlationId) throws JMSException {
this.correlationId = correlationId;
}
public void setJMSCorrelationIDAsBytes(byte[] correlationID) throws JMSException {
this.correlationId = new String(correlationID);
}
public void setJMSDeliveryMode(int deliveryMode) throws JMSException {
this.deliveryMode = deliveryMode;
}
public void setJMSDestination(Destination destination) throws JMSException {
this.destination = destination;
}
public void setJMSExpiration(long expiration) throws JMSException {
this.expiration = expiration;
}
public void setJMSMessageID(String id) throws JMSException {
this.messageId = id;
}
public void setJMSPriority(int priority) throws JMSException {
this.priority = priority;
}
public void setJMSRedelivered(boolean redelivered) throws JMSException {
this.redelivered = redelivered;
}
public void setJMSReplyTo(Destination replyTo) throws JMSException {
this.replyTo = replyTo;
}
public void setJMSTimestamp(long timestamp) throws JMSException {
this.timestamp = timestamp;
}
public void setJMSType(String type) throws JMSException {
this.type = type;
}
public void setLongProperty(String name, long value) throws JMSException {
this.properties.put(name, value);
}
public void setObjectProperty(String name, Object value) throws JMSException {
this.properties.put(name, value);
}
public void setShortProperty(String name, short value) throws JMSException {
this.properties.put(name, value);
}
public void setStringProperty(String name, String value) throws JMSException {
this.properties.put(name, value);
}
}

View File

@@ -0,0 +1,210 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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.
*/
package org.springframework.jms.annotation;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import javax.jms.JMSException;
import javax.jms.Session;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.context.ApplicationContext;
import org.springframework.jms.StubTextMessage;
import org.springframework.jms.config.JmsListenerContainerTestFactory;
import org.springframework.jms.config.JmsListenerEndpoint;
import org.springframework.jms.config.JmsListenerEndpointRegistry;
import org.springframework.jms.config.MethodJmsListenerEndpoint;
import org.springframework.jms.config.SimpleJmsListenerEndpoint;
import org.springframework.jms.listener.SimpleMessageListenerContainer;
import org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.validation.annotation.Validated;
/**
*
* @author Stephane Nicoll
*/
public abstract class AbstractJmsAnnotationDrivenTests {
@Rule
public final ExpectedException thrown = ExpectedException.none();
@Test
public abstract void sampleConfiguration();
@Test
public abstract void fullConfiguration();
@Test
public abstract void customConfiguration();
@Test
public abstract void defaultContainerFactoryConfiguration();
@Test
public abstract void jmsHandlerMethodFactoryConfiguration() throws JMSException;
/**
* Test for {@link SampleBean} discovery.
*/
public void testSampleConfiguration(ApplicationContext context) {
JmsListenerContainerTestFactory defaultFactory =
context.getBean("defaultFactory", JmsListenerContainerTestFactory.class);
JmsListenerContainerTestFactory simpleFactory =
context.getBean("simpleFactory", JmsListenerContainerTestFactory.class);
assertEquals(1, defaultFactory.getContainers().size());
assertEquals(1, simpleFactory.getContainers().size());
}
@Component
static class SampleBean {
@JmsListener(containerFactory = "defaultFactory", destination = "myQueue")
public void defaultHandle(String msg) {
}
@JmsListener(containerFactory = "simpleFactory", destination = "myQueue")
public void simpleHandle(String msg) {
}
}
/**
* Test for {@link FullBean} discovery.
*/
public void testFullConfiguration(ApplicationContext context) {
JmsListenerContainerTestFactory simpleFactory =
context.getBean("simpleFactory", JmsListenerContainerTestFactory.class);
assertEquals(1, simpleFactory.getContainers().size());
MethodJmsListenerEndpoint endpoint = (MethodJmsListenerEndpoint)
simpleFactory.getContainers().get(0).getEndpoint();
assertEquals("listener1", endpoint.getId());
assertEquals("queueIn", endpoint.getDestination());
assertTrue(endpoint.isQueue());
assertEquals("mySelector", endpoint.getSelector());
assertEquals("mySubscription", endpoint.getSubscription());
}
@Component
static class FullBean {
@JmsListener(id = "listener1", containerFactory = "simpleFactory", destination = "queueIn",
responseDestination = "queueOut", selector = "mySelector", subscription = "mySubscription")
public String fullHandle(String msg) {
return "reply";
}
}
/**
* Test for {@link CustomBean} and an manually endpoint registered
* with "myCustomEndpointId".
*/
public void testCustomConfiguration(ApplicationContext context) {
JmsListenerContainerTestFactory defaultFactory =
context.getBean("defaultFactory", JmsListenerContainerTestFactory.class);
JmsListenerContainerTestFactory customFactory =
context.getBean("customFactory", JmsListenerContainerTestFactory.class);
assertEquals(1, defaultFactory.getContainers().size());
assertEquals(1, customFactory.getContainers().size());
JmsListenerEndpoint endpoint = defaultFactory.getContainers().get(0).getEndpoint();
assertEquals("Wrong endpoint type", SimpleJmsListenerEndpoint.class, endpoint.getClass());
assertEquals("Wrong listener set in custom endpoint", context.getBean("simpleMessageListener"),
((SimpleJmsListenerEndpoint) endpoint).getMessageListener());
JmsListenerEndpointRegistry customRegistry =
context.getBean("customRegistry", JmsListenerEndpointRegistry.class);
assertEquals("Wrong number of containers in the registry", 2,
customRegistry.getContainers().size());
assertNotNull("Container with custom id on the annotation should be found",
customRegistry.getContainer("listenerId"));
assertNotNull("Container created with custom id should be found",
customRegistry.getContainer("myCustomEndpointId"));
}
@Component
static class CustomBean {
@JmsListener(id = "listenerId", containerFactory = "customFactory", destination = "myQueue")
public void customHandle(String msg) {
}
}
/**
* Test for {@link DefaultBean} that does not define the container
* factory to use as a default is registered.
*/
public void testDefaultContainerFactoryConfiguration(ApplicationContext context) {
JmsListenerContainerTestFactory defaultFactory =
context.getBean("defaultFactory", JmsListenerContainerTestFactory.class);
assertEquals(1, defaultFactory.getContainers().size());
}
static class DefaultBean {
@JmsListener(destination = "myQueue")
public void handleIt(String msg) {
}
}
/**
* Test for {@link ValidationBean} with a validator ({@link TestValidator}) specified
* in a custom {@link org.springframework.jms.config.DefaultJmsHandlerMethodFactory}.
*
* The test should throw a {@link org.springframework.jms.listener.adapter.ListenerExecutionFailedException}
*/
public void testJmsHandlerMethodFactoryConfiguration(ApplicationContext context) throws JMSException {
JmsListenerContainerTestFactory simpleFactory =
context.getBean("defaultFactory", JmsListenerContainerTestFactory.class);
assertEquals(1, simpleFactory.getContainers().size());
MethodJmsListenerEndpoint endpoint = (MethodJmsListenerEndpoint)
simpleFactory.getContainers().get(0).getEndpoint();
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
endpoint.setupMessageContainer(container);
MessagingMessageListenerAdapter listener = (MessagingMessageListenerAdapter) container.getMessageListener();
listener.onMessage(new StubTextMessage("failValidation"), mock(Session.class));
}
@Component
static class ValidationBean {
@JmsListener(containerFactory = "defaultFactory", destination = "myQueue")
public void defaultHandle(@Validated String msg) {
}
}
static class TestValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return String.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
String value = (String) target;
if ("failValidation".equals(value)) {
errors.reject("TEST: expected invalid value");
}
}
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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.
*/
package org.springframework.jms.annotation;
import javax.jms.JMSException;
import javax.jms.MessageListener;
import org.hamcrest.core.Is;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerEndpointRegistrar;
import org.springframework.jms.config.SimpleJmsListenerEndpoint;
import org.springframework.jms.listener.adapter.ListenerExecutionFailedException;
import org.springframework.messaging.handler.annotation.support.MethodArgumentNotValidException;
/**
*
* @author Stephane Nicoll
*/
public class AnnotationDrivenNamespaceTests extends AbstractJmsAnnotationDrivenTests {
@Override
@Test
public void sampleConfiguration() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"annotation-driven-sample-config.xml", getClass());
testSampleConfiguration(context);
}
@Override
@Test
public void fullConfiguration() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"annotation-driven-full-config.xml", getClass());
testFullConfiguration(context);
}
@Override
@Test
public void customConfiguration() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"annotation-driven-custom-registry.xml", getClass());
testCustomConfiguration(context);
}
@Override
@Test
public void defaultContainerFactoryConfiguration() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"annotation-driven-custom-container-factory.xml", getClass());
testDefaultContainerFactoryConfiguration(context);
}
@Override
public void jmsHandlerMethodFactoryConfiguration() throws JMSException {
ApplicationContext context = new ClassPathXmlApplicationContext(
"annotation-driven-custom-handler-method-factory.xml", getClass());
thrown.expect(ListenerExecutionFailedException.class);
thrown.expectCause(Is.<MethodArgumentNotValidException>isA(MethodArgumentNotValidException.class));
testJmsHandlerMethodFactoryConfiguration(context);
}
static class CustomJmsListenerConfigurer implements JmsListenerConfigurer {
private MessageListener messageListener;
private JmsListenerContainerFactory containerFactory;
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setId("myCustomEndpointId");
endpoint.setDestination("myQueue");
endpoint.setMessageListener(messageListener);
registrar.registerEndpoint(endpoint, containerFactory);
}
public void setMessageListener(MessageListener messageListener) {
this.messageListener = messageListener;
}
public void setContainerFactory(JmsListenerContainerFactory containerFactory) {
this.containerFactory = containerFactory;
}
}
}

View File

@@ -0,0 +1,184 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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.
*/
package org.springframework.jms.annotation;
import javax.jms.JMSException;
import javax.jms.MessageListener;
import org.hamcrest.core.Is;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.jms.config.DefaultJmsHandlerMethodFactory;
import org.springframework.jms.config.JmsHandlerMethodFactory;
import org.springframework.jms.config.JmsListenerContainerTestFactory;
import org.springframework.jms.config.JmsListenerEndpointRegistrar;
import org.springframework.jms.config.JmsListenerEndpointRegistry;
import org.springframework.jms.config.SimpleJmsListenerEndpoint;
import org.springframework.jms.listener.adapter.ListenerExecutionFailedException;
import org.springframework.jms.listener.adapter.MessageListenerAdapter;
import org.springframework.messaging.handler.annotation.support.MethodArgumentNotValidException;
/**
*
* @author Stephane Nicoll
*/
public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
@Rule
public final ExpectedException thrown = ExpectedException.none();
@Override
@Test
public void sampleConfiguration() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsConfig.class, SampleBean.class);
testSampleConfiguration(context);
}
@Override
@Test
public void fullConfiguration() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsConfig.class, FullBean.class);
testFullConfiguration(context);
}
@Override
@Test
public void customConfiguration() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsCustomConfig.class, CustomBean.class);
testCustomConfiguration(context);
}
@Override
@Test
public void defaultContainerFactoryConfiguration() {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsDefaultContainerFactoryConfig.class, DefaultBean.class);
testDefaultContainerFactoryConfiguration(context);
}
@Override
@Test
public void jmsHandlerMethodFactoryConfiguration() throws JMSException {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
EnableJmsHandlerMethodFactoryConfig.class, ValidationBean.class);
thrown.expect(ListenerExecutionFailedException.class);
thrown.expectCause(Is.<MethodArgumentNotValidException>isA(MethodArgumentNotValidException.class));
testJmsHandlerMethodFactoryConfiguration(context);
}
@Test
public void unknownFactory() {
thrown.expect(BeanCreationException.class);
thrown.expectMessage("customFactory"); // Not found
new AnnotationConfigApplicationContext(
EnableJmsConfig.class, CustomBean.class);
}
@EnableJms
@Configuration
static class EnableJmsConfig {
@Bean
public JmsListenerContainerTestFactory defaultFactory() {
return new JmsListenerContainerTestFactory();
}
@Bean
public JmsListenerContainerTestFactory simpleFactory() {
return new JmsListenerContainerTestFactory();
}
}
@Configuration
@Import(EnableJmsConfig.class)
static class EnableJmsCustomConfig implements JmsListenerConfigurer {
@Autowired
private EnableJmsConfig jmsConfig;
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
registrar.setEndpointRegistry(customRegistry());
// Also register a custom endpoint
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setId("myCustomEndpointId");
endpoint.setDestination("myQueue");
endpoint.setMessageListener(simpleMessageListener());
registrar.registerEndpoint(endpoint, jmsConfig.defaultFactory());
}
@Bean
public JmsListenerEndpointRegistry customRegistry() {
return new JmsListenerEndpointRegistry();
}
@Bean
public JmsListenerContainerTestFactory customFactory() {
return new JmsListenerContainerTestFactory();
}
@Bean
public MessageListener simpleMessageListener() {
return new MessageListenerAdapter();
}
}
@Configuration
@Import(EnableJmsConfig.class)
static class EnableJmsDefaultContainerFactoryConfig implements JmsListenerConfigurer {
@Autowired
private EnableJmsConfig jmsConfig;
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
registrar.setDefaultContainerFactory(jmsConfig.defaultFactory());
}
}
@Configuration
@Import(EnableJmsConfig.class)
static class EnableJmsHandlerMethodFactoryConfig implements JmsListenerConfigurer {
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
registrar.setJmsHandlerMethodFactory(jmsHandlerMethodFactory());
}
@Bean
public JmsHandlerMethodFactory jmsHandlerMethodFactory() {
DefaultJmsHandlerMethodFactory factory = new DefaultJmsHandlerMethodFactory();
factory.setValidator(new TestValidator());
return factory;
}
}
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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.
*/
package org.springframework.jms.annotation;
import static org.junit.Assert.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.AbstractJmsListenerEndpoint;
import org.springframework.jms.config.JmsListenerContainerTestFactory;
import org.springframework.jms.config.JmsListenerEndpoint;
import org.springframework.jms.config.JmsListenerEndpointRegistry;
import org.springframework.jms.config.MessageListenerTestContainer;
import org.springframework.jms.config.MethodJmsListenerEndpoint;
import org.springframework.jms.listener.SimpleMessageListenerContainer;
import org.springframework.stereotype.Component;
/**
*
* @author Stephane Nicoll
*/
public class JmsListenerAnnotationBeanPostProcessorTests {
@Test
public void simpleMessageListener() {
final ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(Config.class,
SimpleMessageListenerTestBean.class);
JmsListenerContainerTestFactory factory = context.getBean(JmsListenerContainerTestFactory.class);
assertEquals("one container should have been registered", 1, factory.getContainers().size());
MessageListenerTestContainer container = factory.getContainers().get(0);
JmsListenerEndpoint endpoint = container.getEndpoint();
assertEquals("Wrong endpoint type", MethodJmsListenerEndpoint.class, endpoint.getClass());
MethodJmsListenerEndpoint methodEndpoint = (MethodJmsListenerEndpoint) endpoint;
assertNotNull(methodEndpoint.getBean());
assertNotNull(methodEndpoint.getMethod());
assertNull(methodEndpoint.getResponseDestination());
assertTrue(methodEndpoint.isQueue());
assertTrue("Should have been started " + container, container.isStarted());
SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer();
methodEndpoint.setupMessageContainer(listenerContainer);
assertNotNull(listenerContainer.getMessageListener());
context.close(); // Close and stop the listeners
assertTrue("Should have been stopped " + container, container.isStopped());
}
@Test
public void metaAnnotationIsDiscovered() {
final ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(Config.class,
MetaAnnotationTestBean.class);
JmsListenerContainerTestFactory factory = context.getBean(JmsListenerContainerTestFactory.class);
assertEquals("one container should have been registered", 1, factory.getContainers().size());
JmsListenerEndpoint endpoint = factory.getContainers().get(0).getEndpoint();
assertEquals("metaTestQueue", ((AbstractJmsListenerEndpoint) endpoint).getDestination());
}
@Component
static class SimpleMessageListenerTestBean {
@JmsListener(destination = "testQueue")
public void handleIt(String body) {
}
}
@Component
static class MetaAnnotationTestBean {
@FooListener
public void handleIt(String body) {
}
}
@JmsListener(destination = "metaTestQueue")
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
static @interface FooListener {
}
@Configuration
static class Config {
@Bean
public JmsListenerAnnotationBeanPostProcessor postProcessor() {
JmsListenerAnnotationBeanPostProcessor postProcessor = new JmsListenerAnnotationBeanPostProcessor();
postProcessor.setEndpointRegistry(jmsListenerEndpointRegistry());
postProcessor.setDefaultContainerFactory(testFactory());
return postProcessor;
}
@Bean
public JmsListenerEndpointRegistry jmsListenerEndpointRegistry() {
return new JmsListenerEndpointRegistry();
}
@Bean
public JmsListenerContainerTestFactory testFactory() {
return new JmsListenerContainerTestFactory();
}
}
}

View File

@@ -0,0 +1,203 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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.
*/
package org.springframework.jms.config;
import static org.junit.Assert.*;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TestName;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.core.MethodParameter;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.messaging.Message;
import org.springframework.messaging.converter.ByteArrayMessageConverter;
import org.springframework.messaging.converter.MessageConversionException;
import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
import org.springframework.messaging.handler.invocation.InvocableHandlerMethod;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.util.ReflectionUtils;
/**
*
* @author Stephane Nicoll
*/
public class DefaultJmsHandlerMethodFactoryTests {
@Rule
public final TestName name = new TestName();
@Rule
public final ExpectedException thrown = ExpectedException.none();
private final SampleBean sample = new SampleBean();
@Test
public void customConversion() throws Exception {
DefaultJmsHandlerMethodFactory instance = createInstance();
GenericConversionService conversionService = new GenericConversionService();
conversionService.addConverter(SampleBean.class, String.class, new Converter<SampleBean, String>() {
@Override
public String convert(SampleBean source) {
return "foo bar";
}
});
instance.setConversionService(conversionService);
instance.afterPropertiesSet();
InvocableHandlerMethod invocableHandlerMethod =
createInvocableHandlerMethod(instance, "simpleString", String.class);
invocableHandlerMethod.invoke(MessageBuilder.withPayload(sample).build());
assertMethodInvocation(sample, "simpleString");
}
@Test
public void customConversionServiceFailure() throws Exception {
DefaultJmsHandlerMethodFactory instance = createInstance();
GenericConversionService conversionService = new GenericConversionService();
assertFalse("conversion service should fail to convert payload",
conversionService.canConvert(Integer.class, String.class));
instance.setConversionService(conversionService);
instance.afterPropertiesSet();
InvocableHandlerMethod invocableHandlerMethod =
createInvocableHandlerMethod(instance, "simpleString", String.class);
thrown.expect(MessageConversionException.class);
invocableHandlerMethod.invoke(MessageBuilder.withPayload(123).build());
}
@Test
public void customMessageConverterFailure() throws Exception {
DefaultJmsHandlerMethodFactory instance = createInstance();
MessageConverter messageConverter = new ByteArrayMessageConverter();
instance.setMessageConverter(messageConverter);
instance.afterPropertiesSet();
InvocableHandlerMethod invocableHandlerMethod =
createInvocableHandlerMethod(instance, "simpleString", String.class);
thrown.expect(MessageConversionException.class);
invocableHandlerMethod.invoke(MessageBuilder.withPayload(123).build());
}
@Test
public void customArgumentResolver() throws Exception {
DefaultJmsHandlerMethodFactory instance = createInstance();
List<HandlerMethodArgumentResolver> customResolvers = new ArrayList<HandlerMethodArgumentResolver>();
customResolvers.add(new CustomHandlerMethodArgumentResolver());
instance.setCustomArgumentResolvers(customResolvers);
instance.afterPropertiesSet();
InvocableHandlerMethod invocableHandlerMethod =
createInvocableHandlerMethod(instance, "customArgumentResolver", Locale.class);
invocableHandlerMethod.invoke(MessageBuilder.withPayload(123).build());
assertMethodInvocation(sample, "customArgumentResolver");
}
@Test
public void overrideArgumentResolvers() throws Exception {
DefaultJmsHandlerMethodFactory instance = createInstance();
List<HandlerMethodArgumentResolver> customResolvers = new ArrayList<HandlerMethodArgumentResolver>();
customResolvers.add(new CustomHandlerMethodArgumentResolver());
instance.setArgumentResolvers(customResolvers);
instance.afterPropertiesSet();
Message<String> message = MessageBuilder.withPayload("sample").build();
// This will work as the local resolver is set
InvocableHandlerMethod invocableHandlerMethod =
createInvocableHandlerMethod(instance, "customArgumentResolver", Locale.class);
invocableHandlerMethod.invoke(message);
assertMethodInvocation(sample, "customArgumentResolver");
// This won't work as no resolver is known for the payload
InvocableHandlerMethod invocableHandlerMethod2 =
createInvocableHandlerMethod(instance, "simpleString", String.class);
thrown.expect(IllegalStateException.class);
thrown.expectMessage("No suitable resolver for");
invocableHandlerMethod2.invoke(message);
}
private void assertMethodInvocation(SampleBean bean, String methodName) {
assertTrue("Method " + methodName + " should have been invoked", bean.invocations.get(methodName));
}
private InvocableHandlerMethod createInvocableHandlerMethod(
DefaultJmsHandlerMethodFactory factory, String methodName, Class<?>... parameterTypes) {
return factory.createInvocableHandlerMethod(sample, getListenerMethod(methodName, parameterTypes));
}
private DefaultJmsHandlerMethodFactory createInstance() {
DefaultJmsHandlerMethodFactory factory = new DefaultJmsHandlerMethodFactory();
factory.setApplicationContext(new StaticApplicationContext());
return factory;
}
private Method getListenerMethod(String methodName, Class<?>... parameterTypes) {
Method method = ReflectionUtils.findMethod(SampleBean.class,
methodName, parameterTypes);
assertNotNull("no method found with name " + methodName
+ " and parameters " + Arrays.toString(parameterTypes));
return method;
}
static class SampleBean {
private final Map<String, Boolean> invocations = new HashMap<String, Boolean>();
public void simpleString(String value) {
invocations.put("simpleString", true);
}
public void customArgumentResolver(Locale locale) {
invocations.put("customArgumentResolver", true);
assertEquals("Wrong value for locale", Locale.getDefault(), locale);
}
}
static class CustomHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().isAssignableFrom(Locale.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, Message<?> message) throws Exception {
return Locale.getDefault();
}
}
}

View File

@@ -0,0 +1,143 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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.
*/
package org.springframework.jms.config;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.jms.StubTextMessage;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import org.springframework.jms.listener.SessionAwareMessageListener;
import org.springframework.jms.support.converter.MessageConversionException;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.util.ReflectionUtils;
/**
*
* @author Stephane Nicoll
*/
public class JmsListenerContainerFactoryIntegrationTests {
private final DefaultJmsListenerContainerFactory containerFactory = new DefaultJmsListenerContainerFactory();
private final DefaultJmsHandlerMethodFactory factory = new DefaultJmsHandlerMethodFactory();
private final JmsEndpointSampleBean sample = new JmsEndpointSampleBean();
@Before
public void setup() {
initializeFactory(factory);
}
@Test
public void messageConverterUsedIfSet() throws JMSException {
containerFactory.setMessageConverter(new UpperCaseMessageConverter());
MethodJmsListenerEndpoint endpoint = createDefaultMethodJmsEndpoint("expectFooBarUpperCase", String.class);
Message message = new StubTextMessage("foo-bar");
invokeListener(endpoint, message);
assertListenerMethodInvocation("expectFooBarUpperCase");
}
static class JmsEndpointSampleBean {
private final Map<String, Boolean> invocations = new HashMap<String, Boolean>();
public void expectFooBarUpperCase(@Payload String msg) {
invocations.put("expectFooBarUpperCase", true);
assertEquals("Unexpected payload message", "FOO-BAR", msg);
}
}
@SuppressWarnings("unchecked")
private void invokeListener(JmsListenerEndpoint endpoint, Message message) throws JMSException {
DefaultMessageListenerContainer messageListenerContainer =
containerFactory.createMessageListenerContainer(endpoint);
Object listener = messageListenerContainer.getMessageListener();
if (listener instanceof SessionAwareMessageListener) {
((SessionAwareMessageListener<Message>) listener).onMessage(message, mock(Session.class));
}
else {
((MessageListener) listener).onMessage(message);
}
}
private void assertListenerMethodInvocation(String methodName) {
assertTrue("Method " + methodName + " should have been invoked", sample.invocations.get(methodName));
}
private MethodJmsListenerEndpoint createMethodJmsEndpoint(
DefaultJmsHandlerMethodFactory factory, Method method) {
MethodJmsListenerEndpoint endpoint = new MethodJmsListenerEndpoint();
endpoint.setBean(sample);
endpoint.setMethod(method);
endpoint.setJmsHandlerMethodFactory(factory);
return endpoint;
}
private MethodJmsListenerEndpoint createDefaultMethodJmsEndpoint(String methodName, Class<?>... parameterTypes) {
return createMethodJmsEndpoint(this.factory, getListenerMethod(methodName, parameterTypes));
}
private Method getListenerMethod(String methodName, Class<?>... parameterTypes) {
Method method = ReflectionUtils.findMethod(JmsEndpointSampleBean.class,
methodName, parameterTypes);
assertNotNull("no method found with name " + methodName
+ " and parameters " + Arrays.toString(parameterTypes));
return method;
}
private void initializeFactory(DefaultJmsHandlerMethodFactory factory) {
factory.setApplicationContext(new StaticApplicationContext());
factory.afterPropertiesSet();
}
private static class UpperCaseMessageConverter implements MessageConverter {
@Override
public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException {
return new StubTextMessage(object.toString().toUpperCase());
}
@Override
public Object fromMessage(Message message) throws JMSException, MessageConversionException {
String content = ((TextMessage) message).getText();
return content.toUpperCase();
}
}
}

View File

@@ -0,0 +1,193 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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.
*/
package org.springframework.jms.config;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import javax.jms.ConnectionFactory;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.transaction.TransactionManager;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.jms.StubConnectionFactory;
import org.springframework.jms.listener.AbstractMessageListenerContainer;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import org.springframework.jms.listener.SimpleMessageListenerContainer;
import org.springframework.jms.listener.adapter.MessageListenerAdapter;
import org.springframework.jms.listener.endpoint.JmsActivationSpecConfig;
import org.springframework.jms.listener.endpoint.JmsMessageEndpointManager;
import org.springframework.jms.listener.endpoint.StubJmsActivationSpecFactory;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.converter.SimpleMessageConverter;
import org.springframework.jms.support.destination.DestinationResolver;
import org.springframework.jms.support.destination.DynamicDestinationResolver;
/**
*
* @author Stephane Nicoll
*/
public class JmsListenerContainerFactoryTests {
@Rule
public final ExpectedException thrown = ExpectedException.none();
private final ConnectionFactory connectionFactory = new StubConnectionFactory();
private final DestinationResolver destinationResolver = new DynamicDestinationResolver();
private final MessageConverter messageConverter = new SimpleMessageConverter();
private final TransactionManager transactionManager = mock(TransactionManager.class);
@Test
public void createSimpleContainer() {
SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
setDefaultJmsConfig(factory);
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
MessageListener messageListener = new MessageListenerAdapter();
endpoint.setMessageListener(messageListener);
endpoint.setDestination("myQueue");
endpoint.setQueue(false); // See #setDefaultJmsConfig
SimpleMessageListenerContainer container = factory.createMessageListenerContainer(endpoint);
assertDefaultJmsConfig(container);
assertEquals(messageListener, container.getMessageListener());
assertEquals("myQueue", container.getDestinationName());
}
@Test
public void createJmsContainerFullConfig() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
setDefaultJmsConfig(factory);
factory.setCacheLevel(DefaultMessageListenerContainer.CACHE_CONSUMER);
factory.setConcurrency("3-10");
factory.setMaxMessagesPerTask(5);
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
MessageListener messageListener = new MessageListenerAdapter();
endpoint.setMessageListener(messageListener);
endpoint.setDestination("myQueue");
endpoint.setQueue(false); // See #setDefaultJmsConfig
DefaultMessageListenerContainer container = factory.createMessageListenerContainer(endpoint);
assertDefaultJmsConfig(container);
assertEquals(DefaultMessageListenerContainer.CACHE_CONSUMER, container.getCacheLevel());
assertEquals(3, container.getConcurrentConsumers());
assertEquals(10, container.getMaxConcurrentConsumers());
assertEquals(5, container.getMaxMessagesPerTask());
assertEquals(messageListener, container.getMessageListener());
assertEquals("myQueue", container.getDestinationName());
}
@Test
public void createJcaContainerFullConfig() {
DefaultJcaListenerContainerFactory factory = new DefaultJcaListenerContainerFactory();
setDefaultJcaConfig(factory);
factory.getActivationSpecConfig().setConcurrency("10");
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
MessageListener messageListener = new MessageListenerAdapter();
endpoint.setMessageListener(messageListener);
endpoint.setDestination("myQueue");
endpoint.setQueue(false); // See #setDefaultJmsConfig
JmsMessageEndpointManager container = factory.createMessageListenerContainer(endpoint);
assertDefaultJcaConfig(container);
assertEquals(10, container.getActivationSpecConfig().getMaxConcurrency());
assertEquals(messageListener, container.getMessageListener());
assertEquals("myQueue", container.getActivationSpecConfig().getDestinationName());
}
@Test
public void endpointCanOverrideConfig() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setPubSubDomain(true); // topic
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setMessageListener(new MessageListenerAdapter());
endpoint.setQueue(true); // queue
DefaultMessageListenerContainer container = factory.createMessageListenerContainer(endpoint);
assertEquals(false, container.isPubSubDomain()); // overridden by the endpoint config
}
@Test
public void jcaExclusiveProperties() {
DefaultJcaListenerContainerFactory factory = new DefaultJcaListenerContainerFactory();
factory.setDestinationResolver(destinationResolver);
factory.setActivationSpecFactory(new StubJmsActivationSpecFactory());
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setMessageListener(new MessageListenerAdapter());
thrown.expect(IllegalStateException.class);
factory.createMessageListenerContainer(endpoint);
}
private void setDefaultJmsConfig(AbstractJmsListenerContainerFactory factory) {
factory.setConnectionFactory(connectionFactory);
factory.setDestinationResolver(destinationResolver);
factory.setMessageConverter(messageConverter);
factory.setSessionTransacted(true);
factory.setSessionAcknowledgeMode(Session.DUPS_OK_ACKNOWLEDGE);
factory.setPubSubDomain(true);
factory.setSubscriptionDurable(true);
factory.setClientId("client-1234");
}
private void assertDefaultJmsConfig(AbstractMessageListenerContainer container) {
assertEquals(connectionFactory, container.getConnectionFactory());
assertEquals(destinationResolver, container.getDestinationResolver());
assertEquals(messageConverter, container.getMessageConverter());
assertEquals(true, container.isSessionTransacted());
assertEquals(Session.DUPS_OK_ACKNOWLEDGE, container.getSessionAcknowledgeMode());
assertEquals(true, container.isPubSubDomain());
assertEquals(true, container.isSubscriptionDurable());
assertEquals("client-1234", container.getClientId());
}
private void setDefaultJcaConfig(DefaultJcaListenerContainerFactory factory) {
factory.setDestinationResolver(destinationResolver);
factory.setTransactionManager(transactionManager);
JmsActivationSpecConfig config = new JmsActivationSpecConfig();
config.setMessageConverter(messageConverter);
config.setAcknowledgeMode(Session.DUPS_OK_ACKNOWLEDGE);
config.setPubSubDomain(true);
config.setSubscriptionDurable(true);
config.setClientId("client-1234");
factory.setActivationSpecConfig(config);
}
private void assertDefaultJcaConfig(JmsMessageEndpointManager container) {
assertEquals(messageConverter, container.getMessageConverter());
JmsActivationSpecConfig config = container.getActivationSpecConfig();
assertNotNull(config);
assertEquals(Session.DUPS_OK_ACKNOWLEDGE, config.getAcknowledgeMode());
assertEquals(true, config.isPubSubDomain());
assertEquals(true, config.isSubscriptionDurable());
assertEquals("client-1234", config.getClientId());
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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.
*/
package org.springframework.jms.config;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Stephane Nicoll
*/
public class JmsListenerContainerTestFactory implements JmsListenerContainerFactory<MessageListenerTestContainer> {
private final List<MessageListenerTestContainer> containers =
new ArrayList<MessageListenerTestContainer>();
public List<MessageListenerTestContainer> getContainers() {
return containers;
}
@Override
public MessageListenerTestContainer createMessageListenerContainer(JmsListenerEndpoint endpoint) {
MessageListenerTestContainer container = new MessageListenerTestContainer(endpoint);
this.containers.add(container);
return container;
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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.
*/
package org.springframework.jms.config;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
/**
*
* @author Stephane Nicoll
*/
public class JmsListenerEndpointRegistrarTests {
@Rule
public final ExpectedException thrown = ExpectedException.none();
private final JmsListenerEndpointRegistrar registrar = new JmsListenerEndpointRegistrar();
private final JmsListenerEndpointRegistry registry = new JmsListenerEndpointRegistry();
private final JmsListenerContainerTestFactory containerFactory = new JmsListenerContainerTestFactory();
@Before
public void setup() {
registrar.setEndpointRegistry(registry);
}
@Test
public void registerNullEndpoint() {
thrown.expect(IllegalArgumentException.class);
registrar.registerEndpoint(null, containerFactory);
}
@Test
public void registerNullEndpointId() {
thrown.expect(IllegalArgumentException.class);
registrar.registerEndpoint(new SimpleJmsListenerEndpoint(), containerFactory);
}
@Test
public void registerNullContainerFactoryIsAllowed() throws Exception {
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setId("some id");
registrar.setDefaultContainerFactory(containerFactory);
registrar.registerEndpoint(endpoint, null);
registrar.afterPropertiesSet();
assertNotNull("Container not created", registry.getContainer("some id"));
assertEquals(1, registry.getContainers().size());
}
@Test
public void registerNullContainerFactoryWithNoDefault() throws Exception {
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setId("some id");
registrar.registerEndpoint(endpoint, null);
thrown.expect(IllegalStateException.class);
thrown.expectMessage(endpoint.toString());
registrar.afterPropertiesSet();
}
@Test
public void registerContainerWithoutFactory() throws Exception {
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setId("myEndpoint");
registrar.setDefaultContainerFactory(containerFactory);
registrar.registerEndpoint(endpoint);
registrar.afterPropertiesSet();
assertNotNull("Container not created", registry.getContainer("myEndpoint"));
assertEquals(1, registry.getContainers().size());
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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.
*/
package org.springframework.jms.config;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
/**
*
* @author Stephane Nicoll
*/
public class JmsListenerEndpointRegistryTests {
@Rule
public final ExpectedException thrown = ExpectedException.none();
private final JmsListenerEndpointRegistry registry = new JmsListenerEndpointRegistry();
private final JmsListenerContainerTestFactory containerFactory = new JmsListenerContainerTestFactory();
@Test
public void createWithNullEndpoint() {
thrown.expect(IllegalArgumentException.class);
registry.createJmsListenerContainer(null, containerFactory);
}
@Test
public void createWithNullEndpointId() {
thrown.expect(IllegalArgumentException.class);
registry.createJmsListenerContainer(new SimpleJmsListenerEndpoint(), containerFactory);
}
@Test
public void createWithNullContainerFactory() {
thrown.expect(IllegalArgumentException.class);
registry.createJmsListenerContainer(createEndpoint("foo", "myDestination"), null);
}
@Test
public void createWithDuplicateEndpointId() {
registry.createJmsListenerContainer(createEndpoint("test", "queue"), containerFactory);
thrown.expect(IllegalStateException.class);
registry.createJmsListenerContainer(createEndpoint("test", "queue"), containerFactory);
}
private SimpleJmsListenerEndpoint createEndpoint(String id, String destinationName) {
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setId(id);
endpoint.setDestination(destinationName);
return endpoint;
}
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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.
*/
package org.springframework.jms.config;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import javax.jms.MessageListener;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import org.springframework.jms.listener.MessageListenerContainer;
import org.springframework.jms.listener.adapter.MessageListenerAdapter;
import org.springframework.jms.listener.endpoint.JmsActivationSpecConfig;
import org.springframework.jms.listener.endpoint.JmsMessageEndpointManager;
/**
*
* @author Stephane Nicoll
*/
public class JmsListenerEndpointTests {
@Rule
public final ExpectedException thrown = ExpectedException.none();
@Test
public void setupJmsMessageContainerFullConfig() {
DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
MessageListener messageListener = new MessageListenerAdapter();
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setDestination("myQueue");
endpoint.setQueue(true);
endpoint.setSelector("foo = 'bar'");
endpoint.setSubscription("mySubscription");
endpoint.setMessageListener(messageListener);
endpoint.setupMessageContainer(container);
assertEquals("myQueue", container.getDestinationName());
assertFalse(container.isPubSubDomain());
assertEquals("foo = 'bar'", container.getMessageSelector());
assertEquals("mySubscription", container.getDurableSubscriptionName());
assertEquals(messageListener, container.getMessageListener());
}
@Test
public void setupJcaMessageContainerFullConfig() {
JmsMessageEndpointManager container = new JmsMessageEndpointManager();
MessageListener messageListener = new MessageListenerAdapter();
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setDestination("myQueue");
endpoint.setQueue(true);
endpoint.setSelector("foo = 'bar'");
endpoint.setSubscription("mySubscription");
endpoint.setMessageListener(messageListener);
endpoint.setupMessageContainer(container);
JmsActivationSpecConfig config = container.getActivationSpecConfig();
assertEquals("myQueue", config.getDestinationName());
assertFalse(config.isPubSubDomain());
assertEquals("foo = 'bar'", config.getMessageSelector());
assertEquals("mySubscription", config.getDurableSubscriptionName());
assertEquals(messageListener, container.getMessageListener());
}
@Test
public void setupMessageContainerNoListener() {
DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
thrown.expect(IllegalStateException.class);
endpoint.setupMessageContainer(container);
}
@Test
public void setupMessageContainerUnsupportedContainer() {
MessageListenerContainer container = mock(MessageListenerContainer.class);
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setMessageListener(new MessageListenerAdapter());
thrown.expect(IllegalArgumentException.class);
endpoint.setupMessageContainer(container);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,9 @@
package org.springframework.jms.config;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
@@ -29,6 +32,7 @@ import javax.jms.TextMessage;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.ComponentDefinition;
@@ -41,17 +45,16 @@ import org.springframework.context.Phased;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jca.endpoint.GenericMessageEndpointManager;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import org.springframework.jms.listener.adapter.MessageListenerAdapter;
import org.springframework.jms.listener.endpoint.JmsMessageEndpointManager;
import org.springframework.tests.sample.beans.TestBean;
import org.springframework.util.ErrorHandler;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
/**
* @author Mark Fisher
* @author Juergen Hoeller
* @author Christian Dupuis
* @author Stephane Nicoll
*/
public class JmsNamespaceHandlerTests {
@@ -80,6 +83,10 @@ public class JmsNamespaceHandlerTests {
containers = context.getBeansOfType(GenericMessageEndpointManager.class);
assertEquals("Context should contain 3 JCA endpoint containers", 3, containers.size());
Map<String, JmsListenerContainerFactory> containerFactories =
context.getBeansOfType(JmsListenerContainerFactory.class);
assertEquals("Context should contain 3 JmsListenerContainerFactory instances", 3, containerFactories.size());
}
@Test
@@ -99,8 +106,8 @@ public class JmsNamespaceHandlerTests {
}
else if (container.getConnectionFactory().equals(explicitConnectionFactory)) {
explicitConnectionFactoryCount++;
assertEquals(1, container.getConcurrentConsumers());
assertEquals(2, container.getMaxConcurrentConsumers());
assertEquals(3, container.getConcurrentConsumers());
assertEquals(5, container.getMaxConcurrentConsumers());
}
}
@@ -108,6 +115,72 @@ public class JmsNamespaceHandlerTests {
assertEquals("2 containers should have the explicit connectionFactory", 2, explicitConnectionFactoryCount);
}
@Test
public void testJcaContainerConfiguration() throws Exception {
Map<String, JmsMessageEndpointManager> containers = context.getBeansOfType(JmsMessageEndpointManager.class);
assertTrue("listener3 not found", containers.containsKey("listener3"));
JmsMessageEndpointManager listener3 = containers.get("listener3");
assertEquals("Wrong resource adapter",
context.getBean("testResourceAdapter"), listener3.getResourceAdapter());
assertEquals("Wrong activation spec factory", context.getBean("testActivationSpecFactory"),
new DirectFieldAccessor(listener3).getPropertyValue("activationSpecFactory"));
Object endpointFactory = new DirectFieldAccessor(listener3).getPropertyValue("endpointFactory");
Object messageListener = new DirectFieldAccessor(endpointFactory).getPropertyValue("messageListener");
assertEquals("Wrong message listener", MessageListenerAdapter.class, messageListener.getClass());
MessageListenerAdapter adapter = (MessageListenerAdapter) messageListener;
DirectFieldAccessor adapterFieldAccessor = new DirectFieldAccessor(adapter);
assertEquals("Message converter not set properly", context.getBean("testMessageConverter"),
adapterFieldAccessor.getPropertyValue("messageConverter"));
assertEquals("Wrong delegate", context.getBean("testBean1"),
adapterFieldAccessor.getPropertyValue("delegate"));
assertEquals("Wrong method name", "setName",
adapterFieldAccessor.getPropertyValue("defaultListenerMethod"));
}
@Test
public void testJmsContainerFactoryConfiguration() {
Map<String, DefaultJmsListenerContainerFactory> containers =
context.getBeansOfType(DefaultJmsListenerContainerFactory.class);
DefaultJmsListenerContainerFactory factory = containers.get("testJmsFactory");
assertNotNull("No factory registered with testJmsFactory id", factory);
DefaultMessageListenerContainer container =
factory.createMessageListenerContainer(createDummyEndpoint());
assertEquals("explicit connection factory not set",
context.getBean(EXPLICIT_CONNECTION_FACTORY), container.getConnectionFactory());
assertEquals("explicit destination resolver not set",
context.getBean("testDestinationResolver"), container.getDestinationResolver());
assertEquals("explicit message converter not set",
context.getBean("testMessageConverter"), container.getMessageConverter());
assertEquals("wrong cache", DefaultMessageListenerContainer.CACHE_CONNECTION, container.getCacheLevel());
assertEquals("wrong concurrency", 3, container.getConcurrentConsumers());
assertEquals("wrong concurrency", 5, container.getMaxConcurrentConsumers());
assertEquals("wrong prefetch", 50, container.getMaxMessagesPerTask());
assertEquals("phase cannot be customized by the factory", Integer.MAX_VALUE, container.getPhase());
}
@Test
public void testJcaContainerFactoryConfiguration() {
Map<String, DefaultJcaListenerContainerFactory> containers =
context.getBeansOfType(DefaultJcaListenerContainerFactory.class);
DefaultJcaListenerContainerFactory factory = containers.get("testJcaFactory");
assertNotNull("No factory registered with testJcaFactory id", factory);
JmsMessageEndpointManager container =
factory.createMessageListenerContainer(createDummyEndpoint());
assertEquals("explicit resource adapter not set",
context.getBean("testResourceAdapter"),container.getResourceAdapter());
assertEquals("explicit message converter not set",
context.getBean("testMessageConverter"), container.getActivationSpecConfig().getMessageConverter());
assertEquals("wrong concurrency", 5, container.getActivationSpecConfig().getMaxConcurrency());
assertEquals("Wrong prefetch", 50, container.getActivationSpecConfig().getPrefetchSize());
assertEquals("phase cannot be customized by the factory", Integer.MAX_VALUE, container.getPhase());
}
@Test
public void testListeners() throws Exception {
TestBean testBean1 = context.getBean("testBean1", TestBean.class);
@@ -177,13 +250,24 @@ public class JmsNamespaceHandlerTests {
@Test
public void testComponentRegistration() {
assertTrue("Parser should have registered a component named 'listener1'", context.containsComponentDefinition("listener1"));
assertTrue("Parser should have registered a component named 'listener2'", context.containsComponentDefinition("listener2"));
assertTrue("Parser should have registered a component named 'listener3'", context.containsComponentDefinition("listener3"));
assertTrue("Parser should have registered a component named '" + DefaultMessageListenerContainer.class.getName() + "#0'",
context.containsComponentDefinition(DefaultMessageListenerContainer.class.getName() + "#0"));
assertTrue("Parser should have registered a component named '" + JmsMessageEndpointManager.class.getName() + "#0'",
context.containsComponentDefinition(JmsMessageEndpointManager.class.getName() + "#0"));
assertTrue("Parser should have registered a component named 'listener1'",
context.containsComponentDefinition("listener1"));
assertTrue("Parser should have registered a component named 'listener2'",
context.containsComponentDefinition("listener2"));
assertTrue("Parser should have registered a component named 'listener3'",
context.containsComponentDefinition("listener3"));
assertTrue("Parser should have registered a component named '"
+ DefaultMessageListenerContainer.class.getName() + "#0'",
context.containsComponentDefinition(DefaultMessageListenerContainer.class.getName() + "#0"));
assertTrue("Parser should have registered a component named '"
+ JmsMessageEndpointManager.class.getName() + "#0'",
context.containsComponentDefinition(JmsMessageEndpointManager.class.getName() + "#0"));
assertTrue("Parser should have registered a component named 'testJmsFactory",
context.containsComponentDefinition("testJmsFactory"));
assertTrue("Parser should have registered a component named 'testJcaFactory",
context.containsComponentDefinition("testJcaFactory"));
assertTrue("Parser should have registered a component named 'testJcaFactory",
context.containsComponentDefinition("onlyJmsFactory"));
}
@Test
@@ -191,7 +275,7 @@ public class JmsNamespaceHandlerTests {
Iterator iterator = context.getRegisteredComponents();
while (iterator.hasNext()) {
ComponentDefinition compDef = (ComponentDefinition) iterator.next();
assertNotNull("CompositeComponentDefinition '" + compDef.getName()+ "' has no source attachment", compDef.getSource());
assertNotNull("CompositeComponentDefinition '" + compDef.getName() + "' has no source attachment", compDef.getSource());
validateComponentDefinition(compDef);
}
}
@@ -228,6 +312,13 @@ public class JmsNamespaceHandlerTests {
return ((Phased) container).getPhase();
}
private JmsListenerEndpoint createDummyEndpoint() {
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setMessageListener(new MessageListenerAdapter());
endpoint.setDestination("testQueue");
return endpoint;
}
public static class TestMessageListener implements MessageListener {

View File

@@ -0,0 +1,118 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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.
*/
package org.springframework.jms.config;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jms.JmsException;
import org.springframework.jms.listener.MessageListenerContainer;
import org.springframework.jms.support.converter.MessageConverter;
/**
*
* @author Stephane Nicoll
*/
public class MessageListenerTestContainer
implements MessageListenerContainer, InitializingBean, DisposableBean {
private final JmsListenerEndpoint endpoint;
private boolean startInvoked;
private boolean initializationInvoked;
private boolean stopInvoked;
private boolean destroyInvoked;
MessageListenerTestContainer(JmsListenerEndpoint endpoint) {
this.endpoint = endpoint;
}
public JmsListenerEndpoint getEndpoint() {
return endpoint;
}
public boolean isStarted() {
return startInvoked && initializationInvoked;
}
public boolean isStopped() {
return stopInvoked && destroyInvoked;
}
@Override
public void start() throws JmsException {
if (startInvoked) {
throw new IllegalStateException("Start already invoked on " + this);
}
startInvoked = true;
}
@Override
public boolean isRunning() {
return startInvoked && !stopInvoked;
}
@Override
public void stop() throws JmsException {
if (stopInvoked) {
throw new IllegalStateException("Stop already invoked on " + this);
}
stopInvoked = true;
}
@Override
public void setupMessageListener(Object messageListener) {
}
@Override
public MessageConverter getMessageConverter() {
return null;
}
@Override
public void afterPropertiesSet() {
if (!startInvoked) {
throw new IllegalStateException("Start should have been invoked before " +
"afterPropertiesSet on " + this);
}
initializationInvoked = true;
}
@Override
public void destroy() {
if (!stopInvoked) {
throw new IllegalStateException("Stop should have been invoked before " +
"destroy on " + this);
}
destroyInvoked = true;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("TestContainer{");
sb.append("endpoint=").append(endpoint);
sb.append(", startInvoked=").append(startInvoked);
sb.append(", initializationInvoked=").append(initializationInvoked);
sb.append(", stopInvoked=").append(stopInvoked);
sb.append(", destroyInvoked=").append(destroyInvoked);
sb.append('}');
return sb.toString();
}
}

View File

@@ -0,0 +1,418 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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.
*/
package org.springframework.jms.config;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.*;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.ObjectMessage;
import javax.jms.QueueSender;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TestName;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.jms.StubTextMessage;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import org.springframework.jms.listener.SimpleMessageListenerContainer;
import org.springframework.jms.listener.adapter.ListenerExecutionFailedException;
import org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter;
import org.springframework.jms.support.JmsMessageHeaderAccessor;
import org.springframework.jms.support.converter.JmsHeaders;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.converter.MessageConversionException;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.handler.annotation.support.MethodArgumentTypeMismatchException;
import org.springframework.util.ReflectionUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.validation.annotation.Validated;
/**
*
* @author Stephane Nicoll
*/
public class MethodJmsListenerEndpointTests {
@Rule
public final TestName name = new TestName();
@Rule
public final ExpectedException thrown = ExpectedException.none();
private final DefaultJmsHandlerMethodFactory factory = new DefaultJmsHandlerMethodFactory();
private final DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
private final JmsEndpointSampleBean sample = new JmsEndpointSampleBean();
@Before
public void setup() {
initializeFactory(factory);
}
@Test
public void createMessageListenerNoFactory() {
MethodJmsListenerEndpoint endpoint = new MethodJmsListenerEndpoint();
endpoint.setBean(this);
endpoint.setMethod(getTestMethod());
thrown.expect(IllegalStateException.class);
endpoint.createMessageListener(container);
}
@Test
public void createMessageListener() {
MethodJmsListenerEndpoint endpoint = new MethodJmsListenerEndpoint();
endpoint.setBean(this);
endpoint.setMethod(getTestMethod());
endpoint.setJmsHandlerMethodFactory(factory);
endpoint.setResponseDestination("myResponseQueue");
assertNotNull(endpoint.createMessageListener(container));
}
@Test
public void resolveMessageAndSession() throws JMSException {
MessagingMessageListenerAdapter listener = createDefaultInstance(javax.jms.Message.class, Session.class);
Session session = mock(Session.class);
listener.onMessage(createSimpleJmsTextMessage("test"), session);
assertDefaultListenerMethodInvocation();
}
@Test
public void resolveGenericMessage() throws JMSException {
MessagingMessageListenerAdapter listener = createDefaultInstance(Message.class);
Session session = mock(Session.class);
listener.onMessage(createSimpleJmsTextMessage("test"), session);
assertDefaultListenerMethodInvocation();
}
@Test
public void resolveHeaderAndPayload() throws JMSException {
MessagingMessageListenerAdapter listener = createDefaultInstance(String.class, int.class);
Session session = mock(Session.class);
StubTextMessage message = createSimpleJmsTextMessage("my payload");
message.setIntProperty("myCounter", 55);
listener.onMessage(message, session);
assertDefaultListenerMethodInvocation();
}
@Test
public void resolveHeaders() throws JMSException {
MessagingMessageListenerAdapter listener = createDefaultInstance(String.class, Map.class);
Session session = mock(Session.class);
StubTextMessage message = createSimpleJmsTextMessage("my payload");
message.setIntProperty("customInt", 1234);
message.setJMSMessageID("abcd-1234");
listener.onMessage(message, session);
assertDefaultListenerMethodInvocation();
}
@Test
public void resolveMessageHeaders() throws JMSException {
MessagingMessageListenerAdapter listener = createDefaultInstance(MessageHeaders.class);
Session session = mock(Session.class);
StubTextMessage message = createSimpleJmsTextMessage("my payload");
message.setLongProperty("customLong", 4567L);
message.setJMSType("myMessageType");
listener.onMessage(message, session);
assertDefaultListenerMethodInvocation();
}
@Test
public void resolveJmsMessageHeaderAccessor() throws JMSException {
MessagingMessageListenerAdapter listener = createDefaultInstance(JmsMessageHeaderAccessor.class);
Session session = mock(Session.class);
StubTextMessage message = createSimpleJmsTextMessage("my payload");
message.setBooleanProperty("customBoolean", true);
message.setJMSPriority(9);
listener.onMessage(message, session);
assertDefaultListenerMethodInvocation();
}
@Test
public void resolveObjectPayload() throws JMSException {
MessagingMessageListenerAdapter listener = createDefaultInstance(MyBean.class);
MyBean myBean = new MyBean();
myBean.name = "myBean name";
Session session = mock(Session.class);
ObjectMessage message = mock(ObjectMessage.class);
given(message.getObject()).willReturn(myBean);
listener.onMessage(message, session);
assertDefaultListenerMethodInvocation();
}
@Test
public void resolveConvertedPayload() throws JMSException {
MessagingMessageListenerAdapter listener = createDefaultInstance(Integer.class);
Session session = mock(Session.class);
listener.onMessage(createSimpleJmsTextMessage("33"), session);
assertDefaultListenerMethodInvocation();
}
@Test
public void processAndReply() throws JMSException {
MessagingMessageListenerAdapter listener = createDefaultInstance(String.class);
String body = "echo text";
String correlationId = "link-1234";
Destination replyDestination = new Destination() {};
TextMessage reply = mock(TextMessage.class);
QueueSender queueSender = mock(QueueSender.class);
Session session = mock(Session.class);
given(session.createTextMessage(body)).willReturn(reply);
given(session.createProducer(replyDestination)).willReturn(queueSender);
listener.setDefaultResponseDestination(replyDestination);
StubTextMessage inputMessage = createSimpleJmsTextMessage(body);
inputMessage.setJMSCorrelationID(correlationId);
listener.onMessage(inputMessage, session);
assertDefaultListenerMethodInvocation();
verify(reply).setJMSCorrelationID(correlationId);
verify(queueSender).send(reply);
verify(queueSender).close();
}
@Test
public void validatePayloadValid() throws JMSException {
String methodName = "validatePayload";
DefaultJmsHandlerMethodFactory customFactory = new DefaultJmsHandlerMethodFactory();
customFactory.setValidator(testValidator("invalid value"));
initializeFactory(customFactory);
Method method = getListenerMethod(methodName, String.class);
MessagingMessageListenerAdapter listener = createInstance(customFactory, method);
Session session = mock(Session.class);
listener.onMessage(createSimpleJmsTextMessage("test"), session); // test is a valid value
assertListenerMethodInvocation(sample, methodName);
}
@Test
public void validatePayloadInvalid() throws JMSException {
DefaultJmsHandlerMethodFactory customFactory = new DefaultJmsHandlerMethodFactory();
customFactory.setValidator(testValidator("invalid value"));
Method method = getListenerMethod("validatePayload", String.class);
MessagingMessageListenerAdapter listener = createInstance(customFactory, method);
Session session = mock(Session.class);
thrown.expect(ListenerExecutionFailedException.class);
listener.onMessage(createSimpleJmsTextMessage("invalid value"), session); // test is an invalid value
}
// failure scenario
@Test
public void invalidPayloadType() throws JMSException {
MessagingMessageListenerAdapter listener = createDefaultInstance(Integer.class);
Session session = mock(Session.class);
thrown.expect(ListenerExecutionFailedException.class);
thrown.expectCause(Matchers.isA(MessageConversionException.class));
thrown.expectMessage(getDefaultListenerMethod(Integer.class).toGenericString()); // ref to method
listener.onMessage(createSimpleJmsTextMessage("test"), session); // test is not a valid integer
}
@Test
public void invalidMessagePayloadType() throws JMSException {
MessagingMessageListenerAdapter listener = createDefaultInstance(Message.class);
Session session = mock(Session.class);
thrown.expect(ListenerExecutionFailedException.class);
thrown.expectCause(Matchers.isA(MethodArgumentTypeMismatchException.class));
listener.onMessage(createSimpleJmsTextMessage("test"), session); // Message<String> as Message<Integer>
}
private MessagingMessageListenerAdapter createInstance(
DefaultJmsHandlerMethodFactory factory, Method method) {
MethodJmsListenerEndpoint endpoint = new MethodJmsListenerEndpoint();
endpoint.setBean(sample);
endpoint.setMethod(method);
endpoint.setJmsHandlerMethodFactory(factory);
return endpoint.createMessageListener(new SimpleMessageListenerContainer());
}
private MessagingMessageListenerAdapter createDefaultInstance(Class<?>... parameterTypes) {
return createInstance(this.factory, getDefaultListenerMethod(parameterTypes));
}
private StubTextMessage createSimpleJmsTextMessage(String body) {
return new StubTextMessage(body);
}
private Method getListenerMethod(String methodName, Class<?>... parameterTypes) {
Method method = ReflectionUtils.findMethod(JmsEndpointSampleBean.class,
methodName, parameterTypes);
assertNotNull("no method found with name " + methodName
+ " and parameters " + Arrays.toString(parameterTypes));
return method;
}
private Method getDefaultListenerMethod(Class<?>... parameterTypes) {
return getListenerMethod(name.getMethodName(), parameterTypes);
}
private void assertDefaultListenerMethodInvocation() {
assertListenerMethodInvocation(sample, name.getMethodName());
}
private void assertListenerMethodInvocation(JmsEndpointSampleBean bean, String methodName) {
assertTrue("Method " + methodName + " should have been invoked", bean.invocations.get(methodName));
}
private void initializeFactory(DefaultJmsHandlerMethodFactory factory) {
factory.setApplicationContext(new StaticApplicationContext());
factory.afterPropertiesSet();
}
private Validator testValidator(final String invalidValue) {
return new Validator() {
@Override
public boolean supports(Class<?> clazz) {
return String.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
String value = (String) target;
if (invalidValue.equals(value)) {
errors.reject("not a valid value");
}
}
};
}
private Method getTestMethod() {
return ReflectionUtils.findMethod(MethodJmsListenerEndpointTests.class, name.getMethodName());
}
static class JmsEndpointSampleBean {
private final Map<String, Boolean> invocations = new HashMap<String, Boolean>();
public void resolveMessageAndSession(javax.jms.Message message, Session session) {
invocations.put("resolveMessageAndSession", true);
assertNotNull("Message not injected", message);
assertNotNull("Session not injected", session);
}
public void resolveGenericMessage(Message<String> message) {
invocations.put("resolveGenericMessage", true);
assertNotNull("Generic message not injected", message);
assertEquals("Wrong message payload", "test", message.getPayload());
}
public void resolveHeaderAndPayload(@Payload String content, @Header("myCounter") int counter) {
invocations.put("resolveHeaderAndPayload", true);
assertEquals("Wrong @Payload resolution", "my payload", content);
assertEquals("Wrong @Header resolution", 55, counter);
}
public void resolveHeaders(String content, @Headers Map<String, Object> headers) {
invocations.put("resolveHeaders", true);
assertEquals("Wrong payload resolution", "my payload", content);
assertNotNull("headers not injected", headers);
assertEquals("Missing JMS message id header", "abcd-1234", headers.get(JmsHeaders.MESSAGE_ID));
assertEquals("Missing custom header", 1234, headers.get("customInt"));
}
public void resolveMessageHeaders(MessageHeaders headers) {
invocations.put("resolveMessageHeaders", true);
assertNotNull("MessageHeaders not injected", headers);
assertEquals("Missing JMS message type header", "myMessageType", headers.get(JmsHeaders.TYPE));
assertEquals("Missing custom header", 4567L, (long) headers.get("customLong"), 0.0);
}
public void resolveJmsMessageHeaderAccessor(JmsMessageHeaderAccessor headers) {
invocations.put("resolveJmsMessageHeaderAccessor", true);
assertNotNull("MessageHeaders not injected", headers);
assertEquals("Missing JMS message priority header", Integer.valueOf(9), headers.getPriority());
assertEquals("Missing custom header", true, headers.getHeader("customBoolean"));
}
public void resolveObjectPayload(MyBean bean) {
invocations.put("resolveObjectPayload", true);
assertNotNull("Object payload not injected", bean);
assertEquals("Wrong content for payload", "myBean name", bean.name);
}
public void resolveConvertedPayload(Integer counter) {
invocations.put("resolveConvertedPayload", true);
assertNotNull("Payload not injected", counter);
assertEquals("Wrong content for payload", Integer.valueOf(33), counter);
}
public String processAndReply(@Payload String content) {
invocations.put("processAndReply", true);
return content;
}
public void validatePayload(@Validated String payload) {
invocations.put("validatePayload", true);
}
public void invalidPayloadType(@Payload Integer payload) {
throw new IllegalStateException("Should never be called.");
}
public void invalidMessagePayloadType(Message<Integer> message) {
throw new IllegalStateException("Should never be called.");
}
}
@SuppressWarnings("serial")
static class MyBean implements Serializable {
private String name;
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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.
*/
package org.springframework.jms.config;
import static org.junit.Assert.*;
import javax.jms.MessageListener;
import org.junit.Test;
import org.springframework.jms.listener.SimpleMessageListenerContainer;
import org.springframework.jms.listener.adapter.MessageListenerAdapter;
/**
*
* @author Stephane Nicoll
*/
public class SimpleJmsListenerEndpointTests {
private final SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
@Test
public void createListener() {
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
MessageListener messageListener = new MessageListenerAdapter();
endpoint.setMessageListener(messageListener);
assertSame(messageListener, endpoint.createMessageListener(container));
}
}

View File

@@ -1,72 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-4.0.xsd">
<jms:listener-container connection-factory="testConnectionFactory" task-executor="testTaskExecutor"
destination-resolver="testDestinationResolver" message-converter="testMessageConverter"
transaction-manager="testTransactionManager" error-handler="testErrorHandler"
concurrency="1-2" prefetch="50" receive-timeout="100" recovery-interval="1000" phase="99">
<jms:listener id="listener1" destination="testDestination" ref="testBean1" method="setName"/>
<jms:listener id="listener2" destination="testDestination" ref="testBean2" method="setName" response-destination="responseDestination"/>
</jms:listener-container>
<!-- TODO: remove the task-executor reference once issue with blocking on stop is resolved -->
<jms:listener-container task-executor="testTaskExecutor" concurrency="${concurrency}">
<jms:listener destination="testDestination" ref="testBean3"/>
</jms:listener-container>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties">
<props>
<prop key="concurrency">2-3</prop>
</props>
</property>
</bean>
<jms:jca-listener-container resource-adapter="testResourceAdapter" activation-spec-factory="testActivationSpecFactory"
message-converter="testMessageConverter" phase="77">
<jms:listener id="listener3" destination="testDestination" ref="testBean1" method="setName"/>
<jms:listener id="listener4" destination="testDestination" ref="testBean2" method="setName" response-destination="responseDestination"/>
</jms:jca-listener-container>
<jms:jca-listener-container activation-spec-factory="testActivationSpecFactory">
<jms:listener destination="testDestination" ref="testBean3"/>
</jms:jca-listener-container>
<!-- the default ConnectionFactory -->
<bean id="connectionFactory" class="org.springframework.jms.StubConnectionFactory"/>
<bean id="testConnectionFactory" class="org.springframework.jms.StubConnectionFactory"/>
<!-- the default ResourceAdapter -->
<bean id="resourceAdapter" class="org.springframework.jca.StubResourceAdapter"/>
<bean id="testResourceAdapter" class="org.springframework.jca.StubResourceAdapter"/>
<bean id="testTaskExecutor" class="org.springframework.core.task.StubTaskExecutor"/>
<bean id="testActivationSpecFactory" class="org.springframework.jms.listener.endpoint.StubJmsActivationSpecFactory"/>
<bean id="testDestinationResolver" class="org.springframework.jms.support.destination.DynamicDestinationResolver"/>
<bean id="testMessageConverter" class="org.springframework.jms.support.converter.SimpleMessageConverter"/>
<bean id="testTransactionManager" class="org.springframework.tests.transaction.CallCountingTransactionManager"/>
<bean id="testErrorHandler" class="org.springframework.jms.config.JmsNamespaceHandlerTests$TestErrorHandler"/>
<bean id="testBean1" class="org.springframework.tests.sample.beans.TestBean"/>
<bean id="testBean2" class="org.springframework.tests.sample.beans.TestBean"/>
<bean id="testBean3" class="org.springframework.jms.config.JmsNamespaceHandlerTests$TestMessageListener"/>
<!-- TODO: remove this once issue with blocking on stop is resolved -->
<bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor">
<property name="timeoutPerShutdownPhase" value="0"/>
</bean>
</beans>

View File

@@ -0,0 +1,103 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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.
*/
package org.springframework.jms.listener.adapter;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import java.lang.reflect.Method;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.jms.StubTextMessage;
import org.springframework.jms.config.DefaultJmsHandlerMethodFactory;
import org.springframework.jms.support.converter.JmsHeaders;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.util.ReflectionUtils;
/**
*
* @author Stephane Nicoll
*/
public class MessagingMessageListenerAdapterTests {
private final DefaultJmsHandlerMethodFactory factory = new DefaultJmsHandlerMethodFactory();
private final SampleBean sample = new SampleBean();
@Before
public void setup() {
initializeFactory(factory);
}
@Test
public void buildMessageWithStandardMessage() throws JMSException {
Destination replyTo = new Destination() {};
Message<String> result = MessageBuilder.withPayload("Response")
.setHeader("foo", "bar")
.setHeader(JmsHeaders.TYPE, "msg_type")
.setHeader(JmsHeaders.REPLY_TO, replyTo)
.build();
Session session = mock(Session.class);
given(session.createTextMessage("Response")).willReturn(new StubTextMessage("Response"));
javax.jms.Message replyMessage = getSimpleInstance().buildMessage(session, result);
verify(session).createTextMessage("Response");
assertNotNull("reply should never be null", replyMessage);
assertEquals("Response", ((TextMessage) replyMessage).getText());
assertEquals("custom header not copied", "bar", replyMessage.getStringProperty("foo"));
assertEquals("type header not copied", "msg_type", replyMessage.getJMSType());
assertEquals("replyTo header not copied", replyTo, replyMessage.getJMSReplyTo());
}
protected MessagingMessageListenerAdapter getSimpleInstance() {
Method m = ReflectionUtils.findMethod(SampleBean.class, "echo", Message.class);
return createInstance(m);
}
protected MessagingMessageListenerAdapter createInstance(Method m) {
MessagingMessageListenerAdapter adapter = new MessagingMessageListenerAdapter();
adapter.setHandlerMethod(factory.createInvocableHandlerMethod(sample, m));
return adapter;
}
private void initializeFactory(DefaultJmsHandlerMethodFactory factory) {
factory.setApplicationContext(new StaticApplicationContext());
factory.afterPropertiesSet();
}
private static class SampleBean {
public Message<String> echo(Message<String> input) {
return MessageBuilder.withPayload(input.getPayload())
.setHeader(JmsHeaders.TYPE, "reply")
.build();
}
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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.
*/
package org.springframework.jms.support;
import static org.junit.Assert.*;
import java.util.Map;
import javax.jms.Destination;
import javax.jms.JMSException;
import org.junit.Test;
import org.springframework.jms.StubTextMessage;
import org.springframework.jms.support.converter.SimpleJmsHeaderMapper;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
/**
*
* @author Stephane Nicoll
*/
public class JmsMessageHeaderAccessorTests {
@Test
public void validateJmsHeaders() throws JMSException {
Destination destination = new Destination() {};
Destination replyTo = new Destination() {};
StubTextMessage jmsMessage = new StubTextMessage("test");
jmsMessage.setJMSCorrelationID("correlation-1234");
jmsMessage.setJMSPriority(9);
jmsMessage.setJMSDestination(destination);
jmsMessage.setJMSDeliveryMode(1);
jmsMessage.setJMSExpiration(1234L);
jmsMessage.setJMSMessageID("abcd-1234");
jmsMessage.setJMSPriority(9);
jmsMessage.setJMSReplyTo(replyTo);
jmsMessage.setJMSRedelivered(true);
jmsMessage.setJMSType("type");
jmsMessage.setJMSTimestamp(4567L);
Map<String, Object> mappedHeaders = new SimpleJmsHeaderMapper().toHeaders(jmsMessage);
Message<String> message = MessageBuilder.withPayload("test").copyHeaders(mappedHeaders).build();
JmsMessageHeaderAccessor headerAccessor = JmsMessageHeaderAccessor.wrap(message);
assertEquals("correlation-1234", headerAccessor.getCorrelationId());
assertEquals(destination, headerAccessor.getDestination());
assertEquals(Integer.valueOf(1), headerAccessor.getDeliveryMode());
assertEquals(1234L, headerAccessor.getExpiration(), 0.0);
assertEquals("abcd-1234", headerAccessor.getMessageId());
assertEquals(Integer.valueOf(9), headerAccessor.getPriority());
assertEquals(replyTo, headerAccessor.getReplyTo());
assertEquals(replyTo, headerAccessor.getReplyChannel());
assertEquals(true, headerAccessor.getRedelivered());
assertEquals("type", headerAccessor.getType());
assertEquals(4567L, headerAccessor.getTimestamp(), 0.0);
}
}

View File

@@ -0,0 +1,562 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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.
*/
package org.springframework.jms.support.converter;
import static org.junit.Assert.*;
import java.util.Date;
import java.util.Map;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import org.junit.Test;
import org.springframework.jms.StubTextMessage;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.support.MessageBuilder;
/**
*
* @author Mark Fisher
* @author Gary Russel
* @author Stephane Nicoll
*/
public class SimpleJmsHeaderMapperTests {
private final SimpleJmsHeaderMapper mapper = new SimpleJmsHeaderMapper();
// Outbound mapping
@Test
public void jmsReplyToMappedFromHeader() throws JMSException {
Destination replyTo = new Destination() {};
Message<String> message = initBuilder()
.setHeader(JmsHeaders.REPLY_TO, replyTo).build();
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.fromHeaders(message.getHeaders(), jmsMessage);
assertNotNull(jmsMessage.getJMSReplyTo());
assertSame(replyTo, jmsMessage.getJMSReplyTo());
}
@Test
public void JmsReplyToIgnoredIfIncorrectType() throws JMSException {
Message<String> message = initBuilder()
.setHeader(JmsHeaders.REPLY_TO, "not-a-destination").build();
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.fromHeaders(message.getHeaders(), jmsMessage);
assertNull(jmsMessage.getJMSReplyTo());
}
@Test
public void jmsCorrelationIdMappedFromHeader() throws JMSException {
String jmsCorrelationId = "ABC-123";
Message<String> message = initBuilder()
.setHeader(JmsHeaders.CORRELATION_ID, jmsCorrelationId).build();
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.fromHeaders(message.getHeaders(), jmsMessage);
assertNotNull(jmsMessage.getJMSCorrelationID());
assertEquals(jmsCorrelationId, jmsMessage.getJMSCorrelationID());
}
@Test
public void jmsCorrelationIdNumberConvertsToString() throws JMSException {
Message<String> message = initBuilder()
.setHeader(JmsHeaders.CORRELATION_ID, 123).build();
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.fromHeaders(message.getHeaders(), jmsMessage);
assertEquals("123", jmsMessage.getJMSCorrelationID());
}
@Test
public void jmsCorrelationIdIgnoredIfIncorrectType() throws JMSException {
Message<String> message = initBuilder()
.setHeader(JmsHeaders.CORRELATION_ID, new Date()).build();
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.fromHeaders(message.getHeaders(), jmsMessage);
assertNull(jmsMessage.getJMSCorrelationID());
}
@Test
public void jmsTypeMappedFromHeader() throws JMSException {
String jmsType = "testing";
Message<String> message = initBuilder()
.setHeader(JmsHeaders.TYPE, jmsType).build();
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.fromHeaders(message.getHeaders(), jmsMessage);
assertNotNull(jmsMessage.getJMSType());
assertEquals(jmsType, jmsMessage.getJMSType());
}
@Test
public void jmsTypeIgnoredIfIncorrectType() throws JMSException {
Message<String> message = initBuilder()
.setHeader(JmsHeaders.TYPE, 123).build();
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.fromHeaders(message.getHeaders(), jmsMessage);
assertNull(jmsMessage.getJMSType());
}
@Test
public void jmsReadOnlyPropertiesNotMapped() throws JMSException {
Message<String> message = initBuilder()
.setHeader(JmsHeaders.DESTINATION, new Destination() {})
.setHeader(JmsHeaders.DELIVERY_MODE, DeliveryMode.NON_PERSISTENT)
.setHeader(JmsHeaders.EXPIRATION, 1000L)
.setHeader(JmsHeaders.MESSAGE_ID, "abc-123")
.setHeader(JmsHeaders.PRIORITY, 9)
.setHeader(JmsHeaders.REDELIVERED, true)
.setHeader(JmsHeaders.TIMESTAMP, System.currentTimeMillis())
.build();
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.fromHeaders(message.getHeaders(), jmsMessage);
assertNull(jmsMessage.getJMSDestination());
assertEquals(DeliveryMode.PERSISTENT, jmsMessage.getJMSDeliveryMode());
assertEquals(0, jmsMessage.getJMSExpiration());
assertNull(jmsMessage.getJMSMessageID());
assertEquals(javax.jms.Message.DEFAULT_PRIORITY, jmsMessage.getJMSPriority());
assertFalse(jmsMessage.getJMSRedelivered());
assertEquals(0, jmsMessage.getJMSTimestamp());
}
@Test
public void contentTypePropertyMappedFromHeader() throws JMSException {
Message<String> message = initBuilder()
.setHeader(MessageHeaders.CONTENT_TYPE, "foo")
.build();
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.fromHeaders(message.getHeaders(), jmsMessage);
Object value = jmsMessage.getObjectProperty(JmsHeaderMapper.CONTENT_TYPE_PROPERTY);
assertNotNull(value);
assertEquals("foo", value);
}
@Test
public void userDefinedPropertyMappedFromHeader() throws JMSException {
Message<String> message = initBuilder()
.setHeader("foo", 123)
.build();
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.fromHeaders(message.getHeaders(), jmsMessage);
Object value = jmsMessage.getObjectProperty("foo");
assertNotNull(value);
assertEquals(Integer.class, value.getClass());
assertEquals(123, ((Integer) value).intValue());
}
@Test
public void userDefinedPropertyMappedFromHeaderWithCustomPrefix() throws JMSException {
Message<String> message = initBuilder()
.setHeader("foo", 123)
.build();
mapper.setOutboundPrefix("custom_");
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.fromHeaders(message.getHeaders(), jmsMessage);
Object value = jmsMessage.getObjectProperty("custom_foo");
assertNotNull(value);
assertEquals(Integer.class, value.getClass());
assertEquals(123, ((Integer) value).intValue());
}
@Test
public void userDefinedPropertyWithUnsupportedType() throws JMSException {
Destination destination = new Destination() {};
Message<String> message = initBuilder()
.setHeader("destination", destination)
.build();
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.fromHeaders(message.getHeaders(), jmsMessage);
Object value = jmsMessage.getObjectProperty("destination");
assertNull(value);
}
@Test
public void attemptToReadDisallowedCorrelationIdPropertyIsNotFatal() throws JMSException {
javax.jms.Message jmsMessage = new StubTextMessage() {
@Override
public String getJMSCorrelationID() throws JMSException {
throw new JMSException("illegal property");
}
};
assertAttemptReadDisallowedPropertyIsNotFatal(jmsMessage, JmsHeaders.CORRELATION_ID);
}
@Test
public void attemptToReadDisallowedDestinationPropertyIsNotFatal() throws JMSException {
javax.jms.Message jmsMessage = new StubTextMessage() {
@Override
public Destination getJMSDestination() throws JMSException {
throw new JMSException("illegal property");
}
};
assertAttemptReadDisallowedPropertyIsNotFatal(jmsMessage, JmsHeaders.DESTINATION);
}
@Test
public void attemptToReadDisallowedDeliveryModePropertyIsNotFatal() throws JMSException {
javax.jms.Message jmsMessage = new StubTextMessage() {
@Override
public int getJMSDeliveryMode() throws JMSException {
throw new JMSException("illegal property");
}
};
assertAttemptReadDisallowedPropertyIsNotFatal(jmsMessage, JmsHeaders.DELIVERY_MODE);
}
@Test
public void attemptToReadDisallowedExpirationPropertyIsNotFatal() throws JMSException {
javax.jms.Message jmsMessage = new StubTextMessage() {
@Override
public long getJMSExpiration() throws JMSException {
throw new JMSException("illegal property");
}
};
assertAttemptReadDisallowedPropertyIsNotFatal(jmsMessage, JmsHeaders.EXPIRATION);
}
@Test
public void attemptToReadDisallowedMessageIdPropertyIsNotFatal() throws JMSException {
javax.jms.Message jmsMessage = new StubTextMessage() {
@Override
public String getJMSMessageID() throws JMSException {
throw new JMSException("illegal property");
}
};
assertAttemptReadDisallowedPropertyIsNotFatal(jmsMessage, JmsHeaders.MESSAGE_ID);
}
@Test
public void attemptToReadDisallowedPriorityPropertyIsNotFatal() throws JMSException {
javax.jms.Message jmsMessage = new StubTextMessage() {
@Override
public int getJMSPriority() throws JMSException {
throw new JMSException("illegal property");
}
};
assertAttemptReadDisallowedPropertyIsNotFatal(jmsMessage, JmsHeaders.PRIORITY);
}
@Test
public void attemptToReadDisallowedReplyToPropertyIsNotFatal() throws JMSException {
javax.jms.Message jmsMessage = new StubTextMessage() {
@Override
public Destination getJMSReplyTo() throws JMSException {
throw new JMSException("illegal property");
}
};
assertAttemptReadDisallowedPropertyIsNotFatal(jmsMessage, JmsHeaders.REPLY_TO);
}
@Test
public void attemptToReadDisallowedRedeliveredPropertyIsNotFatal() throws JMSException {
javax.jms.Message jmsMessage = new StubTextMessage() {
@Override
public boolean getJMSRedelivered() throws JMSException {
throw new JMSException("illegal property");
}
};
assertAttemptReadDisallowedPropertyIsNotFatal(jmsMessage, JmsHeaders.REDELIVERED);
}
@Test
public void attemptToReadDisallowedTypePropertyIsNotFatal() throws JMSException {
javax.jms.Message jmsMessage = new StubTextMessage() {
@Override
public String getJMSType() throws JMSException {
throw new JMSException("illegal property");
}
};
assertAttemptReadDisallowedPropertyIsNotFatal(jmsMessage, JmsHeaders.TYPE);
}
@Test
public void attemptToReadDisallowedTimestampPropertyIsNotFatal() throws JMSException {
javax.jms.Message jmsMessage = new StubTextMessage() {
@Override
public long getJMSTimestamp() throws JMSException {
throw new JMSException("illegal property");
}
};
assertAttemptReadDisallowedPropertyIsNotFatal(jmsMessage, JmsHeaders.TIMESTAMP);
}
@Test
public void attemptToReadDisallowedUserPropertyIsNotFatal() throws JMSException {
javax.jms.Message jmsMessage = new StubTextMessage() {
@Override
public Object getObjectProperty(String name) throws JMSException {
if (name.equals("fail")) {
throw new JMSException("illegal property");
}
else {
return super.getObjectProperty(name);
}
}
};
jmsMessage.setBooleanProperty("fail", true);
assertAttemptReadDisallowedPropertyIsNotFatal(jmsMessage, "fail");
}
// Inbound mapping
@Test
public void jmsCorrelationIdMappedToHeader() throws JMSException {
String correlationId = "ABC-123";
javax.jms.Message jmsMessage = new StubTextMessage();
jmsMessage.setJMSCorrelationID(correlationId);
assertInboundHeader(jmsMessage, JmsHeaders.CORRELATION_ID, correlationId);
}
@Test
public void destinationMappedToHeader() throws JMSException {
Destination destination = new Destination() {};
javax.jms.Message jmsMessage = new StubTextMessage();
jmsMessage.setJMSDestination(destination);
assertInboundHeader(jmsMessage, JmsHeaders.DESTINATION, destination);
}
@Test
public void jmsDeliveryModeMappedToHeader() throws JMSException {
int deliveryMode = 1;
javax.jms.Message jmsMessage = new StubTextMessage();
jmsMessage.setJMSDeliveryMode(deliveryMode);
assertInboundHeader(jmsMessage, JmsHeaders.DELIVERY_MODE, deliveryMode);
}
@Test
public void jmsExpirationMappedToHeader() throws JMSException {
long expiration = 1000L;
javax.jms.Message jmsMessage = new StubTextMessage();
jmsMessage.setJMSExpiration(expiration);
assertInboundHeader(jmsMessage, JmsHeaders.EXPIRATION, expiration);
}
@Test
public void jmsMessageIdMappedToHeader() throws JMSException {
String messageId = "ID:ABC-123";
javax.jms.Message jmsMessage = new StubTextMessage();
jmsMessage.setJMSMessageID(messageId);
assertInboundHeader(jmsMessage, JmsHeaders.MESSAGE_ID, messageId);
}
@Test
public void jmsPriorityMappedToHeader() throws JMSException {
int priority = 8;
javax.jms.Message jmsMessage = new StubTextMessage();
jmsMessage.setJMSPriority(priority);
assertInboundHeader(jmsMessage, JmsHeaders.PRIORITY, priority);
}
@Test
public void jmsReplyToMappedToHeader() throws JMSException {
Destination replyTo = new Destination() {};
javax.jms.Message jmsMessage = new StubTextMessage();
jmsMessage.setJMSReplyTo(replyTo);
assertInboundHeader(jmsMessage, JmsHeaders.REPLY_TO, replyTo);
}
@Test
public void jmsTypeMappedToHeader() throws JMSException {
String type = "testing";
javax.jms.Message jmsMessage = new StubTextMessage();
jmsMessage.setJMSType(type);
assertInboundHeader(jmsMessage, JmsHeaders.TYPE, type);
}
@Test
public void jmsTimestampMappedToHeader() throws JMSException {
long timestamp = 123L;
javax.jms.Message jmsMessage = new StubTextMessage();
jmsMessage.setJMSTimestamp(timestamp);
assertInboundHeader(jmsMessage, JmsHeaders.TIMESTAMP, timestamp);
}
@Test
public void contentTypePropertyMappedToHeader() throws JMSException {
javax.jms.Message jmsMessage = new StubTextMessage();
jmsMessage.setStringProperty("content_type", "foo");
assertInboundHeader(jmsMessage, MessageHeaders.CONTENT_TYPE, "foo");
}
@Test
public void userDefinedPropertyMappedToHeader() throws JMSException {
javax.jms.Message jmsMessage = new StubTextMessage();
jmsMessage.setIntProperty("foo", 123);
assertInboundHeader(jmsMessage, "foo", 123);
}
@Test
public void userDefinedPropertyMappedToHeaderWithCustomPrefix() throws JMSException {
javax.jms.Message jmsMessage = new StubTextMessage();
jmsMessage.setIntProperty("foo", 123);
mapper.setInboundPrefix("custom_");
assertInboundHeader(jmsMessage, "custom_foo", 123);
}
@Test
public void propertyMappingExceptionIsNotFatal() throws JMSException {
Message<String> message = initBuilder()
.setHeader("foo", 123)
.setHeader("bad", 456)
.setHeader("bar", 789)
.build();
javax.jms.Message jmsMessage = new StubTextMessage() {
@Override
public void setObjectProperty(String name, Object value) throws JMSException {
if (name.equals("bad")) {
throw new JMSException("illegal property");
}
super.setObjectProperty(name, value);
}
};
mapper.fromHeaders(message.getHeaders(), jmsMessage);
Object foo = jmsMessage.getObjectProperty("foo");
assertNotNull(foo);
Object bar = jmsMessage.getObjectProperty("bar");
assertNotNull(bar);
Object bad = jmsMessage.getObjectProperty("bad");
assertNull(bad);
}
@Test
public void illegalArgumentExceptionIsNotFatal() throws JMSException {
Message<String> message = initBuilder()
.setHeader("foo", 123)
.setHeader("bad", 456)
.setHeader("bar", 789)
.build();
javax.jms.Message jmsMessage = new StubTextMessage() {
@Override
public void setObjectProperty(String name, Object value) throws JMSException {
if (name.equals("bad")) {
throw new IllegalArgumentException("illegal property");
}
super.setObjectProperty(name, value);
}
};
mapper.fromHeaders(message.getHeaders(), jmsMessage);
Object foo = jmsMessage.getObjectProperty("foo");
assertNotNull(foo);
Object bar = jmsMessage.getObjectProperty("bar");
assertNotNull(bar);
Object bad = jmsMessage.getObjectProperty("bad");
assertNull(bad);
}
@Test
public void attemptToWriteDisallowedReplyToPropertyIsNotFatal() throws JMSException {
Message<String> message = initBuilder()
.setHeader(JmsHeaders.REPLY_TO, new Destination() {})
.setHeader("foo", "bar")
.build();
javax.jms.Message jmsMessage = new StubTextMessage() {
@Override
public void setJMSReplyTo(Destination replyTo) throws JMSException {
throw new JMSException("illegal property");
}
};
mapper.fromHeaders(message.getHeaders(), jmsMessage);
assertNull(jmsMessage.getJMSReplyTo());
assertNotNull(jmsMessage.getStringProperty("foo"));
assertEquals("bar", jmsMessage.getStringProperty("foo"));
}
@Test
public void attemptToWriteDisallowedTypePropertyIsNotFatal() throws JMSException {
Message<String> message = initBuilder()
.setHeader(JmsHeaders.TYPE, "someType")
.setHeader("foo", "bar")
.build();
javax.jms.Message jmsMessage = new StubTextMessage() {
@Override
public void setJMSType(String type) throws JMSException {
throw new JMSException("illegal property");
}
};
mapper.fromHeaders(message.getHeaders(), jmsMessage);
assertNull(jmsMessage.getJMSType());
assertNotNull(jmsMessage.getStringProperty("foo"));
assertEquals("bar", jmsMessage.getStringProperty("foo"));
}
@Test
public void attemptToWriteDisallowedCorrelationIdStringPropertyIsNotFatal() throws JMSException {
Message<String> message = initBuilder()
.setHeader(JmsHeaders.CORRELATION_ID, "abc")
.setHeader("foo", "bar")
.build();
javax.jms.Message jmsMessage = new StubTextMessage() {
@Override
public void setJMSCorrelationID(String correlationId) throws JMSException {
throw new JMSException("illegal property");
}
};
mapper.fromHeaders(message.getHeaders(), jmsMessage);
assertNull(jmsMessage.getJMSCorrelationID());
assertNotNull(jmsMessage.getStringProperty("foo"));
assertEquals("bar", jmsMessage.getStringProperty("foo"));
}
@Test
public void attemptToWriteDisallowedCorrelationIdNumberPropertyIsNotFatal() throws JMSException {
Message<String> message = initBuilder()
.setHeader(JmsHeaders.CORRELATION_ID, 123)
.setHeader("foo", "bar")
.build();
javax.jms.Message jmsMessage = new StubTextMessage() {
@Override
public void setJMSCorrelationID(String correlationId) throws JMSException {
throw new JMSException("illegal property");
}
};
mapper.fromHeaders(message.getHeaders(), jmsMessage);
assertNull(jmsMessage.getJMSCorrelationID());
assertNotNull(jmsMessage.getStringProperty("foo"));
assertEquals("bar", jmsMessage.getStringProperty("foo"));
}
private void assertInboundHeader(javax.jms.Message jmsMessage, String headerId, Object value) {
Map<String, Object> headers = mapper.toHeaders(jmsMessage);
Object headerValue = headers.get(headerId);
if (value == null) {
assertNull(headerValue);
}
else {
assertNotNull(headerValue);
assertEquals(value.getClass(), headerValue.getClass());
assertEquals(value, headerValue);
}
}
private void assertAttemptReadDisallowedPropertyIsNotFatal(javax.jms.Message jmsMessage, String headerId)
throws JMSException {
jmsMessage.setStringProperty("foo", "bar");
Map<String, Object> headers = mapper.toHeaders(jmsMessage);
assertNull(headers.get(headerId));
assertNotNull(headers.get("foo"));
assertEquals("bar", headers.get("foo"));
}
private MessageBuilder<String> initBuilder() {
return MessageBuilder.withPayload("test");
}
}