Move JmsHandlerMethodFactory to spring-messaging

This commit moves JmsHandlerMethodFactory and its default
implementation to the messaging abstraction. Working on a similar
support for AMQP revealed that this factory has nothing that is JMS
specific and is exactly identical in the case of AMQP.

Issue: SPR-12053
This commit is contained in:
Stephane Nicoll
2014-08-01 16:08:31 +02:00
parent 25decee1a4
commit 7d1e33d88d
15 changed files with 148 additions and 104 deletions

View File

@@ -184,7 +184,7 @@ public abstract class AbstractJmsAnnotationDrivenTests {
/**
* Test for {@link ValidationBean} with a validator ({@link TestValidator}) specified
* in a custom {@link org.springframework.jms.config.DefaultJmsHandlerMethodFactory}.
* in a custom {@link org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory}.
*
* The test should throw a {@link org.springframework.jms.listener.adapter.ListenerExecutionFailedException}
*/

View File

@@ -25,14 +25,12 @@ 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.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory;
import org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory;
import org.springframework.jms.config.JmsListenerContainerTestFactory;
import org.springframework.jms.config.JmsListenerEndpointRegistrar;
import org.springframework.jms.config.JmsListenerEndpointRegistry;
@@ -42,7 +40,6 @@ import org.springframework.jms.listener.adapter.MessageListenerAdapter;
import org.springframework.messaging.handler.annotation.support.MethodArgumentNotValidException;
/**
*
* @author Stephane Nicoll
*/
public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
@@ -202,12 +199,12 @@ public class EnableJmsTests extends AbstractJmsAnnotationDrivenTests {
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
registrar.setJmsHandlerMethodFactory(jmsHandlerMethodFactory());
registrar.setMessageHandlerMethodFactory(customMessageHandlerMethodFactory());
}
@Bean
public JmsHandlerMethodFactory jmsHandlerMethodFactory() {
DefaultJmsHandlerMethodFactory factory = new DefaultJmsHandlerMethodFactory();
public MessageHandlerMethodFactory customMessageHandlerMethodFactory() {
DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
factory.setValidator(new TestValidator());
return factory;
}

View File

@@ -1,201 +0,0 @@
/*
* 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.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.beans.factory.support.StaticListableBeanFactory;
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;
import static org.junit.Assert.*;
/**
* @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.setBeanFactory(new StaticListableBeanFactory());
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

@@ -36,6 +36,7 @@ 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.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory;
import org.springframework.util.ReflectionUtils;
import static org.junit.Assert.*;
@@ -48,7 +49,7 @@ public class JmsListenerContainerFactoryIntegrationTests {
private final DefaultJmsListenerContainerFactory containerFactory = new DefaultJmsListenerContainerFactory();
private final DefaultJmsHandlerMethodFactory factory = new DefaultJmsHandlerMethodFactory();
private final DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
private final JmsEndpointSampleBean sample = new JmsEndpointSampleBean();
@@ -88,11 +89,11 @@ public class JmsListenerContainerFactoryIntegrationTests {
private MethodJmsListenerEndpoint createMethodJmsEndpoint(
DefaultJmsHandlerMethodFactory factory, Method method) {
DefaultMessageHandlerMethodFactory factory, Method method) {
MethodJmsListenerEndpoint endpoint = new MethodJmsListenerEndpoint();
endpoint.setBean(sample);
endpoint.setMethod(method);
endpoint.setJmsHandlerMethodFactory(factory);
endpoint.setMessageHandlerMethodFactory(factory);
return endpoint;
}
@@ -107,7 +108,7 @@ public class JmsListenerContainerFactoryIntegrationTests {
}
private void initializeFactory(DefaultJmsHandlerMethodFactory factory) {
private void initializeFactory(DefaultMessageHandlerMethodFactory factory) {
factory.setBeanFactory(new StaticListableBeanFactory());
factory.afterPropertiesSet();
}

View File

@@ -55,6 +55,7 @@ import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.handler.annotation.support.MethodArgumentTypeMismatchException;
import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory;
import org.springframework.util.ReflectionUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
@@ -76,7 +77,7 @@ public class MethodJmsListenerEndpointTests {
@Rule
public final ExpectedException thrown = ExpectedException.none();
private final DefaultJmsHandlerMethodFactory factory = new DefaultJmsHandlerMethodFactory();
private final DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
private final DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
@@ -103,7 +104,7 @@ public class MethodJmsListenerEndpointTests {
MethodJmsListenerEndpoint endpoint = new MethodJmsListenerEndpoint();
endpoint.setBean(this);
endpoint.setMethod(getTestMethod());
endpoint.setJmsHandlerMethodFactory(factory);
endpoint.setMessageHandlerMethodFactory(factory);
assertNotNull(endpoint.createMessageListener(container));
}
@@ -304,7 +305,7 @@ public class MethodJmsListenerEndpointTests {
public void validatePayloadValid() throws JMSException {
String methodName = "validatePayload";
DefaultJmsHandlerMethodFactory customFactory = new DefaultJmsHandlerMethodFactory();
DefaultMessageHandlerMethodFactory customFactory = new DefaultMessageHandlerMethodFactory();
customFactory.setValidator(testValidator("invalid value"));
initializeFactory(customFactory);
@@ -317,7 +318,7 @@ public class MethodJmsListenerEndpointTests {
@Test
public void validatePayloadInvalid() throws JMSException {
DefaultJmsHandlerMethodFactory customFactory = new DefaultJmsHandlerMethodFactory();
DefaultMessageHandlerMethodFactory customFactory = new DefaultMessageHandlerMethodFactory();
customFactory.setValidator(testValidator("invalid value"));
Method method = getListenerMethod("validatePayload", String.class);
@@ -353,16 +354,16 @@ public class MethodJmsListenerEndpointTests {
}
private MessagingMessageListenerAdapter createInstance(
DefaultJmsHandlerMethodFactory factory, Method method, MessageListenerContainer container) {
DefaultMessageHandlerMethodFactory factory, Method method, MessageListenerContainer container) {
MethodJmsListenerEndpoint endpoint = new MethodJmsListenerEndpoint();
endpoint.setBean(sample);
endpoint.setMethod(method);
endpoint.setJmsHandlerMethodFactory(factory);
endpoint.setMessageHandlerMethodFactory(factory);
return endpoint.createMessageListener(container);
}
private MessagingMessageListenerAdapter createInstance(
DefaultJmsHandlerMethodFactory factory, Method method) {
DefaultMessageHandlerMethodFactory factory, Method method) {
return createInstance(factory, method, new SimpleMessageListenerContainer());
}
@@ -392,7 +393,7 @@ public class MethodJmsListenerEndpointTests {
assertTrue("Method " + methodName + " should have been invoked", bean.invocations.get(methodName));
}
private void initializeFactory(DefaultJmsHandlerMethodFactory factory) {
private void initializeFactory(DefaultMessageHandlerMethodFactory factory) {
factory.setBeanFactory(new StaticListableBeanFactory());
factory.afterPropertiesSet();
}

View File

@@ -27,7 +27,7 @@ import org.junit.Test;
import org.springframework.beans.factory.support.StaticListableBeanFactory;
import org.springframework.jms.StubTextMessage;
import org.springframework.jms.config.DefaultJmsHandlerMethodFactory;
import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory;
import org.springframework.jms.support.JmsHeaders;
import org.springframework.messaging.Message;
import org.springframework.messaging.converter.MessageConversionException;
@@ -42,7 +42,7 @@ import static org.mockito.BDDMockito.*;
*/
public class MessagingMessageListenerAdapterTests {
private final DefaultJmsHandlerMethodFactory factory = new DefaultJmsHandlerMethodFactory();
private final DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
private final SampleBean sample = new SampleBean();
@@ -122,7 +122,7 @@ public class MessagingMessageListenerAdapterTests {
return adapter;
}
private void initializeFactory(DefaultJmsHandlerMethodFactory factory) {
private void initializeFactory(DefaultMessageHandlerMethodFactory factory) {
factory.setBeanFactory(new StaticListableBeanFactory());
factory.afterPropertiesSet();
}