Domino and Jar Files
Those of us who have been working with Domino and Java for some time know that one of the big strengths over LotusScript is the host of standard Java libraries that can be utilised. If you want better string or number handling etc, you have Apache Commons libraries. If you want Excel export, you have Apache POI. If you want conversion from JSON to Java objects, there’s Jackson. And there are a host of others.
But how you use them is slightly less straightforward. In many Java application development environments a build management tool like Maven or Gradle is used. This has the benefit of downloading not only the relevant jar file but all relevant dependencies. That then requires two options for deployment and running. With something like Vert.x or Spring Boot, if the host for the application also has the relevant software, it’s possible to retrieve the dependencies at runtime. This is what is typically done when developing Java applications via an embedded web server. The other approach in Vert.x or Spring Boot is to package the application as a “fat jar” – the application plus all dependencies packaged at compile time into a single jar or war file. The application is a single discrete file, but could include dependencies that are also included in other applications, hence the term “fat jar”.
OSGi, the basis of XPages, works differently. The approach, popular with large enterprise systems, is intended to minimise the duplication by defining dependencies and relying on the administrator of the relevant server to ensure the plugins an application is dependent upon have been added. The downside is that dependencies could be nested at various levels and conflicts could occur if jar files are embedded in multiple plugins, particularly if they are exposed in the wrong manner. As you start adding more and more OSGi plugins – particularly custom ones – the risk of conflicts increases.
But it means dependencies should not occur more times than necessary.
This became more apparent recently when I happened to look at the temp folders on a server. Typically I’ve included Apache Commons Lang and others within an NSF. This can be done by using the Jar design element or manually by adding them to a folder (e.g. WebContent\WEB-INF\lib), right-clicking them and adding them to the build path. But this is what happens when you do either of those:
The four timed 12:58 are the jar files from a single NSF. The four timed 12:59 are the same jar files in a different NSF. The one timed 13:00 is a Jar design element from a third NSF. The code that’s running doesn’t necessarily use them. Indeed, for the Jar resource I just added it to the NSF and previewed a blank XPage in the application.
This may seem alarming, but when you think about it, there is no alternative. An NSF is a single file. The jar file is a file resource within that NSF. So obviously it needs to be detached to the file system in order for the server to use it. I’ve heard questions about why Domino doesn’t allow Maven to incorporate jar files and their dependencies in an NSF, but that would still require the jar files to be stored somewhere temporarily.
This highlights also the importance of admins ensuring temp drives are appropriately sized. Restricting them to the minimum could impact things, even if the server’s xsp properties are set to ensure XPages temporary file uploads, persistence files and component trees are stored on a separate drive.
Obviously, OSGi avoids the need for this completely. So it highlights further the benefits of packages jar files into an XPages extension library (a.k.a. OSGi plugin). That’s what I’ve done for a recent plugin but there are ways to leverage Maven as well, to minimise manual steps and avoid missing dependencies. And its standardisation is to be lauded, as I’ll show in an upcoming blog post.
One final comment on Java agents. It’s possible to add jar files to a Script Library or Java agent. But similarly those need detaching – both at design time and run time. Just to reinforce that, next time you open a Java agent, look at the Package Explorer in Domino Designer. You’ll see a separate Java project is created on-the-fly with the relevant hierarchy within it. Recommendations from developers tend to be to put any jar files on the server in the jvn/lib/ext folder. If you search, there are a couple of technotes for memory leaks when the jar files are detached at runtime and not fully cleaned up. Whether or not they’re fully resolved I don’t know, most Java developers avoid adding jar files to an agent so it’s probably not widely used in order to tell.
For all of this, the nirvana for Java developers is to have a scheduled process that can be coded in Java re-using code already developed for XPages without the need for reduplication. Whether you use agents or DOTS, there’s still a need for duplication (DOTS uses OSGi, but from a different folder, and if you code youor shared logic in a plugin then you will need to restart HTTP before seeing any change as well as importing the plugin into Design to use any new methods from Java in the NSF, so that’s not ideal either). There’s no easy answer, if you’re coding Java in an NSF, and I’ve wrestled with it for some time. We’ll see if cleverer minds than me can come up with a solution in the future.