It is a number of years now since I decided to commit to Java, for a number of reasons. The biggest were:
- lack of good compile-time validation, which meant it was possible to mistype a variable name or method name
- lack of templating, which meant constantly typing try/catch blocks
- difficulty troubleshooting – this was before the SSJS debugger, but even when the debugger was released, I struggled to work well with it
A little while after starting with Java I had a discussion with Tim Tripcony. Typically for Tim he explained exactly what SSJS was, which makes all those limitations totally understandable and reinforced my conviction that less SSJS and more Java was a no-brainer.
Secondly, and most importantly, it’s not really a language. There is no SSJS engine, as such, within the XPages runtime. This becomes particularly apparent when you look at what actually runs on the server. This means going to the Package Explorer view and looking at the Local\xsp Java package, which holds the Java classes compiled from the XML markup for each XPage and Custom Control – which further reinforces that XPages is Java. Each component (Computed Text, Button etc) is a separate Java object created by its own method when the page is initially created. Here is the code for a button with a SSJS rendered property. Note, the corresponding eventHandler is also a component, separate from the button component, with its own properties.
Once a chunk of code has been separated, it needs parsing. There will be some specific keywords, like “if”, “else”, “var”, “:” (used to cast a variable to a Java class). Those keywords can easily be handled, so the first four characters –
if ( can be quickly handled.
If a word is not a keyword, then it needs processing. Most developers are probably unaware of what happens next, but it was something I identified a while back by adding a print statement to a custom VariableResolver. Once a word that’s not a keyword is identified, it’s passed to the VariableResolver. The VariableResolver is queried to find the variable name (in the first case “view”) in one of the scopes, working from requestScope out to applicationScope (or further, if available). In the case of a line of SSJS that initialises a variable, presumably it is added to requestScope once initialised, to be removed once the SSJS has been processed or at the latest once the component has been processed.
In the case of parameters, like in
document.getItemValueString("Name") it gets more complex. That’s because those parameters need converting, from SSJS “variable types” to Java classes. This is probably less well known, unless you’ve dug into the OpenNTF Domino API or Extension Library. The comment in the Extension Library example explains things very well:
// Each function expose by a library can then have one or multiple
// “prototypes”, defining its parameters and the returned value type. To
// make this definition as efficient as possible, the parameter definition
// is compacted within a string, where all the parameters are defined
// within parenthesis followed by the returned value type.
// A parameter is defined by its name, followed by a colon and its type.
// Generally, the type is defined by a single character (see bellow) or a
// full Java class name. The returned type is defined right after the
// closing parameter parenthesis.
// Here is, for example, the definition of the “@Date” function which can
// take 3 different set of parameters:
So even though
getItemValueString() takes a String and Java also has a String, there still needs to be some comparison, both converting the parameter and converting the result. This is why it can cause problems when calling Java methods from SSJS with different variable types, like numeric ones.
This is why my preference is even more to use Java, even if it means using a single line of SSJS to call Java.
SSJS is not completely bad. It’s easy to screw things up when coding it. How many developers have forgotten to add “var”, which means the variable is not instantiated and attempts to use it fail? And how many have written SSJS that includes a typo, especially when not casting variables to an SSJS / Java class? It’s easily done.
But the SSJS editor is reasonably good in the typeahead support, although it only works for core classes. When an XPages app dev roadmap existed, enhancements to typeahead support were planned to extend it to include custom Java classes. Who knows if that will ever be delivered. But the editor helps a lot, which is also why I would recommend casting variables to SSJS / Java classes.
But the key point is that, even though it’s compiled down to an escaped String in the underlying Java class behind each XPage or Custom Control, the development experience is via the SSJS editor. Thankfully we don’t need to write SSJS into a Java String variable directly (reminiscent of writing print statements to pass to a browser from a LotusScript web agent).
As I’ve started looking at other database types, the learning from SSJS covered in this blog post and particularly that last point have been at the forefront of my mind.
I’ve done a lot on Graph recently and Neo4J is a popular Graph database. Similarly any interaction with the database seems to be through statements written as and stored in strings.
Apache Cassandra has a document API query language, CQL. That allows the same kind of thing, executing CQL statements written as Strings from Java, as covered in the first part of the introduction tutorial, which are executed against the session as detailed in the Java Driver API documentation. But the Java API also provides Java methods for each part of those statements, which the second part introduces quite promptly, which are loaded into a QueryBuilder as detailed in the API documentation. This makes me feel much more comfortable because it is less error prone as well as showing a provider committed to Java.
Compare also the Java API examples for IBM Graph (which uses Titan, a Java API based on Tinkerpop). This requires you to create JSON queries to the Gremlin server and convert the JSON data (which has already been converted from Java to JSON by the Gremlin server) back into Java. Needless to say, that’s also very error prone and frustrating for anyone familiar with Tinkerpop or graph databases.
So as bad as SSJS may seem, the editor is worth applauding and without it, many Domino developers would not have embraced XPages.