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-15891pull/15951/head
parent
b645e0a581
commit
bbe555a4f5
40
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyManagementChildContextConfiguration.java → spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyChildManagementContextConfiguration.java
40
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyManagementChildContextConfiguration.java → spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyChildManagementContextConfiguration.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<ServletContainer> jerseyServletRegistration(
|
||||||
|
JerseyApplicationPath jerseyApplicationPath, ResourceConfig resourceConfig) {
|
||||||
|
return new ServletRegistrationBean<>(new ServletContainer(resourceConfig),
|
||||||
|
jerseyApplicationPath.getUrlMapping());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ResourceConfig resourceConfig(
|
||||||
|
ObjectProvider<ResourceConfigCustomizer> resourceConfigCustomizers) {
|
||||||
|
ResourceConfig resourceConfig = new ResourceConfig();
|
||||||
|
resourceConfigCustomizers.orderedStream()
|
||||||
|
.forEach((customizer) -> customizer.customize(resourceConfig));
|
||||||
|
return resourceConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
49
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyManagementChildContextConfigurationTests.java → spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyChildManagementContextConfigurationTests.java
49
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyManagementChildContextConfigurationTests.java → spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/jersey/JerseyChildManagementContextConfigurationTests.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<ServletContainer> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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<String> entity = this.testRestTemplate.getForEntity(
|
||||||
|
"http://localhost:" + this.managementPort + "/actuator/health",
|
||||||
|
String.class);
|
||||||
|
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
|
assertThat(entity.getBody()).contains("\"status\":\"UP\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue