2016-08-10 24 views
8

Po aktualizacji z Spring Boot 1.3.7 do 1.4.0 nie możemy już uruchomić naszej aplikacji jako pojedynczej kompilacji słoika z wtyczką Spring Boot Maven. Nasza aplikacja to mały interfejs REST wykorzystujący Jersey i Jetty. Używamy Mavena, a nasz plik pom jest dość standardowym Spring Bootem.Uruchomienie słoika nie powiodło się po uaktualnieniu z Spring Boot 1.3.7 do 1.4.0

Nadal możemy uruchomić aplikację za pomocą mvn spring-boot:run i od wewnątrz Eclipse, ale po uruchomieniu jako jeden słoik Jersey ResourceFinder narzeka, że ​​nie może znaleźć .jar!/BOOT-INF/classes.

Po rozpakowaniu słoika znajduje się folder BOOT-INF/classes zawierający oczekiwane klasy i zasoby.

Każda pomoc doceniona.

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) 

Odpowiedz

8

Z Spring Boot 1.4 release notes:

Zmiana na układ słojów wykonywalnych oznacza, że ​​limitation in Jersey's classpath scanning wpływa teraz wykonywalne pliki jar jak pliki wykonywalne wojennych. Aby obejść problem, klasy, które chcesz skanować przez Jersey, powinny być spakowane w słoiku i włączone jako zależność w BOOT-INF/lib. Program uruchamiający Spring Boot powinien wtedy być configured to unpack those jars on start up, aby Jersey mógł skanować ich zawartość.

+0

Dzięki! Tęskniłem za tym. Działa, gdy zasoby są rejestrowane indywidualnie. – oleb

+0

@oleb Uratowałeś mój dzień !! Dzięki –

1

ze sprężyną Boot (+ Jersey 2) może wyglądać osobnej klasy config (w celu uzyskania indywidualnej rejestracji zasobów):

@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

Tylko inne rozwiązanie:

Chociaż Jersey nie może skanować swoje klasy W nowej wersji słoika z grubym butem można osiągnąć ten sam efekt, korzystając z funkcji skanowania wiosennych ścieżek klasy. W ten sposób można zeskanować pakiet podobny do 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())); 

Uwaga: proszę spojrzeć na źródła org.glassfish.jersey.server.internal.scanning.AnnotationAcceptingListener. To jest rozwiązanie podstawowe i widać, że robi to samo: skanuje klasy opisane w @Path lub @Provider (ale nie udało się znaleźć nic z powodu uszkodzonego mechanizmu skanowania).

Przy okazji, metoda oparta na fasoli napisana przez lanwen może być wyraźniejsza :) Po prostu dodaj do niej także @Provider.