Yesterday I blogged introducing where we are with XOTS in OpenNTF Domino API, plus a short example about how to create a tasklet and call it. The example was a bit “hello world” – why would you want to call a tasklet to get the current username, when it’s possible and much easier to do that directly in your XPages code?
But it gave the basics of creating a background tasklet and accessing the outcome immediately. So let’s go further with an example that runs a background tasklet but doesn’t wait for the result. Instead the background tasklet posts the result to sessionScope
, ready to be picked up, for example, next time the user accesses the page or is displayed on the top of any page.
The code to call the XOTS tasklet is much simpler, because we just want to kick it off. We don’t want to wait for it to complete. It’s just one line of code:
We create a new instance of the UserOutput tasklet and submit it to the service. We’re not interested in the result, so we don’t pass the result to any variable (as you’ll see, there is not result). The only difference here is we’re passing the sessionScope
object into the constructor. As I mentioned yesterday, the only annotation currently enabled for tasklets is to denote the session type, so it’s currently just like running back-end code. So we currently need to pass in any other objects from the XPages runtime, like sessionScope
, XspContext
etc.
Now let’s look at the code for the tasklet class itself:
-
@Tasklet(session = Tasklet.Session.CLONE)
-
sessScope = scopeObj;
-
}
-
public void run() {
-
try {
-
if (sessScope.containsKey(“javaXotsOutput”)) {
-
sessScope.put(“javaXotsOutput”, null);
-
}
-
Database currDb = Factory.getSession(SessionType.CURRENT).getCurrentDatabase();
-
sb.append(“Processing “ + name + “….<br/>”);
-
+ doc.getItemValueString(“LastName”);
-
names.append(personName);
-
names.append(“, “);
-
}
-
if (names.length() > 2) {
-
sb.append(names.substring(0, names.length() – 2) + “<br/>”);
-
} else {
-
sb.append(“No names found.<br/>”);
-
}
-
}
-
sessScope.put(“javaXotsOutput”, sb.toString());
-
t.printStackTrace();
-
}
-
}
-
}
The first thing to notice is the class extends Runnable
instead of Callable
. That’s because we don’t care about the result, we just want to run the code. So it has a run()
method instead of a call()
method, whose return value is void
.
The next point to notice is on line 6, the constructor takes that sessionScope
object and passes it to a private variable in the class, so we can interact with it from the run()
method.
The code in the run()
method itself is not rocket science. It clears the sessionScope
variable, if it exists. Then it gets the AllStates view in the current database and iterates over it, getting the contacts for each state and building a string with their names. Finally it loads that into sessionScope
.
This means when the user clicks the button to trigger the tasklet, they can continue their work with the database. This is a basic example, so when the page is accessed after it completes (not very long, in this example), the list of contacts will be presented. But hopefully it gives an idea of what could be done.
Longer term, the context annotation will allow the developer to define whether the current XSP context should be passed, a “clean” XSP context, or no context. The XOTS code will then automatically instantiate sessionScope
etc, as if it was a normal XPages request, and you’ll be able to access them as normal. (Currently I got around this by adding a utility method, getSessionScope
, which tries to get the XPages sessionScope
, which will work in most code; else gets the current instance of my tasklet (or tasklets), and if they’re not null, gets the relevant sessionScope
object; I can then call the same helper method from throughout my application, and a quick Find / Replace allowed me to update all references in my Java code – obviously I don’t have to worry about SSJS code).
Good work and good blog. When is it stable enough to get started with it. The only missing part is the trigger of the tasklet as you described in your previous blog post.
When that is in place I think it opens a whole bunch of new opportunities
The tasklet code itself is, I believe, stable enough. I’ve used it for a recent project that’s going live, so I have a vested interest in things not gettig broken. Unfortunately at the moment I don’t have enough understanding to write the scheduler code.
Pingback: Access FacesContext in xAgent (in new Thread) - dex page