File uploads to Domino servlets (with an Angular demo)

(Updated: add required java security policy changes)

For one of my customers I’ve started working on an application that uses AngularJS for the frontend that talks to a REST API served by IBM Domino. For the REST API we decided use servlets: something that’s covered in great detail on Ed McCormick’s excellent blog. If you haven’t used servlets in a Domino database yet, go read some of his posts on this topic. Make sure you also take a look at the demo application he created containing examples of using servlets for a REST API.

One of the functions in the app (and probably in almost every app you’re going to work on too) is uploading files. Since I couldn’t find any info on how to do that with a servlet running on Domino, I decided to figure it out myself.

In case you’re only here for the code: download the demo app here. The GitHub repo is here.

Screenshot 2015-06-24 10.45.23

The demo shows how you upload files to the servlet and store it in documents in the NSF. I added a simple Angular front end that uses the angular-file-upload plugin to handle the uploads (MIT licensed). Out of the box that gives you multiple file select, image previews, progress bars and drag-and-drop. The code for the upload servlet can be found in the UploadServlet class in the database. Included in the demo database is also a very simple form showing that you can also use a

<input multiple="multiple" type="file" />

to upload multiple files in a single request. Something that (AFAIK) can’t be done on Domino if you’re going the XPages route.

My first attempt at the servlet was to use the same code I wrote a while age to process file uploads to an XAgent. That didn’t really work, because XAgents go through the XPages runtime and that does some pre-processing for you. In a servlet context you don’t get that: you have to work with the unmodified HttpServletRequest object. So I looked to see how the rest of the Java world was handling file uploads with servlets and discovered the Apache FileUpload project. That package abstracts the complexity of dealing with multipart/form-data. In a servlet context it gives you easy access to the uploaded files. So I added the required JARs to my database, read the docs and copied some sample code to get a handle on the uploaded file:

// Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();
// Configure a repository (to ensure a secure temp location is used)
ServletContext servletContext = this.getServletConfig().getServletContext();
File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
factory.setRepository(repository);

// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);

// Parse the request
List items = upload.parseRequest(request);

The items List in the code above contains all the items in the incoming request: note that every item can be either a form field or a file. You can differentiate between the two by using the isFormField() method.

Since I didn’t copy the required imports in the Java class, I ended up with some error messages about classes that couldn’t be resolved. Clicking on the errors revealed something interesting: I could solve the error by importing the Apache packages from org.apache.commons.fileupload (from the JARs that I just added to the database), but the list also showed a second option: use the com.ibm.xsp.http.fileupload package. Apparently Domino uses the same code under the hood to process uploads. That’s good stuff and means you don’t have to import any JARs to get the upload code to work 🙂

 

Screen Shot 2015-06-22 at 14.06.48

 

The rest of the code in the UploadServlet class in the demo database speaks for itself: I get the uploaded file(s) using the Apache FileUpload class and store all files received (in a single POST request) in the same document. Since the angular-file-upload plugin sends a request to the server for every file, they all end up in separate documents. Of course you can change this behavior by adding some logic to store them all in the same document, but I’ll leave that up to you.

One thing to note: the code in the demo database requires access to the getClassLoader method in Java, so you have to allow that in your Java security policy. Best practice on a Domino server is to create a file called java.pol in the <domino install>/jvm/lib/security/ folder and add:

grant {
permission java.lang.RuntimePermission "getClassLoader";
};

It was already in my settings, because a lot of other libraries need this too.

Enjoy!

 

 

Domino Access Services: ‘Limit Exceeded’ error for view entry collections

If you’re using Domino Access Services to get a view entry collection and include the count=XXX parameter (like described here), you’ll get an error if the number is larger than 100:

Limit exceeded.  Cannot read more than 1500 entries.

According to this, this limit was introduced with the 901v00_10 version of the Extension Library. I just ran into that limit myself and decided to do some digging in the ExtLib source. In one of the source files I found that the maximum can actually be controlled by a notes.ini parameter called DataServiceMaxViewEntries.

I just set that on my server and it works like a charm!

(not sure if this is a supported parameter, or if it will remain in the ExtLib, so you’re on your own with this…)

 

Bootstrap in XPages: now part of the Extension Library

bootstrap-logoToday IBM released a new version of the Extension Library (901v00_10 to be exact). The biggest news being that Bootstrap is now an official part of that plugin. They essentially took the Bootstrap4XPages plugin that Phil Riand and I have been working on and integrated it in the project. It’s great to see that IBM fully embraces Bootstrap to make XPages responsive (and good looking) and too see how a community driven project becomes part of the core product.

I already had a play with the new version and must say that Brian Gleeson and the rest of the team did an excellent job in extending the support of Bootstrap in the core controls: an area that could definitely need some work. They also improved the wizard to create a new application layout.

Unfortunately some parts of the plugin didn’t make it to the Extension Library, like the embedded Select2 support. I hope they’ll be able to add that again (and/or other useful Bootstrap plugins) in a future release.

If you want to see the new plugin in action: just visit Bootstrap4XPages.com. Good to know: the Select2 demos on that site are still powered by the Bootstrap4XPages plugin showing that that plugin can happily coexist with the Extension Library on the same server!