1 16 17 package org.springframework.jms.connection; 18 19 import javax.jms.Connection ; 20 import javax.jms.ConnectionFactory ; 21 import javax.jms.JMSException ; 22 import javax.jms.Session ; 23 import javax.jms.TransactionRolledBackException ; 24 25 import org.springframework.transaction.CannotCreateTransactionException; 26 import org.springframework.transaction.InvalidIsolationLevelException; 27 import org.springframework.transaction.TransactionDefinition; 28 import org.springframework.transaction.TransactionSystemException; 29 import org.springframework.transaction.UnexpectedRollbackException; 30 import org.springframework.transaction.support.AbstractPlatformTransactionManager; 31 import org.springframework.transaction.support.DefaultTransactionStatus; 32 import org.springframework.transaction.support.SmartTransactionObject; 33 import org.springframework.transaction.support.TransactionSynchronizationManager; 34 import org.springframework.transaction.support.ResourceTransactionManager; 35 import org.springframework.beans.factory.InitializingBean; 36 37 80 public class JmsTransactionManager extends AbstractPlatformTransactionManager 81 implements ResourceTransactionManager, InitializingBean { 82 83 private ConnectionFactory connectionFactory; 84 85 86 98 public JmsTransactionManager() { 99 setTransactionSynchronization(SYNCHRONIZATION_NEVER); 100 } 101 102 106 public JmsTransactionManager(ConnectionFactory connectionFactory) { 107 this(); 108 setConnectionFactory(connectionFactory); 109 afterPropertiesSet(); 110 } 111 112 113 116 public void setConnectionFactory(ConnectionFactory cf) { 117 if (cf instanceof TransactionAwareConnectionFactoryProxy) { 118 this.connectionFactory = ((TransactionAwareConnectionFactoryProxy) cf).getTargetConnectionFactory(); 122 } 123 else { 124 this.connectionFactory = cf; 125 } 126 } 127 128 131 public ConnectionFactory getConnectionFactory() { 132 return this.connectionFactory; 133 } 134 135 138 public void afterPropertiesSet() { 139 if (getConnectionFactory() == null) { 140 throw new IllegalArgumentException ("Property 'connectionFactory' is required"); 141 } 142 } 143 144 145 public Object getResourceFactory() { 146 return getConnectionFactory(); 147 } 148 149 protected Object doGetTransaction() { 150 JmsTransactionObject txObject = new JmsTransactionObject(); 151 txObject.setResourceHolder( 152 (JmsResourceHolder) TransactionSynchronizationManager.getResource(getConnectionFactory())); 153 return txObject; 154 } 155 156 protected boolean isExistingTransaction(Object transaction) { 157 JmsTransactionObject txObject = (JmsTransactionObject) transaction; 158 return (txObject.getResourceHolder() != null); 159 } 160 161 protected void doBegin(Object transaction, TransactionDefinition definition) { 162 if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { 163 throw new InvalidIsolationLevelException("JMS does not support an isolation level concept"); 164 } 165 JmsTransactionObject txObject = (JmsTransactionObject) transaction; 166 Connection con = null; 167 Session session = null; 168 try { 169 con = createConnection(); 170 session = createSession(con); 171 con.start(); 172 if (logger.isDebugEnabled()) { 173 logger.debug("Created JMS transaction on Session [" + session + "] from Connection [" + con + "]"); 174 } 175 txObject.setResourceHolder(new JmsResourceHolder(getConnectionFactory(), con, session)); 176 txObject.getResourceHolder().setSynchronizedWithTransaction(true); 177 int timeout = determineTimeout(definition); 178 if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { 179 txObject.getResourceHolder().setTimeoutInSeconds(timeout); 180 } 181 TransactionSynchronizationManager.bindResource( 182 getConnectionFactory(), txObject.getResourceHolder()); 183 } 184 catch (JMSException ex) { 185 if (session != null) { 186 try { 187 session.close(); 188 } 189 catch (Throwable ex2) { 190 } 192 } 193 if (con != null) { 194 try { 195 con.close(); 196 } 197 catch (Throwable ex2) { 198 } 200 } 201 throw new CannotCreateTransactionException("Could not create JMS transaction", ex); 202 } 203 } 204 205 protected Object doSuspend(Object transaction) { 206 JmsTransactionObject txObject = (JmsTransactionObject) transaction; 207 txObject.setResourceHolder(null); 208 return TransactionSynchronizationManager.unbindResource(getConnectionFactory()); 209 } 210 211 protected void doResume(Object transaction, Object suspendedResources) { 212 JmsResourceHolder conHolder = (JmsResourceHolder) suspendedResources; 213 TransactionSynchronizationManager.bindResource(getConnectionFactory(), conHolder); 214 } 215 216 protected void doCommit(DefaultTransactionStatus status) { 217 JmsTransactionObject txObject = (JmsTransactionObject) status.getTransaction(); 218 Session session = txObject.getResourceHolder().getSession(); 219 try { 220 if (status.isDebug()) { 221 logger.debug("Committing JMS transaction on Session [" + session + "]"); 222 } 223 session.commit(); 224 } 225 catch (TransactionRolledBackException ex) { 226 throw new UnexpectedRollbackException("JMS transaction rolled back", ex); 227 } 228 catch (JMSException ex) { 229 throw new TransactionSystemException("Could not commit JMS transaction", ex); 230 } 231 } 232 233 protected void doRollback(DefaultTransactionStatus status) { 234 JmsTransactionObject txObject = (JmsTransactionObject) status.getTransaction(); 235 Session session = txObject.getResourceHolder().getSession(); 236 try { 237 if (status.isDebug()) { 238 logger.debug("Rolling back JMS transaction on Session [" + session + "]"); 239 } 240 session.rollback(); 241 } 242 catch (JMSException ex) { 243 throw new TransactionSystemException("Could not roll back JMS transaction", ex); 244 } 245 } 246 247 protected void doSetRollbackOnly(DefaultTransactionStatus status) { 248 JmsTransactionObject txObject = (JmsTransactionObject) status.getTransaction(); 249 txObject.getResourceHolder().setRollbackOnly(); 250 } 251 252 protected void doCleanupAfterCompletion(Object transaction) { 253 JmsTransactionObject txObject = (JmsTransactionObject) transaction; 254 TransactionSynchronizationManager.unbindResource(getConnectionFactory()); 255 txObject.getResourceHolder().closeAll(); 256 txObject.getResourceHolder().clear(); 257 } 258 259 260 264 270 protected Connection createConnection() throws JMSException { 271 return getConnectionFactory().createConnection(); 272 } 273 274 281 protected Session createSession(Connection con) throws JMSException { 282 return con.createSession(true, Session.AUTO_ACKNOWLEDGE); 283 } 284 285 286 291 private static class JmsTransactionObject implements SmartTransactionObject { 292 293 private JmsResourceHolder resourceHolder; 294 295 public void setResourceHolder(JmsResourceHolder resourceHolder) { 296 this.resourceHolder = resourceHolder; 297 } 298 299 public JmsResourceHolder getResourceHolder() { 300 return resourceHolder; 301 } 302 303 public boolean isRollbackOnly() { 304 return getResourceHolder().isRollbackOnly(); 305 } 306 } 307 308 } 309 | Popular Tags |