How to create a fat Plugin.jar with Maven that includes dependencies.

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

How to create a fat Plugin.jar with Maven that includes dependencies.

Michael P Ellis
I am trying to create an ImageJ (1) plugin with maven. There is a dependency (log4J) and I am using the maven maven-shade-plugin to create a plugin with the intention that the plugin will be self-contained and include the necessary dependencies.

So far I have found that when this plugin is installed into a standard ImageJ installation and run from the command line (OS-X) with java -jar in,jar it fails with an error message indicating that it has been unable to locate the log4j libraries.

Manually installing copes of the log4j libraries in the ImageJ plugins/jar directory allows the plugin to run successfully and I get to see the log output on the terminal/

        I have created a SSCCE to demonstrate which can be seen here: https://gitlab.com/Michael51773/minimalimagejplugin (https://gitlab.com/Michael51773/minimalimagejplugin)

        I am not that experienced with maven so if the solution is maven related please assume I have the experience of a small child!

The ultimate use scenario will include a multitude of dependencies and not just the log4j.

I hope to release some of the plugins I am using for general public use and to be free of charge (so hope to put something back into the community)

Many thanks in anticipation of any help.

        --- MinimalImageJPlugin_.jar ---
import ij.IJ;
import ij.plugin.PlugIn;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class MinimalImageJPlugin_ implements PlugIn {
 private static final Logger LOGGER = LogManager.getLogger();

 @Override
 public void run(String arg) {
 LOGGER.error("Hello");
 IJ.showMessage(String.format("MinimalImageJPlugin_ arg="%s"", arg));
 }
}

        --- pom.xml ---
<?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>biz.dsuk</groupId>
 <artifactId>MinimalImageJPlugin__</artifactId>
 <version>1.0-SNAPSHOT</version>
 <packaging>jar</packaging>
 <name>MinimalImageJ</name>
 <description>A minimal ImageJ PlugIn build with a maven with a dependency
on log4j to work out how to build a fat or uber jar that includes the
log4j jar dependency and can still be used as an ImageJ Plugin.</description>

 <properties>
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 <maven.compiler.source>14</maven.compiler.source>
 <maven.compiler.target>14</maven.compiler.target>
 </properties>
 <dependencies>
 <dependency>
 <groupId>net.imagej</groupId>
 <artifactId>ij</artifactId>
 <version>1.53e (DS)</version>
 </dependency>

 <dependency>
 <groupId>org.apache.logging.log4j</groupId>
 <artifactId>log4j-api</artifactId>
 <version>2.13.3</version>
 <scope>compile</scope>
 <type>jar</type>
 </dependency>
 <dependency>
 <groupId>org.apache.logging.log4j</groupId>
 <artifactId>log4j-core</artifactId>
 <version>2.13.3</version>
 <scope>compile</scope>
 <type>jar</type>
 </dependency>
 </dependencies>
 <build>
 <finalName>SC4_</finalName>
 <plugins>
 <plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-shade-plugin</artifactId>
 <!-- see https://github.com/AdoptOpenJDK/openjdk-installer/issues/93 -->
 <version>3.2.4</version>
 <executions>
 <execution>
 <phase>package</phase>
 <goals>
 <goal>shade</goal>
 </goals>
 <configuration>
 <artifactSet>
 <excludes>
 <exclude>net.imagej:ij</exclude>
 </excludes>
 </artifactSet>
 </configuration>
 </execution>
 </executions>
 </plugin>
 </plugins>
 </build>
</project>

--- END ---

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: How to create a fat Plugin.jar with Maven that includes dependencies.

Kenneth R Sloan-2
This is partly an answer to a specific post - and partly a request for guidance on current best practices when developing a  collection of ImageJ plugins with shared code.  I apologize for hijacking the thread.

I have similar issues - with a few twists.  I also have an experimental observation that *might* complicate matters.

First, I'm using 'ant'.  This was set up years and years ago by my students, and I have never come fully up to speed.  But, I use the same template to maintain many (>20) plugins.  Some of these are relatively ephemeral, some have been used for over a decade.  Switching to maven would be a significant effort.  But...I will probably start building a new collection of plugins at the start of the new year and am willing to consider setting this up with 'maven'

My original goal was to make each .jar file completely independent of the others.  This worked for awhile, but caused some duplication of source code.  As I restructured things - breaking out common chunks of code - it became obvious that this was no longer feasible.  So, I have created at least one (distributed), with more on the way, separate .jar files containing support, library methods.  This has not been too painful.

I do not understand how to maintain dependencies.  The ImageJ Update Site mechanism appears to invent dependencies.  I see no way to edit these - except that occasionally I will be offered the opportunity to "break this dependency" - which I always do!

BUT...and this is a big "but"...I have noticed that including common code in multiple .jar files does not seem to do what I want in ImageJ.  [note: this is an excellent reason to create separate library .jar files].  The symptom I see is:

==============================================
When a method "foo()" appears in more than one .jar file (that is, as part of an independent .jar file containing all necessary support methods), ImageJ appears to use only the FIRST one installed.

When you do things perfectly and update *all* of the "independent" .jar files, this is not an issue. ImageJ (and the ImageJ Update Site) appears to identify a "dependency" for the FIRST .jar file containing the duplicated methods.  This means that the "independent" .jar files are no longer "independent".  In particular, if you (mistakenly) update ONE version of "foo()" and install it - the update will not be effective unless you uninstall all other .jar files mentioning "foo()".  Instead, your new, updated .jar file will (silently!) use the version of "foo()" contained in the FIRST .jar file installed.  [imagine how long it took me to discover this!]
==============================================

This may be the death-knell for your goal of producing truly independent .jar files for multiple plugins which rely on identically named methods.

Now - I freely admit that I know nothing about 'maven' and precious little about 'ant' or ImageJ Update Site details or the finer points of how ImageJ resolves name conflicts.  I would welcome a comprehensive guide (esp to the ImageJ Update Site mechanics).

My most pressing need is a simple way to maintain and edit "dependencies" created and enforced by the ImageJ Update Site mechanism.  Right now, I just wait until an update produces a complaint, at which point I *always* "break the dependency".

Second on my wish list is a comprehensive guide to "building a collection of ImageJ plugins with shared libraries, using maven" which starts from ground zero.  I'm an old dog, but I've been known to learn a new trick every once in awhile.  It feels like it's time.  Oh, yeah...I have (but do not use) a github account, if that helps.  My development environment is all Mac.  My development tools are:

        EMACS - to write
        command-line - to compile, etc.
        web browser - to read documentation and APIs

In other words - no IDE.  Right now, changing that is a non-starter.

All help gratefully accepted.

--
Kenneth Sloan
[hidden email]
Vision is the art of seeing what is invisible to others.

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html