[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