diff --git a/build.gradle b/build.gradle index 67f7c1b0c5..9e5dc95155 100644 --- a/build.gradle +++ b/build.gradle @@ -32,6 +32,7 @@ configure(allprojects) { project -> version = qualifyVersionIfNecessary(version) ext.aspectjVersion = "1.8.9" + ext.beanvalVersion = "1.1.0.Final" ext.caffeineVersion = "2.3.1" ext.eclipselinkVersion = "2.6.3" ext.ehcacheVersion = "2.10.2" @@ -52,8 +53,10 @@ configure(allprojects) { project -> ext.jackson2Version = "2.8.0" ext.jasperreportsVersion = "6.2.1" // our tests fail with JR-internal NPEs against 6.2.2 and higher ext.javamailVersion = "1.5.5" + ext.jcaVersion = "1.7" ext.jettyVersion = "9.3.10.v20160621" ext.jodaVersion = "2.9.4" + ext.jpaVersion = "2.1.1" ext.jtaVersion = "1.2" ext.junitVersion = "4.12" ext.junitJupiterVersion = '5.0.0-SNAPSHOT' @@ -458,8 +461,8 @@ project("spring-context") { optional("javax.ejb:ejb-api:${ejbVersion}") optional("javax.enterprise.concurrent:javax.enterprise.concurrent-api:1.0") optional("javax.money:money-api:1.0") - optional("org.eclipse.persistence:javax.persistence:2.1.1") - optional("javax.validation:validation-api:1.1.0.Final") + optional("org.eclipse.persistence:javax.persistence:${jpaVersion}") + optional("javax.validation:validation-api:${beanvalVersion}") optional("org.hibernate:hibernate-validator:${hibval5Version}") optional("joda-time:joda-time:${jodaVersion}") optional("org.aspectj:aspectjweaver:${aspectjVersion}") @@ -494,7 +497,7 @@ project("spring-messaging") { optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}") testCompile("javax.inject:javax.inject-tck:1") testCompile("javax.servlet:javax.servlet-api:3.1.0") - testCompile("javax.validation:validation-api:1.1.0.Final") + testCompile("javax.validation:validation-api:${beanvalVersion}") testCompile("com.thoughtworks.xstream:xstream:${xstreamVersion}") testCompile("org.apache.activemq:activemq-broker:5.8.0") testCompile("org.apache.activemq:activemq-kahadb-store:5.8.0") { @@ -521,11 +524,11 @@ project("spring-tx") { optional(project(":spring-aop")) optional(project(":spring-context")) // for JCA, @EnableTransactionManagement optional("javax.transaction:javax.transaction-api:${jtaVersion}") - optional("javax.resource:connector-api:1.5") + optional("javax.resource:javax.resource-api:${jcaVersion}") optional("javax.ejb:ejb-api:${ejbVersion}") optional("com.ibm.websphere:uow:6.0.2.17") testCompile("org.aspectj:aspectjweaver:${aspectjVersion}") - testCompile("org.eclipse.persistence:javax.persistence:2.1.1") + testCompile("org.eclipse.persistence:javax.persistence:${jpaVersion}") testCompile("org.codehaus.groovy:groovy-all:${groovyVersion}") } } @@ -576,10 +579,10 @@ project("spring-jms") { compile(project(":spring-context")) compile(project(":spring-messaging")) compile(project(":spring-tx")) - provided("javax.jms:jms-api:1.1-rev-1") + provided("javax.jms:javax.jms-api:2.0.1") optional(project(":spring-oxm")) optional("javax.transaction:javax.transaction-api:${jtaVersion}") - optional("javax.resource:connector-api:1.5") + optional("javax.resource:javax.resource-api:${jcaVersion}") optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}") } } @@ -665,7 +668,7 @@ project("spring-web") { optional("javax.servlet.jsp:javax.servlet.jsp-api:2.2.1") optional("javax.el:javax.el-api:2.2.5") optional("javax.faces:javax.faces-api:2.2") - optional("javax.validation:validation-api:1.1.0.Final") + optional("javax.validation:validation-api:${beanvalVersion}") optional("org.codehaus.groovy:groovy-all:${groovyVersion}") optional("com.caucho:hessian:4.0.38") optional("commons-fileupload:commons-fileupload:${fileuploadVersion}") @@ -711,7 +714,7 @@ project("spring-orm") { optional(project(":spring-aop")) optional(project(":spring-context")) optional(project(":spring-web")) - optional("org.eclipse.persistence:javax.persistence:2.1.1") + optional("org.eclipse.persistence:javax.persistence:${jpaVersion}") optional("org.eclipse.persistence:org.eclipse.persistence.core:${eclipselinkVersion}") optional("org.eclipse.persistence:org.eclipse.persistence.jpa:${eclipselinkVersion}") { exclude group: 'org.eclipse.persistence', module: 'javax.persistence' @@ -790,7 +793,7 @@ project("spring-webmvc") { testCompile("org.eclipse.jetty:jetty-server:${jettyVersion}") { exclude group: "javax.servlet", module: "javax.servlet" } - testCompile("javax.validation:validation-api:1.1.0.Final") + testCompile("javax.validation:validation-api:${beanvalVersion}") testCompile("org.hibernate:hibernate-validator:${hibval5Version}") testCompile("org.apache.httpcomponents:httpclient:${httpclientVersion}") testCompile("commons-fileupload:commons-fileupload:${fileuploadVersion}") @@ -949,7 +952,7 @@ project("spring-aspects") { ajc("org.aspectj:aspectjtools:${aspectjVersion}") rt("org.aspectj:aspectjrt:${aspectjVersion}") compile("org.aspectj:aspectjweaver:${aspectjVersion}") - provided("org.eclipse.persistence:javax.persistence:2.1.1") + provided("org.eclipse.persistence:javax.persistence:${jpaVersion}") optional(project(":spring-aop")) // for @Async support optional(project(":spring-beans")) // for @Configurable support optional(project(":spring-context")) // for @Enable* support @@ -1069,7 +1072,7 @@ configure(rootProject) { testCompile(project(":spring-web")) testCompile("javax.servlet:javax.servlet-api:3.0.1") testCompile("javax.inject:javax.inject:1") - testCompile("javax.resource:connector-api:1.5") + testCompile("javax.resource:javax.resource-api:${jcaVersion}") testCompile("org.aspectj:aspectjweaver:${aspectjVersion}") testCompile("org.hibernate:hibernate-core:${hibernate5Version}") testCompile("org.hsqldb:hsqldb:${hsqldbVersion}") diff --git a/spring-jms/src/main/java/org/springframework/jms/connection/CachedMessageProducer.java b/spring-jms/src/main/java/org/springframework/jms/connection/CachedMessageProducer.java index 288ab5afc1..93d7f92fb8 100644 --- a/spring-jms/src/main/java/org/springframework/jms/connection/CachedMessageProducer.java +++ b/spring-jms/src/main/java/org/springframework/jms/connection/CachedMessageProducer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,10 +16,7 @@ package org.springframework.jms.connection; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; +import javax.jms.CompletionListener; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.Message; @@ -29,9 +26,6 @@ import javax.jms.QueueSender; import javax.jms.Topic; import javax.jms.TopicPublisher; -import org.springframework.util.ClassUtils; -import org.springframework.util.ReflectionUtils; - /** * JMS MessageProducer decorator that adapts calls to a shared MessageProducer * instance underneath, managing QoS settings locally within the decorator. @@ -41,36 +35,6 @@ import org.springframework.util.ReflectionUtils; */ class CachedMessageProducer implements MessageProducer, QueueSender, TopicPublisher { - // Various JMS 2.0 MessageProducer methods, if available - - private static final Method setDeliveryDelayMethod = - ClassUtils.getMethodIfAvailable(MessageProducer.class, "setDeliveryDelay", long.class); - - private static final Method getDeliveryDelayMethod = - ClassUtils.getMethodIfAvailable(MessageProducer.class, "getDeliveryDelay"); - - private static Class completionListenerClass; - - private static Method sendWithCompletionListenerMethod; - - private static Method sendWithDestinationAndCompletionListenerMethod; - - static { - try { - completionListenerClass = ClassUtils.forName( - "javax.jms.CompletionListener", CachedMessageProducer.class.getClassLoader()); - sendWithCompletionListenerMethod = MessageProducer.class.getMethod( - "send", Message.class, int.class, int.class, long.class, completionListenerClass); - sendWithDestinationAndCompletionListenerMethod = MessageProducer.class.getMethod( - "send", Destination.class, Message.class, int.class, int.class, long.class, completionListenerClass); - } - catch (Exception ex) { - // No JMS 2.0 API available - completionListenerClass = null; - } - } - - private final MessageProducer target; private Boolean originalDisableMessageID; @@ -120,15 +84,15 @@ class CachedMessageProducer implements MessageProducer, QueueSender, TopicPublis return this.target.getDisableMessageTimestamp(); } - public void setDeliveryDelay(long deliveryDelay) { + public void setDeliveryDelay(long deliveryDelay) throws JMSException { if (this.originalDeliveryDelay == null) { - this.originalDeliveryDelay = (Long) ReflectionUtils.invokeMethod(getDeliveryDelayMethod, this.target); + this.originalDeliveryDelay = this.target.getDeliveryDelay(); } - ReflectionUtils.invokeMethod(setDeliveryDelayMethod, this.target, deliveryDelay); + this.target.setDeliveryDelay(deliveryDelay); } - public long getDeliveryDelay() { - return (Long) ReflectionUtils.invokeMethod(getDeliveryDelayMethod, this.target); + public long getDeliveryDelay() throws JMSException { + return this.target.getDeliveryDelay(); } @Override @@ -196,6 +160,31 @@ class CachedMessageProducer implements MessageProducer, QueueSender, TopicPublis this.target.send(destination, message, deliveryMode, priority, timeToLive); } + @Override + public void send(Message message, CompletionListener completionListener) throws JMSException { + this.target.send(message, this.deliveryMode, this.priority, this.timeToLive, completionListener); + } + + @Override + public void send(Message message, int deliveryMode, int priority, long timeToLive, + CompletionListener completionListener) throws JMSException { + + this.target.send(message, deliveryMode, priority, timeToLive, completionListener); + } + + @Override + public void send(Destination destination, Message message, CompletionListener completionListener) throws JMSException { + this.target.send(destination, message, this.deliveryMode, this.priority, this.timeToLive, completionListener); + } + + @Override + public void send(Destination destination, Message message, int deliveryMode, int priority, + long timeToLive, CompletionListener completionListener) throws JMSException { + + this.target.send(destination, message, deliveryMode, priority, timeToLive, completionListener); + + } + @Override public void send(Queue queue, Message message) throws JMSException { this.target.send(queue, message, this.deliveryMode, this.priority, this.timeToLive); @@ -238,7 +227,7 @@ class CachedMessageProducer implements MessageProducer, QueueSender, TopicPublis this.originalDisableMessageTimestamp = null; } if (this.originalDeliveryDelay != null) { - ReflectionUtils.invokeMethod(setDeliveryDelayMethod, this.target, this.originalDeliveryDelay); + this.target.setDeliveryDelay(this.originalDeliveryDelay); this.originalDeliveryDelay = null; } } @@ -248,54 +237,4 @@ class CachedMessageProducer implements MessageProducer, QueueSender, TopicPublis return "Cached JMS MessageProducer: " + this.target; } - - /** - * Build a dynamic proxy that reflectively adapts to JMS 2.0 API methods, if necessary. - * Otherwise simply return this CachedMessageProducer instance itself. - */ - public MessageProducer getProxyIfNecessary() { - if (completionListenerClass != null) { - return (MessageProducer) Proxy.newProxyInstance(CachedMessageProducer.class.getClassLoader(), - new Class[] {MessageProducer.class, QueueSender.class, TopicPublisher.class}, - new Jms2MessageProducerInvocationHandler()); - } - else { - return this; - } - } - - - /** - * Reflective InvocationHandler which adapts to JMS 2.0 API methods that we - * cannot statically compile against while preserving JMS 1.1 compatibility - * (due to the new {@code javax.jms.CompletionListener} type in the signatures). - */ - private class Jms2MessageProducerInvocationHandler implements InvocationHandler { - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - try { - if (method.getName().equals("send") && args != null && - completionListenerClass == method.getParameterTypes()[args.length - 1]) { - switch (args.length) { - case 2: // send(message, completionListener) - return sendWithCompletionListenerMethod.invoke( - target, args[0], deliveryMode, priority, timeToLive, args[1]); - case 3: // send(destination, message, completionListener) - return sendWithDestinationAndCompletionListenerMethod.invoke( - target, args[0], args[1], deliveryMode, priority, timeToLive, args[2]); - case 5: // send(message, deliveryMode, priority, timeToLive, completionListener) - return sendWithCompletionListenerMethod.invoke(target, args); - case 6: // send(destination, message, deliveryMode, priority, timeToLive, completionListener) - return sendWithDestinationAndCompletionListenerMethod.invoke(target, args); - } - } - return method.invoke(CachedMessageProducer.this, args); - } - catch (InvocationTargetException ex) { - throw ex.getTargetException(); - } - } - } - } diff --git a/spring-jms/src/main/java/org/springframework/jms/connection/CachingConnectionFactory.java b/spring-jms/src/main/java/org/springframework/jms/connection/CachingConnectionFactory.java index bc2aa5c050..ff70aef60c 100644 --- a/spring-jms/src/main/java/org/springframework/jms/connection/CachingConnectionFactory.java +++ b/spring-jms/src/main/java/org/springframework/jms/connection/CachingConnectionFactory.java @@ -40,9 +40,7 @@ import javax.jms.Topic; import javax.jms.TopicSession; import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; -import org.springframework.util.ReflectionUtils; /** * {@link SingleConnectionFactory} subclass that adds {@link javax.jms.Session} @@ -78,15 +76,6 @@ import org.springframework.util.ReflectionUtils; */ public class CachingConnectionFactory extends SingleConnectionFactory { - /** 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 int sessionCacheSize = 1; private boolean cacheProducers = true; @@ -405,7 +394,7 @@ public class CachingConnectionFactory extends SingleConnectionFactory { } this.cachedProducers.put(cacheKey, producer); } - return new CachedMessageProducer(producer).getProxyIfNecessary(); + return new CachedMessageProducer(producer); } private MessageConsumer getCachedConsumer( @@ -421,21 +410,9 @@ public class CachingConnectionFactory extends SingleConnectionFactory { else { if (dest instanceof Topic) { if (noLocal == null) { - // createSharedConsumer((Topic) dest, subscription, selector); - // createSharedDurableConsumer((Topic) dest, subscription, selector); - Method method = (durable ? createSharedDurableConsumerMethod : createSharedConsumerMethod); - try { - consumer = (MessageConsumer) method.invoke(this.target, dest, subscription, selector); - } - catch (InvocationTargetException ex) { - if (ex.getTargetException() instanceof JMSException) { - throw (JMSException) ex.getTargetException(); - } - ReflectionUtils.handleInvocationTargetException(ex); - } - catch (IllegalAccessException ex) { - throw new IllegalStateException("Could not access JMS 2.0 API method: " + ex.getMessage()); - } + consumer = (durable ? + this.target.createSharedDurableConsumer((Topic) dest, subscription, selector) : + this.target.createSharedConsumer((Topic) dest, subscription, selector)); } else { consumer = (durable ? diff --git a/spring-jms/src/main/java/org/springframework/jms/connection/DelegatingConnectionFactory.java b/spring-jms/src/main/java/org/springframework/jms/connection/DelegatingConnectionFactory.java index 0b81da699f..643980174e 100644 --- a/spring-jms/src/main/java/org/springframework/jms/connection/DelegatingConnectionFactory.java +++ b/spring-jms/src/main/java/org/springframework/jms/connection/DelegatingConnectionFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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. @@ -18,6 +18,7 @@ package org.springframework.jms.connection; import javax.jms.Connection; import javax.jms.ConnectionFactory; +import javax.jms.JMSContext; import javax.jms.JMSException; import javax.jms.QueueConnection; import javax.jms.QueueConnectionFactory; @@ -95,22 +96,22 @@ public class DelegatingConnectionFactory @Override public Connection createConnection() throws JMSException { - return getTargetConnectionFactory().createConnection(); + return obtainTargetConnectionFactory().createConnection(); } @Override public Connection createConnection(String username, String password) throws JMSException { - return getTargetConnectionFactory().createConnection(username, password); + return obtainTargetConnectionFactory().createConnection(username, password); } @Override public QueueConnection createQueueConnection() throws JMSException { - ConnectionFactory cf = getTargetConnectionFactory(); - if (cf instanceof QueueConnectionFactory) { - return ((QueueConnectionFactory) cf).createQueueConnection(); + ConnectionFactory target = obtainTargetConnectionFactory(); + if (target instanceof QueueConnectionFactory) { + return ((QueueConnectionFactory) target).createQueueConnection(); } else { - Connection con = cf.createConnection(); + Connection con = target.createConnection(); if (!(con instanceof QueueConnection)) { throw new javax.jms.IllegalStateException("'targetConnectionFactory' is not a QueueConnectionFactory"); } @@ -120,12 +121,12 @@ public class DelegatingConnectionFactory @Override public QueueConnection createQueueConnection(String username, String password) throws JMSException { - ConnectionFactory cf = getTargetConnectionFactory(); - if (cf instanceof QueueConnectionFactory) { - return ((QueueConnectionFactory) cf).createQueueConnection(username, password); + ConnectionFactory target = obtainTargetConnectionFactory(); + if (target instanceof QueueConnectionFactory) { + return ((QueueConnectionFactory) target).createQueueConnection(username, password); } else { - Connection con = cf.createConnection(username, password); + Connection con = target.createConnection(username, password); if (!(con instanceof QueueConnection)) { throw new javax.jms.IllegalStateException("'targetConnectionFactory' is not a QueueConnectionFactory"); } @@ -135,12 +136,12 @@ public class DelegatingConnectionFactory @Override public TopicConnection createTopicConnection() throws JMSException { - ConnectionFactory cf = getTargetConnectionFactory(); - if (cf instanceof TopicConnectionFactory) { - return ((TopicConnectionFactory) cf).createTopicConnection(); + ConnectionFactory target = obtainTargetConnectionFactory(); + if (target instanceof TopicConnectionFactory) { + return ((TopicConnectionFactory) target).createTopicConnection(); } else { - Connection con = cf.createConnection(); + Connection con = target.createConnection(); if (!(con instanceof TopicConnection)) { throw new javax.jms.IllegalStateException("'targetConnectionFactory' is not a TopicConnectionFactory"); } @@ -150,12 +151,12 @@ public class DelegatingConnectionFactory @Override public TopicConnection createTopicConnection(String username, String password) throws JMSException { - ConnectionFactory cf = getTargetConnectionFactory(); - if (cf instanceof TopicConnectionFactory) { - return ((TopicConnectionFactory) cf).createTopicConnection(username, password); + ConnectionFactory target = obtainTargetConnectionFactory(); + if (target instanceof TopicConnectionFactory) { + return ((TopicConnectionFactory) target).createTopicConnection(username, password); } else { - Connection con = cf.createConnection(username, password); + Connection con = target.createConnection(username, password); if (!(con instanceof TopicConnection)) { throw new javax.jms.IllegalStateException("'targetConnectionFactory' is not a TopicConnectionFactory"); } @@ -163,6 +164,32 @@ public class DelegatingConnectionFactory } } + @Override + public JMSContext createContext() { + return obtainTargetConnectionFactory().createContext(); + } + + @Override + public JMSContext createContext(String userName, String password) { + return obtainTargetConnectionFactory().createContext(userName, password); + } + + @Override + public JMSContext createContext(String userName, String password, int sessionMode) { + return obtainTargetConnectionFactory().createContext(userName, password, sessionMode); + } + + @Override + public JMSContext createContext(int sessionMode) { + 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; diff --git a/spring-jms/src/main/java/org/springframework/jms/connection/SingleConnectionFactory.java b/spring-jms/src/main/java/org/springframework/jms/connection/SingleConnectionFactory.java index a780a0363e..7790c5d7b1 100644 --- a/spring-jms/src/main/java/org/springframework/jms/connection/SingleConnectionFactory.java +++ b/spring-jms/src/main/java/org/springframework/jms/connection/SingleConnectionFactory.java @@ -27,6 +27,7 @@ import java.util.Set; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.ExceptionListener; +import javax.jms.JMSContext; import javax.jms.JMSException; import javax.jms.QueueConnection; import javax.jms.QueueConnectionFactory; @@ -270,6 +271,32 @@ public class SingleConnectionFactory implements ConnectionFactory, QueueConnecti "SingleConnectionFactory does not support custom username and password"); } + @Override + public JMSContext createContext() { + return obtainTargetConnectionFactory().createContext(); + } + + @Override + public JMSContext createContext(String userName, String password) { + return obtainTargetConnectionFactory().createContext(userName, password); + } + + @Override + public JMSContext createContext(String userName, String password, int sessionMode) { + return obtainTargetConnectionFactory().createContext(userName, password, sessionMode); + } + + @Override + public JMSContext createContext(int sessionMode) { + return obtainTargetConnectionFactory().createContext(sessionMode); + } + + private ConnectionFactory obtainTargetConnectionFactory() { + ConnectionFactory target = getTargetConnectionFactory(); + Assert.state(target != null, "'targetConnectionFactory' is required"); + return target; + } + /** * Obtain an initialized shared Connection. diff --git a/spring-jms/src/main/java/org/springframework/jms/connection/TransactionAwareConnectionFactoryProxy.java b/spring-jms/src/main/java/org/springframework/jms/connection/TransactionAwareConnectionFactoryProxy.java index b2b0768968..8dba975e6a 100644 --- a/spring-jms/src/main/java/org/springframework/jms/connection/TransactionAwareConnectionFactoryProxy.java +++ b/spring-jms/src/main/java/org/springframework/jms/connection/TransactionAwareConnectionFactoryProxy.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.List; import javax.jms.Connection; import javax.jms.ConnectionFactory; +import javax.jms.JMSContext; import javax.jms.JMSException; import javax.jms.QueueConnection; import javax.jms.QueueConnectionFactory; @@ -101,7 +102,7 @@ public class TransactionAwareConnectionFactoryProxy * Set the target ConnectionFactory that this ConnectionFactory should delegate to. */ public final void setTargetConnectionFactory(ConnectionFactory targetConnectionFactory) { - Assert.notNull(targetConnectionFactory, "targetConnectionFactory must not be nul"); + Assert.notNull(targetConnectionFactory, "'targetConnectionFactory' must not be null"); this.targetConnectionFactory = targetConnectionFactory; } @@ -144,50 +145,76 @@ public class TransactionAwareConnectionFactoryProxy @Override public Connection createConnection(String username, String password) throws JMSException { - Connection targetConnection = this.targetConnectionFactory.createConnection(username, password); + Connection targetConnection = obtainTargetConnectionFactory().createConnection(username, password); return getTransactionAwareConnectionProxy(targetConnection); } @Override public QueueConnection createQueueConnection() throws JMSException { - if (!(this.targetConnectionFactory instanceof QueueConnectionFactory)) { + ConnectionFactory target = obtainTargetConnectionFactory(); + if (!(target instanceof QueueConnectionFactory)) { throw new javax.jms.IllegalStateException("'targetConnectionFactory' is no QueueConnectionFactory"); } - QueueConnection targetConnection = - ((QueueConnectionFactory) this.targetConnectionFactory).createQueueConnection(); + QueueConnection targetConnection = ((QueueConnectionFactory) target).createQueueConnection(); return (QueueConnection) getTransactionAwareConnectionProxy(targetConnection); } @Override public QueueConnection createQueueConnection(String username, String password) throws JMSException { - if (!(this.targetConnectionFactory instanceof QueueConnectionFactory)) { + ConnectionFactory target = obtainTargetConnectionFactory(); + if (!(target instanceof QueueConnectionFactory)) { throw new javax.jms.IllegalStateException("'targetConnectionFactory' is no QueueConnectionFactory"); } - QueueConnection targetConnection = - ((QueueConnectionFactory) this.targetConnectionFactory).createQueueConnection(username, password); + QueueConnection targetConnection = ((QueueConnectionFactory) target).createQueueConnection(username, password); return (QueueConnection) getTransactionAwareConnectionProxy(targetConnection); } @Override public TopicConnection createTopicConnection() throws JMSException { - if (!(this.targetConnectionFactory instanceof TopicConnectionFactory)) { + ConnectionFactory target = obtainTargetConnectionFactory(); + if (!(target instanceof TopicConnectionFactory)) { throw new javax.jms.IllegalStateException("'targetConnectionFactory' is no TopicConnectionFactory"); } - TopicConnection targetConnection = - ((TopicConnectionFactory) this.targetConnectionFactory).createTopicConnection(); + TopicConnection targetConnection = ((TopicConnectionFactory) target).createTopicConnection(); return (TopicConnection) getTransactionAwareConnectionProxy(targetConnection); } @Override public TopicConnection createTopicConnection(String username, String password) throws JMSException { - if (!(this.targetConnectionFactory instanceof TopicConnectionFactory)) { + ConnectionFactory target = obtainTargetConnectionFactory(); + if (!(target instanceof TopicConnectionFactory)) { throw new javax.jms.IllegalStateException("'targetConnectionFactory' is no TopicConnectionFactory"); } - TopicConnection targetConnection = - ((TopicConnectionFactory) this.targetConnectionFactory).createTopicConnection(username, password); + TopicConnection targetConnection = ((TopicConnectionFactory) target).createTopicConnection(username, password); return (TopicConnection) getTransactionAwareConnectionProxy(targetConnection); } + @Override + public JMSContext createContext() { + return obtainTargetConnectionFactory().createContext(); + } + + @Override + public JMSContext createContext(String userName, String password) { + return obtainTargetConnectionFactory().createContext(userName, password); + } + + @Override + public JMSContext createContext(String userName, String password, int sessionMode) { + return obtainTargetConnectionFactory().createContext(userName, password, sessionMode); + } + + @Override + public JMSContext createContext(int sessionMode) { + return obtainTargetConnectionFactory().createContext(sessionMode); + } + + private ConnectionFactory obtainTargetConnectionFactory() { + ConnectionFactory target = getTargetConnectionFactory(); + Assert.state(target != null, "'targetConnectionFactory' is required"); + return target; + } + /** * Wrap the given Connection with a proxy that delegates every method call to it diff --git a/spring-jms/src/main/java/org/springframework/jms/connection/UserCredentialsConnectionFactoryAdapter.java b/spring-jms/src/main/java/org/springframework/jms/connection/UserCredentialsConnectionFactoryAdapter.java index bc5f1e69e8..3916e8b141 100644 --- a/spring-jms/src/main/java/org/springframework/jms/connection/UserCredentialsConnectionFactoryAdapter.java +++ b/spring-jms/src/main/java/org/springframework/jms/connection/UserCredentialsConnectionFactoryAdapter.java @@ -18,6 +18,7 @@ package org.springframework.jms.connection; import javax.jms.Connection; import javax.jms.ConnectionFactory; +import javax.jms.JMSContext; import javax.jms.JMSException; import javax.jms.QueueConnection; import javax.jms.QueueConnectionFactory; @@ -173,16 +174,15 @@ public class UserCredentialsConnectionFactoryAdapter * @see javax.jms.ConnectionFactory#createConnection() */ protected Connection doCreateConnection(String username, String password) throws JMSException { - Assert.state(this.targetConnectionFactory != null, "'targetConnectionFactory' is required"); + ConnectionFactory target = obtainTargetConnectionFactory(); if (StringUtils.hasLength(username)) { - return this.targetConnectionFactory.createConnection(username, password); + return target.createConnection(username, password); } else { - return this.targetConnectionFactory.createConnection(); + return target.createConnection(); } } - /** * Determine whether there are currently thread-bound credentials, * using them if available, falling back to the statically specified @@ -220,11 +220,11 @@ public class UserCredentialsConnectionFactoryAdapter * @see javax.jms.QueueConnectionFactory#createQueueConnection() */ protected QueueConnection doCreateQueueConnection(String username, String password) throws JMSException { - Assert.state(this.targetConnectionFactory != null, "'targetConnectionFactory' is required"); - if (!(this.targetConnectionFactory instanceof QueueConnectionFactory)) { + ConnectionFactory target = obtainTargetConnectionFactory(); + if (!(target instanceof QueueConnectionFactory)) { throw new javax.jms.IllegalStateException("'targetConnectionFactory' is not a QueueConnectionFactory"); } - QueueConnectionFactory queueFactory = (QueueConnectionFactory) this.targetConnectionFactory; + QueueConnectionFactory queueFactory = (QueueConnectionFactory) target; if (StringUtils.hasLength(username)) { return queueFactory.createQueueConnection(username, password); } @@ -233,7 +233,6 @@ public class UserCredentialsConnectionFactoryAdapter } } - /** * Determine whether there are currently thread-bound credentials, * using them if available, falling back to the statically specified @@ -271,11 +270,11 @@ public class UserCredentialsConnectionFactoryAdapter * @see javax.jms.TopicConnectionFactory#createTopicConnection() */ protected TopicConnection doCreateTopicConnection(String username, String password) throws JMSException { - Assert.state(this.targetConnectionFactory != null, "'targetConnectionFactory' is required"); - if (!(this.targetConnectionFactory instanceof TopicConnectionFactory)) { + ConnectionFactory target = obtainTargetConnectionFactory(); + if (!(target instanceof TopicConnectionFactory)) { throw new javax.jms.IllegalStateException("'targetConnectionFactory' is not a TopicConnectionFactory"); } - TopicConnectionFactory queueFactory = (TopicConnectionFactory) this.targetConnectionFactory; + TopicConnectionFactory queueFactory = (TopicConnectionFactory) target; if (StringUtils.hasLength(username)) { return queueFactory.createTopicConnection(username, password); } @@ -284,6 +283,31 @@ public class UserCredentialsConnectionFactoryAdapter } } + @Override + public JMSContext createContext() { + return obtainTargetConnectionFactory().createContext(); + } + + @Override + public JMSContext createContext(String userName, String password) { + return obtainTargetConnectionFactory().createContext(userName, password); + } + + @Override + public JMSContext createContext(String userName, String password, int sessionMode) { + return obtainTargetConnectionFactory().createContext(userName, password, sessionMode); + } + + @Override + public JMSContext createContext(int sessionMode) { + return obtainTargetConnectionFactory().createContext(sessionMode); + } + + private ConnectionFactory obtainTargetConnectionFactory() { + Assert.state(this.targetConnectionFactory != null, "'targetConnectionFactory' is required"); + return this.targetConnectionFactory; + } + /** * Inner class used as ThreadLocal value. diff --git a/spring-jms/src/main/java/org/springframework/jms/listener/endpoint/JmsMessageEndpointFactory.java b/spring-jms/src/main/java/org/springframework/jms/listener/endpoint/JmsMessageEndpointFactory.java index fe448aa2bc..372ba73db3 100644 --- a/spring-jms/src/main/java/org/springframework/jms/listener/endpoint/JmsMessageEndpointFactory.java +++ b/spring-jms/src/main/java/org/springframework/jms/listener/endpoint/JmsMessageEndpointFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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,7 @@ import javax.resource.spi.UnavailableException; import org.springframework.jca.endpoint.AbstractMessageEndpointFactory; /** - * JMS-specific implementation of the JCA 1.5 + * JMS-specific implementation of the JCA 1.7 * {@link javax.resource.spi.endpoint.MessageEndpointFactory} interface, * providing transaction management capabilities for a JMS listener object * (e.g. a {@link javax.jms.MessageListener} object). @@ -61,7 +61,7 @@ public class JmsMessageEndpointFactory extends AbstractMessageEndpointFactory { * Return the JMS MessageListener for this endpoint. */ protected MessageListener getMessageListener() { - return messageListener; + return this.messageListener; } /** diff --git a/spring-jms/src/test/java/org/springframework/jms/StubConnectionFactory.java b/spring-jms/src/test/java/org/springframework/jms/StubConnectionFactory.java index 8945622e81..72524ea3db 100644 --- a/spring-jms/src/test/java/org/springframework/jms/StubConnectionFactory.java +++ b/spring-jms/src/test/java/org/springframework/jms/StubConnectionFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 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. @@ -18,6 +18,7 @@ package org.springframework.jms; import javax.jms.Connection; import javax.jms.ConnectionFactory; +import javax.jms.JMSContext; import javax.jms.JMSException; /** @@ -37,4 +38,24 @@ public class StubConnectionFactory implements ConnectionFactory { return null; } + @Override + public JMSContext createContext() { + return null; + } + + @Override + public JMSContext createContext(String userName, String password) { + return null; + } + + @Override + public JMSContext createContext(String userName, String password, int sessionMode) { + return null; + } + + @Override + public JMSContext createContext(int sessionMode) { + return null; + } + } diff --git a/spring-jms/src/test/java/org/springframework/jms/StubTextMessage.java b/spring-jms/src/test/java/org/springframework/jms/StubTextMessage.java index 58bd47a288..69ecbb14a6 100644 --- a/spring-jms/src/test/java/org/springframework/jms/StubTextMessage.java +++ b/spring-jms/src/test/java/org/springframework/jms/StubTextMessage.java @@ -44,6 +44,8 @@ public class StubTextMessage implements TextMessage { private String type; + private long deliveryTime; + private long timestamp = 0L; private long expiration = 0L; @@ -152,6 +154,11 @@ public class StubTextMessage implements TextMessage { return this.type; } + @Override + public long getJMSDeliveryTime() throws JMSException { + return this.deliveryTime; + } + public long getLongProperty(String name) throws JMSException { Object value = this.properties.get(name); return (value instanceof Long) ? ((Long) value).longValue() : 0; @@ -243,6 +250,11 @@ public class StubTextMessage implements TextMessage { this.type = type; } + @Override + public void setJMSDeliveryTime(long deliveryTime) throws JMSException { + this.deliveryTime = deliveryTime; + } + public void setLongProperty(String name, long value) throws JMSException { this.properties.put(name, value); } @@ -259,5 +271,14 @@ public class StubTextMessage implements TextMessage { this.properties.put(name, value); } -} + @Override + public T getBody(Class c) throws JMSException { + return null; + } + @Override + public boolean isBodyAssignableTo(Class c) throws JMSException { + return false; + } + +} diff --git a/spring-jms/src/test/java/org/springframework/jms/connection/TestConnection.java b/spring-jms/src/test/java/org/springframework/jms/connection/TestConnection.java index 357174c59f..2c10db99c9 100644 --- a/spring-jms/src/test/java/org/springframework/jms/connection/TestConnection.java +++ b/spring-jms/src/test/java/org/springframework/jms/connection/TestConnection.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 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. @@ -43,6 +43,16 @@ public class TestConnection implements Connection { return null; } + @Override + public Session createSession(int sessionMode) throws JMSException { + return null; + } + + @Override + public Session createSession() throws JMSException { + return null; + } + @Override public String getClientID() throws JMSException { return null; @@ -91,6 +101,16 @@ public class TestConnection implements Connection { return null; } + @Override + public ConnectionConsumer createSharedConnectionConsumer(Topic topic, String subscriptionName, String messageSelector, ServerSessionPool sessionPool, int maxMessages) throws JMSException { + return null; + } + + @Override + public ConnectionConsumer createSharedDurableConnectionConsumer(Topic topic, String subscriptionName, String messageSelector, ServerSessionPool sessionPool, int maxMessages) throws JMSException { + return null; + } + public int getStartCount() { return startCount; diff --git a/spring-jms/src/test/java/org/springframework/jms/remoting/JmsInvokerTests.java b/spring-jms/src/test/java/org/springframework/jms/remoting/JmsInvokerTests.java index e023481c08..db17c6334a 100644 --- a/spring-jms/src/test/java/org/springframework/jms/remoting/JmsInvokerTests.java +++ b/spring-jms/src/test/java/org/springframework/jms/remoting/JmsInvokerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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,7 @@ package org.springframework.jms.remoting; import java.io.Serializable; import java.util.Arrays; import java.util.Enumeration; +import javax.jms.CompletionListener; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.Message; @@ -214,6 +215,15 @@ public class JmsInvokerTests { return 0; } + @Override + public void setDeliveryDelay(long deliveryDelay) throws JMSException { + } + + @Override + public long getDeliveryDelay() throws JMSException { + return 0; + } + @Override public Destination getDestination() throws JMSException { return null; @@ -240,6 +250,22 @@ public class JmsInvokerTests { @Override public void send(Destination destination, Message message, int i, int i1, long l) throws JMSException { } + + @Override + public void send(Message message, CompletionListener completionListener) throws JMSException { + } + + @Override + public void send(Message message, int deliveryMode, int priority, long timeToLive, CompletionListener completionListener) throws JMSException { + } + + @Override + public void send(Destination destination, Message message, CompletionListener completionListener) throws JMSException { + } + + @Override + public void send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive, CompletionListener completionListener) throws JMSException { + } } @@ -363,6 +389,25 @@ public class JmsInvokerTests { public void setJMSPriority(int i) throws JMSException { } + @Override + public long getJMSDeliveryTime() throws JMSException { + return 0; + } + + @Override + public void setJMSDeliveryTime(long deliveryTime) throws JMSException { + } + + @Override + public T getBody(Class c) throws JMSException { + return null; + } + + @Override + public boolean isBodyAssignableTo(Class c) throws JMSException { + return false; + } + @Override public void clearProperties() throws JMSException { } diff --git a/spring-tx/src/main/java/org/springframework/jca/context/SpringContextResourceAdapter.java b/spring-tx/src/main/java/org/springframework/jca/context/SpringContextResourceAdapter.java index 259f9f6ca2..d66291cdbe 100644 --- a/spring-tx/src/main/java/org/springframework/jca/context/SpringContextResourceAdapter.java +++ b/spring-tx/src/main/java/org/springframework/jca/context/SpringContextResourceAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2016 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. @@ -37,7 +37,7 @@ import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; /** - * JCA 1.5 {@link javax.resource.spi.ResourceAdapter} implementation + * JCA 1.7 {@link javax.resource.spi.ResourceAdapter} implementation * that loads a Spring {@link org.springframework.context.ApplicationContext}, * starting and stopping Spring-managed beans as part of the ResourceAdapter's * lifecycle. diff --git a/spring-tx/src/main/java/org/springframework/jca/context/package-info.java b/spring-tx/src/main/java/org/springframework/jca/context/package-info.java index 4b0061a05c..c3b2f62e56 100644 --- a/spring-tx/src/main/java/org/springframework/jca/context/package-info.java +++ b/spring-tx/src/main/java/org/springframework/jca/context/package-info.java @@ -1,5 +1,5 @@ /** * Integration package that allows for deploying a Spring application context - * as a JCA 1.5 compliant RAR file. + * as a JCA 1.7 compliant RAR file. */ package org.springframework.jca.context; diff --git a/spring-tx/src/main/java/org/springframework/jca/endpoint/AbstractMessageEndpointFactory.java b/spring-tx/src/main/java/org/springframework/jca/endpoint/AbstractMessageEndpointFactory.java index 6b266172a2..5f7883e0aa 100644 --- a/spring-tx/src/main/java/org/springframework/jca/endpoint/AbstractMessageEndpointFactory.java +++ b/spring-tx/src/main/java/org/springframework/jca/endpoint/AbstractMessageEndpointFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2016 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,7 +34,7 @@ import org.springframework.transaction.jta.SimpleTransactionFactory; import org.springframework.transaction.jta.TransactionFactory; /** - * Abstract base implementation of the JCA 1.5/1.6/1.7 + * Abstract base implementation of the JCA 1.7 * {@link javax.resource.spi.endpoint.MessageEndpointFactory} interface, * providing transaction management capabilities as well as ClassLoader * exposure for endpoint invocations. @@ -134,10 +134,20 @@ public abstract class AbstractMessageEndpointFactory implements MessageEndpointF * returning the bean name as set on this MessageEndpointFactory. * @see #setBeanName */ + @Override public String getActivationName() { return this.beanName; } + /** + * Implementation of the JCA 1.7 {@code #getEndpointClass()} method, + * returning {@code} null in order to indicate a synthetic endpoint type. + */ + @Override + public Class getEndpointClass() { + return null; + } + /** * This implementation returns {@code true} if a transaction manager * has been specified; {@code false} otherwise. @@ -166,6 +176,7 @@ public abstract class AbstractMessageEndpointFactory implements MessageEndpointF *

This implementation delegates to {@link #createEndpointInternal()}, * ignoring the specified timeout. It is only here for JCA 1.6 compliance. */ + @Override public MessageEndpoint createEndpoint(XAResource xaResource, long timeout) throws UnavailableException { AbstractMessageEndpoint endpoint = createEndpointInternal(); endpoint.initXAResource(xaResource); @@ -205,7 +216,7 @@ public abstract class AbstractMessageEndpointFactory implements MessageEndpointF * This {@code beforeDelivery} implementation starts a transaction, * if necessary, and exposes the endpoint ClassLoader as current * thread context ClassLoader. - *

Note that the JCA 1.5 specification does not require a ResourceAdapter + *

Note that the JCA 1.7 specification does not require a ResourceAdapter * to call this method before invoking the concrete endpoint. If this method * has not been called (check {@link #hasBeforeDeliveryBeenCalled()}), the * concrete endpoint method should call {@code beforeDelivery} and its @@ -255,7 +266,7 @@ public abstract class AbstractMessageEndpointFactory implements MessageEndpointF /** * This {@code afterDelivery} implementation resets the thread context * ClassLoader and completes the transaction, if any. - *

Note that the JCA 1.5 specification does not require a ResourceAdapter + *

Note that the JCA 1.7 specification does not require a ResourceAdapter * to call this method after invoking the concrete endpoint. See the * explanation in {@link #beforeDelivery}'s javadoc. */ diff --git a/spring-tx/src/main/java/org/springframework/jca/endpoint/GenericMessageEndpointFactory.java b/spring-tx/src/main/java/org/springframework/jca/endpoint/GenericMessageEndpointFactory.java index 908dbd7f1c..41c826ff6e 100644 --- a/spring-tx/src/main/java/org/springframework/jca/endpoint/GenericMessageEndpointFactory.java +++ b/spring-tx/src/main/java/org/springframework/jca/endpoint/GenericMessageEndpointFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2016 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. @@ -29,7 +29,7 @@ import org.springframework.aop.support.DelegatingIntroductionInterceptor; import org.springframework.util.ReflectionUtils; /** - * Generic implementation of the JCA 1.5 + * Generic implementation of the JCA 1.7 * {@link javax.resource.spi.endpoint.MessageEndpointFactory} interface, * providing transaction management capabilities for any kind of message * listener object (e.g. {@link javax.jms.MessageListener} objects or diff --git a/spring-tx/src/main/java/org/springframework/jca/endpoint/GenericMessageEndpointManager.java b/spring-tx/src/main/java/org/springframework/jca/endpoint/GenericMessageEndpointManager.java index 61253e025c..d6bfc5a954 100644 --- a/spring-tx/src/main/java/org/springframework/jca/endpoint/GenericMessageEndpointManager.java +++ b/spring-tx/src/main/java/org/springframework/jca/endpoint/GenericMessageEndpointManager.java @@ -26,7 +26,7 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.context.SmartLifecycle; /** - * Generic bean that manages JCA 1.5 message endpoints within a Spring + * Generic bean that manages JCA 1.7 message endpoints within a Spring * application context, activating and deactivating the endpoint as part * of the application context's lifecycle. * diff --git a/spring-tx/src/main/java/org/springframework/jca/support/LocalConnectionFactoryBean.java b/spring-tx/src/main/java/org/springframework/jca/support/LocalConnectionFactoryBean.java index 5552089cc0..ded27dbaa9 100644 --- a/spring-tx/src/main/java/org/springframework/jca/support/LocalConnectionFactoryBean.java +++ b/spring-tx/src/main/java/org/springframework/jca/support/LocalConnectionFactoryBean.java @@ -86,7 +86,7 @@ public class LocalConnectionFactoryBean implements FactoryBean, Initiali * by the JCA specification, analogous to a JDBC DataSource and a JPA * EntityManagerFactory. *

Note that the ManagerConnectionFactory implementation might expect - * a reference to its JCA 1.5 ResourceAdapter, expressed through the + * a reference to its JCA 1.7 ResourceAdapter, expressed through the * {@link javax.resource.spi.ResourceAdapterAssociation} interface. * Simply inject the corresponding ResourceAdapter instance into its * "resourceAdapter" bean property in this case, before passing the diff --git a/spring-tx/src/main/java/org/springframework/jca/support/ResourceAdapterFactoryBean.java b/spring-tx/src/main/java/org/springframework/jca/support/ResourceAdapterFactoryBean.java index 2a81efc182..7e7ff1eda5 100644 --- a/spring-tx/src/main/java/org/springframework/jca/support/ResourceAdapterFactoryBean.java +++ b/spring-tx/src/main/java/org/springframework/jca/support/ResourceAdapterFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 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. @@ -30,11 +30,11 @@ import org.springframework.util.Assert; /** * {@link org.springframework.beans.factory.FactoryBean} that bootstraps - * the specified JCA 1.5 {@link javax.resource.spi.ResourceAdapter}, + * the specified JCA 1.7 {@link javax.resource.spi.ResourceAdapter}, * starting it with a local {@link javax.resource.spi.BootstrapContext} * and exposing it for bean references. It will also stop the ResourceAdapter * on context shutdown. This corresponds to 'non-managed' bootstrap in a - * local environment, according to the JCA 1.5 specification. + * local environment, according to the JCA 1.7 specification. * *

This is essentially an adapter for bean-style bootstrapping of a * JCA ResourceAdapter, allowing the BootstrapContext or its elements diff --git a/spring-tx/src/main/java/org/springframework/jca/support/SimpleBootstrapContext.java b/spring-tx/src/main/java/org/springframework/jca/support/SimpleBootstrapContext.java index e94052fca8..3cca326ea3 100644 --- a/spring-tx/src/main/java/org/springframework/jca/support/SimpleBootstrapContext.java +++ b/spring-tx/src/main/java/org/springframework/jca/support/SimpleBootstrapContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 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,10 +20,12 @@ import java.util.Timer; import javax.resource.spi.BootstrapContext; import javax.resource.spi.UnavailableException; import javax.resource.spi.XATerminator; +import javax.resource.spi.work.WorkContext; import javax.resource.spi.work.WorkManager; +import javax.transaction.TransactionSynchronizationRegistry; /** - * Simple implementation of the JCA 1.5 {@link javax.resource.spi.BootstrapContext} + * Simple implementation of the JCA 1.7 {@link javax.resource.spi.BootstrapContext} * interface, used for bootstrapping a JCA ResourceAdapter in a local environment. * *

Delegates to the given WorkManager and XATerminator, if any. Creates simple @@ -40,6 +42,8 @@ public class SimpleBootstrapContext implements BootstrapContext { private XATerminator xaTerminator; + private TransactionSynchronizationRegistry transactionSynchronizationRegistry; + /** * Create a new SimpleBootstrapContext for the given WorkManager, @@ -60,6 +64,23 @@ public class SimpleBootstrapContext implements BootstrapContext { this.xaTerminator = xaTerminator; } + /** + * Create a new SimpleBootstrapContext for the given WorkManager, XATerminator + * and TransactionSynchronizationRegistry. + * @param workManager the JCA WorkManager to use (may be {@code null}) + * @param xaTerminator the JCA XATerminator to use (may be {@code null}) + * @param transactionSynchronizationRegistry the TransactionSynchronizationRegistry + * to use (may be {@code null}) + * @since 5.0 + */ + public SimpleBootstrapContext(WorkManager workManager, XATerminator xaTerminator, + TransactionSynchronizationRegistry transactionSynchronizationRegistry) { + + this.workManager = workManager; + this.xaTerminator = xaTerminator; + this.transactionSynchronizationRegistry = transactionSynchronizationRegistry; + } + @Override public WorkManager getWorkManager() { @@ -79,4 +100,14 @@ public class SimpleBootstrapContext implements BootstrapContext { return new Timer(); } + @Override + public boolean isContextSupported(Class workContextClass) { + return false; + } + + @Override + public TransactionSynchronizationRegistry getTransactionSynchronizationRegistry() { + return this.transactionSynchronizationRegistry; + } + } diff --git a/spring-tx/src/main/java/org/springframework/jca/work/SimpleTaskWorkManager.java b/spring-tx/src/main/java/org/springframework/jca/work/SimpleTaskWorkManager.java index 96645a6e24..c8faca7f19 100644 --- a/spring-tx/src/main/java/org/springframework/jca/work/SimpleTaskWorkManager.java +++ b/spring-tx/src/main/java/org/springframework/jca/work/SimpleTaskWorkManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 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,7 +35,7 @@ import org.springframework.core.task.TaskTimeoutException; import org.springframework.util.Assert; /** - * Simple JCA 1.5 {@link javax.resource.spi.work.WorkManager} implementation that + * Simple JCA 1.7 {@link javax.resource.spi.work.WorkManager} implementation that * delegates to a Spring {@link org.springframework.core.task.TaskExecutor}. * Provides simple task execution including start timeouts, but without support * for a JCA ExecutionContext (i.e. without support for imported transactions). diff --git a/spring-tx/src/main/java/org/springframework/jca/work/WorkManagerTaskExecutor.java b/spring-tx/src/main/java/org/springframework/jca/work/WorkManagerTaskExecutor.java index fd24159daf..5d221ad19b 100644 --- a/spring-tx/src/main/java/org/springframework/jca/work/WorkManagerTaskExecutor.java +++ b/spring-tx/src/main/java/org/springframework/jca/work/WorkManagerTaskExecutor.java @@ -43,17 +43,17 @@ import org.springframework.util.concurrent.ListenableFutureTask; /** * {@link org.springframework.core.task.TaskExecutor} implementation - * that delegates to a JCA 1.5 WorkManager, implementing the + * that delegates to a JCA 1.7 WorkManager, implementing the * {@link javax.resource.spi.work.WorkManager} interface. * *

This is mainly intended for use within a JCA ResourceAdapter implementation, * but may also be used in a standalone environment, delegating to a locally * embedded WorkManager implementation (such as Geronimo's). * - *

Also implements the JCA 1.5 WorkManager interface itself, delegating all + *

Also implements the JCA 1.7 WorkManager interface itself, delegating all * calls to the target WorkManager. Hence, a caller can choose whether it wants * to talk to this executor through the Spring TaskExecutor interface or the - * JCA 1.5 WorkManager interface. + * WorkManager interface. * *

This adapter is also capable of obtaining a JCA WorkManager from JNDI. * This is for example appropriate on the Geronimo application server, where @@ -159,7 +159,7 @@ public class WorkManagerTaskExecutor extends JndiLocatorSupport } /** - * Specify a JCA 1.5 WorkListener to apply, if any. + * Specify a JCA WorkListener to apply, if any. *

This shared WorkListener instance will be passed on to the * WorkManager by all {@link #execute} calls on this TaskExecutor. */ diff --git a/spring-tx/src/main/java/org/springframework/jca/work/package-info.java b/spring-tx/src/main/java/org/springframework/jca/work/package-info.java index 9fe3e89e61..ef83b0e3ba 100644 --- a/spring-tx/src/main/java/org/springframework/jca/work/package-info.java +++ b/spring-tx/src/main/java/org/springframework/jca/work/package-info.java @@ -1,5 +1,5 @@ /** - * Convenience classes for scheduling based on the JCA 1.5 WorkManager facility, - * as supported within JCA 1.5 ResourceAdapters. + * Convenience classes for scheduling based on the JCA WorkManager facility, + * as supported within ResourceAdapters. */ package org.springframework.jca.work;