Consistent use of @Nullable across the codebase (even for internals)
Beyond just formally declaring the current behavior, this revision actually enforces non-null behavior in selected signatures now, not tolerating null values anymore when not explicitly documented. It also changes some utility methods with historic null-in/null-out tolerance towards enforced non-null return values, making them a proper citizen in non-null assignments. Some issues are left as to-do: in particular a thorough revision of spring-test, and a few tests with unclear failures (ignored as "TODO: NULLABLE") to be sorted out in a follow-up commit. Issue: SPR-15540
This commit is contained in:
@@ -47,7 +47,7 @@ public abstract class JmsException extends NestedRuntimeException {
|
||||
* expected to be a proper subclass of {@link javax.jms.JMSException},
|
||||
* but can also be a JNDI NamingException or the like.
|
||||
*/
|
||||
public JmsException(String msg, Throwable cause) {
|
||||
public JmsException(String msg, @Nullable Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public abstract class JmsException extends NestedRuntimeException {
|
||||
* @param cause the cause of the exception. This argument is generally
|
||||
* expected to be a proper subclass of {@link javax.jms.JMSException}.
|
||||
*/
|
||||
public JmsException(Throwable cause) {
|
||||
public JmsException(@Nullable Throwable cause) {
|
||||
super(cause != null ? cause.getMessage() : null, cause);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.springframework.jms.config.JmsListenerContainerFactory;
|
||||
import org.springframework.jms.config.JmsListenerEndpointRegistrar;
|
||||
import org.springframework.jms.config.JmsListenerEndpointRegistry;
|
||||
import org.springframework.jms.config.MethodJmsListenerEndpoint;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory;
|
||||
import org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory;
|
||||
import org.springframework.messaging.handler.invocation.InvocableHandlerMethod;
|
||||
@@ -211,13 +212,10 @@ public class JmsListenerAnnotationBeanPostProcessor
|
||||
if (!this.nonAnnotatedClasses.contains(bean.getClass())) {
|
||||
Class<?> targetClass = AopUtils.getTargetClass(bean);
|
||||
Map<Method, Set<JmsListener>> annotatedMethods = MethodIntrospector.selectMethods(targetClass,
|
||||
new MethodIntrospector.MetadataLookup<Set<JmsListener>>() {
|
||||
@Override
|
||||
public Set<JmsListener> inspect(Method method) {
|
||||
Set<JmsListener> listenerMethods = AnnotatedElementUtils.getMergedRepeatableAnnotations(
|
||||
method, JmsListener.class, JmsListeners.class);
|
||||
return (!listenerMethods.isEmpty() ? listenerMethods : null);
|
||||
}
|
||||
(MethodIntrospector.MetadataLookup<Set<JmsListener>>) method -> {
|
||||
Set<JmsListener> listenerMethods = AnnotatedElementUtils.getMergedRepeatableAnnotations(
|
||||
method, JmsListener.class, JmsListeners.class);
|
||||
return (!listenerMethods.isEmpty() ? listenerMethods : null);
|
||||
});
|
||||
if (annotatedMethods.isEmpty()) {
|
||||
this.nonAnnotatedClasses.add(bean.getClass());
|
||||
@@ -301,6 +299,7 @@ public class JmsListenerAnnotationBeanPostProcessor
|
||||
return new MethodJmsListenerEndpoint();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getEndpointId(JmsListener jmsListener) {
|
||||
if (StringUtils.hasText(jmsListener.id())) {
|
||||
return resolve(jmsListener.id());
|
||||
@@ -310,6 +309,7 @@ public class JmsListenerAnnotationBeanPostProcessor
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String resolve(String value) {
|
||||
return (this.embeddedValueResolver != null ? this.embeddedValueResolver.resolveStringValue(value) : value);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public abstract class AbstractJmsListenerEndpoint implements JmsListenerEndpoint
|
||||
private String concurrency;
|
||||
|
||||
|
||||
public void setId(String id) {
|
||||
public void setId(@Nullable String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public abstract class AbstractJmsListenerEndpoint implements JmsListenerEndpoint
|
||||
/**
|
||||
* Set the name of the destination for this endpoint.
|
||||
*/
|
||||
public void setDestination(String destination) {
|
||||
public void setDestination(@Nullable String destination) {
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public abstract class AbstractJmsListenerEndpoint implements JmsListenerEndpoint
|
||||
/**
|
||||
* Set the name for the durable subscription.
|
||||
*/
|
||||
public void setSubscription(String subscription) {
|
||||
public void setSubscription(@Nullable String subscription) {
|
||||
this.subscription = subscription;
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ public abstract class AbstractJmsListenerEndpoint implements JmsListenerEndpoint
|
||||
* Set the JMS message selector expression.
|
||||
* <p>See the JMS specification for a detailed definition of selector expressions.
|
||||
*/
|
||||
public void setSelector(String selector) {
|
||||
public void setSelector(@Nullable String selector) {
|
||||
this.selector = selector;
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ public abstract class AbstractJmsListenerEndpoint implements JmsListenerEndpoint
|
||||
* <p>The underlying container may or may not support all features. For instance, it
|
||||
* may not be able to scale: in that case only the upper value is used.
|
||||
*/
|
||||
public void setConcurrency(String concurrency) {
|
||||
public void setConcurrency(@Nullable String concurrency) {
|
||||
this.concurrency = concurrency;
|
||||
}
|
||||
|
||||
@@ -154,11 +154,7 @@ public abstract class AbstractJmsListenerEndpoint implements JmsListenerEndpoint
|
||||
protected abstract MessageListener createMessageListener(MessageListenerContainer container);
|
||||
|
||||
private void setupMessageListener(MessageListenerContainer container) {
|
||||
MessageListener messageListener = createMessageListener(container);
|
||||
if (messageListener == null) {
|
||||
throw new IllegalStateException("Endpoint [" + this + "] must provide a non-null message listener");
|
||||
}
|
||||
container.setupMessageListener(messageListener);
|
||||
container.setupMessageListener(createMessageListener(container));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -108,8 +108,8 @@ abstract class AbstractListenerContainerParser implements BeanDefinitionParser {
|
||||
new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
|
||||
parserContext.pushContainingComponent(compositeDef);
|
||||
|
||||
PropertyValues commonProperties = parseCommonContainerProperties(element, parserContext);
|
||||
PropertyValues specificProperties = parseSpecificContainerProperties(element, parserContext);
|
||||
MutablePropertyValues commonProperties = parseCommonContainerProperties(element, parserContext);
|
||||
MutablePropertyValues specificProperties = parseSpecificContainerProperties(element, parserContext);
|
||||
|
||||
String factoryId = element.getAttribute(FACTORY_ID_ATTRIBUTE);
|
||||
if (StringUtils.hasText(factoryId)) {
|
||||
@@ -137,7 +137,7 @@ abstract class AbstractListenerContainerParser implements BeanDefinitionParser {
|
||||
}
|
||||
|
||||
private void parseListener(Element containerEle, Element listenerEle, ParserContext parserContext,
|
||||
PropertyValues commonContainerProperties, PropertyValues specificContainerProperties) {
|
||||
MutablePropertyValues commonContainerProperties, PropertyValues specificContainerProperties) {
|
||||
|
||||
RootBeanDefinition listenerDef = new RootBeanDefinition();
|
||||
listenerDef.setSource(parserContext.extractSource(listenerEle));
|
||||
@@ -152,15 +152,14 @@ abstract class AbstractListenerContainerParser implements BeanDefinitionParser {
|
||||
listenerDef.getPropertyValues().add("delegate", new RuntimeBeanReference(ref));
|
||||
}
|
||||
|
||||
String method = null;
|
||||
if (listenerEle.hasAttribute(METHOD_ATTRIBUTE)) {
|
||||
method = listenerEle.getAttribute(METHOD_ATTRIBUTE);
|
||||
String method = listenerEle.getAttribute(METHOD_ATTRIBUTE);
|
||||
if (!StringUtils.hasText(method)) {
|
||||
parserContext.getReaderContext().error(
|
||||
"Listener 'method' attribute contains empty value.", listenerEle);
|
||||
}
|
||||
listenerDef.getPropertyValues().add("defaultListenerMethod", method);
|
||||
}
|
||||
listenerDef.getPropertyValues().add("defaultListenerMethod", method);
|
||||
|
||||
PropertyValue messageConverterPv = commonContainerProperties.getPropertyValue("messageConverter");
|
||||
if (messageConverterPv != null) {
|
||||
@@ -173,12 +172,15 @@ abstract class AbstractListenerContainerParser implements BeanDefinitionParser {
|
||||
|
||||
if (listenerEle.hasAttribute(RESPONSE_DESTINATION_ATTRIBUTE)) {
|
||||
String responseDestination = listenerEle.getAttribute(RESPONSE_DESTINATION_ATTRIBUTE);
|
||||
Boolean pubSubDomain = (Boolean) commonContainerProperties.getPropertyValue("replyPubSubDomain").getValue();
|
||||
Boolean pubSubDomain = (Boolean) commonContainerProperties.get("replyPubSubDomain");
|
||||
if (pubSubDomain == null) {
|
||||
pubSubDomain = false;
|
||||
}
|
||||
listenerDef.getPropertyValues().add(
|
||||
pubSubDomain ? "defaultResponseTopicName" : "defaultResponseQueueName", responseDestination);
|
||||
if (containerDef.getPropertyValues().contains("destinationResolver")) {
|
||||
listenerDef.getPropertyValues().add("destinationResolver",
|
||||
containerDef.getPropertyValues().getPropertyValue("destinationResolver").getValue());
|
||||
PropertyValue destinationResolver = containerDef.getPropertyValues().getPropertyValue("destinationResolver");
|
||||
if (destinationResolver != null) {
|
||||
listenerDef.getPropertyValues().addPropertyValue(destinationResolver);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -26,6 +26,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -83,7 +84,7 @@ class AnnotationDrivenJmsBeanDefinitionParser implements BeanDefinitionParser {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void registerDefaultEndpointRegistry(Object source, ParserContext parserContext) {
|
||||
private static void registerDefaultEndpointRegistry(@Nullable Object source, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
"org.springframework.jms.config.JmsListenerEndpointRegistry");
|
||||
builder.getRawBeanDefinition().setSource(source);
|
||||
|
||||
@@ -202,7 +202,8 @@ public class JmsListenerEndpointRegistrar implements BeanFactoryAware, Initializ
|
||||
|
||||
public final JmsListenerContainerFactory<?> containerFactory;
|
||||
|
||||
public JmsListenerEndpointDescriptor(JmsListenerEndpoint endpoint, JmsListenerContainerFactory<?> containerFactory) {
|
||||
public JmsListenerEndpointDescriptor(JmsListenerEndpoint endpoint,
|
||||
@Nullable JmsListenerContainerFactory<?> containerFactory) {
|
||||
this.endpoint = endpoint;
|
||||
this.containerFactory = containerFactory;
|
||||
}
|
||||
|
||||
@@ -190,6 +190,7 @@ public class MethodJmsListenerEndpoint extends AbstractJmsListenerEndpoint imple
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private SendTo getSendTo(Method specificMethod) {
|
||||
SendTo ann = AnnotatedElementUtils.findMergedAnnotation(specificMethod, SendTo.class);
|
||||
if (ann == null) {
|
||||
@@ -198,6 +199,7 @@ public class MethodJmsListenerEndpoint extends AbstractJmsListenerEndpoint imple
|
||||
return ann;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String resolve(String value) {
|
||||
return (this.embeddedValueResolver != null ? this.embeddedValueResolver.resolveStringValue(value) : value);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -19,6 +19,8 @@ package org.springframework.jms.config;
|
||||
import javax.jms.MessageListener;
|
||||
|
||||
import org.springframework.jms.listener.MessageListenerContainer;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link JmsListenerEndpoint} simply providing the {@link MessageListener} to
|
||||
@@ -44,6 +46,7 @@ public class SimpleJmsListenerEndpoint extends AbstractJmsListenerEndpoint {
|
||||
* Return the {@link MessageListener} to invoke when a message matching
|
||||
* the endpoint is received.
|
||||
*/
|
||||
@Nullable
|
||||
public MessageListener getMessageListener() {
|
||||
return this.messageListener;
|
||||
}
|
||||
@@ -51,7 +54,9 @@ public class SimpleJmsListenerEndpoint extends AbstractJmsListenerEndpoint {
|
||||
|
||||
@Override
|
||||
protected MessageListener createMessageListener(MessageListenerContainer container) {
|
||||
return getMessageListener();
|
||||
MessageListener listener = getMessageListener();
|
||||
Assert.state(listener != null, "No MessageListener set");
|
||||
return listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -25,6 +25,8 @@ import javax.jms.QueueReceiver;
|
||||
import javax.jms.Topic;
|
||||
import javax.jms.TopicSubscriber;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* JMS MessageConsumer decorator that adapts all calls
|
||||
* to a shared MessageConsumer instance underneath.
|
||||
@@ -48,11 +50,13 @@ class CachedMessageConsumer implements MessageConsumer, QueueReceiver, TopicSubs
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Queue getQueue() throws JMSException {
|
||||
return (this.target instanceof QueueReceiver ? ((QueueReceiver) this.target).getQueue() : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Topic getTopic() throws JMSException {
|
||||
return (this.target instanceof TopicSubscriber ? ((TopicSubscriber) this.target).getTopic() : null);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -85,8 +85,7 @@ public class CachingConnectionFactory extends SingleConnectionFactory {
|
||||
|
||||
private volatile boolean active = true;
|
||||
|
||||
private final Map<Integer, LinkedList<Session>> cachedSessions =
|
||||
new HashMap<>();
|
||||
private final Map<Integer, LinkedList<Session>> cachedSessions = new HashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
@@ -381,7 +380,7 @@ public class CachingConnectionFactory extends SingleConnectionFactory {
|
||||
}
|
||||
}
|
||||
|
||||
private MessageProducer getCachedProducer(Destination dest) throws JMSException {
|
||||
private MessageProducer getCachedProducer(@Nullable Destination dest) throws JMSException {
|
||||
DestinationCacheKey cacheKey = (dest != null ? new DestinationCacheKey(dest) : null);
|
||||
MessageProducer producer = this.cachedProducers.get(cacheKey);
|
||||
if (producer != null) {
|
||||
@@ -399,8 +398,8 @@ public class CachingConnectionFactory extends SingleConnectionFactory {
|
||||
return new CachedMessageProducer(producer);
|
||||
}
|
||||
|
||||
private MessageConsumer getCachedConsumer(
|
||||
Destination dest, String selector, @Nullable Boolean noLocal, @Nullable String subscription, boolean durable) throws JMSException {
|
||||
private MessageConsumer getCachedConsumer(Destination dest, @Nullable String selector,
|
||||
@Nullable Boolean noLocal, @Nullable String subscription, boolean durable) throws JMSException {
|
||||
|
||||
ConsumerCacheKey cacheKey = new ConsumerCacheKey(dest, selector, noLocal, subscription, durable);
|
||||
MessageConsumer consumer = this.cachedConsumers.get(cacheKey);
|
||||
@@ -553,7 +552,9 @@ public class CachingConnectionFactory extends SingleConnectionFactory {
|
||||
|
||||
private final boolean durable;
|
||||
|
||||
public ConsumerCacheKey(Destination destination, String selector, Boolean noLocal, String subscription, boolean durable) {
|
||||
public ConsumerCacheKey(Destination destination, @Nullable String selector, @Nullable Boolean noLocal,
|
||||
@Nullable String subscription, boolean durable) {
|
||||
|
||||
super(destination);
|
||||
this.selector = selector;
|
||||
this.noLocal = noLocal;
|
||||
|
||||
@@ -65,7 +65,7 @@ public abstract class ConnectionFactoryUtils {
|
||||
* @see SmartConnectionFactory#shouldStop
|
||||
* @see org.springframework.jms.support.JmsUtils#closeConnection
|
||||
*/
|
||||
public static void releaseConnection(Connection con, @Nullable ConnectionFactory cf, boolean started) {
|
||||
public static void releaseConnection(@Nullable Connection con, @Nullable ConnectionFactory cf, boolean started) {
|
||||
if (con == null) {
|
||||
return;
|
||||
}
|
||||
@@ -110,7 +110,7 @@ public abstract class ConnectionFactoryUtils {
|
||||
* @param cf the JMS ConnectionFactory that the Session originated from
|
||||
* @return whether the Session is transactional
|
||||
*/
|
||||
public static boolean isSessionTransactional(Session session, ConnectionFactory cf) {
|
||||
public static boolean isSessionTransactional(@Nullable Session session, @Nullable ConnectionFactory cf) {
|
||||
if (session == null || cf == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -26,6 +26,7 @@ import javax.jms.TopicConnection;
|
||||
import javax.jms.TopicConnectionFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -70,10 +71,17 @@ public class DelegatingConnectionFactory
|
||||
/**
|
||||
* Return the target ConnectionFactory that this ConnectionFactory delegates to.
|
||||
*/
|
||||
@Nullable
|
||||
public ConnectionFactory getTargetConnectionFactory() {
|
||||
return this.targetConnectionFactory;
|
||||
}
|
||||
|
||||
private ConnectionFactory obtainTargetConnectionFactory() {
|
||||
ConnectionFactory target = getTargetConnectionFactory();
|
||||
Assert.state(target != null, "No 'targetConnectionFactory' set");
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether Connections obtained from the target factory are supposed
|
||||
* to be stopped before closed ("true") or simply closed ("false").
|
||||
@@ -184,12 +192,6 @@ public class DelegatingConnectionFactory
|
||||
return obtainTargetConnectionFactory().createContext(sessionMode);
|
||||
}
|
||||
|
||||
private ConnectionFactory obtainTargetConnectionFactory() {
|
||||
ConnectionFactory target = getTargetConnectionFactory();
|
||||
Assert.state(target != null, "'targetConnectionFactory' is required");
|
||||
return target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldStop(Connection con) {
|
||||
return this.shouldStopConnections;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -21,7 +21,6 @@ import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.JMSException;
|
||||
@@ -62,8 +61,7 @@ public class JmsResourceHolder extends ResourceHolderSupport {
|
||||
|
||||
private final List<Session> sessions = new LinkedList<>();
|
||||
|
||||
private final Map<Connection, List<Session>> sessionsPerConnection =
|
||||
new HashMap<>();
|
||||
private final Map<Connection, List<Session>> sessionsPerConnection = new HashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
@@ -155,27 +153,29 @@ public class JmsResourceHolder extends ResourceHolderSupport {
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public Connection getConnection() {
|
||||
return (!this.connections.isEmpty() ? this.connections.get(0) : null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Connection getConnection(Class<? extends Connection> connectionType) {
|
||||
return CollectionUtils.findValueOfType(this.connections, connectionType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Session getSession() {
|
||||
return (!this.sessions.isEmpty() ? this.sessions.get(0) : null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Session getSession(Class<? extends Session> sessionType) {
|
||||
return getSession(sessionType, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Session getSession(Class<? extends Session> sessionType, @Nullable Connection connection) {
|
||||
List<Session> sessions = this.sessions;
|
||||
if (connection != null) {
|
||||
sessions = this.sessionsPerConnection.get(connection);
|
||||
}
|
||||
List<Session> sessions = (connection != null ? this.sessionsPerConnection.get(connection) : this.sessions);
|
||||
return CollectionUtils.findValueOfType(sessions, sessionType);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||
import org.springframework.transaction.support.ResourceTransactionManager;
|
||||
import org.springframework.transaction.support.SmartTransactionObject;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.transaction.PlatformTransactionManager} implementation
|
||||
@@ -140,10 +141,23 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager
|
||||
/**
|
||||
* Return the JMS ConnectionFactory that this instance should manage transactions for.
|
||||
*/
|
||||
@Nullable
|
||||
public ConnectionFactory getConnectionFactory() {
|
||||
return this.connectionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the ConnectionFactory for actual use.
|
||||
* @return the ConnectionFactory (never {@code null})
|
||||
* @throws IllegalStateException in case of no ConnectionFactory set
|
||||
* @since 5.0
|
||||
*/
|
||||
protected final ConnectionFactory obtainConnectionFactory() {
|
||||
ConnectionFactory connectionFactory = getConnectionFactory();
|
||||
Assert.state(connectionFactory != null, "No ConnectionFactory set");
|
||||
return connectionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure the ConnectionFactory has been set.
|
||||
*/
|
||||
@@ -157,21 +171,21 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager
|
||||
|
||||
@Override
|
||||
public Object getResourceFactory() {
|
||||
return getConnectionFactory();
|
||||
return obtainConnectionFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doGetTransaction() {
|
||||
JmsTransactionObject txObject = new JmsTransactionObject();
|
||||
txObject.setResourceHolder(
|
||||
(JmsResourceHolder) TransactionSynchronizationManager.getResource(getConnectionFactory()));
|
||||
(JmsResourceHolder) TransactionSynchronizationManager.getResource(obtainConnectionFactory()));
|
||||
return txObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isExistingTransaction(Object transaction) {
|
||||
JmsTransactionObject txObject = (JmsTransactionObject) transaction;
|
||||
return (txObject.getResourceHolder() != null);
|
||||
return txObject.hasResourceHolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -180,6 +194,7 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager
|
||||
throw new InvalidIsolationLevelException("JMS does not support an isolation level concept");
|
||||
}
|
||||
|
||||
ConnectionFactory connectionFactory = obtainConnectionFactory();
|
||||
JmsTransactionObject txObject = (JmsTransactionObject) transaction;
|
||||
Connection con = null;
|
||||
Session session = null;
|
||||
@@ -189,13 +204,14 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Created JMS transaction on Session [" + session + "] from Connection [" + con + "]");
|
||||
}
|
||||
txObject.setResourceHolder(new JmsResourceHolder(getConnectionFactory(), con, session));
|
||||
txObject.getResourceHolder().setSynchronizedWithTransaction(true);
|
||||
JmsResourceHolder resourceHolder = new JmsResourceHolder(connectionFactory, con, session);
|
||||
resourceHolder.setSynchronizedWithTransaction(true);
|
||||
int timeout = determineTimeout(definition);
|
||||
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
|
||||
txObject.getResourceHolder().setTimeoutInSeconds(timeout);
|
||||
resourceHolder.setTimeoutInSeconds(timeout);
|
||||
}
|
||||
TransactionSynchronizationManager.bindResource(getConnectionFactory(), txObject.getResourceHolder());
|
||||
txObject.setResourceHolder(resourceHolder);
|
||||
TransactionSynchronizationManager.bindResource(connectionFactory, resourceHolder);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
if (session != null) {
|
||||
@@ -222,29 +238,31 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager
|
||||
protected Object doSuspend(Object transaction) {
|
||||
JmsTransactionObject txObject = (JmsTransactionObject) transaction;
|
||||
txObject.setResourceHolder(null);
|
||||
return TransactionSynchronizationManager.unbindResource(getConnectionFactory());
|
||||
return TransactionSynchronizationManager.unbindResource(obtainConnectionFactory());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doResume(Object transaction, Object suspendedResources) {
|
||||
TransactionSynchronizationManager.bindResource(getConnectionFactory(), suspendedResources);
|
||||
protected void doResume(@Nullable Object transaction, Object suspendedResources) {
|
||||
TransactionSynchronizationManager.bindResource(obtainConnectionFactory(), suspendedResources);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doCommit(DefaultTransactionStatus status) {
|
||||
JmsTransactionObject txObject = (JmsTransactionObject) status.getTransaction();
|
||||
Session session = txObject.getResourceHolder().getSession();
|
||||
try {
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Committing JMS transaction on Session [" + session + "]");
|
||||
if (session != null) {
|
||||
try {
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Committing JMS transaction on Session [" + session + "]");
|
||||
}
|
||||
session.commit();
|
||||
}
|
||||
catch (TransactionRolledBackException ex) {
|
||||
throw new UnexpectedRollbackException("JMS transaction rolled back", ex);
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new TransactionSystemException("Could not commit JMS transaction", ex);
|
||||
}
|
||||
session.commit();
|
||||
}
|
||||
catch (TransactionRolledBackException ex) {
|
||||
throw new UnexpectedRollbackException("JMS transaction rolled back", ex);
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new TransactionSystemException("Could not commit JMS transaction", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,14 +270,16 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager
|
||||
protected void doRollback(DefaultTransactionStatus status) {
|
||||
JmsTransactionObject txObject = (JmsTransactionObject) status.getTransaction();
|
||||
Session session = txObject.getResourceHolder().getSession();
|
||||
try {
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Rolling back JMS transaction on Session [" + session + "]");
|
||||
if (session != null) {
|
||||
try {
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Rolling back JMS transaction on Session [" + session + "]");
|
||||
}
|
||||
session.rollback();
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new TransactionSystemException("Could not roll back JMS transaction", ex);
|
||||
}
|
||||
session.rollback();
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new TransactionSystemException("Could not roll back JMS transaction", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,7 +292,7 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager
|
||||
@Override
|
||||
protected void doCleanupAfterCompletion(Object transaction) {
|
||||
JmsTransactionObject txObject = (JmsTransactionObject) transaction;
|
||||
TransactionSynchronizationManager.unbindResource(getConnectionFactory());
|
||||
TransactionSynchronizationManager.unbindResource(obtainConnectionFactory());
|
||||
txObject.getResourceHolder().closeAll();
|
||||
txObject.getResourceHolder().clear();
|
||||
}
|
||||
@@ -285,7 +305,7 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager
|
||||
* @throws javax.jms.JMSException if thrown by JMS API methods
|
||||
*/
|
||||
protected Connection createConnection() throws JMSException {
|
||||
return getConnectionFactory().createConnection();
|
||||
return obtainConnectionFactory().createConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,9 +334,14 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager
|
||||
}
|
||||
|
||||
public JmsResourceHolder getResourceHolder() {
|
||||
Assert.state(this.resourceHolder != null, "No JmsResourceHolder available");
|
||||
return this.resourceHolder;
|
||||
}
|
||||
|
||||
public boolean hasResourceHolder() {
|
||||
return (this.resourceHolder != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRollbackOnly() {
|
||||
return this.resourceHolder.isRollbackOnly();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -24,7 +24,6 @@ import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.ExceptionListener;
|
||||
@@ -394,7 +393,7 @@ public class SingleConnectionFactory implements ConnectionFactory, QueueConnecti
|
||||
return ((TopicConnectionFactory) cf).createTopicConnection();
|
||||
}
|
||||
else {
|
||||
return getTargetConnectionFactory().createConnection();
|
||||
return obtainTargetConnectionFactory().createConnection();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -531,8 +530,9 @@ public class SingleConnectionFactory implements ConnectionFactory, QueueConnecti
|
||||
private boolean locallyStarted = false;
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
if (method.getName().equals("equals")) {
|
||||
@Nullable
|
||||
public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
|
||||
if (method.getName().equals("equals") && args != null) {
|
||||
Object other = args[0];
|
||||
if (proxy == other) {
|
||||
return true;
|
||||
@@ -551,7 +551,7 @@ public class SingleConnectionFactory implements ConnectionFactory, QueueConnecti
|
||||
else if (method.getName().equals("toString")) {
|
||||
return "Shared JMS Connection: " + getConnection();
|
||||
}
|
||||
else if (method.getName().equals("setClientID")) {
|
||||
else if (method.getName().equals("setClientID") && args != null) {
|
||||
// Handle setClientID method: throw exception if not compatible.
|
||||
String currentClientId = getConnection().getClientID();
|
||||
if (currentClientId != null && currentClientId.equals(args[0])) {
|
||||
@@ -563,7 +563,7 @@ public class SingleConnectionFactory implements ConnectionFactory, QueueConnecti
|
||||
"Set the 'clientId' property on the SingleConnectionFactory instead.");
|
||||
}
|
||||
}
|
||||
else if (method.getName().equals("setExceptionListener")) {
|
||||
else if (method.getName().equals("setExceptionListener") && args != null) {
|
||||
// Handle setExceptionListener method: add to the chain.
|
||||
synchronized (connectionMonitor) {
|
||||
if (aggregatedExceptionListener != null) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -35,6 +35,7 @@ import javax.jms.TopicConnectionFactory;
|
||||
import javax.jms.TopicSession;
|
||||
import javax.jms.TransactionInProgressException;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -109,6 +110,7 @@ public class TransactionAwareConnectionFactoryProxy
|
||||
/**
|
||||
* Return the target ConnectionFactory that this ConnectionFactory should delegate to.
|
||||
*/
|
||||
@Nullable
|
||||
protected ConnectionFactory getTargetConnectionFactory() {
|
||||
return this.targetConnectionFactory;
|
||||
}
|
||||
@@ -263,14 +265,14 @@ public class TransactionAwareConnectionFactoryProxy
|
||||
}
|
||||
else if (Session.class == method.getReturnType()) {
|
||||
Session session = ConnectionFactoryUtils.getTransactionalSession(
|
||||
getTargetConnectionFactory(), this.target, isSynchedLocalTransactionAllowed());
|
||||
obtainTargetConnectionFactory(), this.target, isSynchedLocalTransactionAllowed());
|
||||
if (session != null) {
|
||||
return getCloseSuppressingSessionProxy(session);
|
||||
}
|
||||
}
|
||||
else if (QueueSession.class == method.getReturnType()) {
|
||||
QueueSession session = ConnectionFactoryUtils.getTransactionalQueueSession(
|
||||
(QueueConnectionFactory) getTargetConnectionFactory(), (QueueConnection) this.target,
|
||||
(QueueConnectionFactory) obtainTargetConnectionFactory(), (QueueConnection) this.target,
|
||||
isSynchedLocalTransactionAllowed());
|
||||
if (session != null) {
|
||||
return getCloseSuppressingSessionProxy(session);
|
||||
@@ -278,7 +280,7 @@ public class TransactionAwareConnectionFactoryProxy
|
||||
}
|
||||
else if (TopicSession.class == method.getReturnType()) {
|
||||
TopicSession session = ConnectionFactoryUtils.getTransactionalTopicSession(
|
||||
(TopicConnectionFactory) getTargetConnectionFactory(), (TopicConnection) this.target,
|
||||
(TopicConnectionFactory) obtainTargetConnectionFactory(), (TopicConnection) this.target,
|
||||
isSynchedLocalTransactionAllowed());
|
||||
if (session != null) {
|
||||
return getCloseSuppressingSessionProxy(session);
|
||||
@@ -323,6 +325,7 @@ public class TransactionAwareConnectionFactoryProxy
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
// Invocation on SessionProxy interface coming in...
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.jms.core;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.jms.Destination;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -93,8 +92,8 @@ public interface JmsMessageOperations extends MessageSendingOperations<Destinati
|
||||
* @param headers headers for the message to send
|
||||
* @param postProcessor the post processor to apply to the message
|
||||
*/
|
||||
void convertAndSend(String destinationName, Object payload, @Nullable Map<String,
|
||||
Object> headers, @Nullable MessagePostProcessor postProcessor) throws MessagingException;
|
||||
void convertAndSend(String destinationName, Object payload, @Nullable Map<String, Object> headers,
|
||||
@Nullable MessagePostProcessor postProcessor) throws MessagingException;
|
||||
|
||||
/**
|
||||
* Receive a message from the given destination.
|
||||
|
||||
@@ -96,6 +96,7 @@ public class JmsMessagingTemplate extends AbstractMessagingTemplate<Destination>
|
||||
* Return the ConnectionFactory that the underlying {@link JmsTemplate} uses.
|
||||
* @since 4.1.2
|
||||
*/
|
||||
@Nullable
|
||||
public ConnectionFactory getConnectionFactory() {
|
||||
return (this.jmsTemplate != null ? this.jmsTemplate.getConnectionFactory() : null);
|
||||
}
|
||||
@@ -150,6 +151,7 @@ public class JmsMessagingTemplate extends AbstractMessagingTemplate<Destination>
|
||||
/**
|
||||
* Return the configured default destination name.
|
||||
*/
|
||||
@Nullable
|
||||
public String getDefaultDestinationName() {
|
||||
return this.defaultDestinationName;
|
||||
}
|
||||
@@ -198,14 +200,14 @@ public class JmsMessagingTemplate extends AbstractMessagingTemplate<Destination>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertAndSend(String destinationName, Object payload, Map<String, Object> headers)
|
||||
public void convertAndSend(String destinationName, Object payload, @Nullable Map<String, Object> headers)
|
||||
throws MessagingException {
|
||||
|
||||
convertAndSend(destinationName, payload, headers, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertAndSend(String destinationName, Object payload, MessagePostProcessor postProcessor)
|
||||
public void convertAndSend(String destinationName, Object payload, @Nullable MessagePostProcessor postProcessor)
|
||||
throws MessagingException {
|
||||
|
||||
convertAndSend(destinationName, payload, null, postProcessor);
|
||||
@@ -305,7 +307,7 @@ public class JmsMessagingTemplate extends AbstractMessagingTemplate<Destination>
|
||||
|
||||
@Override
|
||||
public <T> T convertSendAndReceive(String destinationName, Object request, Class<T> targetClass,
|
||||
MessagePostProcessor requestPostProcessor) throws MessagingException {
|
||||
@Nullable MessagePostProcessor requestPostProcessor) throws MessagingException {
|
||||
|
||||
return convertSendAndReceive(destinationName, request, null, targetClass, requestPostProcessor);
|
||||
}
|
||||
@@ -350,6 +352,7 @@ public class JmsMessagingTemplate extends AbstractMessagingTemplate<Destination>
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected Message<?> doReceive(String destinationName) {
|
||||
try {
|
||||
javax.jms.Message jmsMessage = this.jmsTemplate.receive(destinationName);
|
||||
@@ -372,6 +375,7 @@ public class JmsMessagingTemplate extends AbstractMessagingTemplate<Destination>
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected Message<?> doSendAndReceive(String destinationName, Message<?> requestMessage) {
|
||||
try {
|
||||
javax.jms.Message jmsMessage = this.jmsTemplate.sendAndReceive(
|
||||
@@ -396,7 +400,8 @@ public class JmsMessagingTemplate extends AbstractMessagingTemplate<Destination>
|
||||
return name;
|
||||
}
|
||||
|
||||
protected Message<?> convertJmsMessage(javax.jms.Message message) {
|
||||
@Nullable
|
||||
protected Message<?> convertJmsMessage(@Nullable javax.jms.Message message) {
|
||||
if (message == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -54,6 +54,7 @@ public interface JmsOperations {
|
||||
* @return the result object from working with the session
|
||||
* @throws JmsException if there is any problem
|
||||
*/
|
||||
@Nullable
|
||||
<T> T execute(SessionCallback<T> action) throws JmsException;
|
||||
|
||||
/**
|
||||
@@ -64,6 +65,7 @@ public interface JmsOperations {
|
||||
* @return the result object from working with the session
|
||||
* @throws JmsException checked JMSException converted to unchecked
|
||||
*/
|
||||
@Nullable
|
||||
<T> T execute(ProducerCallback<T> action) throws JmsException;
|
||||
|
||||
/**
|
||||
@@ -74,6 +76,7 @@ public interface JmsOperations {
|
||||
* @return the result object from working with the session
|
||||
* @throws JmsException checked JMSException converted to unchecked
|
||||
*/
|
||||
@Nullable
|
||||
<T> T execute(Destination destination, ProducerCallback<T> action) throws JmsException;
|
||||
|
||||
/**
|
||||
@@ -85,6 +88,7 @@ public interface JmsOperations {
|
||||
* @return the result object from working with the session
|
||||
* @throws JmsException checked JMSException converted to unchecked
|
||||
*/
|
||||
@Nullable
|
||||
<T> T execute(String destinationName, ProducerCallback<T> action) throws JmsException;
|
||||
|
||||
|
||||
@@ -428,6 +432,7 @@ public interface JmsOperations {
|
||||
* @return the result object from working with the session
|
||||
* @throws JmsException checked JMSException converted to unchecked
|
||||
*/
|
||||
@Nullable
|
||||
<T> T browse(BrowserCallback<T> action) throws JmsException;
|
||||
|
||||
/**
|
||||
@@ -438,6 +443,7 @@ public interface JmsOperations {
|
||||
* @return the result object from working with the session
|
||||
* @throws JmsException checked JMSException converted to unchecked
|
||||
*/
|
||||
@Nullable
|
||||
<T> T browse(Queue queue, BrowserCallback<T> action) throws JmsException;
|
||||
|
||||
/**
|
||||
@@ -449,6 +455,7 @@ public interface JmsOperations {
|
||||
* @return the result object from working with the session
|
||||
* @throws JmsException checked JMSException converted to unchecked
|
||||
*/
|
||||
@Nullable
|
||||
<T> T browse(String queueName, BrowserCallback<T> action) throws JmsException;
|
||||
|
||||
/**
|
||||
@@ -460,6 +467,7 @@ public interface JmsOperations {
|
||||
* @return the result object from working with the session
|
||||
* @throws JmsException checked JMSException converted to unchecked
|
||||
*/
|
||||
@Nullable
|
||||
<T> T browseSelected(String messageSelector, BrowserCallback<T> action) throws JmsException;
|
||||
|
||||
/**
|
||||
@@ -472,6 +480,7 @@ public interface JmsOperations {
|
||||
* @return the result object from working with the session
|
||||
* @throws JmsException checked JMSException converted to unchecked
|
||||
*/
|
||||
@Nullable
|
||||
<T> T browseSelected(Queue queue, String messageSelector, BrowserCallback<T> action) throws JmsException;
|
||||
|
||||
/**
|
||||
@@ -485,6 +494,7 @@ public interface JmsOperations {
|
||||
* @return the result object from working with the session
|
||||
* @throws JmsException checked JMSException converted to unchecked
|
||||
*/
|
||||
@Nullable
|
||||
<T> T browseSelected(String queueName, String messageSelector, BrowserCallback<T> action) throws JmsException;
|
||||
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.jms.core;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.DeliveryMode;
|
||||
@@ -42,8 +40,6 @@ import org.springframework.jms.support.destination.JmsDestinationAccessor;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Helper class that simplifies synchronous JMS access code.
|
||||
@@ -92,10 +88,6 @@ import org.springframework.util.ReflectionUtils;
|
||||
*/
|
||||
public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations {
|
||||
|
||||
/** The JMS 2.0 MessageProducer.setDeliveryDelay method, if available */
|
||||
private static final Method setDeliveryDelayMethod =
|
||||
ClassUtils.getMethodIfAvailable(MessageProducer.class, "setDeliveryDelay", long.class);
|
||||
|
||||
/** Internal ResourceFactory adapter for interacting with ConnectionFactoryUtils */
|
||||
private final JmsTemplateResourceFactory transactionalResourceFactory = new JmsTemplateResourceFactory();
|
||||
|
||||
@@ -177,10 +169,12 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
|
||||
* Return the destination to be used on send/receive operations that do not
|
||||
* have a destination parameter.
|
||||
*/
|
||||
@Nullable
|
||||
public Destination getDefaultDestination() {
|
||||
return (this.defaultDestination instanceof Destination ? (Destination) this.defaultDestination : null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Queue getDefaultQueue() {
|
||||
Destination defaultDestination = getDefaultDestination();
|
||||
if (defaultDestination != null && !(defaultDestination instanceof Queue)) {
|
||||
@@ -209,6 +203,7 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
|
||||
* Return the destination name to be used on send/receive operations that
|
||||
* do not have a destination parameter.
|
||||
*/
|
||||
@Nullable
|
||||
public String getDefaultDestinationName() {
|
||||
return (this.defaultDestination instanceof String ? (String) this.defaultDestination : null);
|
||||
}
|
||||
@@ -239,6 +234,7 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
|
||||
/**
|
||||
* Return the message converter for this template.
|
||||
*/
|
||||
@Nullable
|
||||
public MessageConverter getMessageConverter() {
|
||||
return this.messageConverter;
|
||||
}
|
||||
@@ -483,13 +479,14 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
|
||||
* @see #execute(SessionCallback)
|
||||
* @see #receive
|
||||
*/
|
||||
@Nullable
|
||||
public <T> T execute(SessionCallback<T> action, boolean startConnection) throws JmsException {
|
||||
Assert.notNull(action, "Callback object must not be null");
|
||||
Connection conToClose = null;
|
||||
Session sessionToClose = null;
|
||||
try {
|
||||
Session sessionToUse = ConnectionFactoryUtils.doGetTransactionalSession(
|
||||
getConnectionFactory(), this.transactionalResourceFactory, startConnection);
|
||||
obtainConnectionFactory(), this.transactionalResourceFactory, startConnection);
|
||||
if (sessionToUse == null) {
|
||||
conToClose = createConnection();
|
||||
sessionToClose = createSession(conToClose);
|
||||
@@ -524,18 +521,15 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T execute(final Destination destination, final ProducerCallback<T> action) throws JmsException {
|
||||
public <T> T execute(final @Nullable Destination destination, final ProducerCallback<T> action) throws JmsException {
|
||||
Assert.notNull(action, "Callback object must not be null");
|
||||
return execute(new SessionCallback<T>() {
|
||||
@Override
|
||||
public T doInJms(Session session) throws JMSException {
|
||||
MessageProducer producer = createProducer(session, destination);
|
||||
try {
|
||||
return action.doInJms(session, producer);
|
||||
}
|
||||
finally {
|
||||
JmsUtils.closeMessageProducer(producer);
|
||||
}
|
||||
return execute(session -> {
|
||||
MessageProducer producer = createProducer(session, destination);
|
||||
try {
|
||||
return action.doInJms(session, producer);
|
||||
}
|
||||
finally {
|
||||
JmsUtils.closeMessageProducer(producer);
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
@@ -543,17 +537,14 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
|
||||
@Override
|
||||
public <T> T execute(final String destinationName, final ProducerCallback<T> action) throws JmsException {
|
||||
Assert.notNull(action, "Callback object must not be null");
|
||||
return execute(new SessionCallback<T>() {
|
||||
@Override
|
||||
public T doInJms(Session session) throws JMSException {
|
||||
Destination destination = resolveDestinationName(session, destinationName);
|
||||
MessageProducer producer = createProducer(session, destination);
|
||||
try {
|
||||
return action.doInJms(session, producer);
|
||||
}
|
||||
finally {
|
||||
JmsUtils.closeMessageProducer(producer);
|
||||
}
|
||||
return execute(session -> {
|
||||
Destination destination = resolveDestinationName(session, destinationName);
|
||||
MessageProducer producer = createProducer(session, destination);
|
||||
try {
|
||||
return action.doInJms(session, producer);
|
||||
}
|
||||
finally {
|
||||
JmsUtils.closeMessageProducer(producer);
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
@@ -576,24 +567,18 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
|
||||
|
||||
@Override
|
||||
public void send(final Destination destination, final MessageCreator messageCreator) throws JmsException {
|
||||
execute(new SessionCallback<Object>() {
|
||||
@Override
|
||||
public Object doInJms(Session session) throws JMSException {
|
||||
doSend(session, destination, messageCreator);
|
||||
return null;
|
||||
}
|
||||
execute(session -> {
|
||||
doSend(session, destination, messageCreator);
|
||||
return null;
|
||||
}, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(final String destinationName, final MessageCreator messageCreator) throws JmsException {
|
||||
execute(new SessionCallback<Object>() {
|
||||
@Override
|
||||
public Object doInJms(Session session) throws JMSException {
|
||||
Destination destination = resolveDestinationName(session, destinationName);
|
||||
doSend(session, destination, messageCreator);
|
||||
return null;
|
||||
}
|
||||
execute(session -> {
|
||||
Destination destination = resolveDestinationName(session, destinationName);
|
||||
doSend(session, destination, messageCreator);
|
||||
return null;
|
||||
}, false);
|
||||
}
|
||||
|
||||
@@ -634,10 +619,7 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
|
||||
*/
|
||||
protected void doSend(MessageProducer producer, Message message) throws JMSException {
|
||||
if (this.deliveryDelay >= 0) {
|
||||
if (setDeliveryDelayMethod == null) {
|
||||
throw new IllegalStateException("setDeliveryDelay requires JMS 2.0");
|
||||
}
|
||||
ReflectionUtils.invokeMethod(setDeliveryDelayMethod, producer, this.deliveryDelay);
|
||||
producer.setDeliveryDelay(this.deliveryDelay);
|
||||
}
|
||||
if (isExplicitQosEnabled()) {
|
||||
producer.send(message, getDeliveryMode(), getPriority(), getTimeToLive());
|
||||
@@ -665,21 +647,15 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
|
||||
|
||||
@Override
|
||||
public void convertAndSend(Destination destination, final Object message) throws JmsException {
|
||||
send(destination, new MessageCreator() {
|
||||
@Override
|
||||
public Message createMessage(Session session) throws JMSException {
|
||||
return getRequiredMessageConverter().toMessage(message, session);
|
||||
}
|
||||
send(destination, session -> {
|
||||
return getRequiredMessageConverter().toMessage(message, session);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertAndSend(String destinationName, final Object message) throws JmsException {
|
||||
send(destinationName, new MessageCreator() {
|
||||
@Override
|
||||
public Message createMessage(Session session) throws JMSException {
|
||||
return getRequiredMessageConverter().toMessage(message, session);
|
||||
}
|
||||
send(destinationName, session -> {
|
||||
return getRequiredMessageConverter().toMessage(message, session);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -699,12 +675,9 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
|
||||
Destination destination, final Object message, final MessagePostProcessor postProcessor)
|
||||
throws JmsException {
|
||||
|
||||
send(destination, new MessageCreator() {
|
||||
@Override
|
||||
public Message createMessage(Session session) throws JMSException {
|
||||
Message msg = getRequiredMessageConverter().toMessage(message, session);
|
||||
return postProcessor.postProcessMessage(msg);
|
||||
}
|
||||
send(destination, session -> {
|
||||
Message msg = getRequiredMessageConverter().toMessage(message, session);
|
||||
return postProcessor.postProcessMessage(msg);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -713,12 +686,9 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
|
||||
String destinationName, final Object message, final MessagePostProcessor postProcessor)
|
||||
throws JmsException {
|
||||
|
||||
send(destinationName, new MessageCreator() {
|
||||
@Override
|
||||
public Message createMessage(Session session) throws JMSException {
|
||||
Message msg = getRequiredMessageConverter().toMessage(message, session);
|
||||
return postProcessor.postProcessMessage(msg);
|
||||
}
|
||||
send(destinationName, session -> {
|
||||
Message msg = getRequiredMessageConverter().toMessage(message, session);
|
||||
return postProcessor.postProcessMessage(msg);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -761,22 +731,16 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
|
||||
|
||||
@Override
|
||||
public Message receiveSelected(final Destination destination, @Nullable final String messageSelector) throws JmsException {
|
||||
return execute(new SessionCallback<Message>() {
|
||||
@Override
|
||||
public Message doInJms(Session session) throws JMSException {
|
||||
return doReceive(session, destination, messageSelector);
|
||||
}
|
||||
return execute(session -> {
|
||||
return doReceive(session, destination, messageSelector);
|
||||
}, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message receiveSelected(final String destinationName, @Nullable final String messageSelector) throws JmsException {
|
||||
return execute(new SessionCallback<Message>() {
|
||||
@Override
|
||||
public Message doInJms(Session session) throws JMSException {
|
||||
Destination destination = resolveDestinationName(session, destinationName);
|
||||
return doReceive(session, destination, messageSelector);
|
||||
}
|
||||
return execute(session -> {
|
||||
Destination destination = resolveDestinationName(session, destinationName);
|
||||
return doReceive(session, destination, messageSelector);
|
||||
}, true);
|
||||
}
|
||||
|
||||
@@ -807,8 +771,11 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
|
||||
try {
|
||||
// Use transaction timeout (if available).
|
||||
long timeout = getReceiveTimeout();
|
||||
JmsResourceHolder resourceHolder =
|
||||
(JmsResourceHolder) TransactionSynchronizationManager.getResource(getConnectionFactory());
|
||||
ConnectionFactory connectionFactory = getConnectionFactory();
|
||||
JmsResourceHolder resourceHolder = null;
|
||||
if (connectionFactory != null) {
|
||||
resourceHolder = (JmsResourceHolder) TransactionSynchronizationManager.getResource(connectionFactory);
|
||||
}
|
||||
if (resourceHolder != null && resourceHolder.hasTimeout()) {
|
||||
timeout = Math.min(timeout, resourceHolder.getTimeToLiveInMillis());
|
||||
}
|
||||
@@ -904,22 +871,14 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
|
||||
|
||||
@Override
|
||||
public Message sendAndReceive(final Destination destination, final MessageCreator messageCreator) throws JmsException {
|
||||
return executeLocal(new SessionCallback<Message>() {
|
||||
@Override
|
||||
public Message doInJms(Session session) throws JMSException {
|
||||
return doSendAndReceive(session, destination, messageCreator);
|
||||
}
|
||||
}, true);
|
||||
return executeLocal(session -> doSendAndReceive(session, destination, messageCreator), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message sendAndReceive(final String destinationName, final MessageCreator messageCreator) throws JmsException {
|
||||
return executeLocal(new SessionCallback<Message>() {
|
||||
@Override
|
||||
public Message doInJms(Session session) throws JMSException {
|
||||
Destination destination = resolveDestinationName(session, destinationName);
|
||||
return doSendAndReceive(session, destination, messageCreator);
|
||||
}
|
||||
return executeLocal(session -> {
|
||||
Destination destination = resolveDestinationName(session, destinationName);
|
||||
return doSendAndReceive(session, destination, messageCreator);
|
||||
}, true);
|
||||
}
|
||||
|
||||
@@ -963,12 +922,13 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
|
||||
* creates a non-transactional {@link Session}. The given {@link SessionCallback}
|
||||
* does not participate in an existing transaction.
|
||||
*/
|
||||
@Nullable
|
||||
private <T> T executeLocal(SessionCallback<T> action, boolean startConnection) throws JmsException {
|
||||
Assert.notNull(action, "Callback object must not be null");
|
||||
Connection con = null;
|
||||
Session session = null;
|
||||
try {
|
||||
con = getConnectionFactory().createConnection();
|
||||
con = createConnection();
|
||||
session = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
if (startConnection) {
|
||||
con.start();
|
||||
@@ -1029,16 +989,13 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
|
||||
throws JmsException {
|
||||
|
||||
Assert.notNull(action, "Callback object must not be null");
|
||||
return execute(new SessionCallback<T>() {
|
||||
@Override
|
||||
public T doInJms(Session session) throws JMSException {
|
||||
QueueBrowser browser = createBrowser(session, queue, messageSelector);
|
||||
try {
|
||||
return action.doInJms(session, browser);
|
||||
}
|
||||
finally {
|
||||
JmsUtils.closeQueueBrowser(browser);
|
||||
}
|
||||
return execute(session -> {
|
||||
QueueBrowser browser = createBrowser(session, queue, messageSelector);
|
||||
try {
|
||||
return action.doInJms(session, browser);
|
||||
}
|
||||
finally {
|
||||
JmsUtils.closeQueueBrowser(browser);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
@@ -1048,17 +1005,14 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
|
||||
throws JmsException {
|
||||
|
||||
Assert.notNull(action, "Callback object must not be null");
|
||||
return execute(new SessionCallback<T>() {
|
||||
@Override
|
||||
public T doInJms(Session session) throws JMSException {
|
||||
Queue queue = (Queue) getDestinationResolver().resolveDestinationName(session, queueName, false);
|
||||
QueueBrowser browser = createBrowser(session, queue, messageSelector);
|
||||
try {
|
||||
return action.doInJms(session, browser);
|
||||
}
|
||||
finally {
|
||||
JmsUtils.closeQueueBrowser(browser);
|
||||
}
|
||||
return execute(session -> {
|
||||
Queue queue = (Queue) getDestinationResolver().resolveDestinationName(session, queueName, false);
|
||||
QueueBrowser browser = createBrowser(session, queue, messageSelector);
|
||||
try {
|
||||
return action.doInJms(session, browser);
|
||||
}
|
||||
finally {
|
||||
JmsUtils.closeQueueBrowser(browser);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
@@ -1117,7 +1071,7 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
|
||||
* @see #setMessageIdEnabled
|
||||
* @see #setMessageTimestampEnabled
|
||||
*/
|
||||
protected MessageProducer createProducer(Session session, Destination destination) throws JMSException {
|
||||
protected MessageProducer createProducer(Session session, @Nullable Destination destination) throws JMSException {
|
||||
MessageProducer producer = doCreateProducer(session, destination);
|
||||
if (!isMessageIdEnabled()) {
|
||||
producer.setDisableMessageID(true);
|
||||
@@ -1136,7 +1090,7 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
|
||||
* @return the new JMS MessageProducer
|
||||
* @throws JMSException if thrown by JMS API methods
|
||||
*/
|
||||
protected MessageProducer doCreateProducer(Session session, Destination destination) throws JMSException {
|
||||
protected MessageProducer doCreateProducer(Session session, @Nullable Destination destination) throws JMSException {
|
||||
return session.createProducer(destination);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.jms.listener;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.ExceptionListener;
|
||||
@@ -35,9 +32,7 @@ import org.springframework.jms.support.QosSettings;
|
||||
import org.springframework.jms.support.converter.MessageConverter;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ErrorHandler;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Abstract base class for Spring message listener container implementations.
|
||||
@@ -148,15 +143,6 @@ import org.springframework.util.ReflectionUtils;
|
||||
public abstract class AbstractMessageListenerContainer extends AbstractJmsListeningContainer
|
||||
implements MessageListenerContainer {
|
||||
|
||||
/** The JMS 2.0 Session.createSharedConsumer method, if available */
|
||||
private static final Method createSharedConsumerMethod = ClassUtils.getMethodIfAvailable(
|
||||
Session.class, "createSharedConsumer", Topic.class, String.class, String.class);
|
||||
|
||||
/** The JMS 2.0 Session.createSharedDurableConsumer method, if available */
|
||||
private static final Method createSharedDurableConsumerMethod = ClassUtils.getMethodIfAvailable(
|
||||
Session.class, "createSharedDurableConsumer", Topic.class, String.class, String.class);
|
||||
|
||||
|
||||
private volatile Object destination;
|
||||
|
||||
private volatile String messageSelector;
|
||||
@@ -229,10 +215,9 @@ public abstract class AbstractMessageListenerContainer extends AbstractJmsListen
|
||||
* container picking up the new destination immediately (works e.g. with
|
||||
* DefaultMessageListenerContainer, as long as the cache level is less than
|
||||
* CACHE_CONSUMER). However, this is considered advanced usage; use it with care!
|
||||
* @param destinationName the desired destination (can be {@code null})
|
||||
* @see #setDestination(javax.jms.Destination)
|
||||
*/
|
||||
public void setDestinationName(@Nullable String destinationName) {
|
||||
public void setDestinationName(String destinationName) {
|
||||
Assert.notNull(destinationName, "'destinationName' must not be null");
|
||||
this.destination = destinationName;
|
||||
}
|
||||
@@ -302,6 +287,7 @@ public abstract class AbstractMessageListenerContainer extends AbstractJmsListen
|
||||
/**
|
||||
* Return the message listener object to register.
|
||||
*/
|
||||
@Nullable
|
||||
public Object getMessageListener() {
|
||||
return this.messageListener;
|
||||
}
|
||||
@@ -780,7 +766,7 @@ public abstract class AbstractMessageListenerContainer extends AbstractJmsListen
|
||||
* @param message the Message to acknowledge
|
||||
* @throws javax.jms.JMSException in case of commit failure
|
||||
*/
|
||||
protected void commitIfNecessary(Session session, Message message) throws JMSException {
|
||||
protected void commitIfNecessary(Session session, @Nullable Message message) throws JMSException {
|
||||
// Commit session or acknowledge message.
|
||||
if (session.getTransacted()) {
|
||||
// Commit necessary - but avoid commit call within a JTA transaction.
|
||||
@@ -835,17 +821,9 @@ public abstract class AbstractMessageListenerContainer extends AbstractJmsListen
|
||||
catch (IllegalStateException ex2) {
|
||||
logger.debug("Could not roll back because Session already closed", ex2);
|
||||
}
|
||||
catch (JMSException ex2) {
|
||||
logger.error("Application exception overridden by rollback exception", ex);
|
||||
throw ex2;
|
||||
}
|
||||
catch (RuntimeException ex2) {
|
||||
logger.error("Application exception overridden by rollback exception", ex);
|
||||
throw ex2;
|
||||
}
|
||||
catch (Error err) {
|
||||
catch (JMSException | RuntimeException | Error ex2) {
|
||||
logger.error("Application exception overridden by rollback error", ex);
|
||||
throw err;
|
||||
throw ex2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -873,27 +851,12 @@ public abstract class AbstractMessageListenerContainer extends AbstractJmsListen
|
||||
* @return the new JMS MessageConsumer
|
||||
* @throws javax.jms.JMSException if thrown by JMS API methods
|
||||
*/
|
||||
@Nullable
|
||||
protected MessageConsumer createConsumer(Session session, Destination destination) throws JMSException {
|
||||
if (isPubSubDomain() && destination instanceof Topic) {
|
||||
if (isSubscriptionShared()) {
|
||||
// createSharedConsumer((Topic) dest, subscription, selector);
|
||||
// createSharedDurableConsumer((Topic) dest, subscription, selector);
|
||||
Method method = (isSubscriptionDurable() ?
|
||||
createSharedDurableConsumerMethod : createSharedConsumerMethod);
|
||||
try {
|
||||
return (MessageConsumer) method.invoke(session, destination, getSubscriptionName(), getMessageSelector());
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
if (ex.getTargetException() instanceof JMSException) {
|
||||
throw (JMSException) ex.getTargetException();
|
||||
}
|
||||
ReflectionUtils.handleInvocationTargetException(ex);
|
||||
return null;
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new IllegalStateException("Could not access JMS 2.0 API method: " + ex.getMessage());
|
||||
}
|
||||
return (isSubscriptionDurable() ?
|
||||
session.createSharedDurableConsumer((Topic) destination, getSubscriptionName(), getMessageSelector()) :
|
||||
session.createSharedConsumer((Topic) destination, getSubscriptionName(), getMessageSelector()));
|
||||
}
|
||||
else if (isSubscriptionDurable()) {
|
||||
return session.createDurableSubscriber(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -34,6 +34,7 @@ import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
import org.springframework.transaction.support.ResourceTransactionManager;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Base class for listener container implementations which are based on polling.
|
||||
@@ -129,6 +130,7 @@ public abstract class AbstractPollingMessageListenerContainer extends AbstractMe
|
||||
* Return the Spring PlatformTransactionManager to use for transactional
|
||||
* wrapping of message reception plus listener execution.
|
||||
*/
|
||||
@Nullable
|
||||
protected final PlatformTransactionManager getTransactionManager() {
|
||||
return this.transactionManager;
|
||||
}
|
||||
@@ -186,13 +188,16 @@ public abstract class AbstractPollingMessageListenerContainer extends AbstractMe
|
||||
if (!this.sessionTransactedCalled &&
|
||||
this.transactionManager instanceof ResourceTransactionManager &&
|
||||
!TransactionSynchronizationUtils.sameResourceFactory(
|
||||
(ResourceTransactionManager) this.transactionManager, getConnectionFactory())) {
|
||||
(ResourceTransactionManager) this.transactionManager, obtainConnectionFactory())) {
|
||||
super.setSessionTransacted(true);
|
||||
}
|
||||
|
||||
// Use bean name as default transaction name.
|
||||
if (this.transactionDefinition.getName() == null) {
|
||||
this.transactionDefinition.setName(getBeanName());
|
||||
String beanName = getBeanName();
|
||||
if (beanName != null) {
|
||||
this.transactionDefinition.setName(beanName);
|
||||
}
|
||||
}
|
||||
|
||||
// Proceed with superclass initialization.
|
||||
@@ -211,7 +216,9 @@ public abstract class AbstractPollingMessageListenerContainer extends AbstractMe
|
||||
protected MessageConsumer createListenerConsumer(Session session) throws JMSException {
|
||||
Destination destination = getDestination();
|
||||
if (destination == null) {
|
||||
destination = resolveDestinationName(session, getDestinationName());
|
||||
String destinationName = getDestinationName();
|
||||
Assert.state(destinationName != null, "No destination set");
|
||||
destination = resolveDestinationName(session, destinationName);
|
||||
}
|
||||
return createConsumer(session, destination);
|
||||
}
|
||||
@@ -267,9 +274,8 @@ public abstract class AbstractPollingMessageListenerContainer extends AbstractMe
|
||||
* @throws JMSException if thrown by JMS methods
|
||||
* @see #doExecuteListener(javax.jms.Session, javax.jms.Message)
|
||||
*/
|
||||
protected boolean doReceiveAndExecute(
|
||||
Object invoker, Session session, MessageConsumer consumer, @Nullable TransactionStatus status)
|
||||
throws JMSException {
|
||||
protected boolean doReceiveAndExecute(Object invoker, @Nullable Session session,
|
||||
@Nullable MessageConsumer consumer, @Nullable TransactionStatus status) throws JMSException {
|
||||
|
||||
Connection conToClose = null;
|
||||
Session sessionToClose = null;
|
||||
@@ -279,7 +285,7 @@ public abstract class AbstractPollingMessageListenerContainer extends AbstractMe
|
||||
boolean transactional = false;
|
||||
if (sessionToUse == null) {
|
||||
sessionToUse = ConnectionFactoryUtils.doGetTransactionalSession(
|
||||
getConnectionFactory(), this.transactionalResourceFactory, true);
|
||||
obtainConnectionFactory(), this.transactionalResourceFactory, true);
|
||||
transactional = (sessionToUse != null);
|
||||
}
|
||||
if (sessionToUse == null) {
|
||||
@@ -309,10 +315,10 @@ public abstract class AbstractPollingMessageListenerContainer extends AbstractMe
|
||||
}
|
||||
messageReceived(invoker, sessionToUse);
|
||||
boolean exposeResource = (!transactional && isExposeListenerSession() &&
|
||||
!TransactionSynchronizationManager.hasResource(getConnectionFactory()));
|
||||
!TransactionSynchronizationManager.hasResource(obtainConnectionFactory()));
|
||||
if (exposeResource) {
|
||||
TransactionSynchronizationManager.bindResource(
|
||||
getConnectionFactory(), new LocallyExposedJmsResourceHolder(sessionToUse));
|
||||
obtainConnectionFactory(), new LocallyExposedJmsResourceHolder(sessionToUse));
|
||||
}
|
||||
try {
|
||||
doExecuteListener(sessionToUse, message);
|
||||
@@ -333,7 +339,7 @@ public abstract class AbstractPollingMessageListenerContainer extends AbstractMe
|
||||
}
|
||||
finally {
|
||||
if (exposeResource) {
|
||||
TransactionSynchronizationManager.unbindResource(getConnectionFactory());
|
||||
TransactionSynchronizationManager.unbindResource(obtainConnectionFactory());
|
||||
}
|
||||
}
|
||||
// Indicate that a message has been received.
|
||||
@@ -347,7 +353,7 @@ public abstract class AbstractPollingMessageListenerContainer extends AbstractMe
|
||||
noMessageReceived(invoker, sessionToUse);
|
||||
// Nevertheless call commit, in order to reset the transaction timeout (if any).
|
||||
if (shouldCommitAfterNoMessageReceived(sessionToUse)) {
|
||||
commitIfNecessary(sessionToUse, message);
|
||||
commitIfNecessary(sessionToUse, null);
|
||||
}
|
||||
// Indicate that no message has been received.
|
||||
return false;
|
||||
@@ -372,7 +378,7 @@ public abstract class AbstractPollingMessageListenerContainer extends AbstractMe
|
||||
return false;
|
||||
}
|
||||
JmsResourceHolder resourceHolder =
|
||||
(JmsResourceHolder) TransactionSynchronizationManager.getResource(getConnectionFactory());
|
||||
(JmsResourceHolder) TransactionSynchronizationManager.getResource(obtainConnectionFactory());
|
||||
return (resourceHolder == null || resourceHolder instanceof LocallyExposedJmsResourceHolder ||
|
||||
!resourceHolder.containsSession(session));
|
||||
}
|
||||
@@ -413,6 +419,7 @@ public abstract class AbstractPollingMessageListenerContainer extends AbstractMe
|
||||
* @return the Message, or {@code null} if none
|
||||
* @throws JMSException if thrown by JMS methods
|
||||
*/
|
||||
@Nullable
|
||||
protected Message receiveMessage(MessageConsumer consumer) throws JMSException {
|
||||
return receiveFromConsumer(consumer, getReceiveTimeout());
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||
* @see #setCacheLevel
|
||||
*/
|
||||
public void setCacheLevelName(String constantName) throws IllegalArgumentException {
|
||||
if (constantName == null || !constantName.startsWith("CACHE_")) {
|
||||
if (!constantName.startsWith("CACHE_")) {
|
||||
throw new IllegalArgumentException("Only cache constants allowed");
|
||||
}
|
||||
setCacheLevel(constants.asNumber(constantName).intValue());
|
||||
|
||||
@@ -67,8 +67,8 @@ public interface MessageListenerContainer extends SmartLifecycle {
|
||||
boolean isReplyPubSubDomain();
|
||||
|
||||
/**
|
||||
* Return the {@link QosSettings} to use when sending a reply or {@code null}
|
||||
* if the broker's defaults should be used.
|
||||
* Return the {@link QosSettings} to use when sending a reply,
|
||||
* or {@code null} if the broker's defaults should be used.
|
||||
* @since 5.0
|
||||
*/
|
||||
@Nullable
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -54,6 +54,6 @@ public interface SessionAwareMessageListener<M extends Message> {
|
||||
* @param session the underlying JMS Session (never {@code null})
|
||||
* @throws JMSException if thrown by JMS methods
|
||||
*/
|
||||
void onMessage(M message, @Nullable Session session) throws JMSException;
|
||||
void onMessage(M message, Session session) throws JMSException;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -20,12 +20,12 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.ExceptionListener;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageListener;
|
||||
import javax.jms.Session;
|
||||
|
||||
import org.springframework.jms.support.JmsUtils;
|
||||
@@ -282,30 +282,17 @@ public class SimpleMessageListenerContainer extends AbstractMessageListenerConta
|
||||
protected MessageConsumer createListenerConsumer(final Session session) throws JMSException {
|
||||
Destination destination = getDestination();
|
||||
if (destination == null) {
|
||||
destination = resolveDestinationName(session, getDestinationName());
|
||||
String destinationName = getDestinationName();
|
||||
Assert.state(destinationName != null, "No destination set");
|
||||
destination = resolveDestinationName(session, destinationName);
|
||||
}
|
||||
MessageConsumer consumer = createConsumer(session, destination);
|
||||
|
||||
if (this.taskExecutor != null) {
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(final Message message) {
|
||||
taskExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
processMessage(message, session);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
consumer.setMessageListener(message -> taskExecutor.execute(() -> processMessage(message, session)));
|
||||
}
|
||||
else {
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
processMessage(message, session);
|
||||
}
|
||||
});
|
||||
consumer.setMessageListener(message -> processMessage(message, session));
|
||||
}
|
||||
|
||||
return consumer;
|
||||
@@ -321,10 +308,11 @@ public class SimpleMessageListenerContainer extends AbstractMessageListenerConta
|
||||
* @see #setExposeListenerSession
|
||||
*/
|
||||
protected void processMessage(Message message, Session session) {
|
||||
boolean exposeResource = isExposeListenerSession();
|
||||
ConnectionFactory connectionFactory = getConnectionFactory();
|
||||
boolean exposeResource = (connectionFactory != null && isExposeListenerSession());
|
||||
if (exposeResource) {
|
||||
TransactionSynchronizationManager.bindResource(
|
||||
getConnectionFactory(), new LocallyExposedJmsResourceHolder(session));
|
||||
connectionFactory, new LocallyExposedJmsResourceHolder(session));
|
||||
}
|
||||
try {
|
||||
executeListener(session, message);
|
||||
|
||||
@@ -70,6 +70,7 @@ public abstract class AbstractAdaptableMessageListener
|
||||
|
||||
private QosSettings responseQosSettings;
|
||||
|
||||
|
||||
/**
|
||||
* Set the default destination to send response messages to. This will be applied
|
||||
* in case of a request message that does not carry a "JMSReplyTo" field.
|
||||
@@ -148,6 +149,7 @@ public abstract class AbstractAdaptableMessageListener
|
||||
* listener method arguments, and objects returned from listener
|
||||
* methods back to JMS messages.
|
||||
*/
|
||||
@Nullable
|
||||
protected MessageConverter getMessageConverter() {
|
||||
return this.messageConverter;
|
||||
}
|
||||
@@ -182,14 +184,15 @@ public abstract class AbstractAdaptableMessageListener
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link QosSettings} to use when sending a response or {@code null} if
|
||||
* the defaults should be used.
|
||||
* Return the {@link QosSettings} to use when sending a response,
|
||||
* or {@code null} if the defaults should be used.
|
||||
*/
|
||||
@Nullable
|
||||
protected QosSettings getResponseQosSettings() {
|
||||
return this.responseQosSettings;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Standard JMS {@link MessageListener} entry point.
|
||||
* <p>Delegates the message to the target listener method, with appropriate
|
||||
@@ -213,6 +216,9 @@ public abstract class AbstractAdaptableMessageListener
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract void onMessage(Message message, @Nullable Session session) throws JMSException;
|
||||
|
||||
/**
|
||||
* Handle the given exception that arose during listener execution.
|
||||
* The default implementation logs the exception at error level.
|
||||
@@ -226,6 +232,7 @@ public abstract class AbstractAdaptableMessageListener
|
||||
logger.error("Listener execution failed", ex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract the message body from the given JMS message.
|
||||
* @param message the JMS {@code Message}
|
||||
@@ -457,9 +464,6 @@ public abstract class AbstractAdaptableMessageListener
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Object fromMessage(javax.jms.Message message) throws JMSException, MessageConversionException {
|
||||
if (message == null) {
|
||||
return null;
|
||||
}
|
||||
return new LazyResolutionMessage(message);
|
||||
}
|
||||
|
||||
@@ -481,8 +485,9 @@ public abstract class AbstractAdaptableMessageListener
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Message createMessageForPayload(Object payload, Session session, Object conversionHint)
|
||||
protected Message createMessageForPayload(Object payload, Session session, @Nullable Object conversionHint)
|
||||
throws JMSException {
|
||||
|
||||
MessageConverter converter = getMessageConverter();
|
||||
if (converter == null) {
|
||||
throw new IllegalStateException("No message converter, cannot handle '" + payload + "'");
|
||||
@@ -494,6 +499,7 @@ public abstract class AbstractAdaptableMessageListener
|
||||
return converter.toMessage(payload, session);
|
||||
}
|
||||
|
||||
|
||||
protected class LazyResolutionMessage implements org.springframework.messaging.Message<Object> {
|
||||
|
||||
private final javax.jms.Message message;
|
||||
@@ -517,7 +523,6 @@ public abstract class AbstractAdaptableMessageListener
|
||||
"Failed to extract payload from [" + this.message + "]", ex);
|
||||
}
|
||||
}
|
||||
//
|
||||
return this.payload;
|
||||
}
|
||||
|
||||
@@ -543,7 +548,6 @@ public abstract class AbstractAdaptableMessageListener
|
||||
return this.headers;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -196,20 +196,14 @@ public class MessageListenerAdapter extends AbstractAdaptableMessageListener imp
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void onMessage(Message message, @Nullable Session session) throws JMSException {
|
||||
public void onMessage(Message message, Session session) throws JMSException {
|
||||
// Check whether the delegate is a MessageListener impl itself.
|
||||
// In that case, the adapter will simply act as a pass-through.
|
||||
Object delegate = getDelegate();
|
||||
if (delegate != this) {
|
||||
if (delegate instanceof SessionAwareMessageListener) {
|
||||
if (session != null) {
|
||||
((SessionAwareMessageListener<Message>) delegate).onMessage(message, session);
|
||||
return;
|
||||
}
|
||||
else if (!(delegate instanceof MessageListener)) {
|
||||
throw new javax.jms.IllegalStateException("MessageListenerAdapter cannot handle a " +
|
||||
"SessionAwareMessageListener delegate if it hasn't been invoked with a Session itself");
|
||||
}
|
||||
((SessionAwareMessageListener<Message>) delegate).onMessage(message, session);
|
||||
return;
|
||||
}
|
||||
if (delegate instanceof MessageListener) {
|
||||
((MessageListener) delegate).onMessage(message);
|
||||
@@ -260,6 +254,7 @@ public class MessageListenerAdapter extends AbstractAdaptableMessageListener imp
|
||||
* @throws JMSException if thrown by JMS API methods
|
||||
* @see #setDefaultListenerMethod
|
||||
*/
|
||||
@Nullable
|
||||
protected String getListenerMethodName(Message originalMessage, Object extractedMessage) throws JMSException {
|
||||
return getDefaultListenerMethod();
|
||||
}
|
||||
@@ -292,6 +287,7 @@ public class MessageListenerAdapter extends AbstractAdaptableMessageListener imp
|
||||
* @see #getListenerMethodName
|
||||
* @see #buildListenerArguments
|
||||
*/
|
||||
@Nullable
|
||||
protected Object invokeListenerMethod(String methodName, Object[] arguments) throws JMSException {
|
||||
try {
|
||||
MethodInvoker methodInvoker = new MethodInvoker();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -62,7 +62,7 @@ public class MessagingMessageListenerAdapter extends AbstractAdaptableMessageLis
|
||||
|
||||
|
||||
@Override
|
||||
public void onMessage(javax.jms.Message jmsMessage, @Nullable Session session) throws JMSException {
|
||||
public void onMessage(javax.jms.Message jmsMessage, Session session) throws JMSException {
|
||||
Message<?> message = toMessagingMessage(jmsMessage);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Processing [" + message + "]");
|
||||
@@ -100,6 +100,7 @@ public class MessagingMessageListenerAdapter extends AbstractAdaptableMessageLis
|
||||
* Invoke the handler, wrapping any exception to a {@link ListenerExecutionFailedException}
|
||||
* with a dedicated error message.
|
||||
*/
|
||||
@Nullable
|
||||
private Object invokeHandler(javax.jms.Message jmsMessage, Session session, Message<?> message) {
|
||||
try {
|
||||
return this.handlerMethod.invoke(message, jmsMessage, session);
|
||||
|
||||
@@ -134,6 +134,7 @@ public class JmsActivationSpecConfig {
|
||||
this.subscriptionName = subscriptionName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getSubscriptionName() {
|
||||
return this.subscriptionName;
|
||||
}
|
||||
@@ -143,6 +144,7 @@ public class JmsActivationSpecConfig {
|
||||
this.subscriptionDurable = true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getDurableSubscriptionName() {
|
||||
return (this.subscriptionDurable ? this.subscriptionName : null);
|
||||
}
|
||||
@@ -151,6 +153,7 @@ public class JmsActivationSpecConfig {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getClientId() {
|
||||
return this.clientId;
|
||||
}
|
||||
@@ -159,6 +162,7 @@ public class JmsActivationSpecConfig {
|
||||
this.messageSelector = messageSelector;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getMessageSelector() {
|
||||
return this.messageSelector;
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ public class JmsMessageEndpointManager extends GenericMessageEndpointManager
|
||||
* (plus a couple of autodetected vendor-specific properties).
|
||||
* @see DefaultJmsActivationSpecFactory
|
||||
*/
|
||||
public void setActivationSpecFactory(JmsActivationSpecFactory activationSpecFactory) {
|
||||
public void setActivationSpecFactory(@Nullable JmsActivationSpecFactory activationSpecFactory) {
|
||||
this.activationSpecFactory =
|
||||
(activationSpecFactory != null ? activationSpecFactory : new DefaultJmsActivationSpecFactory());
|
||||
}
|
||||
@@ -162,6 +162,9 @@ public class JmsMessageEndpointManager extends GenericMessageEndpointManager
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws ResourceException {
|
||||
if (getResourceAdapter() == null) {
|
||||
throw new IllegalArgumentException("Property 'resourceAdapter' is required");
|
||||
}
|
||||
if (this.messageListenerSet) {
|
||||
setMessageEndpointFactory(this.endpointFactory);
|
||||
}
|
||||
@@ -169,6 +172,7 @@ public class JmsMessageEndpointManager extends GenericMessageEndpointManager
|
||||
setActivationSpec(
|
||||
this.activationSpecFactory.createActivationSpec(getResourceAdapter(), this.activationSpecConfig));
|
||||
}
|
||||
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.jms.listener.endpoint;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Session;
|
||||
@@ -88,17 +87,19 @@ public class StandardJmsActivationSpecFactory implements JmsActivationSpecFactor
|
||||
* or {@link org.springframework.jms.support.destination.BeanFactoryDestinationResolver}
|
||||
* but not {@link org.springframework.jms.support.destination.DynamicDestinationResolver}.
|
||||
*/
|
||||
public void setDestinationResolver(DestinationResolver destinationResolver) {
|
||||
public void setDestinationResolver(@Nullable DestinationResolver destinationResolver) {
|
||||
this.destinationResolver = destinationResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link DestinationResolver} to use for resolving destinations names.
|
||||
*/
|
||||
@Nullable
|
||||
public DestinationResolver getDestinationResolver() {
|
||||
return destinationResolver;
|
||||
return this.destinationResolver;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ActivationSpec createActivationSpec(ResourceAdapter adapter, JmsActivationSpecConfig config) {
|
||||
Class<?> activationSpecClassToUse = this.activationSpecClass;
|
||||
|
||||
@@ -38,6 +38,7 @@ 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;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.remoting.RemoteAccessException;
|
||||
import org.springframework.remoting.RemoteInvocationFailureException;
|
||||
import org.springframework.remoting.RemoteTimeoutException;
|
||||
@@ -45,6 +46,7 @@ import org.springframework.remoting.support.DefaultRemoteInvocationFactory;
|
||||
import org.springframework.remoting.support.RemoteInvocation;
|
||||
import org.springframework.remoting.support.RemoteInvocationFactory;
|
||||
import org.springframework.remoting.support.RemoteInvocationResult;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link org.aopalliance.intercept.MethodInterceptor} for accessing a
|
||||
@@ -95,6 +97,7 @@ public class JmsInvokerClientInterceptor implements MethodInterceptor, Initializ
|
||||
/**
|
||||
* Return the QueueConnectionFactory to use for obtaining JMS QueueConnections.
|
||||
*/
|
||||
@Nullable
|
||||
protected ConnectionFactory getConnectionFactory() {
|
||||
return this.connectionFactory;
|
||||
}
|
||||
@@ -123,7 +126,7 @@ public class JmsInvokerClientInterceptor implements MethodInterceptor, Initializ
|
||||
* @see org.springframework.jms.support.destination.DynamicDestinationResolver
|
||||
* @see org.springframework.jms.support.destination.JndiDestinationResolver
|
||||
*/
|
||||
public void setDestinationResolver(DestinationResolver destinationResolver) {
|
||||
public void setDestinationResolver(@Nullable DestinationResolver destinationResolver) {
|
||||
this.destinationResolver =
|
||||
(destinationResolver != null ? destinationResolver : new DynamicDestinationResolver());
|
||||
}
|
||||
@@ -134,7 +137,7 @@ public class JmsInvokerClientInterceptor implements MethodInterceptor, Initializ
|
||||
* <p>A custom invocation factory can add further context information
|
||||
* to the invocation, for example user credentials.
|
||||
*/
|
||||
public void setRemoteInvocationFactory(RemoteInvocationFactory remoteInvocationFactory) {
|
||||
public void setRemoteInvocationFactory(@Nullable RemoteInvocationFactory remoteInvocationFactory) {
|
||||
this.remoteInvocationFactory =
|
||||
(remoteInvocationFactory != null ? remoteInvocationFactory : new DefaultRemoteInvocationFactory());
|
||||
}
|
||||
@@ -151,7 +154,7 @@ public class JmsInvokerClientInterceptor implements MethodInterceptor, Initializ
|
||||
* objects into special kinds of messages, or might be specifically tailored for
|
||||
* translating {@code RemoteInvocation(Result)s} into specific kinds of messages.
|
||||
*/
|
||||
public void setMessageConverter(MessageConverter messageConverter) {
|
||||
public void setMessageConverter(@Nullable MessageConverter messageConverter) {
|
||||
this.messageConverter = (messageConverter != null ? messageConverter : new SimpleMessageConverter());
|
||||
}
|
||||
|
||||
@@ -263,7 +266,9 @@ public class JmsInvokerClientInterceptor implements MethodInterceptor, Initializ
|
||||
* Create a new JMS Connection for this JMS invoker.
|
||||
*/
|
||||
protected Connection createConnection() throws JMSException {
|
||||
return getConnectionFactory().createConnection();
|
||||
ConnectionFactory connectionFactory = getConnectionFactory();
|
||||
Assert.state(connectionFactory != null, "No ConnectionFactory set");
|
||||
return connectionFactory.createConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -329,6 +334,7 @@ public class JmsInvokerClientInterceptor implements MethodInterceptor, Initializ
|
||||
* @return the RemoteInvocationResult object
|
||||
* @throws JMSException in case of JMS failure
|
||||
*/
|
||||
@Nullable
|
||||
protected Message doExecuteRequest(Session session, Queue queue, Message requestMessage) throws JMSException {
|
||||
TemporaryQueue responseQueue = null;
|
||||
MessageProducer producer = null;
|
||||
@@ -408,6 +414,7 @@ public class JmsInvokerClientInterceptor implements MethodInterceptor, Initializ
|
||||
* @throws Throwable if the invocation result is an exception
|
||||
* @see org.springframework.remoting.support.RemoteInvocationResult#recreate()
|
||||
*/
|
||||
@Nullable
|
||||
protected Object recreateRemoteInvocationResult(RemoteInvocationResult result) throws Throwable {
|
||||
return result.recreate();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -20,6 +20,7 @@ import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
@@ -55,18 +56,18 @@ public class JmsInvokerProxyFactoryBean extends JmsInvokerClientInterceptor
|
||||
* Set the interface that the proxy must implement.
|
||||
* @param serviceInterface the interface that the proxy must implement
|
||||
* @throws IllegalArgumentException if the supplied {@code serviceInterface}
|
||||
* is {@code null}, or if the supplied {@code serviceInterface}
|
||||
* is not an interface type
|
||||
*/
|
||||
public void setServiceInterface(Class<?> serviceInterface) {
|
||||
if (serviceInterface == null || !serviceInterface.isInterface()) {
|
||||
Assert.notNull(serviceInterface, "'serviceInterface' must not be null");
|
||||
if (!serviceInterface.isInterface()) {
|
||||
throw new IllegalArgumentException("'serviceInterface' must be an interface");
|
||||
}
|
||||
this.serviceInterface = serviceInterface;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(@Nullable ClassLoader classLoader) {
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -74,7 +74,7 @@ public class JmsInvokerServiceExporter extends RemoteInvocationBasedExporter
|
||||
* special kinds of messages, or might be specifically tailored for
|
||||
* translating RemoteInvocation(Result)s into specific kinds of messages.
|
||||
*/
|
||||
public void setMessageConverter(MessageConverter messageConverter) {
|
||||
public void setMessageConverter(@Nullable MessageConverter messageConverter) {
|
||||
this.messageConverter = (messageConverter != null ? messageConverter : new SimpleMessageConverter());
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ public class JmsInvokerServiceExporter extends RemoteInvocationBasedExporter
|
||||
|
||||
|
||||
@Override
|
||||
public void onMessage(Message requestMessage, @Nullable Session session) throws JMSException {
|
||||
public void onMessage(Message requestMessage, Session session) throws JMSException {
|
||||
RemoteInvocation invocation = readRemoteInvocation(requestMessage);
|
||||
if (invocation != null) {
|
||||
RemoteInvocationResult result = invokeAndCreateResult(invocation, this.proxy);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -27,6 +27,8 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.Constants;
|
||||
import org.springframework.jms.JmsException;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Base class for {@link org.springframework.jms.core.JmsTemplate} and other
|
||||
@@ -70,10 +72,23 @@ public abstract class JmsAccessor implements InitializingBean {
|
||||
* Return the ConnectionFactory that this accessor uses for obtaining
|
||||
* JMS {@link Connection Connections}.
|
||||
*/
|
||||
@Nullable
|
||||
public ConnectionFactory getConnectionFactory() {
|
||||
return this.connectionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the ConnectionFactory for actual use.
|
||||
* @return the ConnectionFactory (never {@code null})
|
||||
* @throws IllegalStateException in case of no ConnectionFactory set
|
||||
* @since 5.0
|
||||
*/
|
||||
protected final ConnectionFactory obtainConnectionFactory() {
|
||||
ConnectionFactory connectionFactory = getConnectionFactory();
|
||||
Assert.state(connectionFactory != null, "No ConnectionFactory set");
|
||||
return connectionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the transaction mode that is used when creating a JMS {@link Session}.
|
||||
* Default is "false".
|
||||
@@ -177,7 +192,7 @@ public abstract class JmsAccessor implements InitializingBean {
|
||||
* @see javax.jms.ConnectionFactory#createConnection()
|
||||
*/
|
||||
protected Connection createConnection() throws JMSException {
|
||||
return getConnectionFactory().createConnection();
|
||||
return obtainConnectionFactory().createConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -20,6 +20,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.jms.Destination;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.NativeMessageHeaderAccessor;
|
||||
|
||||
@@ -45,6 +46,7 @@ public class JmsMessageHeaderAccessor extends NativeMessageHeaderAccessor {
|
||||
* Return the {@link JmsHeaders#CORRELATION_ID correlationId}.
|
||||
* @see JmsHeaders#CORRELATION_ID
|
||||
*/
|
||||
@Nullable
|
||||
public String getCorrelationId() {
|
||||
return (String) getHeader(JmsHeaders.CORRELATION_ID);
|
||||
}
|
||||
@@ -53,6 +55,7 @@ public class JmsMessageHeaderAccessor extends NativeMessageHeaderAccessor {
|
||||
* Return the {@link JmsHeaders#DESTINATION destination}.
|
||||
* @see JmsHeaders#DESTINATION
|
||||
*/
|
||||
@Nullable
|
||||
public Destination getDestination() {
|
||||
return (Destination) getHeader(JmsHeaders.DESTINATION);
|
||||
}
|
||||
@@ -61,6 +64,7 @@ public class JmsMessageHeaderAccessor extends NativeMessageHeaderAccessor {
|
||||
* Return the {@link JmsHeaders#DELIVERY_MODE delivery mode}.
|
||||
* @see JmsHeaders#DELIVERY_MODE
|
||||
*/
|
||||
@Nullable
|
||||
public Integer getDeliveryMode() {
|
||||
return (Integer) getHeader(JmsHeaders.DELIVERY_MODE);
|
||||
}
|
||||
@@ -69,6 +73,7 @@ public class JmsMessageHeaderAccessor extends NativeMessageHeaderAccessor {
|
||||
* Return the message {@link JmsHeaders#EXPIRATION expiration}.
|
||||
* @see JmsHeaders#EXPIRATION
|
||||
*/
|
||||
@Nullable
|
||||
public Long getExpiration() {
|
||||
return (Long) getHeader(JmsHeaders.EXPIRATION);
|
||||
}
|
||||
@@ -77,6 +82,7 @@ public class JmsMessageHeaderAccessor extends NativeMessageHeaderAccessor {
|
||||
* Return the {@link JmsHeaders#MESSAGE_ID message id}.
|
||||
* @see JmsHeaders#MESSAGE_ID
|
||||
*/
|
||||
@Nullable
|
||||
public String getMessageId() {
|
||||
return (String) getHeader(JmsHeaders.MESSAGE_ID);
|
||||
}
|
||||
@@ -85,6 +91,7 @@ public class JmsMessageHeaderAccessor extends NativeMessageHeaderAccessor {
|
||||
* Return the {@link JmsHeaders#PRIORITY}.
|
||||
* @see JmsHeaders#PRIORITY
|
||||
*/
|
||||
@Nullable
|
||||
public Integer getPriority() {
|
||||
return (Integer) getHeader(JmsHeaders.PRIORITY);
|
||||
}
|
||||
@@ -93,6 +100,7 @@ public class JmsMessageHeaderAccessor extends NativeMessageHeaderAccessor {
|
||||
* Return the {@link JmsHeaders#REPLY_TO reply to}.
|
||||
* @see JmsHeaders#REPLY_TO
|
||||
*/
|
||||
@Nullable
|
||||
public Destination getReplyTo() {
|
||||
return (Destination) getHeader(JmsHeaders.REPLY_TO);
|
||||
}
|
||||
@@ -101,6 +109,7 @@ public class JmsMessageHeaderAccessor extends NativeMessageHeaderAccessor {
|
||||
* Return the {@link JmsHeaders#REDELIVERED redelivered} flag.
|
||||
* @see JmsHeaders#REDELIVERED
|
||||
*/
|
||||
@Nullable
|
||||
public Boolean getRedelivered() {
|
||||
return (Boolean) getHeader(JmsHeaders.REDELIVERED);
|
||||
}
|
||||
@@ -109,6 +118,7 @@ public class JmsMessageHeaderAccessor extends NativeMessageHeaderAccessor {
|
||||
* Return the {@link JmsHeaders#TYPE type}.
|
||||
* @see JmsHeaders#TYPE
|
||||
*/
|
||||
@Nullable
|
||||
public String getType() {
|
||||
return (String) getHeader(JmsHeaders.TYPE);
|
||||
}
|
||||
@@ -117,6 +127,7 @@ public class JmsMessageHeaderAccessor extends NativeMessageHeaderAccessor {
|
||||
* Return the {@link JmsHeaders#TIMESTAMP timestamp}.
|
||||
* @see JmsHeaders#TIMESTAMP
|
||||
*/
|
||||
@Nullable
|
||||
public Long getTimestamp() {
|
||||
return (Long) getHeader(JmsHeaders.TIMESTAMP);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ package org.springframework.jms.support;
|
||||
import javax.jms.Message;
|
||||
|
||||
/**
|
||||
* Gather the Quality of Service settings that can be used when sending a message.
|
||||
* Gather the Quality-of-Service settings that can be used when sending a message.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 5.0
|
||||
@@ -32,6 +32,7 @@ public class QosSettings {
|
||||
|
||||
private long timeToLive;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance with the default settings.
|
||||
* @see Message#DEFAULT_DELIVERY_MODE
|
||||
@@ -39,8 +40,7 @@ public class QosSettings {
|
||||
* @see Message#DEFAULT_TIME_TO_LIVE
|
||||
*/
|
||||
public QosSettings() {
|
||||
this(Message.DEFAULT_DELIVERY_MODE, Message.DEFAULT_PRIORITY,
|
||||
Message.DEFAULT_TIME_TO_LIVE);
|
||||
this(Message.DEFAULT_DELIVERY_MODE, Message.DEFAULT_PRIORITY, Message.DEFAULT_TIME_TO_LIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,6 +52,7 @@ public class QosSettings {
|
||||
this.timeToLive = timeToLive;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the delivery mode to use when sending a message.
|
||||
* Default is the JMS Message default: "PERSISTENT".
|
||||
@@ -105,31 +106,30 @@ public class QosSettings {
|
||||
return this.timeToLive;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof QosSettings)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QosSettings that = (QosSettings) o;
|
||||
|
||||
if (this.deliveryMode != that.deliveryMode) return false;
|
||||
if (this.priority != that.priority) return false;
|
||||
return this.timeToLive == that.timeToLive;
|
||||
QosSettings otherSettings = (QosSettings) other;
|
||||
return (this.deliveryMode == otherSettings.deliveryMode &&
|
||||
this.priority == otherSettings.priority &&
|
||||
this.timeToLive == otherSettings.timeToLive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = this.deliveryMode;
|
||||
result = 31 * result + this.priority;
|
||||
result = 31 * result + (int) (this.timeToLive ^ (this.timeToLive >>> 32));
|
||||
return result;
|
||||
return (this.deliveryMode * 31 + this.priority);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "QosSettings{" + "deliveryMode=" + deliveryMode +
|
||||
", priority=" + priority +
|
||||
", timeToLive=" + timeToLive +
|
||||
'}';
|
||||
return "QosSettings{" + "deliveryMode=" + this.deliveryMode +
|
||||
", priority=" + this.priority + ", timeToLive=" + this.timeToLive + '}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -23,7 +23,6 @@ import java.io.StringWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.jms.BytesMessage;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
@@ -168,7 +167,7 @@ public class MappingJackson2MessageConverter implements SmartMessageConverter, B
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(@Nullable ClassLoader classLoader) {
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
|
||||
@@ -213,7 +212,7 @@ public class MappingJackson2MessageConverter implements SmartMessageConverter, B
|
||||
* @throws MessageConversionException in case of conversion failure
|
||||
* @since 4.3
|
||||
*/
|
||||
public Message toMessage(Object object, Session session, Class<?> jsonView)
|
||||
public Message toMessage(Object object, Session session, @Nullable Class<?> jsonView)
|
||||
throws JMSException, MessageConversionException {
|
||||
|
||||
if (jsonView != null) {
|
||||
@@ -459,7 +458,7 @@ public class MappingJackson2MessageConverter implements SmartMessageConverter, B
|
||||
* @return the serialization view class, or {@code null} if none
|
||||
*/
|
||||
@Nullable
|
||||
protected Class<?> getSerializationView(Object conversionHint) {
|
||||
protected Class<?> getSerializationView(@Nullable Object conversionHint) {
|
||||
if (conversionHint instanceof MethodParameter) {
|
||||
MethodParameter methodParam = (MethodParameter) conversionHint;
|
||||
JsonView annotation = methodParam.getParameterAnnotation(JsonView.class);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -20,8 +20,6 @@ import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.Session;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Strategy interface that specifies a converter between Java objects and JMS messages.
|
||||
*
|
||||
@@ -56,7 +54,6 @@ public interface MessageConverter {
|
||||
* @throws javax.jms.JMSException if thrown by JMS API methods
|
||||
* @throws MessageConversionException in case of conversion failure
|
||||
*/
|
||||
@Nullable
|
||||
Object fromMessage(Message message) throws JMSException, MessageConversionException;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -23,6 +23,7 @@ import javax.jms.Session;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.jms.support.JmsHeaderMapper;
|
||||
import org.springframework.jms.support.SimpleJmsHeaderMapper;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.core.AbstractMessagingTemplate;
|
||||
@@ -96,8 +97,7 @@ public class MessagingMessageConverter implements MessageConverter, Initializing
|
||||
}
|
||||
Message<?> input = (Message<?>) object;
|
||||
MessageHeaders headers = input.getHeaders();
|
||||
Object conversionHint = (headers != null ? headers.get(
|
||||
AbstractMessagingTemplate.CONVERSION_HINT_HEADER) : null);
|
||||
Object conversionHint = headers.get(AbstractMessagingTemplate.CONVERSION_HINT_HEADER);
|
||||
javax.jms.Message reply = createMessageForPayload(input.getPayload(), session, conversionHint);
|
||||
this.headerMapper.fromHeaders(headers, reply);
|
||||
return reply;
|
||||
@@ -106,9 +106,6 @@ public class MessagingMessageConverter implements MessageConverter, Initializing
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Object fromMessage(javax.jms.Message message) throws JMSException, MessageConversionException {
|
||||
if (message == null) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> mappedHeaders = extractHeaders(message);
|
||||
Object convertedObject = extractPayload(message);
|
||||
MessageBuilder<Object> builder = (convertedObject instanceof org.springframework.messaging.Message) ?
|
||||
@@ -131,8 +128,8 @@ public class MessagingMessageConverter implements MessageConverter, Initializing
|
||||
* @see MessageConverter#toMessage(Object, Session)
|
||||
* @since 4.3
|
||||
*/
|
||||
protected javax.jms.Message createMessageForPayload(Object payload, Session session, Object conversionHint)
|
||||
throws JMSException {
|
||||
protected javax.jms.Message createMessageForPayload(
|
||||
Object payload, Session session, @Nullable Object conversionHint) throws JMSException {
|
||||
|
||||
return this.payloadConverter.toMessage(payload, session);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user