Convert CRLF (dos) to LF (unix)
Prior to this change, roughly 5% (~300 out of 6000+) of files under the source tree had CRLF line endings as opposed to the majority which have LF endings. This change normalizes these files to LF for consistency going forward. Command used: $ git ls-files | xargs file | grep CRLF | cut -d":" -f1 | xargs dos2unix Issue: SPR-5608
This commit is contained in:
@@ -1,54 +1,54 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.beans.factory.aspectj;
|
||||
|
||||
/**
|
||||
* Generic-based dependency injection aspect.
|
||||
* <p>
|
||||
* This aspect allows users to implement efficient, type-safe dependency injection without
|
||||
* the use of the @Configurable annotation.
|
||||
*
|
||||
* The subaspect of this aspect doesn't need to include any AOP constructs.
|
||||
* For example, here is a subaspect that configures the <code>PricingStrategyClient</code> objects.
|
||||
* <pre>
|
||||
* aspect PricingStrategyDependencyInjectionAspect
|
||||
* extends GenericInterfaceDrivenDependencyInjectionAspect<PricingStrategyClient> {
|
||||
* private PricingStrategy pricingStrategy;
|
||||
*
|
||||
* public void configure(PricingStrategyClient bean) {
|
||||
* bean.setPricingStrategy(pricingStrategy);
|
||||
* }
|
||||
*
|
||||
* public void setPricingStrategy(PricingStrategy pricingStrategy) {
|
||||
* this.pricingStrategy = pricingStrategy;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* @author Ramnivas Laddad
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public abstract aspect GenericInterfaceDrivenDependencyInjectionAspect<I> extends AbstractInterfaceDrivenDependencyInjectionAspect {
|
||||
declare parents: I implements ConfigurableObject;
|
||||
|
||||
public pointcut inConfigurableBean() : within(I+);
|
||||
|
||||
public final void configureBean(Object bean) {
|
||||
configure((I)bean);
|
||||
}
|
||||
|
||||
// Unfortunately, erasure used with generics won't allow to use the same named method
|
||||
protected abstract void configure(I bean);
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.beans.factory.aspectj;
|
||||
|
||||
/**
|
||||
* Generic-based dependency injection aspect.
|
||||
* <p>
|
||||
* This aspect allows users to implement efficient, type-safe dependency injection without
|
||||
* the use of the @Configurable annotation.
|
||||
*
|
||||
* The subaspect of this aspect doesn't need to include any AOP constructs.
|
||||
* For example, here is a subaspect that configures the <code>PricingStrategyClient</code> objects.
|
||||
* <pre>
|
||||
* aspect PricingStrategyDependencyInjectionAspect
|
||||
* extends GenericInterfaceDrivenDependencyInjectionAspect<PricingStrategyClient> {
|
||||
* private PricingStrategy pricingStrategy;
|
||||
*
|
||||
* public void configure(PricingStrategyClient bean) {
|
||||
* bean.setPricingStrategy(pricingStrategy);
|
||||
* }
|
||||
*
|
||||
* public void setPricingStrategy(PricingStrategy pricingStrategy) {
|
||||
* this.pricingStrategy = pricingStrategy;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* @author Ramnivas Laddad
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public abstract aspect GenericInterfaceDrivenDependencyInjectionAspect<I> extends AbstractInterfaceDrivenDependencyInjectionAspect {
|
||||
declare parents: I implements ConfigurableObject;
|
||||
|
||||
public pointcut inConfigurableBean() : within(I+);
|
||||
|
||||
public final void configureBean(Object bean) {
|
||||
configure((I)bean);
|
||||
}
|
||||
|
||||
// Unfortunately, erasure used with generics won't allow to use the same named method
|
||||
protected abstract void configure(I bean);
|
||||
}
|
||||
|
||||
@@ -1,73 +1,73 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aspectj.lang.annotation.SuppressAjWarnings;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.cache.interceptor.CacheAspectSupport;
|
||||
import org.springframework.cache.interceptor.CacheOperationSource;
|
||||
|
||||
/**
|
||||
* Abstract superaspect for AspectJ cache aspects. Concrete subaspects will implement the
|
||||
* {@link #cacheMethodExecution} pointcut using a strategy such as Java 5 annotations.
|
||||
*
|
||||
* <p>Suitable for use inside or outside the Spring IoC container. Set the
|
||||
* {@link #setCacheManager cacheManager} property appropriately, allowing use of any cache
|
||||
* implementation supported by Spring.
|
||||
*
|
||||
* <p><b>NB:</b> If a method implements an interface that is itself cache annotated, the
|
||||
* relevant Spring cache definition will <i>not</i> be resolved.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @since 3.1
|
||||
*/
|
||||
public abstract aspect AbstractCacheAspect extends CacheAspectSupport {
|
||||
|
||||
protected AbstractCacheAspect() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct object using the given caching metadata retrieval strategy.
|
||||
* @param cos {@link CacheOperationSource} implementation, retrieving Spring cache
|
||||
* metadata for each joinpoint.
|
||||
*/
|
||||
protected AbstractCacheAspect(CacheOperationSource... cos) {
|
||||
setCacheOperationSources(cos);
|
||||
}
|
||||
|
||||
@SuppressAjWarnings("adviceDidNotMatch")
|
||||
Object around(final Object cachedObject) : cacheMethodExecution(cachedObject) {
|
||||
MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
|
||||
Method method = methodSignature.getMethod();
|
||||
|
||||
Invoker aspectJInvoker = new Invoker() {
|
||||
public Object invoke() {
|
||||
return proceed(cachedObject);
|
||||
}
|
||||
};
|
||||
|
||||
return execute(aspectJInvoker, thisJoinPoint.getTarget(), method, thisJoinPoint.getArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Concrete subaspects must implement this pointcut, to identify cached methods.
|
||||
*/
|
||||
protected abstract pointcut cacheMethodExecution(Object cachedObject);
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aspectj.lang.annotation.SuppressAjWarnings;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.cache.interceptor.CacheAspectSupport;
|
||||
import org.springframework.cache.interceptor.CacheOperationSource;
|
||||
|
||||
/**
|
||||
* Abstract superaspect for AspectJ cache aspects. Concrete subaspects will implement the
|
||||
* {@link #cacheMethodExecution} pointcut using a strategy such as Java 5 annotations.
|
||||
*
|
||||
* <p>Suitable for use inside or outside the Spring IoC container. Set the
|
||||
* {@link #setCacheManager cacheManager} property appropriately, allowing use of any cache
|
||||
* implementation supported by Spring.
|
||||
*
|
||||
* <p><b>NB:</b> If a method implements an interface that is itself cache annotated, the
|
||||
* relevant Spring cache definition will <i>not</i> be resolved.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @since 3.1
|
||||
*/
|
||||
public abstract aspect AbstractCacheAspect extends CacheAspectSupport {
|
||||
|
||||
protected AbstractCacheAspect() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct object using the given caching metadata retrieval strategy.
|
||||
* @param cos {@link CacheOperationSource} implementation, retrieving Spring cache
|
||||
* metadata for each joinpoint.
|
||||
*/
|
||||
protected AbstractCacheAspect(CacheOperationSource... cos) {
|
||||
setCacheOperationSources(cos);
|
||||
}
|
||||
|
||||
@SuppressAjWarnings("adviceDidNotMatch")
|
||||
Object around(final Object cachedObject) : cacheMethodExecution(cachedObject) {
|
||||
MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
|
||||
Method method = methodSignature.getMethod();
|
||||
|
||||
Invoker aspectJInvoker = new Invoker() {
|
||||
public Object invoke() {
|
||||
return proceed(cachedObject);
|
||||
}
|
||||
};
|
||||
|
||||
return execute(aspectJInvoker, thisJoinPoint.getTarget(), method, thisJoinPoint.getArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Concrete subaspects must implement this pointcut, to identify cached methods.
|
||||
*/
|
||||
protected abstract pointcut cacheMethodExecution(Object cachedObject);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,116 +1,116 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.aspectj;
|
||||
|
||||
import org.springframework.cache.annotation.AnnotationCacheOperationSource;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
|
||||
/**
|
||||
* Concrete AspectJ cache aspect using Spring's @{@link Cacheable} annotation.
|
||||
*
|
||||
* <p>When using this aspect, you <i>must</i> annotate the implementation class (and/or
|
||||
* methods within that class), <i>not</i> the interface (if any) that the class
|
||||
* implements. AspectJ follows Java's rule that annotations on interfaces are <i>not</i>
|
||||
* inherited.
|
||||
*
|
||||
* <p>A {@code @Cacheable} annotation on a class specifies the default caching semantics
|
||||
* for the execution of any <b>public</b> operation in the class.
|
||||
*
|
||||
* <p>A {@code @Cacheable} annotation on a method within the class overrides the default
|
||||
* caching semantics given by the class annotation (if present). Any method may be
|
||||
* annotated (regardless of visibility). Annotating non-public methods directly is the
|
||||
* only way to get caching demarcation for the execution of such operations.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @since 3.1
|
||||
*/
|
||||
public aspect AnnotationCacheAspect extends AbstractCacheAspect {
|
||||
|
||||
public AnnotationCacheAspect() {
|
||||
super(new AnnotationCacheOperationSource(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches the execution of any public method in a type with the @{@link Cacheable}
|
||||
* annotation, or any subtype of a type with the {@code @Cacheable} annotation.
|
||||
*/
|
||||
private pointcut executionOfAnyPublicMethodInAtCacheableType() :
|
||||
execution(public * ((@Cacheable *)+).*(..)) && within(@Cacheable *);
|
||||
|
||||
/**
|
||||
* Matches the execution of any public method in a type with the @{@link CacheEvict}
|
||||
* annotation, or any subtype of a type with the {@code CacheEvict} annotation.
|
||||
*/
|
||||
private pointcut executionOfAnyPublicMethodInAtCacheEvictType() :
|
||||
execution(public * ((@CacheEvict *)+).*(..)) && within(@CacheEvict *);
|
||||
|
||||
/**
|
||||
* Matches the execution of any public method in a type with the @{@link CachePut}
|
||||
* annotation, or any subtype of a type with the {@code CachePut} annotation.
|
||||
*/
|
||||
private pointcut executionOfAnyPublicMethodInAtCachePutType() :
|
||||
execution(public * ((@CachePut *)+).*(..)) && within(@CachePut *);
|
||||
|
||||
/**
|
||||
* Matches the execution of any public method in a type with the @{@link Caching}
|
||||
* annotation, or any subtype of a type with the {@code Caching} annotation.
|
||||
*/
|
||||
private pointcut executionOfAnyPublicMethodInAtCachingType() :
|
||||
execution(public * ((@Caching *)+).*(..)) && within(@Caching *);
|
||||
|
||||
/**
|
||||
* Matches the execution of any method with the @{@link Cacheable} annotation.
|
||||
*/
|
||||
private pointcut executionOfCacheableMethod() :
|
||||
execution(@Cacheable * *(..));
|
||||
|
||||
/**
|
||||
* Matches the execution of any method with the @{@link CacheEvict} annotation.
|
||||
*/
|
||||
private pointcut executionOfCacheEvictMethod() :
|
||||
execution(@CacheEvict * *(..));
|
||||
|
||||
/**
|
||||
* Matches the execution of any method with the @{@link CachePut} annotation.
|
||||
*/
|
||||
private pointcut executionOfCachePutMethod() :
|
||||
execution(@CachePut * *(..));
|
||||
|
||||
/**
|
||||
* Matches the execution of any method with the @{@link Caching} annotation.
|
||||
*/
|
||||
private pointcut executionOfCachingMethod() :
|
||||
execution(@Caching * *(..));
|
||||
|
||||
/**
|
||||
* Definition of pointcut from super aspect - matched join points will have Spring
|
||||
* cache management applied.
|
||||
*/
|
||||
protected pointcut cacheMethodExecution(Object cachedObject) :
|
||||
(executionOfAnyPublicMethodInAtCacheableType()
|
||||
|| executionOfAnyPublicMethodInAtCacheEvictType()
|
||||
|| executionOfAnyPublicMethodInAtCachePutType()
|
||||
|| executionOfAnyPublicMethodInAtCachingType()
|
||||
|| executionOfCacheableMethod()
|
||||
|| executionOfCacheEvictMethod()
|
||||
|| executionOfCachePutMethod()
|
||||
|| executionOfCachingMethod())
|
||||
&& this(cachedObject);
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.aspectj;
|
||||
|
||||
import org.springframework.cache.annotation.AnnotationCacheOperationSource;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
|
||||
/**
|
||||
* Concrete AspectJ cache aspect using Spring's @{@link Cacheable} annotation.
|
||||
*
|
||||
* <p>When using this aspect, you <i>must</i> annotate the implementation class (and/or
|
||||
* methods within that class), <i>not</i> the interface (if any) that the class
|
||||
* implements. AspectJ follows Java's rule that annotations on interfaces are <i>not</i>
|
||||
* inherited.
|
||||
*
|
||||
* <p>A {@code @Cacheable} annotation on a class specifies the default caching semantics
|
||||
* for the execution of any <b>public</b> operation in the class.
|
||||
*
|
||||
* <p>A {@code @Cacheable} annotation on a method within the class overrides the default
|
||||
* caching semantics given by the class annotation (if present). Any method may be
|
||||
* annotated (regardless of visibility). Annotating non-public methods directly is the
|
||||
* only way to get caching demarcation for the execution of such operations.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @since 3.1
|
||||
*/
|
||||
public aspect AnnotationCacheAspect extends AbstractCacheAspect {
|
||||
|
||||
public AnnotationCacheAspect() {
|
||||
super(new AnnotationCacheOperationSource(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches the execution of any public method in a type with the @{@link Cacheable}
|
||||
* annotation, or any subtype of a type with the {@code @Cacheable} annotation.
|
||||
*/
|
||||
private pointcut executionOfAnyPublicMethodInAtCacheableType() :
|
||||
execution(public * ((@Cacheable *)+).*(..)) && within(@Cacheable *);
|
||||
|
||||
/**
|
||||
* Matches the execution of any public method in a type with the @{@link CacheEvict}
|
||||
* annotation, or any subtype of a type with the {@code CacheEvict} annotation.
|
||||
*/
|
||||
private pointcut executionOfAnyPublicMethodInAtCacheEvictType() :
|
||||
execution(public * ((@CacheEvict *)+).*(..)) && within(@CacheEvict *);
|
||||
|
||||
/**
|
||||
* Matches the execution of any public method in a type with the @{@link CachePut}
|
||||
* annotation, or any subtype of a type with the {@code CachePut} annotation.
|
||||
*/
|
||||
private pointcut executionOfAnyPublicMethodInAtCachePutType() :
|
||||
execution(public * ((@CachePut *)+).*(..)) && within(@CachePut *);
|
||||
|
||||
/**
|
||||
* Matches the execution of any public method in a type with the @{@link Caching}
|
||||
* annotation, or any subtype of a type with the {@code Caching} annotation.
|
||||
*/
|
||||
private pointcut executionOfAnyPublicMethodInAtCachingType() :
|
||||
execution(public * ((@Caching *)+).*(..)) && within(@Caching *);
|
||||
|
||||
/**
|
||||
* Matches the execution of any method with the @{@link Cacheable} annotation.
|
||||
*/
|
||||
private pointcut executionOfCacheableMethod() :
|
||||
execution(@Cacheable * *(..));
|
||||
|
||||
/**
|
||||
* Matches the execution of any method with the @{@link CacheEvict} annotation.
|
||||
*/
|
||||
private pointcut executionOfCacheEvictMethod() :
|
||||
execution(@CacheEvict * *(..));
|
||||
|
||||
/**
|
||||
* Matches the execution of any method with the @{@link CachePut} annotation.
|
||||
*/
|
||||
private pointcut executionOfCachePutMethod() :
|
||||
execution(@CachePut * *(..));
|
||||
|
||||
/**
|
||||
* Matches the execution of any method with the @{@link Caching} annotation.
|
||||
*/
|
||||
private pointcut executionOfCachingMethod() :
|
||||
execution(@Caching * *(..));
|
||||
|
||||
/**
|
||||
* Definition of pointcut from super aspect - matched join points will have Spring
|
||||
* cache management applied.
|
||||
*/
|
||||
protected pointcut cacheMethodExecution(Object cachedObject) :
|
||||
(executionOfAnyPublicMethodInAtCacheableType()
|
||||
|| executionOfAnyPublicMethodInAtCacheEvictType()
|
||||
|| executionOfAnyPublicMethodInAtCachePutType()
|
||||
|| executionOfAnyPublicMethodInAtCachingType()
|
||||
|| executionOfCacheableMethod()
|
||||
|| executionOfCacheEvictMethod()
|
||||
|| executionOfCachePutMethod()
|
||||
|| executionOfCachingMethod())
|
||||
&& this(cachedObject);
|
||||
}
|
||||
@@ -1,197 +1,197 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.mock.staticmock;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Abstract aspect to enable mocking of methods picked out by a pointcut.
|
||||
* Sub-aspects must define the mockStaticsTestMethod() pointcut to
|
||||
* indicate call stacks when mocking should be triggered, and the
|
||||
* methodToMock() pointcut to pick out a method invocations to mock.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
*/
|
||||
public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMethod()) {
|
||||
|
||||
protected abstract pointcut mockStaticsTestMethod();
|
||||
|
||||
protected abstract pointcut methodToMock();
|
||||
|
||||
private boolean recording = true;
|
||||
|
||||
static enum CallResponse { nothing, return_, throw_ };
|
||||
|
||||
// Represents a list of expected calls to static entity methods
|
||||
// Public to allow inserted code to access: is this normal??
|
||||
public class Expectations {
|
||||
|
||||
// Represents an expected call to a static entity method
|
||||
private class Call {
|
||||
private final String signature;
|
||||
private final Object[] args;
|
||||
|
||||
private Object responseObject; // return value or throwable
|
||||
private CallResponse responseType = CallResponse.nothing;
|
||||
|
||||
public Call(String name, Object[] args) {
|
||||
this.signature = name;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public boolean hasResponseSpecified() {
|
||||
return responseType != CallResponse.nothing;
|
||||
}
|
||||
|
||||
public void setReturnVal(Object retVal) {
|
||||
this.responseObject = retVal;
|
||||
responseType = CallResponse.return_;
|
||||
}
|
||||
|
||||
public void setThrow(Throwable throwable) {
|
||||
this.responseObject = throwable;
|
||||
responseType = CallResponse.throw_;
|
||||
}
|
||||
|
||||
public Object returnValue(String lastSig, Object[] args) {
|
||||
checkSignature(lastSig, args);
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
public Object throwException(String lastSig, Object[] args) {
|
||||
checkSignature(lastSig, args);
|
||||
throw (RuntimeException)responseObject;
|
||||
}
|
||||
|
||||
private void checkSignature(String lastSig, Object[] args) {
|
||||
if (!signature.equals(lastSig)) {
|
||||
throw new IllegalArgumentException("Signature doesn't match");
|
||||
}
|
||||
if (!Arrays.equals(this.args, args)) {
|
||||
throw new IllegalArgumentException("Arguments don't match");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<Call> calls = new LinkedList<Call>();
|
||||
|
||||
// Calls already verified
|
||||
private int verified;
|
||||
|
||||
public void verify() {
|
||||
if (verified != calls.size()) {
|
||||
throw new IllegalStateException("Expected " + calls.size()
|
||||
+ " calls, received " + verified);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the call and provide the expected return value
|
||||
* @param lastSig
|
||||
* @param args
|
||||
* @return
|
||||
*/
|
||||
public Object respond(String lastSig, Object[] args) {
|
||||
Call call = nextCall();
|
||||
CallResponse responseType = call.responseType;
|
||||
if (responseType == CallResponse.return_) {
|
||||
return call.returnValue(lastSig, args);
|
||||
} else if(responseType == CallResponse.throw_) {
|
||||
return (RuntimeException)call.throwException(lastSig, args);
|
||||
} else if(responseType == CallResponse.nothing) {
|
||||
// do nothing
|
||||
}
|
||||
throw new IllegalStateException("Behavior of " + call + " not specified");
|
||||
}
|
||||
|
||||
private Call nextCall() {
|
||||
if (verified > calls.size() - 1) {
|
||||
throw new IllegalStateException("Expected " + calls.size()
|
||||
+ " calls, received " + verified);
|
||||
}
|
||||
return calls.get(verified++);
|
||||
}
|
||||
|
||||
public void expectCall(String lastSig, Object lastArgs[]) {
|
||||
Call call = new Call(lastSig, lastArgs);
|
||||
calls.add(call);
|
||||
}
|
||||
|
||||
public boolean hasCalls() {
|
||||
return !calls.isEmpty();
|
||||
}
|
||||
|
||||
public void expectReturn(Object retVal) {
|
||||
Call call = calls.get(calls.size() - 1);
|
||||
if (call.hasResponseSpecified()) {
|
||||
throw new IllegalStateException("No static method invoked before setting return value");
|
||||
}
|
||||
call.setReturnVal(retVal);
|
||||
}
|
||||
|
||||
public void expectThrow(Throwable throwable) {
|
||||
Call call = calls.get(calls.size() - 1);
|
||||
if (call.hasResponseSpecified()) {
|
||||
throw new IllegalStateException("No static method invoked before setting throwable");
|
||||
}
|
||||
call.setThrow(throwable);
|
||||
}
|
||||
}
|
||||
|
||||
private Expectations expectations = new Expectations();
|
||||
|
||||
after() returning : mockStaticsTestMethod() {
|
||||
if (recording && (expectations.hasCalls())) {
|
||||
throw new IllegalStateException(
|
||||
"Calls recorded, yet playback state never reached: Create expectations then call "
|
||||
+ this.getClass().getSimpleName() + ".playback()");
|
||||
}
|
||||
expectations.verify();
|
||||
}
|
||||
|
||||
Object around() : methodToMock() && cflowbelow(mockStaticsTestMethod()) {
|
||||
if (recording) {
|
||||
expectations.expectCall(thisJoinPointStaticPart.toLongString(), thisJoinPoint.getArgs());
|
||||
// Return value doesn't matter
|
||||
return null;
|
||||
} else {
|
||||
return expectations.respond(thisJoinPointStaticPart.toLongString(), thisJoinPoint.getArgs());
|
||||
}
|
||||
}
|
||||
|
||||
public void expectReturnInternal(Object retVal) {
|
||||
if (!recording) {
|
||||
throw new IllegalStateException("Not recording: Cannot set return value");
|
||||
}
|
||||
expectations.expectReturn(retVal);
|
||||
}
|
||||
|
||||
public void expectThrowInternal(Throwable throwable) {
|
||||
if (!recording) {
|
||||
throw new IllegalStateException("Not recording: Cannot set throwable value");
|
||||
}
|
||||
expectations.expectThrow(throwable);
|
||||
}
|
||||
|
||||
public void playbackInternal() {
|
||||
recording = false;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.mock.staticmock;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Abstract aspect to enable mocking of methods picked out by a pointcut.
|
||||
* Sub-aspects must define the mockStaticsTestMethod() pointcut to
|
||||
* indicate call stacks when mocking should be triggered, and the
|
||||
* methodToMock() pointcut to pick out a method invocations to mock.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
*/
|
||||
public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMethod()) {
|
||||
|
||||
protected abstract pointcut mockStaticsTestMethod();
|
||||
|
||||
protected abstract pointcut methodToMock();
|
||||
|
||||
private boolean recording = true;
|
||||
|
||||
static enum CallResponse { nothing, return_, throw_ };
|
||||
|
||||
// Represents a list of expected calls to static entity methods
|
||||
// Public to allow inserted code to access: is this normal??
|
||||
public class Expectations {
|
||||
|
||||
// Represents an expected call to a static entity method
|
||||
private class Call {
|
||||
private final String signature;
|
||||
private final Object[] args;
|
||||
|
||||
private Object responseObject; // return value or throwable
|
||||
private CallResponse responseType = CallResponse.nothing;
|
||||
|
||||
public Call(String name, Object[] args) {
|
||||
this.signature = name;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public boolean hasResponseSpecified() {
|
||||
return responseType != CallResponse.nothing;
|
||||
}
|
||||
|
||||
public void setReturnVal(Object retVal) {
|
||||
this.responseObject = retVal;
|
||||
responseType = CallResponse.return_;
|
||||
}
|
||||
|
||||
public void setThrow(Throwable throwable) {
|
||||
this.responseObject = throwable;
|
||||
responseType = CallResponse.throw_;
|
||||
}
|
||||
|
||||
public Object returnValue(String lastSig, Object[] args) {
|
||||
checkSignature(lastSig, args);
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
public Object throwException(String lastSig, Object[] args) {
|
||||
checkSignature(lastSig, args);
|
||||
throw (RuntimeException)responseObject;
|
||||
}
|
||||
|
||||
private void checkSignature(String lastSig, Object[] args) {
|
||||
if (!signature.equals(lastSig)) {
|
||||
throw new IllegalArgumentException("Signature doesn't match");
|
||||
}
|
||||
if (!Arrays.equals(this.args, args)) {
|
||||
throw new IllegalArgumentException("Arguments don't match");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<Call> calls = new LinkedList<Call>();
|
||||
|
||||
// Calls already verified
|
||||
private int verified;
|
||||
|
||||
public void verify() {
|
||||
if (verified != calls.size()) {
|
||||
throw new IllegalStateException("Expected " + calls.size()
|
||||
+ " calls, received " + verified);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the call and provide the expected return value
|
||||
* @param lastSig
|
||||
* @param args
|
||||
* @return
|
||||
*/
|
||||
public Object respond(String lastSig, Object[] args) {
|
||||
Call call = nextCall();
|
||||
CallResponse responseType = call.responseType;
|
||||
if (responseType == CallResponse.return_) {
|
||||
return call.returnValue(lastSig, args);
|
||||
} else if(responseType == CallResponse.throw_) {
|
||||
return (RuntimeException)call.throwException(lastSig, args);
|
||||
} else if(responseType == CallResponse.nothing) {
|
||||
// do nothing
|
||||
}
|
||||
throw new IllegalStateException("Behavior of " + call + " not specified");
|
||||
}
|
||||
|
||||
private Call nextCall() {
|
||||
if (verified > calls.size() - 1) {
|
||||
throw new IllegalStateException("Expected " + calls.size()
|
||||
+ " calls, received " + verified);
|
||||
}
|
||||
return calls.get(verified++);
|
||||
}
|
||||
|
||||
public void expectCall(String lastSig, Object lastArgs[]) {
|
||||
Call call = new Call(lastSig, lastArgs);
|
||||
calls.add(call);
|
||||
}
|
||||
|
||||
public boolean hasCalls() {
|
||||
return !calls.isEmpty();
|
||||
}
|
||||
|
||||
public void expectReturn(Object retVal) {
|
||||
Call call = calls.get(calls.size() - 1);
|
||||
if (call.hasResponseSpecified()) {
|
||||
throw new IllegalStateException("No static method invoked before setting return value");
|
||||
}
|
||||
call.setReturnVal(retVal);
|
||||
}
|
||||
|
||||
public void expectThrow(Throwable throwable) {
|
||||
Call call = calls.get(calls.size() - 1);
|
||||
if (call.hasResponseSpecified()) {
|
||||
throw new IllegalStateException("No static method invoked before setting throwable");
|
||||
}
|
||||
call.setThrow(throwable);
|
||||
}
|
||||
}
|
||||
|
||||
private Expectations expectations = new Expectations();
|
||||
|
||||
after() returning : mockStaticsTestMethod() {
|
||||
if (recording && (expectations.hasCalls())) {
|
||||
throw new IllegalStateException(
|
||||
"Calls recorded, yet playback state never reached: Create expectations then call "
|
||||
+ this.getClass().getSimpleName() + ".playback()");
|
||||
}
|
||||
expectations.verify();
|
||||
}
|
||||
|
||||
Object around() : methodToMock() && cflowbelow(mockStaticsTestMethod()) {
|
||||
if (recording) {
|
||||
expectations.expectCall(thisJoinPointStaticPart.toLongString(), thisJoinPoint.getArgs());
|
||||
// Return value doesn't matter
|
||||
return null;
|
||||
} else {
|
||||
return expectations.respond(thisJoinPointStaticPart.toLongString(), thisJoinPoint.getArgs());
|
||||
}
|
||||
}
|
||||
|
||||
public void expectReturnInternal(Object retVal) {
|
||||
if (!recording) {
|
||||
throw new IllegalStateException("Not recording: Cannot set return value");
|
||||
}
|
||||
expectations.expectReturn(retVal);
|
||||
}
|
||||
|
||||
public void expectThrowInternal(Throwable throwable) {
|
||||
if (!recording) {
|
||||
throw new IllegalStateException("Not recording: Cannot set throwable value");
|
||||
}
|
||||
expectations.expectThrow(throwable);
|
||||
}
|
||||
|
||||
public void playbackInternal() {
|
||||
recording = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,68 +1,68 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.mock.staticmock;
|
||||
|
||||
/**
|
||||
* Annotation-based aspect to use in test build to enable mocking static methods
|
||||
* on JPA-annotated <code>@Entity</code> classes, as used by Roo for finders.
|
||||
*
|
||||
* <p>Mocking will occur in the call stack of any method in a class (typically a test class)
|
||||
* that is annotated with the @MockStaticEntityMethods annotation.
|
||||
*
|
||||
* <p>Also provides static methods to simplify the programming model for
|
||||
* entering playback mode and setting expected return values.
|
||||
*
|
||||
* <p>Usage:
|
||||
* <ol>
|
||||
* <li>Annotate a test class with @MockStaticEntityMethods.
|
||||
* <li>In each test method, AnnotationDrivenStaticEntityMockingControl will begin in recording mode.
|
||||
* Invoke static methods on Entity classes, with each recording-mode invocation
|
||||
* being followed by an invocation to the static expectReturn() or expectThrow()
|
||||
* method on AnnotationDrivenStaticEntityMockingControl.
|
||||
* <li>Invoke the static AnnotationDrivenStaticEntityMockingControl() method.
|
||||
* <li>Call the code you wish to test that uses the static methods. Verification will
|
||||
* occur automatically.
|
||||
* </ol>
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
* @see MockStaticEntityMethods
|
||||
*/
|
||||
public aspect AnnotationDrivenStaticEntityMockingControl extends AbstractMethodMockingControl {
|
||||
|
||||
/**
|
||||
* Stop recording mock calls and enter playback state
|
||||
*/
|
||||
public static void playback() {
|
||||
AnnotationDrivenStaticEntityMockingControl.aspectOf().playbackInternal();
|
||||
}
|
||||
|
||||
public static void expectReturn(Object retVal) {
|
||||
AnnotationDrivenStaticEntityMockingControl.aspectOf().expectReturnInternal(retVal);
|
||||
}
|
||||
|
||||
public static void expectThrow(Throwable throwable) {
|
||||
AnnotationDrivenStaticEntityMockingControl.aspectOf().expectThrowInternal(throwable);
|
||||
}
|
||||
|
||||
// Only matches directly annotated @Test methods, to allow methods in
|
||||
// @MockStatics classes to invoke each other without resetting the mocking environment
|
||||
protected pointcut mockStaticsTestMethod() : execution(public * (@MockStaticEntityMethods *).*(..));
|
||||
|
||||
protected pointcut methodToMock() : execution(public static * (@javax.persistence.Entity *).*(..));
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.mock.staticmock;
|
||||
|
||||
/**
|
||||
* Annotation-based aspect to use in test build to enable mocking static methods
|
||||
* on JPA-annotated <code>@Entity</code> classes, as used by Roo for finders.
|
||||
*
|
||||
* <p>Mocking will occur in the call stack of any method in a class (typically a test class)
|
||||
* that is annotated with the @MockStaticEntityMethods annotation.
|
||||
*
|
||||
* <p>Also provides static methods to simplify the programming model for
|
||||
* entering playback mode and setting expected return values.
|
||||
*
|
||||
* <p>Usage:
|
||||
* <ol>
|
||||
* <li>Annotate a test class with @MockStaticEntityMethods.
|
||||
* <li>In each test method, AnnotationDrivenStaticEntityMockingControl will begin in recording mode.
|
||||
* Invoke static methods on Entity classes, with each recording-mode invocation
|
||||
* being followed by an invocation to the static expectReturn() or expectThrow()
|
||||
* method on AnnotationDrivenStaticEntityMockingControl.
|
||||
* <li>Invoke the static AnnotationDrivenStaticEntityMockingControl() method.
|
||||
* <li>Call the code you wish to test that uses the static methods. Verification will
|
||||
* occur automatically.
|
||||
* </ol>
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
* @see MockStaticEntityMethods
|
||||
*/
|
||||
public aspect AnnotationDrivenStaticEntityMockingControl extends AbstractMethodMockingControl {
|
||||
|
||||
/**
|
||||
* Stop recording mock calls and enter playback state
|
||||
*/
|
||||
public static void playback() {
|
||||
AnnotationDrivenStaticEntityMockingControl.aspectOf().playbackInternal();
|
||||
}
|
||||
|
||||
public static void expectReturn(Object retVal) {
|
||||
AnnotationDrivenStaticEntityMockingControl.aspectOf().expectReturnInternal(retVal);
|
||||
}
|
||||
|
||||
public static void expectThrow(Throwable throwable) {
|
||||
AnnotationDrivenStaticEntityMockingControl.aspectOf().expectThrowInternal(throwable);
|
||||
}
|
||||
|
||||
// Only matches directly annotated @Test methods, to allow methods in
|
||||
// @MockStatics classes to invoke each other without resetting the mocking environment
|
||||
protected pointcut mockStaticsTestMethod() : execution(public * (@MockStaticEntityMethods *).*(..));
|
||||
|
||||
protected pointcut methodToMock() : execution(public static * (@javax.persistence.Entity *).*(..));
|
||||
|
||||
}
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.mock.staticmock;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation to indicate a test class for whose @Test methods
|
||||
* static methods on Entity classes should be mocked.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see AbstractMethodMockingControl
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface MockStaticEntityMethods {
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.mock.staticmock;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation to indicate a test class for whose @Test methods
|
||||
* static methods on Entity classes should be mocked.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see AbstractMethodMockingControl
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface MockStaticEntityMethods {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,75 +1,75 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.scheduling.aspectj;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.core.task.support.TaskExecutorAdapter;
|
||||
|
||||
/**
|
||||
* Abstract aspect that routes selected methods asynchronously.
|
||||
*
|
||||
* <p>This aspect needs to be injected with an implementation of
|
||||
* {@link Executor} to activate it for a specific thread pool.
|
||||
* Otherwise it will simply delegate all calls synchronously.
|
||||
*
|
||||
* @author Ramnivas Laddad
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0.5
|
||||
*/
|
||||
public abstract aspect AbstractAsyncExecutionAspect {
|
||||
|
||||
private AsyncTaskExecutor asyncExecutor;
|
||||
|
||||
public void setExecutor(Executor executor) {
|
||||
if (executor instanceof AsyncTaskExecutor) {
|
||||
this.asyncExecutor = (AsyncTaskExecutor) executor;
|
||||
}
|
||||
else {
|
||||
this.asyncExecutor = new TaskExecutorAdapter(executor);
|
||||
}
|
||||
}
|
||||
|
||||
Object around() : asyncMethod() {
|
||||
if (this.asyncExecutor == null) {
|
||||
return proceed();
|
||||
}
|
||||
Callable<Object> callable = new Callable<Object>() {
|
||||
public Object call() throws Exception {
|
||||
Object result = proceed();
|
||||
if (result instanceof Future) {
|
||||
return ((Future<?>) result).get();
|
||||
}
|
||||
return null;
|
||||
}};
|
||||
Future<?> result = this.asyncExecutor.submit(callable);
|
||||
if (Future.class.isAssignableFrom(((MethodSignature) thisJoinPointStaticPart.getSignature()).getReturnType())) {
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract pointcut asyncMethod();
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.scheduling.aspectj;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.core.task.support.TaskExecutorAdapter;
|
||||
|
||||
/**
|
||||
* Abstract aspect that routes selected methods asynchronously.
|
||||
*
|
||||
* <p>This aspect needs to be injected with an implementation of
|
||||
* {@link Executor} to activate it for a specific thread pool.
|
||||
* Otherwise it will simply delegate all calls synchronously.
|
||||
*
|
||||
* @author Ramnivas Laddad
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0.5
|
||||
*/
|
||||
public abstract aspect AbstractAsyncExecutionAspect {
|
||||
|
||||
private AsyncTaskExecutor asyncExecutor;
|
||||
|
||||
public void setExecutor(Executor executor) {
|
||||
if (executor instanceof AsyncTaskExecutor) {
|
||||
this.asyncExecutor = (AsyncTaskExecutor) executor;
|
||||
}
|
||||
else {
|
||||
this.asyncExecutor = new TaskExecutorAdapter(executor);
|
||||
}
|
||||
}
|
||||
|
||||
Object around() : asyncMethod() {
|
||||
if (this.asyncExecutor == null) {
|
||||
return proceed();
|
||||
}
|
||||
Callable<Object> callable = new Callable<Object>() {
|
||||
public Object call() throws Exception {
|
||||
Object result = proceed();
|
||||
if (result instanceof Future) {
|
||||
return ((Future<?>) result).get();
|
||||
}
|
||||
return null;
|
||||
}};
|
||||
Future<?> result = this.asyncExecutor.submit(callable);
|
||||
if (Future.class.isAssignableFrom(((MethodSignature) thisJoinPointStaticPart.getSignature()).getReturnType())) {
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract pointcut asyncMethod();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.scheduling.aspectj;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
/**
|
||||
* Aspect to route methods based on the {@link Async} annotation.
|
||||
*
|
||||
* <p>This aspect routes methods marked with the {@link Async} annotation
|
||||
* as well as methods in classes marked with the same. Any method expected
|
||||
* to be routed asynchronously must return either void, {@link Future},
|
||||
* or a subtype of {@link Future}. This aspect, therefore, will produce
|
||||
* a compile-time error for methods that violate this constraint on the return type.
|
||||
* If, however, a class marked with <code>@Async</code> contains a method that
|
||||
* violates this constraint, it produces only a warning.
|
||||
*
|
||||
* @author Ramnivas Laddad
|
||||
* @since 3.0.5
|
||||
*/
|
||||
public aspect AnnotationAsyncExecutionAspect extends AbstractAsyncExecutionAspect {
|
||||
|
||||
private pointcut asyncMarkedMethod()
|
||||
: execution(@Async (void || Future+) *(..));
|
||||
|
||||
private pointcut asyncTypeMarkedMethod()
|
||||
: execution((void || Future+) (@Async *).*(..));
|
||||
|
||||
public pointcut asyncMethod() : asyncMarkedMethod() || asyncTypeMarkedMethod();
|
||||
|
||||
declare error:
|
||||
execution(@Async !(void||Future) *(..)):
|
||||
"Only methods that return void or Future may have an @Async annotation";
|
||||
|
||||
declare warning:
|
||||
execution(!(void||Future) (@Async *).*(..)):
|
||||
"Methods in a class marked with @Async that do not return void or Future will be routed synchronously";
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.scheduling.aspectj;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
/**
|
||||
* Aspect to route methods based on the {@link Async} annotation.
|
||||
*
|
||||
* <p>This aspect routes methods marked with the {@link Async} annotation
|
||||
* as well as methods in classes marked with the same. Any method expected
|
||||
* to be routed asynchronously must return either void, {@link Future},
|
||||
* or a subtype of {@link Future}. This aspect, therefore, will produce
|
||||
* a compile-time error for methods that violate this constraint on the return type.
|
||||
* If, however, a class marked with <code>@Async</code> contains a method that
|
||||
* violates this constraint, it produces only a warning.
|
||||
*
|
||||
* @author Ramnivas Laddad
|
||||
* @since 3.0.5
|
||||
*/
|
||||
public aspect AnnotationAsyncExecutionAspect extends AbstractAsyncExecutionAspect {
|
||||
|
||||
private pointcut asyncMarkedMethod()
|
||||
: execution(@Async (void || Future+) *(..));
|
||||
|
||||
private pointcut asyncTypeMarkedMethod()
|
||||
: execution((void || Future+) (@Async *).*(..));
|
||||
|
||||
public pointcut asyncMethod() : asyncMarkedMethod() || asyncTypeMarkedMethod();
|
||||
|
||||
declare error:
|
||||
execution(@Async !(void||Future) *(..)):
|
||||
"Only methods that return void or Future may have an @Async annotation";
|
||||
|
||||
declare warning:
|
||||
execution(!(void||Future) (@Async *).*(..)):
|
||||
"Methods in a class marked with @Async that do not return void or Future will be routed synchronously";
|
||||
|
||||
}
|
||||
|
||||
@@ -1,93 +1,93 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aspectj.lang.annotation.SuppressAjWarnings;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.transaction.interceptor.TransactionAspectSupport;
|
||||
import org.springframework.transaction.interceptor.TransactionAttributeSource;
|
||||
|
||||
/**
|
||||
* Abstract superaspect for AspectJ transaction aspects. Concrete
|
||||
* subaspects will implement the <code>transactionalMethodExecution()</code>
|
||||
* pointcut using a strategy such as Java 5 annotations.
|
||||
*
|
||||
* <p>Suitable for use inside or outside the Spring IoC container.
|
||||
* Set the "transactionManager" property appropriately, allowing
|
||||
* use of any transaction implementation supported by Spring.
|
||||
*
|
||||
* <p><b>NB:</b> If a method implements an interface that is itself
|
||||
* transactionally annotated, the relevant Spring transaction attribute
|
||||
* will <i>not</i> be resolved. This behavior will vary from that of Spring AOP
|
||||
* if proxying an interface (but not when proxying a class). We recommend that
|
||||
* transaction annotations should be added to classes, rather than business
|
||||
* interfaces, as they are an implementation detail rather than a contract
|
||||
* specification validation.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract aspect AbstractTransactionAspect extends TransactionAspectSupport {
|
||||
|
||||
/**
|
||||
* Construct object using the given transaction metadata retrieval strategy.
|
||||
* @param tas TransactionAttributeSource implementation, retrieving Spring
|
||||
* transaction metadata for each joinpoint. Write the subclass to pass in null
|
||||
* if it's intended to be configured by Setter Injection.
|
||||
*/
|
||||
protected AbstractTransactionAspect(TransactionAttributeSource tas) {
|
||||
setTransactionAttributeSource(tas);
|
||||
}
|
||||
|
||||
@SuppressAjWarnings("adviceDidNotMatch")
|
||||
before(Object txObject) : transactionalMethodExecution(txObject) {
|
||||
MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
|
||||
Method method = methodSignature.getMethod();
|
||||
TransactionInfo txInfo = createTransactionIfNecessary(method, txObject.getClass());
|
||||
}
|
||||
|
||||
@SuppressAjWarnings("adviceDidNotMatch")
|
||||
after(Object txObject) throwing(Throwable t) : transactionalMethodExecution(txObject) {
|
||||
try {
|
||||
completeTransactionAfterThrowing(TransactionAspectSupport.currentTransactionInfo(), t);
|
||||
}
|
||||
catch (Throwable t2) {
|
||||
logger.error("Failed to close transaction after throwing in a transactional method", t2);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressAjWarnings("adviceDidNotMatch")
|
||||
after(Object txObject) returning() : transactionalMethodExecution(txObject) {
|
||||
commitTransactionAfterReturning(TransactionAspectSupport.currentTransactionInfo());
|
||||
}
|
||||
|
||||
@SuppressAjWarnings("adviceDidNotMatch")
|
||||
after(Object txObject) : transactionalMethodExecution(txObject) {
|
||||
cleanupTransactionInfo(TransactionAspectSupport.currentTransactionInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
* Concrete subaspects must implement this pointcut, to identify
|
||||
* transactional methods. For each selected joinpoint, TransactionMetadata
|
||||
* will be retrieved using Spring's TransactionAttributeSource interface.
|
||||
*/
|
||||
protected abstract pointcut transactionalMethodExecution(Object txObject);
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aspectj.lang.annotation.SuppressAjWarnings;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.transaction.interceptor.TransactionAspectSupport;
|
||||
import org.springframework.transaction.interceptor.TransactionAttributeSource;
|
||||
|
||||
/**
|
||||
* Abstract superaspect for AspectJ transaction aspects. Concrete
|
||||
* subaspects will implement the <code>transactionalMethodExecution()</code>
|
||||
* pointcut using a strategy such as Java 5 annotations.
|
||||
*
|
||||
* <p>Suitable for use inside or outside the Spring IoC container.
|
||||
* Set the "transactionManager" property appropriately, allowing
|
||||
* use of any transaction implementation supported by Spring.
|
||||
*
|
||||
* <p><b>NB:</b> If a method implements an interface that is itself
|
||||
* transactionally annotated, the relevant Spring transaction attribute
|
||||
* will <i>not</i> be resolved. This behavior will vary from that of Spring AOP
|
||||
* if proxying an interface (but not when proxying a class). We recommend that
|
||||
* transaction annotations should be added to classes, rather than business
|
||||
* interfaces, as they are an implementation detail rather than a contract
|
||||
* specification validation.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract aspect AbstractTransactionAspect extends TransactionAspectSupport {
|
||||
|
||||
/**
|
||||
* Construct object using the given transaction metadata retrieval strategy.
|
||||
* @param tas TransactionAttributeSource implementation, retrieving Spring
|
||||
* transaction metadata for each joinpoint. Write the subclass to pass in null
|
||||
* if it's intended to be configured by Setter Injection.
|
||||
*/
|
||||
protected AbstractTransactionAspect(TransactionAttributeSource tas) {
|
||||
setTransactionAttributeSource(tas);
|
||||
}
|
||||
|
||||
@SuppressAjWarnings("adviceDidNotMatch")
|
||||
before(Object txObject) : transactionalMethodExecution(txObject) {
|
||||
MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
|
||||
Method method = methodSignature.getMethod();
|
||||
TransactionInfo txInfo = createTransactionIfNecessary(method, txObject.getClass());
|
||||
}
|
||||
|
||||
@SuppressAjWarnings("adviceDidNotMatch")
|
||||
after(Object txObject) throwing(Throwable t) : transactionalMethodExecution(txObject) {
|
||||
try {
|
||||
completeTransactionAfterThrowing(TransactionAspectSupport.currentTransactionInfo(), t);
|
||||
}
|
||||
catch (Throwable t2) {
|
||||
logger.error("Failed to close transaction after throwing in a transactional method", t2);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressAjWarnings("adviceDidNotMatch")
|
||||
after(Object txObject) returning() : transactionalMethodExecution(txObject) {
|
||||
commitTransactionAfterReturning(TransactionAspectSupport.currentTransactionInfo());
|
||||
}
|
||||
|
||||
@SuppressAjWarnings("adviceDidNotMatch")
|
||||
after(Object txObject) : transactionalMethodExecution(txObject) {
|
||||
cleanupTransactionInfo(TransactionAspectSupport.currentTransactionInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
* Concrete subaspects must implement this pointcut, to identify
|
||||
* transactional methods. For each selected joinpoint, TransactionMetadata
|
||||
* will be retrieved using Spring's TransactionAttributeSource interface.
|
||||
*/
|
||||
protected abstract pointcut transactionalMethodExecution(Object txObject);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,75 +1,75 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.aspectj;
|
||||
|
||||
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Concrete AspectJ transaction aspect using Spring's @Transactional annotation.
|
||||
*
|
||||
* <p>When using this aspect, you <i>must</i> annotate the implementation class
|
||||
* (and/or methods within that class), <i>not</i> the interface (if any) that
|
||||
* the class implements. AspectJ follows Java's rule that annotations on
|
||||
* interfaces are <i>not</i> inherited.
|
||||
*
|
||||
* <p>An @Transactional annotation on a class specifies the default transaction
|
||||
* semantics for the execution of any <b>public</b> operation in the class.
|
||||
*
|
||||
* <p>An @Transactional annotation on a method within the class overrides the
|
||||
* default transaction semantics given by the class annotation (if present).
|
||||
* Any method may be annotated (regardless of visibility).
|
||||
* Annotating non-public methods directly is the only way
|
||||
* to get transaction demarcation for the execution of such operations.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
* @author Adrian Colyer
|
||||
* @since 2.0
|
||||
* @see org.springframework.transaction.annotation.Transactional
|
||||
*/
|
||||
public aspect AnnotationTransactionAspect extends AbstractTransactionAspect {
|
||||
|
||||
public AnnotationTransactionAspect() {
|
||||
super(new AnnotationTransactionAttributeSource(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches the execution of any public method in a type with the
|
||||
* Transactional annotation, or any subtype of a type with the
|
||||
* Transactional annotation.
|
||||
*/
|
||||
private pointcut executionOfAnyPublicMethodInAtTransactionalType() :
|
||||
execution(public * ((@Transactional *)+).*(..)) && within(@Transactional *);
|
||||
|
||||
/**
|
||||
* Matches the execution of any method with the
|
||||
* Transactional annotation.
|
||||
*/
|
||||
private pointcut executionOfTransactionalMethod() :
|
||||
execution(@Transactional * *(..));
|
||||
|
||||
/**
|
||||
* Definition of pointcut from super aspect - matched join points
|
||||
* will have Spring transaction management applied.
|
||||
*/
|
||||
protected pointcut transactionalMethodExecution(Object txObject) :
|
||||
(executionOfAnyPublicMethodInAtTransactionalType()
|
||||
|| executionOfTransactionalMethod() )
|
||||
&& this(txObject);
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.aspectj;
|
||||
|
||||
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Concrete AspectJ transaction aspect using Spring's @Transactional annotation.
|
||||
*
|
||||
* <p>When using this aspect, you <i>must</i> annotate the implementation class
|
||||
* (and/or methods within that class), <i>not</i> the interface (if any) that
|
||||
* the class implements. AspectJ follows Java's rule that annotations on
|
||||
* interfaces are <i>not</i> inherited.
|
||||
*
|
||||
* <p>An @Transactional annotation on a class specifies the default transaction
|
||||
* semantics for the execution of any <b>public</b> operation in the class.
|
||||
*
|
||||
* <p>An @Transactional annotation on a method within the class overrides the
|
||||
* default transaction semantics given by the class annotation (if present).
|
||||
* Any method may be annotated (regardless of visibility).
|
||||
* Annotating non-public methods directly is the only way
|
||||
* to get transaction demarcation for the execution of such operations.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
* @author Adrian Colyer
|
||||
* @since 2.0
|
||||
* @see org.springframework.transaction.annotation.Transactional
|
||||
*/
|
||||
public aspect AnnotationTransactionAspect extends AbstractTransactionAspect {
|
||||
|
||||
public AnnotationTransactionAspect() {
|
||||
super(new AnnotationTransactionAttributeSource(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches the execution of any public method in a type with the
|
||||
* Transactional annotation, or any subtype of a type with the
|
||||
* Transactional annotation.
|
||||
*/
|
||||
private pointcut executionOfAnyPublicMethodInAtTransactionalType() :
|
||||
execution(public * ((@Transactional *)+).*(..)) && within(@Transactional *);
|
||||
|
||||
/**
|
||||
* Matches the execution of any method with the
|
||||
* Transactional annotation.
|
||||
*/
|
||||
private pointcut executionOfTransactionalMethod() :
|
||||
execution(@Transactional * *(..));
|
||||
|
||||
/**
|
||||
* Definition of pointcut from super aspect - matched join points
|
||||
* will have Spring transaction management applied.
|
||||
*/
|
||||
protected pointcut transactionalMethodExecution(Object txObject) :
|
||||
(executionOfAnyPublicMethodInAtTransactionalType()
|
||||
|| executionOfTransactionalMethod() )
|
||||
&& this(txObject);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.autoproxy;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
*/
|
||||
public class AutoProxyWithCodeStyleAspectsTests extends TestCase {
|
||||
|
||||
public void testNoAutoproxyingOfAjcCompiledAspects() {
|
||||
new ClassPathXmlApplicationContext("org/springframework/aop/aspectj/autoproxy/ajcAutoproxyTests.xml");
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.autoproxy;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
*/
|
||||
public class AutoProxyWithCodeStyleAspectsTests extends TestCase {
|
||||
|
||||
public void testNoAutoproxyingOfAjcCompiledAspects() {
|
||||
new ClassPathXmlApplicationContext("org/springframework/aop/aspectj/autoproxy/ajcAutoproxyTests.xml");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.autoproxy;
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
*/
|
||||
public aspect CodeStyleAspect {
|
||||
|
||||
private String foo;
|
||||
|
||||
pointcut somePC() : call(* someMethod());
|
||||
|
||||
before() : somePC() {
|
||||
System.out.println("match");
|
||||
}
|
||||
|
||||
public void setFoo(String foo) {
|
||||
this.foo = foo;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.autoproxy;
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
*/
|
||||
public aspect CodeStyleAspect {
|
||||
|
||||
private String foo;
|
||||
|
||||
pointcut somePC() : call(* someMethod());
|
||||
|
||||
before() : somePC() {
|
||||
System.out.println("match");
|
||||
}
|
||||
|
||||
public void setFoo(String foo) {
|
||||
this.foo = foo;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans.factory.aspectj;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class SpringConfiguredWithAutoProxyingTests extends TestCase {
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
new ClassPathXmlApplicationContext("org/springframework/beans/factory/aspectj/springConfigured.xml");
|
||||
}
|
||||
|
||||
public void testSpringConfiguredAndAutoProxyUsedTogether() {
|
||||
; // set up is sufficient to trigger failure if this is going to fail...
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans.factory.aspectj;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class SpringConfiguredWithAutoProxyingTests extends TestCase {
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
new ClassPathXmlApplicationContext("org/springframework/beans/factory/aspectj/springConfigured.xml");
|
||||
}
|
||||
|
||||
public void testSpringConfiguredAndAutoProxyUsedTogether() {
|
||||
; // set up is sufficient to trigger failure if this is going to fail...
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,33 +1,33 @@
|
||||
/*
|
||||
* Copyright 2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.aspectj;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.GenericXmlApplicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class AspectJAnnotationTest extends AbstractAnnotationTest {
|
||||
|
||||
|
||||
@Override
|
||||
protected ApplicationContext getApplicationContext() {
|
||||
return new GenericXmlApplicationContext("/org/springframework/cache/config/annotation-cache-aspectj.xml");
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.aspectj;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.GenericXmlApplicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class AspectJAnnotationTest extends AbstractAnnotationTest {
|
||||
|
||||
|
||||
@Override
|
||||
protected ApplicationContext getApplicationContext() {
|
||||
return new GenericXmlApplicationContext("/org/springframework/cache/config/annotation-cache-aspectj.xml");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,138 +1,138 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.config;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
|
||||
/**
|
||||
* @author Costin Leau
|
||||
*/
|
||||
@Cacheable("default")
|
||||
public class AnnotatedClassCacheableService implements CacheableService<Object> {
|
||||
|
||||
private final AtomicLong counter = new AtomicLong();
|
||||
public static final AtomicLong nullInvocations = new AtomicLong();
|
||||
|
||||
public Object cache(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
public Object conditional(int field) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@CacheEvict("default")
|
||||
public void invalidate(Object arg1) {
|
||||
}
|
||||
|
||||
@CacheEvict("default")
|
||||
public void evictWithException(Object arg1) {
|
||||
throw new RuntimeException("exception thrown - evict should NOT occur");
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", allEntries = true)
|
||||
public void evictAll(Object arg1) {
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", beforeInvocation = true)
|
||||
public void evictEarly(Object arg1) {
|
||||
throw new RuntimeException("exception thrown - evict should still occur");
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", key = "#p0")
|
||||
public void evict(Object arg1, Object arg2) {
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", key = "#p0", beforeInvocation = true)
|
||||
public void invalidateEarly(Object arg1, Object arg2) {
|
||||
throw new RuntimeException("exception thrown - evict should still occur");
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", key = "#p0")
|
||||
public Object key(Object arg1, Object arg2) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", key = "#root.methodName + #root.caches[0].name")
|
||||
public Object name(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", key = "#root.methodName + #root.method.name + #root.targetClass + #root.target")
|
||||
public Object rootVars(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@CachePut("default")
|
||||
public Object update(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@CachePut(value = "default", condition = "#arg.equals(3)")
|
||||
public Object conditionalUpdate(Object arg) {
|
||||
return arg;
|
||||
}
|
||||
|
||||
public Object nullValue(Object arg1) {
|
||||
nullInvocations.incrementAndGet();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Number nullInvocations() {
|
||||
return nullInvocations.get();
|
||||
}
|
||||
|
||||
public Long throwChecked(Object arg1) throws Exception {
|
||||
throw new UnsupportedOperationException(arg1.toString());
|
||||
}
|
||||
|
||||
public Long throwUnchecked(Object arg1) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
// multi annotations
|
||||
|
||||
@Caching(cacheable = { @Cacheable("primary"), @Cacheable("secondary") })
|
||||
public Object multiCache(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(evict = { @CacheEvict("primary"), @CacheEvict(value = "secondary", key = "#p0") })
|
||||
public Object multiEvict(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(cacheable = { @Cacheable(value = "primary", key = "#root.methodName") }, evict = { @CacheEvict("secondary") })
|
||||
public Object multiCacheAndEvict(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(cacheable = { @Cacheable(value = "primary", condition = "#p0 == 3") }, evict = { @CacheEvict("secondary") })
|
||||
public Object multiConditionalCacheAndEvict(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(put = { @CachePut("primary"), @CachePut("secondary") })
|
||||
public Object multiUpdate(Object arg1) {
|
||||
return arg1;
|
||||
}
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.config;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
|
||||
/**
|
||||
* @author Costin Leau
|
||||
*/
|
||||
@Cacheable("default")
|
||||
public class AnnotatedClassCacheableService implements CacheableService<Object> {
|
||||
|
||||
private final AtomicLong counter = new AtomicLong();
|
||||
public static final AtomicLong nullInvocations = new AtomicLong();
|
||||
|
||||
public Object cache(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
public Object conditional(int field) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@CacheEvict("default")
|
||||
public void invalidate(Object arg1) {
|
||||
}
|
||||
|
||||
@CacheEvict("default")
|
||||
public void evictWithException(Object arg1) {
|
||||
throw new RuntimeException("exception thrown - evict should NOT occur");
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", allEntries = true)
|
||||
public void evictAll(Object arg1) {
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", beforeInvocation = true)
|
||||
public void evictEarly(Object arg1) {
|
||||
throw new RuntimeException("exception thrown - evict should still occur");
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", key = "#p0")
|
||||
public void evict(Object arg1, Object arg2) {
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", key = "#p0", beforeInvocation = true)
|
||||
public void invalidateEarly(Object arg1, Object arg2) {
|
||||
throw new RuntimeException("exception thrown - evict should still occur");
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", key = "#p0")
|
||||
public Object key(Object arg1, Object arg2) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", key = "#root.methodName + #root.caches[0].name")
|
||||
public Object name(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", key = "#root.methodName + #root.method.name + #root.targetClass + #root.target")
|
||||
public Object rootVars(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@CachePut("default")
|
||||
public Object update(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@CachePut(value = "default", condition = "#arg.equals(3)")
|
||||
public Object conditionalUpdate(Object arg) {
|
||||
return arg;
|
||||
}
|
||||
|
||||
public Object nullValue(Object arg1) {
|
||||
nullInvocations.incrementAndGet();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Number nullInvocations() {
|
||||
return nullInvocations.get();
|
||||
}
|
||||
|
||||
public Long throwChecked(Object arg1) throws Exception {
|
||||
throw new UnsupportedOperationException(arg1.toString());
|
||||
}
|
||||
|
||||
public Long throwUnchecked(Object arg1) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
// multi annotations
|
||||
|
||||
@Caching(cacheable = { @Cacheable("primary"), @Cacheable("secondary") })
|
||||
public Object multiCache(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(evict = { @CacheEvict("primary"), @CacheEvict(value = "secondary", key = "#p0") })
|
||||
public Object multiEvict(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(cacheable = { @Cacheable(value = "primary", key = "#root.methodName") }, evict = { @CacheEvict("secondary") })
|
||||
public Object multiCacheAndEvict(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(cacheable = { @Cacheable(value = "primary", condition = "#p0 == 3") }, evict = { @CacheEvict("secondary") })
|
||||
public Object multiConditionalCacheAndEvict(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(put = { @CachePut("primary"), @CachePut("secondary") })
|
||||
public Object multiUpdate(Object arg1) {
|
||||
return arg1;
|
||||
}
|
||||
}
|
||||
@@ -1,70 +1,70 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.config;
|
||||
|
||||
/**
|
||||
* Basic service interface.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public interface CacheableService<T> {
|
||||
|
||||
T cache(Object arg1);
|
||||
|
||||
void invalidate(Object arg1);
|
||||
|
||||
void evictEarly(Object arg1);
|
||||
|
||||
void evictAll(Object arg1);
|
||||
|
||||
void evictWithException(Object arg1);
|
||||
|
||||
void evict(Object arg1, Object arg2);
|
||||
|
||||
void invalidateEarly(Object arg1, Object arg2);
|
||||
|
||||
T conditional(int field);
|
||||
|
||||
T key(Object arg1, Object arg2);
|
||||
|
||||
T name(Object arg1);
|
||||
|
||||
T nullValue(Object arg1);
|
||||
|
||||
T update(Object arg1);
|
||||
|
||||
T conditionalUpdate(Object arg2);
|
||||
|
||||
Number nullInvocations();
|
||||
|
||||
T rootVars(Object arg1);
|
||||
|
||||
T throwChecked(Object arg1) throws Exception;
|
||||
|
||||
T throwUnchecked(Object arg1);
|
||||
|
||||
// multi annotations
|
||||
T multiCache(Object arg1);
|
||||
|
||||
T multiEvict(Object arg1);
|
||||
|
||||
T multiCacheAndEvict(Object arg1);
|
||||
|
||||
T multiConditionalCacheAndEvict(Object arg1);
|
||||
|
||||
T multiUpdate(Object arg1);
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.config;
|
||||
|
||||
/**
|
||||
* Basic service interface.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public interface CacheableService<T> {
|
||||
|
||||
T cache(Object arg1);
|
||||
|
||||
void invalidate(Object arg1);
|
||||
|
||||
void evictEarly(Object arg1);
|
||||
|
||||
void evictAll(Object arg1);
|
||||
|
||||
void evictWithException(Object arg1);
|
||||
|
||||
void evict(Object arg1, Object arg2);
|
||||
|
||||
void invalidateEarly(Object arg1, Object arg2);
|
||||
|
||||
T conditional(int field);
|
||||
|
||||
T key(Object arg1, Object arg2);
|
||||
|
||||
T name(Object arg1);
|
||||
|
||||
T nullValue(Object arg1);
|
||||
|
||||
T update(Object arg1);
|
||||
|
||||
T conditionalUpdate(Object arg2);
|
||||
|
||||
Number nullInvocations();
|
||||
|
||||
T rootVars(Object arg1);
|
||||
|
||||
T throwChecked(Object arg1) throws Exception;
|
||||
|
||||
T throwUnchecked(Object arg1);
|
||||
|
||||
// multi annotations
|
||||
T multiCache(Object arg1);
|
||||
|
||||
T multiEvict(Object arg1);
|
||||
|
||||
T multiCacheAndEvict(Object arg1);
|
||||
|
||||
T multiConditionalCacheAndEvict(Object arg1);
|
||||
|
||||
T multiUpdate(Object arg1);
|
||||
}
|
||||
@@ -1,144 +1,144 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.config;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
|
||||
/**
|
||||
* Simple cacheable service
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class DefaultCacheableService implements CacheableService<Long> {
|
||||
|
||||
private final AtomicLong counter = new AtomicLong();
|
||||
private final AtomicLong nullInvocations = new AtomicLong();
|
||||
|
||||
@Cacheable("default")
|
||||
public Long cache(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@CacheEvict("default")
|
||||
public void invalidate(Object arg1) {
|
||||
}
|
||||
|
||||
@CacheEvict("default")
|
||||
public void evictWithException(Object arg1) {
|
||||
throw new RuntimeException("exception thrown - evict should NOT occur");
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", allEntries = true)
|
||||
public void evictAll(Object arg1) {
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", beforeInvocation = true)
|
||||
public void evictEarly(Object arg1) {
|
||||
throw new RuntimeException("exception thrown - evict should still occur");
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", key = "#p0")
|
||||
public void evict(Object arg1, Object arg2) {
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", key = "#p0", beforeInvocation = true)
|
||||
public void invalidateEarly(Object arg1, Object arg2) {
|
||||
throw new RuntimeException("exception thrown - evict should still occur");
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", condition = "#classField == 3")
|
||||
public Long conditional(int classField) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", key = "#p0")
|
||||
public Long key(Object arg1, Object arg2) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", key = "#root.methodName")
|
||||
public Long name(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", key = "#root.methodName + #root.method.name + #root.targetClass + #root.target")
|
||||
public Long rootVars(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@CachePut("default")
|
||||
public Long update(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@CachePut(value = "default", condition = "#arg.equals(3)")
|
||||
public Long conditionalUpdate(Object arg) {
|
||||
return Long.valueOf(arg.toString());
|
||||
}
|
||||
|
||||
@Cacheable("default")
|
||||
public Long nullValue(Object arg1) {
|
||||
nullInvocations.incrementAndGet();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Number nullInvocations() {
|
||||
return nullInvocations.get();
|
||||
}
|
||||
|
||||
@Cacheable("default")
|
||||
public Long throwChecked(Object arg1) throws Exception {
|
||||
throw new Exception(arg1.toString());
|
||||
}
|
||||
|
||||
@Cacheable("default")
|
||||
public Long throwUnchecked(Object arg1) {
|
||||
throw new UnsupportedOperationException(arg1.toString());
|
||||
}
|
||||
|
||||
// multi annotations
|
||||
|
||||
@Caching(cacheable = { @Cacheable("primary"), @Cacheable("secondary") })
|
||||
public Long multiCache(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(evict = { @CacheEvict("primary"), @CacheEvict(value = "secondary", key = "#p0") })
|
||||
public Long multiEvict(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(cacheable = { @Cacheable(value = "primary", key = "#root.methodName") }, evict = { @CacheEvict("secondary") })
|
||||
public Long multiCacheAndEvict(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(cacheable = { @Cacheable(value = "primary", condition = "#p0 == 3") }, evict = { @CacheEvict("secondary") })
|
||||
public Long multiConditionalCacheAndEvict(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(put = { @CachePut("primary"), @CachePut("secondary") })
|
||||
public Long multiUpdate(Object arg1) {
|
||||
return Long.valueOf(arg1.toString());
|
||||
}
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.config;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
|
||||
/**
|
||||
* Simple cacheable service
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class DefaultCacheableService implements CacheableService<Long> {
|
||||
|
||||
private final AtomicLong counter = new AtomicLong();
|
||||
private final AtomicLong nullInvocations = new AtomicLong();
|
||||
|
||||
@Cacheable("default")
|
||||
public Long cache(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@CacheEvict("default")
|
||||
public void invalidate(Object arg1) {
|
||||
}
|
||||
|
||||
@CacheEvict("default")
|
||||
public void evictWithException(Object arg1) {
|
||||
throw new RuntimeException("exception thrown - evict should NOT occur");
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", allEntries = true)
|
||||
public void evictAll(Object arg1) {
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", beforeInvocation = true)
|
||||
public void evictEarly(Object arg1) {
|
||||
throw new RuntimeException("exception thrown - evict should still occur");
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", key = "#p0")
|
||||
public void evict(Object arg1, Object arg2) {
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", key = "#p0", beforeInvocation = true)
|
||||
public void invalidateEarly(Object arg1, Object arg2) {
|
||||
throw new RuntimeException("exception thrown - evict should still occur");
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", condition = "#classField == 3")
|
||||
public Long conditional(int classField) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", key = "#p0")
|
||||
public Long key(Object arg1, Object arg2) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", key = "#root.methodName")
|
||||
public Long name(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", key = "#root.methodName + #root.method.name + #root.targetClass + #root.target")
|
||||
public Long rootVars(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@CachePut("default")
|
||||
public Long update(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@CachePut(value = "default", condition = "#arg.equals(3)")
|
||||
public Long conditionalUpdate(Object arg) {
|
||||
return Long.valueOf(arg.toString());
|
||||
}
|
||||
|
||||
@Cacheable("default")
|
||||
public Long nullValue(Object arg1) {
|
||||
nullInvocations.incrementAndGet();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Number nullInvocations() {
|
||||
return nullInvocations.get();
|
||||
}
|
||||
|
||||
@Cacheable("default")
|
||||
public Long throwChecked(Object arg1) throws Exception {
|
||||
throw new Exception(arg1.toString());
|
||||
}
|
||||
|
||||
@Cacheable("default")
|
||||
public Long throwUnchecked(Object arg1) {
|
||||
throw new UnsupportedOperationException(arg1.toString());
|
||||
}
|
||||
|
||||
// multi annotations
|
||||
|
||||
@Caching(cacheable = { @Cacheable("primary"), @Cacheable("secondary") })
|
||||
public Long multiCache(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(evict = { @CacheEvict("primary"), @CacheEvict(value = "secondary", key = "#p0") })
|
||||
public Long multiEvict(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(cacheable = { @Cacheable(value = "primary", key = "#root.methodName") }, evict = { @CacheEvict("secondary") })
|
||||
public Long multiCacheAndEvict(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(cacheable = { @Cacheable(value = "primary", condition = "#p0 == 3") }, evict = { @CacheEvict("secondary") })
|
||||
public Long multiConditionalCacheAndEvict(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(put = { @CachePut("primary"), @CachePut("secondary") })
|
||||
public Long multiUpdate(Object arg1) {
|
||||
return Long.valueOf(arg1.toString());
|
||||
}
|
||||
}
|
||||
@@ -1,146 +1,146 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.mock.staticmock;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import static org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl.*;
|
||||
|
||||
|
||||
/**
|
||||
* Test for static entity mocking framework.
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
*
|
||||
*/
|
||||
@MockStaticEntityMethods
|
||||
@RunWith(JUnit4.class)
|
||||
public class AnnotationDrivenStaticEntityMockingControlTest {
|
||||
|
||||
@Test
|
||||
public void testNoArgIntReturn() {
|
||||
int expectedCount = 13;
|
||||
Person.countPeople();
|
||||
expectReturn(expectedCount);
|
||||
playback();
|
||||
Assert.assertEquals(expectedCount, Person.countPeople());
|
||||
}
|
||||
|
||||
@Test(expected=PersistenceException.class)
|
||||
public void testNoArgThrows() {
|
||||
Person.countPeople();
|
||||
expectThrow(new PersistenceException());
|
||||
playback();
|
||||
Person.countPeople();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArgMethodMatches() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
expectReturn(found);
|
||||
playback();
|
||||
Assert.assertEquals(found, Person.findPerson(id));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLongSeriesOfCalls() {
|
||||
long id1 = 13;
|
||||
long id2 = 24;
|
||||
Person found1 = new Person();
|
||||
Person.findPerson(id1);
|
||||
expectReturn(found1);
|
||||
Person found2 = new Person();
|
||||
Person.findPerson(id2);
|
||||
expectReturn(found2);
|
||||
Person.findPerson(id1);
|
||||
expectReturn(found1);
|
||||
Person.countPeople();
|
||||
expectReturn(0);
|
||||
playback();
|
||||
|
||||
Assert.assertEquals(found1, Person.findPerson(id1));
|
||||
Assert.assertEquals(found2, Person.findPerson(id2));
|
||||
Assert.assertEquals(found1, Person.findPerson(id1));
|
||||
Assert.assertEquals(0, Person.countPeople());
|
||||
}
|
||||
|
||||
// Note delegation is used when tests are invalid and should fail, as otherwise
|
||||
// the failure will occur on the verify() method in the aspect after
|
||||
// this method returns, failing the test case
|
||||
@Test
|
||||
public void testArgMethodNoMatchExpectReturn() {
|
||||
try {
|
||||
new Delegate().testArgMethodNoMatchExpectReturn();
|
||||
Assert.fail();
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testArgMethodNoMatchExpectThrow() {
|
||||
new Delegate().testArgMethodNoMatchExpectThrow();
|
||||
}
|
||||
|
||||
private void called(Person found, long id) {
|
||||
Assert.assertEquals(found, Person.findPerson(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReentrant() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
expectReturn(found);
|
||||
playback();
|
||||
called(found, id);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void testRejectUnexpectedCall() {
|
||||
new Delegate().rejectUnexpectedCall();
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void testFailTooFewCalls() {
|
||||
new Delegate().failTooFewCalls();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmpty() {
|
||||
// Test that verification check doesn't blow up if no replay() call happened
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void testDoesntEverReplay() {
|
||||
new Delegate().doesntEverReplay();
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void testDoesntEverSetReturn() {
|
||||
new Delegate().doesntEverSetReturn();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.mock.staticmock;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import static org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl.*;
|
||||
|
||||
|
||||
/**
|
||||
* Test for static entity mocking framework.
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
*
|
||||
*/
|
||||
@MockStaticEntityMethods
|
||||
@RunWith(JUnit4.class)
|
||||
public class AnnotationDrivenStaticEntityMockingControlTest {
|
||||
|
||||
@Test
|
||||
public void testNoArgIntReturn() {
|
||||
int expectedCount = 13;
|
||||
Person.countPeople();
|
||||
expectReturn(expectedCount);
|
||||
playback();
|
||||
Assert.assertEquals(expectedCount, Person.countPeople());
|
||||
}
|
||||
|
||||
@Test(expected=PersistenceException.class)
|
||||
public void testNoArgThrows() {
|
||||
Person.countPeople();
|
||||
expectThrow(new PersistenceException());
|
||||
playback();
|
||||
Person.countPeople();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArgMethodMatches() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
expectReturn(found);
|
||||
playback();
|
||||
Assert.assertEquals(found, Person.findPerson(id));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLongSeriesOfCalls() {
|
||||
long id1 = 13;
|
||||
long id2 = 24;
|
||||
Person found1 = new Person();
|
||||
Person.findPerson(id1);
|
||||
expectReturn(found1);
|
||||
Person found2 = new Person();
|
||||
Person.findPerson(id2);
|
||||
expectReturn(found2);
|
||||
Person.findPerson(id1);
|
||||
expectReturn(found1);
|
||||
Person.countPeople();
|
||||
expectReturn(0);
|
||||
playback();
|
||||
|
||||
Assert.assertEquals(found1, Person.findPerson(id1));
|
||||
Assert.assertEquals(found2, Person.findPerson(id2));
|
||||
Assert.assertEquals(found1, Person.findPerson(id1));
|
||||
Assert.assertEquals(0, Person.countPeople());
|
||||
}
|
||||
|
||||
// Note delegation is used when tests are invalid and should fail, as otherwise
|
||||
// the failure will occur on the verify() method in the aspect after
|
||||
// this method returns, failing the test case
|
||||
@Test
|
||||
public void testArgMethodNoMatchExpectReturn() {
|
||||
try {
|
||||
new Delegate().testArgMethodNoMatchExpectReturn();
|
||||
Assert.fail();
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testArgMethodNoMatchExpectThrow() {
|
||||
new Delegate().testArgMethodNoMatchExpectThrow();
|
||||
}
|
||||
|
||||
private void called(Person found, long id) {
|
||||
Assert.assertEquals(found, Person.findPerson(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReentrant() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
expectReturn(found);
|
||||
playback();
|
||||
called(found, id);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void testRejectUnexpectedCall() {
|
||||
new Delegate().rejectUnexpectedCall();
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void testFailTooFewCalls() {
|
||||
new Delegate().failTooFewCalls();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmpty() {
|
||||
// Test that verification check doesn't blow up if no replay() call happened
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void testDoesntEverReplay() {
|
||||
new Delegate().doesntEverReplay();
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void testDoesntEverSetReturn() {
|
||||
new Delegate().doesntEverSetReturn();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,92 +1,92 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.mock.staticmock;
|
||||
|
||||
import java.rmi.RemoteException;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl;
|
||||
import org.springframework.mock.staticmock.MockStaticEntityMethods;
|
||||
|
||||
//Used because verification failures occur after method returns,
|
||||
//so we can't test for them in the test case itself
|
||||
@MockStaticEntityMethods
|
||||
@Ignore // This isn't meant for direct testing; rather it is driven from AnnotationDrivenStaticEntityMockingControl
|
||||
public class Delegate {
|
||||
|
||||
@Test
|
||||
public void testArgMethodNoMatchExpectReturn() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
AnnotationDrivenStaticEntityMockingControl.expectReturn(found);
|
||||
AnnotationDrivenStaticEntityMockingControl.playback();
|
||||
Assert.assertEquals(found, Person.findPerson(id + 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArgMethodNoMatchExpectThrow() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
AnnotationDrivenStaticEntityMockingControl.expectThrow(new PersistenceException());
|
||||
AnnotationDrivenStaticEntityMockingControl.playback();
|
||||
Assert.assertEquals(found, Person.findPerson(id + 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failTooFewCalls() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
AnnotationDrivenStaticEntityMockingControl.expectReturn(found);
|
||||
Person.countPeople();
|
||||
AnnotationDrivenStaticEntityMockingControl.expectReturn(25);
|
||||
AnnotationDrivenStaticEntityMockingControl.playback();
|
||||
Assert.assertEquals(found, Person.findPerson(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesntEverReplay() {
|
||||
Person.countPeople();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesntEverSetReturn() {
|
||||
Person.countPeople();
|
||||
AnnotationDrivenStaticEntityMockingControl.playback();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rejectUnexpectedCall() {
|
||||
AnnotationDrivenStaticEntityMockingControl.playback();
|
||||
Person.countPeople();
|
||||
}
|
||||
|
||||
@Test(expected=RemoteException.class)
|
||||
public void testVerificationFailsEvenWhenTestFailsInExpectedManner() throws RemoteException {
|
||||
Person.countPeople();
|
||||
AnnotationDrivenStaticEntityMockingControl.playback();
|
||||
// No calls to allow verification failure
|
||||
throw new RemoteException();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.mock.staticmock;
|
||||
|
||||
import java.rmi.RemoteException;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl;
|
||||
import org.springframework.mock.staticmock.MockStaticEntityMethods;
|
||||
|
||||
//Used because verification failures occur after method returns,
|
||||
//so we can't test for them in the test case itself
|
||||
@MockStaticEntityMethods
|
||||
@Ignore // This isn't meant for direct testing; rather it is driven from AnnotationDrivenStaticEntityMockingControl
|
||||
public class Delegate {
|
||||
|
||||
@Test
|
||||
public void testArgMethodNoMatchExpectReturn() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
AnnotationDrivenStaticEntityMockingControl.expectReturn(found);
|
||||
AnnotationDrivenStaticEntityMockingControl.playback();
|
||||
Assert.assertEquals(found, Person.findPerson(id + 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArgMethodNoMatchExpectThrow() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
AnnotationDrivenStaticEntityMockingControl.expectThrow(new PersistenceException());
|
||||
AnnotationDrivenStaticEntityMockingControl.playback();
|
||||
Assert.assertEquals(found, Person.findPerson(id + 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failTooFewCalls() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
AnnotationDrivenStaticEntityMockingControl.expectReturn(found);
|
||||
Person.countPeople();
|
||||
AnnotationDrivenStaticEntityMockingControl.expectReturn(25);
|
||||
AnnotationDrivenStaticEntityMockingControl.playback();
|
||||
Assert.assertEquals(found, Person.findPerson(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesntEverReplay() {
|
||||
Person.countPeople();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesntEverSetReturn() {
|
||||
Person.countPeople();
|
||||
AnnotationDrivenStaticEntityMockingControl.playback();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rejectUnexpectedCall() {
|
||||
AnnotationDrivenStaticEntityMockingControl.playback();
|
||||
Person.countPeople();
|
||||
}
|
||||
|
||||
@Test(expected=RemoteException.class)
|
||||
public void testVerificationFailsEvenWhenTestFailsInExpectedManner() throws RemoteException {
|
||||
Person.countPeople();
|
||||
AnnotationDrivenStaticEntityMockingControl.playback();
|
||||
// No calls to allow verification failure
|
||||
throw new RemoteException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.mock.staticmock;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
@Entity
|
||||
public class Person {
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.mock.staticmock;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
@Entity
|
||||
public class Person {
|
||||
}
|
||||
|
||||
|
||||
@@ -1,100 +1,100 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.mock.staticmock;
|
||||
|
||||
privileged aspect Person_Roo_Entity {
|
||||
|
||||
@javax.persistence.PersistenceContext
|
||||
transient javax.persistence.EntityManager Person.entityManager;
|
||||
|
||||
@javax.persistence.Id
|
||||
@javax.persistence.GeneratedValue(strategy = javax.persistence.GenerationType.AUTO)
|
||||
@javax.persistence.Column(name = "id")
|
||||
private java.lang.Long Person.id;
|
||||
|
||||
@javax.persistence.Version
|
||||
@javax.persistence.Column(name = "version")
|
||||
private java.lang.Integer Person.version;
|
||||
|
||||
public java.lang.Long Person.getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void Person.setId(java.lang.Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public java.lang.Integer Person.getVersion() {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
public void Person.setVersion(java.lang.Integer version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@org.springframework.transaction.annotation.Transactional
|
||||
public void Person.persist() {
|
||||
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
|
||||
this.entityManager.persist(this);
|
||||
}
|
||||
|
||||
@org.springframework.transaction.annotation.Transactional
|
||||
public void Person.remove() {
|
||||
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
|
||||
this.entityManager.remove(this);
|
||||
}
|
||||
|
||||
@org.springframework.transaction.annotation.Transactional
|
||||
public void Person.flush() {
|
||||
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
|
||||
this.entityManager.flush();
|
||||
}
|
||||
|
||||
@org.springframework.transaction.annotation.Transactional
|
||||
public void Person.merge() {
|
||||
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
|
||||
Person merged = this.entityManager.merge(this);
|
||||
this.entityManager.flush();
|
||||
this.id = merged.getId();
|
||||
}
|
||||
|
||||
public static long Person.countPeople() {
|
||||
javax.persistence.EntityManager em = new Person().entityManager;
|
||||
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
|
||||
return (Long) em.createQuery("select count(o) from Person o").getSingleResult();
|
||||
}
|
||||
|
||||
public static java.util.List<Person> Person.findAllPeople() {
|
||||
javax.persistence.EntityManager em = new Person().entityManager;
|
||||
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
|
||||
return em.createQuery("select o from Person o").getResultList();
|
||||
}
|
||||
|
||||
public static Person Person.findPerson(java.lang.Long id) {
|
||||
if (id == null) throw new IllegalArgumentException("An identifier is required to retrieve an instance of Person");
|
||||
javax.persistence.EntityManager em = new Person().entityManager;
|
||||
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
|
||||
return em.find(Person.class, id);
|
||||
}
|
||||
|
||||
public static java.util.List<Person> Person.findPersonEntries(int firstResult, int maxResults) {
|
||||
javax.persistence.EntityManager em = new Person().entityManager;
|
||||
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
|
||||
return em.createQuery("select o from Person o").setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.mock.staticmock;
|
||||
|
||||
privileged aspect Person_Roo_Entity {
|
||||
|
||||
@javax.persistence.PersistenceContext
|
||||
transient javax.persistence.EntityManager Person.entityManager;
|
||||
|
||||
@javax.persistence.Id
|
||||
@javax.persistence.GeneratedValue(strategy = javax.persistence.GenerationType.AUTO)
|
||||
@javax.persistence.Column(name = "id")
|
||||
private java.lang.Long Person.id;
|
||||
|
||||
@javax.persistence.Version
|
||||
@javax.persistence.Column(name = "version")
|
||||
private java.lang.Integer Person.version;
|
||||
|
||||
public java.lang.Long Person.getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void Person.setId(java.lang.Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public java.lang.Integer Person.getVersion() {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
public void Person.setVersion(java.lang.Integer version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@org.springframework.transaction.annotation.Transactional
|
||||
public void Person.persist() {
|
||||
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
|
||||
this.entityManager.persist(this);
|
||||
}
|
||||
|
||||
@org.springframework.transaction.annotation.Transactional
|
||||
public void Person.remove() {
|
||||
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
|
||||
this.entityManager.remove(this);
|
||||
}
|
||||
|
||||
@org.springframework.transaction.annotation.Transactional
|
||||
public void Person.flush() {
|
||||
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
|
||||
this.entityManager.flush();
|
||||
}
|
||||
|
||||
@org.springframework.transaction.annotation.Transactional
|
||||
public void Person.merge() {
|
||||
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
|
||||
Person merged = this.entityManager.merge(this);
|
||||
this.entityManager.flush();
|
||||
this.id = merged.getId();
|
||||
}
|
||||
|
||||
public static long Person.countPeople() {
|
||||
javax.persistence.EntityManager em = new Person().entityManager;
|
||||
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
|
||||
return (Long) em.createQuery("select count(o) from Person o").getSingleResult();
|
||||
}
|
||||
|
||||
public static java.util.List<Person> Person.findAllPeople() {
|
||||
javax.persistence.EntityManager em = new Person().entityManager;
|
||||
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
|
||||
return em.createQuery("select o from Person o").getResultList();
|
||||
}
|
||||
|
||||
public static Person Person.findPerson(java.lang.Long id) {
|
||||
if (id == null) throw new IllegalArgumentException("An identifier is required to retrieve an instance of Person");
|
||||
javax.persistence.EntityManager em = new Person().entityManager;
|
||||
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
|
||||
return em.find(Person.class, id);
|
||||
}
|
||||
|
||||
public static java.util.List<Person> Person.findPersonEntries(int firstResult, int maxResults) {
|
||||
javax.persistence.EntityManager em = new Person().entityManager;
|
||||
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
|
||||
return em.createQuery("select o from Person o").setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,178 +1,178 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.scheduling.aspectj;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import static junit.framework.Assert.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.AsyncResult;
|
||||
|
||||
/**
|
||||
* @author Ramnivas Laddad
|
||||
*/
|
||||
public class AnnotationAsyncExecutionAspectTests {
|
||||
|
||||
private static final long WAIT_TIME = 1000; //milli seconds
|
||||
|
||||
private CountingExecutor executor;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
executor = new CountingExecutor();
|
||||
AnnotationAsyncExecutionAspect.aspectOf().setExecutor(executor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asyncMethodGetsRoutedAsynchronously() {
|
||||
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation();
|
||||
obj.incrementAsync();
|
||||
executor.waitForCompletion();
|
||||
assertEquals(1, obj.counter);
|
||||
assertEquals(1, executor.submitStartCounter);
|
||||
assertEquals(1, executor.submitCompleteCounter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asyncMethodReturningFutureGetsRoutedAsynchronouslyAndReturnsAFuture() throws InterruptedException, ExecutionException {
|
||||
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation();
|
||||
Future<Integer> future = obj.incrementReturningAFuture();
|
||||
// No need to executor.waitForCompletion() as future.get() will have the same effect
|
||||
assertEquals(5, future.get().intValue());
|
||||
assertEquals(1, obj.counter);
|
||||
assertEquals(1, executor.submitStartCounter);
|
||||
assertEquals(1, executor.submitCompleteCounter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void syncMethodGetsRoutedSynchronously() {
|
||||
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation();
|
||||
obj.increment();
|
||||
assertEquals(1, obj.counter);
|
||||
assertEquals(0, executor.submitStartCounter);
|
||||
assertEquals(0, executor.submitCompleteCounter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void voidMethodInAsyncClassGetsRoutedAsynchronously() {
|
||||
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation();
|
||||
obj.increment();
|
||||
executor.waitForCompletion();
|
||||
assertEquals(1, obj.counter);
|
||||
assertEquals(1, executor.submitStartCounter);
|
||||
assertEquals(1, executor.submitCompleteCounter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void methodReturningFutureInAsyncClassGetsRoutedAsynchronouslyAndReturnsAFuture() throws InterruptedException, ExecutionException {
|
||||
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation();
|
||||
Future<Integer> future = obj.incrementReturningAFuture();
|
||||
assertEquals(5, future.get().intValue());
|
||||
assertEquals(1, obj.counter);
|
||||
assertEquals(1, executor.submitStartCounter);
|
||||
assertEquals(1, executor.submitCompleteCounter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void methodReturningNonVoidNonFutureInAsyncClassGetsRoutedSynchronously() {
|
||||
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation();
|
||||
int returnValue = obj.return5();
|
||||
assertEquals(5, returnValue);
|
||||
assertEquals(0, executor.submitStartCounter);
|
||||
assertEquals(0, executor.submitCompleteCounter);
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class CountingExecutor extends SimpleAsyncTaskExecutor {
|
||||
int submitStartCounter;
|
||||
int submitCompleteCounter;
|
||||
|
||||
@Override
|
||||
public <T> Future<T> submit(Callable<T> task) {
|
||||
submitStartCounter++;
|
||||
Future<T> future = super.submit(task);
|
||||
submitCompleteCounter++;
|
||||
synchronized (this) {
|
||||
notifyAll();
|
||||
}
|
||||
return future;
|
||||
}
|
||||
|
||||
public synchronized void waitForCompletion() {
|
||||
try {
|
||||
wait(WAIT_TIME);
|
||||
} catch (InterruptedException e) {
|
||||
Assert.fail("Didn't finish the async job in " + WAIT_TIME + " milliseconds");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class ClassWithoutAsyncAnnotation {
|
||||
int counter;
|
||||
|
||||
@Async public void incrementAsync() {
|
||||
counter++;
|
||||
}
|
||||
|
||||
public void increment() {
|
||||
counter++;
|
||||
}
|
||||
|
||||
@Async public Future<Integer> incrementReturningAFuture() {
|
||||
counter++;
|
||||
return new AsyncResult<Integer>(5);
|
||||
}
|
||||
|
||||
// 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.
|
||||
// Please uncomment and re-comment this periodically to check that the compiler
|
||||
// produces an error message due to the 'declare error' statement
|
||||
// in AnnotationAsyncExecutionAspect
|
||||
// @Async public int getInt() {
|
||||
// return 0;
|
||||
// }
|
||||
}
|
||||
|
||||
@Async
|
||||
static class ClassWithAsyncAnnotation {
|
||||
int counter;
|
||||
|
||||
public void increment() {
|
||||
counter++;
|
||||
}
|
||||
|
||||
// Manually check that there is a warning from the 'declare warning' statement in AnnotationAsynchExecutionAspect
|
||||
public int return5() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
public Future<Integer> incrementReturningAFuture() {
|
||||
counter++;
|
||||
return new AsyncResult<Integer>(5);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.scheduling.aspectj;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import static junit.framework.Assert.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.AsyncResult;
|
||||
|
||||
/**
|
||||
* @author Ramnivas Laddad
|
||||
*/
|
||||
public class AnnotationAsyncExecutionAspectTests {
|
||||
|
||||
private static final long WAIT_TIME = 1000; //milli seconds
|
||||
|
||||
private CountingExecutor executor;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
executor = new CountingExecutor();
|
||||
AnnotationAsyncExecutionAspect.aspectOf().setExecutor(executor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asyncMethodGetsRoutedAsynchronously() {
|
||||
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation();
|
||||
obj.incrementAsync();
|
||||
executor.waitForCompletion();
|
||||
assertEquals(1, obj.counter);
|
||||
assertEquals(1, executor.submitStartCounter);
|
||||
assertEquals(1, executor.submitCompleteCounter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asyncMethodReturningFutureGetsRoutedAsynchronouslyAndReturnsAFuture() throws InterruptedException, ExecutionException {
|
||||
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation();
|
||||
Future<Integer> future = obj.incrementReturningAFuture();
|
||||
// No need to executor.waitForCompletion() as future.get() will have the same effect
|
||||
assertEquals(5, future.get().intValue());
|
||||
assertEquals(1, obj.counter);
|
||||
assertEquals(1, executor.submitStartCounter);
|
||||
assertEquals(1, executor.submitCompleteCounter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void syncMethodGetsRoutedSynchronously() {
|
||||
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation();
|
||||
obj.increment();
|
||||
assertEquals(1, obj.counter);
|
||||
assertEquals(0, executor.submitStartCounter);
|
||||
assertEquals(0, executor.submitCompleteCounter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void voidMethodInAsyncClassGetsRoutedAsynchronously() {
|
||||
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation();
|
||||
obj.increment();
|
||||
executor.waitForCompletion();
|
||||
assertEquals(1, obj.counter);
|
||||
assertEquals(1, executor.submitStartCounter);
|
||||
assertEquals(1, executor.submitCompleteCounter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void methodReturningFutureInAsyncClassGetsRoutedAsynchronouslyAndReturnsAFuture() throws InterruptedException, ExecutionException {
|
||||
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation();
|
||||
Future<Integer> future = obj.incrementReturningAFuture();
|
||||
assertEquals(5, future.get().intValue());
|
||||
assertEquals(1, obj.counter);
|
||||
assertEquals(1, executor.submitStartCounter);
|
||||
assertEquals(1, executor.submitCompleteCounter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void methodReturningNonVoidNonFutureInAsyncClassGetsRoutedSynchronously() {
|
||||
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation();
|
||||
int returnValue = obj.return5();
|
||||
assertEquals(5, returnValue);
|
||||
assertEquals(0, executor.submitStartCounter);
|
||||
assertEquals(0, executor.submitCompleteCounter);
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class CountingExecutor extends SimpleAsyncTaskExecutor {
|
||||
int submitStartCounter;
|
||||
int submitCompleteCounter;
|
||||
|
||||
@Override
|
||||
public <T> Future<T> submit(Callable<T> task) {
|
||||
submitStartCounter++;
|
||||
Future<T> future = super.submit(task);
|
||||
submitCompleteCounter++;
|
||||
synchronized (this) {
|
||||
notifyAll();
|
||||
}
|
||||
return future;
|
||||
}
|
||||
|
||||
public synchronized void waitForCompletion() {
|
||||
try {
|
||||
wait(WAIT_TIME);
|
||||
} catch (InterruptedException e) {
|
||||
Assert.fail("Didn't finish the async job in " + WAIT_TIME + " milliseconds");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class ClassWithoutAsyncAnnotation {
|
||||
int counter;
|
||||
|
||||
@Async public void incrementAsync() {
|
||||
counter++;
|
||||
}
|
||||
|
||||
public void increment() {
|
||||
counter++;
|
||||
}
|
||||
|
||||
@Async public Future<Integer> incrementReturningAFuture() {
|
||||
counter++;
|
||||
return new AsyncResult<Integer>(5);
|
||||
}
|
||||
|
||||
// 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.
|
||||
// Please uncomment and re-comment this periodically to check that the compiler
|
||||
// produces an error message due to the 'declare error' statement
|
||||
// in AnnotationAsyncExecutionAspect
|
||||
// @Async public int getInt() {
|
||||
// return 0;
|
||||
// }
|
||||
}
|
||||
|
||||
@Async
|
||||
static class ClassWithAsyncAnnotation {
|
||||
int counter;
|
||||
|
||||
public void increment() {
|
||||
counter++;
|
||||
}
|
||||
|
||||
// Manually check that there is a warning from the 'declare warning' statement in AnnotationAsynchExecutionAspect
|
||||
public int return5() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
public Future<Integer> incrementReturningAFuture() {
|
||||
counter++;
|
||||
return new AsyncResult<Integer>(5);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Created on 11 Sep 2006 by Adrian Colyer
|
||||
*/
|
||||
package org.springframework.transaction.aspectj;
|
||||
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ClassWithPrivateAnnotatedMember {
|
||||
|
||||
public void doSomething() {
|
||||
doInTransaction();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
private void doInTransaction() {}
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Created on 11 Sep 2006 by Adrian Colyer
|
||||
*/
|
||||
package org.springframework.transaction.aspectj;
|
||||
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ClassWithPrivateAnnotatedMember {
|
||||
|
||||
public void doSomething() {
|
||||
doInTransaction();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
private void doInTransaction() {}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Created on 11 Sep 2006 by Adrian Colyer
|
||||
*/
|
||||
package org.springframework.transaction.aspectj;
|
||||
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ClassWithProtectedAnnotatedMember {
|
||||
|
||||
public void doSomething() {
|
||||
doInTransaction();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
protected void doInTransaction() {}
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Created on 11 Sep 2006 by Adrian Colyer
|
||||
*/
|
||||
package org.springframework.transaction.aspectj;
|
||||
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ClassWithProtectedAnnotatedMember {
|
||||
|
||||
public void doSomething() {
|
||||
doInTransaction();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
protected void doInTransaction() {}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package org.springframework.transaction.aspectj;
|
||||
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Transactional
|
||||
public interface ITransactional {
|
||||
|
||||
Object echo(Throwable t) throws Throwable;
|
||||
|
||||
}
|
||||
package org.springframework.transaction.aspectj;
|
||||
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Transactional
|
||||
public interface ITransactional {
|
||||
|
||||
Object echo(Throwable t) throws Throwable;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
package org.springframework.transaction.aspectj;
|
||||
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
public class MethodAnnotationOnClassWithNoInterface {
|
||||
|
||||
@Transactional(rollbackFor=InterruptedException.class)
|
||||
public Object echo(Throwable t) throws Throwable {
|
||||
if (t != null) {
|
||||
throw t;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
public void noTransactionAttribute() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
package org.springframework.transaction.aspectj;
|
||||
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
public class MethodAnnotationOnClassWithNoInterface {
|
||||
|
||||
@Transactional(rollbackFor=InterruptedException.class)
|
||||
public Object echo(Throwable t) throws Throwable {
|
||||
if (t != null) {
|
||||
throw t;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
public void noTransactionAttribute() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,261 +1,261 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
|
||||
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
|
||||
import org.springframework.transaction.CallCountingTransactionManager;
|
||||
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
|
||||
import org.springframework.transaction.interceptor.TransactionAspectSupport;
|
||||
import org.springframework.transaction.interceptor.TransactionAttribute;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
*/
|
||||
public class TransactionAspectTests extends AbstractDependencyInjectionSpringContextTests {
|
||||
|
||||
private TransactionAspectSupport transactionAspect;
|
||||
|
||||
private CallCountingTransactionManager txManager;
|
||||
|
||||
private TransactionalAnnotationOnlyOnClassWithNoInterface annotationOnlyOnClassWithNoInterface;
|
||||
|
||||
private ClassWithProtectedAnnotatedMember beanWithAnnotatedProtectedMethod;
|
||||
|
||||
private ClassWithPrivateAnnotatedMember beanWithAnnotatedPrivateMethod;
|
||||
|
||||
private MethodAnnotationOnClassWithNoInterface methodAnnotationOnly = new MethodAnnotationOnClassWithNoInterface();
|
||||
|
||||
|
||||
public void setAnnotationOnlyOnClassWithNoInterface(
|
||||
TransactionalAnnotationOnlyOnClassWithNoInterface annotationOnlyOnClassWithNoInterface) {
|
||||
this.annotationOnlyOnClassWithNoInterface = annotationOnlyOnClassWithNoInterface;
|
||||
}
|
||||
|
||||
public void setClassWithAnnotatedProtectedMethod(ClassWithProtectedAnnotatedMember aBean) {
|
||||
this.beanWithAnnotatedProtectedMethod = aBean;
|
||||
}
|
||||
|
||||
public void setClassWithAnnotatedPrivateMethod(ClassWithPrivateAnnotatedMember aBean) {
|
||||
this.beanWithAnnotatedPrivateMethod = aBean;
|
||||
}
|
||||
|
||||
public void setTransactionAspect(TransactionAspectSupport transactionAspect) {
|
||||
this.transactionAspect = transactionAspect;
|
||||
this.txManager = (CallCountingTransactionManager) transactionAspect.getTransactionManager();
|
||||
}
|
||||
|
||||
public TransactionAspectSupport getTransactionAspect() {
|
||||
return this.transactionAspect;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getConfigPath() {
|
||||
return "TransactionAspectTests-context.xml";
|
||||
}
|
||||
|
||||
|
||||
public void testCommitOnAnnotatedClass() throws Throwable {
|
||||
txManager.clear();
|
||||
assertEquals(0, txManager.begun);
|
||||
annotationOnlyOnClassWithNoInterface.echo(null);
|
||||
assertEquals(1, txManager.commits);
|
||||
}
|
||||
|
||||
public void testCommitOnAnnotatedProtectedMethod() throws Throwable {
|
||||
txManager.clear();
|
||||
assertEquals(0, txManager.begun);
|
||||
beanWithAnnotatedProtectedMethod.doInTransaction();
|
||||
assertEquals(1, txManager.commits);
|
||||
}
|
||||
|
||||
public void testCommitOnAnnotatedPrivateMethod() throws Throwable {
|
||||
txManager.clear();
|
||||
assertEquals(0, txManager.begun);
|
||||
beanWithAnnotatedPrivateMethod.doSomething();
|
||||
assertEquals(1, txManager.commits);
|
||||
}
|
||||
|
||||
public void testNoCommitOnNonAnnotatedNonPublicMethodInTransactionalType() throws Throwable {
|
||||
txManager.clear();
|
||||
assertEquals(0,txManager.begun);
|
||||
annotationOnlyOnClassWithNoInterface.nonTransactionalMethod();
|
||||
assertEquals(0,txManager.begun);
|
||||
}
|
||||
|
||||
public void testCommitOnAnnotatedMethod() throws Throwable {
|
||||
txManager.clear();
|
||||
assertEquals(0, txManager.begun);
|
||||
methodAnnotationOnly.echo(null);
|
||||
assertEquals(1, txManager.commits);
|
||||
}
|
||||
|
||||
|
||||
public static class NotTransactional {
|
||||
public void noop() {
|
||||
}
|
||||
}
|
||||
|
||||
public void testNotTransactional() throws Throwable {
|
||||
txManager.clear();
|
||||
assertEquals(0, txManager.begun);
|
||||
new NotTransactional().noop();
|
||||
assertEquals(0, txManager.begun);
|
||||
}
|
||||
|
||||
|
||||
public void testDefaultCommitOnAnnotatedClass() throws Throwable {
|
||||
testRollback(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return annotationOnlyOnClassWithNoInterface.echo(new Exception());
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
public void testDefaultRollbackOnAnnotatedClass() throws Throwable {
|
||||
testRollback(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return annotationOnlyOnClassWithNoInterface.echo(new RuntimeException());
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
|
||||
public static class SubclassOfClassWithTransactionalAnnotation extends TransactionalAnnotationOnlyOnClassWithNoInterface {
|
||||
}
|
||||
|
||||
public void testDefaultCommitOnSubclassOfAnnotatedClass() throws Throwable {
|
||||
testRollback(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return new SubclassOfClassWithTransactionalAnnotation().echo(new Exception());
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
public static class SubclassOfClassWithTransactionalMethodAnnotation extends MethodAnnotationOnClassWithNoInterface {
|
||||
}
|
||||
|
||||
public void testDefaultCommitOnSubclassOfClassWithTransactionalMethodAnnotated() throws Throwable {
|
||||
testRollback(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return new SubclassOfClassWithTransactionalMethodAnnotation().echo(new Exception());
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
public static class ImplementsAnnotatedInterface implements ITransactional {
|
||||
public Object echo(Throwable t) throws Throwable {
|
||||
if (t != null) {
|
||||
throw t;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
public void testDefaultCommitOnImplementationOfAnnotatedInterface() throws Throwable {
|
||||
// testRollback(new TransactionOperationCallback() {
|
||||
// public Object performTransactionalOperation() throws Throwable {
|
||||
// return new ImplementsAnnotatedInterface().echo(new Exception());
|
||||
// }
|
||||
// }, false);
|
||||
|
||||
final Exception ex = new Exception();
|
||||
testNotTransactional(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return new ImplementsAnnotatedInterface().echo(ex);
|
||||
}
|
||||
}, ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: resolution does not occur. Thus we can't make a class transactional if
|
||||
* it implements a transactionally annotated interface. This behaviour could only
|
||||
* be changed in AbstractFallbackTransactionAttributeSource in Spring proper.
|
||||
* @throws SecurityException
|
||||
* @throws NoSuchMethodException
|
||||
*/
|
||||
public void testDoesNotResolveTxAnnotationOnMethodFromClassImplementingAnnotatedInterface() throws SecurityException, NoSuchMethodException {
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
Method m = ImplementsAnnotatedInterface.class.getMethod("echo", Throwable.class);
|
||||
TransactionAttribute ta = atas.getTransactionAttribute(m, ImplementsAnnotatedInterface.class);
|
||||
assertNull(ta);
|
||||
}
|
||||
|
||||
|
||||
public void testDefaultRollbackOnImplementationOfAnnotatedInterface() throws Throwable {
|
||||
// testRollback(new TransactionOperationCallback() {
|
||||
// public Object performTransactionalOperation() throws Throwable {
|
||||
// return new ImplementsAnnotatedInterface().echo(new RuntimeException());
|
||||
// }
|
||||
// }, true);
|
||||
|
||||
final Exception rollbackProvokingException = new RuntimeException();
|
||||
testNotTransactional(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return new ImplementsAnnotatedInterface().echo(rollbackProvokingException);
|
||||
}
|
||||
}, rollbackProvokingException);
|
||||
}
|
||||
|
||||
|
||||
protected void testRollback(TransactionOperationCallback toc, boolean rollback) throws Throwable {
|
||||
txManager.clear();
|
||||
assertEquals(0, txManager.begun);
|
||||
try {
|
||||
toc.performTransactionalOperation();
|
||||
assertEquals(1, txManager.commits);
|
||||
}
|
||||
catch (Throwable caught) {
|
||||
if (caught instanceof AssertionFailedError) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (rollback) {
|
||||
assertEquals(1, txManager.rollbacks);
|
||||
}
|
||||
assertEquals(1, txManager.begun);
|
||||
}
|
||||
|
||||
protected void testNotTransactional(TransactionOperationCallback toc, Throwable expected) throws Throwable {
|
||||
txManager.clear();
|
||||
assertEquals(0, txManager.begun);
|
||||
try {
|
||||
toc.performTransactionalOperation();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
if (expected == null) {
|
||||
fail("Expected " + expected);
|
||||
}
|
||||
assertSame(expected, t);
|
||||
}
|
||||
finally {
|
||||
assertEquals(0, txManager.begun);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private interface TransactionOperationCallback {
|
||||
|
||||
Object performTransactionalOperation() throws Throwable;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
|
||||
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
|
||||
import org.springframework.transaction.CallCountingTransactionManager;
|
||||
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
|
||||
import org.springframework.transaction.interceptor.TransactionAspectSupport;
|
||||
import org.springframework.transaction.interceptor.TransactionAttribute;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
*/
|
||||
public class TransactionAspectTests extends AbstractDependencyInjectionSpringContextTests {
|
||||
|
||||
private TransactionAspectSupport transactionAspect;
|
||||
|
||||
private CallCountingTransactionManager txManager;
|
||||
|
||||
private TransactionalAnnotationOnlyOnClassWithNoInterface annotationOnlyOnClassWithNoInterface;
|
||||
|
||||
private ClassWithProtectedAnnotatedMember beanWithAnnotatedProtectedMethod;
|
||||
|
||||
private ClassWithPrivateAnnotatedMember beanWithAnnotatedPrivateMethod;
|
||||
|
||||
private MethodAnnotationOnClassWithNoInterface methodAnnotationOnly = new MethodAnnotationOnClassWithNoInterface();
|
||||
|
||||
|
||||
public void setAnnotationOnlyOnClassWithNoInterface(
|
||||
TransactionalAnnotationOnlyOnClassWithNoInterface annotationOnlyOnClassWithNoInterface) {
|
||||
this.annotationOnlyOnClassWithNoInterface = annotationOnlyOnClassWithNoInterface;
|
||||
}
|
||||
|
||||
public void setClassWithAnnotatedProtectedMethod(ClassWithProtectedAnnotatedMember aBean) {
|
||||
this.beanWithAnnotatedProtectedMethod = aBean;
|
||||
}
|
||||
|
||||
public void setClassWithAnnotatedPrivateMethod(ClassWithPrivateAnnotatedMember aBean) {
|
||||
this.beanWithAnnotatedPrivateMethod = aBean;
|
||||
}
|
||||
|
||||
public void setTransactionAspect(TransactionAspectSupport transactionAspect) {
|
||||
this.transactionAspect = transactionAspect;
|
||||
this.txManager = (CallCountingTransactionManager) transactionAspect.getTransactionManager();
|
||||
}
|
||||
|
||||
public TransactionAspectSupport getTransactionAspect() {
|
||||
return this.transactionAspect;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getConfigPath() {
|
||||
return "TransactionAspectTests-context.xml";
|
||||
}
|
||||
|
||||
|
||||
public void testCommitOnAnnotatedClass() throws Throwable {
|
||||
txManager.clear();
|
||||
assertEquals(0, txManager.begun);
|
||||
annotationOnlyOnClassWithNoInterface.echo(null);
|
||||
assertEquals(1, txManager.commits);
|
||||
}
|
||||
|
||||
public void testCommitOnAnnotatedProtectedMethod() throws Throwable {
|
||||
txManager.clear();
|
||||
assertEquals(0, txManager.begun);
|
||||
beanWithAnnotatedProtectedMethod.doInTransaction();
|
||||
assertEquals(1, txManager.commits);
|
||||
}
|
||||
|
||||
public void testCommitOnAnnotatedPrivateMethod() throws Throwable {
|
||||
txManager.clear();
|
||||
assertEquals(0, txManager.begun);
|
||||
beanWithAnnotatedPrivateMethod.doSomething();
|
||||
assertEquals(1, txManager.commits);
|
||||
}
|
||||
|
||||
public void testNoCommitOnNonAnnotatedNonPublicMethodInTransactionalType() throws Throwable {
|
||||
txManager.clear();
|
||||
assertEquals(0,txManager.begun);
|
||||
annotationOnlyOnClassWithNoInterface.nonTransactionalMethod();
|
||||
assertEquals(0,txManager.begun);
|
||||
}
|
||||
|
||||
public void testCommitOnAnnotatedMethod() throws Throwable {
|
||||
txManager.clear();
|
||||
assertEquals(0, txManager.begun);
|
||||
methodAnnotationOnly.echo(null);
|
||||
assertEquals(1, txManager.commits);
|
||||
}
|
||||
|
||||
|
||||
public static class NotTransactional {
|
||||
public void noop() {
|
||||
}
|
||||
}
|
||||
|
||||
public void testNotTransactional() throws Throwable {
|
||||
txManager.clear();
|
||||
assertEquals(0, txManager.begun);
|
||||
new NotTransactional().noop();
|
||||
assertEquals(0, txManager.begun);
|
||||
}
|
||||
|
||||
|
||||
public void testDefaultCommitOnAnnotatedClass() throws Throwable {
|
||||
testRollback(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return annotationOnlyOnClassWithNoInterface.echo(new Exception());
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
public void testDefaultRollbackOnAnnotatedClass() throws Throwable {
|
||||
testRollback(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return annotationOnlyOnClassWithNoInterface.echo(new RuntimeException());
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
|
||||
public static class SubclassOfClassWithTransactionalAnnotation extends TransactionalAnnotationOnlyOnClassWithNoInterface {
|
||||
}
|
||||
|
||||
public void testDefaultCommitOnSubclassOfAnnotatedClass() throws Throwable {
|
||||
testRollback(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return new SubclassOfClassWithTransactionalAnnotation().echo(new Exception());
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
public static class SubclassOfClassWithTransactionalMethodAnnotation extends MethodAnnotationOnClassWithNoInterface {
|
||||
}
|
||||
|
||||
public void testDefaultCommitOnSubclassOfClassWithTransactionalMethodAnnotated() throws Throwable {
|
||||
testRollback(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return new SubclassOfClassWithTransactionalMethodAnnotation().echo(new Exception());
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
public static class ImplementsAnnotatedInterface implements ITransactional {
|
||||
public Object echo(Throwable t) throws Throwable {
|
||||
if (t != null) {
|
||||
throw t;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
public void testDefaultCommitOnImplementationOfAnnotatedInterface() throws Throwable {
|
||||
// testRollback(new TransactionOperationCallback() {
|
||||
// public Object performTransactionalOperation() throws Throwable {
|
||||
// return new ImplementsAnnotatedInterface().echo(new Exception());
|
||||
// }
|
||||
// }, false);
|
||||
|
||||
final Exception ex = new Exception();
|
||||
testNotTransactional(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return new ImplementsAnnotatedInterface().echo(ex);
|
||||
}
|
||||
}, ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: resolution does not occur. Thus we can't make a class transactional if
|
||||
* it implements a transactionally annotated interface. This behaviour could only
|
||||
* be changed in AbstractFallbackTransactionAttributeSource in Spring proper.
|
||||
* @throws SecurityException
|
||||
* @throws NoSuchMethodException
|
||||
*/
|
||||
public void testDoesNotResolveTxAnnotationOnMethodFromClassImplementingAnnotatedInterface() throws SecurityException, NoSuchMethodException {
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
Method m = ImplementsAnnotatedInterface.class.getMethod("echo", Throwable.class);
|
||||
TransactionAttribute ta = atas.getTransactionAttribute(m, ImplementsAnnotatedInterface.class);
|
||||
assertNull(ta);
|
||||
}
|
||||
|
||||
|
||||
public void testDefaultRollbackOnImplementationOfAnnotatedInterface() throws Throwable {
|
||||
// testRollback(new TransactionOperationCallback() {
|
||||
// public Object performTransactionalOperation() throws Throwable {
|
||||
// return new ImplementsAnnotatedInterface().echo(new RuntimeException());
|
||||
// }
|
||||
// }, true);
|
||||
|
||||
final Exception rollbackProvokingException = new RuntimeException();
|
||||
testNotTransactional(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return new ImplementsAnnotatedInterface().echo(rollbackProvokingException);
|
||||
}
|
||||
}, rollbackProvokingException);
|
||||
}
|
||||
|
||||
|
||||
protected void testRollback(TransactionOperationCallback toc, boolean rollback) throws Throwable {
|
||||
txManager.clear();
|
||||
assertEquals(0, txManager.begun);
|
||||
try {
|
||||
toc.performTransactionalOperation();
|
||||
assertEquals(1, txManager.commits);
|
||||
}
|
||||
catch (Throwable caught) {
|
||||
if (caught instanceof AssertionFailedError) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (rollback) {
|
||||
assertEquals(1, txManager.rollbacks);
|
||||
}
|
||||
assertEquals(1, txManager.begun);
|
||||
}
|
||||
|
||||
protected void testNotTransactional(TransactionOperationCallback toc, Throwable expected) throws Throwable {
|
||||
txManager.clear();
|
||||
assertEquals(0, txManager.begun);
|
||||
try {
|
||||
toc.performTransactionalOperation();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
if (expected == null) {
|
||||
fail("Expected " + expected);
|
||||
}
|
||||
assertSame(expected, t);
|
||||
}
|
||||
finally {
|
||||
assertEquals(0, txManager.begun);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private interface TransactionOperationCallback {
|
||||
|
||||
Object performTransactionalOperation() throws Throwable;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
package org.springframework.transaction.aspectj;
|
||||
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Transactional
|
||||
public class TransactionalAnnotationOnlyOnClassWithNoInterface {
|
||||
|
||||
public Object echo(Throwable t) throws Throwable {
|
||||
if (t != null) {
|
||||
throw t;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
void nonTransactionalMethod() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
package org.springframework.transaction.aspectj;
|
||||
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Transactional
|
||||
public class TransactionalAnnotationOnlyOnClassWithNoInterface {
|
||||
|
||||
public Object echo(Throwable t) throws Throwable {
|
||||
if (t != null) {
|
||||
throw t;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
void nonTransactionalMethod() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user