moved async aspect to aspectj sub-package

This commit is contained in:
Juergen Hoeller 2010-10-13 21:06:38 +00:00
parent a6569a2930
commit 21d6883139
1 changed files with 178 additions and 161 deletions

View File

@ -1,161 +1,178 @@
package org.springframework.scheduling; /*
* Copyright 2002-2010 the original author or authors.
import java.util.concurrent.Callable; *
import java.util.concurrent.ExecutionException; * Licensed under the Apache License, Version 2.0 (the "License");
import java.util.concurrent.Future; * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
import junit.framework.Assert; *
* http://www.apache.org/licenses/LICENSE-2.0
import static junit.framework.Assert.*; *
* Unless required by applicable law or agreed to in writing, software
import org.junit.Before; * distributed under the License is distributed on an "AS IS" BASIS,
import org.junit.Test; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import org.springframework.core.task.SimpleAsyncTaskExecutor; * See the License for the specific language governing permissions and
import org.springframework.scheduling.annotation.Async; * limitations under the License.
import org.springframework.scheduling.annotation.AsyncResult; */
/** package org.springframework.scheduling.aspectj;
* Test for AnnotationDrivenAsynchronousExecutionAspect
* import java.util.concurrent.Callable;
* @author Ramnivas Laddad import java.util.concurrent.ExecutionException;
*/ import java.util.concurrent.Future;
public class AnnotationDrivenAsynchronousExecutionAspectTest {
private static final long WAIT_TIME = 1000; //milli seconds import junit.framework.Assert;
private CountingExecutor executor;
import static junit.framework.Assert.*;
@Before
public void setUp() { import org.junit.Before;
executor = new CountingExecutor(); import org.junit.Test;
AnnotationDrivenAsynchronousExecutionAspect.aspectOf().setExecutor(executor); import org.springframework.core.task.SimpleAsyncTaskExecutor;
} import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
@Test
public void asyncMethodGetsRoutedAsynchronously() { /**
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation(); * @author Ramnivas Laddad
obj.incrementAsync(); */
executor.waitForCompletion(); public class AnnotationDrivenAsynchronousExecutionAspectTests {
assertEquals(1, obj.counter);
assertEquals(1, executor.submitStartCounter); private static final long WAIT_TIME = 1000; //milli seconds
assertEquals(1, executor.submitCompleteCounter);
} private CountingExecutor executor;
@Test @Before
public void asyncMethodReturningFutureGetsRoutedAsynchronouslyAndReturnsAFuture() throws InterruptedException, ExecutionException { public void setUp() {
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation(); executor = new CountingExecutor();
Future<Integer> future = obj.incrementReturningAFuture(); AnnotationDrivenAsynchronousExecutionAspect.aspectOf().setExecutor(executor);
// No need to executor.waitForCompletion() as future.get() will have the same effect }
assertEquals(5, future.get().intValue());
assertEquals(1, obj.counter); @Test
assertEquals(1, executor.submitStartCounter); public void asyncMethodGetsRoutedAsynchronously() {
assertEquals(1, executor.submitCompleteCounter); ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation();
} obj.incrementAsync();
executor.waitForCompletion();
@Test assertEquals(1, obj.counter);
public void syncMethodGetsRoutedSynchronously() { assertEquals(1, executor.submitStartCounter);
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation(); assertEquals(1, executor.submitCompleteCounter);
obj.increment(); }
assertEquals(1, obj.counter);
assertEquals(0, executor.submitStartCounter); @Test
assertEquals(0, executor.submitCompleteCounter); public void asyncMethodReturningFutureGetsRoutedAsynchronouslyAndReturnsAFuture() throws InterruptedException, ExecutionException {
} ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation();
Future<Integer> future = obj.incrementReturningAFuture();
@Test // No need to executor.waitForCompletion() as future.get() will have the same effect
public void voidMethodInAsyncClassGetsRoutedAsynchronously() { assertEquals(5, future.get().intValue());
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation(); assertEquals(1, obj.counter);
obj.increment(); assertEquals(1, executor.submitStartCounter);
executor.waitForCompletion(); assertEquals(1, executor.submitCompleteCounter);
assertEquals(1, obj.counter); }
assertEquals(1, executor.submitStartCounter);
assertEquals(1, executor.submitCompleteCounter); @Test
} public void syncMethodGetsRoutedSynchronously() {
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation();
@Test obj.increment();
public void methodReturningFutureInAsyncClassGetsRoutedAsynchronouslyAndReturnsAFuture() throws InterruptedException, ExecutionException { assertEquals(1, obj.counter);
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation(); assertEquals(0, executor.submitStartCounter);
Future<Integer> future = obj.incrementReturningAFuture(); assertEquals(0, executor.submitCompleteCounter);
assertEquals(5, future.get().intValue()); }
assertEquals(1, obj.counter);
assertEquals(1, executor.submitStartCounter); @Test
assertEquals(1, executor.submitCompleteCounter); public void voidMethodInAsyncClassGetsRoutedAsynchronously() {
} ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation();
obj.increment();
@Test executor.waitForCompletion();
public void methodReturningNonVoidNonFutureInAsyncClassGetsRoutedSynchronously() { assertEquals(1, obj.counter);
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation(); assertEquals(1, executor.submitStartCounter);
int returnValue = obj.return5(); assertEquals(1, executor.submitCompleteCounter);
assertEquals(5, returnValue); }
assertEquals(0, executor.submitStartCounter);
assertEquals(0, executor.submitCompleteCounter); @Test
} public void methodReturningFutureInAsyncClassGetsRoutedAsynchronouslyAndReturnsAFuture() throws InterruptedException, ExecutionException {
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation();
@SuppressWarnings("serial") Future<Integer> future = obj.incrementReturningAFuture();
private static class CountingExecutor extends SimpleAsyncTaskExecutor { assertEquals(5, future.get().intValue());
int submitStartCounter; assertEquals(1, obj.counter);
int submitCompleteCounter; assertEquals(1, executor.submitStartCounter);
assertEquals(1, executor.submitCompleteCounter);
@Override }
public <T> Future<T> submit(Callable<T> task) {
submitStartCounter++; @Test
Future<T> future = super.submit(task); public void methodReturningNonVoidNonFutureInAsyncClassGetsRoutedSynchronously() {
submitCompleteCounter++; ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation();
synchronized (this) { int returnValue = obj.return5();
notifyAll(); assertEquals(5, returnValue);
} assertEquals(0, executor.submitStartCounter);
return future; assertEquals(0, executor.submitCompleteCounter);
} }
public synchronized void waitForCompletion() { @SuppressWarnings("serial")
try { private static class CountingExecutor extends SimpleAsyncTaskExecutor {
wait(WAIT_TIME); int submitStartCounter;
} catch (InterruptedException e) { int submitCompleteCounter;
Assert.fail("Didn't finish the async job in " + WAIT_TIME + " milliseconds");
} @Override
} public <T> Future<T> submit(Callable<T> task) {
} submitStartCounter++;
Future<T> future = super.submit(task);
static class ClassWithoutAsyncAnnotation { submitCompleteCounter++;
int counter; synchronized (this) {
notifyAll();
@Async public void incrementAsync() { }
counter++; return future;
} }
public void increment() { public synchronized void waitForCompletion() {
counter++; try {
} wait(WAIT_TIME);
} catch (InterruptedException e) {
@Async public Future<Integer> incrementReturningAFuture() { Assert.fail("Didn't finish the async job in " + WAIT_TIME + " milliseconds");
counter++; }
return new AsyncResult<Integer>(5); }
} }
// It should be an error to attach @Async to a method that returns a non-void static class ClassWithoutAsyncAnnotation {
// or non-Future. int counter;
// We need to keep this commented out, otherwise there will be a compile-time error.
// Please uncomment and re-comment this periodically to check that the compiler @Async public void incrementAsync() {
// produces an error message due to the 'declare error' statement counter++;
// in AnnotationDrivenAsynchronousExecutionAspect }
// @Async public int getInt() {
// return 0; public void increment() {
// } counter++;
} }
@Async @Async public Future<Integer> incrementReturningAFuture() {
static class ClassWithAsyncAnnotation { counter++;
int counter; return new AsyncResult<Integer>(5);
}
public void increment() {
counter++; // It should be an error to attach @Async to a method that returns a non-void
} // or non-Future.
// We need to keep this commented out, otherwise there will be a compile-time error.
// Manually check that there is a warning from the 'declare warning' statement in AnnotationDrivenAsynchronousExecutionAspect // Please uncomment and re-comment this periodically to check that the compiler
public int return5() { // produces an error message due to the 'declare error' statement
return 5; // in AnnotationDrivenAsynchronousExecutionAspect
} // @Async public int getInt() {
// return 0;
public Future<Integer> incrementReturningAFuture() { // }
counter++; }
return new AsyncResult<Integer>(5);
} @Async
} static class ClassWithAsyncAnnotation {
} int counter;
public void increment() {
counter++;
}
// Manually check that there is a warning from the 'declare warning' statement in AnnotationDrivenAsynchronousExecutionAspect
public int return5() {
return 5;
}
public Future<Integer> incrementReturningAFuture() {
counter++;
return new AsyncResult<Integer>(5);
}
}
}