mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:03:22 +08:00
Configure existing Jersey servlet registration created by the SCI
When a Jersey app is deployed to a standalone container, Jersey’s ServletContainerInitializer will run and register a servlet for a class annotated with @ApplicationPath. If Jersey’s ServletContainerInitializer runs before Spring’s, this servlet will take precedence over the servlet registered by JerseyAutoConfiguration and will therefore not be configured with any init parameters specified using spring.jersey.init For the case where Jersey’s SCI runs first, this commit updates JerseyAutoConfiguration to examine the servlet context for an existing registration of Jersey’s servlet (Jersey names the registration using the fully-qualified name of the ResourceConfig subclass). If a registration is found its init parameters are configured using the configuration provided by spring.jersey.init. For the case where Spring’s SCI runs first, this commit updates JerseyAutoConfiguration so that it names its registration using the fully-qualified name of the ResourceConfig sub-class. This allows Jersey’s SCI to find the existing registration rather than attempting to configure its own. Closes gh-2471
This commit is contained in:
parent
2039ed48c1
commit
e33221aae1
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
* Copyright 2012-2016 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.
|
||||
@ -24,8 +24,12 @@ import javax.annotation.PostConstruct;
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRegistration;
|
||||
import javax.ws.rs.ApplicationPath;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.glassfish.jersey.CommonProperties;
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
import org.glassfish.jersey.servlet.ServletContainer;
|
||||
import org.glassfish.jersey.servlet.ServletProperties;
|
||||
@ -49,8 +53,10 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.WebApplicationInitializer;
|
||||
import org.springframework.web.context.ServletContextAware;
|
||||
import org.springframework.web.filter.RequestContextFilter;
|
||||
|
||||
/**
|
||||
@ -68,7 +74,9 @@ import org.springframework.web.filter.RequestContextFilter;
|
||||
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
|
||||
@AutoConfigureBefore(DispatcherServletAutoConfiguration.class)
|
||||
@EnableConfigurationProperties(JerseyProperties.class)
|
||||
public class JerseyAutoConfiguration {
|
||||
public class JerseyAutoConfiguration implements ServletContextAware {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(JerseyAutoConfiguration.class);
|
||||
|
||||
@Autowired
|
||||
private JerseyProperties jersey;
|
||||
@ -129,10 +137,14 @@ public class JerseyAutoConfiguration {
|
||||
ServletRegistrationBean registration = new ServletRegistrationBean(
|
||||
new ServletContainer(this.config), this.path);
|
||||
addInitParameters(registration);
|
||||
registration.setName("jerseyServlet");
|
||||
registration.setName(getServletRegistrationName());
|
||||
return registration;
|
||||
}
|
||||
|
||||
private String getServletRegistrationName() {
|
||||
return ClassUtils.getUserClass(this.config.getClass()).getName();
|
||||
}
|
||||
|
||||
private void addInitParameters(RegistrationBean registration) {
|
||||
for (Entry<String, String> entry : this.jersey.getInit().entrySet()) {
|
||||
registration.addInitParameter(entry.getKey(), entry.getValue());
|
||||
@ -154,6 +166,23 @@ public class JerseyAutoConfiguration {
|
||||
return applicationPath.equals("/") ? "/*" : applicationPath + "/*";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServletContext(ServletContext servletContext) {
|
||||
String servletRegistrationName = getServletRegistrationName();
|
||||
ServletRegistration registration = servletContext
|
||||
.getServletRegistration(servletRegistrationName);
|
||||
if (registration != null) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Configuring existing registration for Jersey servlet '"
|
||||
+ servletRegistrationName + "'");
|
||||
}
|
||||
registration.setInitParameters(this.jersey.getInit());
|
||||
registration.setInitParameter(
|
||||
CommonProperties.METAINF_SERVICES_LOOKUP_DISABLE,
|
||||
Boolean.TRUE.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public static final class JerseyWebApplicationInitializer
|
||||
implements WebApplicationInitializer {
|
||||
|
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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.autoconfigure.jersey;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
|
||||
import org.apache.catalina.Context;
|
||||
import org.apache.catalina.Wrapper;
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
import org.glassfish.jersey.servlet.ServletContainer;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jersey.JerseyAutoConfigurationServletContainerTests.Application;
|
||||
import org.springframework.boot.autoconfigure.test.ImportAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.test.IntegrationTest;
|
||||
import org.springframework.boot.test.OutputCapture;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Tests that verify the behavior when deployed to a Servlet container where Jersey may
|
||||
* have already initialized itself.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(Application.class)
|
||||
@IntegrationTest("server.port=0")
|
||||
@WebAppConfiguration
|
||||
public class JerseyAutoConfigurationServletContainerTests {
|
||||
|
||||
@ClassRule
|
||||
public static OutputCapture output = new OutputCapture();
|
||||
|
||||
@Value("${local.server.port}")
|
||||
private int port;
|
||||
|
||||
@Test
|
||||
public void existingJerseyServletIsAmended() {
|
||||
assertThat(output.toString(),
|
||||
containsString("Configuring existing registration for Jersey servlet"));
|
||||
assertThat(output.toString(), containsString(
|
||||
"Servlet " + Application.class.getName() + " was not registered"));
|
||||
}
|
||||
|
||||
@ImportAutoConfiguration({ EmbeddedServletContainerAutoConfiguration.class,
|
||||
ServerPropertiesAutoConfiguration.class, JerseyAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class })
|
||||
@Import(ContainerConfiguration.class)
|
||||
@Path("/hello")
|
||||
public static class Application extends ResourceConfig {
|
||||
|
||||
@Value("${message:World}")
|
||||
private String msg;
|
||||
|
||||
public Application() {
|
||||
register(Application.class);
|
||||
}
|
||||
|
||||
@GET
|
||||
public String message() {
|
||||
return "Hello " + this.msg;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class ContainerConfiguration {
|
||||
|
||||
@Bean
|
||||
public TomcatEmbeddedServletContainerFactory tomcat() {
|
||||
return new TomcatEmbeddedServletContainerFactory() {
|
||||
|
||||
@Override
|
||||
protected void postProcessContext(Context context) {
|
||||
Wrapper jerseyServlet = context.createWrapper();
|
||||
String servletName = Application.class.getName();
|
||||
jerseyServlet.setName(servletName);
|
||||
jerseyServlet.setServletClass(ServletContainer.class.getName());
|
||||
jerseyServlet.setServlet(new ServletContainer());
|
||||
jerseyServlet.setOverridable(false);
|
||||
context.addChild(jerseyServlet);
|
||||
context.addServletMapping("/*", servletName);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user