From XAgents to Servlets
¡Feliz Cinco de Mayo!
☀️ 🍹 🎊 🍻 🎉
It's been a little longer to get to this installment of my Saga of Servlets series, but I guess that happens when things like the day job pick up with trouble shooting server issues and family life all seem to get in the way.
This isn't the most "developer sexy" topic, but I hope is worthwhile (and something I promised would be in this series).
The intention of this post to tackle the concept of what an XAgent is (I'll be brief) and why our use of them can be substituted (in most cases) with an HttpServlet. There's a caveat to this, covered below, and for all intents and purposes, I'll be using HttpServlet interchangably with DesignerFacesServlet; the implementation of which I use being Jesse Gallagher's AbstractXSPServlet.
My intentions throughout this series have included to avoid any specific frameworks for building out an HttpServlet and/or RESTful API, hence the pure Java implementation, NSF-level implementation (making it easily accessible before getting into OSGi HttpServlets), and not being so keen on GSON as to put off people who can accomplish the same thing in the IBM commons library. That being said, the intention of this post is to bring us back to some common ground with other Java EE developers in how we perform some tasks; so if you're interested in such things (as I am!), please read Jesse Gallagher's post on using JAX-RS or Toby Samples' blog, as he's kicking off a series on using JAX-RS with Domino in an OSGi plugin.
Ultimately, the purpose is to provide a data response after performing some computation, over HTTP (effectively the same steps in an HttpServlet); whether that's a binary file like a PDF or web-consuable data response. XAgents provide an XPages developer an easy way of creating an endpoint, the XPage name, with which we can easily hook into the data response by setting it non-rendered and overriding the HttpServletResponse (and unless it's a response we don't need to persist state with, setting the xp:view attribute viewState to "nostate").
XAgents are relatively easy to create, especially for a less experienced XPages developer. My experiences in life have taught me that "easier" doesn't always translate to "better", but an XAgent is handy, conveninent, and easy to get started with.
How Much Overhead is in an XAgent?
I wish I had the time to invest in some benchmark comparisons. This may be something I revisit, as it will probably bug me until I have some actual data. In any case, the main idea here is that the full JSF lifecycle is invoked, causing a more-than-needed increase in server processing. An HttpServlet will take a request, process as needed for a valid response (stateless, if you go the RESTful route), and kick out a data response. An XAgent can do the same, but al the moving parts of JSF are still invoked.
In lieu of some recorded tests to back this up, I'm going to link you to a blog post by Karsten Lehmann talking about XAgent bottlenecks and an excerpt here that should sum things up nicely.
The consequence is that you should think twice about your XPages application architecture, if you have many concurrent HTTP requests or if some of them take a lot of time to be processed. An XAgent may be the easiest solution to deploy, but may not produce the best user experience in all cases.
[Insert Data to Back Up Reasoning Here]
When to Keep Using an XAgent
The caveat to using an HttpServlet is the need for reliable sessionAsSigner access. While I believe this is feasible at a conceptual level (especially inside an NSF), it would be lacking in the context of an OSGi plugin, as there would be no actual design element. I've tried to read up on and ask around on this subject, but the most I've found is an old question on OpenNTF and some confusing talk from Jesse Gallagher about ClassLoaders and the underlying Domino C API. Talking with Jesse about these things make it sound like a really good idea for me to take his word on it ð.
When you do have to use an XAgent, I recommend having a single line of invocation in your before/after ...RenderResponse. This should invoke the fully qualified package.class.Method with a parameter being passed as a handle to sessionAsSigner. This keeps things clean and simple, and your class will be easily maintained in a consistent fashion to any HttpServlet you create. For example:
Why Should I Care?
While we may be using a uniquely abstracted variant of an HttpServlet, by building our logic as an HttpServlet as opposed to an equivalent XAgent (especially in Domino/XPage's SSJS), we create our data service in an industry normal fashion. If this on top of the performance increase doesn't sell it for you, I'm not sure what will.
If we want to be more of a Java EE developer, which is the industry equivalent norm for an XPages developer (by my interpretation), then we should ebmrace the more industry norm practices. In this case, it also means we drop some of the unnecessary JSF "baggage" from the process of merely handling a data response.
The final part of this series will cover some of the client-side application in using the the HttpServlet we set up in the Round House
Kick Tour of data handling. It may come soon, if I can keep my spawning of non-series post ideas in check.