From 2207d65b8294fb968170876c5ee438cc42ef5b1e Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Tue, 2 Aug 2022 13:05:08 +0300 Subject: [PATCH] Deprecate methods in ContextLoader API in the TestContext framework For Spring Framework 6.0 we have decided to deprecate the obsolete methods in the ContextLoader API in the Spring TestContext Framework in favor of the methods in the SmartContextLoader API which has been available since Spring Framework 3.1. Closes gh-28905 --- .../test/context/ContextLoader.java | 50 ++++++++++--------- .../test/context/SmartContextLoader.java | 31 +++++++++++- ...efaultCacheAwareContextLoaderDelegate.java | 3 +- .../support/AbstractContextLoader.java | 3 +- .../AbstractDelegatingSmartContextLoader.java | 34 +------------ .../support/AbstractGenericContextLoader.java | 2 + .../AbstractTestContextBootstrapper.java | 1 + .../web/AbstractGenericWebContextLoader.java | 3 +- ...ustomizedGenericXmlContextLoaderTests.java | 11 ++-- ...mlContextLoaderResourceLocationsTests.java | 1 + 10 files changed, 73 insertions(+), 66 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/test/context/ContextLoader.java b/spring-test/src/main/java/org/springframework/test/context/ContextLoader.java index 8856f6d89c..7123a76244 100644 --- a/spring-test/src/main/java/org/springframework/test/context/ContextLoader.java +++ b/spring-test/src/main/java/org/springframework/test/context/ContextLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2022 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. @@ -19,33 +19,29 @@ package org.springframework.test.context; import org.springframework.context.ApplicationContext; /** - * Strategy interface for loading an {@link ApplicationContext application context} - * for an integration test managed by the Spring TestContext Framework. + * Strategy interface for loading an {@link ApplicationContext} for an integration + * test managed by the Spring TestContext Framework. * - *

Note: as of Spring 3.1, implement {@link SmartContextLoader} instead - * of this interface in order to provide support for annotated classes, active - * bean definition profiles, and application context initializers. + *

NOTE: as of Spring Framework 6.0, {@code ContextLoader} is + * effectively a marker interface and should not be implemented directly. Implement + * {@link SmartContextLoader} instead of this interface in order to provide support + * for annotated classes, active bean definition profiles, application context + * initializers, and various other features not supported by methods defined in + * the {@code ContextLoader} SPI. * - *

Clients of a ContextLoader should call + *

Clients of a {@code ContextLoader} should call * {@link #processLocations(Class, String...) processLocations()} prior to * calling {@link #loadContext(String...) loadContext()} in case the - * ContextLoader provides custom support for modifying or generating locations. + * {@code ContextLoader} provides custom support for modifying or generating locations. * The results of {@link #processLocations(Class, String...) processLocations()} * should then be supplied to {@link #loadContext(String...) loadContext()}. * *

Concrete implementations must provide a {@code public} no-args constructor. * - *

Spring provides the following out-of-the-box implementations: - *

- * * @author Sam Brannen * @author Juergen Hoeller * @since 2.5 * @see SmartContextLoader - * @see org.springframework.test.context.support.AnnotationConfigContextLoader AnnotationConfigContextLoader */ public interface ContextLoader { @@ -58,31 +54,37 @@ public interface ContextLoader { * @param locations the unmodified locations to use for loading the * application context (can be {@code null} or empty) * @return an array of application context resource locations + * @deprecated as of Spring Framework 6.0, in favor of methods defined in the + * {@link SmartContextLoader} SPI */ + @Deprecated String[] processLocations(Class clazz, String... locations); /** - * Loads a new {@link ApplicationContext context} based on the supplied + * Loads a new {@link ApplicationContext} based on the supplied * {@code locations}, configures the context, and finally returns * the context in fully refreshed state. *

Configuration locations are generally considered to be classpath * resources by default. *

Concrete implementations should register annotation configuration - * processors with bean factories of {@link ApplicationContext application - * contexts} loaded by this ContextLoader. Beans will therefore automatically - * be candidates for annotation-based dependency injection using + * processors with bean factories of application contexts loaded by this + * {@code ContextLoader}. Beans will therefore automatically be candidates + * for annotation-based dependency injection using * {@link org.springframework.beans.factory.annotation.Autowired @Autowired}, * {@link jakarta.annotation.Resource @Resource}, and * {@link jakarta.inject.Inject @Inject}. - *

Any ApplicationContext loaded by a ContextLoader must - * 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. + *

Any {@code ApplicationContext} loaded by a {@code ContextLoader} + * must 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. * @param locations the resource locations to use to load the application context * @return a new application context * @throws Exception if context loading failed + * @deprecated as of Spring Framework 6.0, in favor of methods defined in the + * {@link SmartContextLoader} SPI */ + @Deprecated ApplicationContext loadContext(String... locations) throws Exception; } diff --git a/spring-test/src/main/java/org/springframework/test/context/SmartContextLoader.java b/spring-test/src/main/java/org/springframework/test/context/SmartContextLoader.java index f59be7fc4f..48529a26a1 100644 --- a/spring-test/src/main/java/org/springframework/test/context/SmartContextLoader.java +++ b/spring-test/src/main/java/org/springframework/test/context/SmartContextLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2022 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. @@ -17,6 +17,7 @@ package org.springframework.test.context; import org.springframework.context.ApplicationContext; +import org.springframework.lang.Nullable; /** * Strategy interface for loading an {@link ApplicationContext application context} @@ -123,4 +124,32 @@ public interface SmartContextLoader extends ContextLoader { */ ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception; + /** + * {@code SmartContextLoader} does not support deprecated {@link ContextLoader} methods. + * Call {@link #processContextConfiguration(ContextConfigurationAttributes)} instead. + * @throws UnsupportedOperationException in this implementation + * @since 6.0 + */ + @Override + @SuppressWarnings("deprecation") + default String[] processLocations(Class clazz, @Nullable String... locations) { + throw new UnsupportedOperationException(""" + SmartContextLoader does not support the ContextLoader SPI. \ + Call processContextConfiguration(ContextConfigurationAttributes) instead."""); + } + + /** + * {@code SmartContextLoader} does not support deprecated {@link ContextLoader} methods. + *

Call {@link #loadContext(MergedContextConfiguration)} instead. + * @throws UnsupportedOperationException in this implementation + * @since 6.0 + */ + @Override + @SuppressWarnings("deprecation") + default ApplicationContext loadContext(String... locations) throws Exception { + throw new UnsupportedOperationException(""" + SmartContextLoader does not support the ContextLoader SPI. \ + Call loadContext(MergedContextConfiguration) instead."""); + } + } diff --git a/spring-test/src/main/java/org/springframework/test/context/cache/DefaultCacheAwareContextLoaderDelegate.java b/spring-test/src/main/java/org/springframework/test/context/cache/DefaultCacheAwareContextLoaderDelegate.java index 8cb5c9ab38..4da86622d0 100644 --- a/spring-test/src/main/java/org/springframework/test/context/cache/DefaultCacheAwareContextLoaderDelegate.java +++ b/spring-test/src/main/java/org/springframework/test/context/cache/DefaultCacheAwareContextLoaderDelegate.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -85,6 +85,7 @@ public class DefaultCacheAwareContextLoaderDelegate implements CacheAwareContext *

Supports both the {@link SmartContextLoader} and {@link ContextLoader} SPIs. * @throws Exception if an error occurs while loading the application context */ + @SuppressWarnings("deprecation") protected ApplicationContext loadContextInternal(MergedContextConfiguration mergedContextConfiguration) throws Exception { diff --git a/spring-test/src/main/java/org/springframework/test/context/support/AbstractContextLoader.java b/spring-test/src/main/java/org/springframework/test/context/support/AbstractContextLoader.java index ffb067b1c2..91d6670202 100644 --- a/spring-test/src/main/java/org/springframework/test/context/support/AbstractContextLoader.java +++ b/spring-test/src/main/java/org/springframework/test/context/support/AbstractContextLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -212,6 +212,7 @@ public abstract class AbstractContextLoader implements SmartContextLoader { * @see #processContextConfiguration(ContextConfigurationAttributes) */ @Override + @SuppressWarnings("deprecation") public final String[] processLocations(Class clazz, String... locations) { return (ObjectUtils.isEmpty(locations) && isGenerateDefaultLocations()) ? generateDefaultLocations(clazz) : modifyLocations(clazz, locations); diff --git a/spring-test/src/main/java/org/springframework/test/context/support/AbstractDelegatingSmartContextLoader.java b/spring-test/src/main/java/org/springframework/test/context/support/AbstractDelegatingSmartContextLoader.java index 4c323cae46..3e2ee68574 100644 --- a/spring-test/src/main/java/org/springframework/test/context/support/AbstractDelegatingSmartContextLoader.java +++ b/spring-test/src/main/java/org/springframework/test/context/support/AbstractDelegatingSmartContextLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 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. @@ -20,7 +20,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationContext; -import org.springframework.lang.Nullable; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfigurationAttributes; import org.springframework.test.context.ContextLoader; @@ -86,37 +85,6 @@ public abstract class AbstractDelegatingSmartContextLoader implements SmartConte protected abstract SmartContextLoader getAnnotationConfigLoader(); - // ContextLoader - - /** - * {@code AbstractDelegatingSmartContextLoader} does not support the - * {@link ContextLoader#processLocations(Class, String...)} method. Call - * {@link #processContextConfiguration(ContextConfigurationAttributes)} instead. - * @throws UnsupportedOperationException in this implementation - */ - @Override - public final String[] processLocations(Class clazz, @Nullable String... locations) { - throw new UnsupportedOperationException( - "DelegatingSmartContextLoaders do not support the ContextLoader SPI. " + - "Call processContextConfiguration(ContextConfigurationAttributes) instead."); - } - - /** - * {@code AbstractDelegatingSmartContextLoader} does not support the - * {@link ContextLoader#loadContext(String...) } method. Call - * {@link #loadContext(MergedContextConfiguration)} instead. - * @throws UnsupportedOperationException in this implementation - */ - @Override - public final ApplicationContext loadContext(String... locations) throws Exception { - throw new UnsupportedOperationException( - "DelegatingSmartContextLoaders do not support the ContextLoader SPI. " + - "Call loadContext(MergedContextConfiguration) instead."); - } - - - // SmartContextLoader - /** * Delegates to candidate {@code SmartContextLoaders} to process the supplied * {@link ContextConfigurationAttributes}. diff --git a/spring-test/src/main/java/org/springframework/test/context/support/AbstractGenericContextLoader.java b/spring-test/src/main/java/org/springframework/test/context/support/AbstractGenericContextLoader.java index 45ae716f6f..38d3130cde 100644 --- a/spring-test/src/main/java/org/springframework/test/context/support/AbstractGenericContextLoader.java +++ b/spring-test/src/main/java/org/springframework/test/context/support/AbstractGenericContextLoader.java @@ -174,7 +174,9 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader * @see org.springframework.test.context.ContextLoader#loadContext * @see GenericApplicationContext * @see #loadContext(MergedContextConfiguration) + * @deprecated as of Spring Framework 6.0, in favor of {@link #loadContext(MergedContextConfiguration)} */ + @Deprecated @Override public final ConfigurableApplicationContext loadContext(String... locations) throws Exception { if (logger.isDebugEnabled()) { diff --git a/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java b/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java index 6e8a9c713d..52a11a3ae6 100644 --- a/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java +++ b/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java @@ -373,6 +373,7 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot classes.addAll(0, Arrays.asList(configAttributes.getClasses())); } else { + @SuppressWarnings("deprecation") String[] processedLocations = contextLoader.processLocations( configAttributes.getDeclaringClass(), configAttributes.getLocations()); locations.addAll(0, Arrays.asList(processedLocations)); diff --git a/spring-test/src/main/java/org/springframework/test/context/web/AbstractGenericWebContextLoader.java b/spring-test/src/main/java/org/springframework/test/context/web/AbstractGenericWebContextLoader.java index 626645bbd1..8260325057 100644 --- a/spring-test/src/main/java/org/springframework/test/context/web/AbstractGenericWebContextLoader.java +++ b/spring-test/src/main/java/org/springframework/test/context/web/AbstractGenericWebContextLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -263,6 +263,7 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa * @see org.springframework.test.context.ContextLoader#loadContext(java.lang.String[]) */ @Override + @SuppressWarnings("deprecation") public final ApplicationContext loadContext(String... locations) throws Exception { throw new UnsupportedOperationException( "AbstractGenericWebContextLoader does not support the loadContext(String... locations) method"); diff --git a/spring-test/src/test/java/org/springframework/test/context/support/CustomizedGenericXmlContextLoaderTests.java b/spring-test/src/test/java/org/springframework/test/context/support/CustomizedGenericXmlContextLoaderTests.java index db9d4af159..aeb340d2fe 100644 --- a/spring-test/src/test/java/org/springframework/test/context/support/CustomizedGenericXmlContextLoaderTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/support/CustomizedGenericXmlContextLoaderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -37,20 +37,21 @@ import static org.assertj.core.api.Assertions.assertThat; class CustomizedGenericXmlContextLoaderTests { @Test + @SuppressWarnings("deprecation") void customizeContext() throws Exception { StringBuilder builder = new StringBuilder(); String expectedContents = "customizeContext() was called"; - new GenericXmlContextLoader() { - + GenericXmlContextLoader customLoader = new GenericXmlContextLoader() { @Override protected void customizeContext(GenericApplicationContext context) { assertThat(context.isActive()).as("The context should not yet have been refreshed.").isFalse(); builder.append(expectedContents); } - }.loadContext("classpath:/org/springframework/test/context/support/CustomizedGenericXmlContextLoaderTests-context.xml"); + }; + customLoader.loadContext("classpath:/org/springframework/test/context/support/CustomizedGenericXmlContextLoaderTests-context.xml"); - assertThat(builder.toString()).as("customizeContext() should have been called.").isEqualTo(expectedContents); + assertThat(builder).asString().as("customizeContext() should have been called.").isEqualTo(expectedContents); } } diff --git a/spring-test/src/test/java/org/springframework/test/context/support/GenericXmlContextLoaderResourceLocationsTests.java b/spring-test/src/test/java/org/springframework/test/context/support/GenericXmlContextLoaderResourceLocationsTests.java index f94735e3fe..d0e7e12642 100644 --- a/spring-test/src/test/java/org/springframework/test/context/support/GenericXmlContextLoaderResourceLocationsTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/support/GenericXmlContextLoaderResourceLocationsTests.java @@ -57,6 +57,7 @@ class GenericXmlContextLoaderResourceLocationsTests { ContextConfiguration contextConfig = testClass.getAnnotation(ContextConfiguration.class); ContextLoader contextLoader = new GenericXmlContextLoader(); String[] configuredLocations = (String[]) AnnotationUtils.getValue(contextConfig); + @SuppressWarnings("deprecation") String[] processedLocations = contextLoader.processLocations(testClass, configuredLocations); if (logger.isDebugEnabled()) {