[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