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.
Loaded vs Rendered
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.)
Expression Language (EL)
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:.
Custom
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.
thanks for this Paul
At our session at IamLUG, Tim Tripcony and I will show the use of entire EL custom *languages*. So instead of #{javascript: or #{id:, we’ll have #{lolcode:
The truth is, because of the extensibility of JSF, it really isn’t even difficult to do this.
Sorry, thought my website would show up as a link. Here’s the session details: { Link }
The mixing of EL is extremely convenient. For example, I often see examples where somebody wants dynamic inline client-side script, so they create a computed field, set escape to false (so the renderer won’t munge the markup), and set it’s value to something like:
“<script>var someGlobal = “” + @DbLookup(…) +
“”;</script>”
This works, of course, but there’s a more elegant approach: create a scriptBlock tag, and set its value to:
var someGlobal = “#{javascript:@DbLookup(…)}”;
As the XPage runtime is rendering the script tag, it detects the inline EL, and automatically translates the value server-side before sending the script tag to the browser.
@Nathan… so will we see #{lotuscript: … } from you then?
@Stephan well that’s just crazy talk right there. 😛
@Nathan The idea of custom languaqges sounds very interesting. I won’t be at IamLUG, but I look forward to hearing how it works.
@Tim I agree on the use of a script block. The key is realising when the inline EL will be converted to a literal value and handling accordingly
Hi Paul,
Just to find out, if you are in a position to upload the demo db for “Creating a Live Text Widget to Launch an Authenticated XPage”. I really appreciate you help on this.
Thanks in advance,
Bernd
sounds awesome!
i appreciate your viewpoint.that is great!!!