Me. Me me me. Me too.

Me... me... me...

Agent Smith was very good at multitasking

One of the best things about computers is that they can do more than one thing at a time. This is such a useful capability that we have a dizzying array of descriptiors for it: multitasking, multiprocessor, multiuser, multiplexing, multithreading — the list goes on. Unfortunately, along with being one of the most useful things about computers, it’s also one of the hardest to get right. This difficulty means that, for many platforms, doing things at the same time is simply not presented as an option.

Our beloved Domino is much like this. Yes, the server can do more than one thing at a time by using distinct processes and threads, but you and I as developers aren’t generally in control of this multithreading and concurrency. And that’s not surprising, since concurrent programming is hard.

It’s particularly tricky in Java and Domino because of something called “thread affinity.” That probably sounds like some kind of knitting technique, so let me elaborate…

A “Thread” is what Java calls a process executing concurrently to other processes, under the context of a single Java virtual machine. In XPages, each time the HTTP server passes along a request, that request is serviced by a Thread that’s then responsible for sending back a response. In classic Notes, you might think of a Thread as an Agent running some particular piece of code. If you have several Agents running at the same time on a server, then they do things independently from each other, but are still on the same server.

Threads are a vital part of large-scale programming; so much so that entire languages have been created specifically to make handling of threads easier. Java’s handling of threads has improved since version 1.0, but can still be pretty obtuse, especially when you aren’t versed in all the subtleties of Runnables, Callables, ThreadPools, Executors, AccessControlContexts, SecurityManagers and ClassLoaders. Frankly, it can all be overwhelming.

To make matters even trickier, the lotus.domino API binds all of its Java objects to a specific Java thread. So when a Domino object is created on a specific thread, it must also be .recycled() on that same thread. An attempt to recycle it on a different thread can lead to some rather spectacular crashes on your servers.

Because of this, when you have some Domino process that you’d like to run in a separate Java Thread, you really want to start with a fresh Session, and make sure you create all your Domino objects from that session, and then recycle that session on the same Thread. It seems kind of natural that you’d like to say “make a session, do some stuff, then release the session when you’re finished” all as one managed multi-threaded process.

Alas, life is never that simple, is it? It turns out there are only a handful of ways to create a Session from a Java Thread. If you’re in an Agent, the AgentContext creates one for you before your process starts. If you’re in an XPage, the NotesContext creates one for you before your process starts. If you’re in DOTS or a Java server addin, you just call NotesFactory.createSession().

What you *can’t* do is just call NotesFactory.createSession() when you’re in an Agent or in an XPage. It’s not allowed. The lotus.domino API walls this off to keep you from making a session directly once certain processes have started. This makes Java multi-threading an enormous pain in the ass, because you end up having to create or copy your Session in one thread, hand it to another thread that does whatever you want to do, then hand it back to the original thread to say “it’s okay for you to recycle this now.” But you better have recycled everything you got from the session in your other thread or you risk some mighty crashes.

Because of all this trouble, almost nobody writes multi-threaded Java programs for Domino. There’s a couple of IBMers and a handful of business partners who will take it on, but for the most part, the platform remains constrained by “what can I do serially with just one process?”

Personally, I’m sick of this. Domino is a very obvious choice for multi-threading processes, given how information is so commonly silo’ed in individual NSFs. And it has lots of great features like full-text searching and cross-server data access that can be quite slow and would benefit greatly from threading.

I’m so sick of it, in fact, that I’ve done something about it. I’ve added a thread management framework to the OpenNTF Domino API that takes all these headaches away. With the next version of the API, you’ll be able to write a Java class that extends XotsBaseTasklet, and simply overrides the .run() method. You just put your Domino code in the .run method, starting with .getSession() to acquire your ThreadLocal session. And you never have to worry about recycling anything at all.

Even better, you can tell your Runnable what kind of Session you want. It can be NATIVE if you want to run the process directly as the server. It can be NAMED if you want to specify a “runAs” name for your process. It can be MANUAL if you want to worry about how to create the Session yourself and just pass it to the process.

Better still, all this works from the XPages JVM. So if you want to write some Java code that runs as the server when you click a button in an XPage, you need a Java class that looks like this…


public class MyTask extends XotsBaseTasklet{

public MyTask() {

this.setDominoSessionType(DominoSessionType.NATIVE);

}

public void run() {

Session session = this.getSession();

//Do whatever the hell you want because you're the server now, baby!

}

}

When you want to run it, you just call…
org.openntf.domino.xots.XotsDaemon.getInstance().queue(new MyTask());

That’s all there is to it. No worrying about where to recycle stuff. No worrying about Java security controls. No worrying about how to deploy the code because you can just define your class as a Java design element. It just works.

You might notice that this is a package called “Xots.” If you’re thinking that this sounds like a cross between XPages and DOTS, you’re exactly right. Putting the Tasklet infrastructure in place is the first step in allowing for template-based scheduled Tasklets that run inside the XPages OSGi context. We have some hardening work to do still, but the end result will be that XPages developers who use the OpenNTF Domino API will be able to do away with scheduled Agents, and execute their scheduled processes inside the same JVM context as all the rest of their code.

I’ve been testing this frantically over the past couple of days and I’m really excited about it. I hope you are too. Feel free to voice your own suggestions, requests, demands and fears in the comments.

Thanks!

Posted in Uncategorized
16 comments on “Me. Me me me. Me too.
  1. How would overuse be governed? For example, if x number of threads were running concurrently and the server is taxed?

    • thentf says:

      Good question Michael. Do you have any thoughts on how you’d LIKE it to work? I can tell you that running native session threads is a lot cheaper than running entire Agents, so you’ll be better off than you were before.

      We could do some kind of centralized monitoring and maybe a concurrency limit control of some kind.

      What do other people think? Is an “admin console” with the ability to monitor Tasklets important?

      • When you start talking about concurrency limit controls, does that mean then building a queue and managing that as well? As a developer that occasionally does admin work, I LOVE consoles that tell me important stuff instead of firing off commands to retrieve it.

  2. thentf says:

    I would definitely build queues when concurrency limits are reached. The failure to queue tasks is one of the fundamental problems with DOTS.

  3. flinden68 says:

    great work, Nathan. Is it also possible to schedule the tasklet? So we have a truly replacement of the grippy Notes Agents

    • thentf says:

      Scheduling is in the plan. It’ll start with annotation-based scheduling, but if we make some kind of admin dashboard for it, then we’ll likely move the scheduling control to there.

      • flinden68 says:

        Dashboard should be nice, but annotations is already a very good start. Keep up the good work

  4. Cameron Gregor says:

    Very interesting. This would be very handy indeed!

  5. Tommy Valand says:

    Nice work, Nathan!

    I struggled with the “create session inside thread” issue a few weeks ago, and gave up..

    Would this API allow you to create session using the LtpaToken of the current user/or is there some magic that allows you to do this without worrying about such things?

    • thentf says:

      Tommy, I haven’t worked much with LtpaTokens yet. I would imagine there’s some way to do it, but I don’t know how much it would be needed, since on the server we can just create http sessions with any name we want.

  6. Is there any way to track how many XOTS sessions / tasklets are running at any one time? I can see times when I would want to check. Then it could be added into something like the XPages Toolbox as a tab for profiling and interrogation.

    For Michael’s suggestion on concurrency limits, I guess we’re talking something similar to the settings for number of agent threads in the server document. We can’t modify that, but we could add a notes.ini variable. Notes.ini would probably be better than xsp.properties, because it’s more prevalent.

    • thentf says:

      *IS* there any way? No. *WILL* there be a way? Absolutely. 🙂 Jesse Gallagher’s even talking about a REST API to get reports and issue commands, which I think would be awesome. Then you could front-end it with anything.

  7. Very COOL functionality!!!

    Look forward to it getting out into “the wild” 😉

  8. Michael Bourak says:

    Hum…could it help in bringing asynchronous support in Domino ? (I mean such as one in NodeJS and so on)

  9. Stephan H. Wissel says:

    Would that also work on a Notes client from an external Java program?

Leave a reply to Paul Withers (@PaulSWithers) Cancel reply