el-next@uel.java.net

Re: Making EL easier to use

From: Kin-man Chung <Kin-Man.Chung_at_Sun.COM>
Date: Fri, 19 Feb 2010 14:52:49 -0800

On 02/19/10 12:04, Jason Porter wrote:
> On Fri, Feb 19, 2010 at 12:37, Kin-man Chung <Kin-Man.Chung_at_sun.com> wrote:
>> To decide what we should discuss first, I think we should put down in
>> a page the issues and requests, and pick the topics that are more
>> important or basic. It can be more effective with wikis pages. For
>> now, let me just pick a topic. If you have other topic that need to
>> be covered first, let's have them too!
>
> Not first, but at least so it's on the board (I think we pretty much
> all agree on these two) better performance and Java 5 features such as
> Enum resolution.
>
I think Enum names resolution is on the list.

>> Let's start our discussion on making EL easier to use, especially
>> when used outside of JSP or JSF. Let me just copy Dan;s writeup on
>> this here. I added the item numbers for the ease of reference.
>>
>> Item 1: Bootstrapping the ELContext (P1)
>>
>> Current the ELContext is created in the UI layer, either by JavaServer Faces
>> or JSP. However, EL is an essential part of the Java EE programming model.
>> It would make a lot more sense if the ELContext would be created at the
>> start of the request so that components such as filters, custom servlets and
>> third-party frameworks could access the EL. Currently, it's necessary to
>> manually construct an EL context if an expression needs to be resolved
>> outside of JSF or JSP.
>>
>> What we are looking for is something similar to the bootstrap that was
>> introduced for Bean Validation. Like Bean Validation, EL transcends the
>> layers of the programming model and should therefore be universally
>> accessible.
>>
>> Item 2: Simplifying the expression evaluator API (P1)
>>
>> It's way too complicated to resolve an EL expression. If you think about it,
>> the task is quite simple. Take an expression string and get a result. We
>> need to make the API as simple as the task.
>>
>> Part of the problem with the Unified EL is that just trying to figure out
>> what you need to actually resolve an expression is a nightmare. It breaks
>> down into three parts:
>>
>> * ELContext - Simply put, To evaluate an Expression, an ELContext must be
>> provided. A real bitch.
>> * ExpressionFactory - Needed to create a ValueExpression or
>> MethodExpression from a string
>> * ELResolver - The thing that actually parses the expression and
>> deferences its parts; each job is handled by a different resolver (one being
>> to find CDI beans by name) and those resolvers are wrapped in a resolver
>> which is a chain of resolver
>>
>> What isn't provided is a simple API to just take an expression and get a
>> result from it.
>>
>>
>> I think these two items are related, so let's talk about item 1 first.
>> There are actually two parts to this item:
>>
>> 1.1. In a web container, how can one obtain an instance of ELContext
>> when the request is first created?
>>
>> 1.2. In a non-web context, how to bootstrap the ELContext?
>>
>> Let tackle 1.2 first, since it may influence how 1.1 is solved.
>>
>> We can do something similar to bootstrap API in Bean Validation, but it
>> still remains a fact that components of a ELContext, such as ELResolver
>> need to be specified somehow. We can, for instance, have a default
>> ELResolver that includes the common ELResolvers, such a BeanELResolver
>> etc, but user must still need to be able to use a map to resolve his/her
>> bean. For instance, in the expression #{foo.bar.baz}, s/he can rely on
>> the default ELResolver to resolve the operator ".", but s/he must
>> still tell us how foo should be resolved.
>
> Bean registration with the resolver is something I was thinking about
> the other day because Ed had mentioned how nice it would be to use EL
> everywhere (+1 from me as well). Would we want resolution for all
> classes, or only managed classes? If it were all classes then what was
> done with CDI and the default name would seem to work (unless you had
> classes with the same name but in a different package, then we run
> into complications).

I am not familiar with how CDI's default name works. Can you give me
a brief description? Thanks.

Perhaps a discussion on what classes are
> available for resolution is needed. If it's only managed classes then
> we're kind of back to square one unless there's a way to obtain all
> the managed classes from the various environments.
>
But even with managed beans, we can still provide simpler APIs for
plugging them in, see below.

>> I already have ExpressionFactory. Can we combine it with ELContext,
>> to make things simpler?
>
> I'm all for simplifying the API as much as possible. One of the
> things we could do to help maintain backwards compatibility and still
> make it simple for the use case outside of the view layer is to
> provide a shortcut entry point. The shortcut would have to use a
> context that's already been started and have a valid ELResolver but
> something as simple as ExpressionFactory.parse(String) or possibly
> ExpressionFactory.parse(String, returnType) would probably go a long
> way into making EL easier to use outside of a managed context.
>
Right.

For managed beans, we can provide a simpler way for resolving them
without the need for a ELResolver. Something along the following
lines.

     Map myBeans; // User managed beans;
     ExpressFactory fact = ExpressFactory.newInstance();
     // Plug a collectons of beans into the default ELResolver
     fact.addBeans(myBeans);
     // Or to add a bean
     fact.addBean("emplyee100", new Employee("Joe Smith"));
     String result = fact.evaluate("${employee100.name}");

This would really simplify things, especially for common use cases.

-Kin-man

>> I think this would probably be enough to start the discussion. :-)
>>
>> -Kin-man
>>
>