moved async aspect to aspectj sub-package
This commit is contained in:
parent
a6569a2930
commit
21d6883139
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue