Showing posts for tag "sftp"

Developing Jakarta Apps Via NSF File Server

Wed Jun 25 16:42:37 EDT 2025

In my previous post, I made an offhanded comment towards the end about how the tool was really for static files and, while it'd be technically possible to deploy Java code this way, it'd be awkward and weird.

But that got me thinking: just how awkward and weird are we talking here? So I set out to trying to see. An app that is all-in on Jakarta EE is basically a normal old webapp housed in an NSF, and the structure of the "WebContent" directory is the same as a WAR: visible files go in the top level, JARs go in "WEB-INF/lib", and compiled classes go in "WEB-INF/classes". Normally, the Code/Java design notes in an NSF are those compiled class files, doing double duty to hold the source and the bytecode in the same note, but that's not the only way. If you have a file resource that calls itself "WEB-INF/classes/foo/Bar.class", it'll count as a class in the app. This is how the pre-8.5.3 method of adding Java classes worked: Designer would make one file resource for the source file and another for the bytecode.

Trying It Out

So, since a running app doesn't care about the source, in theory the presence of just the .class files in the right place should suffice for deploying an app. I decided to put the theory to the test and, lo and behold, it worked:

Screenshot of Java bytecode being uploaded via scp to an NSF and a REST service working

Those are the classes from the Jakarta EE starter project, which gives you a Maven project with a JAX-RS resource that emits JSON. The XPages JEE project creates an environment pretty comparable to a normal Jakarta EE server, so the compiled classes work just the same when copied around.

So far, so good, but what about a more-complicated example? A real app will have non-class Java resources (translation properties files, for example), web resource files (HTML, CSS, JS), and dependency JARs. So I added commonmark as a dependency to my project via Maven and built the project. I found that, with a Maven project, the entire structure of your result WAR is present in "target/your-artifact-id", and thus I switched to copying that up:

Screenshot of a more-complicated app in Eclipse uploaded to and running in Domino

This actually scratches an itch I've had for a long time: I've considered the notion of having a mode in the NSF ODP Tooling project that takes a WAR and makes an NSF out of it in this format. As it turns out, the result of that would be the same as this, and this allows for faster iteration on testing changes.

Some Caveats

One major limitation not so much of the tools but of the underlying protocol is that "recursive delete" isn't inherently a thing in SFTP, but it's necessary to make sure that any files from an old build not in new builds (renamed classes, etc.) are deleted when deploying a new version. Since rsync would take a lot of work, I've been looking at lftp, which may fill the gap, but it'll take some fiddling. Dedicated file-transfer GUI tools like Transmit could help too.

Additionally, while it's possible to create a compatible classpath in a Maven project by including the core JEE APIs and some Domino-specific things like the NoSQL driver as dependencies, this route wouldn't help you for things like creating or modifying views. Those don't change as frequently as app code, though, so it'd probably be fine to have Designer (or Nomad Designer) around for that task in much the same way as one might use a database management app in other environments.

It's also a longer cycle between making a change and seeing it than when using Designer, since you'd have to make sure to do a local build and then copy the files up, which will scale in time with the complexity of your project. That may be a fair price to pay to have your choice of IDEs and the ability to use Maven for dependencies and processing, though.

Anyway, this is all pretty neat. I've really gotten into a good groove of app dev with the JEE project lately, but I won't pretend I wouldn't mind a nicer development environment. I think I'll have to try using this for some of my projects for a bit to find out if it'll work in general.

Integrating VS Code (And Others) With Domino Via NSF File Server

Wed Jun 25 13:46:23 EDT 2025

Earlier today, Richard Moy posted a neat blog post on a mechanism his team developed to be able to work on HTML, CSS, and JS in Visual Studio Code and sync the results to an NSF, allowing them to use more-modern tools while still hosting in an NSF.

That got me thinking about the NSF File Server project and its support for storing files in "WebContent" in an NSF, and how I could write about how it could accomplish a similar thing. After testing it and finding a bug to fix with served MIME types, I uploaded 2.1.0 and now I'm ready to talk about it!

Quick Intro

The current form of the project came out a bit over a year ago, and I posted about the various new features. The important one for our needs is the ability to use the conceptual "WebContent" directory in the NSF to house static files. As a note, though this directory usually comes up in the context of XPages/Java development, it's not really tied to them - it's just another type of File Resource.

The way the project works is that it's an OSGi plugin and thus best deployed in an Update Site NSF referenced via notes.ini. There's also a config NSF to create - the NTF is in the distribution as "fileserverconfig.ntf" and should be created on the server as "fileserverconfig.nsf". This DB can be replicated around your domain, since all of the configuration options are or can be server-specific.

Once the NSF is in place, create a document in the "Server Configurations" view for your server to set the port it will listen on. Then, create a document in "Mounts" to point to the NSF you want to work with, giving it an appropriate name and putting the NSF path in "Data Source Path":

Screenshot of the Mount configuration document UI

You'll probably also want to tweak your Domino Directory NSF to add a text item named "sshPublicKey" to house, well, each user's SSH public key (the kind you get from ssh-keygen). In my environment, I added this (and a bunch of other stuff) to the "$PersonExtensibleSchema" subform as a multi-value text item:

Screenshot of an sshPublicKey item in names.nsf

You can also use password-based authentication, but you shouldn't.

Once it's all set, restart HTTP, since the server's lifetime is bound to HTTP.

Testing It Out

Before trying any fancier integration, it'll be a good idea to test using a simple SFTP client. The simplest is the sftp tool that comes with the SSH suite on basically every OS:

1
sftp -v -i ~/.ssh/id_rsa -P 9022 "CN=Jesse Gallagher/O=IKSG@your.domino.server"

The username should be something recognizable to Domino - I'm sure variations will work, but I like using the full DN by default to eliminate ambiguity.

Once connected, you should see your mounted DB as a folder. You should be able to cd into it and ls to list the contents. In a new NSF, you'll see the WEB-INF directory Designer creates, and you'll also see anything you put in there intentionally. If you have a local file, you can put foo.txt to try uploading and deleting it:

1
2
3
4
5
6
7
sftp> cd appexample
sftp> put license.txt
Uploading license.txt to /appexample/license.txt
license.txt                                                                            100%  589   184.5KB/s   00:00
sftp> rm license.txt
Removing /appexample/license.txt
sftp> 

If all is set up properly and you have Designer access to the NSF, you should be good to go.

Configuring VS Code

In my tinkering, I used the simply-named SFTP plugin for VS Code, which lets you configure a directory to sync automatically with a remote SFTP server. Following the examples, I configured my .vscode/sftp.json config file like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
    "name": "Your Server",
    "host": "your.domino.server",
    "protocol": "sftp",
    "port": 9022,
    "secure": true,
    "username": "CN=Jesse Gallagher/O=IKSG",
    "privateKeyPath": "/Users/jesse/.ssh/id_rsa",
    "remotePath": "/appexample",
    "uploadOnSave": true,
    "ignore": [".vscode", ".git", ".DS_Store"]
}

Once I did that (and re-opened the dir in VS Code to be safe, though I don't know if that was needed), things started syncing on save:

Screenshot of a file edited in VS Code visible in Designer

In that screenshot, you can see the files in WebContent using Designer's Project Explorer view, but that's entirely optional - at this point, you're free to uninstall Designer if you so desire, since VS Code will get the files in there itself thanks to the SFTP server. Your files will show up at URLs like https://your.domino.server/yourapp.nsf/baz.html.

Other Uses

Though I focused on VS Code as an example, there's nothing special about it for using the SFTP server. Since it's a generic protocol, you could also use any other IDE with similar support, or any other SFTP client that can do the syncing for you (rsync doesn't work currently, since it requires its own protocol tunneled over SSH). For example, you might have a CI/CD server like Jenkins do the SFTP for you at the end of a build, so you can see files automatically deployed to Domino. You can also use whatever the heck OS you want as long as it has an SFTP client.

What this won't do (right now) is any kind of non-static programmatic elements like forms, views, agents, or Java elements. I guess you could in theory compile Java locally and push the results to WEB-INF/classes and WEB-INF/lib, which should work, but that would be an odd way to develop. This is primarily of use for writing or deploying static files, either manually edited or as built by a (freaking) JS transpiler toolchain.

It'd also be possible to do much the same thing with other storage "backends". The "NSF File Store" built-in type, for example, uses data documents with the form and views in the "filestore.ntf" template, storing the file data as attachments. One could use that template directly or make compatible views in another app and use that for deployment without requiring giving anyone Designer access to an NSF. It'd also be possible to write an entirely-different storage mechanism, but that'd require the fiddly task of implementing the VFS in Java, so it'd be for dedicated developers only. I think the WebContent mode would do the job nicely in most cases regardless.

In any event, give it a shot! I think it's a neat tool and likely has a potential place in a lot of workflows.