问题
I'm trying to package my Spring Boot App which uses Jersey. When the app is launched during development it has no problems to run, the problem comes when I generate a jar file using
mvnw package && java -jar target/gs-spring-boot-docker-0.1.0.jar
Which produces the following error.
Error creating bean with name 'org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration': Unsatisfied depend ency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jerseyConfig' defined in URL [jar:file:..path/Backend/target/celulascontentas-2.0.jar!/BOOT-INF/classes!/tech/aabo/celulascontenta s/config/JerseyConfig.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [tech.aabo.ce lulascontentas.config.JerseyConfig]: Constructor threw exception; nested exception is org.glassfish.jersey.server.internal.scanning.ResourceFinderException: java.io.File NotFoundException: ..path\Backend\target\celulascontentas-2.0.jar!\BOOT-INF\classes (The system cannot find the path s pecified)
My Jersey Config looks like this:
package tech.aabo.celulascontentas.config;
import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;
import org.springframework.stereotype.Component;
import javax.ws.rs.ApplicationPath;
@Component
@ApplicationPath("/api")
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(JacksonJaxbJsonProvider.class);
packages("tech.aabo.celulascontentas.endpoint");
property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
}
}
And my pom.xml looks like:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>tech.aabo</groupId>
<artifactId>celulascontentas</artifactId>
<version>2.0</version>
<packaging>jar</packaging>
<name>celulascontentas</name>
<description>API para celulas contentas</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- Core -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- DB -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Extra -->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.11.133</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
I have tried various combinations but it always produces the same error. Those anybody now how to fix it?
Thanks
回答1:
Jersey classpath scanning limitations
The change to the layout of executable jars means that a limitation in Jersey’s classpath scanning now affects executable jar files as well as executable war files. To work around the problem, classes that you wish to be scanned by Jersey should be packaged in a jar and included as a dependency in BOOT-INF/lib. The Spring Boot launcher should then be configured to unpack those jars on start up so that Jersey can scan their contents.
This is a known problem and there is a open pull request that's not merged yet. I suggest you refer this issue which mentions some workarounds.
There are few workarounds
Configure Boot's Maven plugin to unpack the jars containing that package
Use the below workaround
jersey 1:
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.ws.rs.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import com.sun.jersey.api.core.DefaultResourceConfig;
@Component
public class RestApplication extends DefaultResourceConfig {
private static final Logger log = LoggerFactory.getLogger(RestApplication.class);
public RestApplication() {
getFeatures().put("com.sun.jersey.api.json.POJOMappingFeature", true);
}
@Autowired
ApplicationContext appCtx;
@PostConstruct
public void setup() {
log.info("Rest classes found:");
Map<String,Object> beans = appCtx.getBeansWithAnnotation(Path.class);
for (Object o : beans.values()) {
log.info(" -> " + o.getClass().getName());
getSingletons().add(o);
}
}
}
and
@Autowired
RestApplication restApplication;
@Bean
public ServletRegistrationBean jersey() {
ServletRegistrationBean bean = new ServletRegistrationBean();
bean.setServlet(new ServletContainer(restApplication));
bean.addInitParameter("com.sun.jersey.api.json.POJOMappingFeature", "true");
bean.setUrlMappings(Arrays.asList("/rest/*"));
return bean;
}
jersery2:
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.Path;
import org.glassfish.jersey.server.ResourceConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import com.sun.jersey.api.core.ResourceConfig;
@Component
@ApplicationPath("/rest")
public class JerseyConfig extends ResourceConfig {
private static final Logger log = LoggerFactory.getLogger(JerseyConfig.class);
@Autowired
ApplicationContext appCtx;
@PostConstruct
public void setup() {
log.info("Rest classes found:");
Map<String,Object> beans = appCtx.getBeansWithAnnotation(Path.class);
for (Object o : beans.values()) {
log.info(" -> " + o.getClass().getName());
register(o);
}
}
}
来源:https://stackoverflow.com/questions/50595221/spring-boot-and-jersey-produces-classnotfound