Commit 58284a45 by Bertrand Renuart Committed by Dave Syer

Change Jersey init to avoid classpath scanning issues

Scan classpath for Jersey resources with Spring and initialize the Jersey filter with a jaxrs Application instead. (Fixes gh-399, fixes gh-400)
parent 2ba5c4b9
......@@ -225,46 +225,6 @@ normal Eureka functionality under `/eureka/*`.
Eureka background reading: see https://github.com/cfregly/fluxcapacitor/wiki/NetflixOSS-FAQ#eureka-service-discovery-load-balancer[flux capacitor] and https://groups.google.com/forum/?fromgroups#!topic/eureka_netflix/g3p2r7gHnN0[google group discussion].
[TIP]
====
You can run the Eureka server as an executable JAR (or WAR) using the
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#build-tool-plugins[Spring
Boot build tools], but to avoid problems with classpath scanning in
Jersey 1.x you have to tell the build plugins to unpack the jars that
contain JAX-RS resources, e.g. (for Maven)
.pom.xml
[source,xml,indent=0]
----
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<requiresUnpack>
<dependency>
<groupId>com.netflix.eureka</groupId>
<artifactId>eureka-core</artifactId>
</dependency>
<dependency>
<groupId>com.netflix.eureka</groupId>
<artifactId>eureka-client</artifactId>
</dependency>
</requiresUnpack>
</configuration>
</plugin>
----
or with Gradle
.build.gradle
[source,java,indent=0]
----
apply plugin: 'spring-boot'
springBoot {
requiresUnpack = ['com.netflix.eureka:eureka-core','com.netflix.eureka:eureka-client']
}
----
====
[TIP]
====
......
......@@ -57,7 +57,6 @@
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.netflix.eureka</groupId>
......
......@@ -17,21 +17,34 @@
package org.springframework.cloud.netflix.eureka.server;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import javax.servlet.Filter;
import javax.ws.rs.Path;
import javax.ws.rs.ext.Provider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EurekaServerConfigBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.ClassUtils;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.sun.jersey.api.core.DefaultResourceConfig;
import com.sun.jersey.spi.container.servlet.ServletContainer;
/**
......@@ -42,6 +55,13 @@ import com.sun.jersey.spi.container.servlet.ServletContainer;
@EnableDiscoveryClient
@EnableConfigurationProperties(EurekaDashboardProperties.class)
public class EurekaServerConfiguration extends WebMvcConfigurerAdapter {
/**
* List of packages containing Jersey resources required by the Eureka server
*/
private static String[] EUREKA_PACKAGES = new String[] {
"com.netflix.discovery",
"com.netflix.eureka"};
@Bean
@ConditionalOnProperty(prefix = "eureka.dashboard", name = "enabled", matchIfMissing = true)
......@@ -49,20 +69,62 @@ public class EurekaServerConfiguration extends WebMvcConfigurerAdapter {
return new EurekaController();
}
/**
* Register the Jersey filter
*
* @param eurekaJerseyApp the jersey application
* @return
*/
@Bean
public FilterRegistrationBean jersey() {
public FilterRegistrationBean jerseyFilterRegistration(javax.ws.rs.core.Application eurekaJerseyApp) {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new ServletContainer());
bean.setFilter(new ServletContainer(eurekaJerseyApp));
bean.setOrder(Ordered.LOWEST_PRECEDENCE);
bean.addInitParameter("com.sun.jersey.config.property.WebPageContentRegex",
EurekaServerConfigBean.DEFAULT_PREFIX + "/(fonts|images|css|js)/.*");
bean.addInitParameter("com.sun.jersey.config.property.packages",
"com.netflix.discovery;com.netflix.eureka");
bean.setUrlPatterns(Collections
.singletonList(EurekaServerConfigBean.DEFAULT_PREFIX + "/*"));
return bean;
}
/**
* Construct a Jersey {@link javax.ws.rs.core.Application} with all the resources
* required by the Eureka server.
*/
@Bean
public javax.ws.rs.core.Application jerseyApplication(Environment environment, ResourceLoader resourceLoader) {
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false, environment);
// Filter to include only classes that have a particular annotation.
//
provider.addIncludeFilter(new AnnotationTypeFilter(Path.class));
provider.addIncludeFilter(new AnnotationTypeFilter(Provider.class));
// Find classes in Eureka packages (or subpackages)
//
Set<Class<?>> classes = Sets.newHashSet();
for(String basePackage: EUREKA_PACKAGES) {
Set<BeanDefinition> beans = provider.findCandidateComponents(basePackage);
for (BeanDefinition bd : beans) {
Class<?> cls = ClassUtils.resolveClassName(bd.getBeanClassName(), resourceLoader.getClassLoader());
classes.add(cls);
}
}
// Construct the Jersey ResourceConfig
//
Map<String, Object> propsAndFeatures = Maps.newHashMap();
propsAndFeatures.put(
// Skip static content used by the webapp
ServletContainer.PROPERTY_WEB_PAGE_CONTENT_REGEX,
EurekaServerConfigBean.DEFAULT_PREFIX + "/(fonts|images|css|js)/.*");
DefaultResourceConfig rc = new DefaultResourceConfig(classes);
rc.setPropertiesAndFeatures(propsAndFeatures);
return rc;
}
@Bean
public FilterRegistrationBean traceFilterRegistration(
@Qualifier("webRequestLoggingFilter") Filter filter) {
......@@ -71,5 +133,4 @@ public class EurekaServerConfiguration extends WebMvcConfigurerAdapter {
bean.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
return bean;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment