When I started diving in XPages for real – read no SSJS involvement – I derived great benefit from reading and examining the work done by Jesse Gallagher. His framework helped me to push some boundaries. In particular I immediately adopted the XPageController approach and made it my own.
Over time I built upon that model and added some features that I consider handy. The foundation of one of them is being disciplined in managing scope variables (in order to avoid name collisions fo example).
The XPageScope enum
This enum is a class that provides some structure for easier use later on.
public enum XPagesScope {
REQUEST, VIEW, SESSION, APPLICATION;
public String getVariableName() {
return this.toString().toLowerCase() + "Scope";
}
}
The XPageController interface
setScopeVariable
and getScopeVariable
are the methods by means of which I will manipulate the scope variables.
ScopeVariable
will be used in the final implementation of the controller class.
public interface XPageController extends Serializable {
public final static String BACKING_BEAN_NAME = "ctrl";
...
public Object getScopeVariable(ScopeVariable variable);
public void setScopeVariable(ScopeVariable variable, Object o);
public interface ScopeVariable {
public XPagesScope getScope();
}
}
ctrl
is the variable name I use to throughout the XPage to access the controller class for the given XPage.
The StandardXPageController class
The implementation of the above mentioned methods:
public abstract class StandardXPageController implements XPageController {
private static final long serialVersionUID = 1L;
...
private Map<String, Object> getScope(XPagesScope scope) {
switch (scope) {
case REQUEST:
return ExtLibUtil.getRequestScope();
case VIEW:
return ExtLibUtil.getViewScope();
case APPLICATION:
return ExtLibUtil.getApplicationScope();
case SESSION:
return ExtLibUtil.getSessionScope();
}
throw new UnsupportedOperationException();
}
@Override
public Object getScopeVariable(ScopeVariable variable) {
return getScope(variable.getScope()).get(getClass().getName() + "." + variable.toString());
}
@Override
public void setScopeVariable(ScopeVariable variable, Object o) {
getScope(variable.getScope()).put(getClass().getName() + "." + variable.toString(), o);
}
...
An example of implementation
The simplest implementation might look like the following:
public class MyPageController extends StandardXPageController {
private static final long serialVersionUID = 1L;
private enum PageVariable implements ScopeVariable {
MY_ITERATOR;
XPagesScope s;
private PageVariable() {
this(XPagesScope.REQUEST);
}
private PageVariable(XPagesScope s) {
this.s = s;
}
public XPagesScope getScope() {
return this.s;
}
}
public XspDataIterator getMyIterator() {
XspDataIterator iterator = (XspDataIterator) getScopeVariable(PageVariable.MY_ITERATOR);
return iterator;
}
public void setMyIterator(XspDataIterator iterator) {
setScopeVariable(PageVariable.MY_ITERATOR, iterator);
}
...
In this specific instance I declared only one enum, MY_ITERATOR
, but I can declare as many variables as I want and with whichever scope they need to live in.
The enum takes an argument that sentences which scope the variable will be stored in. If the argument is not provided the code assumes it’s a request scoped variable.
The XPage code snippet:
<xp:repeat id="repeatMyIterator" binding="#{ctrl.myIterator}"
value="#{ctrl.data}" var="row"
disableOutputTag="true">
...
</xp:repeat>