Move integration tests => src/test
This commit eliminates the 'integration-tests' subproject in favor of managing these sources under the root project's own 'src' directory. This helps to avoid special-case handling for integration-tests in the Gradle build, e.g. avoiding publication of jars to Artifactory / Maven Central. It is also semantically more correct. This is not a Spring Framework subproject so much as it is a collection of integration tests that span functionality across many subprojects. In this way, it makes sense to place them directly under the root project. Issue: SPR-8116
This commit is contained in:
0
src/test/java/.gitignore
vendored
Normal file
0
src/test/java/.gitignore
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
|
||||
|
||||
<aop:config>
|
||||
<aop:advisor advice-ref="advice" pointcut="execution(* *..ITestBean.*(..))"/>
|
||||
</aop:config>
|
||||
|
||||
<bean id="advice" class="org.springframework.aop.interceptor.DebugInterceptor"/>
|
||||
|
||||
<bean id="testBean" class="test.beans.TestBean"/>
|
||||
|
||||
<bean id="singletonScoped" class="test.beans.TestBean">
|
||||
<aop:scoped-proxy/>
|
||||
<property name="name" value="Rob Harrop"/>
|
||||
</bean>
|
||||
|
||||
<bean id="requestScoped" class="test.beans.TestBean" scope="request">
|
||||
<aop:scoped-proxy/>
|
||||
<property name="name" value="Rob Harrop"/>
|
||||
</bean>
|
||||
|
||||
<bean id="sessionScoped" name="sessionScopedAlias" class="test.beans.TestBean" scope="session">
|
||||
<aop:scoped-proxy proxy-target-class="false"/>
|
||||
<property name="name" value="Rob Harrop"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.config;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.TestBean;
|
||||
import test.util.SerializationTestUtils;
|
||||
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.context.support.XmlWebApplicationContext;
|
||||
|
||||
/**
|
||||
* Integration tests for scoped proxy use in conjunction with aop: namespace.
|
||||
* Deemed an integration test because .web mocks and application contexts are required.
|
||||
*
|
||||
* @see org.springframework.aop.config.AopNamespaceHandlerTests;
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class AopNamespaceHandlerScopeIntegrationTests {
|
||||
|
||||
private static final String CLASSNAME = AopNamespaceHandlerScopeIntegrationTests.class.getName();
|
||||
private static final String CONTEXT = format("classpath:%s-context.xml", ClassUtils.convertClassNameToResourcePath(CLASSNAME));
|
||||
|
||||
private ApplicationContext context;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
XmlWebApplicationContext wac = new XmlWebApplicationContext();
|
||||
wac.setConfigLocations(new String[] {CONTEXT});
|
||||
wac.refresh();
|
||||
this.context = wac;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingletonScoping() throws Exception {
|
||||
ITestBean scoped = (ITestBean) this.context.getBean("singletonScoped");
|
||||
assertTrue("Should be AOP proxy", AopUtils.isAopProxy(scoped));
|
||||
assertTrue("Should be target class proxy", scoped instanceof TestBean);
|
||||
String rob = "Rob Harrop";
|
||||
String bram = "Bram Smeets";
|
||||
assertEquals(rob, scoped.getName());
|
||||
scoped.setName(bram);
|
||||
assertEquals(bram, scoped.getName());
|
||||
ITestBean deserialized = (ITestBean) SerializationTestUtils.serializeAndDeserialize(scoped);
|
||||
assertEquals(bram, deserialized.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestScoping() throws Exception {
|
||||
MockHttpServletRequest oldRequest = new MockHttpServletRequest();
|
||||
MockHttpServletRequest newRequest = new MockHttpServletRequest();
|
||||
|
||||
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(oldRequest));
|
||||
|
||||
ITestBean scoped = (ITestBean) this.context.getBean("requestScoped");
|
||||
assertTrue("Should be AOP proxy", AopUtils.isAopProxy(scoped));
|
||||
assertTrue("Should be target class proxy", scoped instanceof TestBean);
|
||||
|
||||
ITestBean testBean = (ITestBean) this.context.getBean("testBean");
|
||||
assertTrue("Should be AOP proxy", AopUtils.isAopProxy(testBean));
|
||||
assertFalse("Regular bean should be JDK proxy", testBean instanceof TestBean);
|
||||
|
||||
String rob = "Rob Harrop";
|
||||
String bram = "Bram Smeets";
|
||||
|
||||
assertEquals(rob, scoped.getName());
|
||||
scoped.setName(bram);
|
||||
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(newRequest));
|
||||
assertEquals(rob, scoped.getName());
|
||||
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(oldRequest));
|
||||
assertEquals(bram, scoped.getName());
|
||||
|
||||
assertTrue("Should have advisors", ((Advised) scoped).getAdvisors().length > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionScoping() throws Exception {
|
||||
MockHttpSession oldSession = new MockHttpSession();
|
||||
MockHttpSession newSession = new MockHttpSession();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setSession(oldSession);
|
||||
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
|
||||
|
||||
ITestBean scoped = (ITestBean) this.context.getBean("sessionScoped");
|
||||
assertTrue("Should be AOP proxy", AopUtils.isAopProxy(scoped));
|
||||
assertFalse("Should not be target class proxy", scoped instanceof TestBean);
|
||||
|
||||
ITestBean scopedAlias = (ITestBean) this.context.getBean("sessionScopedAlias");
|
||||
assertSame(scoped, scopedAlias);
|
||||
|
||||
ITestBean testBean = (ITestBean) this.context.getBean("testBean");
|
||||
assertTrue("Should be AOP proxy", AopUtils.isAopProxy(testBean));
|
||||
assertFalse("Regular bean should be JDK proxy", testBean instanceof TestBean);
|
||||
|
||||
String rob = "Rob Harrop";
|
||||
String bram = "Bram Smeets";
|
||||
|
||||
assertEquals(rob, scoped.getName());
|
||||
scoped.setName(bram);
|
||||
request.setSession(newSession);
|
||||
assertEquals(rob, scoped.getName());
|
||||
request.setSession(oldSession);
|
||||
assertEquals(bram, scoped.getName());
|
||||
|
||||
assertTrue("Should have advisors", ((Advised) scoped).getAdvisors().length > 0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<!--
|
||||
Common bean definitions for auto proxy creator tests.
|
||||
-->
|
||||
<beans>
|
||||
|
||||
<description>
|
||||
Matches all Advisors in the factory: we don't use a prefix
|
||||
</description>
|
||||
|
||||
<bean id="aapc" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
|
||||
|
||||
<!--
|
||||
Depending on the order value, these beans should appear
|
||||
before or after the transaction advisor. Thus we configure
|
||||
them to check for or to refuse to accept a transaction.
|
||||
The transaction advisor's order value is 10.
|
||||
-->
|
||||
<bean id="orderedBeforeTransaction" class="org.springframework.aop.framework.autoproxy.OrderedTxCheckAdvisor">
|
||||
<property name="order"><value>9</value></property>
|
||||
<property name="requireTransactionContext"><value>false</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="orderedAfterTransaction" class="org.springframework.aop.framework.autoproxy.OrderedTxCheckAdvisor">
|
||||
<property name="order"><value>11</value></property>
|
||||
<property name="requireTransactionContext"><value>true</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="orderedAfterTransaction2" class="org.springframework.aop.framework.autoproxy.OrderedTxCheckAdvisor">
|
||||
<!-- Don't set order value: should remain Integer.MAX_VALUE, so it's non-ordered -->
|
||||
<property name="requireTransactionContext"><value>true</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- Often we can leave the definition of such infrastructural beans to child factories -->
|
||||
<bean id="txManager" class="org.springframework.aop.framework.autoproxy.CallCountingTransactionManager"/>
|
||||
|
||||
<bean id="tas" class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
|
||||
<property name="properties">
|
||||
<props>
|
||||
<prop key="setA*">PROPAGATION_REQUIRED</prop>
|
||||
<prop key="rollbackOnly">PROPAGATION_REQUIRED</prop>
|
||||
<prop key="echoException">PROPAGATION_REQUIRED,+javax.servlet.ServletException,-java.lang.Exception</prop>
|
||||
</props>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="txInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
|
||||
<property name="transactionManager"><ref local="txManager"/></property>
|
||||
<property name="transactionAttributeSource"><ref local="tas"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="txAdvisor" class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
|
||||
<property name="transactionInterceptor"><ref local="txInterceptor"/></property>
|
||||
<property name="order"><value>10</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- ====== Test for prototype definitions to try to provoke circular references ========================= -->
|
||||
<!--
|
||||
This advisor should never match and should not change how any of the tests run,
|
||||
but it's a prototype referencing another (unused) prototype, as well as a
|
||||
singleton, so it may pose circular reference problems, or an infinite loop.
|
||||
-->
|
||||
<bean id="neverMatchAdvisor" class="org.springframework.aop.framework.autoproxy.NeverMatchAdvisor"
|
||||
scope="prototype">
|
||||
<property name="dependencies">
|
||||
<list>
|
||||
<ref local="singletonDependency"/>
|
||||
<ref local="prototypeDependency"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- These two beans would otherwise be eligible for autoproxying -->
|
||||
|
||||
<bean id="singletonDependency" class="test.beans.TestBean" scope="singleton"/>
|
||||
|
||||
<bean id="prototypeDependency" class="test.beans.TestBean" scope="prototype"/>
|
||||
|
||||
<!-- ====== End test for prototype definitions to try to provoke circular references ========================= -->
|
||||
|
||||
<bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
|
||||
<property name="advice"><ref bean="countingAdvice"/></property>
|
||||
<property name="pattern"><value>test.beans.ITestBean.getName</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="countingAdvice" class="test.advice.CountingAfterReturningAdvice"/>
|
||||
|
||||
<bean id="test" class="test.beans.TestBean">
|
||||
<property name="age"><value>4</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="noSetters" class="org.springframework.aop.framework.autoproxy.NoSetters"/>
|
||||
|
||||
<bean id="rollback" class="org.springframework.aop.framework.autoproxy.Rollback"/>
|
||||
|
||||
<!-- The following beans test whether auto-proxying falls over for a null value -->
|
||||
|
||||
<bean id="tb" class="test.beans.TestBean"/>
|
||||
|
||||
<bean id="nullValueReturned" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
|
||||
<property name="targetObject" ref="tb"/>
|
||||
<property name="targetMethod" value="getSpouse"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* 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.aop.framework.autoproxy;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.transaction.NoTransactionException;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.interceptor.TransactionInterceptor;
|
||||
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
|
||||
import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||
|
||||
import test.advice.CountingBeforeAdvice;
|
||||
import test.advice.MethodCounter;
|
||||
import test.beans.ITestBean;
|
||||
import test.interceptor.NopInterceptor;
|
||||
|
||||
/**
|
||||
* Integration tests for auto proxy creation by advisor recognition working in
|
||||
* conjunction with transaction managment resources.
|
||||
*
|
||||
* @see org.springframework.aop.framework.autoproxy.AdvisorAutoProxyCreatorTests;
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class AdvisorAutoProxyCreatorIntegrationTests {
|
||||
|
||||
private static final Class<?> CLASS = AdvisorAutoProxyCreatorIntegrationTests.class;
|
||||
private static final String CLASSNAME = CLASS.getSimpleName();
|
||||
|
||||
private static final String DEFAULT_CONTEXT = CLASSNAME + "-context.xml";
|
||||
|
||||
private static final String ADVISOR_APC_BEAN_NAME = "aapc";
|
||||
private static final String TXMANAGER_BEAN_NAME = "txManager";
|
||||
|
||||
/**
|
||||
* Return a bean factory with attributes and EnterpriseServices configured.
|
||||
*/
|
||||
protected BeanFactory getBeanFactory() throws IOException {
|
||||
return new ClassPathXmlApplicationContext(DEFAULT_CONTEXT, CLASS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultExclusionPrefix() throws Exception {
|
||||
DefaultAdvisorAutoProxyCreator aapc = (DefaultAdvisorAutoProxyCreator) getBeanFactory().getBean(ADVISOR_APC_BEAN_NAME);
|
||||
assertEquals(ADVISOR_APC_BEAN_NAME + DefaultAdvisorAutoProxyCreator.SEPARATOR, aapc.getAdvisorBeanNamePrefix());
|
||||
assertFalse(aapc.isUsePrefix());
|
||||
}
|
||||
|
||||
/**
|
||||
* If no pointcuts match (no attrs) there should be proxying.
|
||||
*/
|
||||
@Test
|
||||
public void testNoProxy() throws Exception {
|
||||
BeanFactory bf = getBeanFactory();
|
||||
Object o = bf.getBean("noSetters");
|
||||
assertFalse(AopUtils.isAopProxy(o));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTxIsProxied() throws Exception {
|
||||
BeanFactory bf = getBeanFactory();
|
||||
ITestBean test = (ITestBean) bf.getBean("test");
|
||||
assertTrue(AopUtils.isAopProxy(test));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegexpApplied() throws Exception {
|
||||
BeanFactory bf = getBeanFactory();
|
||||
ITestBean test = (ITestBean) bf.getBean("test");
|
||||
MethodCounter counter = (MethodCounter) bf.getBean("countingAdvice");
|
||||
assertEquals(0, counter.getCalls());
|
||||
test.getName();
|
||||
assertEquals(1, counter.getCalls());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionAttributeOnMethod() throws Exception {
|
||||
BeanFactory bf = getBeanFactory();
|
||||
ITestBean test = (ITestBean) bf.getBean("test");
|
||||
|
||||
CallCountingTransactionManager txMan = (CallCountingTransactionManager) bf.getBean(TXMANAGER_BEAN_NAME);
|
||||
OrderedTxCheckAdvisor txc = (OrderedTxCheckAdvisor) bf.getBean("orderedBeforeTransaction");
|
||||
assertEquals(0, txc.getCountingBeforeAdvice().getCalls());
|
||||
|
||||
assertEquals(0, txMan.commits);
|
||||
assertEquals("Initial value was correct", 4, test.getAge());
|
||||
int newAge = 5;
|
||||
test.setAge(newAge);
|
||||
assertEquals(1, txc.getCountingBeforeAdvice().getCalls());
|
||||
|
||||
assertEquals("New value set correctly", newAge, test.getAge());
|
||||
assertEquals("Transaction counts match", 1, txMan.commits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Should not roll back on servlet exception.
|
||||
*/
|
||||
@Test
|
||||
public void testRollbackRulesOnMethodCauseRollback() throws Exception {
|
||||
BeanFactory bf = getBeanFactory();
|
||||
Rollback rb = (Rollback) bf.getBean("rollback");
|
||||
|
||||
CallCountingTransactionManager txMan = (CallCountingTransactionManager) bf.getBean(TXMANAGER_BEAN_NAME);
|
||||
OrderedTxCheckAdvisor txc = (OrderedTxCheckAdvisor) bf.getBean("orderedBeforeTransaction");
|
||||
assertEquals(0, txc.getCountingBeforeAdvice().getCalls());
|
||||
|
||||
assertEquals(0, txMan.commits);
|
||||
rb.echoException(null);
|
||||
// Fires only on setters
|
||||
assertEquals(0, txc.getCountingBeforeAdvice().getCalls());
|
||||
assertEquals("Transaction counts match", 1, txMan.commits);
|
||||
|
||||
assertEquals(0, txMan.rollbacks);
|
||||
Exception ex = new Exception();
|
||||
try {
|
||||
rb.echoException(ex);
|
||||
}
|
||||
catch (Exception actual) {
|
||||
assertEquals(ex, actual);
|
||||
}
|
||||
assertEquals("Transaction counts match", 1, txMan.rollbacks);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRollbackRulesOnMethodPreventRollback() throws Exception {
|
||||
BeanFactory bf = getBeanFactory();
|
||||
Rollback rb = (Rollback) bf.getBean("rollback");
|
||||
|
||||
CallCountingTransactionManager txMan = (CallCountingTransactionManager) bf.getBean(TXMANAGER_BEAN_NAME);
|
||||
|
||||
assertEquals(0, txMan.commits);
|
||||
// Should NOT roll back on ServletException
|
||||
try {
|
||||
rb.echoException(new ServletException());
|
||||
}
|
||||
catch (ServletException ex) {
|
||||
|
||||
}
|
||||
assertEquals("Transaction counts match", 1, txMan.commits);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProgrammaticRollback() throws Exception {
|
||||
BeanFactory bf = getBeanFactory();
|
||||
|
||||
Object bean = bf.getBean(TXMANAGER_BEAN_NAME);
|
||||
assertTrue(bean instanceof CallCountingTransactionManager);
|
||||
CallCountingTransactionManager txMan = (CallCountingTransactionManager) bf.getBean(TXMANAGER_BEAN_NAME);
|
||||
|
||||
Rollback rb = (Rollback) bf.getBean("rollback");
|
||||
assertEquals(0, txMan.commits);
|
||||
rb.rollbackOnly(false);
|
||||
assertEquals("Transaction counts match", 1, txMan.commits);
|
||||
assertEquals(0, txMan.rollbacks);
|
||||
// Will cause rollback only
|
||||
rb.rollbackOnly(true);
|
||||
assertEquals(1, txMan.rollbacks);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
class NeverMatchAdvisor extends StaticMethodMatcherPointcutAdvisor {
|
||||
|
||||
public NeverMatchAdvisor() {
|
||||
super(new NopInterceptor());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is solely to allow us to create a mixture of dependencies in
|
||||
* the bean definitions. The dependencies don't have any meaning, and don't
|
||||
* <b>do</b> anything.
|
||||
*/
|
||||
public void setDependencies(List<?> l) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.springframework.aop.MethodMatcher#matches(java.lang.reflect.Method, java.lang.Class)
|
||||
*/
|
||||
public boolean matches(Method m, Class<?> targetClass) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class NoSetters {
|
||||
|
||||
public void A() {
|
||||
|
||||
}
|
||||
|
||||
public int getB() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
class OrderedTxCheckAdvisor extends StaticMethodMatcherPointcutAdvisor implements InitializingBean {
|
||||
|
||||
/**
|
||||
* Should we insist on the presence of a transaction attribute or refuse to accept one?
|
||||
*/
|
||||
private boolean requireTransactionContext = false;
|
||||
|
||||
|
||||
public void setRequireTransactionContext(boolean requireTransactionContext) {
|
||||
this.requireTransactionContext = requireTransactionContext;
|
||||
}
|
||||
|
||||
public boolean isRequireTransactionContext() {
|
||||
return requireTransactionContext;
|
||||
}
|
||||
|
||||
|
||||
public CountingBeforeAdvice getCountingBeforeAdvice() {
|
||||
return (CountingBeforeAdvice) getAdvice();
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
setAdvice(new TxCountingBeforeAdvice());
|
||||
}
|
||||
|
||||
public boolean matches(Method method, Class<?> targetClass) {
|
||||
return method.getName().startsWith("setAge");
|
||||
}
|
||||
|
||||
|
||||
private class TxCountingBeforeAdvice extends CountingBeforeAdvice {
|
||||
|
||||
public void before(Method method, Object[] args, Object target) throws Throwable {
|
||||
// do transaction checks
|
||||
if (requireTransactionContext) {
|
||||
TransactionInterceptor.currentTransactionStatus();
|
||||
}
|
||||
else {
|
||||
try {
|
||||
TransactionInterceptor.currentTransactionStatus();
|
||||
throw new RuntimeException("Shouldn't have a transaction");
|
||||
}
|
||||
catch (NoTransactionException ex) {
|
||||
// this is Ok
|
||||
}
|
||||
}
|
||||
super.before(method, args, target);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class Rollback {
|
||||
|
||||
/**
|
||||
* Inherits transaction attribute.
|
||||
* Illustrates programmatic rollback.
|
||||
* @param rollbackOnly
|
||||
*/
|
||||
public void rollbackOnly(boolean rollbackOnly) {
|
||||
if (rollbackOnly) {
|
||||
setRollbackOnly();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracted in a protected method to facilitate testing
|
||||
*/
|
||||
protected void setRollbackOnly() {
|
||||
TransactionInterceptor.currentTransactionStatus().setRollbackOnly();
|
||||
}
|
||||
|
||||
/**
|
||||
* @org.springframework.transaction.interceptor.RuleBasedTransaction ( timeout=-1 )
|
||||
* @org.springframework.transaction.interceptor.RollbackRule ( "java.lang.Exception" )
|
||||
* @org.springframework.transaction.interceptor.NoRollbackRule ( "ServletException" )
|
||||
*/
|
||||
public void echoException(Exception ex) throws Exception {
|
||||
if (ex != null)
|
||||
throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
class CallCountingTransactionManager extends AbstractPlatformTransactionManager {
|
||||
|
||||
public TransactionDefinition lastDefinition;
|
||||
public int begun;
|
||||
public int commits;
|
||||
public int rollbacks;
|
||||
public int inflight;
|
||||
|
||||
protected Object doGetTransaction() {
|
||||
return new Object();
|
||||
}
|
||||
|
||||
protected void doBegin(Object transaction, TransactionDefinition definition) {
|
||||
this.lastDefinition = definition;
|
||||
++begun;
|
||||
++inflight;
|
||||
}
|
||||
|
||||
protected void doCommit(DefaultTransactionStatus status) {
|
||||
++commits;
|
||||
--inflight;
|
||||
}
|
||||
|
||||
protected void doRollback(DefaultTransactionStatus status) {
|
||||
++rollbacks;
|
||||
--inflight;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
begun = commits = rollbacks = inflight = 0;
|
||||
}
|
||||
|
||||
}
|
||||
129
src/test/java/org/springframework/cache/annotation/EnableCachingIntegrationTests.java
vendored
Normal file
129
src/test/java/org/springframework/cache/annotation/EnableCachingIntegrationTests.java
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* 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.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.interceptor.BeanFactoryCacheOperationSourceAdvisor;
|
||||
import org.springframework.cache.support.NoOpCacheManager;
|
||||
import org.springframework.context.annotation.AdviceMode;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* Integration tests for the @EnableCaching annotation.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
*/
|
||||
public class EnableCachingIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void repositoryIsClassBasedCacheProxy() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(Config.class, ProxyTargetClassCachingConfig.class);
|
||||
ctx.refresh();
|
||||
|
||||
assertCacheProxying(ctx);
|
||||
assertThat(AopUtils.isCglibProxy(ctx.getBean(FooRepository.class)), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void repositoryUsesAspectJAdviceMode() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(Config.class, AspectJCacheConfig.class);
|
||||
try {
|
||||
ctx.refresh();
|
||||
} catch (Exception ex) {
|
||||
// this test is a bit fragile, but gets the job done, proving that an
|
||||
// attempt was made to look up the AJ aspect. It's due to classpath issues
|
||||
// in .integration-tests that it's not found.
|
||||
assertTrue(ex.getMessage().endsWith("AspectJCachingConfiguration.class] cannot be opened because it does not exist"));
|
||||
}
|
||||
}
|
||||
|
||||
private void assertCacheProxying(AnnotationConfigApplicationContext ctx) {
|
||||
FooRepository repo = ctx.getBean(FooRepository.class);
|
||||
|
||||
boolean isCacheProxy = false;
|
||||
if (AopUtils.isAopProxy(repo)) {
|
||||
for (Advisor advisor : ((Advised)repo).getAdvisors()) {
|
||||
if (advisor instanceof BeanFactoryCacheOperationSourceAdvisor) {
|
||||
isCacheProxy = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
assertTrue("FooRepository is not a cache proxy", isCacheProxy);
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableCaching(proxyTargetClass=true)
|
||||
static class ProxyTargetClassCachingConfig {
|
||||
@Bean
|
||||
CacheManager mgr() {
|
||||
return new NoOpCacheManager();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
@Bean
|
||||
FooRepository fooRepository() {
|
||||
return new DummyFooRepository();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableCaching(mode=AdviceMode.ASPECTJ)
|
||||
static class AspectJCacheConfig {
|
||||
@Bean
|
||||
CacheManager cacheManager() {
|
||||
return new NoOpCacheManager();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface FooRepository {
|
||||
List<Object> findAll();
|
||||
}
|
||||
|
||||
|
||||
@Repository
|
||||
static class DummyFooRepository implements FooRepository {
|
||||
|
||||
@Cacheable("primary")
|
||||
public List<Object> findAll() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.context.annotation.jsr330;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.junit.After;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
|
||||
import org.springframework.context.annotation.ScopeMetadata;
|
||||
import org.springframework.context.annotation.ScopeMetadataResolver;
|
||||
import org.springframework.context.annotation.ScopedProxyMode;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class ClassPathBeanDefinitionScannerJsr330ScopeIntegrationTests {
|
||||
|
||||
private static final String DEFAULT_NAME = "default";
|
||||
|
||||
private static final String MODIFIED_NAME = "modified";
|
||||
|
||||
private ServletRequestAttributes oldRequestAttributes;
|
||||
|
||||
private ServletRequestAttributes newRequestAttributes;
|
||||
|
||||
private ServletRequestAttributes oldRequestAttributesWithSession;
|
||||
|
||||
private ServletRequestAttributes newRequestAttributesWithSession;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.oldRequestAttributes = new ServletRequestAttributes(new MockHttpServletRequest());
|
||||
this.newRequestAttributes = new ServletRequestAttributes(new MockHttpServletRequest());
|
||||
|
||||
MockHttpServletRequest oldRequestWithSession = new MockHttpServletRequest();
|
||||
oldRequestWithSession.setSession(new MockHttpSession());
|
||||
this.oldRequestAttributesWithSession = new ServletRequestAttributes(oldRequestWithSession);
|
||||
|
||||
MockHttpServletRequest newRequestWithSession = new MockHttpServletRequest();
|
||||
newRequestWithSession.setSession(new MockHttpSession());
|
||||
this.newRequestAttributesWithSession = new ServletRequestAttributes(newRequestWithSession);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
RequestContextHolder.setRequestAttributes(null);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPrototype() {
|
||||
ApplicationContext context = createContext(ScopedProxyMode.NO);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("prototype");
|
||||
assertTrue(context.isPrototype("prototype"));
|
||||
assertFalse(context.isSingleton("prototype"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingletonScopeWithNoProxy() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.NO);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("singleton");
|
||||
assertTrue(context.isSingleton("singleton"));
|
||||
assertFalse(context.isPrototype("singleton"));
|
||||
|
||||
// should not be a proxy
|
||||
assertFalse(AopUtils.isAopProxy(bean));
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributes);
|
||||
// not a proxy so this should not have changed
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
|
||||
// singleton bean, so name should be modified even after lookup
|
||||
ScopedTestBean bean2 = (ScopedTestBean) context.getBean("singleton");
|
||||
assertEquals(MODIFIED_NAME, bean2.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingletonScopeIgnoresProxyInterfaces() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.INTERFACES);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("singleton");
|
||||
|
||||
// should not be a proxy
|
||||
assertFalse(AopUtils.isAopProxy(bean));
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributes);
|
||||
// not a proxy so this should not have changed
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
|
||||
// singleton bean, so name should be modified even after lookup
|
||||
ScopedTestBean bean2 = (ScopedTestBean) context.getBean("singleton");
|
||||
assertEquals(MODIFIED_NAME, bean2.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingletonScopeIgnoresProxyTargetClass() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.TARGET_CLASS);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("singleton");
|
||||
|
||||
// should not be a proxy
|
||||
assertFalse(AopUtils.isAopProxy(bean));
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributes);
|
||||
// not a proxy so this should not have changed
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
|
||||
// singleton bean, so name should be modified even after lookup
|
||||
ScopedTestBean bean2 = (ScopedTestBean) context.getBean("singleton");
|
||||
assertEquals(MODIFIED_NAME, bean2.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestScopeWithNoProxy() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.NO);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("request");
|
||||
|
||||
// should not be a proxy
|
||||
assertFalse(AopUtils.isAopProxy(bean));
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributes);
|
||||
// not a proxy so this should not have changed
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
|
||||
// but a newly retrieved bean should have the default name
|
||||
ScopedTestBean bean2 = (ScopedTestBean) context.getBean("request");
|
||||
assertEquals(DEFAULT_NAME, bean2.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestScopeWithProxiedInterfaces() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.INTERFACES);
|
||||
IScopedTestBean bean = (IScopedTestBean) context.getBean("request");
|
||||
|
||||
// should be dynamic proxy, implementing both interfaces
|
||||
assertTrue(AopUtils.isJdkDynamicProxy(bean));
|
||||
assertTrue(bean instanceof AnotherScopeTestInterface);
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributes);
|
||||
// this is a proxy so it should be reset to default
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestScopeWithProxiedTargetClass() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.TARGET_CLASS);
|
||||
IScopedTestBean bean = (IScopedTestBean) context.getBean("request");
|
||||
|
||||
// should be a class-based proxy
|
||||
assertTrue(AopUtils.isCglibProxy(bean));
|
||||
assertTrue(bean instanceof RequestScopedTestBean);
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributes);
|
||||
// this is a proxy so it should be reset to default
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionScopeWithNoProxy() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributesWithSession);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.NO);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("session");
|
||||
|
||||
// should not be a proxy
|
||||
assertFalse(AopUtils.isAopProxy(bean));
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributesWithSession);
|
||||
// not a proxy so this should not have changed
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
|
||||
// but a newly retrieved bean should have the default name
|
||||
ScopedTestBean bean2 = (ScopedTestBean) context.getBean("session");
|
||||
assertEquals(DEFAULT_NAME, bean2.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionScopeWithProxiedInterfaces() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributesWithSession);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.INTERFACES);
|
||||
IScopedTestBean bean = (IScopedTestBean) context.getBean("session");
|
||||
|
||||
// should be dynamic proxy, implementing both interfaces
|
||||
assertTrue(AopUtils.isJdkDynamicProxy(bean));
|
||||
assertTrue(bean instanceof AnotherScopeTestInterface);
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributesWithSession);
|
||||
// this is a proxy so it should be reset to default
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
IScopedTestBean bean2 = (IScopedTestBean) context.getBean("session");
|
||||
assertEquals(MODIFIED_NAME, bean2.getName());
|
||||
bean2.setName(DEFAULT_NAME);
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributesWithSession);
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionScopeWithProxiedTargetClass() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributesWithSession);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.TARGET_CLASS);
|
||||
IScopedTestBean bean = (IScopedTestBean) context.getBean("session");
|
||||
|
||||
// should be a class-based proxy
|
||||
assertTrue(AopUtils.isCglibProxy(bean));
|
||||
assertTrue(bean instanceof ScopedTestBean);
|
||||
assertTrue(bean instanceof SessionScopedTestBean);
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributesWithSession);
|
||||
// this is a proxy so it should be reset to default
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
IScopedTestBean bean2 = (IScopedTestBean) context.getBean("session");
|
||||
assertEquals(MODIFIED_NAME, bean2.getName());
|
||||
bean2.setName(DEFAULT_NAME);
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributesWithSession);
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
}
|
||||
|
||||
|
||||
private ApplicationContext createContext(final ScopedProxyMode scopedProxyMode) {
|
||||
GenericWebApplicationContext context = new GenericWebApplicationContext();
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
|
||||
scanner.setIncludeAnnotationConfig(false);
|
||||
scanner.setScopeMetadataResolver(new ScopeMetadataResolver() {
|
||||
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
|
||||
ScopeMetadata metadata = new ScopeMetadata();
|
||||
if (definition instanceof AnnotatedBeanDefinition) {
|
||||
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
|
||||
for (String type : annDef.getMetadata().getAnnotationTypes()) {
|
||||
if (type.equals(javax.inject.Singleton.class.getName())) {
|
||||
metadata.setScopeName(BeanDefinition.SCOPE_SINGLETON);
|
||||
break;
|
||||
}
|
||||
else if (annDef.getMetadata().getMetaAnnotationTypes(type).contains(javax.inject.Scope.class.getName())) {
|
||||
metadata.setScopeName(type.substring(type.length() - 13, type.length() - 6).toLowerCase());
|
||||
metadata.setScopedProxyMode(scopedProxyMode);
|
||||
break;
|
||||
}
|
||||
else if (type.startsWith("javax.inject")) {
|
||||
metadata.setScopeName(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
});
|
||||
|
||||
// Scan twice in order to find errors in the bean definition compatibility check.
|
||||
scanner.scan(getClass().getPackage().getName());
|
||||
scanner.scan(getClass().getPackage().getName());
|
||||
|
||||
context.registerAlias("classPathBeanDefinitionScannerJsr330ScopeIntegrationTests.SessionScopedTestBean", "session");
|
||||
context.refresh();
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
public static interface IScopedTestBean {
|
||||
|
||||
String getName();
|
||||
|
||||
void setName(String name);
|
||||
}
|
||||
|
||||
|
||||
public static abstract class ScopedTestBean implements IScopedTestBean {
|
||||
|
||||
private String name = DEFAULT_NAME;
|
||||
|
||||
public String getName() { return this.name; }
|
||||
|
||||
public void setName(String name) { this.name = name; }
|
||||
}
|
||||
|
||||
|
||||
@Named("prototype")
|
||||
public static class PrototypeScopedTestBean extends ScopedTestBean {
|
||||
}
|
||||
|
||||
|
||||
@Named("singleton")
|
||||
@Singleton
|
||||
public static class SingletonScopedTestBean extends ScopedTestBean {
|
||||
}
|
||||
|
||||
|
||||
public static interface AnotherScopeTestInterface {
|
||||
}
|
||||
|
||||
|
||||
@Named("request")
|
||||
@RequestScoped
|
||||
public static class RequestScopedTestBean extends ScopedTestBean implements AnotherScopeTestInterface {
|
||||
}
|
||||
|
||||
|
||||
@Named
|
||||
@SessionScoped
|
||||
public static class SessionScopedTestBean extends ScopedTestBean implements AnotherScopeTestInterface {
|
||||
}
|
||||
|
||||
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@javax.inject.Scope
|
||||
public static @interface RequestScoped {
|
||||
}
|
||||
|
||||
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@javax.inject.Scope
|
||||
public static @interface SessionScoped {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.context.annotation.ltw;
|
||||
|
||||
import org.springframework.test.jpa.AbstractJpaTests;
|
||||
|
||||
/**
|
||||
* Test to ensure that component scanning work with load-time weaver.
|
||||
* See SPR-3873 for more details.
|
||||
*
|
||||
* @author Ramnivas Laddad
|
||||
*/
|
||||
public class ComponentScanningWithLTWTests extends AbstractJpaTests {
|
||||
|
||||
public ComponentScanningWithLTWTests() {
|
||||
setDependencyCheck(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getConfigPath() {
|
||||
return "ComponentScanningWithLTWTests.xml";
|
||||
}
|
||||
|
||||
public void testLoading() {
|
||||
// do nothing as successful loading is the test
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation=
|
||||
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
|
||||
default-autowire="byType">
|
||||
|
||||
<context:component-scan base-package="org.springframework.context.annotation"/>
|
||||
|
||||
<context:load-time-weaver aspectj-weaving="off"/>
|
||||
|
||||
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" autowire="no"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
* 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.context.annotation.scope;
|
||||
|
||||
import org.junit.After;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.context.annotation.ScopedProxyMode;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class ClassPathBeanDefinitionScannerScopeIntegrationTests {
|
||||
|
||||
private static final String DEFAULT_NAME = "default";
|
||||
|
||||
private static final String MODIFIED_NAME = "modified";
|
||||
|
||||
private ServletRequestAttributes oldRequestAttributes;
|
||||
|
||||
private ServletRequestAttributes newRequestAttributes;
|
||||
|
||||
private ServletRequestAttributes oldRequestAttributesWithSession;
|
||||
|
||||
private ServletRequestAttributes newRequestAttributesWithSession;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.oldRequestAttributes = new ServletRequestAttributes(new MockHttpServletRequest());
|
||||
this.newRequestAttributes = new ServletRequestAttributes(new MockHttpServletRequest());
|
||||
|
||||
MockHttpServletRequest oldRequestWithSession = new MockHttpServletRequest();
|
||||
oldRequestWithSession.setSession(new MockHttpSession());
|
||||
this.oldRequestAttributesWithSession = new ServletRequestAttributes(oldRequestWithSession);
|
||||
|
||||
MockHttpServletRequest newRequestWithSession = new MockHttpServletRequest();
|
||||
newRequestWithSession.setSession(new MockHttpSession());
|
||||
this.newRequestAttributesWithSession = new ServletRequestAttributes(newRequestWithSession);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
RequestContextHolder.setRequestAttributes(null);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSingletonScopeWithNoProxy() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.NO);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("singleton");
|
||||
|
||||
// should not be a proxy
|
||||
assertFalse(AopUtils.isAopProxy(bean));
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributes);
|
||||
// not a proxy so this should not have changed
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
|
||||
// singleton bean, so name should be modified even after lookup
|
||||
ScopedTestBean bean2 = (ScopedTestBean) context.getBean("singleton");
|
||||
assertEquals(MODIFIED_NAME, bean2.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingletonScopeIgnoresProxyInterfaces() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.INTERFACES);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("singleton");
|
||||
|
||||
// should not be a proxy
|
||||
assertFalse(AopUtils.isAopProxy(bean));
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributes);
|
||||
// not a proxy so this should not have changed
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
|
||||
// singleton bean, so name should be modified even after lookup
|
||||
ScopedTestBean bean2 = (ScopedTestBean) context.getBean("singleton");
|
||||
assertEquals(MODIFIED_NAME, bean2.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingletonScopeIgnoresProxyTargetClass() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.TARGET_CLASS);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("singleton");
|
||||
|
||||
// should not be a proxy
|
||||
assertFalse(AopUtils.isAopProxy(bean));
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributes);
|
||||
// not a proxy so this should not have changed
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
|
||||
// singleton bean, so name should be modified even after lookup
|
||||
ScopedTestBean bean2 = (ScopedTestBean) context.getBean("singleton");
|
||||
assertEquals(MODIFIED_NAME, bean2.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestScopeWithNoProxy() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.NO);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("request");
|
||||
|
||||
// should not be a proxy
|
||||
assertFalse(AopUtils.isAopProxy(bean));
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributes);
|
||||
// not a proxy so this should not have changed
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
|
||||
// but a newly retrieved bean should have the default name
|
||||
ScopedTestBean bean2 = (ScopedTestBean) context.getBean("request");
|
||||
assertEquals(DEFAULT_NAME, bean2.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestScopeWithProxiedInterfaces() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.INTERFACES);
|
||||
IScopedTestBean bean = (IScopedTestBean) context.getBean("request");
|
||||
|
||||
// should be dynamic proxy, implementing both interfaces
|
||||
assertTrue(AopUtils.isJdkDynamicProxy(bean));
|
||||
assertTrue(bean instanceof AnotherScopeTestInterface);
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributes);
|
||||
// this is a proxy so it should be reset to default
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestScopeWithProxiedTargetClass() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.TARGET_CLASS);
|
||||
IScopedTestBean bean = (IScopedTestBean) context.getBean("request");
|
||||
|
||||
// should be a class-based proxy
|
||||
assertTrue(AopUtils.isCglibProxy(bean));
|
||||
assertTrue(bean instanceof RequestScopedTestBean);
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributes);
|
||||
// this is a proxy so it should be reset to default
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionScopeWithNoProxy() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributesWithSession);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.NO);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("session");
|
||||
|
||||
// should not be a proxy
|
||||
assertFalse(AopUtils.isAopProxy(bean));
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributesWithSession);
|
||||
// not a proxy so this should not have changed
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
|
||||
// but a newly retrieved bean should have the default name
|
||||
ScopedTestBean bean2 = (ScopedTestBean) context.getBean("session");
|
||||
assertEquals(DEFAULT_NAME, bean2.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionScopeWithProxiedInterfaces() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributesWithSession);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.INTERFACES);
|
||||
IScopedTestBean bean = (IScopedTestBean) context.getBean("session");
|
||||
|
||||
// should be dynamic proxy, implementing both interfaces
|
||||
assertTrue(AopUtils.isJdkDynamicProxy(bean));
|
||||
assertTrue(bean instanceof AnotherScopeTestInterface);
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributesWithSession);
|
||||
// this is a proxy so it should be reset to default
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
IScopedTestBean bean2 = (IScopedTestBean) context.getBean("session");
|
||||
assertEquals(MODIFIED_NAME, bean2.getName());
|
||||
bean2.setName(DEFAULT_NAME);
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributesWithSession);
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionScopeWithProxiedTargetClass() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributesWithSession);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.TARGET_CLASS);
|
||||
IScopedTestBean bean = (IScopedTestBean) context.getBean("session");
|
||||
|
||||
// should be a class-based proxy
|
||||
assertTrue(AopUtils.isCglibProxy(bean));
|
||||
assertTrue(bean instanceof ScopedTestBean);
|
||||
assertTrue(bean instanceof SessionScopedTestBean);
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributesWithSession);
|
||||
// this is a proxy so it should be reset to default
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
IScopedTestBean bean2 = (IScopedTestBean) context.getBean("session");
|
||||
assertEquals(MODIFIED_NAME, bean2.getName());
|
||||
bean2.setName(DEFAULT_NAME);
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributesWithSession);
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
}
|
||||
|
||||
|
||||
private ApplicationContext createContext(ScopedProxyMode scopedProxyMode) {
|
||||
GenericWebApplicationContext context = new GenericWebApplicationContext();
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
|
||||
scanner.setIncludeAnnotationConfig(false);
|
||||
scanner.setBeanNameGenerator(new BeanNameGenerator() {
|
||||
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
|
||||
return definition.getScope();
|
||||
}
|
||||
});
|
||||
scanner.setScopedProxyMode(scopedProxyMode);
|
||||
|
||||
// Scan twice in order to find errors in the bean definition compatibility check.
|
||||
scanner.scan(getClass().getPackage().getName());
|
||||
scanner.scan(getClass().getPackage().getName());
|
||||
|
||||
context.refresh();
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
public static interface IScopedTestBean {
|
||||
|
||||
String getName();
|
||||
|
||||
void setName(String name);
|
||||
}
|
||||
|
||||
|
||||
public static abstract class ScopedTestBean implements IScopedTestBean {
|
||||
|
||||
private String name = DEFAULT_NAME;
|
||||
|
||||
public String getName() { return this.name; }
|
||||
|
||||
public void setName(String name) { this.name = name; }
|
||||
}
|
||||
|
||||
|
||||
@Component
|
||||
public static class SingletonScopedTestBean extends ScopedTestBean {
|
||||
}
|
||||
|
||||
|
||||
public static interface AnotherScopeTestInterface {
|
||||
}
|
||||
|
||||
|
||||
@Component
|
||||
@Scope("request")
|
||||
public static class RequestScopedTestBean extends ScopedTestBean implements AnotherScopeTestInterface {
|
||||
}
|
||||
|
||||
|
||||
@Component
|
||||
@Scope("session")
|
||||
public static class SessionScopedTestBean extends ScopedTestBean implements AnotherScopeTestInterface {
|
||||
}
|
||||
|
||||
}
|
||||
9
src/test/java/org/springframework/core/env/EnvironmentIntegrationTests-context-dev.xml
vendored
Normal file
9
src/test/java/org/springframework/core/env/EnvironmentIntegrationTests-context-dev.xml
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"
|
||||
profile="dev">
|
||||
|
||||
<bean id="devBean" class="java.lang.Object"/>
|
||||
|
||||
</beans>
|
||||
9
src/test/java/org/springframework/core/env/EnvironmentIntegrationTests-context-prod.xml
vendored
Normal file
9
src/test/java/org/springframework/core/env/EnvironmentIntegrationTests-context-prod.xml
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"
|
||||
profile="prod">
|
||||
|
||||
<bean id="prodBean" class="java.lang.Object"/>
|
||||
|
||||
</beans>
|
||||
11
src/test/java/org/springframework/core/env/EnvironmentIntegrationTests-context.xml
vendored
Normal file
11
src/test/java/org/springframework/core/env/EnvironmentIntegrationTests-context.xml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean id="envAwareBean" class="org.springframework.core.env.EnvironmentIntegrationTests$EnvironmentAwareBean"/>
|
||||
|
||||
<import resource="classpath:org/springframework/core/env/EnvironmentIntegrationTests-context-dev.xml"/>
|
||||
<import resource="classpath:org/springframework/core/env/EnvironmentIntegrationTests-context-prod.xml"/>
|
||||
|
||||
</beans>
|
||||
720
src/test/java/org/springframework/core/env/EnvironmentIntegrationTests.java
vendored
Normal file
720
src/test/java/org/springframework/core/env/EnvironmentIntegrationTests.java
vendored
Normal file
@@ -0,0 +1,720 @@
|
||||
/*
|
||||
* 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.core.env;
|
||||
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.lessThan;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
|
||||
import static org.springframework.context.ConfigurableApplicationContext.ENVIRONMENT_BEAN_NAME;
|
||||
import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.DERIVED_DEV_BEAN_NAME;
|
||||
import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.DERIVED_DEV_ENV_NAME;
|
||||
import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.DEV_BEAN_NAME;
|
||||
import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.DEV_ENV_NAME;
|
||||
import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.ENVIRONMENT_AWARE_BEAN_NAME;
|
||||
import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.PROD_BEAN_NAME;
|
||||
import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.PROD_ENV_NAME;
|
||||
import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.TRANSITIVE_BEAN_NAME;
|
||||
import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.XML_PATH;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.context.support.FileSystemXmlApplicationContext;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.context.support.GenericXmlApplicationContext;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.jca.context.ResourceAdapterApplicationContext;
|
||||
import org.springframework.jca.support.SimpleBootstrapContext;
|
||||
import org.springframework.jca.work.SimpleTaskWorkManager;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.mock.env.MockPropertySource;
|
||||
import org.springframework.mock.web.MockServletConfig;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.AbstractRefreshableWebApplicationContext;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.context.support.StandardServletEnvironment;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
import org.springframework.web.context.support.XmlWebApplicationContext;
|
||||
import org.springframework.web.portlet.context.AbstractRefreshablePortletApplicationContext;
|
||||
import org.springframework.web.portlet.context.StandardPortletEnvironment;
|
||||
import org.springframework.web.portlet.context.StaticPortletApplicationContext;
|
||||
import org.springframework.web.portlet.context.XmlPortletApplicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* Integration tests for container support of {@link Environment}
|
||||
* interface.
|
||||
*
|
||||
* Tests all existing BeanFactory and ApplicationContext implementations to
|
||||
* ensure that:
|
||||
* - a standard environment object is always present
|
||||
* - a custom environment object can be set and retrieved against the factory/context
|
||||
* - the {@link EnvironmentAware} interface is respected
|
||||
* - the environment object is registered with the container as a singleton
|
||||
* bean (if an ApplicationContext)
|
||||
* - bean definition files (if any, and whether XML or @Configuration) are
|
||||
* registered conditionally based on environment metadata
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class EnvironmentIntegrationTests {
|
||||
|
||||
private ConfigurableEnvironment prodEnv;
|
||||
private ConfigurableEnvironment devEnv;
|
||||
|
||||
/**
|
||||
* Constants used both locally and in scan* sub-packages
|
||||
*/
|
||||
public static class Constants {
|
||||
public static final String XML_PATH = "org/springframework/core/env/EnvironmentIntegrationTests-context.xml";
|
||||
|
||||
public static final String ENVIRONMENT_AWARE_BEAN_NAME = "envAwareBean";
|
||||
|
||||
public static final String PROD_BEAN_NAME = "prodBean";
|
||||
public static final String DEV_BEAN_NAME = "devBean";
|
||||
public static final String DERIVED_DEV_BEAN_NAME = "derivedDevBean";
|
||||
public static final String TRANSITIVE_BEAN_NAME = "transitiveBean";
|
||||
|
||||
public static final String PROD_ENV_NAME = "prod";
|
||||
public static final String DEV_ENV_NAME = "dev";
|
||||
public static final String DERIVED_DEV_ENV_NAME = "derivedDev";
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
prodEnv = new StandardEnvironment();
|
||||
prodEnv.setActiveProfiles(PROD_ENV_NAME);
|
||||
|
||||
devEnv = new StandardEnvironment();
|
||||
devEnv.setActiveProfiles(DEV_ENV_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void genericApplicationContext_standardEnv() {
|
||||
ConfigurableApplicationContext ctx =
|
||||
new GenericApplicationContext(newBeanFactoryWithEnvironmentAwareBean());
|
||||
|
||||
ctx.refresh();
|
||||
|
||||
assertHasStandardEnvironment(ctx);
|
||||
assertEnvironmentBeanRegistered(ctx);
|
||||
assertEnvironmentAwareInvoked(ctx, ctx.getEnvironment());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void genericApplicationContext_customEnv() {
|
||||
GenericApplicationContext ctx =
|
||||
new GenericApplicationContext(newBeanFactoryWithEnvironmentAwareBean());
|
||||
ctx.setEnvironment(prodEnv);
|
||||
ctx.refresh();
|
||||
|
||||
assertHasEnvironment(ctx, prodEnv);
|
||||
assertEnvironmentBeanRegistered(ctx);
|
||||
assertEnvironmentAwareInvoked(ctx, prodEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlBeanDefinitionReader_inheritsEnvironmentFromEnvironmentCapableBDR() {
|
||||
GenericApplicationContext ctx = new GenericApplicationContext();
|
||||
ctx.setEnvironment(prodEnv);
|
||||
new XmlBeanDefinitionReader(ctx).loadBeanDefinitions(XML_PATH);
|
||||
ctx.refresh();
|
||||
assertThat(ctx.containsBean(DEV_BEAN_NAME), is(false));
|
||||
assertThat(ctx.containsBean(PROD_BEAN_NAME), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void annotatedBeanDefinitionReader_inheritsEnvironmentFromEnvironmentCapableBDR() {
|
||||
GenericApplicationContext ctx = new GenericApplicationContext();
|
||||
ctx.setEnvironment(prodEnv);
|
||||
new AnnotatedBeanDefinitionReader(ctx).register(Config.class);
|
||||
ctx.refresh();
|
||||
assertThat(ctx.containsBean(DEV_BEAN_NAME), is(false));
|
||||
assertThat(ctx.containsBean(PROD_BEAN_NAME), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void classPathBeanDefinitionScanner_inheritsEnvironmentFromEnvironmentCapableBDR_scanProfileAnnotatedConfigClasses() {
|
||||
// it's actually ConfigurationClassPostProcessor's Environment that gets the job done here.
|
||||
GenericApplicationContext ctx = new GenericApplicationContext();
|
||||
ctx.setEnvironment(prodEnv);
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(ctx);
|
||||
scanner.scan("org.springframework.core.env.scan1");
|
||||
ctx.refresh();
|
||||
assertThat(ctx.containsBean(DEV_BEAN_NAME), is(false));
|
||||
assertThat(ctx.containsBean(PROD_BEAN_NAME), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void classPathBeanDefinitionScanner_inheritsEnvironmentFromEnvironmentCapableBDR_scanProfileAnnotatedComponents() {
|
||||
GenericApplicationContext ctx = new GenericApplicationContext();
|
||||
ctx.setEnvironment(prodEnv);
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(ctx);
|
||||
scanner.scan("org.springframework.core.env.scan2");
|
||||
ctx.refresh();
|
||||
assertThat(scanner.getEnvironment(), is((Environment)ctx.getEnvironment()));
|
||||
assertThat(ctx.containsBean(DEV_BEAN_NAME), is(false));
|
||||
assertThat(ctx.containsBean(PROD_BEAN_NAME), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void genericXmlApplicationContext() {
|
||||
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
|
||||
|
||||
assertHasStandardEnvironment(ctx);
|
||||
|
||||
ctx.setEnvironment(prodEnv);
|
||||
|
||||
ctx.load(XML_PATH);
|
||||
ctx.refresh();
|
||||
|
||||
assertHasEnvironment(ctx, prodEnv);
|
||||
assertEnvironmentBeanRegistered(ctx);
|
||||
assertEnvironmentAwareInvoked(ctx, prodEnv);
|
||||
assertThat(ctx.containsBean(DEV_BEAN_NAME), is(false));
|
||||
assertThat(ctx.containsBean(PROD_BEAN_NAME), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void classPathXmlApplicationContext() {
|
||||
ConfigurableApplicationContext ctx =
|
||||
new ClassPathXmlApplicationContext(new String[] { XML_PATH });
|
||||
ctx.setEnvironment(prodEnv);
|
||||
ctx.refresh();
|
||||
|
||||
assertEnvironmentBeanRegistered(ctx);
|
||||
assertHasEnvironment(ctx, prodEnv);
|
||||
assertEnvironmentAwareInvoked(ctx, ctx.getEnvironment());
|
||||
assertThat(ctx.containsBean(DEV_BEAN_NAME), is(false));
|
||||
assertThat(ctx.containsBean(PROD_BEAN_NAME), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileSystemXmlApplicationContext() throws IOException {
|
||||
ClassPathResource xml = new ClassPathResource(XML_PATH);
|
||||
File tmpFile = File.createTempFile("test", "xml");
|
||||
FileCopyUtils.copy(xml.getFile(), tmpFile);
|
||||
|
||||
// strange - FSXAC strips leading '/' unless prefixed with 'file:'
|
||||
ConfigurableApplicationContext ctx =
|
||||
new FileSystemXmlApplicationContext(new String[] { "file:"+tmpFile.getPath() }, false);
|
||||
ctx.setEnvironment(prodEnv);
|
||||
ctx.refresh();
|
||||
assertEnvironmentBeanRegistered(ctx);
|
||||
assertHasEnvironment(ctx, prodEnv);
|
||||
assertEnvironmentAwareInvoked(ctx, ctx.getEnvironment());
|
||||
assertThat(ctx.containsBean(DEV_BEAN_NAME), is(false));
|
||||
assertThat(ctx.containsBean(PROD_BEAN_NAME), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void annotationConfigApplicationContext_withPojos() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
|
||||
assertHasStandardEnvironment(ctx);
|
||||
ctx.setEnvironment(prodEnv);
|
||||
|
||||
ctx.register(EnvironmentAwareBean.class);
|
||||
ctx.refresh();
|
||||
|
||||
assertEnvironmentAwareInvoked(ctx, prodEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void annotationConfigApplicationContext_withProdEnvAndProdConfigClass() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
|
||||
assertHasStandardEnvironment(ctx);
|
||||
ctx.setEnvironment(prodEnv);
|
||||
|
||||
ctx.register(ProdConfig.class);
|
||||
ctx.refresh();
|
||||
|
||||
assertThat("should have prod bean", ctx.containsBean(PROD_BEAN_NAME), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void annotationConfigApplicationContext_withProdEnvAndDevConfigClass() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
|
||||
assertHasStandardEnvironment(ctx);
|
||||
ctx.setEnvironment(prodEnv);
|
||||
|
||||
ctx.register(DevConfig.class);
|
||||
ctx.refresh();
|
||||
|
||||
assertThat("should not have dev bean", ctx.containsBean(DEV_BEAN_NAME), is(false));
|
||||
assertThat("should not have transitive bean", ctx.containsBean(TRANSITIVE_BEAN_NAME), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void annotationConfigApplicationContext_withDevEnvAndDevConfigClass() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
|
||||
assertHasStandardEnvironment(ctx);
|
||||
ctx.setEnvironment(devEnv);
|
||||
|
||||
ctx.register(DevConfig.class);
|
||||
ctx.refresh();
|
||||
|
||||
assertThat("should have dev bean", ctx.containsBean(DEV_BEAN_NAME), is(true));
|
||||
assertThat("should have transitive bean", ctx.containsBean(TRANSITIVE_BEAN_NAME), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void annotationConfigApplicationContext_withImportedConfigClasses() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
|
||||
assertHasStandardEnvironment(ctx);
|
||||
ctx.setEnvironment(prodEnv);
|
||||
|
||||
ctx.register(Config.class);
|
||||
ctx.refresh();
|
||||
|
||||
assertEnvironmentAwareInvoked(ctx, prodEnv);
|
||||
assertThat("should have prod bean", ctx.containsBean(PROD_BEAN_NAME), is(true));
|
||||
assertThat("should not have dev bean", ctx.containsBean(DEV_BEAN_NAME), is(false));
|
||||
assertThat("should not have transitive bean", ctx.containsBean(TRANSITIVE_BEAN_NAME), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mostSpecificDerivedClassDrivesEnvironment_withDerivedDevEnvAndDerivedDevConfigClass() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
StandardEnvironment derivedDevEnv = new StandardEnvironment();
|
||||
derivedDevEnv.setActiveProfiles(DERIVED_DEV_ENV_NAME);
|
||||
ctx.setEnvironment(derivedDevEnv);
|
||||
ctx.register(DerivedDevConfig.class);
|
||||
ctx.refresh();
|
||||
|
||||
assertThat("should have dev bean", ctx.containsBean(DEV_BEAN_NAME), is(true));
|
||||
assertThat("should have derived dev bean", ctx.containsBean(DERIVED_DEV_BEAN_NAME), is(true));
|
||||
assertThat("should have transitive bean", ctx.containsBean(TRANSITIVE_BEAN_NAME), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mostSpecificDerivedClassDrivesEnvironment_withDevEnvAndDerivedDevConfigClass() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.setEnvironment(devEnv);
|
||||
ctx.register(DerivedDevConfig.class);
|
||||
ctx.refresh();
|
||||
|
||||
assertThat("should not have dev bean", ctx.containsBean(DEV_BEAN_NAME), is(false));
|
||||
assertThat("should not have derived dev bean", ctx.containsBean(DERIVED_DEV_BEAN_NAME), is(false));
|
||||
assertThat("should not have transitive bean", ctx.containsBean(TRANSITIVE_BEAN_NAME), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void webApplicationContext() {
|
||||
GenericWebApplicationContext ctx =
|
||||
new GenericWebApplicationContext(newBeanFactoryWithEnvironmentAwareBean());
|
||||
|
||||
assertHasStandardServletEnvironment(ctx);
|
||||
|
||||
ctx.setEnvironment(prodEnv);
|
||||
ctx.refresh();
|
||||
|
||||
assertHasEnvironment(ctx, prodEnv);
|
||||
assertEnvironmentBeanRegistered(ctx);
|
||||
assertEnvironmentAwareInvoked(ctx, prodEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlWebApplicationContext() {
|
||||
AbstractRefreshableWebApplicationContext ctx = new XmlWebApplicationContext();
|
||||
ctx.setConfigLocation("classpath:" + XML_PATH);
|
||||
ctx.setEnvironment(prodEnv);
|
||||
ctx.refresh();
|
||||
|
||||
assertHasEnvironment(ctx, prodEnv);
|
||||
assertEnvironmentBeanRegistered(ctx);
|
||||
assertEnvironmentAwareInvoked(ctx, prodEnv);
|
||||
assertThat(ctx.containsBean(DEV_BEAN_NAME), is(false));
|
||||
assertThat(ctx.containsBean(PROD_BEAN_NAME), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void staticApplicationContext() {
|
||||
StaticApplicationContext ctx = new StaticApplicationContext();
|
||||
|
||||
assertHasStandardEnvironment(ctx);
|
||||
|
||||
registerEnvironmentBeanDefinition(ctx);
|
||||
|
||||
ctx.setEnvironment(prodEnv);
|
||||
ctx.refresh();
|
||||
|
||||
assertHasEnvironment(ctx, prodEnv);
|
||||
assertEnvironmentBeanRegistered(ctx);
|
||||
assertEnvironmentAwareInvoked(ctx, prodEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void staticWebApplicationContext() {
|
||||
StaticWebApplicationContext ctx = new StaticWebApplicationContext();
|
||||
|
||||
assertHasStandardServletEnvironment(ctx);
|
||||
|
||||
registerEnvironmentBeanDefinition(ctx);
|
||||
|
||||
ctx.setEnvironment(prodEnv);
|
||||
ctx.refresh();
|
||||
|
||||
assertHasEnvironment(ctx, prodEnv);
|
||||
assertEnvironmentBeanRegistered(ctx);
|
||||
assertEnvironmentAwareInvoked(ctx, prodEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void annotationConfigWebApplicationContext() {
|
||||
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
|
||||
ctx.setEnvironment(prodEnv);
|
||||
ctx.setConfigLocation(EnvironmentAwareBean.class.getName());
|
||||
ctx.refresh();
|
||||
|
||||
assertHasEnvironment(ctx, prodEnv);
|
||||
assertEnvironmentBeanRegistered(ctx);
|
||||
assertEnvironmentAwareInvoked(ctx, prodEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerServletParamPropertySources_AbstractRefreshableWebApplicationContext() {
|
||||
MockServletContext servletContext = new MockServletContext();
|
||||
servletContext.addInitParameter("pCommon", "pCommonContextValue");
|
||||
servletContext.addInitParameter("pContext1", "pContext1Value");
|
||||
|
||||
MockServletConfig servletConfig = new MockServletConfig(servletContext);
|
||||
servletConfig.addInitParameter("pCommon", "pCommonConfigValue");
|
||||
servletConfig.addInitParameter("pConfig1", "pConfig1Value");
|
||||
|
||||
AbstractRefreshableWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
|
||||
ctx.setConfigLocation(EnvironmentAwareBean.class.getName());
|
||||
ctx.setServletConfig(servletConfig);
|
||||
ctx.refresh();
|
||||
|
||||
ConfigurableEnvironment environment = ctx.getEnvironment();
|
||||
assertThat(environment, instanceOf(StandardServletEnvironment.class));
|
||||
MutablePropertySources propertySources = environment.getPropertySources();
|
||||
assertThat(propertySources.contains(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME), is(true));
|
||||
assertThat(propertySources.contains(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME), is(true));
|
||||
|
||||
// ServletConfig gets precedence
|
||||
assertThat(environment.getProperty("pCommon"), is("pCommonConfigValue"));
|
||||
assertThat(propertySources.precedenceOf(PropertySource.named(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME)),
|
||||
lessThan(propertySources.precedenceOf(PropertySource.named(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME))));
|
||||
|
||||
// but all params are available
|
||||
assertThat(environment.getProperty("pContext1"), is("pContext1Value"));
|
||||
assertThat(environment.getProperty("pConfig1"), is("pConfig1Value"));
|
||||
|
||||
// Servlet* PropertySources have precedence over System* PropertySources
|
||||
assertThat(propertySources.precedenceOf(PropertySource.named(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME)),
|
||||
lessThan(propertySources.precedenceOf(PropertySource.named(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME))));
|
||||
|
||||
// Replace system properties with a mock property source for convenience
|
||||
MockPropertySource mockSystemProperties = new MockPropertySource(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME);
|
||||
mockSystemProperties.setProperty("pCommon", "pCommonSysPropsValue");
|
||||
mockSystemProperties.setProperty("pSysProps1", "pSysProps1Value");
|
||||
propertySources.replace(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, mockSystemProperties);
|
||||
|
||||
// assert that servletconfig params resolve with higher precedence than sysprops
|
||||
assertThat(environment.getProperty("pCommon"), is("pCommonConfigValue"));
|
||||
assertThat(environment.getProperty("pSysProps1"), is("pSysProps1Value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerServletParamPropertySources_GenericWebApplicationContext() {
|
||||
MockServletContext servletContext = new MockServletContext();
|
||||
servletContext.addInitParameter("pCommon", "pCommonContextValue");
|
||||
servletContext.addInitParameter("pContext1", "pContext1Value");
|
||||
|
||||
GenericWebApplicationContext ctx = new GenericWebApplicationContext();
|
||||
ctx.setServletContext(servletContext);
|
||||
ctx.refresh();
|
||||
|
||||
ConfigurableEnvironment environment = ctx.getEnvironment();
|
||||
assertThat(environment, instanceOf(StandardServletEnvironment.class));
|
||||
MutablePropertySources propertySources = environment.getPropertySources();
|
||||
assertThat(propertySources.contains(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME), is(true));
|
||||
|
||||
// ServletContext params are available
|
||||
assertThat(environment.getProperty("pCommon"), is("pCommonContextValue"));
|
||||
assertThat(environment.getProperty("pContext1"), is("pContext1Value"));
|
||||
|
||||
// Servlet* PropertySources have precedence over System* PropertySources
|
||||
assertThat(propertySources.precedenceOf(PropertySource.named(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME)),
|
||||
lessThan(propertySources.precedenceOf(PropertySource.named(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME))));
|
||||
|
||||
// Replace system properties with a mock property source for convenience
|
||||
MockPropertySource mockSystemProperties = new MockPropertySource(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME);
|
||||
mockSystemProperties.setProperty("pCommon", "pCommonSysPropsValue");
|
||||
mockSystemProperties.setProperty("pSysProps1", "pSysProps1Value");
|
||||
propertySources.replace(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, mockSystemProperties);
|
||||
|
||||
// assert that servletcontext init params resolve with higher precedence than sysprops
|
||||
assertThat(environment.getProperty("pCommon"), is("pCommonContextValue"));
|
||||
assertThat(environment.getProperty("pSysProps1"), is("pSysProps1Value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerServletParamPropertySources_StaticWebApplicationContext() {
|
||||
MockServletContext servletContext = new MockServletContext();
|
||||
servletContext.addInitParameter("pCommon", "pCommonContextValue");
|
||||
servletContext.addInitParameter("pContext1", "pContext1Value");
|
||||
|
||||
MockServletConfig servletConfig = new MockServletConfig(servletContext);
|
||||
servletConfig.addInitParameter("pCommon", "pCommonConfigValue");
|
||||
servletConfig.addInitParameter("pConfig1", "pConfig1Value");
|
||||
|
||||
StaticWebApplicationContext ctx = new StaticWebApplicationContext();
|
||||
ctx.setServletConfig(servletConfig);
|
||||
ctx.refresh();
|
||||
|
||||
ConfigurableEnvironment environment = ctx.getEnvironment();
|
||||
MutablePropertySources propertySources = environment.getPropertySources();
|
||||
assertThat(propertySources.contains(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME), is(true));
|
||||
assertThat(propertySources.contains(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME), is(true));
|
||||
|
||||
// ServletConfig gets precedence
|
||||
assertThat(environment.getProperty("pCommon"), is("pCommonConfigValue"));
|
||||
assertThat(propertySources.precedenceOf(PropertySource.named(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME)),
|
||||
lessThan(propertySources.precedenceOf(PropertySource.named(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME))));
|
||||
|
||||
// but all params are available
|
||||
assertThat(environment.getProperty("pContext1"), is("pContext1Value"));
|
||||
assertThat(environment.getProperty("pConfig1"), is("pConfig1Value"));
|
||||
|
||||
// Servlet* PropertySources have precedence over System* PropertySources
|
||||
assertThat(propertySources.precedenceOf(PropertySource.named(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME)),
|
||||
lessThan(propertySources.precedenceOf(PropertySource.named(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME))));
|
||||
|
||||
// Replace system properties with a mock property source for convenience
|
||||
MockPropertySource mockSystemProperties = new MockPropertySource(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME);
|
||||
mockSystemProperties.setProperty("pCommon", "pCommonSysPropsValue");
|
||||
mockSystemProperties.setProperty("pSysProps1", "pSysProps1Value");
|
||||
propertySources.replace(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, mockSystemProperties);
|
||||
|
||||
// assert that servletconfig params resolve with higher precedence than sysprops
|
||||
assertThat(environment.getProperty("pCommon"), is("pCommonConfigValue"));
|
||||
assertThat(environment.getProperty("pSysProps1"), is("pSysProps1Value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resourceAdapterApplicationContext() {
|
||||
ResourceAdapterApplicationContext ctx = new ResourceAdapterApplicationContext(new SimpleBootstrapContext(new SimpleTaskWorkManager()));
|
||||
|
||||
assertHasStandardEnvironment(ctx);
|
||||
|
||||
registerEnvironmentBeanDefinition(ctx);
|
||||
|
||||
ctx.setEnvironment(prodEnv);
|
||||
ctx.refresh();
|
||||
|
||||
assertHasEnvironment(ctx, prodEnv);
|
||||
assertEnvironmentBeanRegistered(ctx);
|
||||
assertEnvironmentAwareInvoked(ctx, prodEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void staticPortletApplicationContext() {
|
||||
StaticPortletApplicationContext ctx = new StaticPortletApplicationContext();
|
||||
|
||||
assertHasStandardPortletEnvironment(ctx);
|
||||
|
||||
registerEnvironmentBeanDefinition(ctx);
|
||||
|
||||
ctx.setEnvironment(prodEnv);
|
||||
ctx.refresh();
|
||||
|
||||
assertHasEnvironment(ctx, prodEnv);
|
||||
assertEnvironmentBeanRegistered(ctx);
|
||||
assertEnvironmentAwareInvoked(ctx, prodEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlPortletApplicationContext() {
|
||||
AbstractRefreshablePortletApplicationContext ctx = new XmlPortletApplicationContext();
|
||||
ctx.setEnvironment(prodEnv);
|
||||
ctx.setConfigLocation("classpath:" + XML_PATH);
|
||||
ctx.refresh();
|
||||
|
||||
assertHasEnvironment(ctx, prodEnv);
|
||||
assertEnvironmentBeanRegistered(ctx);
|
||||
assertEnvironmentAwareInvoked(ctx, prodEnv);
|
||||
assertThat(ctx.containsBean(DEV_BEAN_NAME), is(false));
|
||||
assertThat(ctx.containsBean(PROD_BEAN_NAME), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void abstractApplicationContextValidatesRequiredPropertiesOnRefresh() {
|
||||
{
|
||||
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.refresh();
|
||||
}
|
||||
|
||||
{
|
||||
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.getEnvironment().setRequiredProperties("foo", "bar");
|
||||
try {
|
||||
ctx.refresh();
|
||||
fail("expected missing property exception");
|
||||
} catch (MissingRequiredPropertiesException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.getEnvironment().setRequiredProperties("foo");
|
||||
ctx.setEnvironment(new MockEnvironment().withProperty("foo", "fooValue"));
|
||||
ctx.refresh(); // should succeed
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private DefaultListableBeanFactory newBeanFactoryWithEnvironmentAwareBean() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
registerEnvironmentBeanDefinition(bf);
|
||||
return bf;
|
||||
}
|
||||
|
||||
private void registerEnvironmentBeanDefinition(BeanDefinitionRegistry registry) {
|
||||
registry.registerBeanDefinition(ENVIRONMENT_AWARE_BEAN_NAME,
|
||||
rootBeanDefinition(EnvironmentAwareBean.class).getBeanDefinition());
|
||||
}
|
||||
|
||||
private void assertEnvironmentBeanRegistered(
|
||||
ConfigurableApplicationContext ctx) {
|
||||
// ensure environment is registered as a bean
|
||||
assertThat(ctx.containsBean(ENVIRONMENT_BEAN_NAME), is(true));
|
||||
}
|
||||
|
||||
private void assertHasStandardEnvironment(ApplicationContext ctx) {
|
||||
Environment defaultEnv = ctx.getEnvironment();
|
||||
assertThat(defaultEnv, notNullValue());
|
||||
assertThat(defaultEnv, instanceOf(StandardEnvironment.class));
|
||||
}
|
||||
|
||||
private void assertHasStandardServletEnvironment(WebApplicationContext ctx) {
|
||||
// ensure a default servlet environment exists
|
||||
Environment defaultEnv = ctx.getEnvironment();
|
||||
assertThat(defaultEnv, notNullValue());
|
||||
assertThat(defaultEnv, instanceOf(StandardServletEnvironment.class));
|
||||
}
|
||||
|
||||
private void assertHasStandardPortletEnvironment(WebApplicationContext ctx) {
|
||||
// ensure a default portlet environment exists
|
||||
Environment defaultEnv = ctx.getEnvironment();
|
||||
assertThat(defaultEnv, notNullValue());
|
||||
assertThat(defaultEnv, instanceOf(StandardPortletEnvironment.class));
|
||||
}
|
||||
|
||||
private void assertHasEnvironment(ApplicationContext ctx, Environment expectedEnv) {
|
||||
// ensure the custom environment took
|
||||
Environment actualEnv = ctx.getEnvironment();
|
||||
assertThat(actualEnv, notNullValue());
|
||||
assertThat(actualEnv, is(expectedEnv));
|
||||
// ensure environment is registered as a bean
|
||||
assertThat(ctx.containsBean(ENVIRONMENT_BEAN_NAME), is(true));
|
||||
}
|
||||
|
||||
private void assertEnvironmentAwareInvoked(ConfigurableApplicationContext ctx, Environment expectedEnv) {
|
||||
assertThat(ctx.getBean(EnvironmentAwareBean.class).environment, is(expectedEnv));
|
||||
}
|
||||
|
||||
private static class EnvironmentAwareBean implements EnvironmentAware {
|
||||
|
||||
public Environment environment;
|
||||
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirrors the structure of beans and environment-specific config files
|
||||
* in EnvironmentIntegrationTests-context.xml
|
||||
*/
|
||||
@Configuration
|
||||
@Import({DevConfig.class, ProdConfig.class})
|
||||
static class Config {
|
||||
@Bean
|
||||
public EnvironmentAwareBean envAwareBean() {
|
||||
return new EnvironmentAwareBean();
|
||||
}
|
||||
}
|
||||
|
||||
@Profile(DEV_ENV_NAME)
|
||||
@Configuration
|
||||
@Import(TransitiveConfig.class)
|
||||
static class DevConfig {
|
||||
@Bean
|
||||
public Object devBean() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
|
||||
@Profile(PROD_ENV_NAME)
|
||||
@Configuration
|
||||
static class ProdConfig {
|
||||
@Bean
|
||||
public Object prodBean() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class TransitiveConfig {
|
||||
@Bean
|
||||
public Object transitiveBean() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
|
||||
@Profile(DERIVED_DEV_ENV_NAME)
|
||||
@Configuration
|
||||
static class DerivedDevConfig extends DevConfig {
|
||||
@Bean
|
||||
public Object derivedDevBean() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +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.core.env;
|
||||
|
||||
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
|
||||
public class PropertyPlaceholderConfigurerEnvironmentIntegrationTests {
|
||||
@Test
|
||||
public void test() {
|
||||
GenericApplicationContext ctx = new GenericApplicationContext();
|
||||
ctx.registerBeanDefinition("ppc",
|
||||
rootBeanDefinition(PropertyPlaceholderConfigurer.class)
|
||||
.addPropertyValue("searchSystemEnvironment", false)
|
||||
.getBeanDefinition());
|
||||
ctx.refresh();
|
||||
ctx.getBean("ppc");
|
||||
}
|
||||
}
|
||||
52
src/test/java/org/springframework/core/env/scan1/package-info.java
vendored
Normal file
52
src/test/java/org/springframework/core/env/scan1/package-info.java
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Mirrors the structure of beans and environment-specific config files
|
||||
* in EnvironmentIntegrationTests-context.xml
|
||||
*/
|
||||
package org.springframework.core.env.scan1;
|
||||
|
||||
import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.DEV_ENV_NAME;
|
||||
import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.PROD_ENV_NAME;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
|
||||
@Configuration
|
||||
@Import({DevConfig.class, ProdConfig.class})
|
||||
class Config {
|
||||
}
|
||||
|
||||
@Profile(DEV_ENV_NAME)
|
||||
@Configuration
|
||||
class DevConfig {
|
||||
@Bean
|
||||
public Object devBean() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
|
||||
@Profile(PROD_ENV_NAME)
|
||||
@Configuration
|
||||
class ProdConfig {
|
||||
@Bean
|
||||
public Object prodBean() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
37
src/test/java/org/springframework/core/env/scan2/package-info.java
vendored
Normal file
37
src/test/java/org/springframework/core/env/scan2/package-info.java
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Mirrors the structure of beans and environment-specific config files
|
||||
* in EnvironmentIntegrationTests-context.xml
|
||||
*/
|
||||
package org.springframework.core.env.scan2;
|
||||
|
||||
import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.DEV_BEAN_NAME;
|
||||
import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.DEV_ENV_NAME;
|
||||
import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.PROD_BEAN_NAME;
|
||||
import static org.springframework.core.env.EnvironmentIntegrationTests.Constants.PROD_ENV_NAME;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Profile(DEV_ENV_NAME)
|
||||
@Component(DEV_BEAN_NAME)
|
||||
class DevBean { }
|
||||
|
||||
@Profile(PROD_ENV_NAME)
|
||||
@Component(PROD_BEAN_NAME)
|
||||
class ProdBean { }
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.expression.spel.support;
|
||||
|
||||
import java.beans.PropertyEditor;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.SimpleTypeConverter;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.expression.TypeConverter;
|
||||
|
||||
/**
|
||||
* Copied from Spring Integration for purposes of reproducing
|
||||
* {@link Spr7538Tests}.
|
||||
*/
|
||||
class BeanFactoryTypeConverter implements TypeConverter, BeanFactoryAware {
|
||||
|
||||
private SimpleTypeConverter delegate = new SimpleTypeConverter();
|
||||
|
||||
private static ConversionService defaultConversionService;
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
public BeanFactoryTypeConverter() {
|
||||
synchronized (this) {
|
||||
if (defaultConversionService == null) {
|
||||
defaultConversionService = new DefaultConversionService();
|
||||
}
|
||||
}
|
||||
this.conversionService = defaultConversionService;
|
||||
}
|
||||
|
||||
public BeanFactoryTypeConverter(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
public void setConversionService(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
if (beanFactory instanceof ConfigurableBeanFactory) {
|
||||
Object typeConverter = ((ConfigurableBeanFactory) beanFactory).getTypeConverter();
|
||||
if (typeConverter instanceof SimpleTypeConverter) {
|
||||
delegate = (SimpleTypeConverter) typeConverter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canConvert(Class<?> sourceType, Class<?> targetType) {
|
||||
if (conversionService.canConvert(sourceType, targetType)) {
|
||||
return true;
|
||||
}
|
||||
if (!String.class.isAssignableFrom(sourceType) && !String.class.isAssignableFrom(targetType)) {
|
||||
// PropertyEditor cannot convert non-Strings
|
||||
return false;
|
||||
}
|
||||
if (!String.class.isAssignableFrom(sourceType)) {
|
||||
return delegate.findCustomEditor(sourceType, null) != null || delegate.getDefaultEditor(sourceType) != null;
|
||||
}
|
||||
return delegate.findCustomEditor(targetType, null) != null || delegate.getDefaultEditor(targetType) != null;
|
||||
}
|
||||
|
||||
public boolean canConvert(TypeDescriptor sourceTypeDescriptor, TypeDescriptor targetTypeDescriptor) {
|
||||
if (conversionService.canConvert(sourceTypeDescriptor, targetTypeDescriptor)) {
|
||||
return true;
|
||||
}
|
||||
// TODO: what does this mean? This method is not used in SpEL so probably ignorable?
|
||||
Class<?> sourceType = sourceTypeDescriptor.getObjectType();
|
||||
Class<?> targetType = targetTypeDescriptor.getObjectType();
|
||||
return canConvert(sourceType, targetType);
|
||||
}
|
||||
|
||||
public Object convertValue(Object value, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (targetType.getType() == Void.class || targetType.getType() == Void.TYPE) {
|
||||
return null;
|
||||
}
|
||||
if (conversionService.canConvert(sourceType, targetType)) {
|
||||
return conversionService.convert(value, sourceType, targetType);
|
||||
}
|
||||
if (!String.class.isAssignableFrom(sourceType.getType())) {
|
||||
PropertyEditor editor = delegate.findCustomEditor(sourceType.getType(), null);
|
||||
editor.setValue(value);
|
||||
return editor.getAsText();
|
||||
}
|
||||
return delegate.convertIfNecessary(value, targetType.getType());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.springframework.expression.spel.support;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.expression.MethodExecutor;
|
||||
|
||||
public class Spr7538Tests {
|
||||
|
||||
@Ignore @Test
|
||||
public void repro() throws Exception {
|
||||
AlwaysTrueReleaseStrategy target = new AlwaysTrueReleaseStrategy();
|
||||
BeanFactoryTypeConverter converter = new BeanFactoryTypeConverter();
|
||||
|
||||
StandardEvaluationContext context = new StandardEvaluationContext();
|
||||
context.setTypeConverter(converter);
|
||||
|
||||
List<Foo> arguments = new ArrayList<Foo>();
|
||||
|
||||
// !!!! With the below line commented you'll get NPE. Uncomment and everything is OK!
|
||||
//arguments.add(new Foo());
|
||||
|
||||
List<TypeDescriptor> paramDescriptors = new ArrayList<TypeDescriptor>();
|
||||
Method method = AlwaysTrueReleaseStrategy.class.getMethod("checkCompleteness", List.class);
|
||||
paramDescriptors.add(new TypeDescriptor(new MethodParameter(method, 0)));
|
||||
|
||||
|
||||
List<TypeDescriptor> argumentTypes = new ArrayList<TypeDescriptor>();
|
||||
argumentTypes.add(TypeDescriptor.forObject(arguments));
|
||||
ReflectiveMethodResolver resolver = new ReflectiveMethodResolver();
|
||||
MethodExecutor executor = resolver.resolve(context, target, "checkCompleteness", argumentTypes);
|
||||
|
||||
Object result = executor.execute(context, target, arguments);
|
||||
System.out.println("Result: " + result);
|
||||
}
|
||||
|
||||
public static class AlwaysTrueReleaseStrategy {
|
||||
public boolean checkCompleteness(List<Foo> messages) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Foo{}
|
||||
}
|
||||
60
src/test/java/org/springframework/mock/env/MockEnvironment.java
vendored
Normal file
60
src/test/java/org/springframework/mock/env/MockEnvironment.java
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.mock.env;
|
||||
|
||||
import org.springframework.core.env.AbstractEnvironment;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
|
||||
/**
|
||||
* Simple {@link ConfigurableEnvironment} implementation exposing a
|
||||
* {@link #setProperty(String, String)} and {@link #withProperty(String, String)}
|
||||
* methods for testing purposes.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
* @see MockPropertySource
|
||||
*/
|
||||
public class MockEnvironment extends AbstractEnvironment {
|
||||
|
||||
private MockPropertySource propertySource = new MockPropertySource();
|
||||
|
||||
/**
|
||||
* Create a new {@code MockEnvironment} with a single {@link MockPropertySource}.
|
||||
*/
|
||||
public MockEnvironment() {
|
||||
getPropertySources().addLast(propertySource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a property on the underlying {@link MockPropertySource} for this environment.
|
||||
*/
|
||||
public void setProperty(String key, String value) {
|
||||
propertySource.setProperty(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient synonym for {@link #setProperty} that returns the current instance.
|
||||
* Useful for method chaining and fluent-style use.
|
||||
* @return this {@link MockEnvironment} instance
|
||||
* @see MockPropertySource#withProperty(String, String)
|
||||
*/
|
||||
public MockEnvironment withProperty(String key, String value) {
|
||||
this.setProperty(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* 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.scheduling.annotation;
|
||||
|
||||
import static org.easymock.EasyMock.createMock;
|
||||
import static org.easymock.EasyMock.replay;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.CallCountingTransactionManager;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Integration tests cornering bug SPR-8651, which revealed that @Scheduled methods may
|
||||
* not work well with beans that have already been proxied for other reasons such
|
||||
* as @Transactional or @Async processing.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
*/
|
||||
public class ScheduledAndTransactionalAnnotationIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void failsWhenJdkProxyAndScheduledMethodNotPresentOnInterface() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(Config.class, JdkProxyTxConfig.class, RepoConfigA.class);
|
||||
try {
|
||||
ctx.refresh();
|
||||
fail("expected exception");
|
||||
} catch (BeanCreationException ex) {
|
||||
assertTrue(ex.getRootCause().getMessage().startsWith("@Scheduled method 'scheduled' found"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void succeedsWhenSubclassProxyAndScheduledMethodNotPresentOnInterface() throws InterruptedException {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(Config.class, SubclassProxyTxConfig.class, RepoConfigA.class);
|
||||
ctx.refresh();
|
||||
|
||||
Thread.sleep(10); // allow @Scheduled method to be called several times
|
||||
|
||||
MyRepository repository = ctx.getBean(MyRepository.class);
|
||||
CallCountingTransactionManager txManager = ctx.getBean(CallCountingTransactionManager.class);
|
||||
assertThat("repository is not a proxy", AopUtils.isAopProxy(repository), is(true));
|
||||
assertThat("@Scheduled method never called", repository.getInvocationCount(), greaterThan(0));
|
||||
assertThat("no transactions were committed", txManager.commits, greaterThan(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void succeedsWhenJdkProxyAndScheduledMethodIsPresentOnInterface() throws InterruptedException {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(Config.class, JdkProxyTxConfig.class, RepoConfigB.class);
|
||||
ctx.refresh();
|
||||
|
||||
Thread.sleep(10); // allow @Scheduled method to be called several times
|
||||
|
||||
MyRepositoryWithScheduledMethod repository = ctx.getBean(MyRepositoryWithScheduledMethod.class);
|
||||
CallCountingTransactionManager txManager = ctx.getBean(CallCountingTransactionManager.class);
|
||||
assertThat("repository is not a proxy", AopUtils.isAopProxy(repository), is(true));
|
||||
assertThat("@Scheduled method never called", repository.getInvocationCount(), greaterThan(0));
|
||||
assertThat("no transactions were committed", txManager.commits, greaterThan(0));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
static class JdkProxyTxConfig { }
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement(proxyTargetClass=true)
|
||||
static class SubclassProxyTxConfig { }
|
||||
|
||||
@Configuration
|
||||
static class RepoConfigA {
|
||||
@Bean
|
||||
public MyRepository repository() {
|
||||
return new MyRepositoryImpl();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class RepoConfigB {
|
||||
@Bean
|
||||
public MyRepositoryWithScheduledMethod repository() {
|
||||
return new MyRepositoryWithScheduledMethodImpl();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableScheduling
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public PersistenceExceptionTranslationPostProcessor peTranslationPostProcessor() {
|
||||
return new PersistenceExceptionTranslationPostProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager txManager() {
|
||||
return new CallCountingTransactionManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PersistenceExceptionTranslator peTranslator() {
|
||||
PersistenceExceptionTranslator txlator = createMock(PersistenceExceptionTranslator.class);
|
||||
replay(txlator);
|
||||
return txlator;
|
||||
}
|
||||
}
|
||||
|
||||
public interface MyRepository {
|
||||
int getInvocationCount();
|
||||
}
|
||||
|
||||
@Repository
|
||||
static class MyRepositoryImpl implements MyRepository {
|
||||
|
||||
private final AtomicInteger count = new AtomicInteger(0);
|
||||
|
||||
@Transactional
|
||||
@Scheduled(fixedDelay = 5)
|
||||
public void scheduled() {
|
||||
this.count.incrementAndGet();
|
||||
}
|
||||
|
||||
public int getInvocationCount() {
|
||||
return this.count.get();
|
||||
}
|
||||
}
|
||||
|
||||
public interface MyRepositoryWithScheduledMethod {
|
||||
int getInvocationCount();
|
||||
public void scheduled();
|
||||
}
|
||||
|
||||
@Repository
|
||||
static class MyRepositoryWithScheduledMethodImpl implements MyRepositoryWithScheduledMethod {
|
||||
|
||||
private final AtomicInteger count = new AtomicInteger(0);
|
||||
|
||||
@Transactional
|
||||
@Scheduled(fixedDelay = 5)
|
||||
public void scheduled() {
|
||||
this.count.incrementAndGet();
|
||||
}
|
||||
|
||||
public int getInvocationCount() {
|
||||
return this.count.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.springframework.transaction;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
|
||||
import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class CallCountingTransactionManager extends AbstractPlatformTransactionManager {
|
||||
|
||||
public TransactionDefinition lastDefinition;
|
||||
public int begun;
|
||||
public int commits;
|
||||
public int rollbacks;
|
||||
public int inflight;
|
||||
|
||||
protected Object doGetTransaction() {
|
||||
return new Object();
|
||||
}
|
||||
|
||||
protected void doBegin(Object transaction, TransactionDefinition definition) {
|
||||
this.lastDefinition = definition;
|
||||
++begun;
|
||||
++inflight;
|
||||
}
|
||||
|
||||
protected void doCommit(DefaultTransactionStatus status) {
|
||||
++commits;
|
||||
--inflight;
|
||||
}
|
||||
|
||||
protected void doRollback(DefaultTransactionStatus status) {
|
||||
++rollbacks;
|
||||
--inflight;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
begun = commits = rollbacks = inflight = 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* 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.transaction.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCache;
|
||||
import org.springframework.cache.support.SimpleCacheManager;
|
||||
import org.springframework.context.annotation.AdviceMode;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportResource;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.CallCountingTransactionManager;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor;
|
||||
|
||||
/**
|
||||
* Integration tests for the @EnableTransactionManagement annotation.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
*/
|
||||
public class EnableTransactionManagementIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void repositoryIsNotTxProxy() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(Config.class);
|
||||
ctx.refresh();
|
||||
|
||||
try {
|
||||
assertTxProxying(ctx);
|
||||
fail("expected exception");
|
||||
} catch (AssertionError ex) {
|
||||
assertThat(ex.getMessage(), equalTo("FooRepository is not a TX proxy"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void repositoryIsTxProxy_withDefaultTxManagerName() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(Config.class, DefaultTxManagerNameConfig.class);
|
||||
ctx.refresh();
|
||||
|
||||
assertTxProxying(ctx);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void repositoryIsTxProxy_withCustomTxManagerName() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(Config.class, CustomTxManagerNameConfig.class);
|
||||
ctx.refresh();
|
||||
|
||||
assertTxProxying(ctx);
|
||||
}
|
||||
|
||||
@Ignore @Test // TODO SPR-8207
|
||||
public void repositoryIsTxProxy_withNonConventionalTxManagerName_fallsBackToByTypeLookup() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(Config.class, NonConventionalTxManagerNameConfig.class);
|
||||
ctx.refresh();
|
||||
|
||||
assertTxProxying(ctx);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void repositoryIsClassBasedTxProxy() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(Config.class, ProxyTargetClassTxConfig.class);
|
||||
ctx.refresh();
|
||||
|
||||
assertTxProxying(ctx);
|
||||
assertThat(AopUtils.isCglibProxy(ctx.getBean(FooRepository.class)), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void repositoryUsesAspectJAdviceMode() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(Config.class, AspectJTxConfig.class);
|
||||
try {
|
||||
ctx.refresh();
|
||||
} catch (Exception ex) {
|
||||
// this test is a bit fragile, but gets the job done, proving that an
|
||||
// attempt was made to look up the AJ aspect. It's due to classpath issues
|
||||
// in .integration-tests that it's not found.
|
||||
assertTrue(ex.getMessage().endsWith("AspectJTransactionManagementConfiguration.class] cannot be opened because it does not exist"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void implicitTxManager() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(ImplicitTxManagerConfig.class);
|
||||
ctx.refresh();
|
||||
|
||||
FooRepository fooRepository = ctx.getBean(FooRepository.class);
|
||||
fooRepository.findAll();
|
||||
|
||||
CallCountingTransactionManager txManager = ctx.getBean(CallCountingTransactionManager.class);
|
||||
assertThat(txManager.begun, equalTo(1));
|
||||
assertThat(txManager.commits, equalTo(1));
|
||||
assertThat(txManager.rollbacks, equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void explicitTxManager() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(ExplicitTxManagerConfig.class);
|
||||
ctx.refresh();
|
||||
|
||||
FooRepository fooRepository = ctx.getBean(FooRepository.class);
|
||||
fooRepository.findAll();
|
||||
|
||||
CallCountingTransactionManager txManager1 = ctx.getBean("txManager1", CallCountingTransactionManager.class);
|
||||
assertThat(txManager1.begun, equalTo(1));
|
||||
assertThat(txManager1.commits, equalTo(1));
|
||||
assertThat(txManager1.rollbacks, equalTo(0));
|
||||
|
||||
CallCountingTransactionManager txManager2 = ctx.getBean("txManager2", CallCountingTransactionManager.class);
|
||||
assertThat(txManager2.begun, equalTo(0));
|
||||
assertThat(txManager2.commits, equalTo(0));
|
||||
assertThat(txManager2.rollbacks, equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void apcEscalation() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(EnableTxAndCachingConfig.class);
|
||||
ctx.refresh();
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
@ImportResource("org/springframework/transaction/annotation/enable-caching.xml")
|
||||
static class EnableTxAndCachingConfig {
|
||||
@Bean
|
||||
public PlatformTransactionManager txManager() {
|
||||
return new CallCountingTransactionManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FooRepository fooRepository() {
|
||||
return new DummyFooRepository();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CacheManager cacheManager() {
|
||||
SimpleCacheManager mgr = new SimpleCacheManager();
|
||||
ArrayList<Cache> caches = new ArrayList<Cache>();
|
||||
caches.add(new ConcurrentMapCache(""));
|
||||
mgr.setCaches(caches);
|
||||
return mgr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
static class ImplicitTxManagerConfig {
|
||||
@Bean
|
||||
public PlatformTransactionManager txManager() {
|
||||
return new CallCountingTransactionManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FooRepository fooRepository() {
|
||||
return new DummyFooRepository();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
static class ExplicitTxManagerConfig implements TransactionManagementConfigurer {
|
||||
@Bean
|
||||
public PlatformTransactionManager txManager1() {
|
||||
return new CallCountingTransactionManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager txManager2() {
|
||||
return new CallCountingTransactionManager();
|
||||
}
|
||||
|
||||
public PlatformTransactionManager annotationDrivenTransactionManager() {
|
||||
return txManager1();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FooRepository fooRepository() {
|
||||
return new DummyFooRepository();
|
||||
}
|
||||
}
|
||||
|
||||
private void assertTxProxying(AnnotationConfigApplicationContext ctx) {
|
||||
FooRepository repo = ctx.getBean(FooRepository.class);
|
||||
|
||||
boolean isTxProxy = false;
|
||||
if (AopUtils.isAopProxy(repo)) {
|
||||
for (Advisor advisor : ((Advised)repo).getAdvisors()) {
|
||||
if (advisor instanceof BeanFactoryTransactionAttributeSourceAdvisor) {
|
||||
isTxProxy = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
assertTrue("FooRepository is not a TX proxy", isTxProxy);
|
||||
|
||||
// trigger a transaction
|
||||
repo.findAll();
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
static class DefaultTxManagerNameConfig {
|
||||
@Bean
|
||||
PlatformTransactionManager transactionManager(DataSource dataSource) {
|
||||
return new DataSourceTransactionManager(dataSource);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
static class CustomTxManagerNameConfig {
|
||||
@Bean
|
||||
PlatformTransactionManager txManager(DataSource dataSource) {
|
||||
return new DataSourceTransactionManager(dataSource);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
static class NonConventionalTxManagerNameConfig {
|
||||
@Bean
|
||||
PlatformTransactionManager txManager(DataSource dataSource) {
|
||||
return new DataSourceTransactionManager(dataSource);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement(proxyTargetClass=true)
|
||||
static class ProxyTargetClassTxConfig {
|
||||
@Bean
|
||||
PlatformTransactionManager transactionManager(DataSource dataSource) {
|
||||
return new DataSourceTransactionManager(dataSource);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement(mode=AdviceMode.ASPECTJ)
|
||||
static class AspectJTxConfig {
|
||||
@Bean
|
||||
PlatformTransactionManager transactionManager(DataSource dataSource) {
|
||||
return new DataSourceTransactionManager(dataSource);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
@Bean
|
||||
FooRepository fooRepository() {
|
||||
JdbcFooRepository repos = new JdbcFooRepository();
|
||||
repos.setDataSource(dataSource());
|
||||
return repos;
|
||||
}
|
||||
|
||||
@Bean
|
||||
DataSource dataSource() {
|
||||
return new EmbeddedDatabaseBuilder()
|
||||
.setType(EmbeddedDatabaseType.HSQL)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface FooRepository {
|
||||
List<Object> findAll();
|
||||
}
|
||||
|
||||
|
||||
@Repository
|
||||
static class JdbcFooRepository implements FooRepository {
|
||||
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<Object> findAll() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@Repository
|
||||
static class DummyFooRepository implements FooRepository {
|
||||
|
||||
@Transactional
|
||||
public List<Object> findAll() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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.transaction.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Tests proving that regardless the proxy strategy used (JDK interface-based vs. CGLIB
|
||||
* subclass-based), discovery of advice-oriented annotations is consistent.
|
||||
*
|
||||
* For example, Spring's @Transactional may be declared at the interface or class level,
|
||||
* and whether interface or subclass proxies are used, the @Transactional annotation must
|
||||
* be discovered in a consistent fashion.
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class ProxyAnnotationDiscoveryTests {
|
||||
@Test
|
||||
public void annotatedServiceWithoutInterface_PTC_true() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(PTCTrue.class, AnnotatedServiceWithoutInterface.class);
|
||||
ctx.refresh();
|
||||
AnnotatedServiceWithoutInterface s = ctx.getBean(AnnotatedServiceWithoutInterface.class);
|
||||
assertTrue("expected a subclass proxy", AopUtils.isCglibProxy(s));
|
||||
assertThat(s, instanceOf(AnnotatedServiceWithoutInterface.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void annotatedServiceWithoutInterface_PTC_false() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(PTCFalse.class, AnnotatedServiceWithoutInterface.class);
|
||||
ctx.refresh();
|
||||
AnnotatedServiceWithoutInterface s = ctx.getBean(AnnotatedServiceWithoutInterface.class);
|
||||
assertTrue("expected a subclass proxy", AopUtils.isCglibProxy(s));
|
||||
assertThat(s, instanceOf(AnnotatedServiceWithoutInterface.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonAnnotatedService_PTC_true() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(PTCTrue.class, AnnotatedServiceImpl.class);
|
||||
ctx.refresh();
|
||||
NonAnnotatedService s = ctx.getBean(NonAnnotatedService.class);
|
||||
assertTrue("expected a subclass proxy", AopUtils.isCglibProxy(s));
|
||||
assertThat(s, instanceOf(AnnotatedServiceImpl.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonAnnotatedService_PTC_false() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(PTCFalse.class, AnnotatedServiceImpl.class);
|
||||
ctx.refresh();
|
||||
NonAnnotatedService s = ctx.getBean(NonAnnotatedService.class);
|
||||
assertTrue("expected a jdk proxy", AopUtils.isJdkDynamicProxy(s));
|
||||
assertThat(s, not(instanceOf(AnnotatedServiceImpl.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void annotatedService_PTC_true() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(PTCTrue.class, NonAnnotatedServiceImpl.class);
|
||||
ctx.refresh();
|
||||
AnnotatedService s = ctx.getBean(AnnotatedService.class);
|
||||
assertTrue("expected a subclass proxy", AopUtils.isCglibProxy(s));
|
||||
assertThat(s, instanceOf(NonAnnotatedServiceImpl.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void annotatedService_PTC_false() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(PTCFalse.class, NonAnnotatedServiceImpl.class);
|
||||
ctx.refresh();
|
||||
AnnotatedService s = ctx.getBean(AnnotatedService.class);
|
||||
assertTrue("expected a jdk proxy", AopUtils.isJdkDynamicProxy(s));
|
||||
assertThat(s, not(instanceOf(NonAnnotatedServiceImpl.class)));
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement(proxyTargetClass=false)
|
||||
class PTCFalse { }
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement(proxyTargetClass=true)
|
||||
class PTCTrue { }
|
||||
|
||||
interface NonAnnotatedService {
|
||||
void m();
|
||||
}
|
||||
|
||||
interface AnnotatedService {
|
||||
@Transactional void m();
|
||||
}
|
||||
|
||||
class NonAnnotatedServiceImpl implements AnnotatedService {
|
||||
public void m() { }
|
||||
}
|
||||
|
||||
class AnnotatedServiceImpl implements NonAnnotatedService {
|
||||
@Transactional public void m() { }
|
||||
}
|
||||
|
||||
class AnnotatedServiceWithoutInterface {
|
||||
@Transactional public void m() { }
|
||||
}
|
||||
35
src/test/java/test/advice/CountingAfterReturningAdvice.java
Normal file
35
src/test/java/test/advice/CountingAfterReturningAdvice.java
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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 test.advice;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.aop.AfterReturningAdvice;
|
||||
|
||||
/**
|
||||
* Simple before advice example that we can use for counting checks.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class CountingAfterReturningAdvice extends MethodCounter implements AfterReturningAdvice {
|
||||
|
||||
public void afterReturning(Object o, Method m, Object[] args, Object target) throws Throwable {
|
||||
count(m);
|
||||
}
|
||||
|
||||
}
|
||||
35
src/test/java/test/advice/CountingBeforeAdvice.java
Normal file
35
src/test/java/test/advice/CountingBeforeAdvice.java
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 test.advice;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.aop.MethodBeforeAdvice;
|
||||
|
||||
/**
|
||||
* Simple before advice example that we can use for counting checks.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class CountingBeforeAdvice extends MethodCounter implements MethodBeforeAdvice {
|
||||
|
||||
public void before(Method m, Object[] args, Object target) throws Throwable {
|
||||
count(m);
|
||||
}
|
||||
|
||||
}
|
||||
70
src/test/java/test/advice/MethodCounter.java
Normal file
70
src/test/java/test/advice/MethodCounter.java
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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 test.advice;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Abstract superclass for counting advices etc.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MethodCounter implements Serializable {
|
||||
|
||||
/** Method name --> count, does not understand overloading */
|
||||
private HashMap<String, Integer> map = new HashMap<String, Integer>();
|
||||
|
||||
private int allCount;
|
||||
|
||||
protected void count(Method m) {
|
||||
count(m.getName());
|
||||
}
|
||||
|
||||
protected void count(String methodName) {
|
||||
Integer i = map.get(methodName);
|
||||
i = (i != null) ? new Integer(i.intValue() + 1) : new Integer(1);
|
||||
map.put(methodName, i);
|
||||
++allCount;
|
||||
}
|
||||
|
||||
public int getCalls(String methodName) {
|
||||
Integer i = map.get(methodName);
|
||||
return (i != null ? i.intValue() : 0);
|
||||
}
|
||||
|
||||
public int getCalls() {
|
||||
return allCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* A bit simplistic: just wants the same class.
|
||||
* Doesn't worry about counts.
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object other) {
|
||||
return (other != null && other.getClass() == this.getClass());
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return getClass().hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
36
src/test/java/test/beans/Colour.java
Normal file
36
src/test/java/test/beans/Colour.java
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 test.beans;
|
||||
|
||||
import org.springframework.core.enums.ShortCodedLabeledEnum;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class Colour extends ShortCodedLabeledEnum {
|
||||
|
||||
public static final Colour RED = new Colour(0, "RED");
|
||||
public static final Colour BLUE = new Colour(1, "BLUE");
|
||||
public static final Colour GREEN = new Colour(2, "GREEN");
|
||||
public static final Colour PURPLE = new Colour(3, "PURPLE");
|
||||
|
||||
private Colour(int code, String label) {
|
||||
super(code, label);
|
||||
}
|
||||
|
||||
}
|
||||
23
src/test/java/test/beans/INestedTestBean.java
Normal file
23
src/test/java/test/beans/INestedTestBean.java
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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 test.beans;
|
||||
|
||||
public interface INestedTestBean {
|
||||
|
||||
public String getCompany();
|
||||
|
||||
}
|
||||
24
src/test/java/test/beans/IOther.java
Normal file
24
src/test/java/test/beans/IOther.java
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
/*
|
||||
* Copyright 2002-2005 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 test.beans;
|
||||
|
||||
public interface IOther {
|
||||
|
||||
void absquatulate();
|
||||
|
||||
}
|
||||
71
src/test/java/test/beans/ITestBean.java
Normal file
71
src/test/java/test/beans/ITestBean.java
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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 test.beans;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Interface used for {@link TestBean}.
|
||||
*
|
||||
* <p>Two methods are the same as on Person, but if this
|
||||
* extends person it breaks quite a few tests..
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public interface ITestBean {
|
||||
|
||||
int getAge();
|
||||
|
||||
void setAge(int age);
|
||||
|
||||
String getName();
|
||||
|
||||
void setName(String name);
|
||||
|
||||
ITestBean getSpouse();
|
||||
|
||||
void setSpouse(ITestBean spouse);
|
||||
|
||||
ITestBean[] getSpouses();
|
||||
|
||||
String[] getStringArray();
|
||||
|
||||
void setStringArray(String[] stringArray);
|
||||
|
||||
/**
|
||||
* Throws a given (non-null) exception.
|
||||
*/
|
||||
void exceptional(Throwable t) throws Throwable;
|
||||
|
||||
Object returnsThis();
|
||||
|
||||
INestedTestBean getDoctor();
|
||||
|
||||
INestedTestBean getLawyer();
|
||||
|
||||
IndexedTestBean getNestedIndexedBean();
|
||||
|
||||
/**
|
||||
* Increment the age by one.
|
||||
* @return the previous age
|
||||
*/
|
||||
int haveBirthday();
|
||||
|
||||
void unreliableFileOperation() throws IOException;
|
||||
|
||||
}
|
||||
145
src/test/java/test/beans/IndexedTestBean.java
Normal file
145
src/test/java/test/beans/IndexedTestBean.java
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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 test.beans;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @since 11.11.2003
|
||||
*/
|
||||
public class IndexedTestBean {
|
||||
|
||||
private TestBean[] array;
|
||||
|
||||
private Collection<?> collection;
|
||||
|
||||
private List<TestBean> list;
|
||||
|
||||
private Set<TestBean> set;
|
||||
|
||||
private SortedSet<?> sortedSet;
|
||||
|
||||
private Map<String, Object> map;
|
||||
|
||||
private SortedMap<?, ?> sortedMap;
|
||||
|
||||
|
||||
public IndexedTestBean() {
|
||||
this(true);
|
||||
}
|
||||
|
||||
public IndexedTestBean(boolean populate) {
|
||||
if (populate) {
|
||||
populate();
|
||||
}
|
||||
}
|
||||
|
||||
public void populate() {
|
||||
TestBean tb0 = new TestBean("name0", 0);
|
||||
TestBean tb1 = new TestBean("name1", 0);
|
||||
TestBean tb2 = new TestBean("name2", 0);
|
||||
TestBean tb3 = new TestBean("name3", 0);
|
||||
TestBean tb4 = new TestBean("name4", 0);
|
||||
TestBean tb5 = new TestBean("name5", 0);
|
||||
TestBean tb6 = new TestBean("name6", 0);
|
||||
TestBean tb7 = new TestBean("name7", 0);
|
||||
TestBean tbX = new TestBean("nameX", 0);
|
||||
TestBean tbY = new TestBean("nameY", 0);
|
||||
this.array = new TestBean[] {tb0, tb1};
|
||||
this.list = new ArrayList<TestBean>();
|
||||
this.list.add(tb2);
|
||||
this.list.add(tb3);
|
||||
this.set = new TreeSet<TestBean>();
|
||||
this.set.add(tb6);
|
||||
this.set.add(tb7);
|
||||
this.map = new HashMap<String, Object>();
|
||||
this.map.put("key1", tb4);
|
||||
this.map.put("key2", tb5);
|
||||
this.map.put("key.3", tb5);
|
||||
List<TestBean> list = new ArrayList<TestBean>();
|
||||
list.add(tbX);
|
||||
list.add(tbY);
|
||||
this.map.put("key4", list);
|
||||
}
|
||||
|
||||
|
||||
public TestBean[] getArray() {
|
||||
return array;
|
||||
}
|
||||
|
||||
public void setArray(TestBean[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public Collection<?> getCollection() {
|
||||
return collection;
|
||||
}
|
||||
|
||||
public void setCollection(Collection<?> collection) {
|
||||
this.collection = collection;
|
||||
}
|
||||
|
||||
public List<TestBean> getList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
public void setList(List<TestBean> list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
public Set<TestBean> getSet() {
|
||||
return set;
|
||||
}
|
||||
|
||||
public void setSet(Set<TestBean> set) {
|
||||
this.set = set;
|
||||
}
|
||||
|
||||
public SortedSet<?> getSortedSet() {
|
||||
return sortedSet;
|
||||
}
|
||||
|
||||
public void setSortedSet(SortedSet<?> sortedSet) {
|
||||
this.sortedSet = sortedSet;
|
||||
}
|
||||
|
||||
public Map<String, Object> getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
public void setMap(Map<String, Object> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public SortedMap<?, ?> getSortedMap() {
|
||||
return sortedMap;
|
||||
}
|
||||
|
||||
public void setSortedMap(SortedMap<?, ?> sortedMap) {
|
||||
this.sortedMap = sortedMap;
|
||||
}
|
||||
|
||||
}
|
||||
60
src/test/java/test/beans/NestedTestBean.java
Normal file
60
src/test/java/test/beans/NestedTestBean.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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 test.beans;
|
||||
|
||||
/**
|
||||
* Simple nested test bean used for testing bean factories, AOP framework etc.
|
||||
*
|
||||
* @author Trevor D. Cook
|
||||
* @since 30.09.2003
|
||||
*/
|
||||
public class NestedTestBean implements INestedTestBean {
|
||||
|
||||
private String company = "";
|
||||
|
||||
public NestedTestBean() {
|
||||
}
|
||||
|
||||
public NestedTestBean(String company) {
|
||||
setCompany(company);
|
||||
}
|
||||
|
||||
public void setCompany(String company) {
|
||||
this.company = (company != null ? company : "");
|
||||
}
|
||||
|
||||
public String getCompany() {
|
||||
return company;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof NestedTestBean)) {
|
||||
return false;
|
||||
}
|
||||
NestedTestBean ntb = (NestedTestBean) obj;
|
||||
return this.company.equals(ntb.company);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.company.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "NestedTestBean: " + this.company;
|
||||
}
|
||||
|
||||
}
|
||||
54
src/test/java/test/beans/Pet.java
Normal file
54
src/test/java/test/beans/Pet.java
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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 test.beans;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @since 2.0
|
||||
*/
|
||||
public class Pet {
|
||||
|
||||
private String name;
|
||||
|
||||
public Pet(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
final Pet pet = (Pet) o;
|
||||
|
||||
if (name != null ? !name.equals(pet.name) : pet.name != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return (name != null ? name.hashCode() : 0);
|
||||
}
|
||||
|
||||
}
|
||||
437
src/test/java/test/beans/TestBean.java
Normal file
437
src/test/java/test/beans/TestBean.java
Normal file
@@ -0,0 +1,437 @@
|
||||
/*
|
||||
* 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 test.beans;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Simple test bean used for testing bean factories, the AOP framework etc.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 15 April 2001
|
||||
*/
|
||||
public class TestBean implements BeanNameAware, BeanFactoryAware, ITestBean, IOther, Comparable<Object> {
|
||||
|
||||
private String beanName;
|
||||
|
||||
private String country;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private boolean postProcessed;
|
||||
|
||||
private String name;
|
||||
|
||||
private String sex;
|
||||
|
||||
private int age;
|
||||
|
||||
private boolean jedi;
|
||||
|
||||
private ITestBean[] spouses;
|
||||
|
||||
private String touchy;
|
||||
|
||||
private String[] stringArray;
|
||||
|
||||
private Integer[] someIntegerArray;
|
||||
|
||||
private Date date = new Date();
|
||||
|
||||
private Float myFloat = new Float(0.0);
|
||||
|
||||
private Collection<?> friends = new LinkedList<Object>();
|
||||
|
||||
private Set<?> someSet = new HashSet<Object>();
|
||||
|
||||
private Map<?, ?> someMap = new HashMap<Object, Object>();
|
||||
|
||||
private List<?> someList = new ArrayList<Object>();
|
||||
|
||||
private Properties someProperties = new Properties();
|
||||
|
||||
private INestedTestBean doctor = new NestedTestBean();
|
||||
|
||||
private INestedTestBean lawyer = new NestedTestBean();
|
||||
|
||||
private IndexedTestBean nestedIndexedBean;
|
||||
|
||||
private boolean destroyed;
|
||||
|
||||
private Number someNumber;
|
||||
|
||||
private Colour favouriteColour;
|
||||
|
||||
private Boolean someBoolean;
|
||||
|
||||
private List<?> otherColours;
|
||||
|
||||
private List<?> pets;
|
||||
|
||||
|
||||
public TestBean() {
|
||||
}
|
||||
|
||||
public TestBean(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public TestBean(ITestBean spouse) {
|
||||
this.spouses = new ITestBean[] {spouse};
|
||||
}
|
||||
|
||||
public TestBean(String name, int age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public TestBean(ITestBean spouse, Properties someProperties) {
|
||||
this.spouses = new ITestBean[] {spouse};
|
||||
this.someProperties = someProperties;
|
||||
}
|
||||
|
||||
public TestBean(List<?> someList) {
|
||||
this.someList = someList;
|
||||
}
|
||||
|
||||
public TestBean(Set<?> someSet) {
|
||||
this.someSet = someSet;
|
||||
}
|
||||
|
||||
public TestBean(Map<?, ?> someMap) {
|
||||
this.someMap = someMap;
|
||||
}
|
||||
|
||||
public TestBean(Properties someProperties) {
|
||||
this.someProperties = someProperties;
|
||||
}
|
||||
|
||||
|
||||
public void setBeanName(String beanName) {
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
public String getBeanName() {
|
||||
return beanName;
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
public BeanFactory getBeanFactory() {
|
||||
return beanFactory;
|
||||
}
|
||||
|
||||
public void setPostProcessed(boolean postProcessed) {
|
||||
this.postProcessed = postProcessed;
|
||||
}
|
||||
|
||||
public boolean isPostProcessed() {
|
||||
return postProcessed;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getSex() {
|
||||
return sex;
|
||||
}
|
||||
|
||||
public void setSex(String sex) {
|
||||
this.sex = sex;
|
||||
if (this.name == null) {
|
||||
this.name = sex;
|
||||
}
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public boolean isJedi() {
|
||||
return jedi;
|
||||
}
|
||||
|
||||
public void setJedi(boolean jedi) {
|
||||
this.jedi = jedi;
|
||||
}
|
||||
|
||||
public ITestBean getSpouse() {
|
||||
return (spouses != null ? spouses[0] : null);
|
||||
}
|
||||
|
||||
public void setSpouse(ITestBean spouse) {
|
||||
this.spouses = new ITestBean[] {spouse};
|
||||
}
|
||||
|
||||
public ITestBean[] getSpouses() {
|
||||
return spouses;
|
||||
}
|
||||
|
||||
public String getTouchy() {
|
||||
return touchy;
|
||||
}
|
||||
|
||||
public void setTouchy(String touchy) throws Exception {
|
||||
if (touchy.indexOf('.') != -1) {
|
||||
throw new Exception("Can't contain a .");
|
||||
}
|
||||
if (touchy.indexOf(',') != -1) {
|
||||
throw new NumberFormatException("Number format exception: contains a ,");
|
||||
}
|
||||
this.touchy = touchy;
|
||||
}
|
||||
|
||||
public String getCountry() {
|
||||
return country;
|
||||
}
|
||||
|
||||
public void setCountry(String country) {
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
public String[] getStringArray() {
|
||||
return stringArray;
|
||||
}
|
||||
|
||||
public void setStringArray(String[] stringArray) {
|
||||
this.stringArray = stringArray;
|
||||
}
|
||||
|
||||
public Integer[] getSomeIntegerArray() {
|
||||
return someIntegerArray;
|
||||
}
|
||||
|
||||
public void setSomeIntegerArray(Integer[] someIntegerArray) {
|
||||
this.someIntegerArray = someIntegerArray;
|
||||
}
|
||||
|
||||
public Date getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(Date date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public Float getMyFloat() {
|
||||
return myFloat;
|
||||
}
|
||||
|
||||
public void setMyFloat(Float myFloat) {
|
||||
this.myFloat = myFloat;
|
||||
}
|
||||
|
||||
public Collection<?> getFriends() {
|
||||
return friends;
|
||||
}
|
||||
|
||||
public void setFriends(Collection<?> friends) {
|
||||
this.friends = friends;
|
||||
}
|
||||
|
||||
public Set<?> getSomeSet() {
|
||||
return someSet;
|
||||
}
|
||||
|
||||
public void setSomeSet(Set<?> someSet) {
|
||||
this.someSet = someSet;
|
||||
}
|
||||
|
||||
public Map<?, ?> getSomeMap() {
|
||||
return someMap;
|
||||
}
|
||||
|
||||
public void setSomeMap(Map<?, ?> someMap) {
|
||||
this.someMap = someMap;
|
||||
}
|
||||
|
||||
public List<?> getSomeList() {
|
||||
return someList;
|
||||
}
|
||||
|
||||
public void setSomeList(List<?> someList) {
|
||||
this.someList = someList;
|
||||
}
|
||||
|
||||
public Properties getSomeProperties() {
|
||||
return someProperties;
|
||||
}
|
||||
|
||||
public void setSomeProperties(Properties someProperties) {
|
||||
this.someProperties = someProperties;
|
||||
}
|
||||
|
||||
public INestedTestBean getDoctor() {
|
||||
return doctor;
|
||||
}
|
||||
|
||||
public void setDoctor(INestedTestBean doctor) {
|
||||
this.doctor = doctor;
|
||||
}
|
||||
|
||||
public INestedTestBean getLawyer() {
|
||||
return lawyer;
|
||||
}
|
||||
|
||||
public void setLawyer(INestedTestBean lawyer) {
|
||||
this.lawyer = lawyer;
|
||||
}
|
||||
|
||||
public Number getSomeNumber() {
|
||||
return someNumber;
|
||||
}
|
||||
|
||||
public void setSomeNumber(Number someNumber) {
|
||||
this.someNumber = someNumber;
|
||||
}
|
||||
|
||||
public Colour getFavouriteColour() {
|
||||
return favouriteColour;
|
||||
}
|
||||
|
||||
public void setFavouriteColour(Colour favouriteColour) {
|
||||
this.favouriteColour = favouriteColour;
|
||||
}
|
||||
|
||||
public Boolean getSomeBoolean() {
|
||||
return someBoolean;
|
||||
}
|
||||
|
||||
public void setSomeBoolean(Boolean someBoolean) {
|
||||
this.someBoolean = someBoolean;
|
||||
}
|
||||
|
||||
public IndexedTestBean getNestedIndexedBean() {
|
||||
return nestedIndexedBean;
|
||||
}
|
||||
|
||||
public void setNestedIndexedBean(IndexedTestBean nestedIndexedBean) {
|
||||
this.nestedIndexedBean = nestedIndexedBean;
|
||||
}
|
||||
|
||||
public List<?> getOtherColours() {
|
||||
return otherColours;
|
||||
}
|
||||
|
||||
public void setOtherColours(List<?> otherColours) {
|
||||
this.otherColours = otherColours;
|
||||
}
|
||||
|
||||
public List<?> getPets() {
|
||||
return pets;
|
||||
}
|
||||
|
||||
public void setPets(List<?> pets) {
|
||||
this.pets = pets;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see ITestBean#exceptional(Throwable)
|
||||
*/
|
||||
public void exceptional(Throwable t) throws Throwable {
|
||||
if (t != null) {
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
public void unreliableFileOperation() throws IOException {
|
||||
throw new IOException();
|
||||
}
|
||||
/**
|
||||
* @see ITestBean#returnsThis()
|
||||
*/
|
||||
public Object returnsThis() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IOther#absquatulate()
|
||||
*/
|
||||
public void absquatulate() {
|
||||
}
|
||||
|
||||
public int haveBirthday() {
|
||||
return age++;
|
||||
}
|
||||
|
||||
|
||||
public void destroy() {
|
||||
this.destroyed = true;
|
||||
}
|
||||
|
||||
public boolean wasDestroyed() {
|
||||
return destroyed;
|
||||
}
|
||||
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (other == null || !(other instanceof TestBean)) {
|
||||
return false;
|
||||
}
|
||||
TestBean tb2 = (TestBean) other;
|
||||
return (ObjectUtils.nullSafeEquals(this.name, tb2.name) && this.age == tb2.age);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.age;
|
||||
}
|
||||
|
||||
public int compareTo(Object other) {
|
||||
if (this.name != null && other instanceof TestBean) {
|
||||
return this.name.compareTo(((TestBean) other).getName());
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
}
|
||||
58
src/test/java/test/interceptor/NopInterceptor.java
Normal file
58
src/test/java/test/interceptor/NopInterceptor.java
Normal file
@@ -0,0 +1,58 @@
|
||||
|
||||
/*
|
||||
* Copyright 2002-2005 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 test.interceptor;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
/**
|
||||
* Trivial interceptor that can be introduced in a chain to display it.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public class NopInterceptor implements MethodInterceptor {
|
||||
|
||||
private int count;
|
||||
|
||||
/**
|
||||
* @see org.aopalliance.intercept.MethodInterceptor#invoke(MethodInvocation)
|
||||
*/
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
increment();
|
||||
return invocation.proceed();
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return this.count;
|
||||
}
|
||||
|
||||
protected void increment() {
|
||||
++count;
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof NopInterceptor)) {
|
||||
return false;
|
||||
}
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
return this.count == ((NopInterceptor) other).count;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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 test.interceptor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of NopInterceptor that is serializable and
|
||||
* can be used to test proxy serialization.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class SerializableNopInterceptor extends NopInterceptor implements Serializable {
|
||||
|
||||
/**
|
||||
* We must override this field and the related methods as
|
||||
* otherwise count won't be serialized from the non-serializable
|
||||
* NopInterceptor superclass.
|
||||
*/
|
||||
private int count;
|
||||
|
||||
public int getCount() {
|
||||
return this.count;
|
||||
}
|
||||
|
||||
protected void increment() {
|
||||
++count;
|
||||
}
|
||||
|
||||
}
|
||||
100
src/test/java/test/util/SerializationTestUtils.java
Normal file
100
src/test/java/test/util/SerializationTestUtils.java
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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 test.util;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.NotSerializableException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* Utilities for testing serializability of objects.
|
||||
* Exposes static methods for use in other test cases.
|
||||
* Contains {@link org.junit.Test} methods to test itself.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class SerializationTestUtils {
|
||||
|
||||
public static void testSerialization(Object o) throws IOException {
|
||||
OutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(o);
|
||||
}
|
||||
|
||||
public static boolean isSerializable(Object o) throws IOException {
|
||||
try {
|
||||
testSerialization(o);
|
||||
return true;
|
||||
}
|
||||
catch (NotSerializableException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static Object serializeAndDeserialize(Object o) throws IOException, ClassNotFoundException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(o);
|
||||
oos.flush();
|
||||
baos.flush();
|
||||
byte[] bytes = baos.toByteArray();
|
||||
|
||||
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
|
||||
ObjectInputStream ois = new ObjectInputStream(is);
|
||||
Object o2 = ois.readObject();
|
||||
return o2;
|
||||
}
|
||||
|
||||
|
||||
@Test(expected=NotSerializableException.class)
|
||||
public void testWithNonSerializableObject() throws IOException {
|
||||
TestBean o = new TestBean();
|
||||
assertFalse(o instanceof Serializable);
|
||||
assertFalse(isSerializable(o));
|
||||
|
||||
testSerialization(o);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithSerializableObject() throws Exception {
|
||||
int x = 5;
|
||||
int y = 10;
|
||||
Point p = new Point(x, y);
|
||||
assertTrue(p instanceof Serializable);
|
||||
|
||||
testSerialization(p);
|
||||
|
||||
assertTrue(isSerializable(p));
|
||||
|
||||
Point p2 = (Point) serializeAndDeserialize(p);
|
||||
assertNotSame(p, p2);
|
||||
assertEquals(x, (int) p2.getX());
|
||||
assertEquals(y, (int) p2.getY());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user