2016-08-10 2 views
8

Spring Boot 1.3.7에서 1.4.0으로 업그레이드 한 후 더 이상 Spring Boot Maven 플러그인으로 단일 jar 빌드로 애플리케이션을 시작할 수 없습니다. 우리의 어플리케이션은 Jersey와 Jetty를 사용하는 작은 REST 인터페이스입니다. 우리는 Maven을 사용하고 우리의 pom 파일은 꽤 표준적인 Spring Boot이다.Spring Boot 1.3.7에서 1.4.0으로 업그레이드 한 후 SIngle jar 시작에 실패했습니다.

우리는 여전히 이클립스 mvn spring-boot:run과에서를 사용하여 응용 프로그램을 실행할 수 있지만 하나의 단지로 실행할 때 뉴저지 ResourceFinder.jar!/BOOT-INF/classes를 찾을 수 없습니다 뿌려줍니다.

jar 파일의 압축을 풀면 BOOT-INF/classes 폴더가 있고 예상 클래스와 리소스가 들어 있습니다.

도움을 주시면 감사하겠습니다. Spring Boot 1.4 release notes에서

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) 

답변

8

는 :

실행 항아리의 레이아웃에 변화는 limitation in Jersey's classpath scanning 지금 실행 jar 파일 뿐만 아니라 실행 전쟁 파일에 영향을 미치는 것을 의미한다. 이 문제를 해결하려면 Jersey에서 스캔하려는 클래스를 jar 파일로 패키지화하고 BOOT-INF/lib에 종속성으로 포함해야합니다. Jersey가 내용을 스캔 할 수 있도록 Spring Boot launcher는 configured to unpack those jars on start up이어야합니다.

봄 부팅 (+ 저지 2)와
+0

고마워요! 그 중 하나를 놓쳤습니다. 리소스가 개별적으로 등록 될 때 작동합니다. – oleb

+0

@oleb 오늘 하루를 저장했습니다! 감사 –

1

은 별도의 설정 클래스처럼 보일 수 있습니다 (개별 자원 등록을 달성하기 위해) :

@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

그냥 다른 솔루션 :

저지 클래스를 검사 할 수는 없지만 fat 부트 jar의 새 버전에서는 Spring 클래스 경로 검색 기능을 사용하여 동일한 효과를 얻을 수 있습니다. 당신이 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())); 

참고 : org.glassfish.jersey.server.internal.scanning.AnnotationAcceptingListener의 소스를 볼 수 있습니다하시기 바랍니다. 이것은 증권 솔루션이며 동일하다는 것을 알 수 있습니다 : @Path 또는 @Provider으로 주석 된 클래스를 검색합니다 (그러나 깨진 검색 메커니즘 때문에 아무 것도 찾을 수 없습니다).

그런데 lanwen이 게시 한 bean 기반 메소드는 더 명확 할 수 있습니다 :) 그냥 @Provider을 추가하십시오.