polishing

This commit removes the queue attribute of the JmsListener annotation
as this information should be provided by the container factory and not
by each individual listener endpoints.

There was a side effect that an annotation value cannot be null, which
was forcing the container to be a queue-based container by default.

Issue: SPR-9882
This commit is contained in:
Stephane Nicoll
2014-04-24 16:56:51 +03:00
parent c4843577ba
commit 6aa16b745f
13 changed files with 118 additions and 59 deletions

View File

@@ -96,12 +96,6 @@ public @interface JmsListener {
*/
String destination();
/**
* Specify if the {@link #destination()} refers to a queue or not. Refer to a
* queue by default.
*/
boolean queue() default true;
/**
* The name for the durable subscription, if any.
*/

View File

@@ -175,7 +175,6 @@ public class JmsListenerAnnotationBeanPostProcessor implements BeanPostProcessor
endpoint.setJmsHandlerMethodFactory(jmsHandlerMethodFactory);
endpoint.setId(getEndpointId(jmsListener));
endpoint.setDestination(jmsListener.destination());
endpoint.setQueue(jmsListener.queue());
if (StringUtils.hasText(jmsListener.selector())) {
endpoint.setSelector(jmsListener.selector());
}

View File

@@ -38,8 +38,6 @@ public abstract class AbstractJmsListenerEndpoint implements JmsListenerEndpoint
private String destination;
private boolean queue = true;
private String subscription;
private String selector;
@@ -68,20 +66,6 @@ public abstract class AbstractJmsListenerEndpoint implements JmsListenerEndpoint
this.destination = destination;
}
/**
* Return {@code true} if the destination is a queue.
*/
public boolean isQueue() {
return queue;
}
/**
* Specify if the destination is a queue.
*/
public void setQueue(boolean queue) {
this.queue = queue;
}
/**
* Return the name for the durable subscription, if any.
*/
@@ -136,7 +120,6 @@ public abstract class AbstractJmsListenerEndpoint implements JmsListenerEndpoint
if (getSelector() != null) {
container.setMessageSelector(getSelector());
}
container.setPubSubDomain(!isQueue());
setupMessageListener(container);
}
@@ -156,7 +139,6 @@ public abstract class AbstractJmsListenerEndpoint implements JmsListenerEndpoint
if (getSelector() != null) {
activationSpecConfig.setMessageSelector(getSelector());
}
activationSpecConfig.setPubSubDomain(!isQueue());
setupMessageListener(container);
}
@@ -183,8 +165,6 @@ public abstract class AbstractJmsListenerEndpoint implements JmsListenerEndpoint
.append(this.id)
.append("] destination=")
.append(this.destination)
.append(" | queue='")
.append(this.queue)
.append("' | subscription='")
.append(this.subscription)
.append(" | selector='")

View File

@@ -85,11 +85,11 @@ public class MethodJmsListenerEndpoint extends AbstractJmsListenerEndpoint {
messageListener.setHandlerMethod(invocableHandlerMethod);
String responseDestination = getDefaultResponseDestination();
if (StringUtils.hasText(responseDestination)) {
if (isQueue()) {
messageListener.setDefaultResponseQueueName(responseDestination);
if (container.isPubSubDomain()) {
messageListener.setDefaultResponseTopicName(responseDestination);
}
else {
messageListener.setDefaultResponseTopicName(responseDestination);
messageListener.setDefaultResponseQueueName(responseDestination);
}
}
MessageConverter messageConverter = container.getMessageConverter();

View File

@@ -41,4 +41,10 @@ public interface MessageListenerContainer extends Lifecycle {
*/
MessageConverter getMessageConverter();
/**
* Return whether the Publish/Subscribe domain ({@link javax.jms.Topic Topics}) is used.
* Otherwise, the Point-to-Point domain ({@link javax.jms.Queue Queues}) is used.
*/
boolean isPubSubDomain();
}

View File

@@ -156,6 +156,15 @@ public class JmsMessageEndpointManager extends GenericMessageEndpointManager
return null;
}
@Override
public boolean isPubSubDomain() {
JmsActivationSpecConfig config = getActivationSpecConfig();
if (config != null) {
return config.isPubSubDomain();
}
throw new IllegalStateException("could not determine pubSubDomain, no activation spec config is set");
}
/**
* Set the name of this message endpoint. Populated with the bean name
* automatically when defined within Spring's bean factory.

View File

@@ -105,7 +105,6 @@ public abstract class AbstractJmsAnnotationDrivenTests {
simpleFactory.getContainers().get(0).getEndpoint();
assertEquals("listener1", endpoint.getId());
assertEquals("queueIn", endpoint.getDestination());
assertTrue(endpoint.isQueue());
assertEquals("mySelector", endpoint.getSelector());
assertEquals("mySubscription", endpoint.getSubscription());
}

View File

@@ -58,7 +58,6 @@ public class JmsListenerAnnotationBeanPostProcessorTests {
MethodJmsListenerEndpoint methodEndpoint = (MethodJmsListenerEndpoint) endpoint;
assertNotNull(methodEndpoint.getBean());
assertNotNull(methodEndpoint.getMethod());
assertTrue(methodEndpoint.isQueue());
assertTrue("Should have been started " + container, container.isStarted());
SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer();

View File

@@ -67,7 +67,6 @@ public class JmsListenerContainerFactoryTests {
MessageListener messageListener = new MessageListenerAdapter();
endpoint.setMessageListener(messageListener);
endpoint.setDestination("myQueue");
endpoint.setQueue(false); // See #setDefaultJmsConfig
SimpleMessageListenerContainer container = factory.createMessageListenerContainer(endpoint);
@@ -89,7 +88,6 @@ public class JmsListenerContainerFactoryTests {
MessageListener messageListener = new MessageListenerAdapter();
endpoint.setMessageListener(messageListener);
endpoint.setDestination("myQueue");
endpoint.setQueue(false); // See #setDefaultJmsConfig
DefaultMessageListenerContainer container = factory.createMessageListenerContainer(endpoint);
assertDefaultJmsConfig(container);
@@ -112,7 +110,6 @@ public class JmsListenerContainerFactoryTests {
MessageListener messageListener = new MessageListenerAdapter();
endpoint.setMessageListener(messageListener);
endpoint.setDestination("myQueue");
endpoint.setQueue(false); // See #setDefaultJmsConfig
JmsMessageEndpointManager container = factory.createMessageListenerContainer(endpoint);
assertDefaultJcaConfig(container);
@@ -121,19 +118,6 @@ public class JmsListenerContainerFactoryTests {
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();

View File

@@ -46,14 +46,12 @@ public class JmsListenerEndpointTests {
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());
@@ -65,7 +63,6 @@ public class JmsListenerEndpointTests {
MessageListener messageListener = new MessageListenerAdapter();
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setDestination("myQueue");
endpoint.setQueue(true);
endpoint.setSelector("foo = 'bar'");
endpoint.setSubscription("mySubscription");
endpoint.setMessageListener(messageListener);
@@ -73,7 +70,6 @@ public class JmsListenerEndpointTests {
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());

View File

@@ -86,6 +86,11 @@ public class MessageListenerTestContainer
return null;
}
@Override
public boolean isPubSubDomain() {
return true;
}
@Override
public void afterPropertiesSet() {
if (!startInvoked) {

View File

@@ -44,6 +44,7 @@ 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.MessageListenerContainer;
import org.springframework.jms.listener.SimpleMessageListenerContainer;
import org.springframework.jms.listener.adapter.ListenerExecutionFailedException;
import org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter;
@@ -220,8 +221,27 @@ public class MethodJmsListenerEndpointTests {
}
@Test
public void processAndReplyWithSendTo() throws JMSException {
MessagingMessageListenerAdapter listener = createDefaultInstance(String.class);
public void processAndReplyWithSendToQueue() throws JMSException {
String methodName = "processAndReplyWithSendTo";
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
MessagingMessageListenerAdapter listener = createInstance(this.factory,
getListenerMethod(methodName, String.class), container);
processAndReplyWithSendTo(listener, false);
assertListenerMethodInvocation(sample, methodName);
}
@Test
public void processAndReplyWithSendToTopic() throws JMSException {
String methodName = "processAndReplyWithSendTo";
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setPubSubDomain(true);
MessagingMessageListenerAdapter listener = createInstance(this.factory,
getListenerMethod(methodName, String.class), container);
processAndReplyWithSendTo(listener, true);
assertListenerMethodInvocation(sample, methodName);
}
private void processAndReplyWithSendTo(MessagingMessageListenerAdapter listener, boolean pubSubDomain) throws JMSException {
String body = "echo text";
String correlationId = "link-1234";
Destination replyDestination = new Destination() {};
@@ -231,7 +251,7 @@ public class MethodJmsListenerEndpointTests {
QueueSender queueSender = mock(QueueSender.class);
Session session = mock(Session.class);
given(destinationResolver.resolveDestinationName(session, "replyDestination", false))
given(destinationResolver.resolveDestinationName(session, "replyDestination", pubSubDomain))
.willReturn(replyDestination);
given(session.createTextMessage(body)).willReturn(reply);
given(session.createProducer(replyDestination)).willReturn(queueSender);
@@ -240,9 +260,8 @@ public class MethodJmsListenerEndpointTests {
StubTextMessage inputMessage = createSimpleJmsTextMessage(body);
inputMessage.setJMSCorrelationID(correlationId);
listener.onMessage(inputMessage, session);
assertDefaultListenerMethodInvocation();
verify(destinationResolver).resolveDestinationName(session, "replyDestination", false);
verify(destinationResolver).resolveDestinationName(session, "replyDestination", pubSubDomain);
verify(reply).setJMSCorrelationID(correlationId);
verify(queueSender).send(reply);
verify(queueSender).close();
@@ -322,12 +341,17 @@ public class MethodJmsListenerEndpointTests {
}
private MessagingMessageListenerAdapter createInstance(
DefaultJmsHandlerMethodFactory factory, Method method) {
DefaultJmsHandlerMethodFactory factory, Method method, MessageListenerContainer container) {
MethodJmsListenerEndpoint endpoint = new MethodJmsListenerEndpoint();
endpoint.setBean(sample);
endpoint.setMethod(method);
endpoint.setJmsHandlerMethodFactory(factory);
return endpoint.createMessageListener(new SimpleMessageListenerContainer());
return endpoint.createMessageListener(container);
}
private MessagingMessageListenerAdapter createInstance(
DefaultJmsHandlerMethodFactory factory, Method method) {
return createInstance(factory, method, new SimpleMessageListenerContainer());
}
private MessagingMessageListenerAdapter createDefaultInstance(Class<?>... parameterTypes) {

View File

@@ -0,0 +1,64 @@
/*
* 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.endpoint;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
/**
* @author Stephane Nicoll
*/
public class JmsMessageEndpointManagerTests {
@Rule
public final ExpectedException thrown = ExpectedException.none();
@Test
public void isPubSubDomainWithQueue() {
JmsMessageEndpointManager endpoint = new JmsMessageEndpointManager();
JmsActivationSpecConfig config = new JmsActivationSpecConfig();
config.setPubSubDomain(false);
endpoint.setActivationSpecConfig(config);
assertEquals(false, endpoint.isPubSubDomain());
}
@Test
public void isPubSubDomainWithTopic() {
JmsMessageEndpointManager endpoint = new JmsMessageEndpointManager();
JmsActivationSpecConfig config = new JmsActivationSpecConfig();
config.setPubSubDomain(true);
endpoint.setActivationSpecConfig(config);
assertEquals(true, endpoint.isPubSubDomain());
}
@Test
public void isPubSubDomainWithNoConfig() {
JmsMessageEndpointManager endpoint = new JmsMessageEndpointManager();
thrown.expect(IllegalStateException.class); // far from ideal
endpoint.isPubSubDomain();
}
@Test
public void getMessageConverterNoConfig() {
JmsMessageEndpointManager endpoint = new JmsMessageEndpointManager();
assertNull(endpoint.getMessageConverter());
}
}