Error starting SIngle jar after upgrade from Spring Download 1.3.7 to 1.4.0

After upgrading from Spring Boot 1.3.7 to 1.4.0, we can no longer run our application as a single jar assembly using the Spring Boot Maven plugin. Our application is a small REST interface using Jersey and Jetty. We use Maven and our pom file is pretty standard Spring Boot.

We can still run the application using mvn spring-boot:run and from within Eclipse, but when launched as a jar of Jersey, the ResourceFinder complains that it cannot find .jar!/BOOT-INF/classes .

When I unpack the jar, the BOOT-INF/classes folder is present and contains the expected classes and resources.

Any help was appreciated.

 2016-08-10 14:58:31.162 ERROR 16071 --- [ main] osboot.SpringApplication : Application startup failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jerseyConfig' defined in URL [jar:file:/acmesource/acme/acme-core/acme-core-api/target/acme-core-api-0.1 SNAPSHOT.jar!/BOOT-INF/classes!/com/acme/core/api/JerseyConfig.class]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.acme.core.api.JerseyConfig]: Constructor threw exception; nested exception is org.glassfish.jersey.server.internal.scanning.ResourceFinderException: java.io.FileNotFoundException: /acmesource/acme/acme-core/acme-core api/target/acme-core-api-0.1-SNAPSHOT.jar!/BOOT-INF/classes (No such file or directory) 
+8
spring-boot spring-boot-maven-plugin
source share
3 answers

From Spring Boot 1.4 Release Notes :

Changing the layout of executable cans means that the restriction in tracking the jersey path affects the jar executables as well as war executables. To work around the problem, the classes you want to test Jersey should be packaged in a jar and included as a dependency in BOOT-INF/lib . Spring Boot launcher must be configured to unpack these cans at startup so that Jersey can scan their contents.

+8
source share

Using Spring Boot (+ Jersey 2), it can look like a separate configuration class (to achieve individual resource registration):

 @Configuration public class RestBeansConfiguration { private static final Logger LOG = LoggerFactory.getLogger(RestBeansConfiguration.class); @Inject private ApplicationContext appCtx; @Bean public ResourceConfigCustomizer jersey() { return config -> { LOG.info("Jersey resource classes found:"); appCtx.getBeansWithAnnotation(Path.class).forEach((name, resource) -> { LOG.info(" -> {}", resource.getClass().getName()); config.register(resource); }); }; } } 
+1
source share

Another solution:

Despite the fact that Jersey cannot scan your classes inside the new version of the obese boot can, you can achieve the same effect using Spring's class scanning capabilities. Thus, you can scan the package similarly to ResourceConfig.packages() :

 ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false); scanner.addIncludeFilter(new AnnotationTypeFilter(Provider.class)); scanner.addIncludeFilter(new AnnotationTypeFilter(Path.class)); config.registerClasses(scanner.findCandidateComponents("your.package.to.scan").stream() .map(beanDefinition -> ClassUtils.resolveClassName(beanDefinition.getBeanClassName(), config.getClassLoader())) .collect(Collectors.toSet())); 

Note. Please see the source org.glassfish.jersey.server.internal.scanning.AnnotationAcceptingListener . This is the main solution, and you can see that it does the same thing: it looks at classes annotated with @Path or @Provider (but cannot find anything due to the broken scan mechanism).

By the way, the bean method posted by lanwen may be clearer :) Just add @Provider to this.

+1
source share

All Articles