001 /**
002 * Copyright 2005-2012 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.springframework.transaction.jta;
017
018 import javax.naming.NamingException;
019 import javax.transaction.SystemException;
020
021 import org.objectweb.jotm.Current;
022 import org.objectweb.jotm.Jotm;
023
024 import org.springframework.beans.factory.DisposableBean;
025 import org.springframework.beans.factory.FactoryBean;
026
027 /**
028 * {@link FactoryBean} that retrieves the JTA UserTransaction/TransactionManager
029 * for ObjectWeb's <a href="http://jotm.objectweb.org">JOTM</a>. Will retrieve
030 * an already active JOTM instance if found (e.g. if running in JOnAS),
031 * else create a new local JOTM instance.
032 *
033 * <p>With JOTM, the same object implements both the
034 * {@link javax.transaction.UserTransaction} and the
035 * {@link javax.transaction.TransactionManager} interface,
036 * as returned by this FactoryBean.
037 *
038 * <p>A local JOTM instance is well-suited for working in conjunction with
039 * ObjectWeb's <a href="http://xapool.experlog.com">XAPool</a>, e.g. with bean
040 * definitions like the following:
041 *
042 * <pre class="code">
043 * <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/>
044 *
045 * <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
046 * <property name="userTransaction" ref="jotm"/>
047 * </bean>
048 *
049 * <bean id="innerDataSource" class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
050 * <property name="transactionManager" ref="jotm"/>
051 * <property name="driverName" value="..."/>
052 * <property name="url" value="..."/>
053 * <property name="user" value="..."/>
054 * <property name="password" value="..."/>
055 * </bean>
056 *
057 * <bean id="dataSource" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown">
058 * <property name="dataSource" ref="innerDataSource"/>
059 * <property name="user" value="..."/>
060 * <property name="password" value="..."/>
061 * <property name="maxSize" value="..."/>
062 * </bean></pre>
063 *
064 * Note that Spring's {@link JtaTransactionManager} will automatically detect
065 * that the passed-in UserTransaction reference also implements the
066 * TransactionManager interface. Hence, it is not necessary to specify a
067 * separate reference for JtaTransactionManager's "transactionManager" property.
068 *
069 * <p>Implementation note: This FactoryBean uses JOTM's static access method
070 * to obtain the JOTM {@link org.objectweb.jotm.Current} object, which
071 * implements both the UserTransaction and the TransactionManager interface,
072 * as mentioned above.
073 *
074 * @author Juergen Hoeller
075 * @since 21.01.2004
076 * @see JtaTransactionManager#setUserTransaction
077 * @see JtaTransactionManager#setTransactionManager
078 * @see org.objectweb.jotm.Current
079 */
080 public class JotmFactoryBean implements FactoryBean, DisposableBean {
081
082 private Current jotmCurrent;
083
084 private Jotm jotm;
085
086
087 public JotmFactoryBean() throws NamingException {
088 // Check for already active JOTM instance.
089 this.jotmCurrent = Current.getCurrent();
090
091 // If none found, create new local JOTM instance.
092 if (this.jotmCurrent == null) {
093 // Only for use within the current Spring context:
094 // local, not bound to registry.
095 this.jotm = new Jotm(true, false);
096 this.jotmCurrent = Current.getCurrent();
097 }
098 }
099
100 /**
101 * Set the default transaction timeout for the JOTM instance.
102 * <p>Should only be called for a local JOTM instance,
103 * not when accessing an existing (shared) JOTM instance.
104 */
105 public void setDefaultTimeout(int defaultTimeout) {
106 this.jotmCurrent.setDefaultTimeout(defaultTimeout);
107 // The following is a JOTM oddity: should be used for demarcation transaction only,
108 // but is required here in order to actually get rid of JOTM's default (60 seconds).
109 try {
110 this.jotmCurrent.setTransactionTimeout(defaultTimeout);
111 }
112 catch (SystemException ex) {
113 // should never happen
114 }
115 }
116
117
118 /**
119 * Return the JOTM instance created by this factory bean, if any.
120 * Will be <code>null</code> if an already active JOTM instance is used.
121 * <p>Application code should never need to access this.
122 */
123 public Jotm getJotm() {
124 return this.jotm;
125 }
126
127 public Object getObject() {
128 return this.jotmCurrent;
129 }
130
131 public Class getObjectType() {
132 return this.jotmCurrent.getClass();
133 }
134
135 public boolean isSingleton() {
136 return true;
137 }
138
139
140 /**
141 * Stop the local JOTM instance, if created by this FactoryBean.
142 */
143 public void destroy() {
144 if (this.jotm != null) {
145 this.jotm.stop();
146 }
147 }
148
149 }