0

I added some functions to the JEXL engine wich can be used in the JEXL expressions:

Map<String, Object> functions = new HashMap<String, Object>();

mFunctions = new ConstraintFunctions();
functions.put(null, mFunctions);
mEngine.setFunctions(functions);

However, some functions can throw exceptions, for example:

public String chosen(String questionId) throws NoAnswerException {
        Question<?> question = mQuestionMap.get(questionId);
        SingleSelectAnswer<?> answer = (SingleSelectAnswer<?>) question.getAnswer();
        if (answer == null) {
            throw new NoAnswerException(question);
        }
        return answer.getValue().getId();
}

The custom function is called when i interpret an expression. The expression of course holds a call to this function:

String expression = "chosen('qID')";
Expression jexl = mEngine.createExpression(expression);
String questionId = (String) mExpression.evaluate(mJexlContext);

Unfortunetaly, when this function is called in course of interpretation, if it throws the NoAnswerException, the interpreter does not propagete it to me, but throws a general JEXLException. Is there any way to catch exceptions from custom functions? I use the apache commons JEXL engine for this, which is used as a library jar in my project.

WonderCsabo
  • 11,947
  • 13
  • 63
  • 105
  • It would be interesting to know how you are calling the method chosen(). Is it via an interface which exists in pre-existing code (e.g. some jar of JEXL) – Crickcoder Nov 17 '13 at 11:50
  • So you are basically calling `mExpression.evaluate()` and the caller needs to handle the kind of exception thrown by evaluate and not NoAnswerException. I think you can't achieve this unless you call `chosen()` directly or change the implementation inside JEXL jar. – Crickcoder Nov 17 '13 at 12:09

1 Answers1

1

After some investigation, i found an easy solution!

When an exception is thrown in a custom function, JEXL will throw a general JEXLException. However, it smartly wraps the original exception in the JEXLException, as it's cause in particular. So if we want to catch the original, we can write something like this:

try {
    String questionId = (String) mExpression.evaluate(mJexlContext);
} catch (JexlException e) {
    Exception original = e.getCause();
    // do something with the original
}
WonderCsabo
  • 11,947
  • 13
  • 63
  • 105