From 12bf43359a9d01ea734da700e318cd152dd10997 Mon Sep 17 00:00:00 2001 From: dmytrodanilenkov Date: Fri, 4 Apr 2025 18:54:59 +0100 Subject: [PATCH 1/8] Fix for issue #45001 - ServletRegistrationBean has those properties, but @ServletRegistration hasn't: initParameters, servletRegistrationBeans, multipartConfig Signed-off-by: Dmytro Danilenkov --- .../ServletContextInitializerBeans.java | 50 ++++++++++ .../boot/web/servlet/ServletRegistration.java | 49 ++++++++++ .../ServletContextInitializerBeansTests.java | 96 +++++++++++++++++++ 3 files changed, 195 insertions(+) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java index b0010729ada6..fa8a91f0100a 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java @@ -62,6 +62,7 @@ * @author Phillip Webb * @author Brian Clozel * @author Moritz Halbritter + * @author Dmytro Danilenkov * @since 1.4.0 */ public class ServletContextInitializerBeans extends AbstractCollection { @@ -321,10 +322,59 @@ private void configureFromAnnotation(ServletRegistrationBean bean, Serv if (registration.urlMappings().length > 0) { bean.setUrlMappings(Arrays.asList(registration.urlMappings())); } + + if (registration.initParameters().length > 0) { + bean.setInitParameters(parseInitParameters(registration.initParameters())); + } + + ServletRegistration.MultipartConfigValues multipart = registration.multipartConfig(); + boolean isMultipartConfigUsed = !(multipart.location().isEmpty() + && multipart.maxFileSize() == -1L + && multipart.maxRequestSize() == -1L + && multipart.fileSizeThreshold() == 0); + if (isMultipartConfigUsed) { + bean.setMultipartConfig(new MultipartConfigElement( + multipart.location(), + multipart.maxFileSize(), + multipart.maxRequestSize(), + multipart.fileSizeThreshold() + )); + } + + for (Class> beanClass : registration.servletRegistrationBeans()) { + ServletRegistrationBean extraBean = this.beanFactory.getBean(beanClass); + bean.getInitParameters().putAll(extraBean.getInitParameters()); + } + + } + + /** + * Parses an array of "key=value" strings into a Map. + * @param initParamsArray Array of strings, expected format "key=value". + * @return Map of parsed key-value pairs. + * @throws IllegalArgumentException if any string doesn't match the "key=value" format. + */ + private Map parseInitParameters(String[] initParamsArray) { + Map initParams = new LinkedHashMap<>(); + for (String kv : initParamsArray) { + int index = kv.indexOf('='); + if (index != -1) { + String key = kv.substring(0, index).trim(); + String value = kv.substring(index + 1).trim(); + initParams.put(key, value); + } + else { + throw new IllegalArgumentException( + "initParameters must be in 'key=value' format, got: " + kv); + } + } + return initParams; } } + + /** * {@link RegistrationBeanAdapter} for {@link Filter} beans. */ diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistration.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistration.java index e515747295fa..d1b6cf8c98c9 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistration.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistration.java @@ -23,6 +23,8 @@ import java.lang.annotation.Target; import jakarta.servlet.Servlet; +import jakarta.servlet.annotation.MultipartConfig; +import jakarta.servlet.annotation.WebInitParam; import org.springframework.core.Ordered; import org.springframework.core.annotation.AliasFor; @@ -33,6 +35,7 @@ * annotation-based alternative to {@link ServletRegistrationBean}. * * @author Moritz Halbritter + * @author Dmytro Danilenkov * @since 3.5.0 * @see ServletRegistrationBean */ @@ -87,4 +90,50 @@ */ int loadOnStartup() default -1; + /** + * Init parameters to set on the servlet, as {@code "key=value"} pairs. + */ + String[] initParameters() default {}; + + /** + * (Optional) Additional servlet-registration beans to apply. + * Usually left empty unless you need custom bean logic. + */ + Class>[] servletRegistrationBeans() default {}; + + /** + * Multipart configuration. Mirrors {@link jakarta.servlet.annotation.MultipartConfig}. + * If you omit it (no fields changed), it will not set a multipart config. + */ + MultipartConfigValues multipartConfig() default @MultipartConfigValues; + + /** + * Nested annotation that parallels the fields of + * {@link jakarta.servlet.annotation.MultipartConfig}. Used within + * {@link ServletRegistration#multipartConfig()}. + * @see jakarta.servlet.annotation.MultipartConfig + */ + @Target({}) + @Retention(RetentionPolicy.RUNTIME) + @Documented + @interface MultipartConfigValues { + + /** + * @see jakarta.servlet.annotation.MultipartConfig#location() + */ + String location() default ""; + /** + * @see jakarta.servlet.annotation.MultipartConfig#maxFileSize() + */ + long maxFileSize() default -1L; + /** + * @see jakarta.servlet.annotation.MultipartConfig#maxRequestSize() + */ + long maxRequestSize() default -1L; + /** + * @see jakarta.servlet.annotation.MultipartConfig#fileSizeThreshold() + */ + int fileSizeThreshold() default 0; + + } } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java index 605ce7f0b879..3a3e8560a515 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java @@ -42,6 +42,7 @@ * * @author Andy Wilkinson * @author Moritz Halbritter + * @author Dmytro Danilenkov */ class ServletContextInitializerBeansTests { @@ -179,6 +180,55 @@ void shouldApplyOrderFromOrderAttribute() { .isEqualTo(ServletConfigurationWithAnnotationAndOrder.ORDER)); } + @Test + void shouldApplyExtendedServletRegistrationAnnotation() { + load(ServletConfigurationWithExtendedAttributes.class); + ServletContextInitializerBeans initializerBeans = new ServletContextInitializerBeans( + this.context.getBeanFactory(), TestServletContextInitializer.class); + + ServletRegistrationBean bean = findServletRegistrationBeanByName(initializerBeans, "extended"); + + assertThat(bean.getServletName()).isEqualTo("extended"); + assertThat(bean.getUrlMappings()).containsExactly("/extended/*"); + + assertThat(bean.getInitParameters()).containsEntry("hello", "world") + .containsEntry("flag", "true"); + + assertThat(bean.getMultipartConfig()).isNotNull(); + assertThat(bean.getMultipartConfig().getLocation()).isEqualTo("/tmp"); + assertThat(bean.getMultipartConfig().getMaxFileSize()).isEqualTo(1024); + assertThat(bean.getMultipartConfig().getMaxRequestSize()).isEqualTo(4096); + assertThat(bean.getMultipartConfig().getFileSizeThreshold()).isEqualTo(128); + } + + @Test + void shouldApplyServletRegistrationAnnotationWithExtraRegistrationBeans() { + load(ServletConfigurationWithExtendedAttributes.class); + ServletContextInitializerBeans initializerBeans = new ServletContextInitializerBeans( + this.context.getBeanFactory(), TestServletContextInitializer.class); + + ServletRegistrationBean bean = findServletRegistrationBeanByName(initializerBeans, "extendedWithExtraBeans"); + assertThat(bean).as("extendedWithExtraBeans registration bean").isNotNull(); + + assertThat(bean.getServletName()).isEqualTo("extendedWithExtraBeans"); + assertThat(bean.getUrlMappings()).containsExactly("/extra/*"); + + assertThat(bean.getInitParameters()).containsEntry("extra", "fromExtraBean"); + } + + @SuppressWarnings("rawtypes") + private ServletRegistrationBean findServletRegistrationBeanByName( + ServletContextInitializerBeans initializerBeans, String servletName) { + + return initializerBeans.stream() + .filter(ServletRegistrationBean.class::isInstance) + .map(ServletRegistrationBean.class::cast) + .filter((registrationBean) -> servletName.equals(registrationBean.getServletName())) + .findFirst() + .orElse(null); + } + + private void load(Class... configuration) { this.context = new AnnotationConfigApplicationContext(configuration); } @@ -385,4 +435,50 @@ public void onStartup(ServletContext servletContext) { } + @Configuration(proxyBeanMethods = false) + static class ServletConfigurationWithExtendedAttributes { + + @Bean + @ServletRegistration( + name = "extended", + urlMappings = "/extended/*", + initParameters = { "hello=world", "flag=true" }, + multipartConfig = @ServletRegistration.MultipartConfigValues( + location = "/tmp", + maxFileSize = 1024, + maxRequestSize = 4096, + fileSizeThreshold = 128 + ) + ) + TestServlet testServletWithInitParametersAndMultipart() { + return new TestServlet(); + } + + @Bean + MyExtraServletRegistrationBean myExtraServletRegistrationBean() { + MyExtraServletRegistrationBean bean = new MyExtraServletRegistrationBean(); + bean.addInitParameter("extra", "fromExtraBean"); + return bean; + } + + @Bean + @ServletRegistration( + name = "extendedWithExtraBeans", + urlMappings = "/extra/*", + servletRegistrationBeans = { MyExtraServletRegistrationBean.class } + ) + TestServlet testServletWithExtraBean() { + return new TestServlet(); + } + + static class MyExtraServletRegistrationBean extends ServletRegistrationBean { + + MyExtraServletRegistrationBean() { + super(); + } + + } + } + + } From da9173b09923ad1801d8fd93a50d3911a1694845 Mon Sep 17 00:00:00 2001 From: Dmytro Danilenkov Date: Tue, 8 Apr 2025 00:01:22 +0100 Subject: [PATCH 2/8] Fix for issue #45001 - ServletRegistrationBean has those properties, but @ServletRegistration hasn't: initParameters, servletRegistrationBeans, multipartConfig Signed-off-by: Dmytro Danilenkov Signed-off-by: Dmytro Danilenkov --- .../ServletContextInitializerBeans.java | 56 +++--------- .../boot/web/servlet/ServletRegistration.java | 45 ++-------- .../ServletContextInitializerBeansTests.java | 89 ++++--------------- 3 files changed, 36 insertions(+), 154 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java index fa8a91f0100a..660c705998e6 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java @@ -35,6 +35,9 @@ import jakarta.servlet.Filter; import jakarta.servlet.MultipartConfigElement; import jakarta.servlet.Servlet; +import jakarta.servlet.annotation.MultipartConfig; +import jakarta.servlet.annotation.WebInitParam; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -324,57 +327,24 @@ private void configureFromAnnotation(ServletRegistrationBean bean, Serv } if (registration.initParameters().length > 0) { - bean.setInitParameters(parseInitParameters(registration.initParameters())); + Map initParams = new LinkedHashMap<>(); + for (WebInitParam param : registration.initParameters()) { + initParams.put(param.name(), param.value()); + } + bean.setInitParameters(initParams); } - ServletRegistration.MultipartConfigValues multipart = registration.multipartConfig(); - boolean isMultipartConfigUsed = !(multipart.location().isEmpty() - && multipart.maxFileSize() == -1L - && multipart.maxRequestSize() == -1L - && multipart.fileSizeThreshold() == 0); + MultipartConfig multipart = registration.multipartConfig(); + boolean isMultipartConfigUsed = !(multipart.location().isEmpty() && multipart.maxFileSize() == -1L + && multipart.maxRequestSize() == -1L && multipart.fileSizeThreshold() == 0); if (isMultipartConfigUsed) { - bean.setMultipartConfig(new MultipartConfigElement( - multipart.location(), - multipart.maxFileSize(), - multipart.maxRequestSize(), - multipart.fileSizeThreshold() - )); - } - - for (Class> beanClass : registration.servletRegistrationBeans()) { - ServletRegistrationBean extraBean = this.beanFactory.getBean(beanClass); - bean.getInitParameters().putAll(extraBean.getInitParameters()); - } - - } - - /** - * Parses an array of "key=value" strings into a Map. - * @param initParamsArray Array of strings, expected format "key=value". - * @return Map of parsed key-value pairs. - * @throws IllegalArgumentException if any string doesn't match the "key=value" format. - */ - private Map parseInitParameters(String[] initParamsArray) { - Map initParams = new LinkedHashMap<>(); - for (String kv : initParamsArray) { - int index = kv.indexOf('='); - if (index != -1) { - String key = kv.substring(0, index).trim(); - String value = kv.substring(index + 1).trim(); - initParams.put(key, value); - } - else { - throw new IllegalArgumentException( - "initParameters must be in 'key=value' format, got: " + kv); - } + bean.setMultipartConfig(new MultipartConfigElement(multipart.location(), multipart.maxFileSize(), + multipart.maxRequestSize(), multipart.fileSizeThreshold())); } - return initParams; } } - - /** * {@link RegistrationBeanAdapter} for {@link Filter} beans. */ diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistration.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistration.java index d1b6cf8c98c9..85baeee36bc4 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistration.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistration.java @@ -91,49 +91,14 @@ int loadOnStartup() default -1; /** - * Init parameters to set on the servlet, as {@code "key=value"} pairs. + * Init parameters to set on the servlet (mirrors {@code @WebInitParam} usage). + * @return array of {@link WebInitParam} */ - String[] initParameters() default {}; + WebInitParam[] initParameters() default {}; /** - * (Optional) Additional servlet-registration beans to apply. - * Usually left empty unless you need custom bean logic. + * Multipart configuration. */ - Class>[] servletRegistrationBeans() default {}; + MultipartConfig multipartConfig() default @MultipartConfig; - /** - * Multipart configuration. Mirrors {@link jakarta.servlet.annotation.MultipartConfig}. - * If you omit it (no fields changed), it will not set a multipart config. - */ - MultipartConfigValues multipartConfig() default @MultipartConfigValues; - - /** - * Nested annotation that parallels the fields of - * {@link jakarta.servlet.annotation.MultipartConfig}. Used within - * {@link ServletRegistration#multipartConfig()}. - * @see jakarta.servlet.annotation.MultipartConfig - */ - @Target({}) - @Retention(RetentionPolicy.RUNTIME) - @Documented - @interface MultipartConfigValues { - - /** - * @see jakarta.servlet.annotation.MultipartConfig#location() - */ - String location() default ""; - /** - * @see jakarta.servlet.annotation.MultipartConfig#maxFileSize() - */ - long maxFileSize() default -1L; - /** - * @see jakarta.servlet.annotation.MultipartConfig#maxRequestSize() - */ - long maxRequestSize() default -1L; - /** - * @see jakarta.servlet.annotation.MultipartConfig#fileSizeThreshold() - */ - int fileSizeThreshold() default 0; - - } } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java index 3a3e8560a515..90e69b80206b 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java @@ -23,6 +23,8 @@ import jakarta.servlet.ServletContext; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; +import jakarta.servlet.annotation.MultipartConfig; +import jakarta.servlet.annotation.WebInitParam; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpSessionIdListener; import org.assertj.core.api.ThrowingConsumer; @@ -191,8 +193,7 @@ void shouldApplyExtendedServletRegistrationAnnotation() { assertThat(bean.getServletName()).isEqualTo("extended"); assertThat(bean.getUrlMappings()).containsExactly("/extended/*"); - assertThat(bean.getInitParameters()).containsEntry("hello", "world") - .containsEntry("flag", "true"); + assertThat(bean.getInitParameters()).containsEntry("hello", "world").containsEntry("flag", "true"); assertThat(bean.getMultipartConfig()).isNotNull(); assertThat(bean.getMultipartConfig().getLocation()).isEqualTo("/tmp"); @@ -201,33 +202,7 @@ void shouldApplyExtendedServletRegistrationAnnotation() { assertThat(bean.getMultipartConfig().getFileSizeThreshold()).isEqualTo(128); } - @Test - void shouldApplyServletRegistrationAnnotationWithExtraRegistrationBeans() { - load(ServletConfigurationWithExtendedAttributes.class); - ServletContextInitializerBeans initializerBeans = new ServletContextInitializerBeans( - this.context.getBeanFactory(), TestServletContextInitializer.class); - - ServletRegistrationBean bean = findServletRegistrationBeanByName(initializerBeans, "extendedWithExtraBeans"); - assertThat(bean).as("extendedWithExtraBeans registration bean").isNotNull(); - - assertThat(bean.getServletName()).isEqualTo("extendedWithExtraBeans"); - assertThat(bean.getUrlMappings()).containsExactly("/extra/*"); - - assertThat(bean.getInitParameters()).containsEntry("extra", "fromExtraBean"); - } - - @SuppressWarnings("rawtypes") - private ServletRegistrationBean findServletRegistrationBeanByName( - ServletContextInitializerBeans initializerBeans, String servletName) { - - return initializerBeans.stream() - .filter(ServletRegistrationBean.class::isInstance) - .map(ServletRegistrationBean.class::cast) - .filter((registrationBean) -> servletName.equals(registrationBean.getServletName())) - .findFirst() - .orElse(null); - } - + // Removed the test that relied on servletRegistrationBeans = { ... } private void load(Class... configuration) { this.context = new AnnotationConfigApplicationContext(configuration); @@ -377,7 +352,6 @@ static class TestServlet extends HttpServlet implements ServletContextInitialize @Override public void onStartup(ServletContext servletContext) { - } } @@ -388,7 +362,6 @@ static class OrderedTestServlet extends HttpServlet implements ServletContextIni @Override public void onStartup(ServletContext servletContext) { - } @Override @@ -402,17 +375,14 @@ static class TestFilter implements Filter, ServletContextInitializer { @Override public void onStartup(ServletContext servletContext) { - } @Override public void init(FilterConfig filterConfig) { - } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { - } } @@ -421,7 +391,6 @@ static class TestServletContextInitializer implements ServletContextInitializer @Override public void onStartup(ServletContext servletContext) { - } } @@ -430,7 +399,6 @@ static class OtherTestServletContextInitializer implements ServletContextInitial @Override public void onStartup(ServletContext servletContext) { - } } @@ -439,46 +407,25 @@ public void onStartup(ServletContext servletContext) { static class ServletConfigurationWithExtendedAttributes { @Bean - @ServletRegistration( - name = "extended", - urlMappings = "/extended/*", - initParameters = { "hello=world", "flag=true" }, - multipartConfig = @ServletRegistration.MultipartConfigValues( - location = "/tmp", - maxFileSize = 1024, - maxRequestSize = 4096, - fileSizeThreshold = 128 - ) - ) + @ServletRegistration(name = "extended", urlMappings = "/extended/*", + initParameters = { @WebInitParam(name = "hello", value = "world"), + @WebInitParam(name = "flag", value = "true") }, + multipartConfig = @MultipartConfig(location = "/tmp", maxFileSize = 1024, maxRequestSize = 4096, + fileSizeThreshold = 128)) TestServlet testServletWithInitParametersAndMultipart() { return new TestServlet(); } - @Bean - MyExtraServletRegistrationBean myExtraServletRegistrationBean() { - MyExtraServletRegistrationBean bean = new MyExtraServletRegistrationBean(); - bean.addInitParameter("extra", "fromExtraBean"); - return bean; - } - - @Bean - @ServletRegistration( - name = "extendedWithExtraBeans", - urlMappings = "/extra/*", - servletRegistrationBeans = { MyExtraServletRegistrationBean.class } - ) - TestServlet testServletWithExtraBean() { - return new TestServlet(); - } - - static class MyExtraServletRegistrationBean extends ServletRegistrationBean { - - MyExtraServletRegistrationBean() { - super(); - } - - } } + private ServletRegistrationBean findServletRegistrationBeanByName( + ServletContextInitializerBeans initializerBeans, String name) { + return initializerBeans.stream() + .filter(ServletRegistrationBean.class::isInstance) + .map(ServletRegistrationBean.class::cast) + .filter((r) -> name.equals(r.getServletName())) + .findFirst() + .orElse(null); + } } From 3ca2d2957cf0d7c1de951077be4c6a9a7d4cd753 Mon Sep 17 00:00:00 2001 From: Dmytro Danilenkov Date: Tue, 8 Apr 2025 00:02:54 +0100 Subject: [PATCH 3/8] Fix for issue #45001 - ServletRegistrationBean has those properties, but @ServletRegistration hasn't: initParameters, servletRegistrationBeans, multipartConfig Signed-off-by: Dmytro Danilenkov Signed-off-by: Dmytro Danilenkov --- .../boot/web/servlet/ServletContextInitializerBeansTests.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java index 90e69b80206b..31c799705ade 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java @@ -202,8 +202,6 @@ void shouldApplyExtendedServletRegistrationAnnotation() { assertThat(bean.getMultipartConfig().getFileSizeThreshold()).isEqualTo(128); } - // Removed the test that relied on servletRegistrationBeans = { ... } - private void load(Class... configuration) { this.context = new AnnotationConfigApplicationContext(configuration); } From 839b0876139476b6ccdcc4e17efc3d0c4d15cea2 Mon Sep 17 00:00:00 2001 From: Dmytro Danilenkov Date: Tue, 8 Apr 2025 10:09:20 +0100 Subject: [PATCH 4/8] Fix for issue #45001 - ServletRegistrationBean has those properties, but @ServletRegistration hasn't: initParameters, servletRegistrationBeans, multipartConfig Signed-off-by: Dmytro Danilenkov Signed-off-by: Dmytro Danilenkov --- .../boot/web/servlet/ServletContextInitializerBeans.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java index 24e10daaa042..146b9d286d14 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java @@ -321,7 +321,6 @@ private void configureFromAnnotation(ServletRegistrationBean bean, Serv bean.setAsyncSupported(registration.asyncSupported()); bean.setIgnoreRegistrationFailure(registration.ignoreRegistrationFailure()); bean.setLoadOnStartup(registration.loadOnStartup()); - bean.setUrlMappings(Arrays.asList(registration.urlMappings())); if (registration.initParameters().length > 0) { @@ -339,7 +338,7 @@ private void configureFromAnnotation(ServletRegistrationBean bean, Serv bean.setMultipartConfig(new MultipartConfigElement(multipart.location(), multipart.maxFileSize(), multipart.maxRequestSize(), multipart.fileSizeThreshold())); } - + } } From 9bb90c9f4d9800755995878730e97223dd527040 Mon Sep 17 00:00:00 2001 From: Dmytro Danilenkov Date: Tue, 8 Apr 2025 10:11:06 +0100 Subject: [PATCH 5/8] Fix for issue #45001 - ServletRegistrationBean has those properties, but @ServletRegistration hasn't: initParameters, servletRegistrationBeans, multipartConfig Signed-off-by: Dmytro Danilenkov Signed-off-by: Dmytro Danilenkov --- .../servlet/ServletContextInitializerBeans.java | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java index 146b9d286d14..fb416b49eb0f 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java @@ -323,21 +323,13 @@ private void configureFromAnnotation(ServletRegistrationBean bean, Serv bean.setLoadOnStartup(registration.loadOnStartup()); bean.setUrlMappings(Arrays.asList(registration.urlMappings())); - if (registration.initParameters().length > 0) { - Map initParams = new LinkedHashMap<>(); - for (WebInitParam param : registration.initParameters()) { - initParams.put(param.name(), param.value()); - } - bean.setInitParameters(initParams); + for (WebInitParam param : registration.initParameters()) { + bean.addInitParameter(param.name(), param.value()); } MultipartConfig multipart = registration.multipartConfig(); - boolean isMultipartConfigUsed = !(multipart.location().isEmpty() && multipart.maxFileSize() == -1L - && multipart.maxRequestSize() == -1L && multipart.fileSizeThreshold() == 0); - if (isMultipartConfigUsed) { - bean.setMultipartConfig(new MultipartConfigElement(multipart.location(), multipart.maxFileSize(), - multipart.maxRequestSize(), multipart.fileSizeThreshold())); - } + bean.setMultipartConfig(new MultipartConfigElement(multipart.location(), multipart.maxFileSize(), + multipart.maxRequestSize(), multipart.fileSizeThreshold())); } From c0a84099758007dc9943514c427f85248c703e8d Mon Sep 17 00:00:00 2001 From: Dmytro Danilenkov Date: Wed, 9 Apr 2025 14:03:42 +0100 Subject: [PATCH 6/8] Fix for issue #45001 - ServletRegistrationBean has those properties, but @ServletRegistration hasn't: initParameters, servletRegistrationBeans, multipartConfig Signed-off-by: Dmytro Danilenkov Signed-off-by: Dmytro Danilenkov --- .../ServletContextInitializerBeans.java | 12 +++---- .../boot/web/servlet/ServletRegistration.java | 1 + .../ServletContextInitializerBeansTests.java | 35 ++++++++----------- 3 files changed, 19 insertions(+), 29 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java index fb416b49eb0f..3585ea66c5ae 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java @@ -35,9 +35,7 @@ import jakarta.servlet.Filter; import jakarta.servlet.MultipartConfigElement; import jakarta.servlet.Servlet; -import jakarta.servlet.annotation.MultipartConfig; import jakarta.servlet.annotation.WebInitParam; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -96,9 +94,9 @@ public ServletContextInitializerBeans(ListableBeanFactory beanFactory, addServletContextInitializerBeans(beanFactory); addAdaptableBeans(beanFactory); this.sortedList = this.initializers.values() - .stream() - .flatMap((value) -> value.stream().sorted(AnnotationAwareOrderComparator.INSTANCE)) - .toList(); + .stream() + .flatMap((value) -> value.stream().sorted(AnnotationAwareOrderComparator.INSTANCE)) + .toList(); logMappings(this.initializers); } @@ -327,9 +325,7 @@ private void configureFromAnnotation(ServletRegistrationBean bean, Serv bean.addInitParameter(param.name(), param.value()); } - MultipartConfig multipart = registration.multipartConfig(); - bean.setMultipartConfig(new MultipartConfigElement(multipart.location(), multipart.maxFileSize(), - multipart.maxRequestSize(), multipart.fileSizeThreshold())); + bean.setMultipartConfig(new MultipartConfigElement(registration.multipartConfig())); } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistration.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistration.java index 85baeee36bc4..e054a8b9e367 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistration.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistration.java @@ -98,6 +98,7 @@ /** * Multipart configuration. + * @return multipart config {@link MultipartConfig} */ MultipartConfig multipartConfig() default @MultipartConfig; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java index a10cbe7815e0..1f2f55024f06 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java @@ -203,19 +203,22 @@ void shouldApplyExtendedServletRegistrationAnnotation() { load(ServletConfigurationWithExtendedAttributes.class); ServletContextInitializerBeans initializerBeans = new ServletContextInitializerBeans( this.context.getBeanFactory(), TestServletContextInitializer.class); + assertThatSingleServletRegistration(initializerBeans, (bean) -> { + assertThat(bean.getServletName()).isEqualTo("extended"); + assertThat(bean.getUrlMappings()).containsExactly("/extended/*"); + assertThat(bean.getInitParameters()).containsEntry("hello", "world").containsEntry("flag", "true"); + assertThat(bean.getMultipartConfig()).isNotNull(); + assertThat(bean.getMultipartConfig().getLocation()).isEqualTo("/tmp"); + assertThat(bean.getMultipartConfig().getMaxFileSize()).isEqualTo(1024); + assertThat(bean.getMultipartConfig().getMaxRequestSize()).isEqualTo(4096); + assertThat(bean.getMultipartConfig().getFileSizeThreshold()).isEqualTo(128); + }); - ServletRegistrationBean bean = findServletRegistrationBeanByName(initializerBeans, "extended"); - - assertThat(bean.getServletName()).isEqualTo("extended"); - assertThat(bean.getUrlMappings()).containsExactly("/extended/*"); - - assertThat(bean.getInitParameters()).containsEntry("hello", "world").containsEntry("flag", "true"); + } - assertThat(bean.getMultipartConfig()).isNotNull(); - assertThat(bean.getMultipartConfig().getLocation()).isEqualTo("/tmp"); - assertThat(bean.getMultipartConfig().getMaxFileSize()).isEqualTo(1024); - assertThat(bean.getMultipartConfig().getMaxRequestSize()).isEqualTo(4096); - assertThat(bean.getMultipartConfig().getFileSizeThreshold()).isEqualTo(128); + private void assertThatSingleServletRegistration(ServletContextInitializerBeans initializerBeans, + ThrowingConsumer> code) { + assertThatSingleRegistration(initializerBeans, ServletRegistrationBean.class, code::acceptThrows); } private void load(Class... configuration) { @@ -452,14 +455,4 @@ TestServlet testServletWithInitParametersAndMultipart() { } - private ServletRegistrationBean findServletRegistrationBeanByName( - ServletContextInitializerBeans initializerBeans, String name) { - return initializerBeans.stream() - .filter(ServletRegistrationBean.class::isInstance) - .map(ServletRegistrationBean.class::cast) - .filter((r) -> name.equals(r.getServletName())) - .findFirst() - .orElse(null); - } - } From d4bdaa1d12b19f524afa82c4341c997c43aa7167 Mon Sep 17 00:00:00 2001 From: Dmytro Danilenkov Date: Wed, 9 Apr 2025 15:31:59 +0100 Subject: [PATCH 7/8] Fix for issue #45001 - ServletRegistrationBean has those properties, but @ServletRegistration hasn't: initParameters, servletRegistrationBeans, multipartConfig Signed-off-by: Dmytro Danilenkov Signed-off-by: Dmytro Danilenkov --- .../boot/web/servlet/ServletContextInitializerBeans.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java index 3585ea66c5ae..10a9ca09c44e 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java @@ -94,9 +94,9 @@ public ServletContextInitializerBeans(ListableBeanFactory beanFactory, addServletContextInitializerBeans(beanFactory); addAdaptableBeans(beanFactory); this.sortedList = this.initializers.values() - .stream() - .flatMap((value) -> value.stream().sorted(AnnotationAwareOrderComparator.INSTANCE)) - .toList(); + .stream() + .flatMap((value) -> value.stream().sorted(AnnotationAwareOrderComparator.INSTANCE)) + .toList(); logMappings(this.initializers); } From 4c1af47a00a614251bf82d5f06aee85bfb6cf4e7 Mon Sep 17 00:00:00 2001 From: Dmytro Danilenkov Date: Wed, 9 Apr 2025 15:35:33 +0100 Subject: [PATCH 8/8] Fix for issue #45001 - ServletRegistrationBean has those properties, but @ServletRegistration hasn't: initParameters, servletRegistrationBeans, multipartConfig Signed-off-by: Dmytro Danilenkov Signed-off-by: Dmytro Danilenkov --- .../web/servlet/ServletContextInitializerBeansTests.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java index 1f2f55024f06..6c5d96f5ef9e 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletContextInitializerBeansTests.java @@ -389,6 +389,7 @@ static class TestServlet extends HttpServlet implements ServletContextInitialize @Override public void onStartup(ServletContext servletContext) { + } } @@ -399,6 +400,7 @@ static class OrderedTestServlet extends HttpServlet implements ServletContextIni @Override public void onStartup(ServletContext servletContext) { + } @Override @@ -412,14 +414,17 @@ static class TestFilter implements Filter, ServletContextInitializer { @Override public void onStartup(ServletContext servletContext) { + } @Override public void init(FilterConfig filterConfig) { + } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { + } } @@ -428,6 +433,7 @@ static class TestServletContextInitializer implements ServletContextInitializer @Override public void onStartup(ServletContext servletContext) { + } } @@ -436,6 +442,7 @@ static class OtherTestServletContextInitializer implements ServletContextInitial @Override public void onStartup(ServletContext servletContext) { + } }