Table of Contents
Introduction
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
Glossary

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).

At this point it’s worth a review to give some background on (RESTful) web services. Web services were first introduced in Domino 7 as Web Service Provider and Web Service Consumer design elements. These use SOAP and an XML schema of the structure and calls available – a .wsdl file. As interaction became more popular, API development become prevalent and responses were often handled via JavaScript, the traditional SOAP-based web services became less popular and were overtaken by RESTful web services. If a new web service call was added or the structure amended, the wsdl file changed, affecting any external applications using the web service calls. SOAP-based web services were replaced by web services that sent and returned JSON data, which seems to be much more agile and flexible, with smaller posted and response data. But the Web Service Provider and Web Service Consumer design elements in Domino don’t handle JSON-based web services. So an alternate approach is required.

The alternatives can be from basic to more complex:

  1. 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.
  2. 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 HttpServletRequest object with facesContext.getExternalContext().getRequest() so you can identify whether it’s a GET or POST request and handle accordingly. Similarly you can get the HttpServletResponse object from facesContext.getExternalContext().getResponse() to handle response error codes.
  3. 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.
  4. XPages Extension Library REST Service Control passing access to a CustomServiceBean. This is coded in Java and has a renderService method. The renderService method will get the HttpServletRequest and HttpServletResponse objects from the RestServiceEngine and 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.
  5. A custom servlet within the NSF, using the CustomServletFactory class. This has a createFactory() method to instantiate a ServiceFactory and add one or more ServiceEngines. The ServiceEngine has access to the HttpServletRequest and HttpServletResponse objects, so can handle responding to GET/POST etc and sending the response.
  6. 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 ResponseBuilder to manage different response codes and build the output. Extracting parameters is also standard using @PathParam or @QueryParam. Once you have the shell of the custom servlet application set up, managing your servlet classes is standard.
  7. A plugin that hooks into the com.ibm.domino.das.service extension point, 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 RESTService will override the getClasses() or 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 createErrorResponse(), getUserDatabase() to get the NSF that is part of the URL, verifyDatabaseContext() and 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/

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top