maven shaded jar: change output location

I'm having difficulty using the Maven Shade Plugin because I would like to have my shaded jar be installed to the same folder as the Parent pom (instead of the local src/target directory).

The layout: maven_project

guide/
   parent_pom.xml
projA/
   pom.xml
projB/
   pom.xml
   /target
      original-projB-0.0.3.jar
      projB-0.0.3.jar (shaded jar) 

I have to export the project and to make it easier for others to run the executable jar I want to relocate the shaded jar to the guide folder.

Unfortunately, I tried using

<outputDirectory>/home/name/Desktop/maven_project/guide/</outputDirectory>    

but this only moved the original-jar to the directory.

Question: Any ideas on how to move the shaded jar there instead (and even delete the original jar in the process)?

Answers


The Maven Shade Plugin by default replaces the original jar generated by the build and creates a copy of it prefixed with original.

Replacement and relocation can be configured via the outputDirectory, outputFile and finalName configuration entries.

Applying the configuration below:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <executions>
                <execution>
                    <id>default-jar</id>
                    <phase />
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.4.3</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <finalName>${project.artifactId}-${project.version}-something</finalName>
                        <outputDirectory>../guide</outputDirectory>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

We are:

  • Firstly disable the generation of the default jar, as requested by your requirements and specified by this dedicated SO Q/A
  • Then configuring the Shade Plugin to relocate its output to the upper guide folder (via relative path, better approach as also suggested by @Tunaki)
  • Also configuring the finalName element in order to disable replacement (which also affects relocation, in the sense that also the (prefixed) original jar will be relocated). As per official documentation the finalName is

    The name of the shaded artifactId. If you like to change the name of the native artifact, you may use the <build><finalName> setting. If this is set to something different than <build><finalName>, no file replacement will be performed, even if shadedArtifactAttached is being used.

As such, Maven will generate only the shaded jar at the configured location.


Another approach, would be to use the outputFile configuration entry, which specifies:

The path to the output file for the shaded artifact. When this parameter is set, the created archive will neither replace the project's main artifact nor will it be attached. Hence, this parameter causes the parameters finalName, shadedArtifactAttached, shadedClassifierName and createDependencyReducedPom to be ignored when used.

Hence you could change the configuration above to:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <executions>
                <execution>
                    <id>default-jar</id>
                    <phase />
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.4.3</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <outputFile>../guide/${project.artifactId}-${project.version}-shaded.jar</outputFile>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

And have exactly the same behavior.


Side note: you are really changing the behavior of the build here. If somebody builds only a single module, from the module folder itself, he/she would not find the expected content on the target folder, which would be on the parent one instead (a bit of a surprise).


Update Applying the configuration above and invoking only the Shade Plugin from the command line

mvn shade:shade

You will however have the following issue:

[INFO] --- maven-shade-plugin:2.4.3:shade (default-cli) @ test-addjar ---
[ERROR] The project main artifact does not exist. This could have the following
[ERROR] reasons:
[ERROR] - You have invoked the goal directly from the command line. This is not
[ERROR]   supported. Please add the goal to the default lifecycle via an
[ERROR]   <execution> element in your POM and use "mvn package" to have it run.
[ERROR] - You have bound the goal to a lifecycle phase before "package". Please
[ERROR]   remove this binding from your POM such that the goal will be run in
[ERROR]   the proper phase.
[ERROR] - You removed the configuration of the maven-jar-plugin that produces the main artifact.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------

Need Your Help

how to insert a auto reload in potomak/jquery-instagram

jquery instagram

I'm trying to build something out of potomak's jquery-instagram js code and I'm using it as is.. here is the code:

How to detect whether a character belongs to a Right To Left language?

c# localization right-to-left bidi

What is a good way to tell whether a string contains text in a Right To Left language.