FileDocCategorySizeDatePackage
StatefulContainer.javaAPI DocJBoss 4.2.129996Fri Jul 13 20:53:50 BST 2007org.jboss.ejb3.stateful

StatefulContainer

public class StatefulContainer extends org.jboss.ejb3.SessionContainer
Comment
author
Bill Burke
version
$Revision: 63485 $

Fields Summary
private static final Logger
log
protected org.jboss.ejb3.cache.StatefulCache
cache
Constructors Summary
public StatefulContainer(ClassLoader cl, String beanClassName, String ejbName, org.jboss.aop.AspectManager manager, Hashtable ctxProperties, org.jboss.ejb3.interceptor.InterceptorInfoRepository interceptorRepository, org.jboss.ejb3.Ejb3Deployment deployment)


           
                               
                             
   
      super(cl, beanClassName, ejbName, manager, ctxProperties, interceptorRepository, deployment);
      beanContextClass = StatefulBeanContext.class;
   
Methods Summary
private StatefulContainerInvocationbuildInvocation(org.jboss.aop.MethodInfo info, StatefulRemoteInvocation statefulInvocation)

      StatefulContainerInvocation newStatefulInvocation = null;
      Object newId = null;
      if (statefulInvocation.getId() == null)
      {
         StatefulBeanContext ctx = getCache().create();
         newId = ctx.getId();
         newStatefulInvocation = new StatefulContainerInvocation(info, newId);
      }
      else
      {
         newStatefulInvocation = new StatefulContainerInvocation(info, statefulInvocation.getId());
      }

      newStatefulInvocation.setArguments(statefulInvocation.getArguments());
      newStatefulInvocation.setMetaData(statefulInvocation.getMetaData());
      newStatefulInvocation.setAdvisor(this);

      return newStatefulInvocation;
   
private StatefulContainerInvocationbuildNewInvocation(org.jboss.aop.MethodInfo info, StatefulRemoteInvocation statefulInvocation, java.lang.Class[] initParameterTypes, java.lang.Object[] initParameterValues)

      StatefulContainerInvocation newStatefulInvocation = null;

      StatefulBeanContext ctx = null;
      if (initParameterTypes.length > 0)
         ctx = getCache().create(initParameterTypes, initParameterValues);
      else
         ctx = getCache().create();

      Object newId = ctx.getId();
      newStatefulInvocation = new StatefulContainerInvocation(info, newId);

      newStatefulInvocation.setArguments(statefulInvocation.getArguments());
      newStatefulInvocation.setMetaData(statefulInvocation.getMetaData());
      newStatefulInvocation.setAdvisor(this);

      return newStatefulInvocation;
   
public java.lang.ObjectcreateLocalProxy(java.lang.Object id)

      StatefulLocalProxyFactory factory = new StatefulLocalProxyFactory();
      factory.setContainer(this);
      factory.init();

      return factory.createProxy(id);
   
public java.lang.ObjectcreateRemoteProxy(java.lang.Object id)

      RemoteBinding binding = null;
      RemoteBindings bindings = (RemoteBindings) resolveAnnotation(RemoteBindings.class);
      if (bindings != null)
         binding = bindings.value()[0];
      else
         binding = (RemoteBinding) resolveAnnotation(RemoteBinding.class);
      
      StatefulRemoteProxyFactory factory = new StatefulRemoteProxyFactory();
      factory.setContainer(this);
      factory.setRemoteBinding(binding);
      factory.init();

      if (id != null)
         return factory.createProxy(id);
      else
         return factory.createProxy();
   
public java.lang.ObjectcreateSession()
Create a stateful bean and return its oid.

return

      ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
      pushEnc();
      try
      {
         Thread.currentThread().setContextClassLoader(classloader);
         return getCache().create().getId();
      }
      finally
      {
         Thread.currentThread().setContextClassLoader(oldLoader);
         popEnc();
      }
   
public java.lang.ObjectcreateSession(java.lang.Class[] initTypes, java.lang.Object[] initValues)
Create a stateful bean and return its oid.

return

      ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
      pushEnc();
      try
      {
         Thread.currentThread().setContextClassLoader(classloader);
         return getCache().create(initTypes, initValues).getId();
      }
      finally
      {
         Thread.currentThread().setContextClassLoader(oldLoader);
         popEnc();
      }
   
protected voiddestroySession(java.lang.Object id)

      getCache().remove(id);
   
public org.jboss.aop.joinpoint.InvocationResponsedynamicInvoke(java.lang.Object target, org.jboss.aop.joinpoint.Invocation invocation)
This should be a remote invocation call

param
invocation
return
throws
Throwable

      long start = System.currentTimeMillis();
      
      ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
      EJBContainerInvocation newSi = null;
      pushEnc();
      try
      {
         Thread.currentThread().setContextClassLoader(classloader);
         StatefulRemoteInvocation si = (StatefulRemoteInvocation) invocation;
         MethodInfo info = (MethodInfo) methodInterceptors.get(si.getMethodHash());
         if (info == null)
         {
            throw new RuntimeException("Could not resolve beanClass method from proxy call");
         }

         InvocationResponse response = null;
         Method unadvisedMethod = info.getUnadvisedMethod();
         Object newId = null;
         
         try
         {
            invokeStats.callIn();
            
            if (info != null && unadvisedMethod != null && isHomeMethod(unadvisedMethod))
            {
               response = invokeHomeMethod(info, si);
            }
            else if (info != null && unadvisedMethod != null && isEJBObjectMethod(unadvisedMethod))
            {
               response = invokeEJBObjectMethod(info, si);
            }
            else
            {
               if (si.getId() == null)
               {
                  StatefulBeanContext ctx = getCache().create();
                  newId = ctx.getId();
               }
               else
               {
                  newId = si.getId();
               }
               newSi = new StatefulContainerInvocation(info, newId);
               newSi.setArguments(si.getArguments());
               newSi.setMetaData(si.getMetaData());
               newSi.setAdvisor(this);
   
               Object rtn = null;
               
               invokedMethod.push(new InvokedMethod(false, unadvisedMethod));
               rtn = newSi.invokeNext();

               response = marshallResponse(invocation, rtn, newSi.getResponseContextInfo());
               if (newId != null) response.addAttachment(StatefulConstants.NEW_ID, newId);
            }
         }
         catch (Throwable throwable)
         {
            Throwable exception = throwable;
            if (newId != null)
            {
               exception = new ForwardId(throwable, newId);
            }
            Map responseContext = null;
            if (newSi != null) newSi.getResponseContextInfo();
            response = marshallException(invocation, exception, responseContext);
            return response;
         }
         finally
         {
            if (unadvisedMethod != null)
            {
               long end = System.currentTimeMillis();
               long elapsed = end - start;
               invokeStats.updateStats(unadvisedMethod, elapsed);
            }
            
            invokeStats.callOut();
            
            invokedMethod.pop();
         }

         return response;
      }
      finally
      {
         Thread.currentThread().setContextClassLoader(oldLoader);
         popEnc();
      }
   
public java.lang.ObjectgetBusinessObject(org.jboss.ejb3.BeanContext beanContext, java.lang.Class businessInterface)

      StatefulBeanContext ctx = (StatefulBeanContext) beanContext;

      boolean isRemote = false;
      boolean found = false;
      Class[] remoteInterfaces = ProxyFactoryHelper.getRemoteInterfaces(this);
      if (remoteInterfaces != null)
      {
         for (Class intf : remoteInterfaces)
         {
            if (intf.getName().equals(businessInterface.getName()))
            {
               isRemote = true;
               found = true;
               break;
            }
         }
      }
      if (found == false)
      {
         Class[] localInterfaces = ProxyFactoryHelper.getLocalInterfaces(this);
         if (localInterfaces != null)
         {
            for (Class intf : localInterfaces)
            {
               if (intf.getName().equals(businessInterface.getName()))
               {
                  found = true;
                  break;
               }
            }

         }
      }
      if (found == false) throw new IllegalStateException(businessInterface.getName() + " is not a business interface");

      for (ProxyFactory factory : proxyDeployer.getProxyFactories())
      {
         if (isRemote && factory instanceof StatefulRemoteProxyFactory)
         {
            return ((StatefulRemoteProxyFactory) factory).createProxy(ctx.getId());
         }
         else if (!isRemote && factory instanceof StatefulLocalProxyFactory)
         {
            return ((StatefulLocalProxyFactory) factory).createProxy(ctx.getId());
         }
      }
      throw new IllegalStateException("Unable to create proxy for getBusinessObject as a proxy factory was not found");
   
public org.jboss.ejb3.cache.StatefulCachegetCache()

      return cache;
   
protected java.lang.Class[]getHandledCallbacks()

      return new Class[]
              {PostConstruct.class, PreDestroy.class, PostActivate.class,
                      PrePassivate.class};
   
protected java.lang.Object[]getInitParameters(java.lang.reflect.Method method, java.lang.Class[] initParameterTypes, java.lang.Object[] initParameterValues)

      if (method.getParameterTypes().length == initParameterTypes.length)
      {
         for (int i = 0; i < initParameterTypes.length; ++i)
         {
            Class formal = method.getParameterTypes()[i];
            Class actual = initParameterTypes[i];
            if (!isMethodInvocationConvertible(formal, actual == null ? null
                    : actual))
               return null;
         }
         return initParameterValues;
      }
      return null;
   
public javax.ejb.TimerServicegetTimerService()

      throw new UnsupportedOperationException("stateful bean doesn't support TimerService (EJB3 18.2#2)");
   
public javax.ejb.TimerServicegetTimerService(java.lang.Object pKey)

      return getTimerService();
   
private java.lang.ObjectinvokeEJBLocalObjectMethod(java.lang.Object id, org.jboss.aop.MethodInfo info, java.lang.Object[] args)

      Method unadvisedMethod = info.getUnadvisedMethod();
      if (unadvisedMethod.getName().equals("remove"))
      {
         destroySession(id);

         return null;
      }
      else if (unadvisedMethod.getName().equals("getEJBLocalHome"))
      {
         Object bean = getCache().get(id).getInstance();

         return bean;
      }
      else if (unadvisedMethod.getName().equals("getPrimaryKey"))
      {
         return id;
      }
      else if (unadvisedMethod.getName().equals("isIdentical"))
      {
         EJBObject bean = (EJBObject) args[0];

         Object primaryKey = bean.getPrimaryKey();

         boolean isIdentical = id.equals(primaryKey);

         return isIdentical;
      }
      else
      {
         return null;
      }
   
protected org.jboss.aop.joinpoint.InvocationResponseinvokeEJBObjectMethod(org.jboss.aop.MethodInfo info, StatefulRemoteInvocation statefulInvocation)

      Method unadvisedMethod = info.getUnadvisedMethod();
      if (unadvisedMethod.getName().equals("getHandle"))
      {
         StatefulContainerInvocation newStatefulInvocation = buildInvocation(
                 info, statefulInvocation);

         StatefulHandleImpl handle = new StatefulHandleImpl();
         handle.id = newStatefulInvocation.getId();
         RemoteBinding remoteBinding = (RemoteBinding) resolveAnnotation(RemoteBinding.class);
         if (remoteBinding != null)
            handle.jndiName = remoteBinding.jndiBinding();
         InvocationResponse response = marshallResponse(statefulInvocation, handle, null);
         return response;
      }
      else if (unadvisedMethod.getName().equals("remove"))
      {
         destroySession(statefulInvocation.getId());

         InvocationResponse response = new InvocationResponse(null);
         return response;
      }
      else if (unadvisedMethod.getName().equals("getEJBHome"))
      {
         HomeHandleImpl homeHandle = null;

         RemoteBinding remoteBindingAnnotation = (RemoteBinding) resolveAnnotation(RemoteBinding.class);
         if (remoteBindingAnnotation != null)
            homeHandle = new HomeHandleImpl(ProxyFactoryHelper.getHomeJndiName(this));

         EJBHome ejbHome = homeHandle.getEJBHome();

         InvocationResponse response = marshallResponse(statefulInvocation, ejbHome, null);
         return response;
      }
      else if (unadvisedMethod.getName().equals("getPrimaryKey"))
      {
         Object id = statefulInvocation.getId();

         InvocationResponse response = marshallResponse(statefulInvocation, id, null);
         return response;
      }
      else if (unadvisedMethod.getName().equals("isIdentical"))
      {
         Object id = statefulInvocation.getId();
         EJBObject bean = (EJBObject) statefulInvocation.getArguments()[0];

         Object primaryKey = bean.getPrimaryKey();

         boolean isIdentical = id.equals(primaryKey);

         InvocationResponse response = marshallResponse(statefulInvocation, isIdentical, null);
         return response;
      }
      else
      {
         return null;
      }
   
protected org.jboss.aop.joinpoint.InvocationResponseinvokeHomeMethod(org.jboss.aop.MethodInfo info, StatefulRemoteInvocation statefulInvocation)

      Method unadvisedMethod = info.getUnadvisedMethod();
      if (unadvisedMethod.getName().equals("create"))
      {
         Class[] initParameterTypes =
                 {};
         Object[] initParameterValues =
                 {};
         if (unadvisedMethod.getParameterTypes().length > 0)
         {
            initParameterTypes = unadvisedMethod.getParameterTypes();
            initParameterValues = statefulInvocation.getArguments();
         }

         StatefulContainerInvocation newStatefulInvocation = buildNewInvocation(
                 info, statefulInvocation, initParameterTypes,
                 initParameterValues);

         Object proxy = createRemoteProxy(newStatefulInvocation.getId());

         InvocationResponse response = marshallResponse(statefulInvocation, proxy, newStatefulInvocation.getResponseContextInfo());
         if (newStatefulInvocation.getId() != null)
            response.addAttachment(StatefulConstants.NEW_ID,
                    newStatefulInvocation.getId());
         return response;
      }
      else if (unadvisedMethod.getName().equals("remove"))
      {
         StatefulHandleImpl handle = (StatefulHandleImpl) statefulInvocation
                 .getArguments()[0];

         destroySession(handle.id);

         InvocationResponse response = new InvocationResponse(null);
         response.setContextInfo(statefulInvocation.getResponseContextInfo());
         return response;
      }
      else if (unadvisedMethod.getName().equals("getEJBMetaData"))
      {
         Class remote = null;
         Class home = null;
         Class pkClass = Object.class;
         HomeHandleImpl homeHandle = null;

         Remote remoteAnnotation = (Remote) resolveAnnotation(Remote.class);
         if (remoteAnnotation != null)
            remote = remoteAnnotation.value()[0];
         RemoteHome homeAnnotation = (RemoteHome) resolveAnnotation(RemoteHome.class);
         if (homeAnnotation != null)
            home = homeAnnotation.value();
         RemoteBinding remoteBindingAnnotation = (RemoteBinding) resolveAnnotation(RemoteBinding.class);
         if (remoteBindingAnnotation != null)
            homeHandle = new HomeHandleImpl(remoteBindingAnnotation
                    .jndiBinding());

         EJBMetaDataImpl metadata = new EJBMetaDataImpl(remote, home, pkClass,
                 true, false, homeHandle);

         InvocationResponse response = marshallResponse(statefulInvocation, metadata, null);
         return response;
      }
      else if (unadvisedMethod.getName().equals("getHomeHandle"))
      {
         HomeHandleImpl homeHandle = null;

         RemoteBinding remoteBindingAnnotation = (RemoteBinding) resolveAnnotation(RemoteBinding.class);
         if (remoteBindingAnnotation != null)
            homeHandle = new HomeHandleImpl(remoteBindingAnnotation
                    .jndiBinding());


         InvocationResponse response = marshallResponse(statefulInvocation, homeHandle, null);
         return response;
      }
      else
      {
         return null;
      }
   
public voidinvokeInit(java.lang.Object bean)

      try
      {
         Method[] methods = bean.getClass().getDeclaredMethods();

         for (int i = 0; i < methods.length; i++)
         {
            if (methods[i].getParameterTypes().length == 0)
            {
               if ((methods[i].getAnnotation(Init.class) != null)
                       || (resolveAnnotation(methods[i], Init.class) != null))
               {
                  methods[i].invoke(bean, new Object[0]);
               }
            }
         }
      }
      catch (Exception e)
      {
         throw new RuntimeException(e);
      }
   
public voidinvokeInit(java.lang.Object bean, java.lang.Class[] initParameterTypes, java.lang.Object[] initParameterValues)

      try
      {
         Method[] methods = bean.getClass().getDeclaredMethods();

         for (int i = 0; i < methods.length; i++)
         {
            if ((methods[i].getAnnotation(Init.class) != null)
                    || (resolveAnnotation(methods[i], Init.class) != null))
            {
               Object[] parameters = getInitParameters(methods[i],
                       initParameterTypes, initParameterValues);

               if (parameters != null)
                  methods[i].invoke(bean, parameters);
            }
         }
      }
      catch (Exception e)
      {
         throw new RuntimeException(e);
      }
   
private java.lang.ObjectinvokeLocalHomeMethod(org.jboss.aop.MethodInfo info, java.lang.Object[] args)

      Method unadvisedMethod = info.getUnadvisedMethod();
      if (unadvisedMethod.getName().equals("create"))
      {
         Class[] initParameterTypes =
                 {};
         Object[] initParameterValues =
                 {};
         if (unadvisedMethod.getParameterTypes().length > 0)
         {
            initParameterTypes = unadvisedMethod.getParameterTypes();
            initParameterValues = args;
         }

         LocalBinding binding = (LocalBinding) resolveAnnotation(LocalBinding.class);

         StatefulLocalProxyFactory factory = new StatefulLocalProxyFactory();
         factory.setContainer(this);
         factory.init();

         Object proxy = factory.createProxy(initParameterTypes,
                 initParameterValues);

         return proxy;
      }
      else if (unadvisedMethod.getName().equals("remove"))
      {
         StatefulHandleImpl handle = (StatefulHandleImpl) args[0];

         destroySession(handle.id);

         return null;
      }
      else
      {
         return null;
      }
   
public voidinvokePostActivate(org.jboss.ejb3.BeanContext beanContext)

      for (Injector injector : injectors)
      {
         if (injector instanceof JndiFieldInjector)
         {
            Field field = ((JndiFieldInjector) injector).getField();
            if (field.isAnnotationPresent(javax.ejb.EJB.class))
            {
               continue; // skip nested EJB injection since the local proxy will be (de)serialized correctly
            }
            injector.inject(beanContext);
         }
      }
      callbackHandler.postActivate(beanContext);
   
public voidinvokePrePassivate(org.jboss.ejb3.BeanContext beanContext)

      callbackHandler.prePassivate(beanContext);
   
private static booleanisMethodInvocationConvertible(java.lang.Class formal, java.lang.Class actual)
Determines whether a type represented by a class object is convertible to another type represented by a class object using a method invocation conversion, treating object types of primitive types as if they were primitive types (that is, a Boolean actual parameter type matches boolean primitive formal type). This behavior is because this method is used to determine applicable methods for an actual parameter list, and primitive types are represented by their object duals in reflective method calls.

param
formal the formal parameter type to which the actual parameter type should be convertible
param
actual the actual parameter type.
return
true if either formal type is assignable from actual type, or formal is a primitive type and actual is its corresponding object type or an object type of a primitive type that can be converted to the formal type.

      /*
       * if it's a null, it means the arg was null
       */
      if (actual == null && !formal.isPrimitive())
      {
         return true;
      }
      /*
       * Check for identity or widening reference conversion
       */
      if (actual != null && formal.isAssignableFrom(actual))
      {
         return true;
      }
      /*
       * Check for boxing with widening primitive conversion. Note that actual
       * parameters are never primitives.
       */
      if (formal.isPrimitive())
      {
         if (formal == Boolean.TYPE && actual == Boolean.class)
            return true;
         if (formal == Character.TYPE && actual == Character.class)
            return true;
         if (formal == Byte.TYPE && actual == Byte.class)
            return true;
         if (formal == Short.TYPE
                 && (actual == Short.class || actual == Byte.class))
            return true;
         if (formal == Integer.TYPE
                 && (actual == Integer.class || actual == Short.class || actual == Byte.class))
            return true;
         if (formal == Long.TYPE
                 && (actual == Long.class || actual == Integer.class
                 || actual == Short.class || actual == Byte.class))
            return true;
         if (formal == Float.TYPE
                 && (actual == Float.class || actual == Long.class
                 || actual == Integer.class || actual == Short.class || actual == Byte.class))
            return true;
         if (formal == Double.TYPE
                 && (actual == Double.class || actual == Float.class
                 || actual == Long.class || actual == Integer.class
                 || actual == Short.class || actual == Byte.class))
            return true;
      }
      return false;
   
public java.lang.ObjectlocalHomeInvoke(java.lang.reflect.Method method, java.lang.Object[] args)
Performs a synchronous or asynchronous local invocation

      ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
      pushEnc();
      try
      {
         long hash = MethodHashing.calculateHash(method);
         MethodInfo info = (MethodInfo) methodInterceptors.get(hash);
         if (info == null)
         {
            throw new RuntimeException(
                    "Could not resolve beanClass method from proxy call: "
                            + method.toString());
         }
         return invokeLocalHomeMethod(info, args);
      }
      finally
      {
         Thread.currentThread().setContextClassLoader(oldLoader);
         popEnc();
      }
   
public java.lang.ObjectlocalInvoke(java.lang.Object id, java.lang.reflect.Method method, java.lang.Object[] args)
Performs a synchronous local invocation

      return localInvoke(id, method, args, null);
   
public java.lang.ObjectlocalInvoke(java.lang.Object id, java.lang.reflect.Method method, java.lang.Object[] args, org.jboss.aspects.asynch.FutureHolder provider)
Performs a synchronous or asynchronous local invocation

param
provider If null a synchronous invocation, otherwise an asynchronous

      long start = System.currentTimeMillis();

      ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
      pushEnc();
      try
      {
         long hash = MethodHashing.calculateHash(method);
         MethodInfo info = (MethodInfo) methodInterceptors.get(hash);
         if (info == null)
         {
            throw new RuntimeException(
                  "Could not resolve beanClass method from proxy call: "
                  + method.toString());
         }
      
         Method unadvisedMethod = info.getUnadvisedMethod();
      
         try
         {
            invokeStats.callIn();
      
            if (unadvisedMethod != null && isHomeMethod(unadvisedMethod))
            {
               return invokeLocalHomeMethod(info, args);
            }
            else if (unadvisedMethod != null
                  && isEJBObjectMethod(unadvisedMethod))
            {
               return invokeEJBLocalObjectMethod(id, info, args);
            }
            
            StatefulContainerInvocation nextInvocation = new StatefulContainerInvocation(info, id);
            nextInvocation.setAdvisor(this);
            nextInvocation.setArguments(args);
            
            ProxyUtils.addLocalAsynchronousInfo(nextInvocation, provider);
            
            invokedMethod.push(new InvokedMethod(true, method));
            return nextInvocation.invokeNext();
         }
         finally
         {
            if (unadvisedMethod != null)
            {
               long end = System.currentTimeMillis();
               long elapsed = end - start;
               invokeStats.updateStats(unadvisedMethod, elapsed);
            }
         
            invokeStats.callOut();
            
            invokedMethod.pop();
         }
      }
      finally
      {
         Thread.currentThread().setContextClassLoader(oldLoader);
         popEnc();
      }
   
protected voidremoveHandle(javax.ejb.Handle arg)

      /*
      StatefulHandleImpl handle = (StatefulHandleImpl) arg;

      destroySession(handle.id);
      */
      arg.getEJBObject().remove();
   
public voidstart()

      try
      {
         super.start();
         Cache cacheConfig = (Cache) resolveAnnotation(Cache.class);
         cache = (StatefulCache) cacheConfig.value().newInstance();
         cache.initialize(this);
         cache.start();
      }
      catch (Exception e)
      {
         try
         {
            stop();
         }
         catch (Exception ignore)
         {
            log.debug("Failed to cleanup after start() failure", ignore);
         }
         throw e;
      }

   
public voidstop()

      if (cache != null) cache.stop();
      super.stop();