2

been wrestling with this issue for a few days and would appreciate some guidance.

I am working with Spring Boot and am attempting to build my project into a jar that I can run. There are some nested dependencies (OpenCV) that require me to include them all together into the one Jar file.

Before I added these dependencies, I was able to successfully build a Jar file that worked just fine; it wasn't until I started trying to build a combined jar that things started to become an issue.

The problem I am facing is this: How do I successfully build a Jar file that includes all of the Spring files, nested dependencies, and my source code all into one fat Jar file?

Here is my POM file below with a few of the dependencies omitted.

<?xml version="1.0" encoding="UTF-8"?>
<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>com.myapp</groupId>
    <artifactId>mytestproject</artifactId>
    <packaging>jar</packaging>
    <!--Change the above to a war instead of jar if you need a war file-->
    <name>Spring OSGi Bundle</name>
    <version>0.1</version>
    <url>http://www.springframework.org/osgi</url>

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

    <properties>
        <spring.osgi.version>1.2.1</spring.osgi.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <java.version>1.8</java.version>
    </properties>

    <!-- ================================================ -->
    <!--            Repository Configuration              -->
    <!-- ================================================ -->

    <!-- Repos -->
    <repositories>

        <!-- Apache imaging https://commons.apache.org/proper/commons-imaging/index.html -->
        <repository>
            <id>apache.snapshots</id>
            <name>Apache Development Snapshot Repository</name>
            <url>https://repository.apache.org/content/repositories/snapshots/</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>


        <repository>
            <id>jitpack.io</id>
            <url>https://jitpack.io</url>
        </repository>

        <repository>
            <id>i21-s3-osgi-repo</id>
            <name>i21 osgi artifacts repo</name>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
            <url>http://maven.springframework.org/osgi</url>
        </repository>


        <repository>
            <id>com.springsource.repository.bundles.external</id>
            <name>SpringSource Enterprise Bundle Repository - External Bundle Releases</name>
            <url>http://repository.springsource.com/maven/bundles/external</url>
        </repository>

        <repository>
            <id>com.springsource.repository.bundles.release</id>
            <name>SpringSource Enterprise Bundle Repository - SpringSource Bundle Releases</name>
            <url>http://repository.springsource.com/maven/bundles/release</url>
        </repository>

        <repository>
            <id>com.springsource.repository.bundles.milestone</id>
            <name>SpringSource Enterprise Bundle Repository - SpringSource Milestone Releases</name>
            <url>http://repository.springsource.com/maven/bundles/milestone</url>
        </repository>


        <repository>
            <id>spring-release</id>
            <name>Spring Portfolio Release Repository</name>
            <url>http://maven.springframework.org/release</url>
        </repository>

        <repository>
            <id>eclipse-repository</id>
            <name>Eclipse Repository</name>
            <url>http://repo1.maven.org/eclipse/</url>
        </repository>

        <repository>
            <id>spring-ext</id>
            <name>Spring External Dependencies Repository</name>
            <url>
                https://springframework.svn.sourceforge.net/svnroot/springframework/repos/repo-ext/
            </url>
        </repository>
    </repositories>

    <!-- Plugin Repos -->
    <pluginRepositories>
        <pluginRepository>
            <id>maven-repo</id>
            <name>maven repo</name>
            <url>http://repo1.maven.org/maven2/</url>
        </pluginRepository>
        <pluginRepository>
            <id>com.springsource.repository.bundles.milestone</id>
            <name>SpringSource Enterprise Bundle Repository - SpringSource Milestone Releases</name>
            <url>http://repository.springsource.com/maven/bundles/milestone</url>
        </pluginRepository>
    </pluginRepositories>

    <!-- Dependencies -->
    <dependencies>

        <!-- Local Jar File for open.cv -->
        <dependency>
            <groupId>org.openpnp</groupId>
            <artifactId>opencv</artifactId>
            <scope>system</scope>
            <version>3.2.0</version>
            <systemPath>${basedir}/src/main/libs/opencv-320.jar</systemPath>
        </dependency>

        <!-- OSGI -->
        <dependency>
            <groupId>org.springframework.osgi</groupId>
            <artifactId>spring-osgi-test</artifactId>
            <version>${spring.osgi.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.osgi</groupId>
            <artifactId>spring-osgi-annotation</artifactId>
            <version>${spring.osgi.version}</version>
            <scope>test</scope>
        </dependency>




    </dependencies>

    <!-- Build Tag -->
    <build>
        <sourceDirectory>${basedir}/src/main/java</sourceDirectory>
        <resources>
            <!-- standard Maven folder -->
            <resource>
                <directory>src/main/resources</directory>
            </resource>
            <!-- plus root folder -->
            <resource>
                <directory>.</directory>
                <includes>
                    <include>plugin.xml</include>
                    <include>META-INF/*</include>
                </includes>
            </resource>
        </resources>


        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <!--<classifier>sources</classifier>-->
                    <!--<classifier>spring-boot</classifier>-->
                    <mainClass>com.myapp.internal.MainLauncher</mainClass>
                    <addResources>true</addResources>
                    <!--<executable>true</executable>-->
                </configuration>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <!--<phase>compile</phase>-->
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <!--<classpath>.</classpath>-->
                            <addClasspath>true</addClasspath>
                            <mainClass>com.myapp.internal.MainLauncher</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <!--<execution>-->
                        <!--<id>attach-sources</id>-->
                        <!--<phase>compile</phase>-->
                        <!--<goals>-->
                            <!--<goal>single</goal>-->
                        <!--</goals>-->
                    <!--</execution>-->
                    <execution>
                        <id>assemble-all</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

There are 3 different commands I am trying to compile with at the terminal in the Intellij IDE:

1) mvn clean package

2) mvn clean install

3) mvn clean compile assembly:single

Those 3 commands coupled with changing the commented code within the build tag always yields one of two results:

Either I get one large jar file which has everything in it except my source code is not in the base directory (it is located under the BOOT-INF directory and can't be found when ran) and I get the standard "Could not find MainLauncher" error whenever I run it using java -jar {MyJar}.jar.

or

I get 2 jar files where the "jar-with-dependencies" version has my source code as well as the other libs, but has none of the Spring libs in it.

Consequently, neither of these 2 jars work as I need some combination of both of them.

Things I have tried thus far:

1) Packaging spring sub-projects into one jar

2) No source jar attached with maven-assembly-plugin

3) Include spring xml in jar by maven-assembly-plugin packaging

4) How do I create an an executable jar in Spring Boot?

5) https://www.mkyong.com/maven/create-a-fat-jar-file-maven-assembly-plugin/

What am I missing in order to accomplish the goal of one jar file with my source, spring files, and nested dependencies?

PGMacDesign
  • 6,092
  • 8
  • 41
  • 78
  • Do u really need everything in your pom? And can u post a minimal, verifiable sample on github? – Indraneel Bende May 27 '18 at 14:31
  • I would prefer to be on the side of too much info than too little. May be something simple I mistook that others would easily see. – PGMacDesign May 27 '18 at 14:36
  • Can you replace your build section with org.springframework.boot spring-boot-maven-plugin – Indraneel Bende May 27 '18 at 14:45
  • and use the command mvn clean install – Indraneel Bende May 27 '18 at 14:48
  • Also remove the system scope from your dependencies. – dunni May 27 '18 at 14:52
  • @IndraneelBende Tested that and the built jar is just one with my classes and no nested dependencies. Crashes upon run as it is missing the openCV dependency. – PGMacDesign May 27 '18 at 19:50
  • @dunni That throws a compiler error that prevents me from using the lib at all and when I try to ignore it and run, compilation fails. – PGMacDesign May 27 '18 at 19:50
  • Then you have to install the dependency into your local Maven repository, so that Maven can resolve it as a regular dependency. System scope dependencies are not packaged by default, that's why they are not part of the resulting Spring Boot Jar – dunni May 27 '18 at 22:04
  • @dunni Your tip was helpful in that it dramatically increased the size of the jar, meaning I was absolutely not including the OpenCV jar, as you mentioned. Although it is now included in the jar, it is still missing my source code (though it can be found in the BOOT-INF --> classes --> {mypackage}, it just cannot be referenced). – PGMacDesign May 27 '18 at 22:55
  • Then it's exactly where spring boot needs it. Wait soon you mean with "cannot be referenced"? – dunni May 27 '18 at 23:15

1 Answers1

2

Ok, took quite a bit of research, but the short answer is, you cannot do what I had hoped you could with certain external libraries.

The longer explanation is this:

First, as per this answer, you need to remove the secondary gradle assembly dependency to have your POM file look like this:

<plugins>
    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <mainClass>com.myapp.internal.MainLauncher</mainClass>
            <addResources>true</addResources>
        </configuration>
        <executions>
            <execution>
                <goals>
                    <goal>repackage</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
</plugins>

Then make the build with this command:

mvn clean install

Second, as per this sample, you need to have the library (in my case, OpenCV) and the respective files located along your path / classpath. Here's the link on how to do that with Java.

Once those steps are complete, you can run your jar with the standard

java -jar YOUR_JAR_HERE.jar

and it should work correctly.

PGMacDesign
  • 6,092
  • 8
  • 41
  • 78