Fix @ServletComponentScan with a component index

Previously @ServletComponentScan did not work when there was a
component index on the classpath as it made an assumption about
the concrete type of the BeanDefinitions produced by scanning that
does not hold true when an index is present.

This commit updates the scanning and the handlers to correct the
assumpution by working with a bean definition type that is produced
by scanning both when there is and when there is not an index present.

To prevent the problem from reoccuring, a test that uses and index
has been added and the import of ScannedGenericBeanDefinition is now
prohibited by Checkstyle.

Closes gh-18910
This commit is contained in:
Andy Wilkinson 2019-11-07 09:13:46 +00:00
parent 8d3df1b4b8
commit d1ead884c4
10 changed files with 116 additions and 54 deletions

View File

@ -20,8 +20,8 @@ import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
@ -68,7 +68,7 @@ abstract class ServletComponentHandler {
return initParameters;
}
void handle(ScannedGenericBeanDefinition beanDefinition, BeanDefinitionRegistry registry) {
void handle(AnnotatedBeanDefinition beanDefinition, BeanDefinitionRegistry registry) {
Map<String, Object> attributes = beanDefinition.getMetadata()
.getAnnotationAttributes(this.annotationType.getName());
if (attributes != null) {
@ -76,7 +76,7 @@ abstract class ServletComponentHandler {
}
}
protected abstract void doHandle(Map<String, Object> attributes, ScannedGenericBeanDefinition beanDefinition,
protected abstract void doHandle(Map<String, Object> attributes, AnnotatedBeanDefinition beanDefinition,
BeanDefinitionRegistry registry);
}

View File

@ -22,6 +22,7 @@ import java.util.List;
import java.util.Set;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
@ -29,7 +30,6 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.web.context.WebApplicationContext;
/**
@ -72,9 +72,9 @@ class ServletComponentRegisteringPostProcessor implements BeanFactoryPostProcess
private void scanPackage(ClassPathScanningCandidateComponentProvider componentProvider, String packageToScan) {
for (BeanDefinition candidate : componentProvider.findCandidateComponents(packageToScan)) {
if (candidate instanceof ScannedGenericBeanDefinition) {
if (candidate instanceof AnnotatedBeanDefinition) {
for (ServletComponentHandler handler : HANDLERS) {
handler.handle(((ScannedGenericBeanDefinition) candidate),
handler.handle(((AnnotatedBeanDefinition) candidate),
(BeanDefinitionRegistry) this.applicationContext);
}
}

View File

@ -23,10 +23,10 @@ import java.util.Map;
import javax.servlet.DispatcherType;
import javax.servlet.annotation.WebFilter;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.util.StringUtils;
/**
@ -41,7 +41,7 @@ class WebFilterHandler extends ServletComponentHandler {
}
@Override
public void doHandle(Map<String, Object> attributes, ScannedGenericBeanDefinition beanDefinition,
public void doHandle(Map<String, Object> attributes, AnnotatedBeanDefinition beanDefinition,
BeanDefinitionRegistry registry) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(FilterRegistrationBean.class);
builder.addPropertyValue("asyncSupported", attributes.get("asyncSupported"));

View File

@ -20,9 +20,9 @@ import java.util.Map;
import javax.servlet.annotation.WebListener;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
/**
* Handler for {@link WebListener}-annotated classes.
@ -36,7 +36,7 @@ class WebListenerHandler extends ServletComponentHandler {
}
@Override
protected void doHandle(Map<String, Object> attributes, ScannedGenericBeanDefinition beanDefinition,
protected void doHandle(Map<String, Object> attributes, AnnotatedBeanDefinition beanDefinition,
BeanDefinitionRegistry registry) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ServletListenerRegistrationBean.class);
builder.addPropertyValue("listener", beanDefinition);

View File

@ -22,10 +22,10 @@ import javax.servlet.MultipartConfigElement;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.util.StringUtils;
/**
@ -40,7 +40,7 @@ class WebServletHandler extends ServletComponentHandler {
}
@Override
public void doHandle(Map<String, Object> attributes, ScannedGenericBeanDefinition beanDefinition,
public void doHandle(Map<String, Object> attributes, AnnotatedBeanDefinition beanDefinition,
BeanDefinitionRegistry registry) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ServletRegistrationBean.class);
builder.addPropertyValue("asyncSupported", attributes.get("asyncSupported"));
@ -59,7 +59,7 @@ class WebServletHandler extends ServletComponentHandler {
: beanDefinition.getBeanClassName());
}
private MultipartConfigElement determineMultipartConfig(ScannedGenericBeanDefinition beanDefinition) {
private MultipartConfigElement determineMultipartConfig(AnnotatedBeanDefinition beanDefinition) {
Map<String, Object> attributes = beanDefinition.getMetadata()
.getAnnotationAttributes(MultipartConfig.class.getName());
if (attributes == null) {

View File

@ -16,12 +16,23 @@
package org.springframework.boot.web.servlet;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Map;
import java.util.Properties;
import javax.servlet.MultipartConfigElement;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebListener;
import javax.servlet.annotation.WebServlet;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
@ -40,6 +51,9 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
public class ServletComponentScanIntegrationTests {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
private AnnotationConfigServletWebServerApplicationContext context;
@After
@ -60,6 +74,22 @@ public class ServletComponentScanIntegrationTests {
assertThat(response).isEqualTo("alpha bravo");
}
@Test
public void indexedComponentsAreRegistered() throws IOException {
writeIndex();
this.context = new AnnotationConfigServletWebServerApplicationContext();
try (URLClassLoader classLoader = new URLClassLoader(new URL[] { this.temp.getRoot().toURI().toURL() },
getClass().getClassLoader())) {
this.context.setClassLoader(classLoader);
this.context.register(TestConfiguration.class);
new ServerPortInfoApplicationContextInitializer().initialize(this.context);
this.context.refresh();
String port = this.context.getEnvironment().getProperty("local.server.port");
String response = new RestTemplate().getForObject("http://localhost:" + port + "/test", String.class);
assertThat(response).isEqualTo("alpha bravo");
}
}
@Test
public void multipartConfigIsHonoured() {
this.context = new AnnotationConfigServletWebServerApplicationContext();
@ -78,6 +108,19 @@ public class ServletComponentScanIntegrationTests {
assertThat(multipartConfig.getFileSizeThreshold()).isEqualTo(512);
}
private void writeIndex() throws IOException {
File metaInf = this.temp.newFolder("META-INF");
Properties index = new Properties();
index.setProperty("org.springframework.boot.web.servlet.testcomponents.TestFilter", WebFilter.class.getName());
index.setProperty("org.springframework.boot.web.servlet.testcomponents.TestListener",
WebListener.class.getName());
index.setProperty("org.springframework.boot.web.servlet.testcomponents.TestServlet",
WebServlet.class.getName());
try (FileWriter writer = new FileWriter(new File(metaInf, "spring.components"))) {
index.store(writer, null);
}
}
@Configuration
@ServletComponentScan(basePackages = "org.springframework.boot.web.servlet.testcomponents")
static class TestConfiguration {

View File

@ -33,13 +33,15 @@ import javax.servlet.annotation.WebInitParam;
import org.junit.Test;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link WebFilterHandler}
@ -55,9 +57,8 @@ public class WebFilterHandlerTests {
@SuppressWarnings("unchecked")
@Test
public void defaultFilterConfiguration() throws IOException {
ScannedGenericBeanDefinition scanned = new ScannedGenericBeanDefinition(
new SimpleMetadataReaderFactory().getMetadataReader(DefaultConfigurationFilter.class.getName()));
this.handler.handle(scanned, this.registry);
AnnotatedBeanDefinition definition = createBeanDefinition(DefaultConfigurationFilter.class);
this.handler.handle(definition, this.registry);
BeanDefinition filterRegistrationBean = this.registry
.getBeanDefinition(DefaultConfigurationFilter.class.getName());
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
@ -68,14 +69,13 @@ public class WebFilterHandlerTests {
assertThat((String[]) propertyValues.get("servletNames")).isEmpty();
assertThat((String[]) propertyValues.get("urlPatterns")).isEmpty();
assertThat(propertyValues.get("name")).isEqualTo(DefaultConfigurationFilter.class.getName());
assertThat(propertyValues.get("filter")).isEqualTo(scanned);
assertThat(propertyValues.get("filter")).isEqualTo(definition);
}
@Test
public void filterWithCustomName() throws IOException {
ScannedGenericBeanDefinition scanned = new ScannedGenericBeanDefinition(
new SimpleMetadataReaderFactory().getMetadataReader(CustomNameFilter.class.getName()));
this.handler.handle(scanned, this.registry);
AnnotatedBeanDefinition definition = createBeanDefinition(CustomNameFilter.class);
this.handler.handle(definition, this.registry);
BeanDefinition filterRegistrationBean = this.registry.getBeanDefinition("custom");
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
assertThat(propertyValues.get("name")).isEqualTo("custom");
@ -83,7 +83,7 @@ public class WebFilterHandlerTests {
@Test
public void asyncSupported() throws IOException {
BeanDefinition filterRegistrationBean = getBeanDefinition(AsyncSupportedFilter.class);
BeanDefinition filterRegistrationBean = handleBeanDefinitionForClass(AsyncSupportedFilter.class);
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
assertThat(propertyValues.get("asyncSupported")).isEqualTo(true);
}
@ -91,7 +91,7 @@ public class WebFilterHandlerTests {
@Test
@SuppressWarnings("unchecked")
public void dispatcherTypes() throws IOException {
BeanDefinition filterRegistrationBean = getBeanDefinition(DispatcherTypesFilter.class);
BeanDefinition filterRegistrationBean = handleBeanDefinitionForClass(DispatcherTypesFilter.class);
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
assertThat((Set<DispatcherType>) propertyValues.get("dispatcherTypes")).containsExactly(DispatcherType.FORWARD,
DispatcherType.INCLUDE, DispatcherType.REQUEST);
@ -100,7 +100,7 @@ public class WebFilterHandlerTests {
@SuppressWarnings("unchecked")
@Test
public void initParameters() throws IOException {
BeanDefinition filterRegistrationBean = getBeanDefinition(InitParametersFilter.class);
BeanDefinition filterRegistrationBean = handleBeanDefinitionForClass(InitParametersFilter.class);
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
assertThat((Map<String, String>) propertyValues.get("initParameters")).containsEntry("a", "alpha")
.containsEntry("b", "bravo");
@ -108,35 +108,42 @@ public class WebFilterHandlerTests {
@Test
public void servletNames() throws IOException {
BeanDefinition filterRegistrationBean = getBeanDefinition(ServletNamesFilter.class);
BeanDefinition filterRegistrationBean = handleBeanDefinitionForClass(ServletNamesFilter.class);
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
assertThat((String[]) propertyValues.get("servletNames")).contains("alpha", "bravo");
}
@Test
public void urlPatterns() throws IOException {
BeanDefinition filterRegistrationBean = getBeanDefinition(UrlPatternsFilter.class);
BeanDefinition filterRegistrationBean = handleBeanDefinitionForClass(UrlPatternsFilter.class);
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
assertThat((String[]) propertyValues.get("urlPatterns")).contains("alpha", "bravo");
}
@Test
public void urlPatternsFromValue() throws IOException {
BeanDefinition filterRegistrationBean = getBeanDefinition(UrlPatternsFromValueFilter.class);
BeanDefinition filterRegistrationBean = handleBeanDefinitionForClass(UrlPatternsFromValueFilter.class);
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
assertThat((String[]) propertyValues.get("urlPatterns")).contains("alpha", "bravo");
}
@Test
public void urlPatternsDeclaredTwice() throws IOException {
assertThatIllegalStateException().isThrownBy(() -> getBeanDefinition(UrlPatternsDeclaredTwiceFilter.class))
assertThatIllegalStateException()
.isThrownBy(() -> handleBeanDefinitionForClass(UrlPatternsDeclaredTwiceFilter.class))
.withMessageContaining("The urlPatterns and value attributes are mutually exclusive.");
}
BeanDefinition getBeanDefinition(Class<?> filterClass) throws IOException {
ScannedGenericBeanDefinition scanned = new ScannedGenericBeanDefinition(
new SimpleMetadataReaderFactory().getMetadataReader(filterClass.getName()));
this.handler.handle(scanned, this.registry);
private AnnotatedBeanDefinition createBeanDefinition(Class<?> filterClass) throws IOException {
AnnotatedBeanDefinition definition = mock(AnnotatedBeanDefinition.class);
given(definition.getBeanClassName()).willReturn(filterClass.getName());
given(definition.getMetadata()).willReturn(
new SimpleMetadataReaderFactory().getMetadataReader(filterClass.getName()).getAnnotationMetadata());
return definition;
}
private BeanDefinition handleBeanDefinitionForClass(Class<?> filterClass) throws IOException {
this.handler.handle(createBeanDefinition(filterClass), this.registry);
return this.registry.getBeanDefinition(filterClass.getName());
}

View File

@ -24,10 +24,13 @@ import javax.servlet.annotation.WebListener;
import org.junit.Test;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link WebListenerHandler}.
*
@ -41,9 +44,11 @@ public class WebListenerHandlerTests {
@Test
public void listener() throws IOException {
ScannedGenericBeanDefinition scanned = new ScannedGenericBeanDefinition(
new SimpleMetadataReaderFactory().getMetadataReader(TestListener.class.getName()));
this.handler.handle(scanned, this.registry);
AnnotatedBeanDefinition definition = mock(AnnotatedBeanDefinition.class);
given(definition.getBeanClassName()).willReturn(TestListener.class.getName());
given(definition.getMetadata()).willReturn(new SimpleMetadataReaderFactory()
.getMetadataReader(TestListener.class.getName()).getAnnotationMetadata());
this.handler.handle(definition, this.registry);
this.registry.getBeanDefinition(TestListener.class.getName());
}

View File

@ -26,13 +26,15 @@ import javax.servlet.http.HttpServlet;
import org.junit.Test;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link WebServletHandler}.
@ -48,9 +50,8 @@ public class WebServletHandlerTests {
@SuppressWarnings("unchecked")
@Test
public void defaultServletConfiguration() throws IOException {
ScannedGenericBeanDefinition scanned = new ScannedGenericBeanDefinition(
new SimpleMetadataReaderFactory().getMetadataReader(DefaultConfigurationServlet.class.getName()));
this.handler.handle(scanned, this.registry);
AnnotatedBeanDefinition servletdefinition = createBeanDefinition(DefaultConfigurationServlet.class);
this.handler.handle(servletdefinition, this.registry);
BeanDefinition servletRegistrationBean = this.registry
.getBeanDefinition(DefaultConfigurationServlet.class.getName());
MutablePropertyValues propertyValues = servletRegistrationBean.getPropertyValues();
@ -59,14 +60,13 @@ public class WebServletHandlerTests {
assertThat((Integer) propertyValues.get("loadOnStartup")).isEqualTo(-1);
assertThat(propertyValues.get("name")).isEqualTo(DefaultConfigurationServlet.class.getName());
assertThat((String[]) propertyValues.get("urlMappings")).isEmpty();
assertThat(propertyValues.get("servlet")).isEqualTo(scanned);
assertThat(propertyValues.get("servlet")).isEqualTo(servletdefinition);
}
@Test
public void servletWithCustomName() throws IOException {
ScannedGenericBeanDefinition scanned = new ScannedGenericBeanDefinition(
new SimpleMetadataReaderFactory().getMetadataReader(CustomNameServlet.class.getName()));
this.handler.handle(scanned, this.registry);
AnnotatedBeanDefinition definition = createBeanDefinition(CustomNameServlet.class);
this.handler.handle(definition, this.registry);
BeanDefinition servletRegistrationBean = this.registry.getBeanDefinition("custom");
MutablePropertyValues propertyValues = servletRegistrationBean.getPropertyValues();
assertThat(propertyValues.get("name")).isEqualTo("custom");
@ -74,7 +74,7 @@ public class WebServletHandlerTests {
@Test
public void asyncSupported() throws IOException {
BeanDefinition servletRegistrationBean = getBeanDefinition(AsyncSupportedServlet.class);
BeanDefinition servletRegistrationBean = handleBeanDefinitionForClass(AsyncSupportedServlet.class);
MutablePropertyValues propertyValues = servletRegistrationBean.getPropertyValues();
assertThat(propertyValues.get("asyncSupported")).isEqualTo(true);
}
@ -82,7 +82,7 @@ public class WebServletHandlerTests {
@SuppressWarnings("unchecked")
@Test
public void initParameters() throws IOException {
BeanDefinition servletRegistrationBean = getBeanDefinition(InitParametersServlet.class);
BeanDefinition servletRegistrationBean = handleBeanDefinitionForClass(InitParametersServlet.class);
MutablePropertyValues propertyValues = servletRegistrationBean.getPropertyValues();
assertThat((Map<String, String>) propertyValues.get("initParameters")).containsEntry("a", "alpha")
.containsEntry("b", "bravo");
@ -90,28 +90,35 @@ public class WebServletHandlerTests {
@Test
public void urlMappings() throws IOException {
BeanDefinition servletRegistrationBean = getBeanDefinition(UrlPatternsServlet.class);
BeanDefinition servletRegistrationBean = handleBeanDefinitionForClass(UrlPatternsServlet.class);
MutablePropertyValues propertyValues = servletRegistrationBean.getPropertyValues();
assertThat((String[]) propertyValues.get("urlMappings")).contains("alpha", "bravo");
}
@Test
public void urlMappingsFromValue() throws IOException {
BeanDefinition servletRegistrationBean = getBeanDefinition(UrlPatternsFromValueServlet.class);
BeanDefinition servletRegistrationBean = handleBeanDefinitionForClass(UrlPatternsFromValueServlet.class);
MutablePropertyValues propertyValues = servletRegistrationBean.getPropertyValues();
assertThat((String[]) propertyValues.get("urlMappings")).contains("alpha", "bravo");
}
@Test
public void urlPatternsDeclaredTwice() throws IOException {
assertThatIllegalStateException().isThrownBy(() -> getBeanDefinition(UrlPatternsDeclaredTwiceServlet.class))
assertThatIllegalStateException()
.isThrownBy(() -> handleBeanDefinitionForClass(UrlPatternsDeclaredTwiceServlet.class))
.withMessageContaining("The urlPatterns and value attributes are mutually exclusive.");
}
private BeanDefinition getBeanDefinition(Class<?> filterClass) throws IOException {
ScannedGenericBeanDefinition scanned = new ScannedGenericBeanDefinition(
new SimpleMetadataReaderFactory().getMetadataReader(filterClass.getName()));
this.handler.handle(scanned, this.registry);
private AnnotatedBeanDefinition createBeanDefinition(Class<?> servletClass) throws IOException {
AnnotatedBeanDefinition definition = mock(AnnotatedBeanDefinition.class);
given(definition.getBeanClassName()).willReturn(servletClass.getName());
given(definition.getMetadata()).willReturn(
new SimpleMetadataReaderFactory().getMetadataReader(servletClass.getName()).getAnnotationMetadata());
return definition;
}
private BeanDefinition handleBeanDefinitionForClass(Class<?> filterClass) throws IOException {
this.handler.handle(createBeanDefinition(filterClass), this.registry);
return this.registry.getBeanDefinition(filterClass.getName());
}

View File

@ -14,7 +14,7 @@
<property name="illegalPkgs"
value="^sun.*, ^org\.apache\.commons\.(?!compress|dbcp2|lang|lang3|logging|pool2).*, ^com\.google\.common.*, ^org\.flywaydb\.core\.internal.*, ^org\.testcontainers\.shaded.*" />
<property name="illegalClasses"
value="^com\.hazelcast\.util\.Base64, ^org\.junit\.rules\.ExpectedException, ^org\.slf4j\.LoggerFactory, ^reactor\.core\.support\.Assert" />
value="^com\.hazelcast\.util\.Base64, ^org\.junit\.rules\.ExpectedException, ^org\.slf4j\.LoggerFactory, ^org.springframework.context.annotation.ScannedGenericBeanDefinition, ^reactor\.core\.support\.Assert" />
</module>
<module
name="com.puppycrawl.tools.checkstyle.checks.imports.ImportControlCheck">