Out of the box XPages connect to
Notes Views and
Notes Documents as data sources. Other data souces require some
advanced skills you might not be ready to invest. However controls can be bound to many things, data sources are just one of them. Under the hood the data binding uses the JSF
Expression Language (EL). Since XPages knows a JavaScript binding you can bind your control to any JavaScript function, but that's not what I want to show today. One very interesting option (that is 1:1 JSF) is to bind your controls to a
managed bean. So what is a managed bean? It sounds more complicated than it is. The
bean part is a standard Java class that has a constructor without parameter (which is the default for a Java class anyway) and get/set methods pairs (more about that in just a moment). The
managed part is an entry in the faces-config.xml where you define a "friendly" name for a Java class as well as the scope. If you use that
friendly name in code (in SSJS or EL) the class instance is automatically created for the defined scope if it doesn't exist yet in that scope. Once the scope expires the object is automatically discarded. Since this works automagically the Java class is called "managed". An entry in your faces-config.xml (to find that file, open the Navigator view and look for /WebContent/WEB-INF/ in your NSF) could look like this:
<managed-bean>
<managed-bean-name>demo </managed-bean-name>
<managed-bean-class>com.demo.ELTest </managed-bean-class>
<managed-bean-scope>session </managed-bean-scope>
</managed-bean>
With this entry a new top level object
demo is available for use in EL or SSJS in the same way as you can use database, session, context etc. Our class is valid for the session context, so multiple XPages will see the same content. You can name your methods inside the Java class as you like and call them in SSJS, e.g.
demo.playTune()
. The more interesting use however is the bean use. If your (real live) object has e.g. 3 properties:
Name, Color, Taste, then you would have 6 methods in Java, 2 each for each property:
getName(), setName(newName), getColor(), setColor(newColor), getTaste(), setTaste(newTaste)
.
Once you follow this pattern you can refer to that property in EL just by its name:
demo.name, demo.color, demo.taste
(Note: no brackets here!). You enter that in XPages data binding in "Advanced / Expression Language". It will however appear in the regular data binding setting with the bean's friendly name as name of a data source.
A little stumbling block: the properties start always
lowercase, while the first letter after get/set must be
uppercase. Also the get function needs to return the same data type as the set function takes in as a parameter.
XPages inspects the bean for the get/set functions. If the set function is missing a control is automatically rendered read only, while a missing set function leaves an entry field empty. Once data is posted back to the server the set functions of your bean are called and it is up to you what to do with the data. Having named get/set function is great when you exactly know your object at design time. A very typical use for a bean binding however is retrieving a data set where you don't know what is coming. EL also can cater for that. Your Java class needs to implement a property that returns a
Java MAP in a pair. e.g.
Map<String, String> getStuffProperties(); void setStuffProperties(Map<String, String> newProps);
Once you have that you can write as data binding in EL:
demo.stuffProperties["Color"]
. Here you have the freedom to use upper- or lowercase property names as you like. Of course you are not limited to a static string and have any expression EL is capable of at your disposal. This makes a quite powerful construct. Try it yourself! Use this simple Java class:
package com.demo ;
import java.util.HashMap ;
import java.util.Map ;
public class ELTest
{
private String color
;
private String taste
;
private String name
;
private Map < String,
String > fruitProperties =
new HashMap < String,
String > ( ) ;
public String getColor
( ) {
return color
;
}
public void setColor
( String color
) {
this.
color = color
;
this.
fruitProperties.
put ( "Color", color
) ;
}
public String getTaste
( ) {
return taste
;
}
public void setTaste
( String taste
) {
this.
taste = taste
;
this.
fruitProperties.
put ( "Taste", taste
) ;
}
public String getName
( ) {
return name
;
}
public void setName
( String name
) {
this.
name = name
;
this.
fruitProperties.
put ( "Name", name
) ;
}
public Map < String,
String > getFruitProperties
( ) {
return this.
fruitProperties ;
}
public void setFruitProperties
( Map < String,
String > fruitProperties
) {
this.
fruitProperties = fruitProperties
;
}
}