tests starter run plugin spring-boot spring-boot-maven-plugin

starter - El arranque con jarra única falló después de la actualización de Spring Boot 1.3.7 a 1.4.0



spring loaded maven plugin (3)

De las notas de la versión de Spring Boot 1.4 :

El cambio en el diseño de los archivos jar ejecutables significa que una limitación en el análisis de classpath de Jersey ahora afecta a los archivos jar ejecutables, así como a los archivos war ejecutables. Para evitar el problema, las clases que desea que Jersey escanee deberían estar empaquetadas en un contenedor e incluidas como una dependencia en BOOT-INF/lib . El iniciador de arranque de primavera debería configurarse para desempaquetar esos tarros al inicio para que Jersey pueda escanear sus contenidos.

Después de actualizar de Spring Boot 1.3.7 a 1.4.0, ya no podemos iniciar nuestra aplicación como una compilación de jar individual con el complemento Spring Boot Maven. Nuestra aplicación es una pequeña interfaz REST que utiliza Jersey y Jetty. Usamos Maven y nuestro archivo pom es bastante estándar Spring Boot.

Todavía podemos ejecutar la aplicación usando mvn spring-boot:run y desde Eclipse, pero cuando se ejecuta como un único contenedor, Jersey ResourceFinder queja de que no puede encontrar .jar!/BOOT-INF/classes .

Cuando desempaque el contenedor, la carpeta BOOT-INF/classes está presente y contiene las clases y recursos esperados.

Cualquier ayuda apreciada.

2016-08-10 14:58:31.162 ERROR 16071 --- [ main] o.s.boot.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)


Con Spring Boot (+ Jersey 2) puede parecer una clase de configuración separada (para lograr el registro de recursos individuales):

@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); }); }; } }


Solo otra solución:

Aunque Jersey no puede escanear tus clases dentro de la nueva versión del frasco de arranque gordo, puedes lograr el mismo efecto usando las herramientas de escaneo de clases de clases Spring. De esta forma, puede escanear un paquete de manera similar a 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()));

Nota: echa un vistazo a la fuente de org.glassfish.jersey.server.internal.scanning.AnnotationAcceptingListener . Esta es la solución de stock y puede ver que hace lo mismo: escanea para las clases anotadas con @Path o @Provider (pero no logra encontrar nada debido al mecanismo de escaneo roto).

Por cierto, el método basado en frijol publicado por lanwen puede ser más claro :) Simplemente agrega @Provider a eso también.