[jboss-cvs] JBossAS SVN: r84112 - in projects/ejb3/trunk/async: src/main/java/org/jboss and 15 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Thu Feb 12 02:48:52 EST 2009


Author: ALRubinger
Date: 2009-02-12 02:48:51 -0500 (Thu, 12 Feb 2009)
New Revision: 84112

Added:
   projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/
   projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/
   projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/container/
   projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/container/AsyncInvocationProcessor.java
   projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/future/
   projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/future/AsyncFutureWrapper.java
   projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/hack/
   projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/hack/DevelopmentHacks.java
   projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/interceptor/
   projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/interceptor/AsynchronousInterceptor.java
   projects/ejb3/trunk/async/src/test/java/org/jboss/ejb3/
   projects/ejb3/trunk/async/src/test/java/org/jboss/ejb3/async/
   projects/ejb3/trunk/async/src/test/java/org/jboss/ejb3/async/test/
   projects/ejb3/trunk/async/src/test/java/org/jboss/ejb3/async/test/container/
   projects/ejb3/trunk/async/src/test/java/org/jboss/ejb3/async/test/container/AsyncContainer.java
   projects/ejb3/trunk/async/src/test/java/org/jboss/ejb3/async/test/simple/
   projects/ejb3/trunk/async/src/test/java/org/jboss/ejb3/async/test/simple/Pojo.java
   projects/ejb3/trunk/async/src/test/java/org/jboss/ejb3/async/test/simple/unit/
   projects/ejb3/trunk/async/src/test/java/org/jboss/ejb3/async/test/simple/unit/SimpleAsyncTestCase.java
   projects/ejb3/trunk/async/src/test/resources/log4j.xml
   projects/ejb3/trunk/async/src/test/resources/simple/
   projects/ejb3/trunk/async/src/test/resources/simple/jboss-aop.xml
Modified:
   projects/ejb3/trunk/async/.project
   projects/ejb3/trunk/async/pom.xml
Log:
[EJBTHREE-1721] Some ejb3-async first pass

Modified: projects/ejb3/trunk/async/.project
===================================================================
--- projects/ejb3/trunk/async/.project	2009-02-12 07:31:06 UTC (rev 84111)
+++ projects/ejb3/trunk/async/.project	2009-02-12 07:48:51 UTC (rev 84112)
@@ -1,17 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <projectDescription>
-  <name>jboss-ejb3-async</name>
-  <comment>Support for EJB 3.1 @Asynchronous</comment>
-  <projects/>
-  <buildSpec>
-    <buildCommand>
-      <name>org.eclipse.jdt.core.javabuilder</name>
-    </buildCommand>
-    <buildCommand>
-      <name>org.maven.ide.eclipse.maven2Builder</name>
-    </buildCommand>
-  </buildSpec>
-  <natures>
-    <nature>org.eclipse.jdt.core.javanature</nature>
-    <nature>org.maven.ide.eclipse.maven2Nature</nature>
-  </natures>
-</projectDescription>
\ No newline at end of file
+	<name>jboss-ejb3-async</name>
+	<comment>Support for EJB 3.1 @Asynchronous at key 32303037303533312D31303030206A626F73732D656A62332D6173796E632F616C727562696E676572 </comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.soyatec.additional.Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+		<nature>com.soyatec.additional.Nature</nature>
+	</natures>
+</projectDescription>

Modified: projects/ejb3/trunk/async/pom.xml
===================================================================
--- projects/ejb3/trunk/async/pom.xml	2009-02-12 07:31:06 UTC (rev 84111)
+++ projects/ejb3/trunk/async/pom.xml	2009-02-12 07:48:51 UTC (rev 84112)
@@ -24,9 +24,107 @@
   <name>JBoss EJB 3.1 Asynchronous</name>
   <description>Support for EJB 3.1 @Asynchronous</description>
 
+  <!-- Build Configuration -->
+  <build>
+  
+  
+    <!-- We depend upon JDK6, as we bring in the EJB 3.1 API here  -->
+  
+    <plugins>
+    
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>1.6</source>
+          <target>1.6</target>
+          <executable>${JDK6_HOME}/bin/javac</executable>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>enforce-jdk6</id>
+            <goals>
+              <goal>enforce</goal>
+            </goals>
+            <configuration>
+              <rules>
+                <requireProperty>
+                  <property>env.JDK6_HOME</property>
+                  <message>JDK6_HOME is not set</message>
+                </requireProperty>
+              </rules>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <forkMode>once</forkMode>
+          <jvm>${JDK6_HOME}/bin/java</jvm>
+        </configuration>
+      </plugin>
+      
+    </plugins>
+    
+  </build>
+  
+  <properties>
+  
+    <!-- Versioning -->
+    <version.org.jboss.ejb3_jboss.ejb3.api>3.1.0-SNAPSHOT</version.org.jboss.ejb3_jboss.ejb3.api>
+    <version.org.jboss.ejb3_jboss.ejb3.interceptors>1.0.0</version.org.jboss.ejb3_jboss.ejb3.interceptors>
+  
+  </properties>
+
   <dependencies>
   
+    <!-- 
+    Dependencies: org.jboss.ejb3 
+    -->
     
+    <!-- org.jboss.ejb3:jboss-ejb3-interceptors -->
+    <dependency>
+      <groupId>org.jboss.ejb3</groupId>
+      <artifactId>jboss-ejb3-api</artifactId>
+      <version>${version.org.jboss.ejb3_jboss.ejb3.api}</version>
+    </dependency>
+    
+    <!-- org.jboss.ejb3:jboss-ejb3-interceptors -->
+    <dependency>
+      <groupId>org.jboss.ejb3</groupId>
+      <artifactId>jboss-ejb3-interceptors</artifactId>
+      <version>${version.org.jboss.ejb3_jboss.ejb3.interceptors}</version>
+      <scope>test</scope>
+    </dependency>
+    
+    <!-- 
+    Dependencies: External to EJB3 
+    -->
+
+    <!-- junit:junit -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+  
+    <!-- org.jboss.aop:jboss-aop -->
+    <dependency>
+      <groupId>org.jboss.aop</groupId>
+      <artifactId>jboss-aop</artifactId>
+    </dependency>
+    
+    <!-- org.jboss.aspects:jboss-aspects-common -->
+    <dependency>
+      <groupId>org.jboss.aspects</groupId>
+      <artifactId>jboss-aspects-common</artifactId>
+      <scope>test</scope>
+    </dependency>
+    
   </dependencies>
-
 </project>

Added: projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/container/AsyncInvocationProcessor.java
===================================================================
--- projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/container/AsyncInvocationProcessor.java	                        (rev 0)
+++ projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/container/AsyncInvocationProcessor.java	2009-02-12 07:48:51 UTC (rev 84112)
@@ -0,0 +1,46 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, 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.async.container;
+
+import java.util.concurrent.ExecutorService;
+
+/**
+ * AsyncInvocationProcessor
+ * 
+ * ejb3-async view of the target Container
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public interface AsyncInvocationProcessor
+{
+
+   // --------------------------------------------------------------------------------||
+   // Contracts ----------------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /**
+    * Obtains the ExecutorService to be used for asynchronous invocations
+    */
+   ExecutorService getAsynchronousExecutor();
+
+}

Added: projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/future/AsyncFutureWrapper.java
===================================================================
--- projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/future/AsyncFutureWrapper.java	                        (rev 0)
+++ projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/future/AsyncFutureWrapper.java	2009-02-12 07:48:51 UTC (rev 84112)
@@ -0,0 +1,147 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, 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.async.future;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.jboss.logging.Logger;
+
+/**
+ * AsyncFutureWrapper
+ * 
+ * Client view of an EJB 3.1 Asynchronous invocation's return
+ * value
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public class AsyncFutureWrapper<V> implements Future<V>
+{
+   // --------------------------------------------------------------------------------||
+   // Class Members ------------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   private static final long serialVersionUID = 1L;
+
+   private static final Logger log = Logger.getLogger(AsyncFutureWrapper.class);
+
+   // --------------------------------------------------------------------------------||
+   // Instance Members ---------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /**
+    * Underlying target for inquiry
+    */
+   private Future<Future<V>> target;
+
+   // --------------------------------------------------------------------------------||
+   // Constructor --------------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /**
+    * Constructs a new AsyncFuture for the given invocation
+    * 
+    * @param target The Future returned by the executor
+    */
+   public AsyncFutureWrapper(final Future<Future<V>> target)
+   {
+      // Set properties
+      this.setTarget(target);
+   }
+
+   // --------------------------------------------------------------------------------||
+   // Required Implementations -------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   public boolean cancel(boolean mayInterruptIfRunning)
+   {
+      return this.getUnderlyingTarget().cancel(mayInterruptIfRunning);
+   }
+
+   /**
+    * Obtains the 
+    */
+   public V get() throws InterruptedException, ExecutionException
+   {
+      // Get the underlying target
+      Future<V> underlyingTarget = this.getUnderlyingTarget();
+
+      // Invoke (ignore a null value as this indicates no return/void)
+      V returnValue = underlyingTarget == null ? null : underlyingTarget.get();
+
+      // Return
+      return returnValue;
+   }
+
+   public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
+   {
+      Future<V> underlyingTarget = this.getUnderlyingTarget();
+      return underlyingTarget == null ? null : underlyingTarget.get(timeout, unit);
+   }
+
+   public boolean isCancelled()
+   {
+      return this.getUnderlyingTarget().isCancelled();
+   }
+
+   public boolean isDone()
+   {
+      return this.getUnderlyingTarget().isDone();
+   }
+
+   // --------------------------------------------------------------------------------||
+   // Accessors / Mutators -----------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   private void setTarget(Future<Future<V>> target)
+   {
+      // Precondition checks
+      assert target != null : "target must be specified";
+
+      // Set
+      this.target = target;
+   }
+
+   // --------------------------------------------------------------------------------||
+   // Internal Helper Methods --------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   private Future<V> getUnderlyingTarget()
+   {
+      try
+      {
+         return target.get();
+      }
+      catch (InterruptedException e)
+      {
+         throw new RuntimeException(e);
+      }
+      catch (ExecutionException e)
+      {
+         throw new RuntimeException(e);
+      }
+   }
+
+}

Added: projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/hack/DevelopmentHacks.java
===================================================================
--- projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/hack/DevelopmentHacks.java	                        (rev 0)
+++ projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/hack/DevelopmentHacks.java	2009-02-12 07:48:51 UTC (rev 84112)
@@ -0,0 +1,71 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, 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.async.hack;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * DevelopmentHacks
+ * 
+ * A hack access class used solely in development.  Provides
+ * tight coupling between components which will later be bound
+ * together as configurable beans via MC
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+//TODO Move everything out of here as noted in comments
+ at Deprecated
+public final class DevelopmentHacks
+{
+
+   // --------------------------------------------------------------------------------||
+   // Constructor --------------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /**
+    * Non-instanciable
+    */
+   private DevelopmentHacks()
+   {
+
+   }
+
+   // --------------------------------------------------------------------------------||
+   // Utilities ----------------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /**
+    * Obtains the default ExecutorService to be used for asynchronous
+    * invocations.  Will eventually be injected via MC, as a per-container
+    * configurable property
+    * 
+    * @return 
+    */
+   @Deprecated
+   public static ExecutorService getDefaultAsyncExecutorService()
+   {
+      return Executors.newCachedThreadPool();
+   }
+
+}

Added: projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/interceptor/AsynchronousInterceptor.java
===================================================================
--- projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/interceptor/AsynchronousInterceptor.java	                        (rev 0)
+++ projects/ejb3/trunk/async/src/main/java/org/jboss/ejb3/async/interceptor/AsynchronousInterceptor.java	2009-02-12 07:48:51 UTC (rev 84112)
@@ -0,0 +1,225 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, 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.async.interceptor;
+
+import java.lang.reflect.Method;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import javax.ejb.Asynchronous;
+
+import org.jboss.aop.advice.Interceptor;
+import org.jboss.aop.joinpoint.Invocation;
+import org.jboss.aop.joinpoint.MethodInvocation;
+import org.jboss.ejb3.async.container.AsyncInvocationProcessor;
+import org.jboss.ejb3.async.future.AsyncFutureWrapper;
+import org.jboss.ejb3.async.hack.DevelopmentHacks;
+import org.jboss.logging.Logger;
+
+/**
+ * AsynchronousInterceptor
+ *
+ * Examines invocation metadata to determine if this
+ * should be handled asynchronously; if so, short-circuits and
+ * spawns off into a new Thread, returning a handle back to the client
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public class AsynchronousInterceptor implements Interceptor
+{
+
+   // --------------------------------------------------------------------------------||
+   // Class Members ------------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   private static final Logger log = Logger.getLogger(AsynchronousInterceptor.class);
+
+   // --------------------------------------------------------------------------------||
+   // Constructor --------------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /**
+    * No-arg constructor required
+    */
+   public AsynchronousInterceptor()
+   {
+      log.debug("Created: " + this);
+   }
+
+   // --------------------------------------------------------------------------------||
+   // Required Implementations -------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /* (non-Javadoc)
+    * @see org.jboss.aop.advice.Interceptor#getName()
+    */
+   public String getName()
+   {
+      return this.getClass().getSimpleName();
+   }
+
+   /* (non-Javadoc)
+    * @see org.jboss.aop.advice.Interceptor#invoke(org.jboss.aop.joinpoint.Invocation)
+    */
+   public Object invoke(Invocation invocation) throws Throwable
+   {
+      // If asynchronous
+      if (this.isAsyncInvocation(invocation))
+      {
+         // Spawn
+         return this.invokeAsync(invocation);
+      }
+      // Regular synchronous call
+      else
+      {
+         // Continue along the chain
+         return invocation.invokeNext();
+      }
+   }
+
+   // --------------------------------------------------------------------------------||
+   // Internal Helper Methods --------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /**
+    * Breaks off the specified invocation into 
+    * a queue for asynchronous processing, returning 
+    * a handle to the task
+    */
+   private Future<?> invokeAsync(Invocation invocation)
+   {
+      // Get the target container
+      AsyncInvocationProcessor container = this.getInvocationProcessor(invocation);
+
+      // Get the ExecutorService
+      ExecutorService executorService = container.getAsynchronousExecutor();
+
+      // Make the asynchronous task from the invocation
+      Callable<Object> asyncTask = new AsyncInvocationTask<Object>(invocation);
+
+      // Short-circuit the invocation into new Thread 
+      Future<Object> task = executorService.submit(asyncTask);
+
+      // Make a Future handle for the caller
+      Future<Object> handle = new AsyncFutureWrapper(task);
+
+      // Return
+      return handle;
+   }
+
+   /**
+    * Determines whether the specified invocation is asynchronous
+    * by inspecting its metadata
+    * 
+    * EJB 3.1 4.5.2.2
+    */
+   private boolean isAsyncInvocation(Invocation invocation)
+   {
+      // Precondition check
+      assert invocation instanceof MethodInvocation : this.getClass().getName() + " supports only "
+            + MethodInvocation.class.getSimpleName() + ", but has been passed: " + invocation;
+      MethodInvocation si = (MethodInvocation) invocation;
+
+      // Get the actual method
+      Method actualMethod = si.getActualMethod();
+
+      // Determine if asynchronous (either returns Future or has @Asynchronous)
+      if (actualMethod.getAnnotation(Asynchronous.class) != null || actualMethod.getReturnType().equals(Future.class))
+      {
+         // Log
+         if (log.isTraceEnabled())
+         {
+            log.trace("Intercepted: " + actualMethod);
+         }
+
+         // We'll take it
+         return true;
+      }
+
+      //TODO 
+      /*
+       * Business interface defines method with same name, arguments, return type Future<V>
+       * of bean impl class is eligible for async handling
+       */
+
+      //TODO 
+      /*
+       * Should this be better handled by jboss-metadata
+       * (ie. JBossSessionBeanMetadata.getAsynchronousMethods().match(method))) ? 
+       */
+
+      // Has met no conditions
+      return false;
+   }
+
+   /**
+    * 
+    * @return
+    */
+   private AsyncInvocationProcessor getInvocationProcessor(Invocation invocation)
+   {
+      //TODO Need to get at the container from here
+      return new AsyncInvocationProcessor()
+      {
+
+         public ExecutorService getAsynchronousExecutor()
+         {
+            return DevelopmentHacks.getDefaultAsyncExecutorService();
+         }
+      };
+   }
+
+   // --------------------------------------------------------------------------------||
+   // Inner Classes ------------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /**
+    * Task to invoke the held invocation in a new Thread, either 
+    * returning the result or throwing the generated Exception
+    */
+   private class AsyncInvocationTask<V> implements Callable<V>
+   {
+      private Invocation invocation;
+
+      public AsyncInvocationTask(Invocation invocation)
+      {
+         this.invocation = invocation;
+      }
+
+      @SuppressWarnings("unchecked")
+      public V call() throws Exception
+      {
+         try
+         {
+            return (V) invocation.invokeNext();
+         }
+         catch (Throwable t)
+         {
+            throw new Exception(t);
+         }
+      }
+
+   }
+
+}

Added: projects/ejb3/trunk/async/src/test/java/org/jboss/ejb3/async/test/container/AsyncContainer.java
===================================================================
--- projects/ejb3/trunk/async/src/test/java/org/jboss/ejb3/async/test/container/AsyncContainer.java	                        (rev 0)
+++ projects/ejb3/trunk/async/src/test/java/org/jboss/ejb3/async/test/container/AsyncContainer.java	2009-02-12 07:48:51 UTC (rev 84112)
@@ -0,0 +1,81 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, 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.async.test.container;
+
+import java.util.concurrent.ExecutorService;
+
+import org.jboss.ejb3.async.container.AsyncInvocationProcessor;
+import org.jboss.ejb3.async.hack.DevelopmentHacks;
+import org.jboss.ejb3.interceptors.direct.DirectContainer;
+
+/**
+ * AsyncContainer
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public class AsyncContainer<T> extends DirectContainer<T> implements AsyncInvocationProcessor
+{
+   // --------------------------------------------------------------------------------||
+   // Instance Members ---------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /**
+    * To be used for asynchronous invocations
+    */
+   private ExecutorService asynchronousExecutor;
+
+   // --------------------------------------------------------------------------------||
+   // Constructors -------------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   public AsyncContainer(String name, String domainName, Class<? extends T> beanClass)
+   {
+      this(name, domainName, beanClass, DevelopmentHacks.getDefaultAsyncExecutorService());
+   }
+
+   public AsyncContainer(String name, String domainName, Class<? extends T> beanClass,
+         ExecutorService asynchronousExecutor)
+   {
+      super(name, domainName, beanClass);
+      this.setAsynchronousExecutor(asynchronousExecutor);
+   }
+
+   // --------------------------------------------------------------------------------||
+   // Required Implementations -------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   public ExecutorService getAsynchronousExecutor()
+   {
+      return asynchronousExecutor;
+   }
+
+   // --------------------------------------------------------------------------------||
+   // Accessors / Mutators -----------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   public void setAsynchronousExecutor(ExecutorService asynchronousExecutor)
+   {
+      this.asynchronousExecutor = asynchronousExecutor;
+   }
+
+}

Added: projects/ejb3/trunk/async/src/test/java/org/jboss/ejb3/async/test/simple/Pojo.java
===================================================================
--- projects/ejb3/trunk/async/src/test/java/org/jboss/ejb3/async/test/simple/Pojo.java	                        (rev 0)
+++ projects/ejb3/trunk/async/src/test/java/org/jboss/ejb3/async/test/simple/Pojo.java	2009-02-12 07:48:51 UTC (rev 84112)
@@ -0,0 +1,109 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, 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.async.test.simple;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.ejb.AsyncResult;
+import javax.ejb.Asynchronous;
+
+/**
+ * Pojo
+ * 
+ * A simple POJO to act as BeanContext for a test Container,
+ * candidate for asynchronous interception
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public class Pojo
+{
+   // --------------------------------------------------------------------------------||
+   // Class Members ------------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   public static final String VALUE = "Test Value";
+
+   // --------------------------------------------------------------------------------||
+   // Instance Members ---------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   public AtomicInteger counter = new AtomicInteger();
+
+   // --------------------------------------------------------------------------------||
+   // Business Methods ---------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /**
+    * Obtains a contracted value, asynchronously
+    * 
+    * @return
+    */
+   public Future<String> getValueAsynchronous()
+   {
+      return new AsyncResult<String>(this.getValueSynchronous());
+   }
+
+   /**
+    * Obtains a contracted value
+    * 
+    * @return
+    */
+   public String getValueSynchronous()
+   {
+      return VALUE;
+   }
+
+   /**
+    * Increments the internal counter; intentionally
+    * void return to test @Asynchronous on void
+    */
+   @Asynchronous
+   public void incrementCounterAsynchronous()
+   {
+      // The @Asynchronous annotation here will spawn this off,
+      // so just delegate to the synchronous handling 
+      this.incrementCounterSynchronous();
+   }
+
+   /**
+    * Obtains the internal counter
+    * 
+    * @return
+    */
+   public Future<Integer> getCounter()
+   {
+      return new AsyncResult<Integer>(counter.intValue());
+   }
+
+   /**
+    * Increments the internal counter, though
+    * does so synchronously (not a candidate for
+    * interception)
+    */
+   public void incrementCounterSynchronous()
+   {
+      counter.incrementAndGet();
+   }
+
+}

Added: projects/ejb3/trunk/async/src/test/java/org/jboss/ejb3/async/test/simple/unit/SimpleAsyncTestCase.java
===================================================================
--- projects/ejb3/trunk/async/src/test/java/org/jboss/ejb3/async/test/simple/unit/SimpleAsyncTestCase.java	                        (rev 0)
+++ projects/ejb3/trunk/async/src/test/java/org/jboss/ejb3/async/test/simple/unit/SimpleAsyncTestCase.java	2009-02-12 07:48:51 UTC (rev 84112)
@@ -0,0 +1,188 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, 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.async.test.simple.unit;
+
+import java.util.concurrent.Future;
+
+import javax.ejb.Asynchronous;
+
+import junit.framework.TestCase;
+
+import org.jboss.aspects.common.AOPDeployer;
+import org.jboss.ejb3.async.test.container.AsyncContainer;
+import org.jboss.ejb3.async.test.simple.Pojo;
+import org.jboss.ejb3.interceptors.container.BeanContext;
+import org.jboss.logging.Logger;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * SimpleAsyncTestCase
+ * 
+ * Tests for some common EJB 3.1 @Asynchronous use cases 
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public class SimpleAsyncTestCase
+{
+
+   // --------------------------------------------------------------------------------||
+   // Class Members ------------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   private static final Logger log = Logger.getLogger(SimpleAsyncTestCase.class);
+
+   private static AOPDeployer aopDeployer = new AOPDeployer("simple/jboss-aop.xml");
+
+   private static final String DOMAIN_ASYNC = "Asynchronous Container";
+
+   private static AsyncContainer<Pojo> container;
+
+   /*
+    * Method names in Test POJO
+    */
+
+   private static final String METHOD_NAME_INCREMENT_COUNTER_ASYNCHRONOUS = "incrementCounterAsynchronous";
+
+   private static final String METHOD_NAME_INCREMENT_COUNTER_SYNCHRONOUS = "incrementCounterSynchronous";
+
+   private static final String METHOD_NAME_GET_COUNTER = "getCounter";
+
+   private static final String METHOD_NAME_GET_VALUE_ASYNCHRONOUS = "getValueAsynchronous";
+
+   private static final String METHOD_NAME_GET_VALUE_SYNCHRONOUS = "getValueSynchronous";
+
+   // --------------------------------------------------------------------------------||
+   // Test Lifecycle -----------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   @BeforeClass
+   public static void beforeClass() throws Throwable
+   {
+      aopDeployer.deploy();
+      container = new AsyncContainer<Pojo>("Test Async POJO Container", DOMAIN_ASYNC, Pojo.class);
+   }
+
+   @AfterClass
+   public static void afterClass() throws Throwable
+   {
+      aopDeployer.undeploy();
+   }
+
+   // --------------------------------------------------------------------------------||
+   // Tests --------------------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /**
+    * Tests that a simple invocation to obtain 
+    * some contracted String value returns as expected
+    * 
+    * @throws Throwable 
+    */
+   @Test
+   public void testSimpleInvocation() throws Throwable
+   {
+      // Make a new bean instance upon which we'll invoke
+      BeanContext<Pojo> bean = container.construct();
+
+      // Use the container to get a contracted value from the bean
+      Future<?> futureResult = (Future<?>) container.invoke(bean, METHOD_NAME_GET_VALUE_ASYNCHRONOUS);
+      log.info("Obtained result: " + futureResult);
+
+      // Get the Future value
+      Object result = futureResult.get();
+
+      // Ensure the value is expected
+      TestCase.assertEquals("Did not obtain expected result", Pojo.VALUE, result);
+   }
+
+   /**
+    * Tests that support for methods annotated as @Asynchronous
+    * with return type void succeed
+    * 
+    * @throws Throwable
+    */
+   @Test
+   @SuppressWarnings("unchecked")
+   public void testVoidMethodWithAsynchronous() throws Throwable
+   {
+      // Make a new bean instance upon which we'll invoke
+      BeanContext<Pojo> bean = container.construct();
+
+      // Get the counter as it exists
+      Future<Integer> initialCounterFuture = (Future<Integer>) container.invoke(bean, METHOD_NAME_GET_COUNTER);
+      int initialCounter = initialCounterFuture.get();
+
+      // Increment the counter 
+      Future<Integer> incrementCounterFutureResult = (Future<Integer>) container.invoke(bean,
+            METHOD_NAME_INCREMENT_COUNTER_ASYNCHRONOUS);
+      TestCase.assertNotNull("void return type not intercepted as asynchronous invocation",
+            incrementCounterFutureResult);
+      Object incrementedCounterResult = incrementCounterFutureResult.get();
+      TestCase.assertNull("void return types should return null upon Future.get()", incrementedCounterResult);
+
+      // Test the counter was incremented
+      Future<Integer> incrementedCounterFuture = (Future<Integer>) container.invoke(bean, METHOD_NAME_GET_COUNTER);
+      int incrementedCounter = incrementedCounterFuture.get();
+      TestCase.assertEquals("Counter was not incremented", initialCounter + 1, incrementedCounter);
+   }
+
+   /**
+    * Tests that support for methods not annotated, and of return 
+    * type void succeed
+    * 
+    * @throws Throwable
+    */
+   @Test
+   public void testVoidMethodUnannotated() throws Throwable
+   {
+      // Make a new bean instance upon which we'll invoke
+      BeanContext<Pojo> bean = container.construct();
+
+      // Invoke and test
+      Object shouldBeNullReturnValue = container.invoke(bean, METHOD_NAME_INCREMENT_COUNTER_SYNCHRONOUS);
+      TestCase.assertNull("methods with void return type not annotated with @" + Asynchronous.class.getSimpleName()
+            + " should have null return tyope from container invocation", shouldBeNullReturnValue);
+
+   }
+
+   /**
+    * Tests that support for methods not annotated, and returning
+    * some type other than Future succeed
+    * 
+    * @throws Throwable
+    */
+   @Test
+   public void testUnannotatedMethodsSynchronous() throws Throwable
+   {
+      // Make a new bean instance upon which we'll invoke
+      BeanContext<Pojo> bean = container.construct();
+
+      // Invoke and test
+      String value = container.invoke(bean, METHOD_NAME_GET_VALUE_SYNCHRONOUS);
+      TestCase.assertEquals("Contracted value not obtained as expected", Pojo.VALUE, value);
+
+   }
+
+}

Added: projects/ejb3/trunk/async/src/test/resources/log4j.xml
===================================================================
--- projects/ejb3/trunk/async/src/test/resources/log4j.xml	                        (rev 0)
+++ projects/ejb3/trunk/async/src/test/resources/log4j.xml	2009-02-12 07:48:51 UTC (rev 84112)
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
+
+  <!-- ================================= -->
+  <!-- Preserve messages in a local file -->
+  <!-- ================================= -->
+
+  <!-- A time/date based rolling appender -->
+  <appender name="FILE" class="org.jboss.logging.appender.DailyRollingFileAppender">
+    <param name="File" value="target/test.log"/>
+    <param name="Threshold" value="INFO"/>
+    <param name="Append" value="false"/>
+
+    <!-- Rollover at midnight each day -->
+    <param name="DatePattern" value="'.'yyyy-MM-dd"/>
+
+    <!-- Rollover at the top of each hour
+    <param name="DatePattern" value="'.'yyyy-MM-dd-HH"/>
+    -->
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <!-- The default pattern: Date Priority [Category] Message\n -->
+      <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
+
+      <!-- The full pattern: Date MS Priority [Category] (Thread:NDC) Message\n
+      <param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
+       -->
+    </layout>	    
+  </appender>
+
+  <!-- ============================== -->
+  <!-- Append messages to the console -->
+  <!-- ============================== -->
+
+  <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+    <param name="Target" value="System.out"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <!-- The default pattern: Date Priority [Category] Message\n -->
+      <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
+    </layout>
+  </appender>
+
+
+  <!-- ================ -->
+  <!-- Limit categories -->
+  <!-- ================ -->
+  
+  <category name="org.jboss">
+    <priority value="INFO"/>
+  </category>  
+  
+  <category name="org.jnp">
+    <priority value="INFO"/>
+  </category>
+  
+  <category name="org.jboss.ejb3">
+    <priority value="ALL"/>
+  </category>
+  
+  <!-- ======================= -->
+  <!-- Setup the Root category -->
+  <!-- ======================= -->
+
+  <root>
+    <appender-ref ref="CONSOLE"/>
+    <appender-ref ref="FILE"/>
+  </root>
+  
+</log4j:configuration>

Added: projects/ejb3/trunk/async/src/test/resources/simple/jboss-aop.xml
===================================================================
--- projects/ejb3/trunk/async/src/test/resources/simple/jboss-aop.xml	                        (rev 0)
+++ projects/ejb3/trunk/async/src/test/resources/simple/jboss-aop.xml	2009-02-12 07:48:51 UTC (rev 84112)
@@ -0,0 +1,25 @@
+<aop xmlns="urn:jboss:aop-beans:1.0">
+
+  <!--
+
+    Define the interceptor per-instance for now, each interceptor will
+    need access to the container. If this may be obtained via the
+    invocation, we may make the interceptor per-JVM
+  -->
+  <interceptor name="AsynchronousInterceptor"
+    class="org.jboss.ejb3.async.interceptor.AsynchronousInterceptor"
+    scope="PER_INSTANCE" />
+
+  <domain name="Asynchronous Container">
+
+    <!--
+      Bind to all invocations, let the interceptor sort out via metadata
+      whether it wants to take action
+    -->
+    <bind pointcut="execution(* *->*(..))">
+      <interceptor-ref name="AsynchronousInterceptor" />
+    </bind>
+
+  </domain>
+
+</aop>
\ No newline at end of file




More information about the jboss-cvs-commits mailing list