OpenNTF Domino API has provided a number of significant enhancements. One of the more recent is XOTS. As its name suggests, XOTS brings together XPages and DOTS.

At this point I think it’s worthwhile backtracking and giving some background on DOTS, which many XPages developers will not have utilised. DOTS came in with 8.5.3 and runs within OSGi to allow code that is outside of the NSF to run and return a response, but still interacting with NSFs. The (only officially supported) implementation is for Domino Access Services for REST API access to Domino views, documents, mail and calendar. Better thread management and other extensions were added in the OpenNTF project DOTS Extended.

However, the limitation has always been that an NSF may have specific business logic in it, but the DOTS task had to live outside the NSF, so could not share the same Java code. There was no way to code once and apply to threaded / backend tasks. Furthermore, there was no functionality for scheduling tasks. So agents had to be either ported to LotusScript or coded in Java with a third copy of business logic and utility classes (because XPages Java code cannot be used in Java Script Libraries or Java agents).

XOTS is intended to address these issues, specifically allowing:

  1. Code to be written in the same place as XPages, triggered from e.g. a button or link.
  2. Multiple threads can query multiple databases simultaneously.
  3. Code can run in the background or the code can wait, polling the threads for results periodically and, when all have finished, continuing.
  4. The tasklets can access XPages objects, like sessionScope, applicationScope etc. (This aspect will be improved in future releases.)
  5. Work is still in progress so that tasklets can be written to run on a schedule. A background thread in OpenNTF Domino API already checks for XOTS tasklets on HTTP startup. In the final implementation, this will also run periodically, logging details to a Domino database. A background thread will then run (like Agent Manager) to start the tasks accordingly.

Functionality already exists in the latest Release Candidate to cover numbers 1 – 4. (Currently scopes need to be passed in as properties of the tasklet class, but this is fully functioning to allow updating e.g. sessionScope.)

A tasklet is basically a Java class that implements Runnable or Callable<?> where “?” is the Java class that should be returned (e.g. String, Map etc). If it implements Callable, it can return a value or throw an Exception; if it implements Runnable, it cannot. To implement Callable, it needs a call() method, which contains the code to run when the tasklet is triggered. Settings for the tasklet can be defined through annotations. You get typeahead support for the annotations, so it’s not an arcane art. However, the only annotation currently implemented is session. Here is the code for a simple tasklet:

  1. @Tasklet(session = Tasklet.Session.CLONE)
  2. private static class SessionCallable implements Callable<String> {
  3.   public String call() {
  4.     try {
  5.       return Factory.getSession(SessionType.CURRENT).getEffectiveUserName();
  6.     } catch (Throwable t) {
  7.       t.printStackTrace();
  8.       return t.getMessage();
  9.     }
  10.   }
  11. }

The annotation before the Java class tells it to clone the current session, so Factory.getSession(SessionType.CURRENT) will be the current user’s session. (So like “Run as web user” in a web agent). The class implements Callable<String>, so we’re expecting the call method to return a String, reinforced in the public String call() method declaration. The code then returns the current username and, in the unlikely event of an error, prints the stack trace to the browser and returns the error message to the calling method.

To trigger a single instance of the tasklet (for something like this, it makes no sense to trigger it in multiple threads!) and use the result of the callable tasklet, we pass the result into a java.util.concurrent.Future. To trigger the tasklet coded above and pass the value to viewScope, it’s just a matter of the following code:

Future<String> future = Xots.getService().submit(new SessionCallable());
ExtLibUtil.getViewScope().put(“MessageFromXots”, future.get());

The first line gets the XOTS service and submits (runs) a new instance of the tasklet. It passes the result (a String, remember) into a Future. The second line passes that String result into viewScope. The get() method of the Future will only execute once the tasklet has completed, so the code will wait for completion.

So here we have a simple XOTS tasklet that is called, with code waiting for completion and putting the result into a viewScope variable. In the next blog post I’ll cover running a tasklet as a background task and passing values into the tasklet.

2 thoughts on “XOTS: Background and MultiThreaded Tasks the OpenNTF Domino API Way (Part One)”

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