My application uses spring-boot 2.5.5.
I set a property for Tomcat at application startup to allow encoded slash in @PathVariable :
@SpringBootApplication
public class App {
public static void main(String[] args) {
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
SpringApplication.run(App.class, args);
}
}
Everything works fine when I start the app, except in my integration tests :
@ActiveProfiles("test-connected")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@ExtendWith(SpringExtension.class)
class GlobalFullTest {
When I debug the org.apache.tomcat.util.buf.UDecoder class : I see that the property org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH is null when class is loaded, so a default value false is set.
I tried the following :
- Adding
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");in the@BeforeAllmethod of my test - Adding
properties = { "org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true" }in the@SpringBootTestannotation. - Adding
org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH: truein myapplication-test-connected.yaml - Using
WebServerFactoryCustomizer:
@Configuration
public class WebServerConfiguration {
@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> customizer() {
return factory -> factory.addConnectorCustomizers(connector -> connector.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true"));
}
}
But none of these worked : when the property is retrieved by org.apache.tomcat.util.buf.UDecoder class, its value is always null.
How could I set the property before the org.apache.tomcat.util.buf.UDecoder class is loaded ?
CodePudding user response:
Referring to How to set environment variable or system property in spring tests?
The simplest way
Follow add static initializer in the class
...
class GlobalFullTest {
static {
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
}
...
}
down side is we need to copy that for every test.
Clean way
create ApplicationContextInitializer, which can be reused in the Spring application and any other test.
public class CustomApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>
{
@Override
public void initialize(ConfigurableApplicationContext applicationContext)
{
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
}
}
...
@ContextConfiguration(initializers = CustomApplicationContextInitializer.class,...)
class GlobalFullTest {
...
