KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb > StatefulSessionContainer


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.ejb;
23
24 import java.lang.reflect.Method JavaDoc;
25 import java.lang.reflect.InvocationTargetException JavaDoc;
26 import java.util.Map JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.Hashtable JavaDoc;
29 import java.util.Set JavaDoc;
30 import java.rmi.RemoteException JavaDoc;
31
32 import javax.ejb.EJBObject JavaDoc;
33 import javax.ejb.EJBLocalObject JavaDoc;
34 import javax.ejb.RemoveException JavaDoc;
35 import javax.ejb.EJBException JavaDoc;
36 import javax.ejb.Handle JavaDoc;
37 import javax.management.ObjectName JavaDoc;
38
39 import org.jboss.invocation.Invocation;
40 import org.jboss.invocation.InvocationType;
41 import org.jboss.util.UnreachableStatementException;
42
43 /**
44  * The container for <em>stateful</em> session beans.
45  * @author <a HREF="mailto:rickard.oberg@telkel.com">Rickard ´┐Żberg</a>
46  * @author <a HREF="mailto:docodan@mvcsoft.com">Daniel OConnor</a>
47  * @author <a HREF="mailto:marc.fleury@jboss.org">Marc Fleury</a>
48  * @author <a HREF="mailto:scott.stark@jboss.org">Scott Stark</a>
49  * @author <a HREF="mailto:jason@planet57.com">Jason Dillon</a>
50  * @author <a HREF="mailto:Christoph.Jung@infor.de">Christoph G. Jung</a>
51  * @version <tt>$Revision: 37459 $</tt>
52  * @jmx:mbean extends="org.jboss.ejb.ContainerMBean"
53  */

54
55 public class StatefulSessionContainer
56    extends SessionContainer
57    implements EJBProxyFactoryContainer, InstancePoolContainer
58 {
59    /**
60     * This is the persistence manager for this container
61     */

62    protected StatefulSessionPersistenceManager persistenceManager;
63
64    /**
65     * The instance cache.
66     */

67    protected InstanceCache instanceCache;
68    protected Method JavaDoc getEJBObject;
69
70    public void setInstanceCache(InstanceCache ic)
71    {
72       this.instanceCache = ic;
73       ic.setContainer(this);
74    }
75
76    public InstanceCache getInstanceCache()
77    {
78       return instanceCache;
79    }
80
81    public StatefulSessionPersistenceManager getPersistenceManager()
82    {
83       return persistenceManager;
84    }
85
86    public void setPersistenceManager(StatefulSessionPersistenceManager pm)
87    {
88       persistenceManager = pm;
89       pm.setContainer(this);
90    }
91
92    /**
93     * Override getMethodPermissions to work around the fact that stateful
94     * session handles obtain their ejb objects by doing an invocation on the
95     * container as a home method invocation using the Handle.getEJBObject
96     * method.
97     * @param m
98     * @param iface
99     * @return
100     */

101    public Set JavaDoc getMethodPermissions(Method JavaDoc m, InvocationType iface)
102    {
103       if (m.equals(getEJBObject) == false)
104          return super.getMethodPermissions(m, iface);
105
106       Class JavaDoc[] sig = {};
107       Set JavaDoc permissions = getBeanMetaData().getMethodPermissions("create",
108          sig, iface);
109       return permissions;
110    }
111
112    // Container implementation --------------------------------------
113
protected void createService() throws Exception JavaDoc
114    {
115       super.createService();
116       // Get the Handle.getEJBObject method for permission checks
117
try
118       {
119          getEJBObject = Handle JavaDoc.class.getMethod("getEJBObject",
120             new Class JavaDoc[0]);
121       }
122       catch (Exception JavaDoc e)
123       {
124          log.warn("Failed to grant access to the Handle.getEJBObject method");
125       }
126    }
127
128    /**
129     * creates and registers the instance cache
130     */

131    protected void createInstanceCache() throws Exception JavaDoc
132    {
133       // Try to register the instance cache as an MBean
134
try
135       {
136          ObjectName JavaDoc containerName = super.getJmxName();
137          Hashtable JavaDoc props = containerName.getKeyPropertyList();
138          props.put("plugin", "cache");
139          ObjectName JavaDoc cacheName = new ObjectName JavaDoc(containerName.getDomain(), props);
140          server.registerMBean(instanceCache, cacheName);
141       }
142       catch (Throwable JavaDoc t)
143       {
144          log.debug("Failed to register cache as mbean", t);
145       }
146       // Init instance cache
147
instanceCache.create();
148    }
149
150    /**
151     * create persistence manager
152     */

153    protected void createPersistenceManager() throws Exception JavaDoc
154    {
155       persistenceManager.create();
156    }
157
158    /**
159     * Start persistence
160     */

161    protected void startPersistenceManager() throws Exception JavaDoc
162    {
163       persistenceManager.start();
164    }
165
166    /**
167     * Start instance cache
168     */

169    protected void startInstanceCache() throws Exception JavaDoc
170    {
171       instanceCache.start();
172    }
173
174    /**
175     * Stop persistence
176     */

177    protected void stopPersistenceManager()
178    {
179       persistenceManager.stop();
180    }
181
182    /**
183     * Stop instance cache
184     */

185    protected void stopInstanceCache()
186    {
187       instanceCache.stop();
188    }
189
190    protected void destroyPersistenceManager()
191    {
192       // Destroy persistence
193
persistenceManager.destroy();
194       persistenceManager.setContainer(null);
195    }
196
197    protected void destroyInstanceCache()
198    {
199       // Destroy instance cache
200
instanceCache.destroy();
201       instanceCache.setContainer(null);
202       try
203       {
204          ObjectName JavaDoc containerName = super.getJmxName();
205          Hashtable JavaDoc props = containerName.getKeyPropertyList();
206          props.put("plugin", "cache");
207          ObjectName JavaDoc cacheName = new ObjectName JavaDoc(containerName.getDomain(), props);
208          server.unregisterMBean(cacheName);
209       }
210       catch (Throwable JavaDoc ignore)
211       {
212       }
213    }
214
215    // EJBObject implementation --------------------------------------
216

217    public void remove(Invocation mi)
218       throws RemoteException JavaDoc, RemoveException JavaDoc
219    {
220       // 7.6 EJB2.0, it is illegal to remove a bean while in a transaction
221
// if (((EnterpriseContext) mi.getEnterpriseContext()).getTransaction() != null)
222
// throw new RemoveException("StatefulSession bean in transaction, cannot remove (EJB2.0 7.6)");
223

224       // if the session is removed already then let the user know they have a problem
225
StatefulSessionEnterpriseContext ctx = (StatefulSessionEnterpriseContext) mi.getEnterpriseContext();
226       if (ctx.getId() == null)
227       {
228          throw new RemoveException JavaDoc("SFSB has been removed already");
229       }
230
231       // Remove from storage
232
try
233       {
234          AllowedOperationsAssociation.pushInMethodFlag(IN_EJB_REMOVE);
235          getPersistenceManager().removeSession(ctx);
236       }
237       finally
238       {
239          AllowedOperationsAssociation.popInMethodFlag();
240       }
241
242       // We signify "removed" with a null id
243
ctx.setId(null);
244       removeCount++;
245    }
246
247    // Home interface implementation ---------------------------------
248

249    private void createSession(final Method JavaDoc m,
250       final Object JavaDoc[] args,
251       final StatefulSessionEnterpriseContext ctx)
252       throws Exception JavaDoc
253    {
254       // Create a new ID and set it
255
Object JavaDoc id = getPersistenceManager().createId(ctx);
256       log.debug("Created new session ID: " + id);
257       ctx.setId(id);
258
259       // Invoke ejbCreate<METHOD>()
260
try
261       {
262          AllowedOperationsAssociation.pushInMethodFlag(IN_EJB_CREATE);
263
264          // Build the ejbCreate<METHOD> from the home create<METHOD> sig
265
String JavaDoc createName = m.getName();
266          Object JavaDoc instance = ctx.getInstance();
267          String JavaDoc ejbCreateName = "ejbC" + createName.substring(1);
268          Method JavaDoc createMethod = instance.getClass().getMethod(ejbCreateName, m.getParameterTypes());
269          log.debug("Using create method for session: " + createMethod);
270          createMethod.invoke(instance, args);
271          createCount++;
272       }
273       catch (IllegalAccessException JavaDoc e)
274       {
275          ctx.setId(null);
276
277          throw new EJBException JavaDoc(e);
278       }
279       catch (InvocationTargetException JavaDoc e)
280       {
281          ctx.setId(null);
282
283          Throwable JavaDoc t = e.getTargetException();
284          if (t instanceof RuntimeException JavaDoc)
285          {
286             if (t instanceof EJBException JavaDoc)
287                throw (EJBException JavaDoc) t;
288             // Wrap runtime exceptions
289
throw new EJBException JavaDoc((Exception JavaDoc) t);
290          }
291          else if (t instanceof Exception JavaDoc)
292          {
293             // Remote, Create, or custom app. exception
294
throw (Exception JavaDoc) t;
295          }
296          else if (t instanceof Error JavaDoc)
297          {
298             throw (Error JavaDoc) t;
299          }
300          else
301          {
302             throw new org.jboss.util.UnexpectedThrowable(t);
303          }
304       }
305       finally
306       {
307          AllowedOperationsAssociation.popInMethodFlag();
308       }
309
310       // call back to the PM to let it know that ejbCreate has been called with success
311
getPersistenceManager().createdSession(ctx);
312
313       // Insert in cache
314
getInstanceCache().insert(ctx);
315
316       // Create EJBObject
317
if (getProxyFactory() != null)
318          ctx.setEJBObject((EJBObject JavaDoc) getProxyFactory().getStatefulSessionEJBObject(id));
319
320       // Create EJBLocalObject
321
if (getLocalHomeClass() != null)
322          ctx.setEJBLocalObject(getLocalProxyFactory().getStatefulSessionEJBLocalObject(id));
323    }
324
325    public EJBObject JavaDoc createHome(Invocation mi)
326       throws Exception JavaDoc
327    {
328       StatefulSessionEnterpriseContext ctx = (StatefulSessionEnterpriseContext) mi.getEnterpriseContext();
329       createSession(mi.getMethod(), mi.getArguments(), ctx);
330       return ctx.getEJBObject();
331    }
332
333
334    // local home interface implementation
335

336    /**
337     * @throws Error Not yet implemented
338     */

339    public void removeLocalHome(Invocation mi)
340       throws RemoteException JavaDoc, RemoveException JavaDoc
341    {
342       throw new UnreachableStatementException();
343    }
344
345    public EJBLocalObject JavaDoc createLocalHome(Invocation mi)
346       throws Exception JavaDoc
347    {
348       StatefulSessionEnterpriseContext ctx = (StatefulSessionEnterpriseContext) mi.getEnterpriseContext();
349       createSession(mi.getMethod(), mi.getArguments(), ctx);
350       return ctx.getEJBLocalObject();
351    }
352
353    /**
354     * A method for the getEJBObject from the handle
355     */

356    public EJBObject JavaDoc getEJBObject(Invocation mi) throws RemoteException JavaDoc
357    {
358       // All we need is an EJBObject for this Id, the first argument is the Id
359
EJBProxyFactory ci = getProxyFactory();
360       if (ci == null)
361       {
362          String JavaDoc msg = "No ProxyFactory, check for ProxyFactoryFinderInterceptor";
363          throw new IllegalStateException JavaDoc(msg);
364       }
365
366       Object JavaDoc id = mi.getArguments()[0];
367       if (id == null)
368          throw new IllegalStateException JavaDoc("Cannot get a session interface with a null id");
369
370       // Does the session still exist?
371
InstanceCache cache = getInstanceCache();
372       BeanLock lock = getLockManager().getLock(id);
373       lock.sync();
374       try
375       {
376          if (cache.get(id) == null)
377             throw new RemoteException JavaDoc("Session no longer exists: " + id);
378       }
379       finally
380       {
381          lock.releaseSync();
382          getLockManager().removeLockRef(id);
383       }
384
385       // Ok lets create the proxy
386
return (EJBObject JavaDoc) ci.getStatefulSessionEJBObject(id);
387    }
388
389
390    // EJBHome implementation ----------------------------------------
391

392    //
393
// These are implemented in the local proxy
394
//
395

396    /**
397     * @throws Error Not yet implemented
398     */

399    public void removeHome(Invocation mi)
400       throws RemoteException JavaDoc, RemoveException JavaDoc
401    {
402       throw new Error JavaDoc("Not Yet Implemented");
403    }
404
405    // Private -------------------------------------------------------
406

407    protected void setupHomeMapping() throws Exception JavaDoc
408    {
409       // Adrian Brock: This should go away when we don't support EJB1x
410
boolean isEJB1x = metaData.getApplicationMetaData().isEJB1x();
411
412       Map JavaDoc map = new HashMap JavaDoc();
413
414       if (homeInterface != null)
415       {
416
417          Method JavaDoc[] m = homeInterface.getMethods();
418          for (int i = 0; i < m.length; i++)
419          {
420             try
421             {
422                // Implemented by container
423
if (isEJB1x == false && m[i].getName().startsWith("create"))
424                {
425                   map.put(m[i], getClass().getMethod("createHome",
426                      new Class JavaDoc[]{Invocation.class}));
427                }
428                else
429                {
430                   map.put(m[i], getClass().getMethod(m[i].getName() + "Home",
431                      new Class JavaDoc[]{Invocation.class}));
432                }
433             }
434             catch (NoSuchMethodException JavaDoc e)
435             {
436                log.info(m[i].getName() + " in bean has not been mapped");
437             }
438          }
439       }
440
441       if (localHomeInterface != null)
442       {
443          Method JavaDoc[] m = localHomeInterface.getMethods();
444          for (int i = 0; i < m.length; i++)
445          {
446             try
447             {
448                // Implemented by container
449
if (isEJB1x == false && m[i].getName().startsWith("create"))
450                {
451                   map.put(m[i], getClass().getMethod("createLocalHome",
452                      new Class JavaDoc[]{Invocation.class}));
453                }
454                else
455                {
456                   map.put(m[i], getClass().getMethod(m[i].getName() + "LocalHome",
457                      new Class JavaDoc[]{Invocation.class}));
458                }
459             }
460             catch (NoSuchMethodException JavaDoc e)
461             {
462                log.info(m[i].getName() + " in bean has not been mapped");
463             }
464          }
465       }
466
467       try
468       {
469          // Get getEJBObject from on Handle, first get the class
470
Class JavaDoc handleClass = Class.forName("javax.ejb.Handle");
471
472          //Get only the one called handle.getEJBObject
473
Method JavaDoc getEJBObjectMethod = handleClass.getMethod("getEJBObject", new Class JavaDoc[0]);
474
475          //Map it in the home stuff
476
map.put(getEJBObjectMethod, getClass().getMethod("getEJBObject",
477             new Class JavaDoc[]{Invocation.class}));
478       }
479       catch (NoSuchMethodException JavaDoc e)
480       {
481          log.debug("Couldn't find getEJBObject method on container");
482       }
483
484       homeMapping = map;
485    }
486
487    protected Interceptor createContainerInterceptor()
488    {
489       return new ContainerInterceptor();
490    }
491
492    /**
493     * This is the last step before invocation - all interceptors are done
494     */

495    class ContainerInterceptor
496       extends AbstractContainerInterceptor
497    {
498       public Object JavaDoc invokeHome(Invocation mi) throws Exception JavaDoc
499       {
500          boolean trace = log.isTraceEnabled();
501
502          if (trace)
503          {
504             log.trace("HOMEMETHOD coming in ");
505             log.trace("" + mi.getMethod());
506             log.trace("HOMEMETHOD coming in hashcode" + mi.getMethod().hashCode());
507             log.trace("HOMEMETHOD coming in classloader" + mi.getMethod().getDeclaringClass().getClassLoader().hashCode());
508             log.trace("CONTAINS " + getHomeMapping().containsKey(mi.getMethod()));
509          }
510
511          Method JavaDoc miMethod = mi.getMethod();
512          Method JavaDoc m = (Method JavaDoc) getHomeMapping().get(miMethod);
513          if (m == null)
514          {
515             String JavaDoc msg = "Invalid invocation, check your deployment packaging"
516                + ", method=" + miMethod;
517             throw new EJBException JavaDoc(msg);
518          }
519
520          // Invoke and handle exceptions
521
if (trace)
522          {
523             log.trace("HOMEMETHOD m " + m);
524             java.util.Iterator JavaDoc iterator = getHomeMapping().keySet().iterator();
525             while (iterator.hasNext())
526             {
527                Method JavaDoc me = (Method JavaDoc) iterator.next();
528
529                if (me.getName().endsWith("create"))
530                {
531                   log.trace(me.toString());
532                   log.trace("" + me.hashCode());
533                   log.trace("" + me.getDeclaringClass().getClassLoader().hashCode());
534                   log.trace("equals " + me.equals(mi.getMethod()) + " " + mi.getMethod().equals(me));
535                }
536             }
537          }
538
539          try
540          {
541             return mi.performCall(StatefulSessionContainer.this, m, new Object JavaDoc[]{mi});
542          }
543          catch (Exception JavaDoc e)
544          {
545             rethrow(e);
546          }
547
548          // We will never get this far, but the compiler does not know that
549
throw new org.jboss.util.UnreachableStatementException();
550       }
551
552       public Object JavaDoc invoke(Invocation mi) throws Exception JavaDoc
553       {
554          // wire the transaction on the context, this is how the instance remember the tx
555
// Unlike Entity beans we can't do that in the previous interceptors (ordering)
556
EnterpriseContext ctx = (EnterpriseContext) mi.getEnterpriseContext();
557          if (ctx.getTransaction() == null)
558             ctx.setTransaction(mi.getTransaction());
559
560          // Get method
561
Method JavaDoc miMethod = mi.getMethod();
562          Method JavaDoc m = (Method JavaDoc) getBeanMapping().get(miMethod);
563          if (m == null)
564          {
565             String JavaDoc msg = "Invalid invocation, check your deployment packaging"
566                + ", method=" + miMethod;
567             throw new EJBException JavaDoc(msg);
568          }
569
570          // Select instance to invoke (container or bean)
571
if (m.getDeclaringClass().equals(StatefulSessionContainer.class)
572             || m.getDeclaringClass().equals(SessionContainer.class))
573          {
574             // Invoke and handle exceptions
575
try
576             {
577                return mi.performCall(StatefulSessionContainer.this, m, new Object JavaDoc[]{mi});
578             }
579             catch (Exception JavaDoc e)
580             {
581                rethrow(e);
582             }
583          }
584          else
585          {
586             // Invoke and handle exceptions
587
try
588             {
589                Object JavaDoc bean = ctx.getInstance();
590                return mi.performCall(bean, m, mi.getArguments());
591             }
592             catch (Exception JavaDoc e)
593             {
594                rethrow(e);
595             }
596          }
597
598          // We will never get this far, but the compiler does not know that
599
throw new org.jboss.util.UnreachableStatementException();
600       }
601    }
602 }
603
Popular Tags