001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.tm;
023:
024: import java.util.HashMap;
025: import java.util.Hashtable;
026: import java.util.Map;
027: import javax.management.ObjectName;
028: import javax.naming.Context;
029: import javax.naming.InitialContext;
030: import javax.naming.Name;
031: import javax.naming.Reference;
032: import javax.naming.spi.ObjectFactory;
033: import javax.transaction.TransactionManager;
034: import javax.transaction.xa.XAException;
035: import org.jboss.logging.Logger;
036: import org.jboss.system.ServiceMBeanSupport;
037: import org.jboss.tm.integrity.TransactionIntegrityFactory;
038:
039: /**
040: * This is a JMX service which manages the TransactionManager.
041: * The service creates it and binds a Reference to it into JNDI.
042: *
043: * @see TxManager
044: * @author <a href="mailto:rickard.oberg@telkel.com">Rickard Öberg</a>
045: * @author <a href="mailto:osh@sparre.dk">Ole Husgaard</a>
046: * @author <a href="mailto:toby.allsopp@peace.com">Toby Allsopp</a>
047: * @author <a href="reverbel@ime.usp.br">Francisco Reverbel</a>
048: * @version $Revision: 57208 $
049: *
050: * @jmx.mbean extends="org.jboss.system.ServiceMBean"
051: */
052: public class TransactionManagerService extends ServiceMBeanSupport
053: implements TransactionManagerServiceMBean, ObjectFactory {
054: // Constants -----------------------------------------------------
055: public static String JNDI_NAME = "java:/TransactionManager";
056: public static String JNDI_IMPORTER = "java:/TransactionPropagationContextImporter";
057: public static String JNDI_EXPORTER = "java:/TransactionPropagationContextExporter";
058:
059: // Attributes ----------------------------------------------------
060:
061: private boolean globalIdsEnabled = false; // flag duplicated in TM
062:
063: /** Whether to interrupt threads at transaction timeout */
064: private boolean interruptThreads = false;
065:
066: private int timeout = 300; // default tx timeout, dupl. in TM when it exists.
067: //private String xidClassName = null;
068: private ObjectName xidFactory;
069:
070: /** The integrity factory */
071: private TransactionIntegrityFactory integrityFactory;
072:
073: private final Map xaExceptionFormatters = new HashMap();
074:
075: // Static --------------------------------------------------------
076:
077: static TxManager tm;
078:
079: // ServiceMBeanSupport overrides ---------------------------------
080:
081: protected void startService() throws Exception {
082: XidFactoryMBean xidFactoryObj = (XidFactoryMBean) getServer()
083: .getAttribute(xidFactory, "Instance");
084: TransactionImpl.xidFactory = xidFactoryObj;
085: TransactionImpl.txManagerService = this ;
086:
087: // Get a reference to the TxManager singleton.
088: tm = TxManager.getInstance();
089: // Set its default timeout.
090: tm.setDefaultTransactionTimeout(timeout);
091: // Initialize its globalIdsEnabled flag.
092: tm.setGlobalIdsEnabled(globalIdsEnabled);
093: tm.setInterruptThreads(interruptThreads);
094: if (integrityFactory != null)
095: tm.setTransactionIntegrity(integrityFactory
096: .createTransactionIntegrity());
097: else
098: tm.setTransactionIntegrity(null);
099:
100: // Bind reference to TM in JNDI
101: // Our TM also implement the tx importer and exporter
102: // interfaces, so we bind it under those names too.
103: // Other transaction managers may have seperate
104: // implementations of these objects, so they are
105: // accessed under seperate names.
106: bindRef(JNDI_NAME, "org.jboss.tm.TxManager");
107: bindRef(JNDI_IMPORTER,
108: "org.jboss.tm.TransactionPropagationContextImporter");
109: bindRef(JNDI_EXPORTER,
110: "org.jboss.tm.TransactionPropagationContextFactory");
111: }
112:
113: protected void stopService() {
114: try {
115: // Remove TM, importer and exporter from JNDI
116: Context ctx = new InitialContext();
117: ctx.unbind(JNDI_NAME);
118: ctx.unbind(JNDI_IMPORTER);
119: ctx.unbind(JNDI_EXPORTER);
120: } catch (Exception e) {
121: log.error("Failed to clear JNDI bindings", e);
122: }
123: }
124:
125: /**
126: * Describe <code>getGlobalIdsEnabled</code> method here.
127: *
128: * @return an <code>boolean</code> value
129: * @jmx:managed-attribute
130: */
131: public boolean getGlobalIdsEnabled() {
132: return globalIdsEnabled;
133: }
134:
135: /**
136: * Describe <code>setGlobalIdsEnabled</code> method here.
137: *
138: * @param newValue an <code>boolean</code> value
139: * @jmx:managed-attribute
140: */
141: public void setGlobalIdsEnabled(boolean newValue) {
142: globalIdsEnabled = newValue;
143: if (tm != null) // Update TM setting
144: tm.setGlobalIdsEnabled(newValue);
145: }
146:
147: /**
148: * Is thread interruption enabled at transaction timeout
149: *
150: * @jmx:managed-attribute
151: * @return true for interrupt threads, false otherwise
152: */
153: public boolean isInterruptThreads() {
154: return interruptThreads;
155: }
156:
157: /**
158: * Enable/disable thread interruption at transaction timeout.
159: *
160: * @jmx:managed-attribute
161: * @param interruptThreads pass true to interrupt threads, false otherwise
162: */
163: public void setInterruptThreads(boolean interruptThreads) {
164: this .interruptThreads = interruptThreads;
165: if (tm != null)
166: tm.setInterruptThreads(interruptThreads);
167: }
168:
169: /**
170: * Describe <code>getTransactionTimeout</code> method here.
171: *
172: * @return an <code>int</code> value
173: * @jmx:managed-attribute
174: */
175: public int getTransactionTimeout() {
176: if (tm != null) // Get timeout value from TM (in case it was changed).
177: timeout = tm.getDefaultTransactionTimeout();
178: return timeout;
179: }
180:
181: /**
182: * Describe <code>setTransactionTimeout</code> method here.
183: *
184: * @param timeout an <code>int</code> value
185: * @jmx:managed-attribute
186: */
187: public void setTransactionTimeout(int timeout) {
188: this .timeout = timeout;
189: if (tm != null) // Update TM default timeout
190: tm.setDefaultTransactionTimeout(timeout);
191: }
192:
193: /**
194: * Set the Transaction integrity factory
195: *
196: * @param factory the factory
197: */
198: public void setTransactionIntegrityFactory(
199: TransactionIntegrityFactory factory) {
200: this .integrityFactory = factory;
201: if (tm != null) {
202: if (factory != null)
203: tm.setTransactionIntegrity(factory
204: .createTransactionIntegrity());
205: else
206: tm.setTransactionIntegrity(null);
207: }
208: }
209:
210: /**
211: * mbean get-set pair for field xidFactory
212: * Get the value of xidFactory
213: * @return value of xidFactory
214: *
215: * @jmx:managed-attribute
216: */
217: public ObjectName getXidFactory() {
218: return xidFactory;
219: }
220:
221: /**
222: * Set the value of xidFactory
223: * @param xidFactory Value to assign to xidFactory
224: *
225: * @jmx:managed-attribute
226: */
227: public void setXidFactory(ObjectName xidFactory) {
228: this .xidFactory = xidFactory;
229: }
230:
231: /**
232: * mbean get-set pair for field transactionManager
233: * Get the value of transactionManager
234: * @return value of transactionManager
235: *
236: * @jmx.managed-attribute description="Returns the TransactionManager managed by this service"
237: * access="read-only"
238: */
239: public TransactionManager getTransactionManager() {
240: return tm;
241: }
242:
243: /**
244: * Get the xa terminator
245: *
246: * @jmx.managed-attribute description="Returns the XATerminator managed by this service"
247: * access="read-only"
248: * @return the xa terminator
249: */
250: public JBossXATerminator getXATerminator() {
251: return tm;
252: }
253:
254: /**
255: * Counts the number of transactions
256: *
257: * @return the number of active transactions
258: *
259: * @jmx:managed-attribute
260: */
261: public long getTransactionCount() {
262: return tm.getTransactionCount();
263: }
264:
265: /** The number of commits.
266: *
267: * @return the number of transactions that have been committed
268: *
269: * @jmx:managed-attribute
270: */
271: public long getCommitCount() {
272: return tm.getCommitCount();
273: }
274:
275: /** The number of rollbacks.
276: *
277: * @return the number of transactions that have been rolled back
278: *
279: * @jmx:managed-attribute
280: */
281: public long getRollbackCount() {
282: return tm.getRollbackCount();
283: }
284:
285: /**
286: * The <code>registerXAExceptionFormatter</code> method
287: *
288: * @param clazz a <code>Class</code> value
289: * @param formatter a <code>XAExceptionFormatter</code> value
290: *
291: * @jmx.managed-operation
292: */
293: public void registerXAExceptionFormatter(Class clazz,
294: XAExceptionFormatter formatter) {
295: xaExceptionFormatters.put(clazz, formatter);
296: }
297:
298: /**
299: * The <code>unregisterXAExceptionFormatter</code> method
300: *
301: * @param clazz a <code>Class</code> value
302: *
303: * @jmx.managed-operation
304: */
305: public void unregisterXAExceptionFormatter(Class clazz) {
306: xaExceptionFormatters.remove(clazz);
307: }
308:
309: void formatXAException(XAException xae, Logger log) {
310: Class clazz = xae.getClass();
311: while (clazz != XAException.class) {
312: XAExceptionFormatter formatter = (XAExceptionFormatter) xaExceptionFormatters
313: .get(clazz);
314: if (formatter != null) {
315: formatter.formatXAException(xae, log);
316: return;
317: } // end of if ()
318: clazz = clazz.getSuperclass();
319: }
320: }
321:
322: // ObjectFactory implementation ----------------------------------
323:
324: public Object getObjectInstance(Object obj, Name name,
325: Context nameCtx, Hashtable environment) throws Exception {
326: // Return the transaction manager
327: return tm;
328: }
329:
330: // Private -------------------------------------------------------
331:
332: private void bindRef(String jndiName, String className)
333: throws Exception {
334: Reference ref = new Reference(className, getClass().getName(),
335: null);
336: new InitialContext().bind(jndiName, ref);
337: }
338: }
|