Source Code Cross Referenced for StatefulInstanceManager.java in  » J2EE » openejb3 » org » apache » openejb » core » stateful » 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 » openejb3 » org.apache.openejb.core.stateful 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         *
009:         *     http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */package org.apache.openejb.core.stateful;
017:
018:        import org.apache.openejb.ApplicationException;
019:        import org.apache.openejb.Injection;
020:        import org.apache.openejb.InvalidateReferenceException;
021:        import org.apache.openejb.OpenEJBException;
022:        import org.apache.openejb.SystemException;
023:        import org.apache.openejb.core.BaseContext;
024:        import org.apache.openejb.core.CoreDeploymentInfo;
025:        import org.apache.openejb.core.CoreUserTransaction;
026:        import org.apache.openejb.core.Operation;
027:        import org.apache.openejb.core.ThreadContext;
028:        import org.apache.openejb.core.interceptor.InterceptorData;
029:        import org.apache.openejb.core.interceptor.InterceptorStack;
030:        import org.apache.openejb.core.ivm.IntraVmCopyMonitor;
031:        import org.apache.openejb.core.transaction.TransactionRolledbackException;
032:        import org.apache.openejb.persistence.JtaEntityManagerRegistry;
033:        import org.apache.openejb.spi.SecurityService;
034:        import org.apache.openejb.util.Index;
035:        import org.apache.openejb.util.LogCategory;
036:        import org.apache.openejb.util.Logger;
037:        import org.apache.openejb.util.PojoSerialization;
038:        import org.apache.xbean.recipe.ObjectRecipe;
039:        import org.apache.xbean.recipe.Option;
040:        import org.apache.xbean.recipe.StaticRecipe;
041:        import org.apache.xbean.recipe.ConstructionException;
042:
043:        import javax.ejb.EJBException;
044:        import javax.ejb.SessionContext;
045:        import javax.ejb.SessionBean;
046:        import javax.naming.Context;
047:        import javax.naming.NamingException;
048:        import javax.persistence.EntityManager;
049:        import javax.persistence.EntityManagerFactory;
050:        import javax.transaction.Transaction;
051:        import javax.transaction.TransactionManager;
052:        import java.lang.reflect.Method;
053:        import java.rmi.NoSuchObjectException;
054:        import java.rmi.RemoteException;
055:        import java.util.Hashtable;
056:        import java.util.LinkedList;
057:        import java.util.Map;
058:        import java.util.HashMap;
059:        import java.util.List;
060:        import java.io.Serializable;
061:        import java.io.ObjectStreamException;
062:
063:        public class StatefulInstanceManager {
064:            public static final Logger logger = Logger.getInstance(
065:                    LogCategory.OPENEJB, "org.apache.openejb.util.resources");
066:
067:            protected final long timeOut;
068:
069:            // queue of beans for LRU algorithm
070:            private final BeanEntryQueue lruQueue;
071:
072:            private final PassivationStrategy passivator;
073:
074:            private final int bulkPassivationSize;
075:
076:            private final TransactionManager transactionManager;
077:            private final SecurityService securityService;
078:            private final JtaEntityManagerRegistry jtaEntityManagerRegistry;
079:
080:            public StatefulInstanceManager(
081:                    TransactionManager transactionManager,
082:                    SecurityService securityService,
083:                    JtaEntityManagerRegistry jtaEntityManagerRegistry,
084:                    Class passivatorClass, int timeout, int poolSize,
085:                    int bulkPassivate) throws OpenEJBException {
086:                this .transactionManager = transactionManager;
087:                this .securityService = securityService;
088:                this .jtaEntityManagerRegistry = jtaEntityManagerRegistry;
089:                this .lruQueue = new BeanEntryQueue(poolSize);
090:                if (poolSize == 0) {
091:                    this .bulkPassivationSize = 1;
092:                } else {
093:                    this .bulkPassivationSize = Math
094:                            .min(bulkPassivate, poolSize);
095:                }
096:                this .timeOut = timeout * 60 * 1000;
097:
098:                try {
099:                    passivatorClass = (passivatorClass == null) ? SimplePassivater.class
100:                            : passivatorClass;
101:                    passivator = (PassivationStrategy) passivatorClass
102:                            .newInstance();
103:                } catch (Exception e) {
104:                    throw new OpenEJBException(
105:                            "Could not create the passivator "
106:                                    + passivatorClass.getName(), e);
107:                }
108:            }
109:
110:            public void deploy(CoreDeploymentInfo deploymentInfo,
111:                    Index<Method, StatefulContainer.MethodType> index)
112:                    throws OpenEJBException {
113:                deploymentInfo.setContainerData(new Data(index));
114:            }
115:
116:            public void undeploy(CoreDeploymentInfo deploymentInfo)
117:                    throws OpenEJBException {
118:                Data data = (Data) deploymentInfo.getContainerData();
119:                if (data != null) {
120:                    for (BeanEntry entry : data.getBeanIndex().values()) {
121:                        lruQueue.remove(entry);
122:                    }
123:                    deploymentInfo.setContainerData(null);
124:                }
125:            }
126:
127:            Index<Method, StatefulContainer.MethodType> getMethodIndex(
128:                    CoreDeploymentInfo deploymentInfo) {
129:                Data data = (Data) deploymentInfo.getContainerData();
130:                return data.getMethodIndex();
131:            }
132:
133:            public Transaction getBeanTransaction(ThreadContext callContext)
134:                    throws OpenEJBException {
135:                BeanEntry entry = getBeanEntry(callContext);
136:                if (entry == null)
137:                    return null;
138:                return entry.beanTransaction;
139:            }
140:
141:            public void setBeanTransaction(ThreadContext callContext,
142:                    Transaction beanTransaction) throws OpenEJBException {
143:                BeanEntry entry = getBeanEntry(callContext);
144:                entry.beanTransaction = beanTransaction;
145:            }
146:
147:            public Map<EntityManagerFactory, EntityManager> getEntityManagers(
148:                    ThreadContext callContext,
149:                    Index<EntityManagerFactory, Map> factories)
150:                    throws OpenEJBException {
151:                BeanEntry entry = getBeanEntry(callContext);
152:                return entry.getEntityManagers(factories);
153:            }
154:
155:            public void setEntityManagers(ThreadContext callContext,
156:                    Index<EntityManagerFactory, EntityManager> entityManagers)
157:                    throws OpenEJBException {
158:                BeanEntry entry = getBeanEntry(callContext);
159:                entry.setEntityManagers(entityManagers);
160:            }
161:
162:            public Object newInstance(Object primaryKey, Class beanClass)
163:                    throws OpenEJBException {
164:                Object bean = null;
165:
166:                ThreadContext threadContext = ThreadContext.getThreadContext();
167:                Operation currentOperation = threadContext
168:                        .getCurrentOperation();
169:                try {
170:                    ObjectRecipe objectRecipe = new ObjectRecipe(beanClass);
171:                    objectRecipe.allow(Option.FIELD_INJECTION);
172:                    objectRecipe.allow(Option.PRIVATE_PROPERTIES);
173:                    //            objectRecipe.allow(Option.IGNORE_MISSING_PROPERTIES);
174:
175:                    ThreadContext callContext = ThreadContext
176:                            .getThreadContext();
177:                    CoreDeploymentInfo deploymentInfo = callContext
178:                            .getDeploymentInfo();
179:                    Context ctx = deploymentInfo.getJndiEnc();
180:                    SessionContext sessionContext;
181:                    synchronized (this ) {
182:                        try {
183:                            sessionContext = (SessionContext) ctx
184:                                    .lookup("java:comp/EJBContext");
185:                        } catch (NamingException e1) {
186:                            sessionContext = createSessionContext();
187:                            ctx.bind("java:comp/EJBContext", sessionContext);
188:                        }
189:                    }
190:                    if (javax.ejb.SessionBean.class.isAssignableFrom(beanClass)
191:                            || hasSetSessionContext(beanClass)) {
192:                        callContext.setCurrentOperation(Operation.INJECTION);
193:                        objectRecipe.setProperty("sessionContext",
194:                                new StaticRecipe(sessionContext));
195:                    }
196:
197:                    fillInjectionProperties(objectRecipe, beanClass,
198:                            deploymentInfo, ctx);
199:
200:                    bean = objectRecipe.create(beanClass.getClassLoader());
201:
202:                    Map unsetProperties = objectRecipe.getUnsetProperties();
203:                    if (unsetProperties.size() > 0) {
204:                        for (Object property : unsetProperties.keySet()) {
205:                            logger.warning("Injection: No such property '"
206:                                    + property + "' in class "
207:                                    + beanClass.getName());
208:                        }
209:                    }
210:                    HashMap<String, Object> interceptorInstances = new HashMap<String, Object>();
211:                    for (InterceptorData interceptorData : deploymentInfo
212:                            .getAllInterceptors()) {
213:                        if (interceptorData.getInterceptorClass().equals(
214:                                beanClass))
215:                            continue;
216:
217:                        Class clazz = interceptorData.getInterceptorClass();
218:                        ObjectRecipe interceptorRecipe = new ObjectRecipe(clazz);
219:                        interceptorRecipe.allow(Option.FIELD_INJECTION);
220:                        interceptorRecipe.allow(Option.PRIVATE_PROPERTIES);
221:                        interceptorRecipe
222:                                .allow(Option.IGNORE_MISSING_PROPERTIES);
223:
224:                        fillInjectionProperties(interceptorRecipe, clazz,
225:                                deploymentInfo, ctx);
226:
227:                        try {
228:                            Object interceptorInstance = interceptorRecipe
229:                                    .create(clazz.getClassLoader());
230:                            interceptorInstances.put(clazz.getName(),
231:                                    interceptorInstance);
232:                        } catch (ConstructionException e) {
233:                            throw new Exception(
234:                                    "Failed to create interceptor: "
235:                                            + clazz.getName(), e);
236:                        }
237:                    }
238:
239:                    interceptorInstances.put(beanClass.getName(), bean);
240:
241:                    callContext.setCurrentOperation(Operation.POST_CONSTRUCT);
242:
243:                    List<InterceptorData> callbackInterceptors = deploymentInfo
244:                            .getCallbackInterceptors();
245:                    InterceptorStack interceptorStack = new InterceptorStack(
246:                            bean, null, Operation.POST_CONSTRUCT,
247:                            callbackInterceptors, interceptorInstances);
248:                    interceptorStack.invoke();
249:
250:                    bean = newInstance(primaryKey, bean, interceptorInstances);
251:
252:                } catch (Throwable callbackException) {
253:                    /*
254:                    In the event of an exception, OpenEJB is required to log the exception, evict the instance,
255:                    and mark the transaction for rollback.  If there is a transaction to rollback, then the a
256:                      javax.transaction.TransactionRolledbackException must be throw to the client. Otherwise a
257:                    java.rmi.RemoteException is thrown to the client.
258:                    See EJB 1.1 specification, section 12.3.2
259:                    See EJB 2.0 specification, section 18.3.3
260:                     */
261:                    handleCallbackException(callbackException, bean,
262:                            threadContext, "setSessionContext");
263:                } finally {
264:                    threadContext.setCurrentOperation(currentOperation);
265:                }
266:
267:                // add to index
268:                BeanEntry entry = newBeanEntry(primaryKey, bean);
269:                getBeanIndex(threadContext).put(primaryKey, entry);
270:
271:                return bean;
272:            }
273:
274:            protected Instance newInstance(Object primaryKey, Object bean,
275:                    Map<String, Object> interceptorInstances) {
276:                return new Instance(bean, interceptorInstances);
277:            }
278:
279:            protected BeanEntry newBeanEntry(Object primaryKey, Object bean) {
280:                return new BeanEntry(bean, primaryKey, timeOut);
281:            }
282:
283:            private static void fillInjectionProperties(
284:                    ObjectRecipe objectRecipe, Class clazz,
285:                    CoreDeploymentInfo deploymentInfo, Context context) {
286:                for (Injection injection : deploymentInfo.getInjections()) {
287:                    if (!injection.getTarget().isAssignableFrom(clazz))
288:                        continue;
289:                    try {
290:                        String jndiName = injection.getJndiName();
291:                        Object object = context.lookup("java:comp/env/"
292:                                + jndiName);
293:                        if (object instanceof  String) {
294:                            String string = (String) object;
295:                            // Pass it in raw so it could be potentially converted to
296:                            // another data type by an xbean-reflect property editor
297:                            objectRecipe.setProperty(injection.getTarget()
298:                                    .getName()
299:                                    + "/" + injection.getName(), string);
300:                        } else {
301:                            objectRecipe.setProperty(injection.getTarget()
302:                                    .getName()
303:                                    + "/" + injection.getName(),
304:                                    new StaticRecipe(object));
305:                        }
306:                    } catch (NamingException e) {
307:                        logger
308:                                .warning("Injection data not found in enc: jndiName='"
309:                                        + injection.getJndiName()
310:                                        + "', target="
311:                                        + injection.getTarget()
312:                                        + "/" + injection.getName());
313:                    }
314:                }
315:            }
316:
317:            private boolean hasSetSessionContext(Class beanClass) {
318:                try {
319:                    beanClass.getMethod("setSessionContext",
320:                            SessionContext.class);
321:                    return true;
322:                } catch (NoSuchMethodException e) {
323:                    return false;
324:                }
325:            }
326:
327:            private SessionContext createSessionContext() {
328:                StatefulUserTransaction userTransaction = new StatefulUserTransaction(
329:                        new CoreUserTransaction(transactionManager),
330:                        jtaEntityManagerRegistry);
331:                return new StatefulContext(transactionManager, securityService,
332:                        userTransaction);
333:            }
334:
335:            public Object obtainInstance(Object primaryKey,
336:                    ThreadContext callContext) throws OpenEJBException {
337:                if (primaryKey == null) {
338:                    throw new SystemException(
339:                            new NullPointerException(
340:                                    "Cannot obtain an instance of the stateful session bean with a null session id"));
341:                }
342:
343:                // look for entry in index
344:                BeanEntry entry = getBeanIndex(callContext).get(primaryKey);
345:
346:                // if we didn't find the bean in the index, try to activate it
347:                if (entry == null) {
348:                    Object bean = activateInstance(primaryKey, callContext);
349:                    return bean;
350:                }
351:
352:                // if the bean is already in a transaction, just return it
353:                if (entry.beanTransaction != null) {
354:                    return entry.bean;
355:                }
356:
357:                // remove from the queue so it is not passivated while in use
358:                BeanEntry queueEntry = lruQueue.remove(entry);
359:                if (queueEntry != null) {
360:                    // if bean is timed out, destroy it
361:                    if (entry.isTimedOut()) {
362:                        entry = getBeanIndex(callContext).remove(
363:                                entry.primaryKey);
364:                        handleTimeout(entry, callContext);
365:                        throw new InvalidateReferenceException(
366:                                new NoSuchObjectException(
367:                                        "Stateful SessionBean has timed-out"));
368:                    }
369:                    return entry.bean;
370:                } else {
371:                    // if it is not in the queue, the bean is already being invoked
372:                    // the only reentrant/concurrent operations allowed are Session synchronization callbacks
373:                    Operation currentOperation = callContext
374:                            .getCurrentOperation();
375:                    if (currentOperation != Operation.AFTER_COMPLETION
376:                            && currentOperation != Operation.BEFORE_COMPLETION) {
377:                        throw new ApplicationException(new RemoteException(
378:                                "Concurrent calls not allowed"));
379:                    }
380:
381:                    return entry.bean;
382:                }
383:            }
384:
385:            private Object activateInstance(Object primaryKey,
386:                    ThreadContext callContext) throws SystemException,
387:                    ApplicationException {
388:                // attempt to active a passivated entity
389:                BeanEntry entry = activate(primaryKey);
390:                if (entry == null) {
391:                    throw new InvalidateReferenceException(
392:                            new NoSuchObjectException("Not Found"));
393:                }
394:
395:                return activateInstance(callContext, entry);
396:            }
397:
398:            public Object activateInstance(ThreadContext callContext,
399:                    BeanEntry entry) throws SystemException,
400:                    ApplicationException {
401:                if (entry.isTimedOut()) {
402:                    // Since the bean instance hasn't had its ejbActivate() method called yet,
403:                    // it is still considered to be passivated at this point. Instances that timeout
404:                    // while passivated must be evicted WITHOUT having their ejbRemove()
405:                    // method invoked. Section 6.6 of EJB 1.1 specification.
406:                    throw new InvalidateReferenceException(
407:                            new NoSuchObjectException("Timed Out"));
408:                }
409:
410:                // call the activate method
411:                Operation currentOperation = callContext.getCurrentOperation();
412:                callContext.setCurrentOperation(Operation.ACTIVATE);
413:                try {
414:                    CoreDeploymentInfo deploymentInfo = callContext
415:                            .getDeploymentInfo();
416:
417:                    StatefulInstanceManager.Instance instance = (StatefulInstanceManager.Instance) entry.bean;
418:                    Method remove = instance.bean instanceof  SessionBean ? SessionBean.class
419:                            .getMethod("ejbActivate")
420:                            : null;
421:
422:                    List<InterceptorData> callbackInterceptors = deploymentInfo
423:                            .getCallbackInterceptors();
424:                    InterceptorStack interceptorStack = new InterceptorStack(
425:                            instance.bean, remove, Operation.ACTIVATE,
426:                            callbackInterceptors, instance.interceptors);
427:
428:                    interceptorStack.invoke();
429:                } catch (Throwable callbackException) {
430:                    /*
431:                    In the event of an exception, OpenEJB is required to log the exception, evict the instance,
432:                    and mark the transaction for rollback.  If there is a transaction to rollback, then the a
433:                    javax.transaction.TransactionRolledbackException must be throw to the client. Otherwise a
434:                    java.rmi.RemoteException is thrown to the client.
435:                    See EJB 1.1 specification, section 12.3.2
436:                     */
437:                    handleCallbackException(callbackException, entry.bean,
438:                            callContext, "ejbActivate");
439:                } finally {
440:                    callContext.setCurrentOperation(currentOperation);
441:                }
442:
443:                // add it to the index
444:                getBeanIndex(callContext).put(entry.primaryKey, entry);
445:
446:                return entry.bean;
447:            }
448:
449:            protected void handleTimeout(BeanEntry entry,
450:                    ThreadContext threadContext) {
451:                Operation currentOperation = threadContext
452:                        .getCurrentOperation();
453:                threadContext.setCurrentOperation(Operation.PRE_DESTROY);
454:                BaseContext.State[] originalAllowedStates = threadContext
455:                        .setCurrentAllowedStates(StatefulContext.getStates());
456:                CoreDeploymentInfo deploymentInfo = threadContext
457:                        .getDeploymentInfo();
458:                Instance instance = (Instance) entry.bean;
459:
460:                try {
461:                    Method remove = instance.bean instanceof  SessionBean ? SessionBean.class
462:                            .getMethod("ejbRemove")
463:                            : null;
464:
465:                    List<InterceptorData> callbackInterceptors = deploymentInfo
466:                            .getCallbackInterceptors();
467:                    InterceptorStack interceptorStack = new InterceptorStack(
468:                            instance.bean, remove, Operation.PRE_DESTROY,
469:                            callbackInterceptors, instance.interceptors);
470:
471:                    interceptorStack.invoke();
472:                } catch (Throwable callbackException) {
473:                    /*
474:                      Exceptions are processed "quietly"; they are not reported to the client since
475:                      the timeout that caused the ejbRemove() operation did not, "technically", take
476:                      place in the context of a client call. Logically, it may have timeout sometime
477:                      before the client call.
478:                     */
479:                    String logMessage = "An unexpected exception occured while invoking the ejbRemove method on the timed-out Stateful SessionBean instance; "
480:                            + callbackException.getClass().getName()
481:                            + " "
482:                            + callbackException.getMessage();
483:
484:                    /* [1] Log the exception or error */
485:                    logger.error(logMessage);
486:
487:                } finally {
488:                    logger
489:                            .info("Removing the timed-out stateful session bean instance "
490:                                    + entry.primaryKey);
491:                    threadContext.setCurrentOperation(currentOperation);
492:                    threadContext
493:                            .setCurrentAllowedStates(originalAllowedStates);
494:                }
495:            }
496:
497:            public void poolInstance(ThreadContext callContext, Object bean)
498:                    throws OpenEJBException {
499:                // Don't pool if the bean has been undeployed
500:                if (callContext.getDeploymentInfo().isDestroyed())
501:                    return;
502:
503:                Object primaryKey = callContext.getPrimaryKey();
504:                if (primaryKey == null || bean == null) {
505:                    throw new SystemException("Invalid arguments");
506:                }
507:
508:                BeanEntry entry = getBeanIndex(callContext).get(primaryKey);
509:                if (entry == null) {
510:                    entry = activate(primaryKey);
511:                    if (entry == null) {
512:                        throw new SystemException("Invalid primaryKey:"
513:                                + primaryKey);
514:                    }
515:                } else if (entry.bean != bean) {
516:                    throw new SystemException("Invalid ID for bean");
517:                }
518:
519:                if (entry.beanTransaction == null) {
520:                    if (callContext.getCurrentOperation() != Operation.CREATE) {
521:                        try {
522:                            entry.beanTransaction = transactionManager
523:                                    .getTransaction();
524:                        } catch (javax.transaction.SystemException se) {
525:                            throw new SystemException(
526:                                    "TransactionManager failure", se);
527:                        }
528:                    }
529:
530:                    // only put in LRU if no current transaction
531:                    if (entry.beanTransaction == null) {
532:                        // add it to end of Queue; the most reciently used bean
533:                        lruQueue.add(entry);
534:
535:                        onPoolInstanceWithoutTransaction(callContext, entry);
536:                    }
537:                }
538:            }
539:
540:            protected void onPoolInstanceWithoutTransaction(
541:                    ThreadContext callContext, BeanEntry entry) {
542:            }
543:
544:            public Object freeInstance(ThreadContext threadContext)
545:                    throws SystemException {
546:                Object primaryKey = threadContext.getPrimaryKey();
547:                BeanEntry entry = getBeanIndex(threadContext)
548:                        .remove(primaryKey);// remove frm index
549:                if (entry == null) {
550:                    entry = activate(primaryKey);
551:                } else {
552:                    lruQueue.remove(entry);
553:                }
554:
555:                if (entry == null) {
556:                    return null;
557:                }
558:
559:                onFreeBeanEntry(threadContext, entry);
560:
561:                return entry.bean;
562:            }
563:
564:            protected void onFreeBeanEntry(ThreadContext threadContext,
565:                    BeanEntry entry) {
566:            }
567:
568:            protected void passivate() throws SystemException {
569:                final ThreadContext threadContext = ThreadContext
570:                        .getThreadContext();
571:                Hashtable<Object, BeanEntry> stateTable = new Hashtable<Object, BeanEntry>(
572:                        bulkPassivationSize);
573:
574:                BeanEntry currentEntry;
575:                final Operation currentOperation = threadContext
576:                        .getCurrentOperation();
577:                final BaseContext.State[] originalAllowedStates = threadContext
578:                        .setCurrentAllowedStates(StatefulContext.getStates());
579:                CoreDeploymentInfo deploymentInfo = threadContext
580:                        .getDeploymentInfo();
581:                try {
582:                    for (int i = 0; i < bulkPassivationSize; ++i) {
583:                        currentEntry = lruQueue.first();
584:                        if (currentEntry == null) {
585:                            break;
586:                        }
587:                        getBeanIndex(threadContext).remove(
588:                                currentEntry.primaryKey);
589:                        if (currentEntry.isTimedOut()) {
590:                            handleTimeout(currentEntry, threadContext);
591:                        } else {
592:                            passivate(threadContext, currentEntry);
593:                            stateTable.put(currentEntry.primaryKey,
594:                                    currentEntry);
595:                        }
596:                    }
597:                } finally {
598:                    threadContext.setCurrentOperation(currentOperation);
599:                    threadContext
600:                            .setCurrentAllowedStates(originalAllowedStates);
601:                }
602:
603:                /*
604:                   the IntraVmCopyMonitor.prePssivationOperation() demarcates 
605:                   the begining of passivation; used by EjbHomeProxyHandler, 
606:                   EjbObjectProxyHandler, IntraVmMetaData, and IntraVmHandle 
607:                   to deterime how serialization for these artifacts.
608:                 */
609:                try {
610:                    IntraVmCopyMonitor.prePassivationOperation();
611:
612:                    passivator.passivate(stateTable);
613:                } finally {
614:
615:                    IntraVmCopyMonitor.postPassivationOperation();
616:                }
617:            }
618:
619:            public void passivate(ThreadContext threadContext,
620:                    BeanEntry currentEntry) {
621:                CoreDeploymentInfo deploymentInfo = threadContext
622:                        .getDeploymentInfo();
623:                threadContext.setCurrentOperation(Operation.PASSIVATE);
624:                try {
625:                    StatefulInstanceManager.Instance instance = (StatefulInstanceManager.Instance) currentEntry.bean;
626:
627:                    Method passivate = instance.bean instanceof  SessionBean ? SessionBean.class
628:                            .getMethod("ejbPassivate")
629:                            : null;
630:
631:                    List<InterceptorData> callbackInterceptors = deploymentInfo
632:                            .getCallbackInterceptors();
633:                    InterceptorStack interceptorStack = new InterceptorStack(
634:                            instance.bean, passivate, Operation.PASSIVATE,
635:                            callbackInterceptors, instance.interceptors);
636:
637:                    interceptorStack.invoke();
638:
639:                } catch (Throwable e) {
640:
641:                    String logMessage = "An unexpected exception occured while invoking the ejbPassivate method on the Stateful SessionBean instance; "
642:                            + e.getClass().getName() + " " + e.getMessage();
643:
644:                    /* [1] Log the exception or error */
645:                    logger.error(logMessage);
646:                }
647:            }
648:
649:            protected BeanEntry activate(Object primaryKey)
650:                    throws SystemException {
651:                return (BeanEntry) passivator.activate(primaryKey);
652:            }
653:
654:            protected InvalidateReferenceException destroy(
655:                    ThreadContext callContext, BeanEntry entry, Exception t)
656:                    throws SystemException {
657:
658:                getBeanIndex(callContext).remove(entry.primaryKey);// remove frm index
659:                lruQueue.remove(entry);// remove from queue
660:                if (entry.beanTransaction != null) {
661:                    try {
662:                        entry.beanTransaction.setRollbackOnly();
663:                    } catch (javax.transaction.SystemException se) {
664:                        throw new SystemException(se);
665:                    } catch (IllegalStateException ise) {
666:                        throw new SystemException(
667:                                "Attempt to rollback a non-tx context", ise);
668:                    } catch (SecurityException lse) {
669:                        throw new SystemException(
670:                                "Container not authorized to rollback tx", lse);
671:                    }
672:                    return new InvalidateReferenceException(
673:                            new TransactionRolledbackException(t));
674:                } else if (t instanceof  RemoteException) {
675:                    return new InvalidateReferenceException(t);
676:                } else {
677:                    EJBException e = (EJBException) t;
678:                    return new InvalidateReferenceException(
679:                            new RemoteException(e.getMessage(), e
680:                                    .getCausedByException()));
681:                }
682:
683:            }
684:
685:            protected BeanEntry getBeanEntry(ThreadContext callContext)
686:                    throws OpenEJBException {
687:                Object primaryKey = callContext.getPrimaryKey();
688:                if (primaryKey == null) {
689:                    throw new SystemException(
690:                            new NullPointerException(
691:                                    "The primary key is null. Cannot get the bean entry"));
692:                }
693:                BeanEntry entry = getBeanIndex(callContext).get(primaryKey);
694:                if (entry == null) {
695:                    Object bean = this .obtainInstance(primaryKey, ThreadContext
696:                            .getThreadContext());
697:                    this .poolInstance(callContext, bean);
698:                    entry = getBeanIndex(callContext).get(primaryKey);
699:                }
700:                return entry;
701:            }
702:
703:            protected Hashtable<Object, BeanEntry> getBeanIndex(
704:                    ThreadContext threadContext) {
705:                CoreDeploymentInfo deployment = threadContext
706:                        .getDeploymentInfo();
707:                Data data = (Data) deployment.getContainerData();
708:                return data.getBeanIndex();
709:            }
710:
711:            private static class Data {
712:                private final Index<Method, StatefulContainer.MethodType> methodIndex;
713:                private final Hashtable<Object, BeanEntry> beanIndex = new Hashtable<Object, BeanEntry>();
714:
715:                private Data(
716:                        Index<Method, StatefulContainer.MethodType> methodIndex) {
717:                    this .methodIndex = methodIndex;
718:                }
719:
720:                public Index<Method, StatefulContainer.MethodType> getMethodIndex() {
721:                    return methodIndex;
722:                }
723:
724:                public Hashtable<Object, BeanEntry> getBeanIndex() {
725:                    return beanIndex;
726:                }
727:            }
728:
729:            class BeanEntryQueue {
730:                private final LinkedList<BeanEntry> list;
731:                private final int capacity;
732:
733:                protected BeanEntryQueue(int preferedCapacity) {
734:                    capacity = preferedCapacity;
735:                    list = new LinkedList<BeanEntry>();
736:                }
737:
738:                protected synchronized BeanEntry first() {
739:                    return list.removeFirst();
740:                }
741:
742:                protected synchronized void add(BeanEntry entry)
743:                        throws SystemException {
744:                    entry.resetTimeOut();
745:
746:                    list.addLast(entry);
747:                    entry.inQueue = true;
748:
749:                    if (list.size() >= capacity) {// is the LRU QUE full?
750:                        passivate();
751:                    }
752:                }
753:
754:                protected synchronized BeanEntry remove(BeanEntry entry) {
755:                    if (!entry.inQueue) {
756:                        return null;
757:                    }
758:                    if (list.remove(entry)) {
759:                        entry.inQueue = false;
760:                        return entry;
761:                    } else {
762:
763:                        return null;
764:                    }
765:                }
766:            }
767:
768:            protected void handleCallbackException(Throwable e,
769:                    Object instance, ThreadContext callContext, String callBack)
770:                    throws ApplicationException, SystemException {
771:
772:                String remoteMessage = "An unexpected exception occured while invoking the "
773:                        + callBack
774:                        + " method on the Stateful SessionBean instance";
775:                String logMessage = remoteMessage + "; "
776:                        + e.getClass().getName() + " " + e.getMessage();
777:
778:                /* [1] Log the exception or error */
779:                logger.error(logMessage);
780:
781:                /* [2] If the instance is in a transaction, mark the transaction for rollback. */
782:                Transaction transaction = null;
783:                try {
784:                    transaction = transactionManager.getTransaction();
785:                } catch (Throwable t) {
786:                    logger
787:                            .error("Could not retreive the current transaction from the transaction manager while handling a callback exception from the "
788:                                    + callBack
789:                                    + " method of bean "
790:                                    + callContext.getPrimaryKey());
791:                }
792:                if (transaction != null) {
793:                    markTxRollbackOnly(transaction);
794:                }
795:
796:                /* [3] Discard the instance */
797:                freeInstance(callContext);
798:
799:                /* [4] throw the java.rmi.RemoteException to the client */
800:                if (transaction == null) {
801:                    throw new InvalidateReferenceException(new RemoteException(
802:                            remoteMessage, e));
803:                } else {
804:                    throw new InvalidateReferenceException(
805:                            new TransactionRolledbackException(remoteMessage, e));
806:                }
807:
808:            }
809:
810:            protected void markTxRollbackOnly(Transaction tx)
811:                    throws SystemException {
812:                try {
813:                    if (tx != null) {
814:                        tx.setRollbackOnly();
815:                    }
816:                } catch (javax.transaction.SystemException se) {
817:                    throw new SystemException(se);
818:                }
819:            }
820:
821:            public static class Instance implements  Serializable {
822:                public final Object bean;
823:                public final Map<String, Object> interceptors;
824:
825:                public Instance(Object bean, Map<String, Object> interceptors) {
826:                    this .bean = bean;
827:                    this .interceptors = interceptors;
828:                }
829:
830:                protected Object writeReplace() throws ObjectStreamException {
831:                    return new Serialization(this );
832:                }
833:
834:                private static class Serialization implements  Serializable {
835:                    public final Object bean;
836:                    public final Map<String, Object> interceptors;
837:
838:                    public Serialization(Instance i) {
839:                        if (i.bean instanceof  Serializable) {
840:                            bean = i.bean;
841:                        } else {
842:                            bean = new PojoSerialization(i.bean);
843:                        }
844:
845:                        interceptors = new HashMap(i.interceptors.size());
846:                        for (Map.Entry<String, Object> e : i.interceptors
847:                                .entrySet()) {
848:                            if (e.getValue() == i.bean) {
849:                                // need to use the same wrapped reference or well get two copies.
850:                                interceptors.put(e.getKey(), bean);
851:                            } else if (!(e.getValue() instanceof  Serializable)) {
852:                                interceptors.put(e.getKey(),
853:                                        new PojoSerialization(e.getValue()));
854:                            }
855:                        }
856:                    }
857:
858:                    protected Object readResolve() throws ObjectStreamException {
859:                        // Anything wrapped with PojoSerialization will have been automatically
860:                        // unwrapped via it's own readResolve so passing in the raw bean
861:                        // and interceptors variables is totally fine.
862:                        return new Instance(bean, interceptors);
863:                    }
864:                }
865:            }
866:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.