Spring boot application won't run when trying to run from the jar file

前端 未结 3 1816
别跟我提以往
别跟我提以往 2020-12-11 17:13

I have a spring boot application which works fine when run through intellij. But when I run it from the jar I am getting the below exception.

        2017-02         


        
相关标签:
3条回答
  • 2020-12-11 17:34

    To add onto @Bampfer's answer since Googleing brought me here. This is a way to not have to unpack your resources in a separate module and have dynamic component scanning.

    Create an custom annotation @JaxRsResource that you put on any resource class.

    public @interface JaxRsResource {
    }
    
    @Named
    @JaxRsResource
    @Path("/my/api/path")
    public class MyResource {
        @GET
        public String helloWorld() { return "Hello World"; }
    }
    

    I then utilized spring's component scanning api from this post: Scanning Java annotations at runtime and registered the components I found with my custom annotation and called the register function.

    @Configuration
    public class JaxrsApplication extends ResourceConfig {
    
        private final Logger logger = LoggerFactory.getLogger(JaxrsApplication.class);
    
        public JaxrsApplication() {
    
            final ClassPathScanningCandidateComponentProvider scanner =
                    new ClassPathScanningCandidateComponentProvider(false);
    
            scanner.addIncludeFilter(new AnnotationTypeFilter(JaxRsResource.class));
    
            for (final BeanDefinition resourceBean : scanner.findCandidateComponents("my.base.package")) {
                    try {
                        final Class resourceClass = getClass().getClassLoader().loadClass(resourceBean.getBeanClassName());
                        register(resourceClass);
                    } catch (final ClassNotFoundException e) {
                        logger.error(String.format("Unable to load Jax-RS resource {}.", resourceBean.getBeanClassName()), e);
                    }
                }
            }
        }
    }
    

    Note: You have to load the class from the class loader and pass the Class object to register(). If you only pass the class name as a string to the register method it won't load the resource.

    0 讨论(0)
  • 2020-12-11 17:37

    @abaghel answer has the correct explanation, and arguably the best solution as well.

    Since Jersey's scanning step is what's failing, another way to work around it is to explicitly register each resource. I replaced this:

    @Component
    public JerseyConfig() extends ResourceConfig {
        packages("com.mydomain.resource");
    }
    

    with

    @Component
    public JerseyConfig() extends ResourceConfig {
        register(TimeResource.class);
        register(SpaceResource.class);
        // etc.
    }
    

    (Tested with Spring Boot 2.1.3)

    My code has about 25 Jersey of these resource classes to register. This highlights the downside to this approach, namely that the explicit registration has to be maintained. New resource classes won't be found automatically, and it can be a confusing error to run into.

    On the other hand, you don't need to split your project up. So explicit registration might occasionally be good enough.

    0 讨论(0)
  • 2020-12-11 17:50

    You have spring-boot-starter-jersey in your pom.xml. The error you are getting is /BOOT-INF/classes (No such file or directory). This is the issue with jersey which doesn't work well with spring-boot fat jar. Please refer this and this for more details. For work around you have to package the classes that should be scanned by jersey in a jar and extract the jar as given at Spring-Boot documentation Extract specific libraries when an executable jar runs

    0 讨论(0)
提交回复
热议问题