From XPages to Web App Part Sixteen: OSGi JAX-RS REST Access with ODA Revisited
Table of Contents
Part One – The Application
Part Two – XPages Advanced 1
Part Three: XPages Advanced Database Separation
Part Four: XPages Advanced Document Wrapper
Part Five: XPages Advanced MVC Controller
Part Six: Use of OpenNTF Domino API
Part Seven: OSGi Application Development Introduction
Part Eight: OSGi JAX-RS REST Access with ODA
Part Nine: OsgiWorlds
Part Ten: Vaadin
Part Eleven: OsgiWorlds Document Wrapper
Part Twelve: Key Date Page
Part Thirteen: Application Structure
Part Fourteen: Calendar View
Part Fifteen: Key Dates Filterable View
Part Sixteen: OSGi JAX-RS REST Access with ODA Revisited
In Part Eight I covered using OpenNTF Domino API in a servlet.I’ve been digging a bit deeper in preparation for a couple of potential projects that will need RESTful web services, and picking up an issue identified to me some time ago with my code (although it’s actually deeper than my code, but is probably because I extended the wrong class).
The alternatives can be from basic to more complex:
- XAgents that manually write JSON strings (this was the approach I used for XPages Help Application many years ago). This just acts on a request and requires manual handling of incorrect types of request or incorrect parameters passed.
- XAgents that manually output JSON using JavaJsonObject class from IBM. However, this still just acts on a request and requires manual handling of incorrect types of request or incorrect parameters passed. But XPages does give access to the
facesContext.getExternalContext().getRequest()so you can identify whether it’s a GET or POST request and handle accordingly. Similarly you can get the
facesContext.getExternalContext().getResponse()to handle response error codes.
- XPages Extension Library REST Service Control (xe:customRestService). This handles whether the REST service accepts GET, POST, PUT or DELETE methods. In SSJS it returns an SSJS Object.
- XPages Extension Library REST Service Control passing access to a CustomServiceBean. This is coded in Java and has a renderService method. The
renderServicemethod will get the
HttpServletResponseobjects from the
RestServiceEngineand these two are standard Java classes. So any questions you have on implementation is the same for any Java developer, so StackOverflow is your friend. For example, if you want to know how to identify if it’s a GET or POST request being made and handle accordingly, there’s a question for that and it’s nothing proprietary to XPages. If you want to send a 404 error, there’s a question for that and again it’s nothing proprietary to XPages and, because it’s Java, avoids typos by using an enum. This is the most flexible option for REST services within an NSF, but requires URL access to that NSF and exposes the full URL. It also makes it more difficult to handle authentication yourself, without Domino getting involved.
- A custom servlet within the NSF, using the CustomServletFactory class. This has a
createFactory()method to instantiate a
ServiceFactoryand add one or more
ServiceEnginehas access to the
HttpServletResponseobjects, so can handle responding to GET/POST etc and sending the response.
- A custom servlet application, like the one I created in Part Eight. This identifies whether it’s a GET or POST, can contribute multiple rest services. It’s an OSGi plugin, which means it’s not tied to a specific NSF. It also uses standard JAX-RS can use a
ResponseBuilderto manage different response codes and build the output. Extracting parameters is also standard using
@QueryParam. Once you have the shell of the custom servlet application set up, managing your servlet classes is standard.
- A plugin that hooks into the
com.ibm.domino.das.service extensionpoint, defining a path for the REST service and pointing to a class that extends
com.ibm.domino.das.service.RestService. This is what OpenNTF Domino API is doing for the Graph REST service and is documented on Domino App Dev Wiki by Dave Delay (who created the DAS REST services, I believe). The extension of
RESTServicewill override the
getSingletons()method. I’m not totally certain of the difference, but OpenNTF Domino API uses
getSingletons()method. There is an additional implementation step required for this, specifying the name attribute from the extension in the server document. But it looks like the DasServlet class generates statistics, so a plugin taking this kind of approach may also load those stats.
The approach you choose will vary depending on your requirements and your level of experience with Java. But taking an approach that uses JAX-RS, as the plugins do, is more standard and handles more out-of-the-box than manually interacting with the Response and Request objects.
In Part Eight I used option 6. My application used a custom servlet class in order to start and stop OpenNTF Domino API. This class extended the
DasServlet class. This works fine if it’s the only custom servlet on the server, but throws an Error 500 if there are more than one, because the Response Writer was not available. I’m pretty certain this is because the
DasServlet class isn’t intended to be extended for use on a server. Instead the custom servlets should extend
AbstractRestServlet (which is what DasServlet extends).
The Application class I used also extended
javax.ws.rs.core.Application. On reflection, and after further investigation, I would recommend extending
com.ibm.domino.das.service.RestService. This is because it has a host of useful methods like
getUserDatabase() to get the NSF that is part of the URL,
verifyNoDatabaseContext() to force or prevent a database path being included in the URL, and
verifyUserContext() to ensure an authenticated user.
There are then additional options you can throw into the mix like Jackson or Gson, for manipulating between Java objects and JSON, but that’s more for managing the data conversion rather than where the servlet / XAgent is.
Some useful resources on XAgents / servlets, in addition to the articles by Toby Samples I mentioned before are:
- Craig Shumann’s presentation from Connect 2013 – http://www.slideshare.net/CraigSchumann/bp204-final
- John Dalsgaard’s DanNotes presentation – http://www.slideshare.net/JohnDalsgaard/dannotes-19-20-november-2014
- The PDF for Bernd Hort’s presentation on REST services in Domino from Connect 2016 – http://www.assono.de/blog/downloads/IBM-Connect-2016-AD1238-pdf/$file/1238.pdf
- Eric McCormick’s servlet series – http://edm00se.io/servlet-series/