question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Spring Boot application runs fine with spring-boot:run but not with java -jar

See original GitHub issue

Spring Boot version: 1.5.3 Java: 1.8 Maven: 3.5.0 OS: Ubuntu 16.10 x64

I have a Spring Boot project here: https://github.com/aifa-gov-it/invoices-processor

I have multiple unit and integration test, marked with @SpringBootTest that run fine, as you can see from the Travis CI build logs (example: https://travis-ci.org/aifa-gov-it/invoices-processor/builds/236038253).

If I build the project with mvn clean install -s settings.xml and then run the jar with java -jar target/database-uploader-exec.jar (the -exec qualifier has been added with the qualifier configuration option of the spring-boot-maven-plugin, I get a:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'java.util.Set<it.gov.aifa.invoice_processor.service.InvoiceMappingToEntityConverter<it.gov.aifa.invoice_processor.mapping.InvoiceMapping<java.lang.String>, it.gov.aifa.invoice_processor.entity.invoice.Invoice>>' available:
expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations: {@org.hibernate.validator.constraints.NotEmpty(message={org.hibernate.validator.constraints.NotEmpty.message}, payload=[], groups=[])}

The jar runs fine with the spring-boot:run goal and so do unit and integration tests, so I’m suspecting an issue with the executable JAR. I also tried to add the executable configuration option but it changed nothing.

Shouldn’t the spring-boot-maven-plugin produce a bootable JAR out-of-the-box?

Relevant bits:

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>it.gov.aifa</groupId>
    <artifactId>database-uploader</artifactId>
    <version>1.0.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
    </parent>

    <developers>
        <developer>
            <id>ferrarimarco</id>
            <email>ferrari.marco@gmail.com</email>
            <name>Marco Ferrari</name>
            <organization>Italian Medicines Agency - AIFA</organization>
            <organizationUrl>http://www.aifa.gov.it/</organizationUrl>
        </developer>
    </developers>

    <inceptionYear>2017</inceptionYear>

    <organization>
        <name>Italian Medicines Agency - AIFA</name>
        <url>http://www.aifa.gov.it/</url>
    </organization>

    <properties>
        <!-- Environment properties -->
        <java.version>1.8</java.version>
        <maven-required.version>3.3.9</maven-required.version>
        <project.resources.sourceEncoding>UTF-8</project.resources.sourceEncoding>

        <!-- Dependencies (keep this alphabetically ordered) -->
        <commons-io.version>2.5</commons-io.version>
        <commons-lang3.version>3.5</commons-lang3.version>
        <java-ee-api.version>7.0</java-ee-api.version>
        <liquibase-hibernate5.version>3.6</liquibase-hibernate5.version>
        <mockito-all.version>2.0.2-beta</mockito-all.version>
        <ojdbc.version>12.2.0.1</ojdbc.version>
        <spring-boot.version>${project.parent.version}</spring-boot.version>
        <sysout-over-slf4j.version>1.0.2</sysout-over-slf4j.version>
        <testng.version>6.11</testng.version>

        <!-- Plugins (keep this alphabetically ordered) -->
        <coveralls-maven-plugin.version>4.3.0</coveralls-maven-plugin.version>
        <jacoco-maven-plugin.version>0.7.9</jacoco-maven-plugin.version>
        <maven-project-info-reports-plugin.version>2.9</maven-project-info-reports-plugin.version>
        <maven-release-plugin.version>2.5.3</maven-release-plugin.version>
        <maven-surefire-report-plugin.version>${maven-surefire-plugin.version}</maven-surefire-report-plugin.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.tomcat</groupId>
                    <artifactId>tomcat-jdbc</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-batch</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-oxm</artifactId>
        </dependency>
        <dependency>
            <groupId>org.liquibase</groupId>
            <artifactId>liquibase-core</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>${commons-lang3.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>${commons-io.version}</version>
        </dependency>
        <dependency>
            <groupId>com.oracle.jdbc</groupId>
            <artifactId>ojdbc8</artifactId>
            <version>${ojdbc.version}</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>log4j-over-slf4j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>uk.org.lidalia</groupId>
            <artifactId>sysout-over-slf4j</artifactId>
            <version>${sysout-over-slf4j.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
        </dependency>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>${testng.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>${mockito-all.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.jayway.jsonpath</groupId>
            <artifactId>json-path</artifactId>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>

        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-enforcer-plugin</artifactId>
                <executions>
                    <execution>
                        <id>enforce-versions</id>
                        <goals>
                            <goal>enforce</goal>
                        </goals>
                        <configuration>
                            <rules>
                                <requireMavenVersion>
                                    <version>${maven-required.version}</version>
                                </requireMavenVersion>
                                <requireJavaVersion>
                                    <version>${java.version}</version>
                                </requireJavaVersion>
                            </rules>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <configuration>
                    <!-- Skips tests if the value of skip.unit.tests property is true -->
                    <skipTests>${skipTests}</skipTests>
                    <skipITs>${skipTests}</skipITs>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
                <executions>
                    <execution>
                        <id>attach-javadocs</id>
                        <goals>
                            <goal>jar</goal>
                            <goal>test-jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <executions>
                    <execution>
                        <id>generate-test-jar</id>
                        <goals>
                            <goal>test-jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-release-plugin</artifactId>
                <version>${maven-release-plugin.version}</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <goals>
                            <goal>jar</goal>
                            <goal>test-jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <!-- Skips unit tests if the value of skip.unit.tests property is true -->
                    <skipTests>${skipTests}</skipTests>
                    <workingDirectory>${project.build.directory}</workingDirectory>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.eluder.coveralls</groupId>
                <artifactId>coveralls-maven-plugin</artifactId>
                <version>${coveralls-maven-plugin.version}</version>
            </plugin>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>${jacoco-maven-plugin.version}</version>
                <executions>
                    <execution>
                        <id>default-prepare-agent</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>default-prepare-agent-integration</id>
                        <goals>
                            <goal>prepare-agent-integration</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>default-check</id>
                        <goals>
                            <goal>check</goal>
                        </goals>
                        <configuration>
                            <haltOnFailure>false</haltOnFailure>
                            <rules>
                                <!-- implementation is needed only for Maven 2 -->
                                <rule implementation="org.jacoco.maven.RuleConfiguration">
                                    <element>BUNDLE</element>
                                    <limits>
                                        <!-- implementation is needed only for Maven 2 -->
                                        <limit implementation="org.jacoco.report.check.Limit">
                                            <counter>COMPLEXITY</counter>
                                            <value>COVEREDRATIO</value>
                                            <minimum>0.80</minimum>
                                        </limit>
                                    </limits>
                                </rule>
                            </rules>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.liquibase</groupId>
                <artifactId>liquibase-maven-plugin</artifactId>
                <version>${liquibase.version}</version>
                <configuration>
                    <changeLogFile>src/main/resources/db/changelog/db.changelog-master.yaml</changeLogFile>
                    <diffChangeLogFile>src/main/resources/db/changelog/db.changelog-${project.version}.yaml</diffChangeLogFile>
                    <driver>org.h2.Driver</driver>
                    <outputFileEncoding>${project.resources.sourceEncoding}</outputFileEncoding>
                    <referenceUrl>hibernate:spring:it.gov.aifa.invoice_processor.entity?dialect=org.hibernate.dialect.Oracle12cDialect&amp;hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy</referenceUrl>
                    <url>jdbc:h2:mem:testdb</url>
                    <username>sa</username>
                    <password>sa</password>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.liquibase.ext</groupId>
                        <artifactId>liquibase-hibernate5</artifactId>
                        <version>${liquibase-hibernate5.version}</version>
                    </dependency>
                    <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-data-jpa</artifactId>
                        <version>${spring-boot.version}</version>
                        <exclusions>
                            <exclusion>
                                <groupId>org.apache.tomcat</groupId>
                                <artifactId>tomcat-jdbc</artifactId>
                            </exclusion>
                        </exclusions>
                    </dependency>
                    <dependency>
                        <groupId>org.hibernate</groupId>
                        <artifactId>hibernate-validator</artifactId>
                        <version>${hibernate-validator.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <classifier>exec</classifier>
                    <executable>true</executable>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <reporting>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-report-plugin</artifactId>
                <version>${maven-surefire-report-plugin.version}</version>
                <reportSets>
                    <reportSet>
                        <id>unit-tests</id>
                        <reports>
                            <report>report-only</report>
                        </reports>
                    </reportSet>
                    <reportSet>
                        <id>integration-tests</id>
                        <reports>
                            <report>failsafe-report-only</report>
                        </reports>
                    </reportSet>
                </reportSets>
            </plugin>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <reportSets>
                    <reportSet>
                        <id>jacoco-unit-tests</id>
                        <reports>
                            <report>report</report>
                        </reports>
                    </reportSet>
                    <reportSet>
                        <id>jacoco-integration-tests</id>
                        <reports>
                            <report>report-integration</report>
                        </reports>
                    </reportSet>
                </reportSets>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-project-info-reports-plugin</artifactId>
                <version>${maven-project-info-reports-plugin.version}</version>
            </plugin>
        </plugins>
    </reporting>
</project>

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

3reactions
wilkinsonacommented, May 26, 2017

This is quite a complicated one, but doesn’t actually have anything to do with Spring Boot. The reason for the different behaviour isn’t due to a difference in mvn spring-boot:run vs java -jar specifically, but due to a difference in the ordering of the class path. In both cases it’s governed by Maven.

We can conclude from mvn spring-boot:run working and java -jar failing that Maven uses a different ordering for the classes when running and when packing them in a jar file. It’s also interesting that the jar that I built (which works) has its contents in a different order to those in the jar that you built (which doesn’t). From that, we can conclude that ordering of classes in a Maven-built jar may vary as well.

The ordering of the class path is important as it has an effect on when the beans in your application are created. When Spring Framework is looking at a bean instance it has more information available to it about the bean’s type than it does when it’s only looking at a bean definition. The injection that’s failing is reliant upon the resolution of a fairly complex generic type signature and this only succeeds when the Invoice1_2MappingToEntityConverterImpl bean has been instantiated and the Framework can examine an instance of this bean rather than just its definition.

In the failing case, the injection of Set<InvoiceMappingToEntityConverter<InvoiceMapping<String>, Invoice>> into InvoiceMappingProcessor fails because it is happening before Invoice1_2MappingToEntityConverterImpl has been instantiated. In the successful case, the injection succeeds as Invoice1_2MappingToEntityConverterImpl has already been instantiated.

In the case of the two different jars, this difference in ordering is due to the different ordering of the entries in the jar:

    42617  05-25-2017 20:01   BOOT-INF/classes/it/gov/aifa/invoice_processor/service/impl/Invoice1_2MappingToEntityConverterImpl.class
     3882  05-25-2017 20:01   BOOT-INF/classes/it/gov/aifa/invoice_processor/service/impl/InvoiceMappingProcessor.class

vs

     3882  05-25-2017 22:08   BOOT-INF/classes/it/gov/aifa/invoice_processor/service/impl/InvoiceMappingProcessor.class
    42617  05-25-2017 22:08   BOOT-INF/classes/it/gov/aifa/invoice_processor/service/impl/Invoice1_2MappingToEntityConverterImpl.class

If I rename InvoiceMappingProcessor to AnInvoiceMappingProcessor I can reproduce the injection failure in Eclipse as it causes the processor bean to be created before the converter bean as the processor then appears first on the class path.

There may be an improvement that could be made in Spring Framework here, but I really can’t tell for certain. If you’d like to pursue that, I would recommend stripping your application down as much as possible to a bare minimum that reproduces the problem and then opening a Spring Framework JIRA.

0reactions
romeo16971commented, Apr 4, 2019

@wilkinsona I solved the problem. I use jsf ( i knew jsf is stateful but customer’s requirement ) spring boot for my project. I add folder “META-INF/resources” under “src/main/resources” in order to act like “webapp” like normal maven web project. When i run it in “mvn spring-boot:run” or run project in IDE, it works perfectly but when i build it to jar file to distribute to EC2. It not read “faces-config.xml” under “META-INF/resources/WEB-INF”. Thus resource-bundle inside faces-config.xml was not setup. So i move it in “META-INF” forlder and it worked. Any one got problem ?? please tell me why

NOT Work src/main/resource ---------------------META-INF -------------------------resources -----------------------------WEB-INFO ---------------------------------faces-config.xml

Work src/main/resource ---------------------META-INF -------------------------faces-config.xml -------------------------resources -----------------------------WEB-INFO

Read more comments on GitHub >

github_iconTop Results From Across the Web

Spring boot running fine, but not its Jar? - Stack Overflow
I've build this application using in-memory H2 database. If I run mvn spring-boot:run it starts Tomcat on port 8081 and I can use...
Read more >
Running a Spring Boot App with Maven vs an Executable Jar
In this tutorial, we'll explore the differences between starting a Spring Boot web application via the mvn spring-boot:run command and ...
Read more >
spring boot; using java -jar; not executing but no error ...
If you're using eclipse, run this maven command below to create a runnable jar file in Spring Boot to include all libraries: clean...
Read more >
19. Running your application - Spring
You can run a Spring Boot application from your IDE as a simple Java application, however, first you will need to import your...
Read more >
Spring Boot Reference Documentation
You should always ensure that you are running a supported version of Spring ... Boot to create Java applications that can be started...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found