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:
Juergen Hoeller
2017-06-07 14:17:48 +02:00
parent ffc3f6d87d
commit f813712f5b
1493 changed files with 10670 additions and 9172 deletions

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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));
}
/**

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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) {

View File

@@ -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...

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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(

View File

@@ -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());
}

View File

@@ -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());

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
}
}
}

View File

@@ -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();

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -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();
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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();
}
/**

View File

@@ -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);
}

View File

@@ -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 + '}';
}
}

View File

@@ -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);

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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);
}