javamavenspring-bootintellij-ideajar

Spring Boot Jar created. Runs but fails `DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class` IntelliJ



The question has been edited, look ahead for the Updated sections and all the different ways I approached it in order to find a solution.


Initial question

I tried to create an executable jar file for my project but I run to the error when trying to run it no main manifest attribute, in kerkinibackend.jar.

The project is a Spring Boot application and I am using IntelliJ as an IDE.

I tried to find the most common scenarios when this could happen from similar questions but I couldn't make it work any way.

The steps I took were :

  1. Opened IntelliJ.
  2. Opened the project's Structure on the top right icon.
  3. Navigated to the Artifact.
  4. Pressed the plus to add new artifact.
  5. JAR -> from modules with dependencies. (also tried it using the blank option while having a MANIFEST.MF file, which was automatically generated from the first time I tried it).
  6. Opened the folder for the Main class in the pop-up dialog and specified it. (also tried leaving the Main class empty as I read somewhere and left it connect with it through the Manifest).
  7. Left the rest as default. (this way IntelliJ also creates the needed Manifest, in case you have it already deleting the file will allow to generate it again)
  8. Then, I pressed Build -> Build Artifacts -> Build.
  9. The is created with a size of 57Mbs. I tried running it as an executable but I saw it wasn't working. Then I opened the cmd and ran java -jar kerkinibackend.jar and then the error message comes out. The thing is that the MANIFEST.MF file is actually getting created in src/main/java/META-INF
Manifest-Version: 1.0
Main-Class: com.teicm.kerkinibackend.KerkinibackendApplication

I also do have the needed dependency in pom.xml

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>





UPDATE

I fixed the problem by changing the default generation of the manifest to be in the resources instead.

Now it the Jar runs but then I get and error from Spring No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.









Farther UPDATE

I tried to add an extra file the spring.factories (as a read in another answer Relevant question-answer) inside the META-INF folder in the resource folder in order to fix the previous problem. Now it didn't show the same error but a different one

00:24:26.230 [main] ERROR org.springframework.boot.SpringApplication - Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class
        at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:767)
        at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:218)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1308)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1154)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
        at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:391)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1288)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1127)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
        at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1083)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:853)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
        at com.teicm.kerkinibackend.KerkinibackendApplication.main(KerkinibackendApplication.java:11)

But I don't know if this brings me a step closer or a step farther. And why wouldn't the MySQL data source be recognized. When I use the project locally everything works, it connects to MySQL, it has communication with the front end.





Trying a different build method using maven-assembly-plugin

I also tried using a different way to build the executable jar, through @Zsolt Tolvarys approach (you can find more about it at link). This approach uses in the pom.xml another plugin called maven-assembly-plugin.

Unfortunately doing the suggested steps does generate a jar file but when I try to run the generated jar that exists now in the /target folder, then I get an error message of Error: Could not find or load main class com.teicm.kerkinibackend.KerkinibackendApplication having changed of course in the plugin the name of the Main class :

    <build>
        <plugins>
            <plugin>
                    <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <finalName>KerkiniBackEnd</finalName>
                    <appendAssemblyId>false</appendAssemblyId>
                    <archive>
                        <manifest>
                            <mainClass>com.teicm.kerkinibackend.KerkinibackendApplication</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>





For anyone having some spare time feel free to suggest me a solution or even try it him-her self. I really need to generate it, it's the last part of finishing my thesis...

The link for the Github repository is Github Repository

Thank you for your time and effort


Solution

  • The answer given above by @khmarbaise is correct and is the essential key to getting your Spring Boot bootable jar created successfully.

    I'm responding only to offer additional information to hopefully further clarify some key related things for you. (I would have put this in comments, but since this is my first publication to SO, I have 0 of the 50 reputation points required to post comments - on the other hand I'm free to post answers - a "boot-up" issue of my own :-)

    First, the initial IntelliJ steps you listed aren't necessary. Nor is the usage of the assembly plugin (a little more on that below).

    As long as you have the spring-boot-maven-plugin defined in your pom.xml (assuming you also have the target "packaging" defined as "jar" - both of which you already do), then Maven's interaction with Spring will result in a bootable jar file when running the Maven package command: mvn clean package

    As @khmarbaise also noted, for the moment you need to instruct Maven to skip test execution since your tests are failing, which will prevent the "packaging" of your bootable jar from completing successfully: mvn clean package -DskipTests

    By the way, IntelliJ includes a convenient Maven "tool window" which allows you to run Maven commands like these from the IDE. If it isn't showing go to View -> Tool Windows and select "Maven."

    Spring Boot applications themselves are "assembled" as "main method" jar files. This is why trying to build a Spring Boot app/jar with the maven-assembly-plugin doesn't make sense (or work, since Spring Boot creates a different internal structure inside the jar which Spring Boot requires to run).

    If packaging completes successfully you should see the following pair of jar files underneath your "compiler output" directory (this is usually located at [PROJECT_ROOT_DIR]/target):

    kerkinibackend-0.0.1-SNAPSHOT.jar
    kerkinibackend-0.0.1-SNAPSHOT.jar.original
    

    Peeking into the MANIFEST.MF file of kerkinibackend-0.0.1-SNAPSHOT.jar you'll see a couple key entries:

    Main-Class: org.springframework.boot.loader.JarLauncher
    Start-Class: com.teicm.kerkinibackend.KerkinibackendApplication
    
    

    How this works: When the JVM is invoked with the -jar flag, it will search MANIFEST.MF for the Main-Class entry. In this case it will find Spring's JarLauncher class as the class whose main method it should invoke to launch the app. JarLauncher will then in turn look for the manifest's Start-Class entry, which has been populated with the fully qualified path to your @SpringBootApplication class: (com.teicm.kerkinibackend.KerkinibackendApplication) and will in turn eventually call main on KerkinibackendApplication:

        public static void main(String[] args) {
            SpringApplication.run(KerkinibackendApplication.class, args);
        }
    

    Hope this information helps clarify some things. If not, let me know. Good luck and congrats on being (almost) done with your thesis!