Developing Jakarta Apps Via NSF File Server, Take 2

Sun Jun 21 15:18:48 EDT 2026

Just about a year ago today, I posted about some tinkering I was doing with the then-new support in the NSF File Server for live modifying the files in the virtual "WebContent" folder of an NSF.

Early Tinkering

With that post, I was going the route of developing a project with Maven and then SCP'ing up the build results. That worked for an initial push, but had some big caveats. For one, it took deploying the entire app with every change. The other, bigger problem was that it wouldn't delete files that were no longer part of the app, so old pages and classes would float around until you went in and deleted them.

If you're using a normal SFTP server, you would solve a lot of that with rsync (or could, until it started getting gunked up), but that would be a difficult thing to implement with the virtual filesystem I'm using in the server project.

I also looked a bit into using SSHFS via macFUSE, but hit some trouble where stored files would be truncated by a few bytes. It's possible that this has been fixed, and it could be worth another look, but it put me off of the idea.

File Providers

A couple weeks ago, I decided to look into it again, and found an interesting tack I hadn't thought about: apps using the Mac File Provider API, which is something designed for Dropbox-type apps. While a little indirect compared to mounting the SFTP endpoint via macFUSE, it actually has a nice advantage in that the files actually exist in the local filesystem, making it a bit more resilient to hiccups (hopefully).

There are a number of apps that do this. Panic's Transmit (my FTP client of choice for a long time) is adding this in version 6, but it seems like it's not quite solid yet. For now, I've been using Mountain Duck, which has been working really well. I may switch to Transmit when it settles, but I don't have any complaints about Mountain Duck so far.

Live Projects

Having these files sitting on the filesystem also made me think of another approach for working on the app: rather than building the project with Maven and then copying the build results up, I could work with it a bit more "live", similar to how Designer does it.

To do this, I've cobbled together a couple of old Eclipse techniques that I wouldn't normally use, but do the job here. I made just a plain old Java project in Eclipse and then dragged the root of the app from the now-filesystem-present app to the project to make a linked folder:

Screenshot of the process of linking a filesystem folder to a project in Eclipse

Then, in the project properties, I added a Source folder to the build path for the WEB-INF/src directory within the mapped WebContent folder ("Code/Java"-type Java files won't work with this share type, for reasons I may get in to later) and mapped its output to WEB-INF/classes:

Screenshot of the Java Build Path for my live-edit project

This added the Java source files from the NSF to my Eclipse project, but it had trouble building them: it had no idea about the project's dependencies. For the next step, I got a little hackier: I went to the "Project Natures" section of the project properties and explicitly added "Plug-in Development". As this page in the dialog warns you, you don't normally want to go about adding natures explicitly: other tools should normally do that for you. Here, though, it's fine.

Screenshot of Eclipse's Project Natures page

Then, I went into the app in Designer and copied the contents of the META-INF/MANIFEST.MF file from the Project Explorer pane and made a file at the top of my Eclipse project (which will not be synced to the NSF):

Screenshot of some of the project in Eclipse, showing MANIFEST.MF

With that in place, Eclipse will resolve dependencies from OSGi plugins in the same way as Designer does, so I just need to make sure they're in my Target Platform for the workspace.

While mucking around in there, I also enabled the Project Facets from the Web Tools Platform, though admittedly that doesn't buy me too much yet.

Anyway, with all this set, now I have a local Eclipse project that is a live representation of the project on the server (Designer on the left, Eclipse on the right):

Screenshot of Designer and Eclipse's views of the same NSF

What This Is Good For

For a specific type of app, this is wonderful. The main specific type of app that it's good for is what I'm using for this demonstration: apps like the new OpenNTF home app that are pureblood Jakarta applications. Other than a view or form here and there, pretty much all of the development of this app takes place in Java classes or WebContent resources like CSS, JS, and JSP. These files have natural filesystem representations and work perfectly when synced over SFTP.

I'm deriving a lot of benefits out of this. For one, I can use the Mac version of Eclipse, which is just inherently nicer than using a Windows app via RDP like I normally do (I could also use other tools, but I actually just like Eclipse). Additionally, unlike Designer, this is current Eclipse - specifically, the 2026-06 release that came out just this month. So, with this in place, I can work on a live NSF app the same way I do the various other Java projects I work on:

Screenshot of Eclipse working with an NSF-based web project

Beyond IDEs, this would also let me seamlessly use other tools like image editors or fancier CSS editors without any extra hurdles.

Even if you're not using JSP or JSF in NSFs, you could do this when writing Jakarta REST services and have a good experience. You could also presumably do this if you're writing REST services mounted in an XPage you make in Designer but then implemented in Java, but eh. It'd be better to switch to Jakarta REST in that case regardless.

This would also work pretty well if you're developing client JS apps or static HTML files, like a static blogging system. With complex JS projects, you'll probably want one of the toolchains that has browser integrations and auto-reload, but this still isn't bad and could be good if you want to write against live REST services.

Where This Falls Short

All that said, this is still a pretty limited-use tool. As I mentioned above, this is specifically for files in the WebContent virtual folder, and that rules out all of traditional Notes development and almost all XPages work. I've considered for a while making a filesystem type in the NSF File Server project that represents the rest of the NSF virtual filesystem in the way Designer does, but there are a lot of fiddly little details to doing that, particularly when also allowing for live editing of it. Just off the top of my head:

  • What happens when editing a DXL-type element like a view and you save invalid DXL? I guess there'd be an error, but how would that show up for the user across the SFTP client?
  • What about elements that are both file data and metadata, like image resources? I guess the .metadata file should be created automatically when missing, but it's weird to have "filesystem" operations with side effects.
  • Though presented similarly in Designer, Java in Code/Java is actually stored differently from custom source folders like WebContent/WEB-INF/src. While the latter are stored "filesystem-like" where the .java and .class files are separate notes, Code/Java notes store both the source and bytecode. This includes edge-case things like inner classes in separate class data items. This is not an insurmountable issue, but then that means that the server side starts to have to make all sorts of assumptions on the fly about incoming data beyond simple file operations.
  • XPages have those same problems and require executing proprietary code during the build process. While this is not an impossible task, it's a new hurdle on the client side that would need handling.

It'd be kind of neat if that was all implemented, but it'd be a lot of fiddly work to do and with really diminishing rewards. It'd just be more practical to use Nomad Designer for editing forms and views as needed for that part and then stick with normal Designer while you're still doing XPages. Never say never, I suppose.

New Comment