Migrating: Ant -> Maven

Dear Maven gurus.

Lately I was thinking about migrating from ant to maven (+ transition to Java-8 update site). Unfortunately I am not maven expert and I have lots of problems.
Currently plugin is using old style for ImageJ1 plugins and Ant is used to build two targets (jar files):

  • ImageJ (which crate big jar file including all dependencies)
  • Fiji (it includes in final jar only those jars which are not shipped with Fiji directly like super-csv-2.4.0.jar and its further dependencies)

Yes, this is a little bit a mess especially caused by manual management of included/not included jar files. What is not so nice: it uses a few jars which are not available in maven like CMA-ES and that is a reason of putting that stuff into final plugin jar file.

I have a few questions how to go as smoothly as possible to have something working nicely:

What pom should I have?
I still would like to have plugin working with both - ImageJ and Fiji - so I guess that correct parent pom would be:

    <parent>
        <groupId>net.imagej</groupId>
        <artifactId>pom-imagej</artifactId>
        <version>15.7.1</version>
        <relativePath />
    </parent>

What version of parent pom should I use (having Java-8 in mind)? Especially to deal with problems like changing package name problem described HERE. What is a policy to choosing ‘right’ version of parent pom now and in future (when/basing on what it should be updated)?

How to deal with dependecies?
I have moved code around and created some initial pom.xml: MosaicSuite git

This pom.xml seems to work -> it compiles and test are passing. Unfortunately because of things described above I need to use maven-shade-plugin to bundle all in one big jar file (currently just for simplicity I take it all into jar). If this is not done I get of course NoClassDefFoundError. Should I have different build targets for ImageJ and FIji?
Is this problem with dependencies solveable or…?

Could you provide me with some hints how to deal with it? Should I be aware of something and/or maybe such transition is not recommended?
Well, my current goal is to have project mavenized as easily as possible and it is supposed to be one baby step in (hopefully) good direction. But of course if you have some suggestions to what next step should be please share!

Hi @krzysg,

I think there are 2 possible solutions for this topic.

  1. You build a large JAR file that contains all the needed dependencies. This is similar to your ant build and your first maven project does it this way. The main advantage is that you can choose a specific version of pom-imagej and stay at this one, as long as you like. Your JAR brings all the needed dependencies and you don’t have to care about changes introduced by newer versions of pom-imagej. The major drawback is the size of the JAR file, but about 5 MB is not that large.
  2. You can use the dependencies ImageJ/Fiji offers to you. If you use a library that is not shipped with ImageJ/Fiji the imagej-maven-plugin will copy it to your upload version of ImageJ. The size of your plugin decreases when you use a lot of libraries that are managed by ImageJ/Fiji. There are 2 drawbacks: Firstly you have to handle a lot more files with your update site. Secondly you have to check for compatibility if libraries are updated at the ImageJ update site.

I use the second approach for EFTEMj and it results in handling a lot of files at my update site, to make the plugin compatible with pure ImageJ (using the IO_ plugin to read dm3 files is the reason). Using the first approach updating the plugins update site would be much easier.

For the moment, you can depend on pom-fiji, since it manages the most versions for you automatically. Your ultimate goal is to deploy it on top of Fiji, so this makes sense.

In the future, everything will be consolidated into a single pom-scijava parent + BOM. There will be no more pom-imagej or pom-fiji. This will simplify matters for everyone, I hope. (However, discussion is still ongoing in this forum thread.)

Both now and in the future, the best policy is to depend on the newest possible version of the parent POM which works. (Sometimes, the very newest may reference versions that do not yet exist, due to “preemptive” version bumps. But after the switch to the consolidated pom-scijava, this should be the case far less often.)

I would strongly advise you not to use an uber-JAR at all and instead build only your artifact. Ship the libraries you need on your update site. If you need libraries which are not available in Maven Central, we can deploy them to the ImageJ Maven repository; just let me know… although I see you already have a MOSAIC Maven repository which you can use for that as well. You are welcome to use the ImageJ one though—that’s what it’s for. Using it instead of rolling your own saves you maintenance burden, and also avoids adding another repository dependency to the mix when building. (You are committing to that URL working not just today, but forever—otherwise you will break old builds in the future.)

Nope.

From your linked POM, it seems like you have a good structure. So I don’t understand the actual issue? Why exactly do you need an uber-JAR? Are you trying to support plain ImageJ 1.x? If so, I would discourage that—you are making your life much harder than it needs to be.

I would definitely recommend using Maven over Ant.

From your POM, it looks like you are basically already done. Can you describe more precisely the remaining issues?

2 Likes

Dear @ctrueden @m-entrup,

thank you for your explanations.

Regarding some questions from above: I think that my problems with delivering final jar are very connected to my misunderstanding of how dependency should be shipped/handled in ImageJ/Fiji plugins and my very short (like 1 week) experience with Maven is definitely not helpful here. That is a main reason behind creating uber-jar which seems to … solve what is unsolvable for me in other way.

Just for some real example let’s consider that I am not creating uber-jar and deliver just build artifact from maven. Please also remember that I would like to have update site that works for both ImageJ2 and Fiji users.

Let’s also say that I have two outside dependencies:

  • cmaes.jar - something very 3rd party which was not been so far put to any maven repository (I have added it to mosaic maven for now).
  • Skeletonize3D_.jar - which is not part of ImageJ2 clean install but delivered as a part of Fiji.

As far as I understood I should add them to jar directory and then add them to my update site. Well, in case of cmaes it seems reasonable but case of Skeletonize3D_.jar seems to be not so nice, or?

Of course, currently MosaicSuite has many more dependencies, but those above are showing possible … types of dependencies.
Having your input on those dependency stuff would be really helpful. Maybe there are no problems at all and I am creating artificial ones…

Yes, if you want it to work without the Fiji update site enabled, you have to upload both. There is currently no dependency mechanism between update sites (so you could declare “MosaicSuite requires Fiji”). As such, currently, there are many update sites that implicitly require the Fiji update site. There is also no way to say “I need Skeletonize3D_, but only install it from MosaicSuite if it wasn’t installed already from some other update site.”

You simply have to upload your own, known-to-work-with-MosaicSuite version of Skeletonize3D_, which will then fall out of date (unless you upload the updates yourself) with the version provided by Java-8 update site.

Some day, I want to modularize plugins so that they work more granularly, but that is a huge project for which there is currently no funding.

OK, now everything is much clearer for me - thanks!

1 Like