001    /**
002     * Copyright 2005-2013 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     * &lt;bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/&gt;
044     *
045     * &lt;bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"&gt;
046     *   &lt;property name="userTransaction" ref="jotm"/&gt;
047     * &lt;/bean&gt;
048     *
049     * &lt;bean id="innerDataSource" class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"&gt;
050     *   &lt;property name="transactionManager" ref="jotm"/&gt;
051     *   &lt;property name="driverName" value="..."/&gt;
052     *   &lt;property name="url" value="..."/&gt;
053     *   &lt;property name="user" value="..."/&gt;
054     *   &lt;property name="password" value="..."/&gt;
055     * &lt;/bean&gt;
056     *
057     * &lt;bean id="dataSource" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"&gt;
058     *   &lt;property name="dataSource" ref="innerDataSource"/&gt;
059     *   &lt;property name="user" value="..."/&gt;
060     *   &lt;property name="password" value="..."/&gt;
061     *   &lt;property name="maxSize" value="..."/&gt;
062     * &lt;/bean&gt;</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    }