Reputation: 2359
In a custom control there is this repeat control that refers to a column in a folder (not a view). The folder's default design can be changed in time, in combination with the custom control. So it could happen that the code of the custom control is newer than the design of the folder, and hence the design doesn't match and the XPage errors out.
What I specifically want is that the custom control handles errors related to a missing view/folder column or similar design errors. The error is to be reported somewhere, informing the user that he/she can activate something that will repair the situation.
I know how to trap JavaScript errors, unfortunately all column values are in Expression Language. I could recode them, of course, but I'd like to know if there's a better way.
In short: how can I trap Expression Language errors?
Upvotes: 1
Views: 646
Reputation: 10485
You can trap EL
language errors by adding your own VariableResolver
and your own PropertyResolver
. To do this, you have to create two Java classes:
The Variable resolver
package ch.hasselba.xpages.demo;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.el.EvaluationException;
import javax.faces.el.VariableResolver;
public class ELErrVariableResolver extends VariableResolver {
private final VariableResolver delegate;
public ELErrVariableResolver(VariableResolver resolver) {
delegate = resolver;
}
@Override
public Object resolveVariable(FacesContext context, String name) throws EvaluationException {
Object variable = null;
try{
variable = delegate.resolveVariable(context, name);
}catch( EvaluationException ee ){
addResolveErrMessage( context, name );
}
return variable;
}
public void addResolveErrMessage( FacesContext context , String name ){
FacesMessage msg = new FacesMessage();
msg.setSummary( "BAD EL! Variable '" + name + "' not found." );
msg.setSeverity( FacesMessage.SEVERITY_FATAL );
context.addMessage("BAD EL!", msg);
}
}
The Property resolver
package ch.hasselba.xpages.demo;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.el.EvaluationException;
import javax.faces.el.PropertyNotFoundException;
import javax.faces.el.PropertyResolver;
public class ELErrPropertyResolver extends PropertyResolver{
private final PropertyResolver delegate;
public ELErrPropertyResolver(PropertyResolver resolver) {
delegate = resolver;
}
@Override
public Class getType(Object paramObject1, Object paramObject2)
throws EvaluationException, PropertyNotFoundException {
Class c = null;
try{
c = delegate.getType(paramObject1, paramObject2);
}catch(Exception e){
addResolveErrMessage( FacesContext.getCurrentInstance(), paramObject1.toString() + "." + paramObject2.toString() );
}
return c;
}
@Override
public Class getType(Object paramObject, int paramInt)
throws EvaluationException, PropertyNotFoundException {
Class c = null;
try{
c = delegate.getType(paramObject, paramInt);
}catch(Exception e){
addResolveErrMessage( FacesContext.getCurrentInstance(), paramObject.toString() + "." + paramInt );
}
return c;
}
@Override
public Object getValue(Object paramObject1, Object paramObject2)
throws EvaluationException, PropertyNotFoundException {
Object c = null;
try{
c = delegate.getValue(paramObject1, paramObject2);
}catch(Exception e){
addResolveErrMessage( FacesContext.getCurrentInstance(), paramObject1.toString() + "." + paramObject2.toString() );
}
return c;
}
@Override
public Object getValue(Object paramObject, int paramInt)
throws EvaluationException, PropertyNotFoundException {
Object c = null;
try{
c = delegate.getValue(paramObject, paramInt);
}catch(Exception e){
addResolveErrMessage( FacesContext.getCurrentInstance(), paramObject.toString() + "." + paramInt );
}
return c;
}
@Override
public boolean isReadOnly(Object paramObject1, Object paramObject2)
throws EvaluationException, PropertyNotFoundException {
boolean c = false;
try{
c = delegate.isReadOnly(paramObject1, paramObject2);
}catch(Exception e){
addResolveErrMessage( FacesContext.getCurrentInstance(), paramObject1.toString() + "." + paramObject2.toString() );
}
return c;
}
@Override
public boolean isReadOnly(Object paramObject, int paramInt)
throws EvaluationException, PropertyNotFoundException {
boolean c = false;
try{
c = delegate.isReadOnly(paramObject, paramInt);
}catch(Exception e){
addResolveErrMessage( FacesContext.getCurrentInstance(), paramObject.toString() + "." + paramInt );
}
return c;
}
@Override
public void setValue(Object paramObject1, Object paramObject2,
Object paramObject3) throws EvaluationException,
PropertyNotFoundException {
try{
delegate.setValue(paramObject1, paramObject2, paramObject3);
}catch(Exception e){
addResolveErrMessage( FacesContext.getCurrentInstance(), paramObject1.toString() + "." + paramObject2.toString() );
}
}
@Override
public void setValue(Object paramObject1, int paramInt, Object paramObject2)
throws EvaluationException, PropertyNotFoundException {
try{
delegate.setValue(paramObject1, paramInt, paramObject2);
}catch(Exception e){
addResolveErrMessage( FacesContext.getCurrentInstance(), paramObject1.toString() + "." + paramInt );
}
}
public void addResolveErrMessage( FacesContext context , String name ){
FacesMessage msg = new FacesMessage();
msg.setSummary( "BAD EL! Property '" + name + "' not found." );
msg.setSeverity( FacesMessage.SEVERITY_FATAL );
context.addMessage("BAD EL!", msg);
}
}
Add the new resolvers to your faces-config.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config>
<application>
<variable-resolver>ch.hasselba.xpages.demo.ELErrVariableResolver
</variable-resolver>
<property-resolver>ch.hasselba.xpages.demo.ELErrPropertyResolver
</property-resolver>
</application>
</faces-config>
On your CC add a xp:messages
component to display your message (or change the error routine in the classes to add whatever you want.
Upvotes: 3
Reputation: 1667
In the custom control you can check if the folder/view you are going to work with is correct. Aka has the correct design. This can be done in the beforepageload event. When the design check reports an error it should be written to a log file and a 'nice' message should be displayed to the user.
The error logging could be done with the various logging projects on openntf like xlogger When your code reports an error you can than set a scoped value called 'displayRepeat' to false. The repeat control ( and other controls ) should be rendered according to this displayRepeat value.
To display the nice error message to the user. Place a errors control on the top of your control and add the following code:
facesContext.addMessage( null,
new javax.faces.application.FacesMessage( "your error message" ) );
Upvotes: 2