XPages to Web App Part Eight: OSGi JAX-RS REST Access with ODA
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
Following Toby’s steps gives a simple plugin (bear in mind there have been more developments of that repository since the initial release, so you might wish to refer directly to the initial commit. Also, if you use a pde launch configuration and have the Extension Library installed, you may get an error message saying it’s finding multiple SL4J bindings, as I did. It seems that this was being contributed twice, from Extension Library and the core, so I had to remove the org.apache.wink project that’s part of ExtLib from my Eclipse workspace and from the launch configuration.
Toby’s example just outputs the current username, as a simple “Hello World” demo. The method of getting the current user’s session is
ContextInfo.getUserSession() which returns a lotus.domino.Session. But with OpenNTF Domino API, we need an org.openntf.domino.Session. In XPages, the easiest way to get that is to resolve the variable
session of godmode is enabled, otherwise to resolve
openSession. Outside of XPages, however, you can’t just cast
ContextInfo.getUserSession() to an org.openntf.domino.Session object. Instead, outside of XPages, you need to use
Factory.getSession(SessionType.CURRENT) to retrieve the current session. However, if you tried that in the demo, it would throw the error org.openntf.domino.utils.Factory is not initialized for this thread, as some have encountered.
At this point it worth going into greater depth on what’s happening in XPages with sessions and why resolving variables actually makes best sense. Firstly, with vanilla XPages, if you’ve looked at scoped variables, you’ll know
database get stored in
requestScope. Those variables obviously have to get re-applied on every request, because Domino objects are not serializable. So, not surprisingly, OpenNTF Domino API adds
openDatabase objects to requestScope and, if in godmode, overrides the
database objects. These are applied every time an XPage interacts with the XPages runtime and, before this is done, the process initialises the Factory and adds in the current user session, the signer session and the signer with full access session. (For those who want to know more, they’re applied as implicit objects by FacesContextFactories via either domino-faces-config.xml or OpenntfDominoXspContributor.) So why go to the Factory class to get the session, when the whole process has given you easy access via the implicit variables?
But outside of XPages – whether in a plugin or elsewhere, the Factory will not have been initialised for the thread: no current user session will have been added. So basically we need to do that.
In CrossWorlds, that’s done through a filter, but the ability to use a filter doesn’t work in Domino’s OSGi context (that was my first attempt for OsgiWorlds). In OsgiWorlds, we’ll see that’s done in a VaadinServlet, because every request from the browser to Vaadin has to go through that servlet. In a JAX-RS application, everything also goes through a servlet, defined in the web.xml with the following code in Toby’s example:
This passes everything through Apache Wink’s RestServlet. We can extend that, and I’ve created an XSnippet for it, which is basically a copy of a REST servlet class Nathan has already created in the org.openntf.domino.rest plugin for access via Graph. That reference in the web.xml will need re-pointing to the class you add.
The ODADataServlet class basically uses three methods: doInit() which starts the ODAPlatform (one per “application”, so one for this plugin), doDestroy() which stops the ODAPlatform, and doService() which does the processing. This first initialises the Thread based on configuration to enable all fixes and automatically convert fields to MIME if they hit 32k limit. Then it initialises the Factory using a new DasCurrentSessionFactory. This basically wraps
ContextInfo.getUserSession() into an org.openntf.domino.Session, which basically means your code can use
Factory.getSession(SessionType.CURRENT) to retrieve the current session. From there, you’re into the OpenNTF Domino API, so nothing needs converting.
So there’s no reason for REST servet developers to avoid using OpenNTF Domino API as well.
Postscript earlier today I tweeted that it depended on Nathan’s pending pull request to Extension Library. I’ve realised since that’s not the case.
Here is the com.paulwithers.demoServlet I created as a basic POC.
NOTE: The DasCurrentSessionFactory constructor has changed in ODA 3.0. If you’re using that version, use this version of com.paulwithers.demoServlet.