Using Target Files for Maven Dependencies in Eclipse and Tycho
Tue Nov 03 16:13:12 EST 2026
Over the years, one of my big bugbears when dealing with building Domino-targeting projects has been wrangling the OSGi dependencies in a way that is usable in both Maven+Tycho and Eclipse. I first posted about this over a decade ago and realistically the techniques I've used haven't changed much since then. I eventually settled on the p2-maven-plugin route to make a pool of customized dependencies and talked about it in the context of the XPages JEE project, but it's otherwise not changed much. It's been a combination of using the generate-domino-update-site project to make a pool of the proprietary Domino/XPages bundles and then p2-maven-plugin to build a pool for the open-source ones that are either already OSGi-friendly or need some tweaking.
The Change
In the intervening years, though, a couple things have improved. The core improvement is that .target files (one of the mechanisms that Tycho and Eclipse can use to gather the dependencies) have gained the ability not just to include Maven dependencies, but also to customize those dependencies on the fly, even if they already contain OSGi metadata in their MANIFEST.MF. This is exactly the work I've been doing with the p2-maven-plguin, but the .target files don't require a separate project or manual Maven execution to build the pool. And, crucially, Eclipse-the-IDE supports this too.
This appears to be an effect of a general rapprochement between Eclipse PDE and bndtools happening over the last few years. Tycho is essentially an implementation of Eclipse's Plug-in Development Environment (PDE) in Maven, and it's always hewed most closely to the peculiar way Domino uses OSGi. It's always been something of a manual approach to taking care of your MANIFEST.MF and related elements. bndtools, on the other hand, has always been a bit more free-wheeling in its way, and does more programmatic generation of OSGi metadata than PDE. This works well when your code targets OSGi as an incidental effect or if you're targeting a modern OSGi stack, but has always hit problems with Domino and its pool of proprietary dependencies.
In Practice
With this new tool in hand, I set out at converting the XPages JEE project to use this, and I was met with some success. There are a few tradeoffs, but the result is distinctly better. Instead of the previous xsp-deps stub Maven project, the definitions are now done in xsp-jakartaee.target in the project tree. There's a lot going on here that's similar to the work the previous one did but now done via bnd's Properties-based format instead of an XML encapsulation of it. There's still a lot in there that does some teacup-balancing to make sure that everything resolves correctly on Domino and (hopefully) doesn't conflict, and that's not going to go away any time soon.
The big difference is that this file is natively understood by the entire toolchain now. Previously, I'd configure Tycho and Eclipse to point at the output directory of the update site build, but that was just an incidental result of p2-maven-plugin's work. Now, Tycho+bnd do the work of caching the customized version based on the configuration in my Maven repo, and neither one needs to be told about the specifics. Ignoring the red markers from my dev environment, you can see it resolving both cleanly pre-packaged bundles plus the ones I have to manually tweak to work on Domino:
The Caveats
There are a few tradeoff to this approach compared to my previous one, though not enough to make it not worthwhile.
For one, I quickly ran into the problem described here, where the build failed with an "Invalid Collect Request" because many of the OSGi dependencies from Domino contain slashes in the names of embedded JARs (for example, com.ibm.designer.lib.jsf puts its JSF implementation and related libraries under "lib" in the JAR). As described in the typically-verbose LLM-vomit issue, this can be worked around by adding -Dmaven.resolver.validation=MILD to the project's .mvn/maven.config file. I don't love doing that, but it does work, so it's in there for now. I see a bunch of activity on that issue in the past week, so maybe it'll be fixed in a future Tycho release.
Additionally, the .target file is pickier about having a fully-complete world at build time than an already-built site on the filesystem is. Fortunately, I was able to resolve this by just adding a couple more dependencies from Eclipse and Maven and all is well. There's a mechanism in the .target file to automatically include either direct or all transitive dependencies, but I found that to be more hassle than manually adding the required ones.
Another big one is that .target files, unlike a Maven pom, don't seem to have a mechanism to inject per-file variables for re-use or to override their defaults. Several of the upstream dependencies of the XPages JEE project (in particular Weld, RESTEasy, and JNoSQL) consist of a fair few related dependencies that all share the same version number. Previously, I had a properties block to define these in the pom.xml, like:
1 2 3 4 5 | <properties> <weld-version>6.0.4.Final</weld-version> <resteasy-version>7.0.4.Final</resteasy-version> <nosql-version>1.1.17</nosql-version> </properties> |
Without that, it means that each Maven dependency entry has to include the version independently. It's possible that I could externalize this when building via Maven, but I don't think that would work smoothly with Eclipse, and thus I'd lose half the benefit. As I'll get into later, though, this is mitigated a bit by other benefits.
Finally, the defaults for generating bundles non-OSGi Maven dependencies aren't quite the same as what p2-maven-plugin did. In particular, the generated bundle names changed - for example, the SmallRye OpenAPI Model bundle used to end up named io.smallrye.open-api-model but is now wrapped.io.smallrye.smallrye-open-api-model. That's a bit uglier and I could in theory add special instructions for each changed one, but I decided to just go with the flow. Neither one is truly "correct" anyway, and so I just switched the places I referenced them. This also provided a good opportunity for me to switch some places where I used Require-Bundle to name a dependency to use Import-Package instead, which is good practice when you can do it.
The Benefits
Overall, the big benefit is the tool compatibility. Now that Tycho and Eclipse both use a fully-supported native mechanism, it takes away one of the bits of weirdness I had to do, and Eclipse is all the happier for it.
It's also faster to build, thanks to the better caching being done within the Maven repository. Happier tools, happier builds, all nice all around.
Additionally, while I do still miss having variables to define versions, I got a huge benefit in exchange. The process for searching for updated versions of my dependencies has always been tedious, generally involving me doing to search.maven.org and looking for each in turn. While I'm sure I could have improved my process a bit, there was always a significant amount of inherent hassle due to the required customizations.
Now, since I'm working more smoothly with the existing tools, I can use technology to help. The tycho-version-bump-plugin has an update-target goal that does just what it says on the tin. It looks through your .target file and checks either the upstream p2 repositories or Maven Central for new versions. With a bit of configuration to veer it away from various permutations of "beta", I can run that command (optionally saying -DallowMajorUpdated=false) and it'll update everything for me. There's still a bunch of work involved, since not even every point update is safe either due to weird packaging on Domino or outright behavioral changes, but this saves a ton of hassle.
I also took the opportunity to convert the XPages dependency target to the same type of file. This file uses the API-only XPages build stubs I've been maintaining to allow for building XPages/Domino-targeted projects without actually needing the proprietary implementation (since compilation doesn't actually execute the code). Now, both parts of the target are cleanly defined in tool-friendly files, and that also sped up the automatic builds from GitHub Actions.
And, in general, it led to a fun flurry of activity to improve the project's OSGi and Maven use. I cleaned up a bunch of now-redundant configuration, switch to pomless builds for the bundles and features, cleaned up unused Import-Package and Require-Bundle dependencies, and generally did some mid-autumn spring cleaning. I also did some experimenting with Declarative Services and other non-ancient OSGi capabilities, though those haven't borne useful fruit yet.
If you're maintaining Tycho-based projects, I definitely recommend looking into these sorts of improvements. It's finally done away with at least some of the more-annoying aspects of working with PDE-type projects like this.