Hi,
here is another update on EL as part of message interpolation. We have been discussing and
reviewing the
pull request [1] and it looks imo quite good. However, there are still some questions and
concerns.
Let's have a look at string formatting. Right now it looks like this:
${string:format(locale, 'Max %s', max)}.
Note the parameter 'locale'. Basically we request that the Locale passed to
MessageInterpolator#interpolate is bound to the
EL context as well and that this locale is used when calling string:format. Under the hood
this will call String#format(Locale, String, Object...).
This ensures that the right Locale is used during formatting.
Obviously from a user point of view the 'locale' parameter is unnecessary and it
would be nicer to just call ${string:format('Max %s', max)}.
In this case we cannot just specify that String#format(String, Object…) is bound to the EL
context. Instead it would be up to the implementation
to bind another helper function to the context which would one way or the other
(ThreadLocal!?) get hold of the right Locale to use for formatting.
I guess my concern with this approach is that it introduces a bit of voodoo into the
solution and it is not as transparent than the first solution.
A final approach would be to abandon the static function call and specify that a
java.util.Formatter (instantiated with the right Locale) is bound to
the EL context. In this case we have an instance call which looks somewhat like this
${formatter.format('Max %s', max)}. This looks nice as well.
However, all three solutions have another caveat. None of the above works with the
reference implementation of EL. As far as I know that is
javax.el:javax.el-api:2.2.4 (API) and org.glassfish.web:javax.el:2.2.4 (IMPL). For the
first two solutions to work you need at least a different
implementation. The glassfish implementation does not allow the binding of vararg
functions (the spec itself does not explicitly mention vararg
functions, just that functions must be public static methods). With JBoss EL and JUEL [2]
the use of vararg functions works fine.
To make use of the java.util.Formatter approach even the EL API needs to be exchanged.
Turns out the API in this case also contains a fair amount
of code, including the code to invoke bean methods. javax.el:javax.el-api:2.2.4 has a TODO
in its code to handle vararg methods, but right now
it throws an exception. The solution for this is to use the JUEL API which handles varargs
method properly.
For me it has a bad aftertaste that the EL functionality we want to use within Bean
Validation is neither properly specified in the EL spec nor is it working in the
reference implementation. It s not even clear which specification we could reference.
JSR-341 is supposed to be a standalone specification for EL, but
it seems quite inactive and I am not sure whether it will be part of EE 7. In this case we
would have to reference EL as part of JSR-245 [4].
Short summary:
Which syntax is preferable?
#1 ${string:format(locale, 'Max %s', max)}
#2 ${string:format('Max %s', max)}
#3 ${formatter.format('Max %s', max)}
Do we mind that vararg function calls is not working in the EL reference impl?
--Hardy
[1]
https://github.com/beanvalidation/beanvalidation-spec/pull/41
[2]
http://juel.sourceforge.net/index.html
[3]
http://jcp.org/en/jsr/detail?id=341
[4]
http://jcp.org/aboutJava/communityprocess/final/jsr245/