From bbe555a4f57b0b41598b344eb6a488b3be28a0f1 Mon Sep 17 00:00:00 2001 From: Madhura Bhave Date: Wed, 13 Feb 2019 13:20:46 -0800 Subject: [PATCH] Split Jersey management context configuration This commit splits the management context configuration for jersey into two separate configurations depending on if the type is SAME or CHILD. The configuration for the SAME context should only kick in if there is no existing ResourceConfig bean. Fixes gh-15891 --- ...ndpointManagementContextConfiguration.java | 43 +---- ...yChildManagementContextConfiguration.java} | 40 ++--- .../JerseyManagementContextConfiguration.java | 50 ++++++ ...seySameManagementContextConfiguration.java | 55 +++++++ .../main/resources/META-INF/spring.factories | 3 +- ...ntManagementContextConfigurationTests.java | 104 ++---------- ...dManagementContextConfigurationTests.java} | 49 +++++- ...meManagementContextConfigurationTests.java | 148 ++++++++++++++++++ ...ApplicationPathAndManagementPortTests.java | 62 ++++++++ 9 files changed, 388 insertions(+), 166 deletions(-) rename spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/jersey/{JerseyManagementChildContextConfiguration.java => JerseyChildManagementContextConfiguration.java} (53%) create mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyManagementContextConfiguration.java create mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseySameManagementContextConfiguration.java rename spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/jersey/{JerseyManagementChildContextConfigurationTests.java => JerseyChildManagementContextConfigurationTests.java} (55%) create mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseySameManagementContextConfigurationTests.java create mode 100644 spring-boot-samples/spring-boot-sample-jersey/src/test/java/sample/jersey/JerseyApplicationPathAndManagementPortTests.java diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/jersey/JerseyWebEndpointManagementContextConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/jersey/JerseyWebEndpointManagementContextConfiguration.java index 0b58722855..73cd87d95a 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/jersey/JerseyWebEndpointManagementContextConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/jersey/JerseyWebEndpointManagementContextConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2018 the original author or authors. + * Copyright 2012-2019 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. @@ -23,9 +23,7 @@ import java.util.HashSet; import java.util.List; import org.glassfish.jersey.server.ResourceConfig; -import org.glassfish.jersey.servlet.ServletContainer; -import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties; import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration; import org.springframework.boot.actuate.endpoint.ExposableEndpoint; @@ -42,14 +40,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; -import org.springframework.boot.autoconfigure.jersey.JerseyProperties; import org.springframework.boot.autoconfigure.jersey.ResourceConfigCustomizer; -import org.springframework.boot.autoconfigure.web.servlet.DefaultJerseyApplicationPath; -import org.springframework.boot.autoconfigure.web.servlet.JerseyApplicationPath; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; /** * {@link ManagementContextConfiguration} for Jersey {@link Endpoint} concerns. @@ -88,37 +80,4 @@ class JerseyWebEndpointManagementContextConfiguration { }; } - @Configuration - @ConditionalOnMissingBean(ResourceConfig.class) - @EnableConfigurationProperties(JerseyProperties.class) - static class ResourceConfigConfiguration { - - @Bean - public ResourceConfig resourceConfig( - ObjectProvider resourceConfigCustomizers) { - ResourceConfig resourceConfig = new ResourceConfig(); - resourceConfigCustomizers.orderedStream() - .forEach((customizer) -> customizer.customize(resourceConfig)); - return resourceConfig; - } - - @Bean - @ConditionalOnMissingBean - public JerseyApplicationPath jerseyApplicationPath(JerseyProperties properties, - ResourceConfig config) { - return new DefaultJerseyApplicationPath(properties.getApplicationPath(), - config); - } - - @Bean - public ServletRegistrationBean jerseyServletRegistration( - ObjectProvider resourceConfigCustomizers, - JerseyApplicationPath jerseyApplicationPath) { - return new ServletRegistrationBean<>( - new ServletContainer(resourceConfig(resourceConfigCustomizers)), - jerseyApplicationPath.getUrlMapping()); - } - - } - } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyManagementChildContextConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyChildManagementContextConfiguration.java similarity index 53% rename from spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyManagementChildContextConfiguration.java rename to spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyChildManagementContextConfiguration.java index 1497d8dee8..bfe0da9449 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyManagementChildContextConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyChildManagementContextConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2018 the original author or authors. + * Copyright 2012-2019 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. @@ -13,57 +13,35 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.boot.actuate.autoconfigure.web.jersey; import org.glassfish.jersey.server.ResourceConfig; -import org.glassfish.jersey.servlet.ServletContainer; -import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration; import org.springframework.boot.actuate.autoconfigure.web.ManagementContextType; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; -import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; -import org.springframework.boot.autoconfigure.jersey.ResourceConfigCustomizer; -import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.boot.autoconfigure.web.servlet.JerseyApplicationPath; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; /** * {@link ManagementContextConfiguration} for Jersey infrastructure when a separate * management context with a web server running on a different port is required. * - * @author Stephane Nicoll - * @author Andy Wilkinson - * @author Phillip Webb - * @since 2.0.0 + * @author Madhura Bhave */ @ManagementContextConfiguration(ManagementContextType.CHILD) -@ConditionalOnWebApplication(type = Type.SERVLET) +@Import(JerseyManagementContextConfiguration.class) +@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnClass(ResourceConfig.class) @ConditionalOnMissingClass("org.springframework.web.servlet.DispatcherServlet") -public class JerseyManagementChildContextConfiguration { - - private final ObjectProvider resourceConfigCustomizers; - - public JerseyManagementChildContextConfiguration( - ObjectProvider resourceConfigCustomizers) { - this.resourceConfigCustomizers = resourceConfigCustomizers; - } - - @Bean - public ServletRegistrationBean jerseyServletRegistration() { - return new ServletRegistrationBean<>( - new ServletContainer(endpointResourceConfig()), "/*"); - } +public class JerseyChildManagementContextConfiguration { @Bean - public ResourceConfig endpointResourceConfig() { - ResourceConfig resourceConfig = new ResourceConfig(); - this.resourceConfigCustomizers.orderedStream() - .forEach((customizer) -> customizer.customize(resourceConfig)); - return resourceConfig; + public JerseyApplicationPath jerseyApplicationPath() { + return () -> "/"; } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyManagementContextConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyManagementContextConfiguration.java new file mode 100644 index 0000000000..28668ad208 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyManagementContextConfiguration.java @@ -0,0 +1,50 @@ +/* + * Copyright 2012-2019 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.boot.actuate.autoconfigure.web.jersey; + +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.servlet.ServletContainer; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.jersey.ResourceConfigCustomizer; +import org.springframework.boot.autoconfigure.web.servlet.JerseyApplicationPath; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; + +/** + * Shared configuration for Jersey-based actuators regardless of management context type. + * + * @author Madhura Bhave + */ +class JerseyManagementContextConfiguration { + + @Bean + public ServletRegistrationBean jerseyServletRegistration( + JerseyApplicationPath jerseyApplicationPath, ResourceConfig resourceConfig) { + return new ServletRegistrationBean<>(new ServletContainer(resourceConfig), + jerseyApplicationPath.getUrlMapping()); + } + + @Bean + public ResourceConfig resourceConfig( + ObjectProvider resourceConfigCustomizers) { + ResourceConfig resourceConfig = new ResourceConfig(); + resourceConfigCustomizers.orderedStream() + .forEach((customizer) -> customizer.customize(resourceConfig)); + return resourceConfig; + } + +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseySameManagementContextConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseySameManagementContextConfiguration.java new file mode 100644 index 0000000000..8f83a7659d --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseySameManagementContextConfiguration.java @@ -0,0 +1,55 @@ +/* + * Copyright 2012-2019 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.boot.actuate.autoconfigure.web.jersey; + +import org.glassfish.jersey.server.ResourceConfig; + +import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration; +import org.springframework.boot.actuate.autoconfigure.web.ManagementContextType; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.jersey.JerseyProperties; +import org.springframework.boot.autoconfigure.web.servlet.DefaultJerseyApplicationPath; +import org.springframework.boot.autoconfigure.web.servlet.JerseyApplicationPath; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; + +/** + * {@link ManagementContextConfiguration} for Jersey infrastructure when the management + * context is the same as the main application context. + * + * @author Madhura Bhave + */ +@ManagementContextConfiguration(ManagementContextType.SAME) +@ConditionalOnMissingBean(ResourceConfig.class) +@Import(JerseyManagementContextConfiguration.class) +@EnableConfigurationProperties(JerseyProperties.class) +@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) +@ConditionalOnClass(ResourceConfig.class) +@ConditionalOnMissingClass("org.springframework.web.servlet.DispatcherServlet") +public class JerseySameManagementContextConfiguration { + + @Bean + @ConditionalOnMissingBean(JerseyApplicationPath.class) + public JerseyApplicationPath jerseyApplicationPath(JerseyProperties properties, + ResourceConfig config) { + return new DefaultJerseyApplicationPath(properties.getApplicationPath(), config); + } + +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories index 725355b6b9..cdfd9396c3 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories @@ -94,7 +94,8 @@ org.springframework.boot.actuate.autoconfigure.endpoint.web.ServletEndpointManag org.springframework.boot.actuate.autoconfigure.endpoint.web.reactive.WebFluxEndpointManagementContextConfiguration,\ org.springframework.boot.actuate.autoconfigure.endpoint.web.servlet.WebMvcEndpointManagementContextConfiguration,\ org.springframework.boot.actuate.autoconfigure.endpoint.web.jersey.JerseyWebEndpointManagementContextConfiguration,\ -org.springframework.boot.actuate.autoconfigure.web.jersey.JerseyManagementChildContextConfiguration,\ +org.springframework.boot.actuate.autoconfigure.web.jersey.JerseySameManagementContextConfiguration,\ +org.springframework.boot.actuate.autoconfigure.web.jersey.JerseyChildManagementContextConfiguration,\ org.springframework.boot.actuate.autoconfigure.web.reactive.ReactiveManagementChildContextConfiguration,\ org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementChildContextConfiguration,\ org.springframework.boot.actuate.autoconfigure.web.servlet.WebMvcEndpointChildContextConfiguration diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/jersey/JerseyWebEndpointManagementContextConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/jersey/JerseyWebEndpointManagementContextConfigurationTests.java index 56f8b661fa..99938bbaf8 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/jersey/JerseyWebEndpointManagementContextConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/jersey/JerseyWebEndpointManagementContextConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2018 the original author or authors. + * Copyright 2012-2019 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,23 +19,20 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.web.jersey; import java.util.Collections; import org.glassfish.jersey.server.ResourceConfig; -import org.glassfish.jersey.servlet.ServletContainer; import org.junit.Test; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.web.jersey.JerseySameManagementContextConfiguration; import org.springframework.boot.actuate.endpoint.web.WebEndpointsSupplier; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.jersey.ResourceConfigCustomizer; -import org.springframework.boot.autoconfigure.web.servlet.DefaultJerseyApplicationPath; -import org.springframework.boot.autoconfigure.web.servlet.JerseyApplicationPath; +import org.springframework.boot.test.context.FilteredClassLoader; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; -import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; /** * Tests for {@link JerseyWebEndpointManagementContextConfiguration}. @@ -51,74 +48,25 @@ public class JerseyWebEndpointManagementContextConfigurationTests { .withUserConfiguration(WebEndpointsSupplierConfig.class); @Test - public void resourceConfigIsAutoConfiguredWhenNeeded() { - this.runner.run( - (context) -> assertThat(context).hasSingleBean(ResourceConfig.class)); - } - - @Test - public void jerseyApplicationPathIsAutoConfiguredWhenNeeded() { + public void resourceConfigCustomizerForEndpointsIsAutoConfigured() { this.runner.run((context) -> assertThat(context) - .hasSingleBean(DefaultJerseyApplicationPath.class)); - } - - @Test - public void jerseyApplicationPathIsConditionalOnMissinBean() { - this.runner.withUserConfiguration(ConfigWithJerseyApplicationPath.class) - .run((context) -> { - assertThat(context).hasSingleBean(JerseyApplicationPath.class); - assertThat(context).hasBean("testJerseyApplicationPath"); - }); - } - - @Test - @SuppressWarnings("unchecked") - public void servletRegistrationBeanIsAutoConfiguredWhenNeeded() { - this.runner.withPropertyValues("spring.jersey.application-path=/jersey") - .run((context) -> { - ServletRegistrationBean bean = context - .getBean(ServletRegistrationBean.class); - assertThat(bean.getUrlMappings()).containsExactly("/jersey/*"); - }); + .hasSingleBean(ResourceConfigCustomizer.class)); } @Test - public void existingResourceConfigBeanShouldNotAutoConfigureRelatedBeans() { - this.runner.withUserConfiguration(ConfigWithResourceConfig.class) - .run((context) -> { - assertThat(context).hasSingleBean(ResourceConfig.class); - assertThat(context).doesNotHaveBean(JerseyApplicationPath.class); - assertThat(context).doesNotHaveBean(ServletRegistrationBean.class); - assertThat(context).hasBean("customResourceConfig"); - }); + public void autoConfigurationIsConditionalOnServletWebApplication() { + ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations + .of(JerseySameManagementContextConfiguration.class)); + contextRunner.run((context) -> assertThat(context) + .doesNotHaveBean(JerseySameManagementContextConfiguration.class)); } @Test - public void resourceConfigIsCustomizedWithResourceConfigCustomizerBean() { - this.runner.withUserConfiguration(CustomizerConfiguration.class) - .run((context) -> { - assertThat(context).hasSingleBean(ResourceConfig.class); - ResourceConfig config = context.getBean(ResourceConfig.class); - ResourceConfigCustomizer customizer = (ResourceConfigCustomizer) context - .getBean("testResourceConfigCustomizer"); - verify(customizer).customize(config); - }); - } - - @Test - public void resourceConfigCustomizerBeanIsNotRequired() { - this.runner.run( - (context) -> assertThat(context).hasSingleBean(ResourceConfig.class)); - } - - @Configuration - static class CustomizerConfiguration { - - @Bean - ResourceConfigCustomizer testResourceConfigCustomizer() { - return mock(ResourceConfigCustomizer.class); - } - + public void autoConfigurationIsConditionalOnClassResourceConfig() { + this.runner.withClassLoader(new FilteredClassLoader(ResourceConfig.class)) + .run((context) -> assertThat(context) + .doesNotHaveBean(JerseySameManagementContextConfiguration.class)); } @Configuration @@ -131,24 +79,4 @@ public class JerseyWebEndpointManagementContextConfigurationTests { } - @Configuration - static class ConfigWithResourceConfig { - - @Bean - public ResourceConfig customResourceConfig() { - return new ResourceConfig(); - } - - } - - @Configuration - static class ConfigWithJerseyApplicationPath { - - @Bean - public JerseyApplicationPath testJerseyApplicationPath() { - return mock(JerseyApplicationPath.class); - } - - } - } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyManagementChildContextConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyChildManagementContextConfigurationTests.java similarity index 55% rename from spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyManagementChildContextConfigurationTests.java rename to spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyChildManagementContextConfigurationTests.java index d81a1f0fd1..6063f535bf 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyManagementChildContextConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyChildManagementContextConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2018 the original author or authors. + * Copyright 2012-2019 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,13 +17,19 @@ package org.springframework.boot.actuate.autoconfigure.web.jersey; import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.servlet.ServletContainer; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.jersey.ResourceConfigCustomizer; +import org.springframework.boot.autoconfigure.web.servlet.JerseyApplicationPath; +import org.springframework.boot.test.context.FilteredClassLoader; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.testsupport.runner.classpath.ClassPathExclusions; import org.springframework.boot.testsupport.runner.classpath.ModifiedClassPathRunner; +import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -32,16 +38,33 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; /** - * Tests for {@link JerseyManagementChildContextConfiguration}. + * Tests for {@link JerseyChildManagementContextConfiguration}. * * @author Andy Wilkinson + * @author Madhura Bhave */ @RunWith(ModifiedClassPathRunner.class) @ClassPathExclusions("spring-webmvc-*") -public class JerseyManagementChildContextConfigurationTests { +public class JerseyChildManagementContextConfigurationTests { private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner() - .withUserConfiguration(JerseyManagementChildContextConfiguration.class); + .withUserConfiguration(JerseyChildManagementContextConfiguration.class); + + @Test + public void autoConfigurationIsConditionalOnServletWebApplication() { + ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations + .of(JerseySameManagementContextConfiguration.class)); + contextRunner.run((context) -> assertThat(context) + .doesNotHaveBean(JerseySameManagementContextConfiguration.class)); + } + + @Test + public void autoConfigurationIsConditionalOnClassResourceConfig() { + this.contextRunner.withClassLoader(new FilteredClassLoader(ResourceConfig.class)) + .run((context) -> assertThat(context) + .doesNotHaveBean(JerseySameManagementContextConfiguration.class)); + } @Test public void resourceConfigIsCustomizedWithResourceConfigCustomizerBean() { @@ -55,6 +78,24 @@ public class JerseyManagementChildContextConfigurationTests { }); } + @Test + public void jerseyApplicationPathIsAutoConfigured() { + this.contextRunner.run((context) -> { + JerseyApplicationPath bean = context.getBean(JerseyApplicationPath.class); + assertThat(bean.getPath()).isEqualTo("/"); + }); + } + + @Test + @SuppressWarnings("unchecked") + public void servletRegistrationBeanIsAutoConfigured() { + this.contextRunner.run((context) -> { + ServletRegistrationBean bean = context + .getBean(ServletRegistrationBean.class); + assertThat(bean.getUrlMappings()).containsExactly("/*"); + }); + } + @Test public void resourceConfigCustomizerBeanIsNotRequired() { this.contextRunner.run( diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseySameManagementContextConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseySameManagementContextConfigurationTests.java new file mode 100644 index 0000000000..17e7e0d236 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseySameManagementContextConfigurationTests.java @@ -0,0 +1,148 @@ +/* + * Copyright 2012-2019 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.boot.actuate.autoconfigure.web.jersey; + +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.servlet.ServletContainer; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.jersey.ResourceConfigCustomizer; +import org.springframework.boot.autoconfigure.web.servlet.DefaultJerseyApplicationPath; +import org.springframework.boot.autoconfigure.web.servlet.JerseyApplicationPath; +import org.springframework.boot.test.context.FilteredClassLoader; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.boot.test.context.runner.WebApplicationContextRunner; +import org.springframework.boot.testsupport.runner.classpath.ClassPathExclusions; +import org.springframework.boot.testsupport.runner.classpath.ModifiedClassPathRunner; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +/** + * Tests for {@link JerseySameManagementContextConfiguration}. + * + * @author Madhura Bhave + */ +@RunWith(ModifiedClassPathRunner.class) +@ClassPathExclusions("spring-webmvc-*") +public class JerseySameManagementContextConfigurationTests { + + private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner() + .withConfiguration(AutoConfigurations + .of(JerseySameManagementContextConfiguration.class)); + + @Test + public void autoConfigurationIsConditionalOnServletWebApplication() { + ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations + .of(JerseySameManagementContextConfiguration.class)); + contextRunner.run((context) -> assertThat(context) + .doesNotHaveBean(JerseySameManagementContextConfiguration.class)); + } + + @Test + public void autoConfigurationIsConditionalOnClassResourceConfig() { + this.contextRunner.withClassLoader(new FilteredClassLoader(ResourceConfig.class)) + .run((context) -> assertThat(context) + .doesNotHaveBean(JerseySameManagementContextConfiguration.class)); + } + + @Test + public void resourceConfigIsCustomizedWithResourceConfigCustomizerBean() { + this.contextRunner.withUserConfiguration(CustomizerConfiguration.class) + .run((context) -> { + assertThat(context).hasSingleBean(ResourceConfig.class); + ResourceConfig config = context.getBean(ResourceConfig.class); + ResourceConfigCustomizer customizer = context + .getBean(ResourceConfigCustomizer.class); + verify(customizer).customize(config); + }); + } + + @Test + public void jerseyApplicationPathIsAutoConfiguredWhenNeeded() { + this.contextRunner.run((context) -> assertThat(context) + .hasSingleBean(DefaultJerseyApplicationPath.class)); + } + + @Test + public void jerseyApplicationPathIsConditionalOnMissingBean() { + this.contextRunner.withUserConfiguration(ConfigWithJerseyApplicationPath.class) + .run((context) -> { + assertThat(context).hasSingleBean(JerseyApplicationPath.class); + assertThat(context).hasBean("testJerseyApplicationPath"); + }); + } + + @Test + public void existingResourceConfigBeanShouldNotAutoConfigureRelatedBeans() { + this.contextRunner.withUserConfiguration(ConfigWithResourceConfig.class) + .run((context) -> { + assertThat(context).hasSingleBean(ResourceConfig.class); + assertThat(context).doesNotHaveBean(JerseyApplicationPath.class); + assertThat(context).doesNotHaveBean(ServletRegistrationBean.class); + assertThat(context).hasBean("customResourceConfig"); + }); + } + + @Test + @SuppressWarnings("unchecked") + public void servletRegistrationBeanIsAutoConfiguredWhenNeeded() { + this.contextRunner.withPropertyValues("spring.jersey.application-path=/jersey") + .run((context) -> { + ServletRegistrationBean bean = context + .getBean(ServletRegistrationBean.class); + assertThat(bean.getUrlMappings()).containsExactly("/jersey/*"); + }); + } + + @Configuration + static class ConfigWithJerseyApplicationPath { + + @Bean + public JerseyApplicationPath testJerseyApplicationPath() { + return mock(JerseyApplicationPath.class); + } + + } + + @Configuration + static class ConfigWithResourceConfig { + + @Bean + public ResourceConfig customResourceConfig() { + return new ResourceConfig(); + } + + } + + @Configuration + static class CustomizerConfiguration { + + @Bean + ResourceConfigCustomizer resourceConfigCustomizer() { + return mock(ResourceConfigCustomizer.class); + } + + } + +} diff --git a/spring-boot-samples/spring-boot-sample-jersey/src/test/java/sample/jersey/JerseyApplicationPathAndManagementPortTests.java b/spring-boot-samples/spring-boot-sample-jersey/src/test/java/sample/jersey/JerseyApplicationPathAndManagementPortTests.java new file mode 100644 index 0000000000..08a2bc3692 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-jersey/src/test/java/sample/jersey/JerseyApplicationPathAndManagementPortTests.java @@ -0,0 +1,62 @@ +/* + * Copyright 2012-2019 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package sample.jersey; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.autoconfigure.web.server.LocalManagementPort; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Integration tests for separate management and main service ports with custom + * application path. + * + * @author Madhura Bhave + */ +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = { + "management.server.port=0", "spring.jersey.application-path=/app" }) +public class JerseyApplicationPathAndManagementPortTests { + + @LocalServerPort + private int port = 9010; + + @LocalManagementPort + private int managementPort = 9011; + + @Autowired + private TestRestTemplate testRestTemplate; + + @Test + public void applicationPathShouldNotAffectActuators() { + ResponseEntity entity = this.testRestTemplate.getForEntity( + "http://localhost:" + this.managementPort + "/actuator/health", + String.class); + assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(entity.getBody()).contains("\"status\":\"UP\""); + } + +} +