geneqew
geneqew

Reputation: 2581

Unable to run generated jar from spring-boot jersey

Im unable to run the generated jar file with my spring-boot with jersey project.

exception that i encounter is:

Error starting Tomcat context. Exception: org.springframework.beans.factory.UnsatisfiedDependencyException. Message: Error creating bean with name 'org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 1

Project runs properly when it's done via IDE (running the Main class) or when using spring-boot:run

Here are the details of the current setup:

Packaging:

jar

dependency:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-jersey</artifactId>
  <version>1.5.1.RELEASE</version>
</dependency>

my jersey configuration (ResourceConfig) is set to scan packages

@Component
public class JerseyConfiguration extends ResourceConfig {

    public JerseyConfiguration() {
        packages(true, "com.my.base.jaxrs.packages");
    }

}

spring-boot-maven-plugin configured as: org.springframework.boot

<artifactId>spring-boot-maven-plugin</artifactId>
  <executions>
    <execution>
      <goals>
        <goal>repackage</goal>
      </goals>
    </execution>
  </executions>
</plugin>

I also did not use the spring-boot-starter-parent but added the spring-boot-dependencies as indicated in the docs.

Upvotes: 4

Views: 6241

Answers (3)

Alternatively you could do,

@Configuration
public class JerseyConfig extends ResourceConfig {

    JerseyConfig() {
        BeanConfig beanConfig = new BeanConfig();
        beanConfig.setResourcePackage("com.mycompany.api.resources");
    }
}

Upvotes: 0

Norbert Bicsi
Norbert Bicsi

Reputation: 1568

I had this problem, I did not want to complicate things too much so I just registered all my jersey controllers individually.

@Configuration
public class JerseyConfig extends ResourceConfig {

    JerseyConfig() {

        //  my old version that does not play well with spring boot fat jar        
        /*
            packages(
                    "com.mycompany.api.resources"           
            );
        */

        register(com.mycompany.api.resources.FooController.class);
        register(com.mycompany.api.resources.BarController.class);

}

NOTE: I would not recommend this for large projects with many files, it will very quickly become long and unreadable and tedious to maintain. That said, it is a working solution and you will be able to run your jar with the usual java -jar my-project.jar command.

Upvotes: 1

geneqew
geneqew

Reputation: 2581

This is more of a workaround than an actual valid solution to use packages(true, "my.package");

in reference to Anton's answer, i settled with this solution with the limitation that it requires resources with class level @Path or @Provider annotation:

ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
        provider.addIncludeFilter(new AnnotationTypeFilter(Path.class));
        provider.addIncludeFilter(new AnnotationTypeFilter(Provider.class));
        provider.findCandidateComponents("my.package.here").forEach(beanDefinition -> {
            try {
                LOGGER.info("registering {} to jersey config", beanDefinition.getBeanClassName());
                register(Class.forName(beanDefinition.getBeanClassName()));
            } catch (ClassNotFoundException e) {
                LOGGER.warn("Failed to register: {}", beanDefinition.getBeanClassName());
            }
        });

Upvotes: 2

Related Questions