New Release: XPages Jakarta EE 3.4.0

Sat Jun 07 14:57:04 EDT 2025

Tags: jakartaee

Today, I published version 3.4.0 of the XPages JEE project. In addition to the usual spate of bug fixes and refinements, this release brings two significant features: a bump to Jakarta EE 11 (mostly) and a new type of pure Jakarta app within an NSF.

Jakarta EE 11

Jakarta EE 11 has been in the works for a good while but is now mostly released. There remain a few components that are slotting into place, and some of the implementations remain in beta form, but they're in a reasonable state to put into a release. I like to keep this project up to date, and there are some nice improvements in here.

  • It officially adds Jakarta Data as a spec, though we've had that in the project for a good while now
  • CDI has a bunch of cleanup changes and now lets you organize producers by @Priority, which can be handy in some cases
  • Faces also has a handful of improvements, cleaning up the API a bit and making events more consistent
  • Pages (which remains my HTML generation tool of choice in new apps) got some long-needed cleanup
  • REST gained some new methods for working with headers and processing matched resources
  • Expression Language gained proper support for records and Optional (though the latter is off by default in the spec, it's enabled in this project)
  • Servlet gained some methods to work with Charset and ByteBuffer objects, which I've shimmed into the older ones Domino internally supports
  • MVC made a few good but breaking changes, removing support for Facelets (Jakarta Faces pages) as a view type and making CSRF enabled by default
  • Concurrency has some nice new features, though unfortunately the currently-released implementation doesn't yet support the nifty @Asynchronous annotation. That should come in the future, though

To go with these improvements, I put in a handful of refinements:

  • There's a new @DocumentConfig annotation you can use with NoSQL @Entity-annotated classes to declare what the actual form name should be. This is useful for cases where you have entities in the same app representing documents in different databases that happen to use the same form
  • There's a new org.openntf.xsp.jakarta.el.ext.ELResolverProvider ServiceLoader interface to customize handling of Expression Language resolution per-app
  • MicroProfile Metrics is gone, as it was removed upstream. In a future version, I plan to implement MP Telemetry, which is more flexible and has integrations with more services

Jakarta Modules

The largest feature addition, though, is what I've deemed "Jakarta Modules". The "module" term here is in reference to ComponentModule, the system Domino's HTTP stack uses to manage individual applications at the Java level. I've talked about this before, and the idea here is that a Jakarta Module is a peer to NSFComponentModule (the way NSFs are normally run with XPages) and OSGi*Module (the way Equinox Servlets and OSGI WebContainer apps are run).

These app types still use an NSF and you develop them the same way using Designer, but there are some key differences:

  • The entire application is treated like a "normal" Jakarta web app, which means that it has fewer old-to-new shims and workarounds
  • These apps are configured with a new database - jakartaconfig.nsf - that allows you to specify a web path to reference an NSF. So, for example, you configure "/someapp" to read its data from "/apps/someapp.nsf", and then all URL references will be "/someapp/your/app/url". This means that the URLs don't include ".nsf" and don't require having "xsp" somewhere in there like they do with traditional apps. This also means you can configure REST to use the app root as its own root, which is particularly useful when using MVC
  • XPages and legacy design elements like forms and views are not supported for web access. While you can still freely use views programmatically, they aren't accessible by URL within the module's space. Web-friendly elements like file resources, style sheets, and images work as they do with traditional apps
  • These apps are initialized at HTTP start, which means you can reliably use things like ServletContextListener and CDI beans with methods like void init(@Observes Startup) to do app pre-load. CDI beans like that will have a NoSQL context running as the DB signer, so you can use those to load configuration data from the NSF, for example
  • The ability to hook into HTTP init also means you can use ManagedScheduledExecutorService for a predictable replacement for scheduled agents that run entirely in your app space
  • This also allows reliable use of HttpSessionListeners and ServletRequestListeners, which don't quite have proper hooks in XPages apps

It's possible to develop an application that will work in both "modes", and that's how I've written the test cases for this: I made it so that the non-XPages tests for most features will now access the NSF both in the traditional way and in this new way. Doing this means avoiding XPages-specific classes like ExtLibUtil and NotesContext, and I have some documentation that covers a few of the aspects for writing "portable" apps. In general, though, I imagine it'll be the case that you'll want to pick one type and go with it, since there's no particular reason to access the app both ways.

Since this feature is a complex undertaking, it's more likely than average to contain bugs, so I'd appreciate as much testing as possible. I plan to move a couple apps over to this format - I decided to bite the bullet for Magpie's sake, since I wanted scheduled tasks, but I also plan to dogfood it with other things I work on. I also expect I'll have some followup blog posts about it, as I had to solve a number of interesting technical problems to get it to this point.

Future Enhancements

With this one in the bag, I have some plans for future versions. For one, I've been lining up desired features for Jakarta Modules, but beyond that I'll want to bump the remaining JEE 11 laggards when their implementations are out, and there's the aforementioned MicroProfile Telemetry. I'd also at some point like to give the same Jakarta Module treatment to more-traditional webapps, potentially attaching a WAR file in jakartaconfig.nsf and using that. I imagine most of the code would be shared between the two - a lot of the NSF-specific code is encapsulated in a few classes, while all the app-lifecycle bits are independent of the actual storage of classes and resources. That'd be a fun one to do.

New Comment