diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractAdvisorAutoProxyCreator.java b/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractAdvisorAutoProxyCreator.java index 7e6db639550e0bfbab98127d30d646d2e2f74200..9ca006be4285b2654d9bd1b6294b764d5eb4dce2 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractAdvisorAutoProxyCreator.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractAdvisorAutoProxyCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. @@ -31,8 +31,8 @@ import org.springframework.util.Assert; * Generic auto proxy creator that builds AOP proxies for specific beans * based on detected Advisors for each bean. * - *

Subclasses must implement the abstract {@link #findCandidateAdvisors()} - * method to return a list of Advisors applying to any object. Subclasses can + *

Subclasses may override the {@link #findCandidateAdvisors()} method to + * return a custom list of Advisors applying to any object. Subclasses can * also override the inherited {@link #shouldSkip} method to exclude certain * objects from auto-proxying. * diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/xml/BeansDtdResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/xml/BeansDtdResolver.java index b77b31700add0e9e58b8526ae7fdc7962d49ef6a..dce36a05e42df8f1464429d500a8fcec73165376 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/xml/BeansDtdResolver.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/xml/BeansDtdResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. @@ -28,7 +28,7 @@ import org.springframework.core.io.Resource; import org.springframework.lang.Nullable; /** - * EntityResolver implementation for the Spring beans DTD, + * {@link EntityResolver} implementation for the Spring beans DTD, * to load the DTD from the Spring class path (or JAR file). * *

Fetches "spring-beans.dtd" from the class path resource @@ -57,6 +57,7 @@ public class BeansDtdResolver implements EntityResolver { logger.trace("Trying to resolve XML entity with public ID [" + publicId + "] and system ID [" + systemId + "]"); } + if (systemId != null && systemId.endsWith(DTD_EXTENSION)) { int lastPathSeparator = systemId.lastIndexOf('/'); int dtdNameStart = systemId.indexOf(DTD_NAME, lastPathSeparator); @@ -83,7 +84,7 @@ public class BeansDtdResolver implements EntityResolver { } } - // Use the default behavior -> download from website or wherever. + // Fall back to the parser's default behavior. return null; } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/xml/PluggableSchemaResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/xml/PluggableSchemaResolver.java index 96ac31fda4d9fb4a4d60b7ab28a9473a06166bc1..696a8498010101510c80e1b4bb41a4400021ee62 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/xml/PluggableSchemaResolver.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/xml/PluggableSchemaResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. @@ -38,15 +38,15 @@ import org.springframework.util.CollectionUtils; * {@link EntityResolver} implementation that attempts to resolve schema URLs into * local {@link ClassPathResource classpath resources} using a set of mappings files. * - *

By default, this class will look for mapping files in the classpath using the pattern: - * {@code META-INF/spring.schemas} allowing for multiple files to exist on the - * classpath at any one time. + *

By default, this class will look for mapping files in the classpath using the + * pattern: {@code META-INF/spring.schemas} allowing for multiple files to exist on + * the classpath at any one time. * - * The format of {@code META-INF/spring.schemas} is a properties - * file where each line should be of the form {@code systemId=schema-location} - * where {@code schema-location} should also be a schema file in the classpath. - * Since systemId is commonly a URL, one must be careful to escape any ':' characters - * which are treated as delimiters in properties files. + *

The format of {@code META-INF/spring.schemas} is a properties file where each line + * should be of the form {@code systemId=schema-location} where {@code schema-location} + * should also be a schema file in the classpath. Since systemId is commonly a URL, + * one must be careful to escape any ':' characters which are treated as delimiters + * in properties files. * *

The pattern for the mapping files can be overidden using the * {@link #PluggableSchemaResolver(ClassLoader, String)} constructor @@ -103,6 +103,7 @@ public class PluggableSchemaResolver implements EntityResolver { this.schemaMappingsLocation = schemaMappingsLocation; } + @Override @Nullable public InputSource resolveEntity(String publicId, @Nullable String systemId) throws IOException { @@ -131,6 +132,8 @@ public class PluggableSchemaResolver implements EntityResolver { } } } + + // Fall back to the parser's default behavior. return null; } @@ -169,7 +172,7 @@ public class PluggableSchemaResolver implements EntityResolver { @Override public String toString() { - return "EntityResolver using mappings " + getSchemaMappings(); + return "EntityResolver using schema mappings " + getSchemaMappings(); } } diff --git a/spring-jms/src/main/java/org/springframework/jms/connection/JmsResourceHolder.java b/spring-jms/src/main/java/org/springframework/jms/connection/JmsResourceHolder.java index 5388a6afa0746aaece00622d9d508bc2b91ecc92..4d0d3a1d2e93f6e154540e243d59fffddc89526f 100644 --- a/spring-jms/src/main/java/org/springframework/jms/connection/JmsResourceHolder.java +++ b/spring-jms/src/main/java/org/springframework/jms/connection/JmsResourceHolder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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,7 +19,6 @@ package org.springframework.jms.connection; import java.lang.reflect.Method; import java.util.HashMap; import java.util.LinkedList; -import java.util.List; import java.util.Map; import javax.jms.Connection; import javax.jms.ConnectionFactory; @@ -58,11 +57,11 @@ public class JmsResourceHolder extends ResourceHolderSupport { private boolean frozen = false; - private final List connections = new LinkedList<>(); + private final LinkedList connections = new LinkedList<>(); - private final List sessions = new LinkedList<>(); + private final LinkedList sessions = new LinkedList<>(); - private final Map> sessionsPerConnection = new HashMap<>(); + private final Map> sessionsPerConnection = new HashMap<>(); /** @@ -117,10 +116,19 @@ public class JmsResourceHolder extends ResourceHolderSupport { } + /** + * Return whether this resource holder is frozen, i.e. does not + * allow for adding further Connections and Sessions to it. + * @see #addConnection + * @see #addSession + */ public final boolean isFrozen() { return this.frozen; } + /** + * Add the given Connection to this resource holder. + */ public final void addConnection(Connection connection) { Assert.isTrue(!this.frozen, "Cannot add Connection because JmsResourceHolder is frozen"); Assert.notNull(connection, "Connection must not be null"); @@ -129,54 +137,102 @@ public class JmsResourceHolder extends ResourceHolderSupport { } } + /** + * Add the given Session to this resource holder. + */ public final void addSession(Session session) { addSession(session, null); } + /** + * Add the given Session to this resource holder, + * registered for a specific Connection. + */ public final void addSession(Session session, @Nullable Connection connection) { Assert.isTrue(!this.frozen, "Cannot add Session because JmsResourceHolder is frozen"); Assert.notNull(session, "Session must not be null"); if (!this.sessions.contains(session)) { this.sessions.add(session); if (connection != null) { - List sessions = this.sessionsPerConnection.computeIfAbsent(connection, k -> new LinkedList<>()); + LinkedList sessions = + this.sessionsPerConnection.computeIfAbsent(connection, k -> new LinkedList<>()); sessions.add(session); } } } + /** + * Determine whether the given Session is registered + * with this resource holder. + */ public boolean containsSession(Session session) { return this.sessions.contains(session); } + /** + * Return this resource holder's default Connection, + * or {@code null} if none. + */ @Nullable public Connection getConnection() { - return (!this.connections.isEmpty() ? this.connections.get(0) : null); + return this.connections.peek(); } + /** + * Return this resource holder's Connection of the given type, + * or {@code null} if none. + */ @Nullable - public Connection getConnection(Class connectionType) { + public C getConnection(Class connectionType) { return CollectionUtils.findValueOfType(this.connections, connectionType); } + /** + * Return an existing original Session, if any. + *

In contrast to {@link #getSession()}, this must not lazily initialize + * a new Session, not even in {@link JmsResourceHolder} subclasses. + */ + @Nullable + Session getOriginalSession() { + return this.sessions.peek(); + } + + /** + * Return this resource holder's default Session, + * or {@code null} if none. + */ @Nullable public Session getSession() { - return (!this.sessions.isEmpty() ? this.sessions.get(0) : null); + return this.sessions.peek(); } + /** + * Return this resource holder's Session of the given type, + * or {@code null} if none. + */ @Nullable - public Session getSession(Class sessionType) { + public S getSession(Class sessionType) { return getSession(sessionType, null); } + /** + * Return this resource holder's Session of the given type + * for the given connection, or {@code null} if none. + */ @Nullable - public Session getSession(Class sessionType, @Nullable Connection connection) { - List sessions = (connection != null ? this.sessionsPerConnection.get(connection) : this.sessions); + public S getSession(Class sessionType, @Nullable Connection connection) { + LinkedList sessions = + (connection != null ? this.sessionsPerConnection.get(connection) : this.sessions); return CollectionUtils.findValueOfType(sessions, sessionType); } + /** + * Commit all of this resource holder's Sessions. + * @throws JMSException if thrown from a Session commit attempt + * @see Session#commit() + */ public void commitAll() throws JMSException { for (Session session : this.sessions) { try { @@ -218,6 +274,10 @@ public class JmsResourceHolder extends ResourceHolderSupport { } } + /** + * Close all of this resource holder's Sessions and clear its state. + * @see Session#close() + */ public void closeAll() { for (Session session : this.sessions) { try { diff --git a/spring-jms/src/main/java/org/springframework/jms/connection/JmsTransactionManager.java b/spring-jms/src/main/java/org/springframework/jms/connection/JmsTransactionManager.java index 41dd20f056caeb0e79f5e9fac5b948b2b951d2ef..d23a1ac01eac4cd1061945b141efc13d38beccc9 100644 --- a/spring-jms/src/main/java/org/springframework/jms/connection/JmsTransactionManager.java +++ b/spring-jms/src/main/java/org/springframework/jms/connection/JmsTransactionManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2019 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. @@ -96,6 +96,8 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager @Nullable private ConnectionFactory connectionFactory; + private boolean lazyResourceRetrieval = false; + /** * Create a new JmsTransactionManager for bean-style usage. @@ -128,7 +130,7 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager * Set the JMS ConnectionFactory that this instance should manage transactions for. */ public void setConnectionFactory(@Nullable ConnectionFactory cf) { - if (cf != null && cf instanceof TransactionAwareConnectionFactoryProxy) { + if (cf instanceof TransactionAwareConnectionFactoryProxy) { // If we got a TransactionAwareConnectionFactoryProxy, we need to perform transactions // for its underlying target ConnectionFactory, else JMS access code won't see // properly exposed transactions (i.e. transactions for the target ConnectionFactory). @@ -159,6 +161,19 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager return connectionFactory; } + /** + * Specify whether this transaction manager should lazily retrieve a JMS + * Connection and Session on access within a transaction ({@code true}). + * By default, it will eagerly create a JMS Connection and Session at + * transaction begin ({@code false}). + * @since 5.1.6 + * @see JmsResourceHolder#getConnection() + * @see JmsResourceHolder#getSession() + */ + public void setLazyResourceRetrieval(boolean lazyResourceRetrieval) { + this.lazyResourceRetrieval = lazyResourceRetrieval; + } + /** * Make sure the ConnectionFactory has been set. */ @@ -200,12 +215,18 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager Connection con = null; Session session = null; try { - con = createConnection(); - session = createSession(con); - if (logger.isDebugEnabled()) { - logger.debug("Created JMS transaction on Session [" + session + "] from Connection [" + con + "]"); + JmsResourceHolder resourceHolder; + if (this.lazyResourceRetrieval) { + resourceHolder = new LazyJmsResourceHolder(connectionFactory); + } + else { + con = createConnection(); + session = createSession(con); + if (logger.isDebugEnabled()) { + logger.debug("Created JMS transaction on Session [" + session + "] from Connection [" + con + "]"); + } + resourceHolder = new JmsResourceHolder(connectionFactory, con, session); } - JmsResourceHolder resourceHolder = new JmsResourceHolder(connectionFactory, con, session); resourceHolder.setSynchronizedWithTransaction(true); int timeout = determineTimeout(definition); if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { @@ -250,7 +271,7 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager @Override protected void doCommit(DefaultTransactionStatus status) { JmsTransactionObject txObject = (JmsTransactionObject) status.getTransaction(); - Session session = txObject.getResourceHolder().getSession(); + Session session = txObject.getResourceHolder().getOriginalSession(); if (session != null) { try { if (status.isDebug()) { @@ -270,7 +291,7 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager @Override protected void doRollback(DefaultTransactionStatus status) { JmsTransactionObject txObject = (JmsTransactionObject) status.getTransaction(); - Session session = txObject.getResourceHolder().getSession(); + Session session = txObject.getResourceHolder().getOriginalSession(); if (session != null) { try { if (status.isDebug()) { @@ -321,6 +342,85 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager } + /** + * Lazily initializing variant of {@link JmsResourceHolder}, + * initializing a JMS Connection and Session on user access. + */ + private class LazyJmsResourceHolder extends JmsResourceHolder { + + private boolean connectionInitialized = false; + + private boolean sessionInitialized = false; + + public LazyJmsResourceHolder(@Nullable ConnectionFactory connectionFactory) { + super(connectionFactory); + } + + @Override + @Nullable + public Connection getConnection() { + initializeConnection(); + return super.getConnection(); + } + + @Override + @Nullable + public C getConnection(Class connectionType) { + initializeConnection(); + return super.getConnection(connectionType); + } + + @Override + @Nullable + public Session getSession() { + initializeSession(); + return super.getSession(); + } + + @Override + @Nullable + public S getSession(Class sessionType) { + initializeSession(); + return super.getSession(sessionType); + } + + @Override + @Nullable + public S getSession(Class sessionType, @Nullable Connection connection) { + initializeSession(); + return super.getSession(sessionType, connection); + } + + private void initializeConnection() { + if (!this.connectionInitialized) { + try { + addConnection(createConnection()); + } + catch (JMSException ex) { + throw new CannotCreateTransactionException( + "Failed to lazily initialize JMS Connection for transaction", ex); + } + this.connectionInitialized = true; + } + } + + private void initializeSession() { + if (!this.sessionInitialized) { + Connection con = getConnection(); + Assert.state(con != null, "No transactional JMS Connection"); + try { + addSession(createSession(con), con); + } + catch (JMSException ex) { + throw new CannotCreateTransactionException( + "Failed to lazily initialize JMS Session for transaction", ex); + } + this.sessionInitialized = true; + } + } + } + + /** * JMS transaction object, representing a JmsResourceHolder. * Used as transaction object by JmsTransactionManager. diff --git a/spring-jms/src/test/java/org/springframework/jms/connection/JmsTransactionManagerTests.java b/spring-jms/src/test/java/org/springframework/jms/connection/JmsTransactionManagerTests.java index bd0fb1bd97aae9d75772c5bb4ceb3ad7a99d260a..1019100b1a7655ee0064d66fb5c0e19558ce38eb 100644 --- a/spring-jms/src/test/java/org/springframework/jms/connection/JmsTransactionManagerTests.java +++ b/spring-jms/src/test/java/org/springframework/jms/connection/JmsTransactionManagerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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,6 @@ import org.junit.Test; import org.springframework.jms.StubQueue; import org.springframework.jms.core.JmsTemplate; -import org.springframework.jms.core.MessageCreator; import org.springframework.jms.core.SessionCallback; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; @@ -67,12 +66,9 @@ public class JmsTransactionManagerTests { JmsTransactionManager tm = new JmsTransactionManager(cf); TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition()); JmsTemplate jt = new JmsTemplate(cf); - jt.execute(new SessionCallback() { - @Override - public Void doInJms(Session sess) { - assertTrue(sess == session); - return null; - } + jt.execute((SessionCallback) sess -> { + assertSame(sess, session); + return null; }); tm.commit(ts); @@ -93,12 +89,9 @@ public class JmsTransactionManagerTests { JmsTransactionManager tm = new JmsTransactionManager(cf); TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition()); JmsTemplate jt = new JmsTemplate(cf); - jt.execute(new SessionCallback() { - @Override - public Void doInJms(Session sess) { - assertTrue(sess == session); - return null; - } + jt.execute((SessionCallback) sess -> { + assertSame(sess, session); + return null; }); tm.rollback(ts); @@ -119,23 +112,17 @@ public class JmsTransactionManagerTests { JmsTransactionManager tm = new JmsTransactionManager(cf); TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition()); final JmsTemplate jt = new JmsTemplate(cf); - jt.execute(new SessionCallback() { - @Override - public Void doInJms(Session sess) { - assertTrue(sess == session); - return null; - } + jt.execute((SessionCallback) sess -> { + assertSame(sess, session); + return null; }); TransactionTemplate tt = new TransactionTemplate(tm); tt.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { - jt.execute(new SessionCallback() { - @Override - public Void doInJms(Session sess) { - assertTrue(sess == session); - return null; - } + jt.execute((SessionCallback) sess -> { + assertSame(sess, session); + return null; }); } }); @@ -158,23 +145,17 @@ public class JmsTransactionManagerTests { JmsTransactionManager tm = new JmsTransactionManager(cf); TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition()); final JmsTemplate jt = new JmsTemplate(cf); - jt.execute(new SessionCallback() { - @Override - public Void doInJms(Session sess) { - assertTrue(sess == session); - return null; - } + jt.execute((SessionCallback) sess -> { + assertSame(sess, session); + return null; }); TransactionTemplate tt = new TransactionTemplate(tm); tt.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { - jt.execute(new SessionCallback() { - @Override - public Void doInJms(Session sess) { - assertTrue(sess == session); - return null; - } + jt.execute((SessionCallback) sess -> { + assertSame(sess, session); + return null; }); status.setRollbackOnly(); } @@ -206,33 +187,24 @@ public class JmsTransactionManagerTests { JmsTransactionManager tm = new JmsTransactionManager(cf); TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition()); final JmsTemplate jt = new JmsTemplate(cf); - jt.execute(new SessionCallback() { - @Override - public Void doInJms(Session sess) { - assertTrue(sess == session); - return null; - } + jt.execute((SessionCallback) sess -> { + assertSame(sess, session); + return null; }); TransactionTemplate tt = new TransactionTemplate(tm); tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED); tt.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { - jt.execute(new SessionCallback() { - @Override - public Void doInJms(Session sess) { - assertTrue(sess != session); - return null; - } + jt.execute((SessionCallback) sess -> { + assertNotSame(sess, session); + return null; }); } }); - jt.execute(new SessionCallback() { - @Override - public Void doInJms(Session sess) { - assertTrue(sess == session); - return null; - } + jt.execute((SessionCallback) sess -> { + assertSame(sess, session); + return null; }); tm.commit(ts); @@ -255,33 +227,24 @@ public class JmsTransactionManagerTests { JmsTransactionManager tm = new JmsTransactionManager(cf); TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition()); final JmsTemplate jt = new JmsTemplate(cf); - jt.execute(new SessionCallback() { - @Override - public Void doInJms(Session sess) { - assertTrue(sess == session); - return null; - } + jt.execute((SessionCallback) sess -> { + assertSame(sess, session); + return null; }); TransactionTemplate tt = new TransactionTemplate(tm); tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); tt.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { - jt.execute(new SessionCallback() { - @Override - public Void doInJms(Session sess) { - assertTrue(sess != session); - return null; - } + jt.execute((SessionCallback) sess -> { + assertNotSame(sess, session); + return null; }); } }); - jt.execute(new SessionCallback() { - @Override - public Void doInJms(Session sess) { - assertTrue(sess == session); - return null; - } + jt.execute((SessionCallback) sess -> { + assertSame(sess, session); + return null; }); tm.commit(ts); @@ -310,12 +273,7 @@ public class JmsTransactionManagerTests { JmsTransactionManager tm = new JmsTransactionManager(cf); TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition()); JmsTemplate jt = new JmsTemplate(cf); - jt.send(dest, new MessageCreator() { - @Override - public Message createMessage(Session session) throws JMSException { - return message; - } - }); + jt.send(dest, sess -> message); tm.commit(ts); verify(producer).send(message); @@ -325,4 +283,39 @@ public class JmsTransactionManagerTests { verify(con).close(); } + @Test + public void testLazyTransactionalSession() throws JMSException { + ConnectionFactory cf = mock(ConnectionFactory.class); + Connection con = mock(Connection.class); + final Session session = mock(Session.class); + + JmsTransactionManager tm = new JmsTransactionManager(cf); + tm.setLazyResourceRetrieval(true); + TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition()); + + given(cf.createConnection()).willReturn(con); + given(con.createSession(true, Session.AUTO_ACKNOWLEDGE)).willReturn(session); + + JmsTemplate jt = new JmsTemplate(cf); + jt.execute((SessionCallback) sess -> { + assertSame(sess, session); + return null; + }); + tm.commit(ts); + + verify(session).commit(); + verify(session).close(); + verify(con).close(); + } + + @Test + public void testLazyWithoutSessionAccess() { + ConnectionFactory cf = mock(ConnectionFactory.class); + + JmsTransactionManager tm = new JmsTransactionManager(cf); + tm.setLazyResourceRetrieval(true); + TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition()); + tm.commit(ts); + } + }