ShowTable of Contents
When I first started on XPages last year, one of the big benefits was that virtually anything can be computed. When you do so, you get the option to use three languages: Expression Language (EL), Server Side Javascript (SSJS) or Custom. I immediately started using Server Side Javascript, but the others were a bit of a mystery. If you have experience of JSF or JSP, you'll know about Expression Language. But as a developer whose main experience was Notes Client development, and some classic Domino web development, it meant nothing to me. If I'm not the only one, hopefully this blog post will demystify it all and allow you to reduce the amount of typing by combining languages (that's the Rosetta Stone reference, that you're using all languages side by side).
The process for me when I tried to understand the languages is the same as I've used to try to understand other areas of XPages: use the wizards and look at the Source pane. The first thing to say is that there are actually four languages instead of the three mentioned above. There is also the default language for content. This is usually a literal string, but for some events like onComplete the default language is client-side javascript.
If you look at the Source pane, you'll notice is that if you use EL or SSJS the content is wrapped by default in "#{...}". If you've extended this further, you'll also have come across "${...}". What I found out recently when I started reading The Complete Reference: JavaServer Faces 2.0 is this is based on Expression Language in JSF, where the same two concepts are used. If the hash is used, your code is recomputed every time that element is included in a partial refresh (i.e. each time it is rendered). If you use a dollar, your code is only computed when the page is initially loaded. But this has been extended beyond just EL, to SSJS too. After the hash or dollar, the curly braces denote the start and end of your language. This will be important when we come to combining languages later.
As I said, by default everything is wrapped in "#{...}", but once you get past early development, it's well worth using "${...}" where appropriate to maximise performance. However, bear in mind that if you're referencing output from e.g. a repeat control, you may not be able to use "${...}", because the relevant underlying objects have not been created early enough in the lifecycle. (The lifecycle and when objects are created is an area I'm still getting to grips with.)
Now for the languages. EL uses dot notation to bind to a NotesXSPDocument object (i.e. a DominoDocument datasource), a NotesXSPViewEntry object (i.e. a row of a DominoView object) or a scoped variable. The former is straightforward, and the dot notation binds to a field. The binding is read-write, so providing you have author access to the underlying NotesDocument you can modify the value. (The way I tend to think of it is that the DominoDocument datasource, the NotesXSPDocument, is the equivalent of the NotesUIDocument in classic Notes Client development, so if your datasource is designated document1 - var="document1" in the source - document1.getDocument() gets the back-end NotesDocument object.)
The latter is slightly more convoluted. If you have a DominoView datasource and use it as the source for a View Panel, Data Table or Repeat Control, the NotesXSPViewEntry object gives you access to each row and the dot notation binds to a column in the view. The DominoView will have a variable name which is used to bind the view to a View Panel, Data Table or Repeat Control (e.g. value="view1"). The View Panel, Data Table or Repeat Control can have a variable name (you need to define it, e.g. var="viewEnt") to access a NotesXSPViewEntry. The binding references the name of a column, so "#{viewEnt.FullName}" binds to a column called FullName. Bear in mind that the binding is read only, so if you have an editable field (xp:inputText) bound to a column name on a NotesXSPViewEntry, what you will see is a Computed Field (xp:text). If you want to edit the value, you need to set the value to be the relevant field from the underlying NotesDocument object, and write your own code to save the value back.
As you'll see from the format of "#{viewEnt.FullName}", the content within the curly braces is just the EL. If you have a short expression, what you'll see on the All Properties tab is # viewEnt.FullName. Cross-reference with the source pane and you'll see value="#{viewEnt.FullName}". So by selecting EL, the editor automatically inserts the hash and automatically populates the source accordingly.
Server Side JavaScript (SSJS)
SSJS, as anyone who has looked at the source pane will have seen, follows a similar format, but the content within the curly braces is prefixed with "javascript:", so e.g. "#{javascript:@Subset(@DbName(),1)}". (And this is a perfect example of where you would in preference use dollar, because the server name is not going to change when partially refreshing the page, so you would use "${javascript:@Subset(@DbName(),1)}").
If you think about it, this is understandable because the rest of the syntax to compute values is based on Expression Language in JSF. But something is needed to tell the XSP engine that this is not Expression Language, that a different parser is required. And that's why it is prefixed by javascript:, to tell it to use SSJS (no additional prefix is required, because CSJS is not an option, so there can be no ambiguity by using the term javascript:.
But when you look at the drop-down for languages, there is a third, Custom. For this you get no help, no explanation of what it means. But in actual fact it's very simple. It means that you are combining languages, and this is where the power of XPages comes in and where you can really speed up your development. By using the syntax from the source pane I've already described, you can combine languages. So instead of using a label and computed field, or two labels, or two computed fields, you can combine multiple expressions of all the languages I've outlined.
So let's just paraphrase what those languages are. "Name" is a literal string. "#{document1.Name}" is EL, returning the Name field from a document1 datasource (this will always be a text value - you need to add a converter to manipulate the value). "#{javascript:doc.getItemValueString("Name")}" gets the value from a text field called Name on a NotesDocument or NotesViewEntry defined as doc. The quotes are always used around the various expressions.
This means by using you can have a single Computed Field whose value is "Name is " + the Name field of the document1 datasource by setting the value attribute to "Name is #{document1.Name}". You could equally use "Username: #{javascript:@Name('[CN]',@UserName))}" to have a single Computed Field whose value is e.g. "Username: Paul Withers" (again, this would be a good candidate for using dollar instead of hash). And you could use "#{viewEnt.Site} #{viewEnt.getDocument().getItemValueString('Department')}" to have a single Computed Field that combines a NotesXSPViewEntry's Site column with the value of the Department field in the underlying NotesDocument, all separated by a space. Just remember that anything not in curly braces is a literal string, even a space is a literal space, so if you wanted site and department separated by a colon, with no spaces, you would need to enter .
Once you become confident combining the three languages into the fourth Custom language, you can minimise the number of controls on your XPage and minimise the amount of typing in the source pane.
Paul Withers is a Domino Developer at Intec Systems Ltd. The original post of this and other tips / observations / tutorials are available at the
Intec Blog