26 changed files with 292 additions and 1843 deletions
@ -1,128 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2015 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.test; |
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory; |
|
||||||
import org.springframework.context.ApplicationContext; |
|
||||||
import org.springframework.util.Assert; |
|
||||||
|
|
||||||
/** |
|
||||||
* This class is only used within tests in the spring-orm module. |
|
||||||
* |
|
||||||
* <p>Convenient superclass for JUnit 3.8 based tests depending on a Spring |
|
||||||
* context. The test instance itself is populated by Dependency Injection. |
|
||||||
* |
|
||||||
* <p>Supports Setter Dependency Injection: simply express dependencies |
|
||||||
* on objects in the test fixture, and they will be satisfied by autowiring |
|
||||||
* by type. |
|
||||||
* |
|
||||||
* @author Rod Johnson |
|
||||||
* @author Rob Harrop |
|
||||||
* @author Rick Evans |
|
||||||
* @author Sam Brannen |
|
||||||
* @since 1.1.1 |
|
||||||
* @deprecated as of Spring 3.0, in favor of using the listener-based test context framework |
|
||||||
* ({@link org.springframework.test.context.junit38.AbstractJUnit38SpringContextTests}) |
|
||||||
*/ |
|
||||||
@Deprecated |
|
||||||
public abstract class AbstractDependencyInjectionSpringContextTests extends AbstractSingleSpringContextTests { |
|
||||||
|
|
||||||
/** |
|
||||||
* Constant that indicates no autowiring at all. |
|
||||||
* @see #setAutowireMode |
|
||||||
*/ |
|
||||||
protected static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO; |
|
||||||
|
|
||||||
/** |
|
||||||
* Constant that indicates autowiring bean properties by name. |
|
||||||
* @see #setAutowireMode |
|
||||||
*/ |
|
||||||
protected static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME; |
|
||||||
|
|
||||||
/** |
|
||||||
* Constant that indicates autowiring bean properties by type. |
|
||||||
* @see #setAutowireMode |
|
||||||
*/ |
|
||||||
protected static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE; |
|
||||||
|
|
||||||
private int autowireMode = AUTOWIRE_BY_TYPE; |
|
||||||
|
|
||||||
private boolean dependencyCheck = true; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set the autowire mode for test properties set by Dependency Injection. |
|
||||||
* <p>The default is {@link #AUTOWIRE_BY_TYPE}. Can be set to |
|
||||||
* {@link #AUTOWIRE_BY_NAME} or {@link #AUTOWIRE_NO} instead. |
|
||||||
* @see #AUTOWIRE_BY_TYPE |
|
||||||
* @see #AUTOWIRE_BY_NAME |
|
||||||
* @see #AUTOWIRE_NO |
|
||||||
*/ |
|
||||||
protected final void setAutowireMode(final int autowireMode) { |
|
||||||
this.autowireMode = autowireMode; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the autowire mode for test properties set by Dependency Injection. |
|
||||||
*/ |
|
||||||
protected final int getAutowireMode() { |
|
||||||
return this.autowireMode; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Set whether or not dependency checking should be performed for test |
|
||||||
* properties set by Dependency Injection. |
|
||||||
* <p>The default is {@code true}, meaning that tests cannot be run |
|
||||||
* unless all properties are populated. |
|
||||||
*/ |
|
||||||
protected final void setDependencyCheck(final boolean dependencyCheck) { |
|
||||||
this.dependencyCheck = dependencyCheck; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return whether or not dependency checking should be performed for test |
|
||||||
* properties set by Dependency Injection. |
|
||||||
*/ |
|
||||||
protected final boolean isDependencyCheck() { |
|
||||||
return this.dependencyCheck; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Prepare this test instance, injecting dependencies into its bean properties. |
|
||||||
* <p>Note: if the {@link ApplicationContext} for this test instance has not |
|
||||||
* been configured (e.g., is {@code null}), dependency injection |
|
||||||
* will naturally <strong>not</strong> be performed, but an informational |
|
||||||
* message will be written to the log. |
|
||||||
* @see #injectDependencies() |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
protected void prepareTestInstance() throws Exception { |
|
||||||
if (getApplicationContext() == null) { |
|
||||||
if (this.logger.isInfoEnabled()) { |
|
||||||
this.logger.info("ApplicationContext has not been configured for test [" + getClass().getName() |
|
||||||
+ "]: dependency injection will NOT be performed."); |
|
||||||
} |
|
||||||
} |
|
||||||
else { |
|
||||||
Assert.state(getApplicationContext() != null, |
|
||||||
"injectDependencies() called without first configuring an ApplicationContext"); |
|
||||||
|
|
||||||
getApplicationContext().getBeanFactory().autowireBeanProperties(this, getAutowireMode(), isDependencyCheck()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,231 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2015 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.test; |
|
||||||
|
|
||||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory; |
|
||||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; |
|
||||||
import org.springframework.context.ConfigurableApplicationContext; |
|
||||||
import org.springframework.context.annotation.AnnotationConfigUtils; |
|
||||||
import org.springframework.context.support.GenericApplicationContext; |
|
||||||
import org.springframework.core.io.support.ResourcePatternUtils; |
|
||||||
import org.springframework.util.ClassUtils; |
|
||||||
import org.springframework.util.ResourceUtils; |
|
||||||
import org.springframework.util.StringUtils; |
|
||||||
|
|
||||||
/** |
|
||||||
* This class is only used within tests in the spring-orm module. |
|
||||||
* |
|
||||||
* <p>Abstract JUnit 3.8 test class that holds and exposes a single Spring |
|
||||||
* {@link org.springframework.context.ApplicationContext ApplicationContext}. |
|
||||||
* |
|
||||||
* <p>This class will cache contexts based on a <i>context key</i>: normally the |
|
||||||
* config locations String array describing the Spring resource descriptors |
|
||||||
* making up the context. Unless the {@link #setDirty()} method is called by a |
|
||||||
* test, the context will not be reloaded, even across different subclasses of |
|
||||||
* this test. This is particularly beneficial if your context is slow to |
|
||||||
* construct, for example if you are using Hibernate and the time taken to load |
|
||||||
* the mappings is an issue. |
|
||||||
* |
|
||||||
* <p>For such standard usage, simply override the {@link #getConfigLocations()} |
|
||||||
* method and provide the desired config files. For alternative configuration |
|
||||||
* options, see {@link #getConfigPaths()}. |
|
||||||
* |
|
||||||
* <p><b>WARNING:</b> When doing integration tests from within Eclipse, only use |
|
||||||
* classpath resource URLs. Else, you may see misleading failures when changing |
|
||||||
* context locations. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @author Rod Johnson |
|
||||||
* @author Sam Brannen |
|
||||||
* @since 2.0 |
|
||||||
* @see #getConfigLocations() |
|
||||||
* @see #getApplicationContext() |
|
||||||
* @deprecated as of Spring 3.0, in favor of using the listener-based test context framework |
|
||||||
* ({@link org.springframework.test.context.junit38.AbstractJUnit38SpringContextTests}) |
|
||||||
*/ |
|
||||||
@Deprecated |
|
||||||
abstract class AbstractSingleSpringContextTests extends AbstractSpringContextTests { |
|
||||||
|
|
||||||
private static final String SLASH = "/"; |
|
||||||
|
|
||||||
/** Application context this test will run against */ |
|
||||||
protected ConfigurableApplicationContext applicationContext; |
|
||||||
|
|
||||||
/** |
|
||||||
* This implementation is final. Override {@code onSetUp} for custom behavior. |
|
||||||
* @see #onSetUp() |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
protected final void setUp() throws Exception { |
|
||||||
// lazy load, in case getApplicationContext() has not yet been called.
|
|
||||||
if (this.applicationContext == null) { |
|
||||||
this.applicationContext = getContext(getConfigLocations()); |
|
||||||
} |
|
||||||
prepareTestInstance(); |
|
||||||
onSetUp(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Prepare this test instance, for example populating its fields. |
|
||||||
* The context has already been loaded at the time of this callback. |
|
||||||
* <p>The default implementation does nothing. |
|
||||||
* @throws Exception in case of preparation failure |
|
||||||
*/ |
|
||||||
protected void prepareTestInstance() throws Exception { |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Subclasses can override this method in place of the {@code setUp()} |
|
||||||
* method, which is final in this class. |
|
||||||
* <p>The default implementation does nothing. |
|
||||||
* @throws Exception simply let any exception propagate |
|
||||||
*/ |
|
||||||
protected void onSetUp() throws Exception { |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* This implementation is final. Override {@code onTearDown} for |
|
||||||
* custom behavior. |
|
||||||
* @see #onTearDown() |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
protected final void tearDown() throws Exception { |
|
||||||
onTearDown(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Subclasses can override this to add custom behavior on teardown. |
|
||||||
* @throws Exception simply let any exception propagate |
|
||||||
*/ |
|
||||||
protected void onTearDown() throws Exception { |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Load a Spring ApplicationContext from the given config locations. |
|
||||||
* <p>The default implementation creates a standard |
|
||||||
* {@link #createApplicationContext GenericApplicationContext}, allowing |
|
||||||
* for customizing the internal bean factory through |
|
||||||
* {@link #customizeBeanFactory}. |
|
||||||
* @param locations the config locations (as Spring resource locations, |
|
||||||
* e.g. full classpath locations or any kind of URL) |
|
||||||
* @return the corresponding ApplicationContext instance (potentially cached) |
|
||||||
* @throws Exception if context loading failed |
|
||||||
* @see #createApplicationContext(String[]) |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
protected ConfigurableApplicationContext loadContext(String... locations) throws Exception { |
|
||||||
if (this.logger.isInfoEnabled()) { |
|
||||||
this.logger.info("Loading context for locations: " + StringUtils.arrayToCommaDelimitedString(locations)); |
|
||||||
} |
|
||||||
return createApplicationContext(locations); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Create a Spring {@link ConfigurableApplicationContext} for use by this test. |
|
||||||
* <p>The default implementation creates a standard {@link GenericApplicationContext} |
|
||||||
* instance, calls the {@link #prepareApplicationContext} prepareApplicationContext} |
|
||||||
* method and the {@link #customizeBeanFactory customizeBeanFactory} method to allow |
|
||||||
* for customizing the context and its DefaultListableBeanFactory, populates the |
|
||||||
* context from the specified config {@code locations} through the configured |
|
||||||
* {@link #createBeanDefinitionReader(GenericApplicationContext) BeanDefinitionReader}, |
|
||||||
* and finally {@link ConfigurableApplicationContext#refresh() refreshes} the context. |
|
||||||
* @param locations the config locations (as Spring resource locations, |
|
||||||
* e.g. full classpath locations or any kind of URL) |
|
||||||
* @return the GenericApplicationContext instance |
|
||||||
* @see #loadContext(String...) |
|
||||||
* @see #customizeBeanFactory(DefaultListableBeanFactory) |
|
||||||
* @see #createBeanDefinitionReader(GenericApplicationContext) |
|
||||||
*/ |
|
||||||
private ConfigurableApplicationContext createApplicationContext(String... locations) { |
|
||||||
GenericApplicationContext context = new GenericApplicationContext(); |
|
||||||
new XmlBeanDefinitionReader(context).loadBeanDefinitions(locations); |
|
||||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(context); |
|
||||||
context.refresh(); |
|
||||||
return context; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Subclasses can override this method to return the locations of their |
|
||||||
* config files. |
|
||||||
* <p>A plain path will be treated as class path location, e.g.: |
|
||||||
* "org/springframework/whatever/foo.xml". Note however that you may prefix |
|
||||||
* path locations with standard Spring resource prefixes. Therefore, a |
|
||||||
* config location path prefixed with "classpath:" with behave the same as a |
|
||||||
* plain path, but a config location such as |
|
||||||
* "file:/some/path/path/location/appContext.xml" will be treated as a |
|
||||||
* filesystem location. |
|
||||||
* <p>The default implementation builds config locations for the config paths |
|
||||||
* specified through {@link #getConfigPaths()}. |
|
||||||
* @return an array of config locations |
|
||||||
* @see #getConfigPaths() |
|
||||||
* @see org.springframework.core.io.ResourceLoader#getResource(String) |
|
||||||
*/ |
|
||||||
protected final String[] getConfigLocations() { |
|
||||||
String[] paths = getConfigPaths(); |
|
||||||
String[] convertedPaths = new String[paths.length]; |
|
||||||
for (int i = 0; i < paths.length; i++) { |
|
||||||
String path = paths[i]; |
|
||||||
if (path.startsWith(SLASH)) { |
|
||||||
convertedPaths[i] = ResourceUtils.CLASSPATH_URL_PREFIX + path; |
|
||||||
} |
|
||||||
else if (!ResourcePatternUtils.isUrl(path)) { |
|
||||||
convertedPaths[i] = ResourceUtils.CLASSPATH_URL_PREFIX + SLASH |
|
||||||
+ StringUtils.cleanPath(ClassUtils.classPackageAsResourcePath(getClass()) + SLASH + path); |
|
||||||
} |
|
||||||
else { |
|
||||||
convertedPaths[i] = StringUtils.cleanPath(path); |
|
||||||
} |
|
||||||
} |
|
||||||
return convertedPaths; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Subclasses must override this method to return paths to their config |
|
||||||
* files, relative to the concrete test class. |
|
||||||
* <p>A plain path, e.g. "context.xml", will be loaded as classpath resource |
|
||||||
* from the same package that the concrete test class is defined in. A path |
|
||||||
* starting with a slash is treated as fully qualified class path location, |
|
||||||
* e.g.: "/org/springframework/whatever/foo.xml". |
|
||||||
* <p>The default implementation returns an empty array. |
|
||||||
* @return an array of config locations |
|
||||||
* @see java.lang.Class#getResource(String) |
|
||||||
*/ |
|
||||||
protected abstract String[] getConfigPaths(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the ApplicationContext that this base class manages; may be |
|
||||||
* {@code null}. |
|
||||||
*/ |
|
||||||
protected final ConfigurableApplicationContext getApplicationContext() { |
|
||||||
// lazy load, in case setUp() has not yet been called.
|
|
||||||
if (this.applicationContext == null) { |
|
||||||
try { |
|
||||||
this.applicationContext = getContext(getConfigLocations()); |
|
||||||
} |
|
||||||
catch (Exception e) { |
|
||||||
// log and continue...
|
|
||||||
if (this.logger.isDebugEnabled()) { |
|
||||||
this.logger.debug("Caught exception while retrieving the ApplicationContext for test [" + |
|
||||||
getClass().getName() + "." + getName() + "].", e); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return this.applicationContext; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,113 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2016 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.test; |
|
||||||
|
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import junit.framework.TestCase; |
|
||||||
|
|
||||||
import org.apache.commons.logging.Log; |
|
||||||
import org.apache.commons.logging.LogFactory; |
|
||||||
|
|
||||||
import org.springframework.context.ConfigurableApplicationContext; |
|
||||||
import org.springframework.util.Assert; |
|
||||||
import org.springframework.util.ObjectUtils; |
|
||||||
|
|
||||||
/** |
|
||||||
* This class is only used within tests in the spring-orm module. |
|
||||||
* |
|
||||||
* <p>Superclass for JUnit 3.8 test cases using Spring |
|
||||||
* {@link org.springframework.context.ApplicationContext ApplicationContexts}. |
|
||||||
* |
|
||||||
* <p>Maintains a static cache of contexts by key. This has significant performance |
|
||||||
* benefit if initializing the context would take time. While initializing a |
|
||||||
* Spring context itself is very quick, some beans in a context, such as a |
|
||||||
* LocalSessionFactoryBean for working with Hibernate, may take some time to |
|
||||||
* initialize. Hence it often makes sense to do that initializing once. |
|
||||||
* |
|
||||||
* <p>Any ApplicationContext created by this class will be asked to register a JVM |
|
||||||
* shutdown hook for itself. Unless the context gets closed early, all context |
|
||||||
* instances will be automatically closed on JVM shutdown. This allows for |
|
||||||
* freeing external resources held by beans within the context, e.g. temporary |
|
||||||
* files. |
|
||||||
* |
|
||||||
* @author Rod Johnson |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @author Sam Brannen |
|
||||||
* @since 1.1.1 |
|
||||||
* @see AbstractSingleSpringContextTests |
|
||||||
* @see AbstractDependencyInjectionSpringContextTests |
|
||||||
* @see AbstractTransactionalSpringContextTests |
|
||||||
* @see AbstractTransactionalDataSourceSpringContextTests |
|
||||||
* @deprecated as of Spring 3.0, in favor of using the listener-based test context framework |
|
||||||
* ({@link org.springframework.test.context.junit38.AbstractJUnit38SpringContextTests}) |
|
||||||
*/ |
|
||||||
@Deprecated |
|
||||||
abstract class AbstractSpringContextTests extends TestCase { |
|
||||||
|
|
||||||
protected final Log logger = LogFactory.getLog(getClass()); |
|
||||||
|
|
||||||
private static Map<String, ConfigurableApplicationContext> contextKeyToContextMap = |
|
||||||
new HashMap<>(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Explicitly add an ApplicationContext instance under a given key. |
|
||||||
* <p>This is not meant to be used by subclasses. It is rather exposed for |
|
||||||
* special test suite environments. |
|
||||||
* @param locations the context key |
|
||||||
* @param context the ApplicationContext instance |
|
||||||
*/ |
|
||||||
public final void addContext(String[] locations, ConfigurableApplicationContext context) { |
|
||||||
Assert.notNull(context, "ApplicationContext must not be null"); |
|
||||||
contextKeyToContextMap.put(contextKey(locations), context); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Obtain an ApplicationContext for the given key, potentially cached. |
|
||||||
* @param locations the context key; may be {@code null}. |
|
||||||
* @return the corresponding ApplicationContext instance (potentially cached), |
|
||||||
* or {@code null} if the provided {@code key} is <em>empty</em> |
|
||||||
*/ |
|
||||||
protected final ConfigurableApplicationContext getContext(String... locations) throws Exception { |
|
||||||
if (ObjectUtils.isEmpty(locations)) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
String key = contextKey(locations); |
|
||||||
ConfigurableApplicationContext ctx = contextKeyToContextMap.get(key); |
|
||||||
if (ctx == null) { |
|
||||||
ctx = loadContext(locations); |
|
||||||
ctx.registerShutdownHook(); |
|
||||||
contextKeyToContextMap.put(key, ctx); |
|
||||||
} |
|
||||||
return ctx; |
|
||||||
} |
|
||||||
|
|
||||||
private final String contextKey(String... locations) { |
|
||||||
return ObjectUtils.nullSafeToString(locations); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Load a new ApplicationContext for the given key. |
|
||||||
* <p>To be implemented by subclasses. |
|
||||||
* @param key the context key |
|
||||||
* @return the corresponding ApplicationContext instance (new) |
|
||||||
*/ |
|
||||||
protected abstract ConfigurableApplicationContext loadContext(String... locations) throws Exception; |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,484 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2015 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.test; |
|
||||||
|
|
||||||
import java.lang.reflect.Method; |
|
||||||
import java.lang.reflect.Modifier; |
|
||||||
import javax.sql.DataSource; |
|
||||||
|
|
||||||
import org.springframework.core.io.Resource; |
|
||||||
import org.springframework.dao.DataAccessException; |
|
||||||
import org.springframework.jdbc.core.JdbcTemplate; |
|
||||||
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; |
|
||||||
import org.springframework.transaction.PlatformTransactionManager; |
|
||||||
import org.springframework.transaction.TransactionDefinition; |
|
||||||
import org.springframework.transaction.TransactionException; |
|
||||||
import org.springframework.transaction.TransactionStatus; |
|
||||||
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource; |
|
||||||
import org.springframework.transaction.interceptor.TransactionAttributeSource; |
|
||||||
import org.springframework.transaction.support.DefaultTransactionDefinition; |
|
||||||
|
|
||||||
/** |
|
||||||
* This class is only used within tests in the spring-orm module. |
|
||||||
* |
|
||||||
* <p>Convenient base class for JUnit 3.8 based tests that should occur in a |
|
||||||
* transaction, but normally will roll the transaction back on the completion of |
|
||||||
* each test. |
|
||||||
* |
|
||||||
* <p>This is useful in a range of circumstances, allowing the following benefits: |
|
||||||
* <ul> |
|
||||||
* <li>Ability to delete or insert any data in the database, without affecting |
|
||||||
* other tests |
|
||||||
* <li>Providing a transactional context for any code requiring a transaction |
|
||||||
* <li>Ability to write anything to the database without any need to clean up. |
|
||||||
* </ul> |
|
||||||
* |
|
||||||
* <p>This class is typically very fast, compared to traditional setup/teardown |
|
||||||
* scripts. |
|
||||||
* |
|
||||||
* <p>If data should be left in the database, call the {@link #setComplete()} |
|
||||||
* method in each test. The {@link #setDefaultRollback "defaultRollback"} |
|
||||||
* property, which defaults to "true", determines whether transactions will |
|
||||||
* complete by default. |
|
||||||
* |
|
||||||
* <p>It is even possible to end the transaction early; for example, to verify lazy |
|
||||||
* loading behavior of an O/R mapping tool. (This is a valuable away to avoid |
|
||||||
* unexpected errors when testing a web UI, for example.) Simply call the |
|
||||||
* {@link #endTransaction()} method. Execution will then occur without a |
|
||||||
* transactional context. |
|
||||||
* |
|
||||||
* <p>The {@link #startNewTransaction()} method may be called after a call to |
|
||||||
* {@link #endTransaction()} if you wish to create a new transaction, quite |
|
||||||
* independent of the old transaction. The new transaction's default fate will |
|
||||||
* be to roll back, unless {@link #setComplete()} is called again during the |
|
||||||
* scope of the new transaction. Any number of transactions may be created and |
|
||||||
* ended in this way. The final transaction will automatically be rolled back |
|
||||||
* when the test case is torn down. |
|
||||||
* |
|
||||||
* <p>Transactional behavior requires a single bean in the context implementing the |
|
||||||
* {@link PlatformTransactionManager} interface. This will be set by the |
|
||||||
* superclass's Dependency Injection mechanism. If using the superclass's Field |
|
||||||
* Injection mechanism, the implementation should be named "transactionManager". |
|
||||||
* This mechanism allows the use of the |
|
||||||
* {@link AbstractDependencyInjectionSpringContextTests} superclass even when |
|
||||||
* there is more than one transaction manager in the context. |
|
||||||
* |
|
||||||
* <p><b>This base class can also be used without transaction management, if no |
|
||||||
* PlatformTransactionManager bean is found in the context provided.</b> Be |
|
||||||
* careful about using this mode, as it allows the potential to permanently |
|
||||||
* modify data. This mode is available only if dependency checking is turned off |
|
||||||
* in the {@link AbstractDependencyInjectionSpringContextTests} superclass. The |
|
||||||
* non-transactional capability is provided to enable use of the same subclass |
|
||||||
* in different environments. |
|
||||||
* |
|
||||||
* <p>Adds some convenience functionality for JDBC access. Expects a |
|
||||||
* {@link javax.sql.DataSource} bean to be defined in the Spring application |
|
||||||
* context. |
|
||||||
* |
|
||||||
* <p>This class exposes a {@link org.springframework.jdbc.core.JdbcTemplate} |
|
||||||
* and provides an easy way to delete from the database in a new transaction. |
|
||||||
* |
|
||||||
* <p>Test methods can be annotated with the regular Spring |
|
||||||
* {@link org.springframework.transaction.annotation.Transactional @Transactional} |
|
||||||
* annotation — for example, to force execution in a read-only transaction |
|
||||||
* or to prevent any transaction from being created at all by setting the propagation |
|
||||||
* level to {@code NOT_SUPPORTED}. |
|
||||||
* |
|
||||||
* @author Rod Johnson |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @author Thomas Risberg |
|
||||||
* @author Sam Brannen |
|
||||||
* @since 1.1.1 |
|
||||||
* @deprecated as of Spring 3.0, in favor of using the listener-based test context framework |
|
||||||
* ({@link org.springframework.test.context.junit38.AbstractJUnit38SpringContextTests}) |
|
||||||
*/ |
|
||||||
@Deprecated |
|
||||||
public abstract class AbstractTransactionalSpringContextTests extends AbstractDependencyInjectionSpringContextTests { |
|
||||||
|
|
||||||
/** The transaction manager to use */ |
|
||||||
protected PlatformTransactionManager transactionManager; |
|
||||||
|
|
||||||
/** Should we roll back by default? */ |
|
||||||
private boolean defaultRollback = true; |
|
||||||
|
|
||||||
/** Should we commit the current transaction? */ |
|
||||||
private boolean complete = false; |
|
||||||
|
|
||||||
/** Number of transactions started */ |
|
||||||
private int transactionsStarted = 0; |
|
||||||
|
|
||||||
/** |
|
||||||
* Transaction definition used by this test class: by default, a plain |
|
||||||
* DefaultTransactionDefinition. Subclasses can change this to cause |
|
||||||
* different behavior. |
|
||||||
*/ |
|
||||||
protected TransactionDefinition transactionDefinition = new DefaultTransactionDefinition(); |
|
||||||
|
|
||||||
private final TransactionAttributeSource transactionAttributeSource = new AnnotationTransactionAttributeSource(); |
|
||||||
|
|
||||||
/** |
|
||||||
* TransactionStatus for this test. Typical subclasses won't need to use it. |
|
||||||
*/ |
|
||||||
protected TransactionStatus transactionStatus; |
|
||||||
|
|
||||||
protected JdbcTemplate jdbcTemplate; |
|
||||||
|
|
||||||
/** |
|
||||||
* Did this test delete any tables? If so, we forbid transaction completion, |
|
||||||
* and only allow rollback. |
|
||||||
*/ |
|
||||||
private boolean zappedTables; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Setter: DataSource is provided by Dependency Injection. |
|
||||||
*/ |
|
||||||
public void setDataSource(DataSource dataSource) { |
|
||||||
this.jdbcTemplate = new JdbcTemplate(dataSource); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Specify the transaction manager to use. No transaction management will be |
|
||||||
* available if this is not set. Populated through dependency injection by |
|
||||||
* the superclass. |
|
||||||
* <p> |
|
||||||
* This mode works only if dependency checking is turned off in the |
|
||||||
* {@link AbstractDependencyInjectionSpringContextTests} superclass. |
|
||||||
*/ |
|
||||||
public void setTransactionManager(PlatformTransactionManager transactionManager) { |
|
||||||
this.transactionManager = transactionManager; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Subclasses can set this value in their constructor to change the default, |
|
||||||
* which is always to roll the transaction back. |
|
||||||
*/ |
|
||||||
protected void setDefaultRollback(final boolean defaultRollback) { |
|
||||||
this.defaultRollback = defaultRollback; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get the <em>default rollback</em> flag for this test. |
|
||||||
* @see #setDefaultRollback(boolean) |
|
||||||
* @return The <em>default rollback</em> flag. |
|
||||||
*/ |
|
||||||
protected boolean isDefaultRollback() { |
|
||||||
return this.defaultRollback; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Determine whether or not to roll back transactions for the current test. |
|
||||||
* <p>The default implementation simply delegates to {@link #isDefaultRollback()}. |
|
||||||
* Subclasses can override as necessary. |
|
||||||
* @return the <em>rollback</em> flag for the current test |
|
||||||
*/ |
|
||||||
protected boolean isRollback() { |
|
||||||
boolean rollback = isDefaultRollback(); |
|
||||||
if (this.logger.isDebugEnabled()) { |
|
||||||
this.logger.debug("Using default rollback [" + rollback + "] for test [" + getName() + "]."); |
|
||||||
} |
|
||||||
return rollback; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Call this method in an overridden {@link #runBare()} method to prevent |
|
||||||
* transactional execution. |
|
||||||
*/ |
|
||||||
protected void preventTransaction() { |
|
||||||
this.transactionDefinition = null; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Call this method in an overridden {@link #runBare()} method to override |
|
||||||
* the transaction attributes that will be used, so that {@link #setUp()} |
|
||||||
* and {@link #tearDown()} behavior is modified. |
|
||||||
* @param customDefinition the custom transaction definition |
|
||||||
*/ |
|
||||||
protected void setTransactionDefinition(TransactionDefinition customDefinition) { |
|
||||||
this.transactionDefinition = customDefinition; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* This implementation creates a transaction before test execution. |
|
||||||
* <p>Override {@link #onSetUpBeforeTransaction()} and/or |
|
||||||
* {@link #onSetUpInTransaction()} to add custom set-up behavior for |
|
||||||
* transactional execution. Alternatively, override this method for general |
|
||||||
* set-up behavior, calling {@code super.onSetUp()} as part of your |
|
||||||
* method implementation. |
|
||||||
* @throws Exception simply let any exception propagate |
|
||||||
* @see #onTearDown() |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
protected void onSetUp() throws Exception { |
|
||||||
this.complete = !this.isRollback(); |
|
||||||
|
|
||||||
if (this.transactionManager == null) { |
|
||||||
this.logger.info("No transaction manager set: test will NOT run within a transaction"); |
|
||||||
} |
|
||||||
else if (this.transactionDefinition == null) { |
|
||||||
this.logger.info("No transaction definition set: test will NOT run within a transaction"); |
|
||||||
} |
|
||||||
else { |
|
||||||
onSetUpBeforeTransaction(); |
|
||||||
startNewTransaction(); |
|
||||||
try { |
|
||||||
onSetUpInTransaction(); |
|
||||||
} |
|
||||||
catch (final Exception ex) { |
|
||||||
endTransaction(); |
|
||||||
throw ex; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Subclasses can override this method to perform any setup operations, such |
|
||||||
* as populating a database table, <i>before</i> the transaction created by |
|
||||||
* this class. Only invoked if there <i>is</i> a transaction: that is, if |
|
||||||
* {@link #preventTransaction()} has not been invoked in an overridden |
|
||||||
* {@link #runTest()} method. |
|
||||||
* @throws Exception simply let any exception propagate |
|
||||||
*/ |
|
||||||
protected void onSetUpBeforeTransaction() throws Exception { |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Subclasses can override this method to perform any setup operations, such |
|
||||||
* as populating a database table, <i>within</i> the transaction created by |
|
||||||
* this class. |
|
||||||
* <p><b>NB:</b> Not called if there is no transaction management, due to no |
|
||||||
* transaction manager being provided in the context. |
|
||||||
* <p>If any {@link Throwable} is thrown, the transaction that has been started |
|
||||||
* prior to the execution of this method will be |
|
||||||
* {@link #endTransaction() ended} (or rather an attempt will be made to |
|
||||||
* {@link #endTransaction() end it gracefully}); The offending |
|
||||||
* {@link Throwable} will then be rethrown. |
|
||||||
* @throws Exception simply let any exception propagate |
|
||||||
*/ |
|
||||||
protected void onSetUpInTransaction() throws Exception { |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* This implementation ends the transaction after test execution. |
|
||||||
* <p>Override {@link #onTearDownInTransaction()} and/or |
|
||||||
* {@link #onTearDownAfterTransaction()} to add custom tear-down behavior |
|
||||||
* for transactional execution. Alternatively, override this method for |
|
||||||
* general tear-down behavior, calling {@code super.onTearDown()} as |
|
||||||
* part of your method implementation. |
|
||||||
* <p>Note that {@link #onTearDownInTransaction()} will only be called if a |
|
||||||
* transaction is still active at the time of the test shutdown. In |
|
||||||
* particular, it will <i>not</i> be called if the transaction has been |
|
||||||
* completed with an explicit {@link #endTransaction()} call before. |
|
||||||
* @throws Exception simply let any exception propagate |
|
||||||
* @see #onSetUp() |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
protected void onTearDown() throws Exception { |
|
||||||
// Call onTearDownInTransaction and end transaction if the transaction
|
|
||||||
// is still active.
|
|
||||||
if (this.transactionStatus != null && !this.transactionStatus.isCompleted()) { |
|
||||||
try { |
|
||||||
onTearDownInTransaction(); |
|
||||||
} |
|
||||||
finally { |
|
||||||
endTransaction(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Call onTearDownAfterTransaction if there was at least one
|
|
||||||
// transaction, even if it has been completed early through an
|
|
||||||
// endTransaction() call.
|
|
||||||
if (this.transactionsStarted > 0) { |
|
||||||
onTearDownAfterTransaction(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Subclasses can override this method to run invariant tests here. The |
|
||||||
* transaction is <i>still active</i> at this point, so any changes made in |
|
||||||
* the transaction will still be visible. However, there is no need to clean |
|
||||||
* up the database, as a rollback will follow automatically. |
|
||||||
* <p><b>NB:</b> Not called if there is no actual transaction, for example due |
|
||||||
* to no transaction manager being provided in the application context. |
|
||||||
* @throws Exception simply let any exception propagate |
|
||||||
*/ |
|
||||||
protected void onTearDownInTransaction() throws Exception { |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Subclasses can override this method to perform cleanup after a |
|
||||||
* transaction here. At this point, the transaction is <i>not active anymore</i>. |
|
||||||
* @throws Exception simply let any exception propagate |
|
||||||
*/ |
|
||||||
protected void onTearDownAfterTransaction() throws Exception { |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Overridden to populate transaction definition from annotations. |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public void runBare() throws Throwable { |
|
||||||
final Method testMethod = getTestMethod(); |
|
||||||
|
|
||||||
TransactionDefinition explicitTransactionDefinition = this.transactionAttributeSource.getTransactionAttribute( |
|
||||||
testMethod, getClass()); |
|
||||||
if (explicitTransactionDefinition != null) { |
|
||||||
this.logger.info("Custom transaction definition [" + explicitTransactionDefinition + "] for test method [" |
|
||||||
+ getName() + "]."); |
|
||||||
setTransactionDefinition(explicitTransactionDefinition); |
|
||||||
} |
|
||||||
|
|
||||||
if (this.transactionDefinition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) { |
|
||||||
preventTransaction(); |
|
||||||
} |
|
||||||
|
|
||||||
super.runBare(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get the current test method. |
|
||||||
*/ |
|
||||||
protected Method getTestMethod() { |
|
||||||
assertNotNull("TestCase.getName() cannot be null", getName()); |
|
||||||
Method testMethod = null; |
|
||||||
try { |
|
||||||
// Use same algorithm as JUnit itself to retrieve the test method
|
|
||||||
// about to be executed (the method name is returned by getName). It
|
|
||||||
// has to be public so we can retrieve it.
|
|
||||||
testMethod = getClass().getMethod(getName(), (Class[]) null); |
|
||||||
} |
|
||||||
catch (NoSuchMethodException ex) { |
|
||||||
fail("Method '" + getName() + "' not found"); |
|
||||||
} |
|
||||||
if (!Modifier.isPublic(testMethod.getModifiers())) { |
|
||||||
fail("Method '" + getName() + "' should be public"); |
|
||||||
} |
|
||||||
return testMethod; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Cause the transaction to commit for this test method, even if the test |
|
||||||
* method is configured to {@link #isRollback() rollback}. |
|
||||||
* @throws IllegalStateException if the operation cannot be set to complete |
|
||||||
* as no transaction manager was provided |
|
||||||
*/ |
|
||||||
protected void setComplete() { |
|
||||||
if (this.transactionManager == null) { |
|
||||||
throw new IllegalStateException("No transaction manager set"); |
|
||||||
} |
|
||||||
if (this.zappedTables) { |
|
||||||
throw new IllegalStateException("Cannot set complete after deleting tables"); |
|
||||||
} |
|
||||||
this.complete = true; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Immediately force a commit or rollback of the transaction, according to |
|
||||||
* the {@code complete} and {@link #isRollback() rollback} flags. |
|
||||||
* <p>Can be used to explicitly let the transaction end early, for example to |
|
||||||
* check whether lazy associations of persistent objects work outside of a |
|
||||||
* transaction (that is, have been initialized properly). |
|
||||||
* @see #setComplete() |
|
||||||
*/ |
|
||||||
protected void endTransaction() { |
|
||||||
final boolean commit = this.complete || !isRollback(); |
|
||||||
if (this.transactionStatus != null) { |
|
||||||
try { |
|
||||||
if (commit) { |
|
||||||
this.transactionManager.commit(this.transactionStatus); |
|
||||||
this.logger.debug("Committed transaction after execution of test [" + getName() + "]."); |
|
||||||
} |
|
||||||
else { |
|
||||||
this.transactionManager.rollback(this.transactionStatus); |
|
||||||
this.logger.debug("Rolled back transaction after execution of test [" + getName() + "]."); |
|
||||||
} |
|
||||||
} |
|
||||||
finally { |
|
||||||
this.transactionStatus = null; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Start a new transaction. Only call this method if |
|
||||||
* {@link #endTransaction()} has been called. {@link #setComplete()} can be |
|
||||||
* used again in the new transaction. The fate of the new transaction, by |
|
||||||
* default, will be the usual rollback. |
|
||||||
* @throws TransactionException if starting the transaction failed |
|
||||||
*/ |
|
||||||
protected void startNewTransaction() throws TransactionException { |
|
||||||
if (this.transactionStatus != null) { |
|
||||||
throw new IllegalStateException("Cannot start new transaction without ending existing transaction: " |
|
||||||
+ "Invoke endTransaction() before startNewTransaction()"); |
|
||||||
} |
|
||||||
if (this.transactionManager == null) { |
|
||||||
throw new IllegalStateException("No transaction manager set"); |
|
||||||
} |
|
||||||
|
|
||||||
this.transactionStatus = this.transactionManager.getTransaction(this.transactionDefinition); |
|
||||||
++this.transactionsStarted; |
|
||||||
this.complete = !this.isRollback(); |
|
||||||
|
|
||||||
if (this.logger.isDebugEnabled()) { |
|
||||||
this.logger.debug("Began transaction (" + this.transactionsStarted + "): transaction manager [" |
|
||||||
+ this.transactionManager + "]; rollback [" + this.isRollback() + "]."); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Convenient method to delete all rows from these tables. |
|
||||||
* Calling this method will make avoidance of rollback by calling |
|
||||||
* {@code setComplete()} impossible. |
|
||||||
* @see #setComplete |
|
||||||
*/ |
|
||||||
protected void deleteFromTables(String... names) { |
|
||||||
for (String name : names) { |
|
||||||
int rowCount = this.jdbcTemplate.update("DELETE FROM " + name); |
|
||||||
if (logger.isInfoEnabled()) { |
|
||||||
logger.info("Deleted " + rowCount + " rows from table " + name); |
|
||||||
} |
|
||||||
} |
|
||||||
this.zappedTables = true; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Count the rows in the given table |
|
||||||
* @param tableName table name to count rows in |
|
||||||
* @return the number of rows in the table |
|
||||||
*/ |
|
||||||
protected int countRowsInTable(String tableName) { |
|
||||||
return this.jdbcTemplate.queryForObject("SELECT COUNT(0) FROM " + tableName, Integer.class); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Execute the given SQL script. |
|
||||||
* <p>Use with caution outside of a transaction! |
|
||||||
* <p>The script will normally be loaded by classpath. |
|
||||||
* <p><b>Do not use this method to execute DDL if you expect rollback.</b> |
|
||||||
* @param sqlResourcePath the Spring resource path for the SQL script |
|
||||||
* @param continueOnError whether or not to continue without throwing an |
|
||||||
* exception in the event of an error |
|
||||||
* @throws DataAccessException if there is an error executing a statement |
|
||||||
* @see ResourceDatabasePopulator |
|
||||||
* @see #setSqlScriptEncoding |
|
||||||
*/ |
|
||||||
protected void executeSqlScript(String sqlResourcePath, boolean continueOnError) throws DataAccessException { |
|
||||||
Resource resource = this.applicationContext.getResource(sqlResourcePath); |
|
||||||
new ResourceDatabasePopulator(continueOnError, false, null, resource).execute(jdbcTemplate.getDataSource()); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,354 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2016 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.test.jpa; |
|
||||||
|
|
||||||
import java.lang.instrument.ClassFileTransformer; |
|
||||||
import java.lang.reflect.Constructor; |
|
||||||
import java.lang.reflect.Field; |
|
||||||
import java.lang.reflect.InvocationTargetException; |
|
||||||
import java.lang.reflect.Method; |
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
import javax.persistence.EntityManager; |
|
||||||
import javax.persistence.EntityManagerFactory; |
|
||||||
|
|
||||||
import junit.framework.TestCase; |
|
||||||
|
|
||||||
import org.springframework.beans.BeanUtils; |
|
||||||
import org.springframework.beans.BeansException; |
|
||||||
import org.springframework.beans.factory.config.BeanPostProcessor; |
|
||||||
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; |
|
||||||
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.ConfigurableApplicationContext; |
|
||||||
import org.springframework.context.support.GenericApplicationContext; |
|
||||||
import org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver; |
|
||||||
import org.springframework.instrument.classloading.LoadTimeWeaver; |
|
||||||
import org.springframework.instrument.classloading.ResourceOverridingShadowingClassLoader; |
|
||||||
import org.springframework.instrument.classloading.ShadowingClassLoader; |
|
||||||
import org.springframework.orm.jpa.ExtendedEntityManagerCreator; |
|
||||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; |
|
||||||
import org.springframework.orm.jpa.SharedEntityManagerCreator; |
|
||||||
import org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager; |
|
||||||
import org.springframework.test.AbstractTransactionalSpringContextTests; |
|
||||||
import org.springframework.util.ReflectionUtils; |
|
||||||
import org.springframework.util.StringUtils; |
|
||||||
|
|
||||||
/** |
|
||||||
* This class is only used within tests in the spring-orm module. |
|
||||||
* |
|
||||||
* <p>Convenient support class for JPA-related tests. Offers the same contract as |
|
||||||
* AbstractTransactionalDataSourceSpringContextTests and equally good performance, |
|
||||||
* even when performing the instrumentation required by the JPA specification. |
|
||||||
* |
|
||||||
* <p>Exposes an EntityManagerFactory and a shared EntityManager. |
|
||||||
* Requires an EntityManagerFactory to be injected, plus the DataSource and |
|
||||||
* JpaTransactionManager through the superclass. |
|
||||||
* |
|
||||||
* <p>When using Xerces, make sure a post 2.0.2 version is available on the classpath |
|
||||||
* to avoid a critical |
|
||||||
* <a href="http://nagoya.apache.org/bugzilla/show_bug.cgi?id=16014"/>bug</a> |
|
||||||
* that leads to StackOverflow. Maven users are likely to encounter this problem since |
|
||||||
* 2.0.2 is used by default. |
|
||||||
* |
|
||||||
* <p>A workaround is to explicitly specify the Xerces version inside the Maven POM: |
|
||||||
* <pre> |
|
||||||
* <dependency> |
|
||||||
* <groupId>xerces</groupId> |
|
||||||
* <artifactId>xercesImpl</artifactId> |
|
||||||
* <version>2.8.1</version> |
|
||||||
* </dependency> |
|
||||||
* </pre> |
|
||||||
* |
|
||||||
* @author Rod Johnson |
|
||||||
* @author Rob Harrop |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.0 |
|
||||||
* @deprecated as of Spring 3.0, in favor of using the listener-based test context framework |
|
||||||
* ({@link org.springframework.test.context.junit38.AbstractJUnit38SpringContextTests}) |
|
||||||
*/ |
|
||||||
@Deprecated |
|
||||||
public abstract class AbstractJpaTests extends AbstractTransactionalSpringContextTests { |
|
||||||
|
|
||||||
private static final String DEFAULT_ORM_XML_LOCATION = "META-INF/orm.xml"; |
|
||||||
|
|
||||||
/** |
|
||||||
* Map from String defining unique combination of config locations, to ApplicationContext. |
|
||||||
* Values are intentionally not strongly typed, to avoid potential class cast exceptions |
|
||||||
* through use between different class loaders. |
|
||||||
*/ |
|
||||||
private static Map<String, Object> contextCache = new HashMap<>(); |
|
||||||
|
|
||||||
private static Map<String, ClassLoader> classLoaderCache = new HashMap<>(); |
|
||||||
|
|
||||||
protected EntityManagerFactory entityManagerFactory; |
|
||||||
|
|
||||||
/** |
|
||||||
* If this instance is in a shadow loader, this variable |
|
||||||
* will contain the parent instance of the subclass. |
|
||||||
* The class will not be the same as the class of the |
|
||||||
* shadow instance, as it was loaded by a different class loader, |
|
||||||
* but it can be invoked reflectively. The shadowParent |
|
||||||
* and the shadow loader can communicate reflectively |
|
||||||
* but not through direct invocation. |
|
||||||
*/ |
|
||||||
private Object shadowParent; |
|
||||||
|
|
||||||
/** |
|
||||||
* Subclasses can use this in test cases. |
|
||||||
* It will participate in any current transaction. |
|
||||||
*/ |
|
||||||
protected EntityManager sharedEntityManager; |
|
||||||
|
|
||||||
|
|
||||||
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) { |
|
||||||
this.entityManagerFactory = entityManagerFactory; |
|
||||||
this.sharedEntityManager = SharedEntityManagerCreator.createSharedEntityManager(this.entityManagerFactory); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Create an EntityManager that will always automatically enlist itself in current |
|
||||||
* transactions, in contrast to an EntityManager returned by |
|
||||||
* {@code EntityManagerFactory.createEntityManager()} |
|
||||||
* (which requires an explicit {@code joinTransaction()} call). |
|
||||||
*/ |
|
||||||
protected EntityManager createContainerManagedEntityManager() { |
|
||||||
return ExtendedEntityManagerCreator.createContainerManagedEntityManager(this.entityManagerFactory); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Subclasses should override this method if they wish to disable shadow class loading. |
|
||||||
* <p>The default implementation deactivates shadow class loading if Spring's |
|
||||||
* InstrumentationSavingAgent has been configured on VM startup. |
|
||||||
*/ |
|
||||||
protected boolean shouldUseShadowLoader() { |
|
||||||
return !InstrumentationLoadTimeWeaver.isInstrumentationAvailable(); |
|
||||||
} |
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" }) |
|
||||||
@Override |
|
||||||
public void runBare() throws Throwable { |
|
||||||
if (!shouldUseShadowLoader()) { |
|
||||||
super.runBare(); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
String combinationOfContextLocationsForThisTestClass = cacheKeys(); |
|
||||||
ClassLoader classLoaderForThisTestClass = getClass().getClassLoader(); |
|
||||||
// save the TCCL
|
|
||||||
ClassLoader initialClassLoader = Thread.currentThread().getContextClassLoader(); |
|
||||||
|
|
||||||
if (this.shadowParent != null) { |
|
||||||
Thread.currentThread().setContextClassLoader(classLoaderForThisTestClass); |
|
||||||
super.runBare(); |
|
||||||
} |
|
||||||
|
|
||||||
else { |
|
||||||
ShadowingClassLoader shadowingClassLoader = (ShadowingClassLoader) classLoaderCache.get(combinationOfContextLocationsForThisTestClass); |
|
||||||
|
|
||||||
if (shadowingClassLoader == null) { |
|
||||||
shadowingClassLoader = (ShadowingClassLoader) createShadowingClassLoader(classLoaderForThisTestClass); |
|
||||||
classLoaderCache.put(combinationOfContextLocationsForThisTestClass, shadowingClassLoader); |
|
||||||
} |
|
||||||
try { |
|
||||||
Thread.currentThread().setContextClassLoader(shadowingClassLoader); |
|
||||||
String[] configLocations = getConfigLocations(); |
|
||||||
|
|
||||||
// Do not strongly type, to avoid ClassCastException.
|
|
||||||
Object cachedContext = contextCache.get(combinationOfContextLocationsForThisTestClass); |
|
||||||
|
|
||||||
if (cachedContext == null) { |
|
||||||
|
|
||||||
// Create the LoadTimeWeaver.
|
|
||||||
Class shadowingLoadTimeWeaverClass = shadowingClassLoader.loadClass(ShadowingLoadTimeWeaver.class.getName()); |
|
||||||
Constructor constructor = shadowingLoadTimeWeaverClass.getConstructor(ClassLoader.class); |
|
||||||
constructor.setAccessible(true); |
|
||||||
Object ltw = constructor.newInstance(shadowingClassLoader); |
|
||||||
|
|
||||||
// Create the BeanFactory.
|
|
||||||
Class beanFactoryClass = shadowingClassLoader.loadClass(DefaultListableBeanFactory.class.getName()); |
|
||||||
Object beanFactory = BeanUtils.instantiateClass(beanFactoryClass); |
|
||||||
|
|
||||||
// Create the BeanDefinitionReader.
|
|
||||||
Class beanDefinitionReaderClass = shadowingClassLoader.loadClass(XmlBeanDefinitionReader.class.getName()); |
|
||||||
Class beanDefinitionRegistryClass = shadowingClassLoader.loadClass(BeanDefinitionRegistry.class.getName()); |
|
||||||
Object reader = beanDefinitionReaderClass.getConstructor(beanDefinitionRegistryClass).newInstance(beanFactory); |
|
||||||
|
|
||||||
// Load the bean definitions into the BeanFactory.
|
|
||||||
Method loadBeanDefinitions = beanDefinitionReaderClass.getMethod("loadBeanDefinitions", String[].class); |
|
||||||
loadBeanDefinitions.invoke(reader, new Object[] {configLocations}); |
|
||||||
|
|
||||||
// Create LoadTimeWeaver-injecting BeanPostProcessor.
|
|
||||||
Class loadTimeWeaverInjectingBeanPostProcessorClass = shadowingClassLoader.loadClass(LoadTimeWeaverInjectingBeanPostProcessor.class.getName()); |
|
||||||
Class loadTimeWeaverClass = shadowingClassLoader.loadClass(LoadTimeWeaver.class.getName()); |
|
||||||
Constructor bppConstructor = loadTimeWeaverInjectingBeanPostProcessorClass.getConstructor(loadTimeWeaverClass); |
|
||||||
bppConstructor.setAccessible(true); |
|
||||||
Object beanPostProcessor = bppConstructor.newInstance(ltw); |
|
||||||
|
|
||||||
// Add LoadTimeWeaver-injecting BeanPostProcessor.
|
|
||||||
Class beanPostProcessorClass = shadowingClassLoader.loadClass(BeanPostProcessor.class.getName()); |
|
||||||
Method addBeanPostProcessor = beanFactoryClass.getMethod("addBeanPostProcessor", beanPostProcessorClass); |
|
||||||
addBeanPostProcessor.invoke(beanFactory, beanPostProcessor); |
|
||||||
|
|
||||||
// Create the GenericApplicationContext.
|
|
||||||
Class genericApplicationContextClass = shadowingClassLoader.loadClass(GenericApplicationContext.class.getName()); |
|
||||||
Class defaultListableBeanFactoryClass = shadowingClassLoader.loadClass(DefaultListableBeanFactory.class.getName()); |
|
||||||
cachedContext = genericApplicationContextClass.getConstructor(defaultListableBeanFactoryClass).newInstance(beanFactory); |
|
||||||
|
|
||||||
// Invoke the context's "refresh" method.
|
|
||||||
genericApplicationContextClass.getMethod("refresh").invoke(cachedContext); |
|
||||||
|
|
||||||
// Store the context reference in the cache.
|
|
||||||
contextCache.put(combinationOfContextLocationsForThisTestClass, cachedContext); |
|
||||||
} |
|
||||||
// create the shadowed test
|
|
||||||
Class shadowedTestClass = shadowingClassLoader.loadClass(getClass().getName()); |
|
||||||
|
|
||||||
// So long as JUnit is excluded from shadowing we
|
|
||||||
// can minimize reflective invocation here
|
|
||||||
TestCase shadowedTestCase = (TestCase) BeanUtils.instantiateClass(shadowedTestClass); |
|
||||||
|
|
||||||
/* shadowParent = this */ |
|
||||||
Class thisShadowedClass = shadowingClassLoader.loadClass(AbstractJpaTests.class.getName()); |
|
||||||
Field shadowed = thisShadowedClass.getDeclaredField("shadowParent"); |
|
||||||
shadowed.setAccessible(true); |
|
||||||
shadowed.set(shadowedTestCase, this); |
|
||||||
|
|
||||||
/* AbstractSpringContextTests.addContext(Object, ApplicationContext) */ |
|
||||||
Class applicationContextClass = shadowingClassLoader.loadClass(ConfigurableApplicationContext.class.getName()); |
|
||||||
Method addContextMethod = shadowedTestClass.getMethod("addContext", String[].class, applicationContextClass); |
|
||||||
ReflectionUtils.makeAccessible(addContextMethod); |
|
||||||
addContextMethod.invoke(shadowedTestCase, configLocations, cachedContext); |
|
||||||
|
|
||||||
// Invoke tests on shadowed test case
|
|
||||||
shadowedTestCase.setName(getName()); |
|
||||||
shadowedTestCase.runBare(); |
|
||||||
} |
|
||||||
catch (InvocationTargetException ex) { |
|
||||||
// Unwrap this for better exception reporting
|
|
||||||
// when running tests
|
|
||||||
throw ex.getTargetException(); |
|
||||||
} |
|
||||||
finally { |
|
||||||
Thread.currentThread().setContextClassLoader(initialClassLoader); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected String cacheKeys() { |
|
||||||
return StringUtils.arrayToCommaDelimitedString(getConfigLocations()); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* NB: This method must <b>not</b> have a return type of ShadowingClassLoader as that would cause that |
|
||||||
* class to be loaded eagerly when this test case loads, creating verify errors at runtime. |
|
||||||
*/ |
|
||||||
protected ClassLoader createShadowingClassLoader(ClassLoader classLoader) { |
|
||||||
OrmXmlOverridingShadowingClassLoader orxl = new OrmXmlOverridingShadowingClassLoader(classLoader, |
|
||||||
getActualOrmXmlLocation()); |
|
||||||
customizeResourceOverridingShadowingClassLoader(orxl); |
|
||||||
return orxl; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Customize the shadowing class loader. |
|
||||||
* @param shadowingClassLoader this parameter is actually of type |
|
||||||
* ResourceOverridingShadowingClassLoader, and can safely to be cast to |
|
||||||
* that type. However, the signature must not be of that type as that |
|
||||||
* would cause the present class loader to load that type. |
|
||||||
*/ |
|
||||||
protected void customizeResourceOverridingShadowingClassLoader(ClassLoader shadowingClassLoader) { |
|
||||||
// empty
|
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Subclasses can override this to return the real location path for |
|
||||||
* orm.xml or null if they do not wish to find any orm.xml |
|
||||||
* @return orm.xml path or null to hide any such file |
|
||||||
*/ |
|
||||||
protected String getActualOrmXmlLocation() { |
|
||||||
return DEFAULT_ORM_XML_LOCATION; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private static class LoadTimeWeaverInjectingBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter { |
|
||||||
|
|
||||||
private final LoadTimeWeaver ltw; |
|
||||||
|
|
||||||
@SuppressWarnings("unused") |
|
||||||
public LoadTimeWeaverInjectingBeanPostProcessor(LoadTimeWeaver ltw) { |
|
||||||
this.ltw = ltw; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { |
|
||||||
if (bean instanceof LocalContainerEntityManagerFactoryBean) { |
|
||||||
((LocalContainerEntityManagerFactoryBean) bean).setLoadTimeWeaver(this.ltw); |
|
||||||
} |
|
||||||
if (bean instanceof DefaultPersistenceUnitManager) { |
|
||||||
((DefaultPersistenceUnitManager) bean).setLoadTimeWeaver(this.ltw); |
|
||||||
} |
|
||||||
return bean; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private static class ShadowingLoadTimeWeaver implements LoadTimeWeaver { |
|
||||||
|
|
||||||
private final ClassLoader shadowingClassLoader; |
|
||||||
|
|
||||||
@SuppressWarnings("unused") |
|
||||||
public ShadowingLoadTimeWeaver(ClassLoader shadowingClassLoader) { |
|
||||||
this.shadowingClassLoader = shadowingClassLoader; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void addTransformer(ClassFileTransformer transformer) { |
|
||||||
try { |
|
||||||
Method addClassFileTransformer = |
|
||||||
this.shadowingClassLoader.getClass().getMethod("addTransformer", ClassFileTransformer.class); |
|
||||||
addClassFileTransformer.setAccessible(true); |
|
||||||
addClassFileTransformer.invoke(this.shadowingClassLoader, transformer); |
|
||||||
} |
|
||||||
catch (Exception ex) { |
|
||||||
throw new RuntimeException(ex); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public ClassLoader getInstrumentableClassLoader() { |
|
||||||
return this.shadowingClassLoader; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public ClassLoader getThrowawayClassLoader() { |
|
||||||
// Be sure to copy the same resource overrides and same class file transformers:
|
|
||||||
// We want the throwaway class loader to behave like the instrumentable class loader.
|
|
||||||
ResourceOverridingShadowingClassLoader roscl = |
|
||||||
new ResourceOverridingShadowingClassLoader(getClass().getClassLoader()); |
|
||||||
if (this.shadowingClassLoader instanceof ShadowingClassLoader) { |
|
||||||
roscl.copyTransformers((ShadowingClassLoader) this.shadowingClassLoader); |
|
||||||
} |
|
||||||
if (this.shadowingClassLoader instanceof ResourceOverridingShadowingClassLoader) { |
|
||||||
roscl.copyOverrides((ResourceOverridingShadowingClassLoader) this.shadowingClassLoader); |
|
||||||
} |
|
||||||
return roscl; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,55 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2012 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.test.jpa; |
|
||||||
|
|
||||||
import org.springframework.instrument.classloading.ResourceOverridingShadowingClassLoader; |
|
||||||
|
|
||||||
/** |
|
||||||
* Subclass of ShadowingClassLoader that overrides attempts to |
|
||||||
* locate {@code orm.xml}. |
|
||||||
* |
|
||||||
* <p>This class must <b>not</b> be an inner class of AbstractJpaTests |
|
||||||
* to avoid it being loaded until first used. |
|
||||||
* |
|
||||||
* @author Rod Johnson |
|
||||||
* @author Adrian Colyer |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.0 |
|
||||||
*/ |
|
||||||
class OrmXmlOverridingShadowingClassLoader extends ResourceOverridingShadowingClassLoader { |
|
||||||
|
|
||||||
/** |
|
||||||
* Default location of the {@code orm.xml} file in the class path: |
|
||||||
* "META-INF/orm.xml" |
|
||||||
*/ |
|
||||||
public static final String DEFAULT_ORM_XML_LOCATION = "META-INF/orm.xml"; |
|
||||||
|
|
||||||
|
|
||||||
public OrmXmlOverridingShadowingClassLoader(ClassLoader loader, String realOrmXmlLocation) { |
|
||||||
super(loader); |
|
||||||
|
|
||||||
// Automatically exclude classes from these well-known persistence providers.
|
|
||||||
// Do NOT exclude Hibernate classes --
|
|
||||||
// this causes class casts due to use of CGLIB by Hibernate.
|
|
||||||
// Same goes for OpenJPA which will not enhance the domain classes.
|
|
||||||
excludePackage("oracle.toplink.essentials"); |
|
||||||
excludePackage("junit"); |
|
||||||
|
|
||||||
override(DEFAULT_ORM_XML_LOCATION, realOrmXmlLocation); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,51 +0,0 @@ |
|||||||
<?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"> |
|
||||||
|
|
||||||
<beans> |
|
||||||
|
|
||||||
<bean id="inheritsFromParentFactory" parent="inheritedTestBean"> |
|
||||||
<property name="name"><value>override</value></property> |
|
||||||
<!-- age should inherit value of 1 from parent --> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<bean id="inheritsWithDifferentClass" class="org.springframework.tests.sample.beans.DerivedTestBean" |
|
||||||
parent="inheritedTestBean" init-method="initialize"> |
|
||||||
<property name="name"><value>override</value></property> |
|
||||||
<!-- age should inherit value of 1 from parent --> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<bean id="inheritsWithClass" class="org.springframework.tests.sample.beans.DerivedTestBean" |
|
||||||
parent="inheritedTestBeanWithoutClass" init-method="initialize"> |
|
||||||
<property name="name"><value>override</value></property> |
|
||||||
<!-- age should inherit value of 1 from parent --> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<bean id="protoypeInheritsFromParentFactorySingleton" parent="inheritedTestBean" scope="prototype"> |
|
||||||
<property name="name"><value>prototypeOverridesInheritedSingleton</value></property> |
|
||||||
<!-- age should inherit value of 1 from parent --> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<bean id="prototypeInheritsFromParentFactoryPrototype" parent="inheritedTestBeanPrototype" scope="prototype"> |
|
||||||
<property name="name"><value>prototype-override</value></property> |
|
||||||
<!-- age should inherit value of 2 from parent --> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<bean id="singletonInheritsFromParentFactoryPrototype" parent="inheritedTestBeanPrototype" scope="singleton"> |
|
||||||
<property name="name"><value>prototype-override</value></property> |
|
||||||
<!-- age should inherit value of 2 from parent --> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<bean id="inheritedTestBean" parent="inheritedTestBean"> |
|
||||||
<property name="name"><value>overrideParentBean</value></property> |
|
||||||
<!-- age should inherit value of 1 from parent --> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<bean id="bogusParent" parent="bogus" scope="prototype"/> |
|
||||||
|
|
||||||
<bean id="indexedTestBean" class="org.springframework.tests.sample.beans.IndexedTestBean"> |
|
||||||
<property name="array[0].name"><value>myname</value></property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<bean parent="inheritedTestBean"/> |
|
||||||
|
|
||||||
</beans> |
|
||||||
@ -1,127 +0,0 @@ |
|||||||
<?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"> |
|
||||||
|
|
||||||
<beans> |
|
||||||
|
|
||||||
<bean id="validEmptyWithDescription" class="org.springframework.tests.sample.beans.TestBean"> |
|
||||||
<description> |
|
||||||
I have no properties and I'm happy without them. |
|
||||||
</description> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<!-- |
|
||||||
Check automatic creation of alias, to allow for names that are illegal as XML ids. |
|
||||||
--> |
|
||||||
<bean id="aliased" class=" org.springframework.tests.sample.beans.TestBean " name="myalias"> |
|
||||||
<property name="name"><value>aliased</value></property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<alias name="aliased" alias="youralias"/> |
|
||||||
|
|
||||||
<alias name="multiAliased" alias="alias3"/> |
|
||||||
|
|
||||||
<bean id="multiAliased" class="org.springframework.tests.sample.beans.TestBean" name="alias1,alias2"> |
|
||||||
<property name="name"><value>aliased</value></property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<alias name="multiAliased" alias="alias4"/> |
|
||||||
|
|
||||||
<bean class="org.springframework.tests.sample.beans.TestBean" name="aliasWithoutId1,aliasWithoutId2,aliasWithoutId3"> |
|
||||||
<property name="name"><value>aliased</value></property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<bean class="org.springframework.tests.sample.beans.TestBean"> |
|
||||||
<property name="name"><null/></property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<bean class="org.springframework.beans.factory.xml.DummyReferencer"/> |
|
||||||
|
|
||||||
<bean class="org.springframework.beans.factory.xml.DummyReferencer"/> |
|
||||||
|
|
||||||
<bean class="org.springframework.beans.factory.xml.DummyReferencer"/> |
|
||||||
|
|
||||||
<bean id="rod" class="org.springframework.tests.sample.beans.TestBean"> |
|
||||||
<property name="name"><value><!-- a comment -->Rod</value></property> |
|
||||||
<property name="age"><value>31</value></property> |
|
||||||
<property name="spouse"><ref bean="father"/></property> |
|
||||||
<property name="touchy"><value/></property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<bean id="roderick" parent="rod"> |
|
||||||
<property name="name"><value>Roderick<!-- a comment --></value></property> |
|
||||||
<!-- Should inherit age --> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<bean id="kerry" class="org.springframework.tests.sample.beans.TestBean"> |
|
||||||
<property name="name"><value>Ker<!-- a comment -->ry</value></property> |
|
||||||
<property name="age"><value>34</value></property> |
|
||||||
<property name="spouse"><ref bean="rod"/></property> |
|
||||||
<property name="touchy"><value></value></property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<bean id="kathy" class="org.springframework.tests.sample.beans.TestBean" scope="prototype"> |
|
||||||
<property name="name"><value>Kathy</value></property> |
|
||||||
<property name="age"><value>28</value></property> |
|
||||||
<property name="spouse"><ref bean="father"/></property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<bean id="typeMismatch" class="org.springframework.tests.sample.beans.TestBean" scope="prototype"> |
|
||||||
<property name="name"><value>typeMismatch</value></property> |
|
||||||
<property name="age"><value>34x</value></property> |
|
||||||
<property name="spouse"><ref bean="rod"/></property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<!-- Test of lifecycle callbacks --> |
|
||||||
<bean id="mustBeInitialized" class="org.springframework.tests.sample.beans.MustBeInitialized"/> |
|
||||||
|
|
||||||
<bean id="lifecycle" class="org.springframework.tests.sample.beans.LifecycleBean" |
|
||||||
init-method="declaredInitMethod"> |
|
||||||
<property name="initMethodDeclared"><value>true</value></property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<bean id="protectedLifecycle" class="org.springframework.beans.factory.xml.ProtectedLifecycleBean" |
|
||||||
init-method="declaredInitMethod"> |
|
||||||
<property name="initMethodDeclared"><value>true</value></property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<!-- Factory beans are automatically treated differently --> |
|
||||||
<bean id="singletonFactory" class="org.springframework.tests.sample.beans.factory.DummyFactory"> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<bean id="prototypeFactory" class="org.springframework.tests.sample.beans.factory.DummyFactory"> |
|
||||||
<property name="singleton"><value>false</value></property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<!-- Check that the circular reference resolution mechanism doesn't break |
|
||||||
repeated references to the same FactoryBean --> |
|
||||||
<bean id="factoryReferencer" class="org.springframework.beans.factory.xml.DummyReferencer"> |
|
||||||
<property name="testBean1"><ref bean="singletonFactory"/></property> |
|
||||||
<property name="testBean2"><ref bean="singletonFactory"/></property> |
|
||||||
<property name="dummyFactory"><ref bean="&singletonFactory"/></property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<bean id="factoryReferencerWithConstructor" class="org.springframework.beans.factory.xml.DummyReferencer"> |
|
||||||
<constructor-arg><ref bean="&singletonFactory"/></constructor-arg> |
|
||||||
<property name="testBean1"><ref bean="singletonFactory"/></property> |
|
||||||
<property name="testBean2"><ref bean="singletonFactory"/></property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<!-- Check that the circular reference resolution mechanism doesn't break |
|
||||||
prototype instantiation --> |
|
||||||
<bean id="prototypeReferencer" class="org.springframework.beans.factory.xml.DummyReferencer" scope="prototype"> |
|
||||||
<property name="testBean1"><ref bean="kathy"/></property> |
|
||||||
<property name="testBean2"><ref bean="kathy"/></property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<bean id="listenerVeto" class="org.springframework.tests.sample.beans.TestBean"> |
|
||||||
<property name="name"><value>listenerVeto</value></property> |
|
||||||
<property name="age"><value>66</value></property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
<bean id="validEmpty" class="org.springframework.tests.sample.beans.TestBean"/> |
|
||||||
|
|
||||||
<bean id="commentsInValue" class="org.springframework.tests.sample.beans.TestBean"> |
|
||||||
<property name="name"><value>this is<!-- don't mind me --> a <![CDATA[<!--comment-->]]></value></property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
</beans> |
|
||||||
@ -1,30 +0,0 @@ |
|||||||
<?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"> |
|
||||||
|
|
||||||
<beans> |
|
||||||
|
|
||||||
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBeanTests$FilterTestLocalSessionFactoryBean"> |
|
||||||
<property name="filterDefinitions"> |
|
||||||
<list> |
|
||||||
<bean class="org.springframework.orm.hibernate3.FilterDefinitionFactoryBean"> |
|
||||||
<property name="filterName" value="filter1"/> |
|
||||||
<property name="parameterTypes"> |
|
||||||
<props> |
|
||||||
<prop key="param1">string</prop> |
|
||||||
<prop key="otherParam">long</prop> |
|
||||||
</props> |
|
||||||
</property> |
|
||||||
<property name="defaultFilterCondition" value="someCondition"/> |
|
||||||
</bean> |
|
||||||
<bean id="filter2" class="org.springframework.orm.hibernate3.FilterDefinitionFactoryBean"> |
|
||||||
<property name="parameterTypes"> |
|
||||||
<props> |
|
||||||
<prop key="myParam">integer</prop> |
|
||||||
</props> |
|
||||||
</property> |
|
||||||
</bean> |
|
||||||
</list> |
|
||||||
</property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
</beans> |
|
||||||
@ -1,32 +0,0 @@ |
|||||||
<?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"> |
|
||||||
|
|
||||||
<beans> |
|
||||||
|
|
||||||
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBeanTests$TypeTestLocalSessionFactoryBean"> |
|
||||||
<property name="typeDefinitions"> |
|
||||||
<list> |
|
||||||
<bean class="org.springframework.orm.hibernate3.TypeDefinitionBean"> |
|
||||||
<property name="typeName" value="type1"/> |
|
||||||
<property name="typeClass" value="mypackage.MyTypeClass"/> |
|
||||||
<property name="parameters"> |
|
||||||
<props> |
|
||||||
<prop key="param1">value1</prop> |
|
||||||
<prop key="otherParam">othervalue</prop> |
|
||||||
</props> |
|
||||||
</property> |
|
||||||
</bean> |
|
||||||
<bean id="type2" class="org.springframework.orm.hibernate3.TypeDefinitionBean"> |
|
||||||
<property name="typeName" value="type2"/> |
|
||||||
<property name="typeClass" value="mypackage.MyOtherTypeClass"/> |
|
||||||
<property name="parameters"> |
|
||||||
<props> |
|
||||||
<prop key="myParam">myvalue</prop> |
|
||||||
</props> |
|
||||||
</property> |
|
||||||
</bean> |
|
||||||
</list> |
|
||||||
</property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
</beans> |
|
||||||
@ -1,23 +0,0 @@ |
|||||||
<?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-2.0.xsd |
|
||||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> |
|
||||||
|
|
||||||
<context:load-time-weaver aspectj-weaving="on"/> |
|
||||||
|
|
||||||
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> |
|
||||||
<property name="persistenceXmlLocation" value="org/springframework/orm/jpa/domain/persistence.xml"/> |
|
||||||
<property name="dataSource" ref="dataSource"/> |
|
||||||
<property name="jpaVendorAdapter"> |
|
||||||
<bean class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter"> |
|
||||||
<property name="database" value="HSQL"/> |
|
||||||
<property name="showSql" value="true"/> |
|
||||||
<property name="generateDdl" value="true"/> |
|
||||||
</bean> |
|
||||||
</property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
</beans> |
|
||||||
@ -1,18 +0,0 @@ |
|||||||
<?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"> |
|
||||||
|
|
||||||
<beans> |
|
||||||
|
|
||||||
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> |
|
||||||
<property name="persistenceXmlLocation" value="org/springframework/orm/jpa/domain/persistence.xml"/> |
|
||||||
<property name="dataSource" ref="dataSource"/> |
|
||||||
<property name="jpaVendorAdapter"> |
|
||||||
<bean class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter"> |
|
||||||
<property name="database" value="HSQL"/> |
|
||||||
<property name="showSql" value="true"/> |
|
||||||
<property name="generateDdl" value="true"/> |
|
||||||
</bean> |
|
||||||
</property> |
|
||||||
</bean> |
|
||||||
|
|
||||||
</beans> |
|
||||||
@ -1,41 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2015 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; |
|
||||||
|
|
||||||
/** |
|
||||||
* Test to ensure that component scanning works with load-time weaver. |
|
||||||
* See SPR-3873 for more details. |
|
||||||
* |
|
||||||
* @author Ramnivas Laddad |
|
||||||
*/ |
|
||||||
@SuppressWarnings("deprecation") |
|
||||||
public class ComponentScanningWithLTWTests extends org.springframework.test.jpa.AbstractJpaTests { |
|
||||||
|
|
||||||
{ |
|
||||||
setDependencyCheck(false); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected String[] getConfigPaths() { |
|
||||||
return new String[] { "ComponentScanningWithLTWTests.xml" }; |
|
||||||
} |
|
||||||
|
|
||||||
public void testLoading() { |
|
||||||
// do nothing as successful loading is the test
|
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
Loading…
Reference in new issue