[jboss-cvs] JBossAS SVN: r85852 - in projects/ejb3/trunk: core/src/main/java/org/jboss/ejb3/stateful and 9 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Sun Mar 15 03:57:26 EDT 2009


Author: ALRubinger
Date: 2009-03-15 03:57:25 -0400 (Sun, 15 Mar 2009)
New Revision: 85852

Added:
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1773/
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1773/unit/
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1773/unit/RemoveRequestFromSessionProxyUnitTestCase.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/service/ServiceLocal.java
   projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/session/unit/SessionProxyContractTestCase.java
Modified:
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/session/SessionContainer.java
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/stateful/StatefulContainer.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/service/ServiceBean.java
   projects/ejb3/trunk/proxy-impl/src/main/java/org/jboss/ejb3/proxy/impl/handler/session/SessionProxyInvocationHandlerBase.java
   projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/common/container/ServiceContainer.java
   projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/common/container/StatefulContainer.java
   projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/common/container/StatelessContainer.java
   projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/session/unit/ProxyServiceTestCase.java
   projects/ejb3/trunk/proxy-spi/src/main/java/org/jboss/ejb3/proxy/spi/container/InvokableContext.java
   projects/ejb3/trunk/proxy-spi/src/main/java/org/jboss/ejb3/proxy/spi/intf/SessionProxy.java
Log:
[EJBTHREE-1773] Support proxy requests to remove a bean target

Modified: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/session/SessionContainer.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/session/SessionContainer.java	2009-03-15 06:16:20 UTC (rev 85851)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/session/SessionContainer.java	2009-03-15 07:57:25 UTC (rev 85852)
@@ -81,7 +81,7 @@
 {
    @SuppressWarnings("unused")
    private static final Logger log = Logger.getLogger(SessionContainer.class);
-   
+
    // ------------------------------------------------------------------------------||
    // Instance Members -------------------------------------------------------------||
    // ------------------------------------------------------------------------------||
@@ -89,8 +89,9 @@
    private JndiSessionRegistrarBase jndiRegistrar;
 
    protected ProxyDeployer proxyDeployer;
+
    private Map<String, HATarget> clusterFamilies;
-   
+
    /**
     * Returns a remote binding for this container
     * 
@@ -107,46 +108,50 @@
          binding = bindings.value()[0];
       else
          binding = getAnnotation(RemoteBinding.class);
-      
+
       return binding;
    }
 
    public SessionContainer(ClassLoader cl, String beanClassName, String ejbName, Domain domain,
-                           Hashtable ctxProperties, Ejb3Deployment deployment, JBossSessionBeanMetaData beanMetaData) throws ClassNotFoundException
+         Hashtable ctxProperties, Ejb3Deployment deployment, JBossSessionBeanMetaData beanMetaData)
+         throws ClassNotFoundException
    {
-      super(Ejb3Module.BASE_EJB3_JMX_NAME + ",name=" + ejbName, domain, cl, beanClassName, ejbName, ctxProperties, deployment, beanMetaData);
+      super(Ejb3Module.BASE_EJB3_JMX_NAME + ",name=" + ejbName, domain, cl, beanClassName, ejbName, ctxProperties,
+            deployment, beanMetaData);
       proxyDeployer = new ProxyDeployer(this);
    }
 
    protected SessionProxyFactory getProxyFactory(LocalBinding binding)
    {
-      assert binding!=null : LocalBinding.class.getSimpleName() + " must be specified";
-      
+      assert binding != null : LocalBinding.class.getSimpleName() + " must be specified";
+
       // Find the jndiName
       String jndiName = this.getMetaData().getLocalJndiName();
-      if(binding!=null)
+      if (binding != null)
       {
          jndiName = binding.jndiBinding();
       }
-      
+
       // Get the Registry name
-      String proxyFactoryRegistryBindName = this.getJndiRegistrar().getProxyFactoryRegistryKey(jndiName, this.getMetaData(), true);
-      
+      String proxyFactoryRegistryBindName = this.getJndiRegistrar().getProxyFactoryRegistryKey(jndiName,
+            this.getMetaData(), true);
+
       // Return
       return this.getProxyFactory(proxyFactoryRegistryBindName);
    }
-   
+
    protected SessionProxyFactory getProxyFactory(RemoteBinding binding)
    {
-      assert binding!=null : RemoteBinding.class.getSimpleName() + " must be specified";
-      
+      assert binding != null : RemoteBinding.class.getSimpleName() + " must be specified";
+
       // Get the Registry name
-      String proxyFactoryRegistryBindName = this.getJndiRegistrar().getProxyFactoryRegistryKey(binding.jndiBinding(), this.getMetaData(), true);
-      
+      String proxyFactoryRegistryBindName = this.getJndiRegistrar().getProxyFactoryRegistryKey(binding.jndiBinding(),
+            this.getMetaData(), true);
+
       // Return
       return this.getProxyFactory(proxyFactoryRegistryBindName);
    }
-   
+
    /**
     * Obtains the proxy factory bound at the specified registry name
     * 
@@ -162,7 +167,7 @@
       // Return
       return factory;
    }
-   
+
    /**
     * Entry point for remoting-based invocations via InvokableContextClassProxyHack
     */
@@ -173,7 +178,7 @@
       // TODO: resolve this cast using generics on EJBContainer
       return (JBossSessionBeanMetaData) getXml();
    }
-   
+
    @Override
    public void instantiated()
    {
@@ -189,10 +194,10 @@
       List<Class<?>> list = new ArrayList<Class<?>>();
       list.addAll(Arrays.asList(ProxyFactoryHelper.getLocalBusinessInterfaces(this)));
       list.addAll(Arrays.asList(ProxyFactoryHelper.getRemoteBusinessInterfaces(this)));
-      
+
       return list;
    }
-   
+
    protected void lockedStart() throws Exception
    {
       super.lockedStart();
@@ -214,7 +219,7 @@
                + " was found; byassing binding of Proxies to " + this.getName() + " in Global JNDI.");
       }
    }
-   
+
    /**
     * Registers this Container with Remoting / AOP Dispatcher
     */
@@ -222,10 +227,10 @@
    {
       String registrationName = this.getObjectName().getCanonicalName();
       ClassProxy classProxy = new InvokableContextClassProxyHack(this);
-      
+
       // So that Remoting layer can reference this container easily.
       Dispatcher.singleton.registerTarget(registrationName, classProxy);
-      
+
       // Log
       log.debug("Registered " + this + " with " + Dispatcher.class.getName() + " via "
             + InvokableContextClassProxyHack.class.getSimpleName() + " at key " + registrationName);
@@ -240,10 +245,11 @@
     */
    public Map<String, HATarget> getClusterFamilies()
    {
-      if(clusterFamilies == null)
-      {      
+      if (clusterFamilies == null)
+      {
          Ejb3Registrar registrar = Ejb3RegistrarLocator.locateRegistrar();
-         ProxyClusteringRegistry registry = (ProxyClusteringRegistry) registrar.lookup(ClusteredObjectStoreBindings.CLUSTERED_OBJECTSTORE_BEAN_NAME_PROXY_CLUSTERING_REGISTRY);
+         ProxyClusteringRegistry registry = (ProxyClusteringRegistry) registrar
+               .lookup(ClusteredObjectStoreBindings.CLUSTERED_OBJECTSTORE_BEAN_NAME_PROXY_CLUSTERING_REGISTRY);
          clusterFamilies = registry.getHATargets(this.getObjectName().getCanonicalName());
       }
       return clusterFamilies;
@@ -260,7 +266,7 @@
       {
          log.debug("Dispatcher unregister target failed", ignore);
       }
-      
+
       // Deregister with Remoting
       Dispatcher.singleton.unregisterTarget(this.getName());
 
@@ -270,7 +276,7 @@
       {
          jndiRegistrar.unbindEjb(this.getInitialContext(), this.getMetaData());
       }
-      
+
       super.lockedStop();
    }
 
@@ -284,11 +290,11 @@
          if (home != null)
          {
             Method[] declaredMethods = home.value().getMethods();
-            for(Method declaredMethod : declaredMethods)
+            for (Method declaredMethod : declaredMethods)
                virtualMethods.add(declaredMethod);
 
             declaredMethods = javax.ejb.EJBObject.class.getMethods();
-            for(Method declaredMethod : declaredMethods)
+            for (Method declaredMethod : declaredMethods)
                virtualMethods.add(declaredMethod);
          }
 
@@ -296,11 +302,11 @@
          if (localHome != null)
          {
             Method[] declaredMethods = localHome.value().getMethods();
-            for(Method declaredMethod : declaredMethods)
+            for (Method declaredMethod : declaredMethods)
                virtualMethods.add(declaredMethod);
 
             declaredMethods = javax.ejb.EJBLocalObject.class.getMethods();
-            for(Method declaredMethod : declaredMethods)
+            for (Method declaredMethod : declaredMethods)
                virtualMethods.add(declaredMethod);
          }
       }
@@ -311,12 +317,11 @@
       }
       return virtualMethods;
    }
-   
+
    // --------------------------------------------------------------------------------||
    // Contracts ----------------------------------------------------------------------||
    // --------------------------------------------------------------------------------||
 
-
    /**
     * Returns the name under which the JNDI Registrar for this container is bound
     * 
@@ -374,153 +379,152 @@
    {
       this.jndiRegistrar = jndiRegistrar;
    }
-   
-   
-//   /**
-//    * Obtains a List of all methods handled by the bean class
-//    * 
-//    * @return The methods handled by the bean class directly
-//    */
-//   @Override
-//   //FIXME: Should be adapted to use metadata view from metadata bridge
-//   // such that *-aop.xml annotations may be included
-//   public List<Method> getVirtualMethods()
-//   {
-//      // Initialize
-//      List<Method> virtualMethods = new ArrayList<Method>();
-//
-//      // Obtain Metadata
-//      JBossSessionBeanMetaData smd = this.getMetaData();
-//
-//      // Obtain CL
-//      ClassLoader cl = this.getClassloader();
-//
-//      /*
-//       * Business Remotes
-//       */
-//
-//      // Obtain all specified business remotes
-//      BusinessRemotesMetaData businessRemotes = smd.getBusinessRemotes();
-//      if (businessRemotes != null)
-//      {
-//         // For each business remote
-//         for (String businessRemote : businessRemotes)
-//         {
-//            // Load the Class
-//            Class<?> businessRemoteClass = null;
-//            try
-//            {
-//               businessRemoteClass = Class.forName(businessRemote, true, cl);
-//            }
-//            catch (ClassNotFoundException e)
-//            {
-//               throw new RuntimeException("Could not find specified business remote class: " + businessRemote, e);
-//            }
-//
-//            // Obtain all methods declared by the class
-//            Method[] declaredMethods = businessRemoteClass.getMethods();
-//
-//            // Add each method
-//            for (Method declaredMethod : declaredMethods)
-//            {
-//               virtualMethods.add(declaredMethod);
-//            }
-//         }
-//      }
-//
-//      /*
-//       * Business Locals
-//       */
-//
-//      // Obtain all specified business locals
-//      BusinessLocalsMetaData businessLocals = smd.getBusinessLocals();
-//      if (businessLocals != null)
-//      {
-//         // For each business local
-//         for (String businessLocal : businessLocals)
-//         {
-//            // Load the Class
-//            Class<?> businessLocalClass = null;
-//            try
-//            {
-//               businessLocalClass = Class.forName(businessLocal, true, cl);
-//            }
-//            catch (ClassNotFoundException e)
-//            {
-//               throw new RuntimeException("Could not find specified business local class: " + businessLocal, e);
-//            }
-//
-//            // Obtain all methods declared by the class
-//            Method[] declaredMethods = businessLocalClass.getMethods();
-//
-//            // Add each method
-//            for (Method declaredMethod : declaredMethods)
-//            {
-//               virtualMethods.add(declaredMethod);
-//            }
-//         }
-//      }
-//
-//      // Remote Home
-//      String remoteHomeClassName = smd.getHome();
-//      if (remoteHomeClassName != null)
-//      {
-//         Class<?> remoteHomeClass = null;
-//         try
-//         {
-//            remoteHomeClass = Class.forName(remoteHomeClassName, true, cl);
-//         }
-//         catch (ClassNotFoundException e)
-//         {
-//            throw new RuntimeException("Could not find specified Remote Home Class: " + remoteHomeClassName, e);
-//         }
-//         if (remoteHomeClass != null)
-//         {
-//            Method[] declaredMethods = remoteHomeClass.getMethods();
-//            for (Method declaredMethod : declaredMethods)
-//               virtualMethods.add(declaredMethod);
-//
-//            declaredMethods = javax.ejb.EJBObject.class.getMethods();
-//            for (Method declaredMethod : declaredMethods)
-//               virtualMethods.add(declaredMethod);
-//         }
-//      }
-//
-//      // Local Home
-//      String localHomeClassName = smd.getLocalHome();
-//      if (localHomeClassName != null)
-//      {
-//         Class<?> localHomeClass = null;
-//         try
-//         {
-//            localHomeClass = Class.forName(localHomeClassName, true, cl);
-//         }
-//         catch (ClassNotFoundException e)
-//         {
-//            throw new RuntimeException("Could not find specified Local Home Class: " + localHomeClass, e);
-//         }
-//         if (localHomeClass != null)
-//         {
-//            Method[] declaredMethods = localHomeClass.getMethods();
-//            for (Method declaredMethod : declaredMethods)
-//               virtualMethods.add(declaredMethod);
-//
-//            declaredMethods = javax.ejb.EJBLocalObject.class.getMethods();
-//            for (Method declaredMethod : declaredMethods)
-//               virtualMethods.add(declaredMethod);
-//         }
-//      }
-//      
-//      log.debug("Found virtual methods: ");
-//      for(Method m : virtualMethods)
-//      {
-//         log.debug("\t" + m + " - " + MethodHashing.calculateHash(m));
-//      }
-//      
-//
-//      return virtualMethods;
-//   }
-   
+
+   //   /**
+   //    * Obtains a List of all methods handled by the bean class
+   //    * 
+   //    * @return The methods handled by the bean class directly
+   //    */
+   //   @Override
+   //   //FIXME: Should be adapted to use metadata view from metadata bridge
+   //   // such that *-aop.xml annotations may be included
+   //   public List<Method> getVirtualMethods()
+   //   {
+   //      // Initialize
+   //      List<Method> virtualMethods = new ArrayList<Method>();
+   //
+   //      // Obtain Metadata
+   //      JBossSessionBeanMetaData smd = this.getMetaData();
+   //
+   //      // Obtain CL
+   //      ClassLoader cl = this.getClassloader();
+   //
+   //      /*
+   //       * Business Remotes
+   //       */
+   //
+   //      // Obtain all specified business remotes
+   //      BusinessRemotesMetaData businessRemotes = smd.getBusinessRemotes();
+   //      if (businessRemotes != null)
+   //      {
+   //         // For each business remote
+   //         for (String businessRemote : businessRemotes)
+   //         {
+   //            // Load the Class
+   //            Class<?> businessRemoteClass = null;
+   //            try
+   //            {
+   //               businessRemoteClass = Class.forName(businessRemote, true, cl);
+   //            }
+   //            catch (ClassNotFoundException e)
+   //            {
+   //               throw new RuntimeException("Could not find specified business remote class: " + businessRemote, e);
+   //            }
+   //
+   //            // Obtain all methods declared by the class
+   //            Method[] declaredMethods = businessRemoteClass.getMethods();
+   //
+   //            // Add each method
+   //            for (Method declaredMethod : declaredMethods)
+   //            {
+   //               virtualMethods.add(declaredMethod);
+   //            }
+   //         }
+   //      }
+   //
+   //      /*
+   //       * Business Locals
+   //       */
+   //
+   //      // Obtain all specified business locals
+   //      BusinessLocalsMetaData businessLocals = smd.getBusinessLocals();
+   //      if (businessLocals != null)
+   //      {
+   //         // For each business local
+   //         for (String businessLocal : businessLocals)
+   //         {
+   //            // Load the Class
+   //            Class<?> businessLocalClass = null;
+   //            try
+   //            {
+   //               businessLocalClass = Class.forName(businessLocal, true, cl);
+   //            }
+   //            catch (ClassNotFoundException e)
+   //            {
+   //               throw new RuntimeException("Could not find specified business local class: " + businessLocal, e);
+   //            }
+   //
+   //            // Obtain all methods declared by the class
+   //            Method[] declaredMethods = businessLocalClass.getMethods();
+   //
+   //            // Add each method
+   //            for (Method declaredMethod : declaredMethods)
+   //            {
+   //               virtualMethods.add(declaredMethod);
+   //            }
+   //         }
+   //      }
+   //
+   //      // Remote Home
+   //      String remoteHomeClassName = smd.getHome();
+   //      if (remoteHomeClassName != null)
+   //      {
+   //         Class<?> remoteHomeClass = null;
+   //         try
+   //         {
+   //            remoteHomeClass = Class.forName(remoteHomeClassName, true, cl);
+   //         }
+   //         catch (ClassNotFoundException e)
+   //         {
+   //            throw new RuntimeException("Could not find specified Remote Home Class: " + remoteHomeClassName, e);
+   //         }
+   //         if (remoteHomeClass != null)
+   //         {
+   //            Method[] declaredMethods = remoteHomeClass.getMethods();
+   //            for (Method declaredMethod : declaredMethods)
+   //               virtualMethods.add(declaredMethod);
+   //
+   //            declaredMethods = javax.ejb.EJBObject.class.getMethods();
+   //            for (Method declaredMethod : declaredMethods)
+   //               virtualMethods.add(declaredMethod);
+   //         }
+   //      }
+   //
+   //      // Local Home
+   //      String localHomeClassName = smd.getLocalHome();
+   //      if (localHomeClassName != null)
+   //      {
+   //         Class<?> localHomeClass = null;
+   //         try
+   //         {
+   //            localHomeClass = Class.forName(localHomeClassName, true, cl);
+   //         }
+   //         catch (ClassNotFoundException e)
+   //         {
+   //            throw new RuntimeException("Could not find specified Local Home Class: " + localHomeClass, e);
+   //         }
+   //         if (localHomeClass != null)
+   //         {
+   //            Method[] declaredMethods = localHomeClass.getMethods();
+   //            for (Method declaredMethod : declaredMethods)
+   //               virtualMethods.add(declaredMethod);
+   //
+   //            declaredMethods = javax.ejb.EJBLocalObject.class.getMethods();
+   //            for (Method declaredMethod : declaredMethods)
+   //               virtualMethods.add(declaredMethod);
+   //         }
+   //      }
+   //      
+   //      log.debug("Found virtual methods: ");
+   //      for(Method m : virtualMethods)
+   //      {
+   //         log.debug("\t" + m + " - " + MethodHashing.calculateHash(m));
+   //      }
+   //      
+   //
+   //      return virtualMethods;
+   //   }
+
    /*
    protected void createMethodMap()
    {
@@ -570,9 +574,11 @@
    }
    */
 
-   public static InvocationResponse marshallException(Invocation invocation, Throwable exception, Map responseContext) throws Throwable
+   public static InvocationResponse marshallException(Invocation invocation, Throwable exception, Map responseContext)
+         throws Throwable
    {
-      if (invocation.getMetaData(IsLocalInterceptor.IS_LOCAL,IsLocalInterceptor.IS_LOCAL) == null) throw exception;
+      if (invocation.getMetaData(IsLocalInterceptor.IS_LOCAL, IsLocalInterceptor.IS_LOCAL) == null)
+         throw exception;
 
       InvocationResponse response = new InvocationResponse();
       response.setContextInfo(responseContext);
@@ -583,7 +589,7 @@
    }
 
    public static InvocationResponse marshallResponse(Invocation invocation, Object rtn, Map responseContext)
-           throws java.io.IOException
+         throws java.io.IOException
    {
       InvocationResponse response;
       // marshall return value
@@ -598,7 +604,7 @@
       response.setContextInfo(responseContext);
       return response;
    }
-   
+
    /**
     * Invoke a method on the virtual EJB bean. The method must be one of the methods defined in one
     * of the business interfaces (or home interface) of the bean.
@@ -623,22 +629,19 @@
          MethodInfo info = getAdvisor().getMethodInfo(hash);
          if (info == null)
          {
-            throw new RuntimeException(
-                    "Could not resolve beanClass method from proxy call: "
-                            + method.toString());
+            throw new RuntimeException("Could not resolve beanClass method from proxy call: " + method.toString());
          }
 
-         
          // Handled now by SessionSpecContainer
          //Method unadvisedMethod = info.getUnadvisedMethod();
-//         if (unadvisedMethod != null && isHomeMethod(unadvisedMethod))
-//         {
-//            return invokeHomeMethod(factory, info, args);
-//         }
-//         else if (unadvisedMethod != null && isEJBObjectMethod(unadvisedMethod))
-//         {
-//            return invokeEJBObjectMethod(factory, id, info, args);
-//         }
+         //         if (unadvisedMethod != null && isHomeMethod(unadvisedMethod))
+         //         {
+         //            return invokeHomeMethod(factory, info, args);
+         //         }
+         //         else if (unadvisedMethod != null && isEJBObjectMethod(unadvisedMethod))
+         //         {
+         //            return invokeEJBObjectMethod(factory, id, info, args);
+         //         }
 
          // FIXME: Ahem, stateful container invocation works on all.... (violating contract though)
          StatefulContainerInvocation nextInvocation = new StatefulContainerInvocation(info, id);
@@ -646,7 +649,7 @@
          //EJBContainerInvocation nextInvocation = new StatefulContainerInvocation(info, id);
          nextInvocation.setAdvisor(getAdvisor());
          nextInvocation.setArguments(args);
-         
+
          // allow a container to supplement information into an invocation
          nextInvocation = populateInvocation(nextInvocation);
 
@@ -658,7 +661,7 @@
          popEnc();
       }
    }
-   
+
    /**
     * Create session to an EJB bean.
     * 
@@ -667,16 +670,18 @@
     * @return   the identifier of the session
     */
    abstract public Serializable createSession(Class<?> initParameterTypes[], Object initParameterValues[]);
-   
+
    abstract public Object localInvoke(Object id, Method method, Object[] args) throws Throwable;
-   
+
    abstract public Object localHomeInvoke(Method method, Object[] args) throws Throwable;
-   
+
    public Serializable createSession()
    {
-      return createSession(new Class<?>[]{}, new Object[]{});
+      return createSession(new Class<?>[]
+      {}, new Object[]
+      {});
    }
-   
+
    /**
     * Destroy a created session.
     * 
@@ -686,7 +691,7 @@
    {
       throw new RuntimeException("NYI");
    }
-   
+
    /**
     * Checks if this session bean binds to the given JNDI name.
     */
@@ -695,28 +700,28 @@
    {
       return proxyDeployer.hasJNDIBinding(jndiName);
    }
-   
+
    protected Object invokeEJBObjectMethod(Object id, MethodInfo info, Object args[]) throws Exception
    {
       Method unadvisedMethod = info.getUnadvisedMethod();
-      if(unadvisedMethod.getName().equals("getEJBHome"))
+      if (unadvisedMethod.getName().equals("getEJBHome"))
       {
          return this.getInitialContext().lookup(this.getMetaData().getHomeJndiName());
       }
-      if(unadvisedMethod.getName().equals("getPrimaryKey"))
+      if (unadvisedMethod.getName().equals("getPrimaryKey"))
       {
          return id;
       }
-      if(unadvisedMethod.getName().equals("isIdentical"))
+      if (unadvisedMethod.getName().equals("isIdentical"))
       {
          // object has no identity
-         if(id == null)
+         if (id == null)
             return false;
-         
+
          EJBObject bean = (EJBObject) args[0];
 
          Object primaryKey = bean.getPrimaryKey();
-         if(primaryKey == null)
+         if (primaryKey == null)
             return false;
 
          boolean isIdentical = id.equals(primaryKey);
@@ -729,7 +734,7 @@
          {
             destroySession(id);
          }
-         catch(NoSuchEJBException nsee)
+         catch (NoSuchEJBException nsee)
          {
             String invokingClassName = unadvisedMethod.getDeclaringClass().getName();
             Exception newException = (Exception) this.constructProperNoSuchEjbException(nsee, invokingClassName);
@@ -740,7 +745,7 @@
       }
       throw new RuntimeException("NYI");
    }
-   
+
    /**
     * Obtains the proper Exception to return to the caller in 
     * the event a "remove" call is made on a bean that doesn't exist.
@@ -751,7 +756,7 @@
     * @param invokingClassName
     * @return
     */
-   protected Throwable constructProperNoSuchEjbException(NoSuchEJBException original,String invokingClassName)
+   protected Throwable constructProperNoSuchEjbException(NoSuchEJBException original, String invokingClassName)
    {
       /*
        * EJB 3.0 Core Specification 14.3.9
@@ -763,11 +768,11 @@
        * (which is a subclass of java.rmi.RemoteException) to a remote client, 
        * or the javax.ejb.NoSuchObjectLocalException to a local client.
        */
-      
+
       // Initialize
       Throwable t = original;
       ClassLoader cl = this.getClassloader();
-      
+
       // Obtain the actual invoked class
       Class<?> actualInvokingClass = null;
       try
@@ -807,18 +812,34 @@
       // Return
       return t;
    }
-   
+
    /**
     * Allow a container sub class to supplement an invocation. Per default nothing to supplement.
     * 
     * @param invocation
     * @return
     */
-   protected StatefulContainerInvocation populateInvocation(
-         StatefulContainerInvocation invocation)
+   protected StatefulContainerInvocation populateInvocation(StatefulContainerInvocation invocation)
    {
       return invocation;
    }
-   
+
    abstract protected void removeHandle(Handle handle) throws Exception;
+
+   /**
+    * Requests of the container that the underlying target be removed.
+    * Most frequently used in SFSB, but not necessarily supported 
+    * by SLSB/Singleton/@Service Containers
+    * 
+    * @throws UnsupportedOperationException If the bean type 
+    * does not honor client requests to remove the target
+    * 
+    * @param target
+    * @throws UnsupportedOperationException
+    */
+   public void removeTarget(Object target) throws UnsupportedOperationException
+   {
+      throw new UnsupportedOperationException("EJB " + this.getName()
+            + " does not support removal requests of underlying bean targets");
+   }
 }

Modified: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/stateful/StatefulContainer.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/stateful/StatefulContainer.java	2009-03-15 06:16:20 UTC (rev 85851)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/stateful/StatefulContainer.java	2009-03-15 07:57:25 UTC (rev 85852)
@@ -1369,6 +1369,25 @@
       }
    }
    
+   /**
+    * Requests of the container that the underlying target be removed.
+    * Most frequently used in SFSB, but not necessarily supported 
+    * by SLSB/Singleton/@Service Containers
+    * 
+    * @throws UnsupportedOperationException If the bean type 
+    * does not honor client requests to remove the target
+    * 
+    * @param target
+    * @throws UnsupportedOperationException
+    */
+   @Override
+   public void removeTarget(Object target) throws UnsupportedOperationException
+   {
+      // Delegate to destroy
+      log.debug("Received request from client to destroy SFSB Session with ID: " + target);
+      this.destroySession(target);
+   }
+   
    protected void removeHandle(Handle arg) throws Exception
    {
       /*

Added: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1773/unit/RemoveRequestFromSessionProxyUnitTestCase.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1773/unit/RemoveRequestFromSessionProxyUnitTestCase.java	                        (rev 0)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1773/unit/RemoveRequestFromSessionProxyUnitTestCase.java	2009-03-15 07:57:25 UTC (rev 85852)
@@ -0,0 +1,246 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+  *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+  *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ejb3.core.test.ejbthree1773.unit;
+
+import javax.ejb.NoSuchEJBException;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import junit.framework.TestCase;
+
+import org.jboss.ejb3.core.test.common.AbstractEJB3TestCase;
+import org.jboss.ejb3.core.test.service.ServiceBean;
+import org.jboss.ejb3.core.test.stateful.StatefulBean;
+import org.jboss.ejb3.core.test.stateful.StatefulLocalBusiness;
+import org.jboss.ejb3.core.test.stateless.MyStatelessBean;
+import org.jboss.ejb3.proxy.spi.intf.SessionProxy;
+import org.jboss.ejb3.session.SessionContainer;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * RemoveRequestFromSessionProxyUnitTestCase
+ * 
+ * Test Cases to ensure requests from SessionProxy.removeTarget
+ * are handled accordingly by the Containers
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public class RemoveRequestFromSessionProxyUnitTestCase extends AbstractEJB3TestCase
+{
+   // --------------------------------------------------------------------------------||
+   // Class Members ------------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /*
+    * Bean Impl Classes
+    */
+
+   private static final Class<?> BEAN_IMPL_CLASS_SLSB = MyStatelessBean.class;
+
+   private static final Class<?> BEAN_IMPL_CLASS_SFSB = StatefulBean.class;
+
+   private static final Class<?> BEAN_IMPL_CLASS_SERVICE = ServiceBean.class;
+
+   /*
+    * Containers used
+    */
+
+   private static SessionContainer slsb;
+
+   private static SessionContainer sfsb;
+
+   private static SessionContainer service;
+
+   /*
+    * JNDI Context
+    */
+
+   private static Context namingContext;
+
+   // --------------------------------------------------------------------------------||
+   // Lifecycle Methods --------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /**
+    * Ensures SLSB SessionProxy.removeTarget requests are unsupported
+    */
+   @Test
+   public void testRemoveOnSlsb() throws Throwable
+   {
+      this.assertUnsupportedRemoveRequest(BEAN_IMPL_CLASS_SLSB);
+   }
+
+   /**
+    * Ensures @Service SessionProxy.removeTarget requests are unsupported
+    */
+   @Test
+   public void testRemoveOnService() throws Throwable
+   {
+      this.assertUnsupportedRemoveRequest(BEAN_IMPL_CLASS_SERVICE);
+   }
+
+   /**
+    * Ensures SFSB SessionProxy.removeTarget requests are honored
+    */
+   @Test
+   public void testRemoveOnSfsb() throws Throwable
+   {
+      // Initialized
+      boolean exceptionReceived = false;
+
+      // Lookup
+      SessionProxy proxy = this.lookupProxy(BEAN_IMPL_CLASS_SFSB);
+
+      // Cast
+      StatefulLocalBusiness statefulProxy = (StatefulLocalBusiness) proxy;
+
+      // Invoke
+      int firstCounter = statefulProxy.getNextCounter();
+      int nextCounter = statefulProxy.getNextCounter();
+      TestCase.assertTrue("SFSB Invocations not as expected", firstCounter == nextCounter - 1);
+
+      // Request Removal
+      proxy.removeTarget();
+
+      // Ensure gone
+      try
+      {
+         statefulProxy.getNextCounter();
+      }
+      catch (NoSuchEJBException nsejbe)
+      {
+         exceptionReceived = true;
+      }
+
+      // Test
+      TestCase.assertTrue("SFSB should have been removed", exceptionReceived);
+   }
+
+   // --------------------------------------------------------------------------------||
+   // Internal Helper Methods --------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /**
+    * Ensures that the Container for the specified bean impl class does not support
+    * removal requests from the proxy
+    */
+   private void assertUnsupportedRemoveRequest(Class<?> beanImplClass) throws Throwable
+   {
+      // Initialize
+      boolean gotExpectedException = false;
+
+      // Obtain Proxy
+      SessionProxy proxy = this.lookupProxy(beanImplClass);
+
+      // Request Removal
+      try
+      {
+         proxy.removeTarget();
+      }
+      catch (UnsupportedOperationException uoe)
+      {
+         gotExpectedException = true;
+      }
+
+      // Test
+      TestCase.assertTrue("Should not support removal requests", gotExpectedException);
+   }
+
+   /**
+    * Ensures that the Container for the specified bean impl class does not support
+    * removal requests from the proxy
+    */
+   private SessionProxy lookupProxy(Class<?> beanImplClass) throws Throwable
+   {
+      // Define JNDI Targets for Lookup
+      String jndiName = beanImplClass.getSimpleName() + "/" + "local";
+
+      // Obtain Proxy
+      SessionProxy proxy = (SessionProxy) namingContext.lookup(jndiName);
+
+      // Return
+      return proxy;
+   }
+
+   // --------------------------------------------------------------------------------||
+   // Lifecycle Methods --------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   @BeforeClass
+   public static void beforeClass() throws Exception
+   {
+      AbstractEJB3TestCase.beforeClass();
+
+      // Get the Naming Context
+      try
+      {
+         namingContext = new InitialContext();
+      }
+      catch (NamingException e)
+      {
+         throw new RuntimeException(e);
+      }
+
+      // Deploy the test EJBs
+      slsb = deploySessionEjb(BEAN_IMPL_CLASS_SLSB);
+      sfsb = deploySessionEjb(BEAN_IMPL_CLASS_SFSB);
+      service = deploySessionEjb(BEAN_IMPL_CLASS_SERVICE);
+
+   }
+
+   @AfterClass
+   public static void afterClass() throws Exception
+   {
+      // Undeploy the test EJBs
+      undeployEjb(slsb);
+      undeployEjb(sfsb);
+      undeployEjb(service);
+
+      AbstractEJB3TestCase.afterClass();
+   }
+
+}

Modified: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/service/ServiceBean.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/service/ServiceBean.java	2009-03-15 06:16:20 UTC (rev 85851)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/service/ServiceBean.java	2009-03-15 07:57:25 UTC (rev 85852)
@@ -21,6 +21,7 @@
  */
 package org.jboss.ejb3.core.test.service;
 
+import javax.ejb.Local;
 import javax.ejb.Remote;
 
 import org.jboss.ejb3.annotation.Service;
@@ -31,6 +32,7 @@
  */
 @Service
 @Remote(ServiceRemote.class)
+ at Local(ServiceLocal.class)
 public class ServiceBean implements ServiceRemote
 {
    private int id = -1;

Added: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/service/ServiceLocal.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/service/ServiceLocal.java	                        (rev 0)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/service/ServiceLocal.java	2009-03-15 07:57:25 UTC (rev 85852)
@@ -0,0 +1,33 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ejb3.core.test.service;
+
+/**
+ * @author <a href="mailto:cdewolf at redhat.com">Carlo de Wolf</a>
+ * @version $Revision: $
+ */
+public interface ServiceLocal
+{
+   int getId();
+   
+   void setId(int id);
+}

Modified: projects/ejb3/trunk/proxy-impl/src/main/java/org/jboss/ejb3/proxy/impl/handler/session/SessionProxyInvocationHandlerBase.java
===================================================================
--- projects/ejb3/trunk/proxy-impl/src/main/java/org/jboss/ejb3/proxy/impl/handler/session/SessionProxyInvocationHandlerBase.java	2009-03-15 06:16:20 UTC (rev 85851)
+++ projects/ejb3/trunk/proxy-impl/src/main/java/org/jboss/ejb3/proxy/impl/handler/session/SessionProxyInvocationHandlerBase.java	2009-03-15 07:57:25 UTC (rev 85852)
@@ -70,6 +70,8 @@
 
    private static final String METHOD_NAME_SET_TARGET = "setTarget";
 
+   private static final String METHOD_NAME_REMOVE_TARGET = "removeTarget";
+
    /*
     * Local Methods
     */
@@ -83,6 +85,8 @@
 
    private static final SerializableMethod METHOD_SET_TARGET;
 
+   private static final SerializableMethod METHOD_REMOVE_TARGET;
+
    static
    {
       try
@@ -94,6 +98,7 @@
          METHOD_EQUALS = new SerializableMethod(Object.class.getDeclaredMethod(METHOD_NAME_EQUALS, Object.class),
                Object.class);
          METHOD_HASH_CODE = new SerializableMethod(Object.class.getDeclaredMethod(METHOD_NAME_HASH_CODE), Object.class);
+         METHOD_REMOVE_TARGET = new SerializableMethod(SessionProxy.class.getDeclaredMethod(METHOD_NAME_REMOVE_TARGET));
       }
       catch (NoSuchMethodException nsme)
       {
@@ -295,11 +300,19 @@
          // Return
          return sb.toString();
       }
+      
       // hashCode
       if (invokedMethod.equals(METHOD_HASH_CODE.toMethod()))
       {
          return this.invokeHashCode(proxy);
       }
+      
+      // removeTarget
+      if (invokedMethod.equals(METHOD_REMOVE_TARGET.toMethod()))
+      {
+         this.getContainer().removeTarget(this.getTarget());
+         return null;
+      }
 
       // If no eligible methods were invoked
       throw new NotEligibleForDirectInvocationException("Current invocation \"" + invokedMethod

Modified: projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/common/container/ServiceContainer.java
===================================================================
--- projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/common/container/ServiceContainer.java	2009-03-15 06:16:20 UTC (rev 85851)
+++ projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/common/container/ServiceContainer.java	2009-03-15 07:57:25 UTC (rev 85852)
@@ -51,7 +51,8 @@
    /**
     * Singleton instance
     */
-   private Object beanInstance;
+   //GuardedBy=this
+   private volatile Object beanInstance;
 
    // --------------------------------------------------------------------------------||
    // Constructors -------------------------------------------------------------------||
@@ -98,17 +99,24 @@
     */
    @Override
    //FIXME: @Service has no Session ID
-   protected synchronized Object getBeanInstance(Serializable sessionId)
+   protected Object getBeanInstance(Serializable sessionId)
    {
       // Check if bean instance is not yet created
-      if (this.getBeanInstance() == null)
+      if (this.beanInstance == null)
       {
          try
          {
-            // Create and set the instance
-            Object beanInstance = this.createInstance();
-            this.setBeanInstance(beanInstance);
-            log.info("Set bean (Singleton) instance: " + beanInstance);
+            // Double-check
+            synchronized (this)
+            {
+               if (this.beanInstance == null)
+               {
+                  // Create and set the instance
+                  beanInstance = this.createInstance();
+                  this.setBeanInstance(beanInstance);
+                  log.info("Set bean (Singleton) instance: " + beanInstance);
+               }
+            }
          }
          catch (Throwable t)
          {
@@ -117,9 +125,25 @@
       }
 
       // Return
-      return this.getBeanInstance();
+      return this.beanInstance;
    }
 
+   /**
+    * Requests of the container that the underlying target be removed.
+    * Most frequently used in SFSB, but not necessarily supported 
+    * by SLSB/Singleton/@Service Containers
+    * 
+    * @throws UnsupportedOperationException If the bean type 
+    * does not honor client requests to remove the target
+    * 
+    * @param target
+    * @throws UnsupportedOperationException
+    */
+   public void removeTarget(Object target) throws UnsupportedOperationException
+   {
+      throw new UnsupportedOperationException("@Service");
+   }
+
    // --------------------------------------------------------------------------------||
    // Accessors / Mutators -----------------------------------------------------------||
    // --------------------------------------------------------------------------------||

Modified: projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/common/container/StatefulContainer.java
===================================================================
--- projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/common/container/StatefulContainer.java	2009-03-15 06:16:20 UTC (rev 85851)
+++ projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/common/container/StatefulContainer.java	2009-03-15 07:57:25 UTC (rev 85852)
@@ -138,6 +138,26 @@
       return bean;
    }
 
+   /**
+    * Requests of the container that the underlying target be removed.
+    * Most frequently used in SFSB, but not necessarily supported 
+    * by SLSB/Singleton/@Service Containers
+    * 
+    * @throws UnsupportedOperationException If the bean type 
+    * does not honor client requests to remove the target
+    * 
+    * @param target
+    * @throws UnsupportedOperationException
+    */
+   public void removeTarget(Object target) throws UnsupportedOperationException
+   {
+      Object instance = cache.remove(target);
+      if (instance == null)
+      {
+         throw new RuntimeException("No SFSB instance with ID " + target + " exists for removal");
+      }
+   }
+
    // --------------------------------------------------------------------------------||
    // Accessors / Mutators -----------------------------------------------------------||
    // --------------------------------------------------------------------------------||

Modified: projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/common/container/StatelessContainer.java
===================================================================
--- projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/common/container/StatelessContainer.java	2009-03-15 06:16:20 UTC (rev 85851)
+++ projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/common/container/StatelessContainer.java	2009-03-15 07:57:25 UTC (rev 85852)
@@ -82,4 +82,20 @@
          throw new RuntimeException("Error in creating new SLSB Bean Instance", t);
       }
    }
+
+   /**
+    * Requests of the container that the underlying target be removed.
+    * Most frequently used in SFSB, but not necessarily supported 
+    * by SLSB/Singleton/@Service Containers
+    * 
+    * @throws UnsupportedOperationException If the bean type 
+    * does not honor client requests to remove the target
+    * 
+    * @param target
+    * @throws UnsupportedOperationException
+    */
+   public void removeTarget(Object target) throws UnsupportedOperationException
+   {
+      throw new UnsupportedOperationException("SLSB");
+   }
 }

Modified: projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/session/unit/ProxyServiceTestCase.java
===================================================================
--- projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/session/unit/ProxyServiceTestCase.java	2009-03-15 06:16:20 UTC (rev 85851)
+++ projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/session/unit/ProxyServiceTestCase.java	2009-03-15 07:57:25 UTC (rev 85852)
@@ -96,7 +96,7 @@
 
    /**
     * Tests binding and invocation upon the local business 
-    * interface using @LocalBinding.jnidBinding value
+    * interface using @LocalBinding.jndiBinding value
     */
    @Test
    public void testLocalExplicitBindings() throws Exception
@@ -110,7 +110,7 @@
 
    /**
     * Tests binding and invocation upon the remote business 
-    * interface using @RemoteBinding.jnidBinding value
+    * interface using @RemoteBinding.jndiBinding value
     */
    @Test
    public void testRemoteExplicitBindings() throws Exception

Added: projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/session/unit/SessionProxyContractTestCase.java
===================================================================
--- projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/session/unit/SessionProxyContractTestCase.java	                        (rev 0)
+++ projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/session/unit/SessionProxyContractTestCase.java	2009-03-15 07:57:25 UTC (rev 85852)
@@ -0,0 +1,88 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+  *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ejb3.test.proxy.impl.session.unit;
+
+import org.jboss.ejb3.proxy.spi.intf.SessionProxy;
+import org.jboss.ejb3.test.proxy.impl.common.SessionTestCaseBase;
+import org.jboss.logging.Logger;
+import org.junit.Test;
+
+/**
+ * SessionProxyContractTestCase
+ *
+ * Tests to ensure that the SessionProxy contract remains
+ * backwards-compatible.  Note that we don't need to test anything 
+ * (which is implementation), just compile-time.
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public class SessionProxyContractTestCase extends SessionTestCaseBase
+{
+   // --------------------------------------------------------------------------------||
+   // Class Members ------------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   private static final Logger log = Logger.getLogger(SessionProxyContractTestCase.class);
+
+   // --------------------------------------------------------------------------------||
+   // Tests --------------------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /**
+    * Ensures that the compile-time contracts are in place, performs no real runtime
+    * tests/checks
+    */
+   @Test
+   @SuppressWarnings("null")
+   public void testSessionProxyContract() throws Throwable
+   {
+      SessionProxy proxy = null;
+
+      try
+      {
+         proxy.getTarget();
+      }
+      catch (NullPointerException npe)
+      {
+         // Swallow
+      }
+      try
+      {
+         proxy.setTarget(null);
+      }
+      catch (NullPointerException npe)
+      {
+         // Swallow
+      }
+      try
+      {
+         proxy.removeTarget();
+      }
+      catch (NullPointerException npe)
+      {
+         // Swallow
+      }
+
+      log.info(SessionProxy.class.getName() + " contracts OK");
+   }
+}

Modified: projects/ejb3/trunk/proxy-spi/src/main/java/org/jboss/ejb3/proxy/spi/container/InvokableContext.java
===================================================================
--- projects/ejb3/trunk/proxy-spi/src/main/java/org/jboss/ejb3/proxy/spi/container/InvokableContext.java	2009-03-15 06:16:20 UTC (rev 85851)
+++ projects/ejb3/trunk/proxy-spi/src/main/java/org/jboss/ejb3/proxy/spi/container/InvokableContext.java	2009-03-15 07:57:25 UTC (rev 85852)
@@ -58,4 +58,17 @@
     * @throws Throwable
     */
    InvocationResponse dynamicInvoke(Invocation invocation) throws Throwable;
+   
+   /**
+    * Requests of the container that the underlying target be removed.
+    * Most frequently used in SFSB, but not necessarily supported 
+    * by SLSB/Singleton/@Service Containers
+    * 
+    * @throws UnsupportedOperationException If the bean type 
+    * does not honor client requests to remove the target
+    * 
+    * @param target
+    * @throws UnsupportedOperationException
+    */
+   void removeTarget(Object target) throws UnsupportedOperationException;
 }

Modified: projects/ejb3/trunk/proxy-spi/src/main/java/org/jboss/ejb3/proxy/spi/intf/SessionProxy.java
===================================================================
--- projects/ejb3/trunk/proxy-spi/src/main/java/org/jboss/ejb3/proxy/spi/intf/SessionProxy.java	2009-03-15 06:16:20 UTC (rev 85851)
+++ projects/ejb3/trunk/proxy-spi/src/main/java/org/jboss/ejb3/proxy/spi/intf/SessionProxy.java	2009-03-15 07:57:25 UTC (rev 85852)
@@ -47,4 +47,14 @@
     * @param sessionId
     */
    void setTarget(Object target);
+
+   /**
+    * Requests of the container that the underlying target be removed.
+    * Most frequently used in SFSB, but not necessarily supported 
+    * by SLSB/Singleton/@Service Containers
+    * 
+    * @throws UnsupportedOperationException If the bean type 
+    * does not honor client requests to remove the target
+    */
+   void removeTarget() throws UnsupportedOperationException;
 }




More information about the jboss-cvs-commits mailing list