KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > tm > TransactionManagerInitializer


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

22 package org.jboss.tm;
23
24 import java.util.HashMap JavaDoc;
25 import java.util.Hashtable JavaDoc;
26 import java.util.Map JavaDoc;
27 import javax.naming.Context JavaDoc;
28 import javax.naming.InitialContext JavaDoc;
29 import javax.naming.Name JavaDoc;
30 import javax.naming.Reference JavaDoc;
31 import javax.naming.spi.ObjectFactory JavaDoc;
32 import javax.transaction.TransactionManager JavaDoc;
33 import javax.transaction.xa.XAException JavaDoc;
34 import org.jboss.logging.Logger;
35 import org.jboss.tm.integrity.TransactionIntegrityFactory;
36 import org.jboss.tm.recovery.RecoveryLogger;
37
38 /**
39  * This is a JMX service which manages the TransactionManager.
40  * The service creates it and binds a Reference to it into JNDI.
41  *
42  * @see TxManager
43  * @author <a HREF="mailto:rickard.oberg@telkel.com">Rickard Oberg</a>
44  * @author <a HREF="mailto:osh@sparre.dk">Ole Husgaard</a>
45  * @author <a HREF="mailto:toby.allsopp@peace.com">Toby Allsopp</a>
46  * @author <a HREF="reverbel@ime.usp.br">Francisco Reverbel</a>
47  * @version $Revision: 37459 $
48  *
49  * @jmx.mbean extends="org.jboss.system.ServiceMBean"
50  */

51 public class TransactionManagerInitializer implements XAExceptionFormatter, ObjectFactory JavaDoc
52 {
53    private static Logger log = Logger.getLogger(TransactionManagerInitializer.class);
54
55    // Constants -----------------------------------------------------
56
public static String JavaDoc JNDI_NAME = "java:/TransactionManager";
57    public static String JavaDoc JNDI_IMPORTER = "java:/TransactionPropagationContextImporter";
58    public static String JavaDoc JNDI_EXPORTER = "java:/TransactionPropagationContextExporter";
59
60    // Attributes ----------------------------------------------------
61

62    private boolean globalIdsEnabled = false; // flag duplicated in TM
63

64    /** Whether to interrupt threads at transaction timeout */
65    private boolean interruptThreads = false;
66
67    private int timeout = 300; // default tx timeout, dupl. in TM when it exists.
68

69    private int completionRetryLimit = 0;
70    
71    private int completionRetryTimeout = 1;
72    
73    private int xaRetryTimeout;
74
75    private int preparedTimeout;
76    
77    private boolean rootBranchRemembersHeuristicDecisions = true;
78    
79    private boolean reportHeuristicHazardAsHeuristicMixed = false;
80
81    private final Map JavaDoc xaExceptionFormatters = new HashMap JavaDoc();
82
83    private RecoveryLogger recoveryLogger;
84
85    private XidFactoryBase xidFactory;
86
87    private TransactionIntegrityFactory integrityFactory;
88
89    private InitialContext JavaDoc initialContext;
90
91    protected Hashtable JavaDoc initialContextProperties;
92
93    // Static --------------------------------------------------------
94

95    static TxManager tm;
96
97    // ServiceMBeanSupport overrides ---------------------------------
98

99    public void setInitialContextProperties(Hashtable JavaDoc initialContextProperties)
100    {
101       this.initialContextProperties = initialContextProperties;
102    }
103
104
105    public void start() throws Exception JavaDoc
106    {
107       if (initialContextProperties == null) initialContext = new InitialContext JavaDoc();
108       else initialContext = new InitialContext JavaDoc(initialContextProperties);
109
110       TransactionImpl.xidFactory = xidFactory;
111       TransactionImpl.xaExceptionFormatter = this;
112
113       // Get a reference to the TxManager singleton.
114
tm = TxManager.getInstance();
115       // Set its default timeout.
116
tm.setDefaultTransactionTimeout(timeout);
117       // Set the TxManager limit and timout for retrying a completion operation
118
// before reporting a heuristic hazard outcome.
119
tm.setCompletionRetryLimit(completionRetryLimit);
120       tm.setCompletionRetryTimeout(completionRetryTimeout);
121       // Set the TxManager timouts for retrying a XA operation and
122
// for a foreign transaction to remain in the prepared state.
123
tm.setXARetryTimeout(xaRetryTimeout);
124       tm.setPreparedTimeout(preparedTimeout);
125       // Set the TxManager flags for remembering heuristic decisions
126
// at the root branch and for heuristic hazard reporting.
127
tm.setRootBranchRemembersHeuristicDecisions(
128                                        rootBranchRemembersHeuristicDecisions);
129       tm.setReportHeuristicHazardAsHeuristicMixed(
130                                        reportHeuristicHazardAsHeuristicMixed);
131       // Initialize its globalIdsEnabled flag.
132
tm.setGlobalIdsEnabled(globalIdsEnabled);
133       tm.setInterruptThreads(interruptThreads);
134       if (integrityFactory != null)
135          tm.setTransactionIntegrity(integrityFactory.createTransactionIntegrity());
136       else
137          tm.setTransactionIntegrity(null);
138       
139       // Bind reference to TM in JNDI
140
// Our TM also implement the tx importer and exporter
141
// interfaces, so we bind it under those names too.
142
// Other transaction managers may have seperate
143
// implementations of these objects, so they are
144
// accessed under separate names.
145
bindRef(JNDI_NAME, "org.jboss.tm.TxManager");
146       bindRef(JNDI_IMPORTER, "org.jboss.tm.TransactionPropagationContextImporter");
147       bindRef(JNDI_EXPORTER, "org.jboss.tm.TransactionPropagationContextFactory");
148    }
149
150    public void stop()
151    {
152       try
153       {
154          // Remove TM, importer and exporter from JNDI
155
Context JavaDoc ctx = initialContext;
156          ctx.unbind(JNDI_NAME);
157          ctx.unbind(JNDI_IMPORTER);
158          ctx.unbind(JNDI_EXPORTER);
159       }
160       catch (Exception JavaDoc e)
161       {
162          log.error("Failed to clear JNDI bindings", e);
163       }
164    }
165
166    /**
167     * Set the Recover logger
168     *
169     * @param recoveryLogger
170     */

171    public void setRecoveryLogger(RecoveryLogger recoveryLogger)
172    {
173       this.recoveryLogger = recoveryLogger;
174       // inject the logger into the TxManager
175
TxManager.getInstance().setRecoveryLogger(this.recoveryLogger);
176    }
177
178
179    /**
180     * Set the Transaciton integrity factory
181     *
182     * @param factory the transaction integrity factory
183     */

184    public void setTransactionIntegrityFactory(TransactionIntegrityFactory factory)
185    {
186       this.integrityFactory = factory;
187       if (tm != null)
188       {
189          if (factory != null)
190             tm.setTransactionIntegrity(factory.createTransactionIntegrity());
191          else
192             tm.setTransactionIntegrity(null);
193       }
194    }
195
196    /**
197     * Gets the "global ids enabled" flag.
198     *
199     * @return an <code>boolean</code> value
200     */

201    public boolean getGlobalIdsEnabled()
202    {
203       return globalIdsEnabled;
204    }
205
206    /**
207     * Sets the "global ids enabled" flag.
208     *
209     * @param newValue an <code>boolean</code> value
210     */

211    public void setGlobalIdsEnabled(boolean newValue)
212    {
213       globalIdsEnabled = newValue;
214       if (tm != null) // Update TM setting
215
tm.setGlobalIdsEnabled(newValue);
216    }
217
218    /**
219     * Is thread interruption enabled at transaction timeout
220     *
221     * @return true for interrupt threads, false otherwise
222     */

223    public boolean isInterruptThreads()
224    {
225       return interruptThreads;
226    }
227
228    /**
229     * Enable/disable thread interruption at transaction timeout.
230     *
231     * @param interruptThreads pass true to interrupt threads, false otherwise
232     */

233    public void setInterruptThreads(boolean interruptThreads)
234    {
235       this.interruptThreads = interruptThreads;
236       if (tm != null)
237          tm.setInterruptThreads(interruptThreads);
238    }
239
240    /**
241     * Describe <code>getTransactionTimeout</code> method here.
242     *
243     * @return an <code>int</code> value
244     */

245    public int getTransactionTimeout()
246    {
247       if (tm != null) // Get timeout value from TM (in case it was changed).
248
timeout = tm.getDefaultTransactionTimeout();
249       return timeout;
250    }
251
252    /**
253     * Describe <code>setTransactionTimeout</code> method here.
254     *
255     * @param timeout an <code>int</code> value
256     * @jmx:managed-attribute
257     */

258    public void setTransactionTimeout(int timeout)
259    {
260       this.timeout = timeout;
261       if (tm != null) // Update TM default timeout
262
tm.setDefaultTransactionTimeout(timeout);
263    }
264    
265    /**
266     * Sets the completion retry limit. This is the maximum number of times that
267     * the transaction manager retries a completion operation (either commit or
268     * rollback) on a resource (either a remote <code>Resource</code> or an
269     * <code>XAResource</code>) that raised a transient exception. Whoever called
270     * the transaction manager is blocked while the completion retries are
271     * performed. If the completion retry limit is reached, the transaction
272     * manager abandons the retries and throws a heuristic hazard exception.
273     *
274     * @param maxCompletionRetries the completion retry limit.
275     */

276    public void setCompletionRetryLimit(int maxCompletionRetries)
277    {
278       this.completionRetryLimit = maxCompletionRetries;
279       if (tm != null) // Update TM setting
280
tm.setCompletionRetryLimit(maxCompletionRetries);
281    }
282    
283    /**
284     * Gets the completion retry limit. This is the maximum number of times that
285     * the transaction manager retries a completion operation (either commit or
286     * rollback) on a resource (either a remote <code>Resource</code> or an
287     * <code>XAResource</code>) that raised a transient exception. Whoever called
288     * the transaction manager is blocked while the completion retries are
289     * performed. If the completion retry limit is reached, the transaction
290     * manager abandons the retries and throws a heuristic hazard exception.
291     *
292     * @return the completion retry limit.
293     */

294    public int getCompletionRetryLimit()
295    {
296       return completionRetryLimit;
297    }
298    
299    /**
300     * Sets the completion retry timeout. The completion retry timeout is the
301     * number of seconds that the transaction manager waits before retrying a
302     * completion operation (either commit or rollback) on a resource (either a
303     * remote <code>Resource</code> or an <code>XAResource</code>) that raised a
304     * transient exception. This is a blocking timeout (whoever called the
305     * transaction manager is blocked until the commit or rollback is retried)
306     * and is applicable if the transaction manager did not report a heuristic
307     * hazard for the transaction. If a heuristic hazard has been reported, then
308     * the applicable timouts are the non-blocking ones: the XA retry timeout and
309     * the prepared timeout.
310     *
311     * @param seconds the timeout (in seconds) for retrying a completion
312     * operation after a transient exception and before the
313     * transaction manager reports a heuristic hazard.
314     */

315    public void setCompletionRetryTimeout(int seconds)
316    {
317       this.completionRetryTimeout = seconds;
318       if (tm != null) // Update TM setting
319
tm.setCompletionRetryTimeout(seconds);
320    }
321    
322    /**
323     * Gets the completion retry timeout. The completion retry timeout is the
324     * number of seconds that the transaction manager waits before retrying a
325     * completion operation (either commit or rollback) on a resource (either a
326     * remote <code>Resource</code> or an <code>XAResource</code>) that raised a
327     * transient exception. This is a blocking timeout (whoever called the
328     * transaction manager is blocked until the commit or rollback is retried)
329     * and is applicable if the transaction manager did not report a heuristic
330     * hazard for the transaction. If a heuristic hazard has been reported, then
331     * the applicable timouts are the non-blocking ones: the XA retry timeout and
332     * the prepared timeout.
333     *
334     * @return the timeout (in seconds) for retrying a completion operation
335     * after a transient exception and before the transaction manager
336     * reports a heuristic hazard.
337     */

338    public int getCompletionRetryTimeout()
339    {
340       return completionRetryTimeout;
341    }
342    
343    /**
344     * Sets the XA retry timeout.
345     *
346     * @param xaRetryTimeout the timeout (in seconds) for retrying operations on
347     * XA resources.
348     */

349    public void setXARetryTimeout(int xaRetryTimeout)
350    {
351       this.xaRetryTimeout = xaRetryTimeout;
352       if (tm != null) // Update TM setting
353
tm.setXARetryTimeout(xaRetryTimeout);
354    }
355    
356    /**
357     * Gets the XA retry timeout.
358     *
359     * @return the timeout (in seconds) for retrying operations on XA resources.
360     */

361    public int getXARetryTimeout()
362    {
363       return xaRetryTimeout;
364    }
365    
366    /**
367     * Sets the prepared timeout. A transaction branch that is the prepared
368     * state waits for an amount of time equal to the prepared timeout before
369     * generating a call to <code>replayCompletion</code> on its recovery
370     * coordinator.
371     *
372     * @param preparedTimeout the timeout (in seconds) for a transaction branch
373     * in the prepared state.
374     */

375    public void setPreparedTimeout(int preparedTimeout)
376    {
377       this.preparedTimeout = preparedTimeout;
378       if (tm != null) // Update TM setting
379
tm.setPreparedTimeout(preparedTimeout);
380    }
381    
382    /**
383     * Gets the prepared timeout. A transaction branch that is the prepared
384     * state waits for an amount of time equal to the prepared timeout before
385     * generating a call to <code>replayCompletion</code> on its recovery
386     * coordinator.
387     *
388     * @return the timeout (in seconds) for a transaction branch in the prepared
389     * state.
390     */

391    public int getPreparedTimeout()
392    {
393       return preparedTimeout;
394    }
395    
396    /**
397     * Sets the boolean attribute "root branch remembers heuristic decisions".
398     * If this attribute is true, the root branch remembers a heuristically
399     * completed transaction until explicitly told (through a call to the MBean
400     * operation <code>forget</code>) to forget that transaction. If this
401     * attribute is false, the root branch immediately forgets a transaction
402     * when the transaction completes.
403     *
404     * @param newValue true if the root branch should remember heuristic
405     * decisions, false otherwise.
406     */

407    public void setRootBranchRemembersHeuristicDecisions(boolean newValue)
408    {
409       this.rootBranchRemembersHeuristicDecisions = newValue;
410       if (tm != null) // Update TM setting
411
tm.setRootBranchRemembersHeuristicDecisions(newValue);
412    }
413    
414    /**
415     * Gets the boolean attribute "root branch remembers heuristic decisions".
416     * If this attribute is true, the root branch remembers a heuristically
417     * completed transaction until explicitly told (through a call to the MBean
418     * operation <code>forget</code>) to forget that transaction. If this
419     * attribute is false, the root branch immediately forgets a transaction
420     * when the transaction completes.
421     *
422     * @return true if the root branch remember heuristic decisions,
423     * false otherwise.
424     */

425    public boolean isRootBranchRemembersHeuristicDecisions()
426    {
427       return rootBranchRemembersHeuristicDecisions;
428    }
429    
430    /**
431     * Sets the boolean attribute "report heuristic hazard as heuristic mixed".
432     * If this attribute is true, each of the commit methods of the JTA API
433     * (<code>javax.transaction.Transaction.commit()</code>,
434     * <code>javax.transaction.TransactionManager.commit()</code>, and
435     * <code>javax.transaction.UserTransaction.commit()</code>) throws a
436     * <code>HeuristicMixedException</code> to report a heuristic hazard to its
437     * caller. If the attribute is false, those methods do not report heuristic
438     * hazards to their callers. In any case, transactions with heuristic hazard
439     * status are listed by the MBean operation
440     * <code>listHeuristicallyCompletedTransactions()</code>.
441     *
442     * @param newValue true if a JTA commit should throw
443     * <code>HeuristicMixedException</code> to report a heuristic hazard
444     * to its caller, or false if a JTA commit should not report a
445     * heuristic hazard to its caller.
446     */

447    public void setReportHeuristicHazardAsHeuristicMixed(boolean newValue)
448    {
449       this.reportHeuristicHazardAsHeuristicMixed = newValue;
450       if (tm != null) // Update TM setting
451
tm.setReportHeuristicHazardAsHeuristicMixed(newValue);
452       
453    }
454    
455    /**
456     * Gets the boolean attribute "report heuristic hazard as heuristic mixed".
457     * If this attribute is true, each of the commit methods of the JTA API
458     * (<code>javax.transaction.Transaction.commit()</code>,
459     * <code>javax.transaction.TransactionManager.commit()</code>, and
460     * <code>javax.transaction.UserTransaction.commit()</code>) throws a
461     * <code>HeuristicMixedException</code> to report a heuristic hazard to its
462     * caller. If the attribute is false, those methods do not report heuristic
463     * hazards to their callers. In any case, transactions with heuristic hazard
464     * status are listed by the MBean operation
465     * <code>listHeuristicallyCompletedTransactions()</code>.
466     *
467     * @return true if a JTA commit throws <code>HeuristicMixedException</code>
468     * to report a heuristic hazard to its caller, or false if a JTA
469     * commit does not report a heuristic hazard to its caller.
470     */

471    boolean isReportHeuristicHazardAsHeuristicMixed()
472    {
473       return reportHeuristicHazardAsHeuristicMixed;
474    }
475    
476   /**
477     * mbean get-set pair for field xidFactory
478     * Get the value of xidFactory
479     * @return value of xidFactory
480     *
481     */

482    public XidFactoryBase getXidFactory()
483    {
484       return xidFactory;
485    }
486
487    /**
488     * Set the value of xidFactory
489     * @param xidFactory Value to assign to xidFactory
490     *
491     */

492    public void setXidFactory(XidFactoryBase xidFactory)
493    {
494       this.xidFactory = xidFactory;
495    }
496
497
498    /**
499     * mbean get-set pair for field transactionManager
500     * Get the value of transactionManager
501     * @return value of transactionManager
502     *
503     */

504    public TransactionManager JavaDoc getTransactionManager()
505    {
506       return tm;
507    }
508
509    /**
510     * Get the xa terminator
511     *
512     * @return the xa terminator
513     */

514    public JBossXATerminator getXATerminator()
515    {
516       return tm;
517    }
518
519    /**
520     * Counts the number of transactions
521     *
522     * @return the number of active transactions
523     *
524     */

525    public long getTransactionCount()
526    {
527       return tm.getTransactionCount();
528    }
529    /** The number of commits.
530     *
531     * @return the number of transactions that have been committed
532     *
533     */

534    public long getCommitCount()
535    {
536       return tm.getCommitCount();
537    }
538    /** The number of rollbacks.
539     *
540     * @return the number of transactions that have been rolled back
541     *
542     */

543    public long getRollbackCount()
544    {
545       return tm.getRollbackCount();
546    }
547    
548    /**
549     * Lists the in-doubt transactions.
550     *
551     * @return a string with a text listing of in-doubt transactions.
552     */

553    public String JavaDoc listInDoubtTransactions()
554    {
555       return tm.listInDoubtTransactions();
556    }
557    
558    /**
559     * Heuristically commits an in-doubt transaction.
560     *
561     * @param localTransactionId the local id of the in-doubt transaction to be
562     * heuristically committed.
563     */

564    public void heuristicallyCommit(long localTransactionId)
565    {
566       tm.heuristicallyCommit(localTransactionId);
567    }
568    
569    /**
570     * Heuristically commits all in-doubt transactions.
571     */

572   public void heuristicallyCommitAll()
573   {
574      tm.heuristicallyCommitAll();
575   }
576    
577    /**
578     * Heuristically rolls back an in-doubt transaction.
579     *
580     * @param localTransactionId the local id of the in-doubt transaction to be
581     * heuristically rolled back.
582     */

583    public void heuristicallyRollback(long localTransactionId)
584    {
585       tm.heuristicallyRollback(localTransactionId);
586    }
587    
588    /**
589     * Heuristically rolls back all in-doubt transactions.
590     */

591    public void heuristicallyRollbackAll()
592    {
593       tm.heuristicallyRollbackAll();
594    }
595    
596    /**
597     * Lists the heuristically completed transactions coordinated by this
598     * transaction manager. A transaction that was heuristically completed
599     * by a call to <code>heuristicallyCommit(long localTransactionId)</code>,
600     * <code>heuristicallyCommitAll()</code>,
601     * <code>heuristicallyRollback(long localTransactionId)</code>, or
602     * <code>heuristicallyRollbackAll()</code> does not appear in the listing,
603     * as that transaction had a foreign coordinator.
604     *
605     * @return a string with a text listing of heuristically completed
606     * transactions.
607     */

608    public String JavaDoc listHeuristicallyCompletedTransactions()
609    {
610       return tm.listHeuristicallyCompletedTransactions();
611    }
612    
613    /**
614     * Forgets a heuristically completed transaction coordinated by this
615     * transaction manager.
616     *
617     * @param localTransactionId the local id of a heuristically completed
618     * transaction coordinated by this transaction
619     * manager.
620     */

621    public void forget(long localTransactionId)
622    {
623       tm.forget(localTransactionId);
624    }
625    
626    /**
627     * Forgets all heuristically completed transactions coordinated by this
628     * transaction manager.
629     */

630    public void forgetAll()
631    {
632       tm.forgetAll();
633    }
634
635    /**
636     * The <code>registerXAExceptionFormatter</code> method
637     *
638     * @param clazz a <code>Class</code> value
639     * @param formatter a <code>XAExceptionFormatter</code> value
640     *
641     */

642    public void registerXAExceptionFormatter(Class JavaDoc clazz, XAExceptionFormatter formatter)
643    {
644       xaExceptionFormatters.put(clazz, formatter);
645    }
646
647    /**
648     * The <code>unregisterXAExceptionFormatter</code> method
649     *
650     * @param clazz a <code>Class</code> value
651     *
652     */

653    public void unregisterXAExceptionFormatter(Class JavaDoc clazz)
654    {
655       xaExceptionFormatters.remove(clazz);
656    }
657
658    public void formatXAException(XAException JavaDoc xae, Logger log)
659    {
660       Class JavaDoc clazz = xae.getClass();
661       while (clazz != XAException JavaDoc.class)
662       {
663          XAExceptionFormatter formatter = (XAExceptionFormatter) xaExceptionFormatters.get(clazz);
664          if (formatter != null)
665          {
666             formatter.formatXAException(xae, log);
667             return;
668          } // end of if ()
669
clazz = clazz.getSuperclass();
670       }
671    }
672
673    // ObjectFactory implementation ----------------------------------
674

675    public Object JavaDoc getObjectInstance(Object JavaDoc obj, Name JavaDoc name,
676          Context JavaDoc nameCtx, Hashtable JavaDoc environment)
677          throws Exception JavaDoc
678    {
679       // Return the transaction manager
680
return tm;
681    }
682
683
684    // Private -------------------------------------------------------
685

686    private void bindRef(String JavaDoc jndiName, String JavaDoc className)
687          throws Exception JavaDoc
688    {
689       Reference JavaDoc ref = new Reference JavaDoc(className, getClass().getName(), null);
690       initialContext.bind(jndiName, ref);
691    }
692 }
693
Popular Tags