KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opensubsystems > core > persist > db > transaction > J2EETransactionFactoryImpl


1 /*
2  * Copyright (c) 2005 - 2007 OpenSubsystems s.r.o. Slovak Republic. All rights reserved.
3  *
4  * Project: OpenSubsystems
5  *
6  * $Id: J2EETransactionFactoryImpl.java,v 1.9 2007/01/07 06:14:21 bastafidli Exp $
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; version 2 of the License.
11  *
12  * This program 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
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */

21
22 package org.opensubsystems.core.persist.db.transaction;
23
24 import java.sql.Connection JavaDoc;
25 import java.util.logging.Level JavaDoc;
26 import java.util.logging.Logger JavaDoc;
27
28 import javax.naming.InitialContext JavaDoc;
29 import javax.naming.NameNotFoundException JavaDoc;
30 import javax.naming.NamingException JavaDoc;
31 import javax.transaction.TransactionManager JavaDoc;
32 import javax.transaction.UserTransaction JavaDoc;
33
34 import org.opensubsystems.core.error.OSSDatabaseAccessException;
35 import org.opensubsystems.core.error.OSSException;
36 import org.opensubsystems.core.persist.db.DatabaseConnectionFactoryImpl;
37 import org.opensubsystems.core.persist.db.DatabaseTransactionFactoryImpl;
38 import org.opensubsystems.core.persist.db.connectionpool.J2EEDatabaseConnectionFactoryImpl;
39 import org.opensubsystems.core.util.GlobalConstants;
40 import org.opensubsystems.core.util.Log;
41
42 /**
43  * Transaction factory using J2EE transaction manager. It will connect and expose the
44  * existing transaction manager of the J2EE server under which it currently runs.
45  *
46  * @version $Id: J2EETransactionFactoryImpl.java,v 1.9 2007/01/07 06:14:21 bastafidli Exp $
47  * @author Julo Legeny
48  * @code.reviewer Miroslav Halas
49  * @code.reviewed 1.7 2006/05/15 05:12:15 bastafidli
50  */

51 public class J2EETransactionFactoryImpl extends DatabaseTransactionFactoryImpl
52 {
53    // Constants ////////////////////////////////////////////////////////////////
54

55    /**
56     * An array of object references to the JNDI location of TransactionManager.
57     * The values are for the following servers (in order):
58     * a.) JBoss and JRun4 servers
59     * b.) Resin, Orion (Oracle OC4J), JOnAS (JOTM), BEA WebLogic (unofficial) servers.
60     * c.) BEA WebLogic Server (official)
61     */

62    public static final String JavaDoc[] ARR_TRAN_MANAGER = {"java:/TransactionManager",
63                                                     "java:comp/UserTransaction",
64                                                     "javax.transaction.TransactionManager",
65                                                     };
66
67    /**
68     * An array of object references to the JNDI location of UserTransaction.
69     * The values are for the following servers (in order):
70     * a.) JBoss server
71     * b.) JOnAS (JOTM), BEA WebLogic IBM WebSphere servers
72     */

73    public static final String JavaDoc[] ARR_USER_TRAN = {"UserTransaction",
74                                                  "java:comp/UserTransaction",
75                                                 };
76
77    // Cached values ////////////////////////////////////////////////////////////
78

79    /**
80     * Current UserTransaction that is used for actual j2ee server.
81     * Once it is initialized it should not try to do the lookup again.
82     */

83    protected UserTransaction JavaDoc m_currentUserTransaction = null;
84
85    /**
86     * Current TransactionManager that is used for actual j2ee server.
87     * Once it is initialized it should not try to do the lookup again.
88     */

89    protected TransactionManager JavaDoc m_currentTransactionManager = null;
90
91    /**
92     * Logger for this class
93     */

94    private static Logger JavaDoc s_logger = Log.getInstance(SimpleLocalTransactionFactoryImpl.class);
95
96    // Business logic ///////////////////////////////////////////////////////////
97

98    /**
99     * {@inheritDoc}
100     */

101    public UserTransaction JavaDoc requestTransaction(
102    ) throws OSSException
103    {
104       // once the m_currentUserTransaction variable is initialized
105
// it should not try to do the lookup again
106
UserTransaction JavaDoc transaction = m_currentUserTransaction;
107       int iIndex = 0;
108       
109       // TODO: For Julo: This is not very nice way to do things
110
// For each J2EE server you should know what string should be used
111
// and therefore instead of going through loop we should say if server
112
// is jboss lookup this otherwise if jonas lookup this, etc.
113
// Once you change this correct also documentation in implementation_newj2ee.html
114

115       // lookup for each transaction manager string identifier
116
while ((iIndex < ARR_USER_TRAN.length) && (transaction == null))
117       {
118          transaction = lookupUserTransaction(ARR_USER_TRAN[iIndex]);
119          if (transaction != null)
120          {
121             m_currentUserTransaction = transaction;
122             break;
123          }
124          iIndex++;
125       }
126
127       if (transaction == null)
128       {
129          // There is running unknown or unsupported j2ee server.
130
s_logger.log(Level.FINE, "Cannot get UserTransaction because " +
131                       "unknown or unsupported J2EE server is running.");
132       }
133       else
134       {
135          if (s_bTransactionMonitor)
136          {
137             transaction = new DelegatingUserTransaction(transaction);
138          }
139       }
140
141       // return UserTransaction object or null if not found
142
return transaction;
143    }
144
145    /**
146     * {@inheritDoc}
147     */

148    public TransactionManager JavaDoc getTransactionManager(
149    )
150    {
151       // once the m_currentTransactionManager variable is initialized
152
// it should not try to do the lookup again
153
TransactionManager JavaDoc actualTM = m_currentTransactionManager;
154       int iIndex = 0;
155       
156       // TODO: For Julo: This is not very nice way to do things
157
// For each J2EE server you should know what string should be used
158
// and therefore instead of going through loop we should say if server
159
// is jboss lookup this otherwise if jonas lookup this, etc.
160
// Once you change this correct also documentation in implementation_newj2ee.html
161

162       // lookup for each transaction manager string identifier
163
while ((iIndex < ARR_TRAN_MANAGER.length) && (actualTM == null))
164       {
165          actualTM = lookupTransactionManager(ARR_TRAN_MANAGER[iIndex]);
166          if (actualTM != null)
167          {
168             m_currentTransactionManager = actualTM;
169             break;
170          }
171          iIndex++;
172       }
173
174       if (actualTM == null)
175       {
176          // There is running unknown or unsupported j2ee server.
177
s_logger.log(Level.FINE, "Cannot get TransactionManager because " +
178                       "unknown or unsupported J2EE server is running.");
179       }
180
181       // return TransactionManager object or null if not found
182
return actualTM;
183    }
184
185    /**
186     * {@inheritDoc}
187     */

188    public void reset(
189    ) throws OSSException
190    {
191       // Since we do not control the transaction manager this methods may either
192
// just do not do anything
193
}
194
195    /**
196     * {@inheritDoc}
197     */

198    public void stop(
199    ) throws OSSException
200    {
201       // Since we do not control the transaction manager this methods may either
202
// just do not do anything
203
}
204    
205    // Helper methods //////////////////////////////////////////////////////////////////
206

207    /**
208     * Look up the UserTransaction in JNDI via the configured name.
209     *
210     * @param userTransactionName - the JNDI name of the UserTransaction
211     * @return UserTransaction - the UserTransaction object or null if not found
212     */

213    protected UserTransaction JavaDoc lookupUserTransaction(
214       String JavaDoc userTransactionName
215    )
216    {
217       Object JavaDoc jndiObject = null;
218       UserTransaction JavaDoc userTran = null;
219       InitialContext JavaDoc context = null;
220
221       s_logger.finest("Looking up UserTransaction at location "
222                       + userTransactionName);
223
224       // There are not needed properties when we are running in J2EE server.
225
// It should be just possible to do context = new InitialContext();
226
// when we are not running inside of J2EE server.
227
// The server should have either default values or they can be defined in
228
// the command line used to start the server using -D option. If it throws
229
// an exception than should be a good sign we are not in J2EE server.
230
try
231       {
232          context = new InitialContext JavaDoc();
233          jndiObject = context.lookup(userTransactionName);
234          
235          if (jndiObject instanceof UserTransaction JavaDoc)
236          {
237             userTran = (UserTransaction JavaDoc) jndiObject;
238             s_logger.fine("UserTransaction found at " + userTransactionName);
239          }
240          else
241          {
242             // there was found particular string but it does not represent
243
// UserTransaction object so just log it here
244
s_logger.log(Level.WARNING, "Object " + jndiObject
245                          + " available at JNDI location " + userTransactionName
246                          + " does not implement javax.transaction.UserTransaction."
247                          + " This may be caused by class loading conflict between"
248                          + " multiple jar files containing this interface.");
249          }
250       }
251       catch (NameNotFoundException JavaDoc nnfExc)
252       {
253          // This may not be serious error so just log it
254
// Do not print the exception since it would be just concerning
255
// user and this is normal situation
256
s_logger.log(Level.FINEST, "UserTransaction is not available at " +
257                                     "JNDI location " + userTransactionName);
258       }
259       catch (NamingException JavaDoc nExc)
260       {
261          // This may not be serious error so just log it
262
// Do not print the exception since it would be just concerning
263
// user and this is normal situation
264
s_logger.log(Level.FINEST, "UserTransaction is not available at " +
265                                     "JNDI location " + userTransactionName);
266       }
267       finally
268       {
269          try
270          {
271             context.close();
272          }
273          catch (NamingException JavaDoc nExc)
274          {
275             s_logger.log(Level.FINE, "Unable to close context for user transaction", nExc);
276          }
277       }
278
279       return userTran;
280    }
281
282    /**
283     * Look up the TransactionManager in JNDI via the configured name.
284     *
285     * @param transactionManagerName - the JNDI name of the TransactionManager
286     * @return TransactionManager - the TransactionManager object or null if not found
287     */

288    protected TransactionManager JavaDoc lookupTransactionManager(
289       String JavaDoc transactionManagerName
290    )
291    {
292       Object JavaDoc jndiObject = null;
293       TransactionManager JavaDoc tranManager = null;
294       InitialContext JavaDoc context = null;
295
296       s_logger.finest("Looking up TransactionManager at location "
297                       + transactionManagerName);
298
299       // There are not needed properties when we are running in J2EE server.
300
// It should be just possible to do context = new InitialContext();
301
// when we are not running inside of J2EE server.
302
// The server should have either default values or they can be defined in
303
// the command line used to start the server using -D option. If it throws
304
// an exception than should be a good sign we are not in J2EE server.
305
try
306       {
307          context = new InitialContext JavaDoc();
308          jndiObject = context.lookup(transactionManagerName);
309          
310          if (jndiObject instanceof TransactionManager JavaDoc)
311          {
312             tranManager = (TransactionManager JavaDoc) jndiObject;
313             s_logger.fine("TransactionManager found at " + transactionManagerName);
314          }
315          else
316          {
317             // there was found particular string but it does not represent
318
// TransactionManager object so just log it here
319
s_logger.log(Level.WARNING, "Object " + jndiObject
320                          + " available at JNDI location " + transactionManagerName
321                          + " does not implement javax.transaction.TransactionManager"
322                          + " This may be caused by class loading conflict between"
323                          + " multiple jar files containing this interface.");
324          }
325       }
326       catch (NameNotFoundException JavaDoc nnfExc)
327       {
328          // This may not be serious error so just log it
329
// Do not print the exception since it would be just concerning
330
// user and this is normal situation
331
s_logger.log(Level.FINEST, "TransactionManager is not available at " +
332                                     "JNDI location " + transactionManagerName);
333       }
334       catch (NamingException JavaDoc nExc)
335       {
336          // This may not be serious error so just log it
337
// Do not print the exception since it would be just concerning
338
// user and this is normal situation
339
s_logger.log(Level.FINEST, "TransactionManager is not available at " +
340                                     "JNDI location " + transactionManagerName);
341       }
342       finally
343       {
344          try
345          {
346             context.close();
347          }
348          catch (NamingException JavaDoc nExc)
349          {
350             s_logger.log(Level.FINE, "Unable to close context for transaction manager", nExc);
351          }
352       }
353
354       return tranManager;
355    }
356
357    /**
358     * {@inheritDoc}
359     */

360    protected Connection JavaDoc requestTransactionalConnection(
361       boolean bAutoCommit,
362       String JavaDoc strDataSourceName,
363       String JavaDoc strUser,
364       String JavaDoc strPassword,
365       DatabaseConnectionFactoryImpl connectionFactory
366    ) throws OSSDatabaseAccessException
367    {
368       if (GlobalConstants.ERROR_CHECKING)
369       {
370          // J2EE TF currently works only with J2EE CF because J2EE TF can manage
371
// only XAResources and only J2EE CF represents database connections
372
// as XAResources.
373
// Lets check if it is so
374
assert connectionFactory instanceof J2EEDatabaseConnectionFactoryImpl
375                 : "J2EE transaction factory can manage only J2EE connections" +
376                   " at this time.";
377       }
378       
379       // J2EE CF created connection is always already connected to J2EE TF therefore
380
// nothing neeeds to be done, just call the appropriate version of the method
381
return super.requestTransactionalConnection(bAutoCommit, strDataSourceName,
382                                                   strUser, strPassword,
383                                                   connectionFactory);
384    }
385
386
387    /**
388     * {@inheritDoc}
389     */

390    protected void returnTransactionalConnection(
391       Connection JavaDoc cntDBConnection,
392       DatabaseConnectionFactoryImpl connectionFactory
393    )
394    {
395       if (GlobalConstants.ERROR_CHECKING)
396       {
397          // JOTM currently works only with XAPool because JOTM can manage
398
// only XAResources and only XAPool represents database connections
399
// as XAResources.
400
// Lets check if it is so
401
assert connectionFactory instanceof J2EEDatabaseConnectionFactoryImpl
402                 : "J2EE TM can manage only J2EE CF connections at this time.";
403       }
404
405       // Since J2EE TF and J2EE CD are already integrated just call the base class
406
super.returnTransactionalConnection(cntDBConnection, connectionFactory);
407    }
408 }
409
Popular Tags