[jboss-svn-commits] JBoss Common SVN: r3640 - in invokablecontainer/trunk: core/src/main/java/org/jboss/ejb3/container/core and 1 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Sat Nov 7 02:06:03 EST 2009


Author: ALRubinger
Date: 2009-11-07 02:06:03 -0500 (Sat, 07 Nov 2009)
New Revision: 3640

Added:
   invokablecontainer/trunk/core/src/main/java/org/jboss/ejb3/container/core/MapBasedInvocationContext.java
   invokablecontainer/trunk/core/src/test/java/org/jboss/ejb3/container/core/MapBasedInvocationContextTestCase.java
Modified:
   invokablecontainer/trunk/api/src/main/java/org/jboss/ejb3/container/api/Invocation.java
   invokablecontainer/trunk/api/src/main/java/org/jboss/ejb3/container/api/InvocationContext.java
   invokablecontainer/trunk/core/src/main/java/org/jboss/ejb3/container/core/InvocationImpl.java
   invokablecontainer/trunk/core/src/test/java/org/jboss/ejb3/container/core/DelegatingContainerTestCase.java
   invokablecontainer/trunk/core/src/test/java/org/jboss/ejb3/container/core/InvocationImplTest.java
Log:
[EJBTHREE-1948] Flesh out InvocationContext, impl, and tests.  Minor fixes to InvocationImpl to throw more proper exceptions on deserialization errors.  Make Invocation and InvocationContext interfaces extend Serializable

Modified: invokablecontainer/trunk/api/src/main/java/org/jboss/ejb3/container/api/Invocation.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/ejb3/container/api/Invocation.java	2009-11-07 01:07:58 UTC (rev 3639)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/ejb3/container/api/Invocation.java	2009-11-07 07:06:03 UTC (rev 3640)
@@ -21,19 +21,22 @@
  */
 package org.jboss.ejb3.container.api;
 
+import java.io.Serializable;
 import java.lang.reflect.Method;
 
 /**
  * Invocation
  * 
- * Method invocation upon an EJB.  Composes the target method, arguments, 
- * and business interface originally invoked upon by the client into a unified
- * view.
+ * Unified view of a {@link Method} invocation.  Composes the target method, arguments, 
+ * and mapped context into a single entity.
+ * 
+ * All {@link Invocation} types must be {@link Serializable} as they are
+ * generally accepted to cross network boundaries.
  *
  * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
  * @version $Revision: $
  */
-public interface Invocation
+public interface Invocation extends Serializable
 {
    //-------------------------------------------------------------------------------------||
    // Contracts --------------------------------------------------------------------------||

Modified: invokablecontainer/trunk/api/src/main/java/org/jboss/ejb3/container/api/InvocationContext.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/ejb3/container/api/InvocationContext.java	2009-11-07 01:07:58 UTC (rev 3639)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/ejb3/container/api/InvocationContext.java	2009-11-07 07:06:03 UTC (rev 3640)
@@ -21,15 +21,21 @@
  */
 package org.jboss.ejb3.container.api;
 
+import java.io.Serializable;
+
 /**
  * InvocationContext
  * 
  * Contextual properties which may be associated with an {@link Invocation}
  *
+ * All implementations of {@link InvocationContext} must be {@link Serializable}
+ * as they are intended for use in {@link Invocation} instances, which is itself 
+ * {@link Serializable} .
+ * 
  * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
  * @version $Revision: $
  */
-public interface InvocationContext
+public interface InvocationContext extends Serializable
 {
 
    //-------------------------------------------------------------------------------------||
@@ -37,23 +43,36 @@
    //-------------------------------------------------------------------------------------||
 
    /**
-    * Obtains the context property associated with the specified type
+    * Obtains the context property associated with the specified key,
+    * or null if not found
     * 
-    * @param <T>
-    * @param type
-    * @throws IllegalArgumentException If the type is not specified
+    * @param key
+    * @return The value under the specified key, or null if not found
+    * @throws IllegalArgumentException If the key is not specified
     */
-   <T> T getProperty(Class<T> type) throws IllegalArgumentException;
+   Object getProperty(Object key) throws IllegalArgumentException;
 
    /**
-    * Sets the specified value as a context property under the specified type, 
+    * Obtains the context property associated with the specified key, 
+    * or null if not found
+    * 
+    * @param <T> Type of the object to be returned
+    * @param key
+    * @param expectedType Expected type of the object to be returned
+    * @return The value under the specified key, or null if not found
+    * @throws IllegalArgumentException If the key is not specified
+    * @throws ClassCastException If the expected type is not the correct type for the object under the specified key
+    */
+   <T> T getProperty(Object key, Class<T> expectedType) throws IllegalArgumentException, ClassCastException;
+
+   /**
+    * Sets the specified value as a context property under the specified key, 
     * returning the previous value if one existed, else null
     * 
-    * @param <T>
-    * @param type
+    * @param key
     * @param value
     * @return
-    * @throws IllegalArgumentException If the type or value is not specified
+    * @throws IllegalArgumentException If the key or value is not specified
     */
-   <T> T setProperty(Class<T> type, T value) throws IllegalArgumentException;
+   Object setProperty(Object key, Object value) throws IllegalArgumentException;
 }

Modified: invokablecontainer/trunk/core/src/main/java/org/jboss/ejb3/container/core/InvocationImpl.java
===================================================================
--- invokablecontainer/trunk/core/src/main/java/org/jboss/ejb3/container/core/InvocationImpl.java	2009-11-07 01:07:58 UTC (rev 3639)
+++ invokablecontainer/trunk/core/src/main/java/org/jboss/ejb3/container/core/InvocationImpl.java	2009-11-07 07:06:03 UTC (rev 3640)
@@ -22,6 +22,8 @@
 package org.jboss.ejb3.container.core;
 
 import java.io.IOException;
+import java.io.InvalidClassException;
+import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
@@ -36,7 +38,7 @@
 /**
  * InvocationImpl
  * 
- * Threadsafe implementation of an {@link Invocation}.
+ * Implementation of an {@link Invocation}.
  * 
  * Serializable such that instances may be sent across the wire; though the target
  * method is deconstructed into components and shipped as a custom
@@ -44,6 +46,12 @@
  * 
  * Value equality is determined by equal target arguments, method, 
  * and {@link InvocationContext}.
+ * 
+ * This class is not Thread-safe; invocations are generally
+ * tied to a single Thread, so users wishing to share objects of
+ * this type across Threads must synchronize externally the calls
+ * to {@link Invocation#getContext()} when adding/obtaining
+ * properties.
  *
  * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
  * @version $Revision: $
@@ -80,7 +88,10 @@
     */
    private transient Method targetMethod;
 
-   //TODO: InvocationContext impl must be Threadsafe, and allow for atomic operations (putIfAbsent, etc)
+   /**
+    * Associated Invocation Context (properties)
+    */
+   private final InvocationContext context;
 
    //-------------------------------------------------------------------------------------||
    // Constructors -----------------------------------------------------------------------||
@@ -96,6 +107,20 @@
     */
    public InvocationImpl(final Method targetMethod, final Object[] args)
    {
+      this(targetMethod, args, new MapBasedInvocationContext());
+   }
+
+   /**
+    * Constructs a new instance of this invocation, representing the
+    * specified target method and arguments.  Backed by the specified 
+    * {@link InvocationContext}. 
+    * 
+    * @param targetMethod
+    * @param args
+    * @throws IllegalArgumentException If any of the required arguments are not present
+    */
+   public InvocationImpl(final Method targetMethod, final Object[] args, final InvocationContext context)
+   {
       // Precondition checks
       if (targetMethod == null)
       {
@@ -105,10 +130,16 @@
       {
          throw new IllegalArgumentException("Arguments for the target method must be specified");
       }
+      if (context == null)
+      {
+         throw new IllegalArgumentException("Context must be specified");
+      }
 
       // Set
       this.targetMethod = targetMethod;
       this.args = args;
+      // We don't need to defensively copy the invocation context as it's exposed via getContext() anyway
+      this.context = context;
    }
 
    //-------------------------------------------------------------------------------------||
@@ -130,8 +161,7 @@
    @Override
    public InvocationContext getContext()
    {
-      // TODO Auto-generated method stub
-      return null;
+      return this.context;
    }
 
    /**
@@ -153,8 +183,8 @@
    @Override
    public String toString()
    {
-      return this.getClass().getSimpleName() + " [args=" + Arrays.toString(args) + ", targetMethod=" + targetMethod
-            + "]";
+      return this.getClass().getSimpleName() + " [args=" + Arrays.asList(args).toString() + ", targetMethod="
+            + targetMethod + "]";
    }
 
    /**
@@ -250,15 +280,15 @@
       // Some more assertions
       if (declaringClass == null)
       {
-         throw new IllegalArgumentException("Declaring class was not read in during deserialization");
+         throw new InvalidObjectException("Declaring class was not read in during deserialization");
       }
       if (methodName == null)
       {
-         throw new IllegalArgumentException("Target method name was not read in during deserialization");
+         throw new InvalidObjectException("Target method name was not read in during deserialization");
       }
       if (paramTypes == null)
       {
-         throw new IllegalArgumentException(
+         throw new InvalidObjectException(
                "Parameter types of the target method were not read in during deserialization");
       }
 
@@ -270,7 +300,7 @@
       }
       catch (final NoSuchMethodException nsme)
       {
-         throw new RuntimeException("Could not deserialize; no target method \"" + methodName + " found in "
+         throw new InvalidClassException("Could not deserialize; no target method \"" + methodName + " found in "
                + declaringClass.getName() + " with param types " + Arrays.asList(paramTypes));
       }
 

Added: invokablecontainer/trunk/core/src/main/java/org/jboss/ejb3/container/core/MapBasedInvocationContext.java
===================================================================
--- invokablecontainer/trunk/core/src/main/java/org/jboss/ejb3/container/core/MapBasedInvocationContext.java	                        (rev 0)
+++ invokablecontainer/trunk/core/src/main/java/org/jboss/ejb3/container/core/MapBasedInvocationContext.java	2009-11-07 07:06:03 UTC (rev 3640)
@@ -0,0 +1,126 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.ejb3.container.core;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jboss.ejb3.container.api.InvocationContext;
+
+/**
+ * MapBasedInvocationContext
+ * 
+ * {@link InvocationContext} implementation backed
+ * internally by a {@link Map}.  Not Thread-safe, as invocations
+ * are typically tied to a single Thread.  Must be externally synchronized
+ * if shared.
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+final class MapBasedInvocationContext implements InvocationContext
+{
+
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Default initial size of the backing map; we assume that only a few 
+    * context props will be added, so we keep this small
+    */
+   private static final int DEFAULT_SIZE_MAP = 3;
+
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Backing Map of the context properties
+    */
+   private final Map<Object, Object> map;
+
+   //-------------------------------------------------------------------------------------||
+   // Constructor ------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Constructor
+    */
+   MapBasedInvocationContext()
+   {
+      map = new HashMap<Object, Object>(DEFAULT_SIZE_MAP);
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Required Implementations -----------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * @see org.jboss.ejb3.container.api.InvocationContext#getProperty(java.lang.Object)
+    */
+   @Override
+   public Object getProperty(final Object key) throws IllegalArgumentException
+   {
+      return this.getMap().get(key);
+   }
+
+   /**
+    * @see org.jboss.ejb3.container.api.InvocationContext#getProperty(java.lang.Object, java.lang.Class)
+    */
+   @Override
+   public <T> T getProperty(final Object key, final Class<T> expectedType) throws IllegalArgumentException,
+         ClassCastException
+   {
+      final Object obj = this.getProperty(key);
+      return expectedType.cast(obj);
+   }
+
+   /**
+    * @see org.jboss.ejb3.container.api.InvocationContext#setProperty(java.lang.Object, java.lang.Object)
+    */
+   @Override
+   public Object setProperty(final Object key, final Object value) throws IllegalArgumentException
+   {
+      return this.getMap().put(key, value);
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Internal Helper Methods ------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Returns the underlying Map backing this context
+    */
+   private Map<Object, Object> getMap()
+   {
+      return map;
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Overridden Implementations ---------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * @see java.lang.Object#toString()
+    */
+   @Override
+   public String toString()
+   {
+      return "MapBasedInvocationContext [map=" + map + "]";
+   }
+}

Modified: invokablecontainer/trunk/core/src/test/java/org/jboss/ejb3/container/core/DelegatingContainerTestCase.java
===================================================================
--- invokablecontainer/trunk/core/src/test/java/org/jboss/ejb3/container/core/DelegatingContainerTestCase.java	2009-11-07 01:07:58 UTC (rev 3639)
+++ invokablecontainer/trunk/core/src/test/java/org/jboss/ejb3/container/core/DelegatingContainerTestCase.java	2009-11-07 07:06:03 UTC (rev 3640)
@@ -21,6 +21,7 @@
  */
 package org.jboss.ejb3.container.core;
 
+import java.lang.reflect.Method;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -95,6 +96,15 @@
       this.assertInvocationAddingOneTwoThreeSucceeds(calcContainer, 6);
    }
 
+   @Test
+   public void testSomething()
+   {
+      log.info("\n\n\n\n\nALR\n\n\n\n\n");
+      final Method method = Addable.class.getMethods()[0];
+      log.info(method.toString());
+      log.info(method.getDeclaringClass().toString());
+   }
+
    /**
     * Tests that an invocation resulting in some exception will 
     * be wrapped

Modified: invokablecontainer/trunk/core/src/test/java/org/jboss/ejb3/container/core/InvocationImplTest.java
===================================================================
--- invokablecontainer/trunk/core/src/test/java/org/jboss/ejb3/container/core/InvocationImplTest.java	2009-11-07 01:07:58 UTC (rev 3639)
+++ invokablecontainer/trunk/core/src/test/java/org/jboss/ejb3/container/core/InvocationImplTest.java	2009-11-07 07:06:03 UTC (rev 3640)
@@ -40,6 +40,7 @@
 import junit.framework.TestCase;
 
 import org.jboss.ejb3.container.api.Invocation;
+import org.jboss.ejb3.container.api.InvocationContext;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -162,8 +163,6 @@
    {
       final Addable target = new Calculator();
       final Method targetMethod = roundtrip.getTargetMethod();
-      targetMethod.invoke(target, new int[]
-      {3, 4, 5});
       final int[] args =
       {1, 2, 3};
       final int expected = 6;
@@ -202,6 +201,24 @@
       this.testWireProtocol(original, OriginalVersionInvocationImpl.class);
    }
 
+   /**
+    * Tests that the {@link InvocationContext} may be obtained
+    * from an {@link Invocation}
+    * 
+    * @throws IOException
+    */
+   @Test
+   public void testInvocationContext() throws IOException
+   {
+      // Obtain
+      final Invocation invocation = original;
+      final InvocationContext context = invocation.getContext();
+      log.info("Got context " + context + " from " + invocation);
+
+      // Test
+      TestCase.assertNotNull("Invocation context should not be null", context);
+   }
+
    //-------------------------------------------------------------------------------------||
    // Internal Helper Methods ------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||
@@ -224,8 +241,11 @@
    }
 
    /**
+    * Roundtrip serializes/deserializes the specified {@link Invocation}
+    * and reconsitutes/redefines as the specified target type
     * 
-    * @param 
+    * @param o The original {@link Invocation} instance
+    * @param The new type we should cast to after deserialization 
     * @see http://crazybob.org/2006/01/unit-testing-serialization-evolution.html
     * @see http://crazybob.org/2006/01/unit-testing-serialization-evolution_13.html
     * @see http://www.theserverside.com/news/thread.tss?thread_id=38398

Added: invokablecontainer/trunk/core/src/test/java/org/jboss/ejb3/container/core/MapBasedInvocationContextTestCase.java
===================================================================
--- invokablecontainer/trunk/core/src/test/java/org/jboss/ejb3/container/core/MapBasedInvocationContextTestCase.java	                        (rev 0)
+++ invokablecontainer/trunk/core/src/test/java/org/jboss/ejb3/container/core/MapBasedInvocationContextTestCase.java	2009-11-07 07:06:03 UTC (rev 3640)
@@ -0,0 +1,98 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.ejb3.container.core;
+
+import java.util.Date;
+import java.util.logging.Logger;
+
+import junit.framework.TestCase;
+
+import org.jboss.ejb3.container.api.InvocationContext;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * MapBasedInvocationContextTestCase
+ *
+ * Ensures that the contract of {@link InvocationContext}
+ * holds with the {@link MapBasedInvocationContext} implementation
+ * 
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public class MapBasedInvocationContextTestCase
+{
+
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Logger
+    */
+   private static final Logger log = Logger.getLogger(MapBasedInvocationContextTestCase.class.getName());
+
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * The context to be tested
+    */
+   private InvocationContext context;
+
+   //-------------------------------------------------------------------------------------||
+   // Lifecycle --------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Sets the {@link InvocationContext} before each test run
+    */
+   @Before
+   public void setContext()
+   {
+      context = new MapBasedInvocationContext();
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Tests ------------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Tests that a property set upon the context may be obtained
+    */
+   @Test
+   public void testRoundtripSetAndGet()
+   {
+      // Define key/value pair
+      final String key = "KEY";
+      final Date value = new Date();
+
+      // Set
+      log.info("Setting " + value + " under key " + key);
+      context.setProperty(key, value);
+      log.info("Invocation context is now: " + context);
+
+      // Get
+      final Date roundrip = context.getProperty(key, Date.class);
+      log.info("Obtained value: " + value + " for key " + key);
+
+      // Test
+      TestCase.assertEquals("Did not obtain expected value from context under key " + key, value, roundrip);
+   }
+
+}



More information about the jboss-svn-commits mailing list