Browse Source
Previously, actuator endpoints were registered with Jersey upon injection of the ResourceConfig bean into a registrar class rather than using a ResourceConfigCustomizer. This was done to fix a problem when running the Actuator on a separate port where the main application context's customizers were also applied to the management context, breaking the singleton contract for those resources. This approach meant that the registration could be performed at any point after the ResourceConfig had been created. When Jersey's configured as a Filter this resulted in the registration failing as the attempt was being made after the Filter lifecyle callbacks which make the ResourceConfig immutable. This commit reworks the endpoint registration to be performed using a ManagementContextResourceConfigCustomizer, a resource config customizer that's only applied to the ResourceConfig that's used by the Actuator. When there's a separate management context, this ResourceConfig is created by the Actuator's auto-configuration and the management context resource config customizers are applied to it during its creation. The main application's customizers are not applied. When the actuator is using the same context as the main application, this ResourceConfig is created by the main application. In this case a ResourceConfigCustomizer is defined that delegates to all ManagementContextResourceConfigCustomizers, allowing them to register the actuator endpoints with the main ResourceConfig. Fixes gh-25262pull/25486/head
14 changed files with 358 additions and 51 deletions
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
/* |
||||
* Copyright 2012-2021 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 |
||||
* |
||||
* https://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; |
||||
|
||||
/** |
||||
* Callback interface that can be implemented by beans wishing to customize Jersey's |
||||
* {@link ResourceConfig} in the management context before it is used. |
||||
* |
||||
* @author Andy Wilkinson |
||||
* @since 2.3.10 |
||||
*/ |
||||
public interface ManagementContextResourceConfigCustomizer { |
||||
|
||||
/** |
||||
* Customize the resource config. |
||||
* @param config the {@link ResourceConfig} to customize |
||||
*/ |
||||
void customize(ResourceConfig config); |
||||
|
||||
} |
||||
@ -0,0 +1,78 @@
@@ -0,0 +1,78 @@
|
||||
/* |
||||
* Copyright 2012-2021 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 |
||||
* |
||||
* https://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.endpoint.web.jersey; |
||||
|
||||
import java.util.Set; |
||||
|
||||
import org.glassfish.jersey.server.ResourceConfig; |
||||
import org.glassfish.jersey.server.model.Resource; |
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; |
||||
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; |
||||
import org.springframework.boot.actuate.autoconfigure.web.jersey.JerseySameManagementContextConfiguration; |
||||
import org.springframework.boot.autoconfigure.AutoConfigurations; |
||||
import org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration; |
||||
import org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener; |
||||
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; |
||||
import org.springframework.boot.logging.LogLevel; |
||||
import org.springframework.boot.test.context.FilteredClassLoader; |
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner; |
||||
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.web.servlet.DispatcherServlet; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
/** |
||||
* Integration tests for web endpoints running on Jersey. |
||||
* |
||||
* @author Andy Wilkinson |
||||
*/ |
||||
class JerseyWebEndpointIntegrationTests { |
||||
|
||||
@Test |
||||
void whenJerseyIsConfiguredToUseAFilterThenResourceRegistrationSucceeds() { |
||||
new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new) |
||||
.withConfiguration(AutoConfigurations.of(JerseySameManagementContextConfiguration.class, |
||||
JerseyAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class, |
||||
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, |
||||
JerseyWebEndpointManagementContextConfiguration.class)) |
||||
.withUserConfiguration(ResourceConfigConfiguration.class) |
||||
.withClassLoader(new FilteredClassLoader(DispatcherServlet.class)) |
||||
.withInitializer(new ConditionEvaluationReportLoggingListener(LogLevel.INFO)) |
||||
.withPropertyValues("spring.jersey.type=filter", "server.port=0").run((context) -> { |
||||
assertThat(context).hasNotFailed(); |
||||
Set<Resource> resources = context.getBean(ResourceConfig.class).getResources(); |
||||
assertThat(resources).hasSize(1); |
||||
Resource resource = resources.iterator().next(); |
||||
assertThat(resource.getPath()).isEqualTo("/actuator"); |
||||
}); |
||||
} |
||||
|
||||
@Configuration(proxyBeanMethods = false) |
||||
static class ResourceConfigConfiguration { |
||||
|
||||
@Bean |
||||
ResourceConfig resourceConfig() { |
||||
return new ResourceConfig(); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
/* |
||||
* Copyright 2012-2021 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 |
||||
* |
||||
* https://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 smoketest.jersey; |
||||
|
||||
import org.springframework.test.context.TestPropertySource; |
||||
|
||||
/** |
||||
* Smoke tests for Jersey configured as a Filter. |
||||
* |
||||
* @author Andy Wilkinson |
||||
*/ |
||||
@TestPropertySource(properties = "spring.jersey.type=filter") |
||||
class JerseyFilterApplicationTests extends AbstractJerseyApplicationTests { |
||||
|
||||
} |
||||
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
/* |
||||
* Copyright 2012-2021 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 |
||||
* |
||||
* https://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 smoketest.jersey; |
||||
|
||||
import org.springframework.test.context.TestPropertySource; |
||||
|
||||
/** |
||||
* Integration tests for Jersey configured as a Servlet using separate management and main |
||||
* service ports. |
||||
* |
||||
* @author Andy Wilkinson |
||||
*/ |
||||
@TestPropertySource(properties = "spring.jersey.type=filter") |
||||
public class JerseyFilterManagementPortTests extends AbstractJerseyManagementPortTests { |
||||
|
||||
} |
||||
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
/* |
||||
* Copyright 2012-2021 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 |
||||
* |
||||
* https://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 smoketest.jersey; |
||||
|
||||
/** |
||||
* Smoke tests for Jersey configured as a Servlet. |
||||
* |
||||
* @author Andy Wilkinson |
||||
*/ |
||||
class JerseyServletApplicationTests extends AbstractJerseyApplicationTests { |
||||
|
||||
} |
||||
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
/* |
||||
* Copyright 2012-2021 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 |
||||
* |
||||
* https://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 smoketest.jersey; |
||||
|
||||
/** |
||||
* Integration tests for Jersey configured as a Servlet using separate management and main |
||||
* service ports. |
||||
* |
||||
* @author Andy Wilkinson |
||||
*/ |
||||
public class JerseyServletManagementPortTests extends AbstractJerseyManagementPortTests { |
||||
|
||||
} |
||||
Loading…
Reference in new issue