Source Code Cross Referenced for JStatefulSwitch.java in  » J2EE » JOnAS-4.8.6 » org » objectweb » jonas_ejb » container » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » JOnAS 4.8.6 » org.objectweb.jonas_ejb.container 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * JOnAS: Java(TM) Open Application Server
003:         * Copyright (C) 1999-2004 Bull S.A.
004:         * Contact: jonas-team@objectweb.org
005:         *
006:         * This library is free software; you can redistribute it and/or
007:         * modify it under the terms of the GNU Lesser General Public
008:         * License as published by the Free Software Foundation; either
009:         * version 2.1 of the License, or any later version.
010:         *
011:         * This library is distributed in the hope that it will be useful,
012:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014:         * Lesser General Public License for more details.
015:         *
016:         * You should have received a copy of the GNU Lesser General Public
017:         * License along with this library; if not, write to the Free Software
018:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
019:         * USA
020:         *
021:         * --------------------------------------------------------------------------
022:         * $Id: JStatefulSwitch.java 7900 2006-01-18 16:04:21Z durieuxp $
023:         * --------------------------------------------------------------------------
024:         */package org.objectweb.jonas_ejb.container;
025:
026:        import java.rmi.NoSuchObjectException;
027:        import java.rmi.RemoteException;
028:        import java.util.ArrayList;
029:        import java.util.Collections;
030:        import java.util.Iterator;
031:        import java.util.List;
032:
033:        import javax.ejb.EJBException;
034:        import javax.ejb.NoSuchObjectLocalException;
035:        import javax.ejb.RemoveException;
036:        import javax.ejb.SessionSynchronization;
037:        import javax.ejb.TransactionRolledbackLocalException;
038:        import javax.transaction.InvalidTransactionException;
039:        import javax.transaction.RollbackException;
040:        import javax.transaction.SystemException;
041:        import javax.transaction.Transaction;
042:
043:        import org.objectweb.transaction.jta.ResourceManagerEvent;
044:        import org.objectweb.util.monolog.api.BasicLevel;
045:
046:        /**
047:         * JStatefulSwitch is the implementation of JSessionSwitch dedicated to the
048:         * Stateful Session Bean.
049:         * @author Philippe Durieux
050:         */
051:        public class JStatefulSwitch extends JSessionSwitch {
052:
053:            private int sessionId;
054:
055:            /**
056:             * Count all curent accesses (transactional or not)
057:             * A null value means that this instance is not currently used.
058:             */
059:            private int usedcount = 0;
060:
061:            private JStatefulContext bctx = null;
062:
063:            private Transaction currTx = null;
064:
065:            private boolean mustCommit = false;
066:
067:            private boolean expired = false;
068:
069:            private Transaction beanTx = null; // only for bean managed tx
070:
071:            private long lastaccesstime;
072:
073:            private boolean passivated = false;
074:
075:            /**
076:             * Saved connectionList for this instance. The real connectionList
077:             * is maintained in a ThreadLocal variable in ThreadData.
078:             * Used only for session stateful methods, if they keep
079:             * connection along several calls, not always in same thread.
080:             * This list must not be shared between all instances.
081:             * This info is transient because JDBC connection have not to be
082:             * saved on disk at passivation time : They should be closed in
083:             * ejbPassivate().
084:             */
085:            private List connectionList = Collections
086:                    .synchronizedList(new ArrayList());
087:
088:            /**
089:             * constructor.
090:             * @param bf The Bean Factory
091:             * @param sid the unique statefulSession ident
092:             */
093:            public JStatefulSwitch(JStatefulFactory bf) throws RemoteException {
094:                super (bf);
095:                if (TraceEjb.isDebugIc()) {
096:                    TraceEjb.interp.log(BasicLevel.DEBUG, "");
097:                }
098:            }
099:
100:            public int getSessionId() {
101:                return sessionId;
102:            }
103:
104:            /**
105:             * @return true if instance can be passivated
106:             */
107:            public boolean canPassivate() {
108:                if (usedcount > 0) {
109:                    TraceEjb.ssfpool.log(BasicLevel.DEBUG, "Victim is busy");
110:                    return false;
111:                }
112:                // Don't try to passivate if no matching session context!
113:                return (!passivated && bctx != null);
114:            }
115:
116:            /**
117:             * @return true if instance has been passivated.
118:             */
119:            public boolean isPassivated() {
120:                return passivated;
121:            }
122:
123:            /**
124:             * Passivate this instance
125:             */
126:            public synchronized boolean passivate() {
127:                if (currTx != null || beanTx != null) {
128:                    TraceEjb.ssfpool.log(BasicLevel.DEBUG,
129:                            "Cannot passivate: busy");
130:                    return false;
131:                }
132:                TraceEjb.ssfpool.log(BasicLevel.DEBUG,
133:                        "Instance will be passivated");
134:                passivated = ((JStatefulFactory) bf).passivateStateful(this );
135:                if (passivated) {
136:                    // Disconnect instance so that it will be garbaged.
137:                    bctx.setInstance(null);
138:                }
139:                return passivated;
140:            }
141:
142:            /**
143:             * Set the connection list associated to the current thread
144:             * with the list associated to this stateful session.
145:             */
146:            public void pushConnectionList() {
147:                if (TraceEjb.isDebugTx()) {
148:                    TraceEjb.tx.log(BasicLevel.DEBUG, "pushed connectionList ="
149:                            + connectionList);
150:                }
151:                bf.getTransactionManager().pushThreadLocalRMEventList(
152:                        connectionList);
153:            }
154:
155:            /**
156:             * save the current connectionList for future use (next preInvoke).
157:             */
158:            public void popConnectionList() {
159:                connectionList = bf.getTransactionManager()
160:                        .popThreadLocalRMEventList();
161:                if (TraceEjb.isDebugTx()) {
162:                    TraceEjb.tx.log(BasicLevel.DEBUG, "poped connectionList ="
163:                            + connectionList);
164:                }
165:            }
166:
167:            /**
168:             * Save the Connection List after a create method.
169:             */
170:            public void setConnectionList(List cl) {
171:                connectionList = cl;
172:                if (TraceEjb.isDebugTx()) {
173:                    TraceEjb.tx.log(BasicLevel.DEBUG, "init connectionList ="
174:                            + connectionList);
175:                }
176:            }
177:
178:            /**
179:             * enlist all connection of the list
180:             */
181:            public void enlistConnections(Transaction tx) {
182:                if (tx != null && connectionList != null) {
183:                    try {
184:                        for (Iterator it = connectionList.iterator(); it
185:                                .hasNext();) {
186:                            ResourceManagerEvent rme = (ResourceManagerEvent) it
187:                                    .next();
188:                            if (rme != null) {
189:                                rme.enlistConnection(tx);
190:                            } else {
191:                                TraceEjb.tx
192:                                        .log(BasicLevel.WARN,
193:                                                "Null ResourceManagerEvent in Connection List");
194:                            }
195:                        }
196:                    } catch (SystemException e) {
197:                        TraceEjb.tx.log(BasicLevel.ERROR,
198:                                "cannot enlist connection", e);
199:                    }
200:                }
201:                // push the connection list in case a tx is started by the bean
202:                // or if the method close a connection previously enlisted.
203:                pushConnectionList();
204:            }
205:
206:            /**
207:             * delist all connections of the list
208:             */
209:            public void delistConnections(Transaction tx) {
210:                popConnectionList();
211:            }
212:
213:            // ===============================================================
214:            // TimerEventListener implementation
215:            // ===============================================================
216:
217:            /**
218:             * The session timeout has expired
219:             * @param arg Not Used.
220:             */
221:            public synchronized void timeoutExpired(Object arg) {
222:                if (TraceEjb.isVerbose()) {
223:                    TraceEjb.logger.log(BasicLevel.WARN,
224:                            "stateful session timeout expired");
225:                }
226:                mytimer = null;
227:                // Do not remove if still used in a transaction
228:                if (currTx != null) {
229:                    expired = true;
230:                } else {
231:                    if (bctx != null) {
232:                        try {
233:                            bctx.setRemoved();
234:                        } catch (RemoteException e) {
235:                            if (TraceEjb.isVerbose()) {
236:                                TraceEjb.logger.log(BasicLevel.WARN,
237:                                        "timeout expired", e);
238:                            }
239:                        } catch (RemoveException e) {
240:                            if (TraceEjb.isVerbose()) {
241:                                TraceEjb.logger.log(BasicLevel.WARN,
242:                                        "timeout expired", e);
243:                            }
244:                        }
245:                    }
246:                    noLongerUsed();
247:                }
248:            }
249:
250:            // ===============================================================
251:            // other public methods
252:            // ===============================================================
253:
254:            /**
255:             * @return the StatefulContext (for passivation)
256:             */
257:            public JStatefulContext getStatefulContext() {
258:                if (sessionId == -1) {
259:                    throw new EJBException("This Session has been removed");
260:                }
261:                if (bctx == null) {
262:                    throw new EJBException("Already passivated");
263:                }
264:                return bctx;
265:            }
266:
267:            /**
268:             * At each business method, get a BeanContext to run it
269:             * @param tx The Transaction Context
270:             * @return The Session Context
271:             */
272:            public synchronized JSessionContext getICtx(Transaction tx) {
273:                if (TraceEjb.isDebugIc()) {
274:                    TraceEjb.interp.log(BasicLevel.DEBUG, "");
275:                }
276:
277:                // If session has been removed, we must throw
278:                // NoSuchObject[Local]Exception
279:                // to the caller.
280:                if (sessionId == -1) {
281:                    throw new NoSuchObjectLocalException(
282:                            "This Session has been removed");
283:                }
284:
285:                lastaccesstime = System.currentTimeMillis();
286:
287:                // reload Context if it was passivated
288:                if (passivated) {
289:                    TraceEjb.ssfpool.log(BasicLevel.DEBUG,
290:                            "Bean has been passivated. Reactivate it");
291:                    ((JStatefulFactory) bf).activateStateful(this );
292:                    passivated = false;
293:                }
294:                // Check Transaction
295:                checkTx(tx);
296:
297:                usedcount++;
298:
299:                return bctx;
300:            }
301:
302:            /**
303:             * At each create, bind the Context to the transaction
304:             * @param tx The current Transaction Context
305:             * @param bctx The Context to bind
306:             */
307:            public synchronized void bindICtx(Transaction tx,
308:                    JStatefulContext bctx) {
309:                TraceEjb.interp.log(BasicLevel.DEBUG, "");
310:                sessionId = ((JStatefulFactory) bf).getNewSessionId(this );
311:                this .bctx = bctx;
312:                bctx.initSessionContext(this );
313:                lastaccesstime = System.currentTimeMillis();
314:                usedcount++;
315:                // Check Transaction
316:                checkTx(tx);
317:            }
318:
319:            /**
320:             * Release the Context after use.
321:             * @param tx The current Transaction Context
322:             * @param discard if true, instance must be discarded
323:             */
324:            public synchronized void releaseICtx(RequestCtx req, boolean discard) {
325:                TraceEjb.interp.log(BasicLevel.DEBUG, "");
326:
327:                usedcount--;
328:
329:                // In case getICtx failed, bctx may be null.
330:                if (bctx == null) {
331:                    return;
332:                }
333:
334:                if (bctx.isMarkedRemoved() || discard) {
335:                    stopTimer();
336:                    noLongerUsed();
337:                }
338:            }
339:
340:            /**
341:             * This Session is no longer used: - unexport Remote Object - return the
342:             * Session in the pool
343:             */
344:            public void noLongerUsed() {
345:                if (TraceEjb.isDebugIc()) {
346:                    TraceEjb.interp.log(BasicLevel.DEBUG, "");
347:                }
348:
349:                // Unexport the EJBObject from the Orb
350:                if (myremote != null) {
351:                    try {
352:                        myremote.unexportObject();
353:                    } catch (NoSuchObjectException e) {
354:                        TraceEjb.logger.log(BasicLevel.ERROR,
355:                                "unexportObject failed", e);
356:                    }
357:                }
358:
359:                // Forget transaction that could be uncommitted.
360:                // Avoids to get it in another session bean later.
361:                if (beanTx != null) {
362:                    TraceEjb.tx.log(BasicLevel.WARN,
363:                            "transaction not ended. forget it");
364:                    beanTx = null;
365:                }
366:
367:                // return the SessionSwitch in the pool.
368:                // will be reused for another Session.
369:                bf.removeEJB(this );
370:
371:                // Remove this object.
372:                // Stateful session contexts are not pooled. (EJB spec.)
373:                ((JStatefulFactory) bf).removeStateful(sessionId);
374:                bctx = null;
375:                sessionId = -1;
376:                passivated = false;
377:                usedcount = 0;
378:            }
379:
380:            /**
381:             * End of Transaction
382:             */
383:            public void txCompleted() {
384:                if (TraceEjb.isDebugIc()) {
385:                    TraceEjb.interp.log(BasicLevel.DEBUG, "");
386:                }
387:                currTx = null;
388:                if (expired) {
389:                    timeoutExpired(null); // try again
390:                }
391:            }
392:
393:            /**
394:             * This is used for remove on stateful session beans only.
395:             * @return True if bean is participating in a client transaction
396:             */
397:            public boolean isInTransaction() {
398:                return (currTx != null && !mustCommit);
399:            }
400:
401:            /**
402:             * set a flag to remember that the transaction must be committed
403:             */
404:            public void setMustCommit(boolean mc) {
405:                mustCommit = mc;
406:            }
407:
408:            /**
409:             * Keep the bean opened transaction for later use in other methods. Stateful
410:             * session bean may open a transaction and use it in other methods. This is
411:             * called at postInvoke
412:             */
413:            public void saveBeanTx() {
414:                if (bf.isTxBeanManaged()) {
415:                    if (TraceEjb.isDebugTx()) {
416:                        TraceEjb.tx.log(BasicLevel.DEBUG, "");
417:                    }
418:                    try {
419:                        beanTx = bf.getTransactionManager().suspend();
420:                    } catch (SystemException e) {
421:                        TraceEjb.logger.log(BasicLevel.ERROR,
422:                                "cannot suspend transaction:", e);
423:                    }
424:                }
425:            }
426:
427:            /**
428:             * @return the last access time in milliseconds
429:             */
430:            public long getLastAccessTime() {
431:                return lastaccesstime;
432:            }
433:
434:            // ===============================================================
435:            // private methods
436:            // ===============================================================
437:
438:            /**
439:             * Check Transaction This is called at preInvoke
440:             * @param tx The current Transaction Context
441:             * @throws EJBException
442:             * @throws TransactionRolledbackLocalException
443:             */
444:            private synchronized void checkTx(Transaction tx) {
445:
446:                // No check if no Synchro, except for bean managed transaction.
447:                if (bf.isSessionSynchro() == false) {
448:                    // Resume bean associated transaction.
449:                    // Stateful session bean may open a transaction and use it in other
450:                    // methods.
451:                    if (bf.isTxBeanManaged() && beanTx != null) {
452:                        if (TraceEjb.isDebugTx()) {
453:                            TraceEjb.tx.log(BasicLevel.DEBUG,
454:                                    "resuming Bean Managed Tx");
455:                        }
456:                        try {
457:                            bf.getTransactionManager().resume(beanTx);
458:                        } catch (SystemException e) {
459:                            TraceEjb.logger.log(BasicLevel.ERROR,
460:                                    "cannot resume transaction", e);
461:                        } catch (InvalidTransactionException e) {
462:                            TraceEjb.logger.log(BasicLevel.ERROR,
463:                                    "Cannot resume transaction", e);
464:                        }
465:                    } else {
466:                        if (TraceEjb.isDebugTx()) {
467:                            TraceEjb.tx.log(BasicLevel.DEBUG, "no checkTx");
468:                        }
469:                    }
470:                    return;
471:                }
472:
473:                if (tx == null) {
474:                    if (TraceEjb.isDebugTx()) {
475:                        TraceEjb.tx.log(BasicLevel.DEBUG, "(No Tx)");
476:                    }
477:                    if (currTx != null) {
478:                        // A synchronized session must be called in the same transaction
479:                        // between afterBegin and beforeCompletion calls
480:                        TraceEjb.logger
481:                                .log(BasicLevel.ERROR,
482:                                        "synchronized session called outside transaction context");
483:                        throw new EJBException(
484:                                "Synchronized session called outside transaction context");
485:                    }
486:                } else {
487:                    if (TraceEjb.isDebugTx()) {
488:                        TraceEjb.tx.log(BasicLevel.DEBUG, "");
489:                    }
490:                    if (currTx == null) {
491:                        // A new transaction starts on this synchronized session
492:                        try {
493:                            SessionSynchronization ssbean = (SessionSynchronization) bctx
494:                                    .getInstance();
495:                            if (ssbean == null) {
496:                                throw new EJBException(
497:                                        "Instance should have been reactivated first.");
498:                            }
499:                            tx.registerSynchronization(bctx);
500:                            ssbean.afterBegin();
501:                        } catch (RollbackException e) {
502:                            throw new TransactionRolledbackLocalException(
503:                                    "Session rolled back");
504:                        } catch (SystemException e) {
505:                            throw new EJBException("checkTx error", e);
506:                        } catch (RemoteException e) {
507:                            throw new EJBException("checkTx error", e);
508:                        }
509:                        currTx = tx;
510:                    } else {
511:                        // A synchronized session must be called in the same transaction
512:                        // between afterBegin and beforeCompletion calls
513:                        if (tx.equals(currTx) == false) {
514:                            TraceEjb.logger
515:                                    .log(BasicLevel.ERROR,
516:                                            "synchronized session called in another transaction context");
517:                            throw new EJBException(
518:                                    "Synchronized session called in another transaction context");
519:                        }
520:                    }
521:                }
522:            }
523:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.