MockMvc supports calling init(FilterConfig)
on filters added to it with URL mappings and/or init params and dispatcher types. This was done in 6.1 with #31362.
A filter that's being initialized may in turn try to access the FilterRegistration
. Currently that's not initialized, and that can cause problems. For example:
Caused by: java.lang.NullPointerException: Cannot invoke "jakarta.servlet.FilterRegistration.getUrlPatternMappings()" because "filterRegistration" is null
at org.glassfish.jersey.servlet.init.FilterUrlMappingsProviderImpl.getFilterUrlMappings(FilterUrlMappingsProviderImpl.java:43)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:414)
at org.springframework.test.web.servlet.setup.MockMvcFilterDecorator.initIfRequired(MockMvcFilterDecorator.java:201)
at org.springframework.test.web.servlet.setup.AbstractMockMvcBuilder.build(AbstractMockMvcBuilder.java:191)
at org.springframework.boot.test.autoconfigure.web.servlet.MockMvcAutoConfiguration.mockMvc(MockMvcAutoConfiguration.java:97)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:146)
... 125 more
We can update MockServletContext
to support adding FilterRegistration
s, and then make sure that's added in MockMvc along with the FilterConfig
it prepares.
Comment From: wilkinsona
The stack trace above shows this affecting users of Jersey. The arrangement here is an app that's using both Spring MVC and Jersey and is trying to use MockMvc
to test the Spring MVC portion of the app. In this situation, the problem can be worked around by disabling Jersey during MockMvc
-based tests of the Spring MVC portion of the app.
If Jersey is being configured using Spring Boot's auto-configuration, it can be disabled by excluded JerseyAutoConfiguration
in the tests that are using @AutoConfigureMockMvc
.
If Jersey's being configured by some other mechanism, disabling the bean that registers Jersey's filter will achieve the same effect. This can be done using a BeanPostProcessor that acts upon the registration bean for Jersey's filter. For example, assuming that the registration bean is named jerseyFilterRegistration
:
@Bean
static BeanPostProcessor disableJerseyFilter() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("jerseyFilterRegistration")) {
((FilterRegistrationBean<?>) bean).setEnabled(false);
}
return bean;
}
};
}