4

I have a Spring Boot project and I'm building the jar file with mvn clean build. I need to copy a folder and a file to the root of the jar, where META-INF is located. I tried maven-resources-plugin but I can't reach my goal.

For war files I used maven-war-plugin in the past but I can't find something similar for jars.

Can anybody give me an idea?

Thanks.

Cristian
  • 417
  • 1
  • 9
  • 18
  • Have you tried adding resources location to the build section of your POM? – Maaaatt Jul 17 '17 at 14:12
  • Could you elaborate on this? I don't understand exactly what you mean. – Cristian Jul 17 '17 at 14:23
  • You explained that you tried using maven-resources-plugin but you didn't specify what you did exactly. You can include resources in your jar using ... as explained in the [maven documentation](https://maven.apache.org/plugins/maven-resources-plugin/examples/include-exclude.html). – Maaaatt Jul 17 '17 at 14:53
  • I tried to include the resources with ... but it doesn't work if the resources should be included in the root path. I need something like https://stackoverflow.com/questions/38833373/maven-include-files-in-jars-meta-inf but next to META-INF not inside. Still looking for an answer and testing. Thanks. – Cristian Jul 18 '17 at 06:42
  • Adding my folder into the resources folder and building my project actually puts my folder at the root of my jar. Have you added your resources folder as a source folder on build path? When you extract your jar, where is located? For me, it gives me my package folder containing my classes, the META-INF folder and the one I added to resources. – Maaaatt Jul 18 '17 at 10:47

3 Answers3

2

I could manage to add files after the repackage goal of the spring-boot-maven-plugin using the maven-antrun-plugin and the Jar tool included in the JDK.

Updating a JAR File

The Jar tool provides a u option which you can use to update the contents of an existing JAR file by modifying its manifest or by adding files.

The basic command for adding files has this format:

jar uf jar-file input-file(s)

https://docs.oracle.com/javase/tutorial/deployment/jar/update.html

Using Maven-Antrun-Plugin

This command can be executed using the maven-antrun-plugin together with the exec task, which allows you to execute commands via Runtime.exec(..).

The entry may look like this:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>3.1.0</version>
    <executions>
        <execution>
            <phase>package</phase>
            <configuration>
                <target>
                    <exec executable="jar" vmlauncher="false">
                        <arg value="uf" />
                        <arg value="${project.build.directory}/myprogram.jar" />
                        <arg value="-C" />
                        <arg value="${project.build.directory}/classes" />
                        <arg value="org/company/app/Main.class" />
                    </exec>
                </target>
            </configuration>
            <goals>
                <goal>run</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Notice the -C option, which allows you to change the directory that should not be included in the jar.

https://maven.apache.org/plugins/maven-antrun-plugin/usage.html

https://ant.apache.org/manual/Tasks/exec.html

Using Exec-Maven-Plugin

Alternatively the exec-maven-plugin can be used which does not require Ant to be installed.

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <executions>
        <execution>
            <phase>package</phase>
            <goals><goal>exec</goal></goals>
            <configuration>
                <executable>jar</executable>
                <arguments>
                    <argument>uf</argument>
                    <argument>${project.build.directory}/myprogram.jar</argument>
                    <argument>-C</argument>
                    <argument>${project.build.directory}/classes</argument>
                    <argument>org/company/app/Main.class</argument>
                </arguments>
            </configuration>
        </execution>
    </executions>
</plugin>

The final structure may look like this:

myprogram.jar
|-BOOT-INF/..
|-META-INF/..
|-org/springframework/boot/loader/..
|-org/company/app/Main.class

That way you can add any additional files you want after the jar has been packaged.

benez
  • 1,856
  • 22
  • 28
0

could something like the following help?

See also maven-jar-plugin

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.0.2</version>
            <configuration>
                <includes>
                    <include>**/cdi/*</include>
                    <include>**/META-INF/*</include>
                    <include>*.properties</include>
                </includes>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>test-jar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
aschoerk
  • 3,333
  • 2
  • 15
  • 29
  • As far as I can see, the include and exclude sections for maven-jar-plugin are useful only to include or exclude classes from specific packages. – Cristian Jul 18 '17 at 06:41
  • Ah I see, I presume you want to copy from a place outside of your module src. I would have to check if a relative path can be used something like ../..//resources/global.properties The documentation states: "Note that the patterns need to be relative to the path specified for the plugin's classesDirectory parameter." – aschoerk Jul 18 '17 at 07:07
  • Indeed, I have a folder resources next to src and target, and I want to include it's contents in the root of the generated jar file, next to META-INF and BOOT-INF. – Cristian Jul 18 '17 at 07:12
  • why not parallel to src/main/java? That could be included this way, since that would be copied to the target directory. if you don't want the resources in other goals, you can exclude these there at will. – aschoerk Jul 18 '17 at 07:22
  • If I put those config files in src/main/resources, next to other resources, everything gets copied into /target/classes. From there they go to the jar file in BOOT-INF/classes. – Cristian Jul 18 '17 at 07:27
  • 1
    I suspect there is an additional plugin working. normally the jar-plugin should put everything from classes into the root of the jar-file. Sorry, you might need a spring-boot expert. Perhaps change your tags. – aschoerk Jul 18 '17 at 07:52
0

I resolved my problem by using the maven-assembly-plugin. I created an assembly zip which contains the application jar and some other resources. This solution is specific for applications which use AWS Elastic Beanstalk and need to implement the Procfile (http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/java-se-platform.html#java-se-procfile).

Cristian
  • 417
  • 1
  • 9
  • 18