el-next@uel.java.net

Re: Making EL easier to use

From: Jason Porter <lightguard.jp_at_gmail.com>
Date: Fri, 19 Feb 2010 16:35:24 -0700

On Fri, Feb 19, 2010 at 15:52, Kin-man Chung <Kin-Man.Chung_at_sun.com> wrote:
>
>
> 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.

In CDI the default @Named is the simple name of the class with the
first letter lower case.

> 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

It's not bad, and the only thing I don't like about it is having to
add the instances, but you'd either have to instantiate each class
when it's resolved and toss that instance into a cache or something or
come up with some way to 1) find the instances of the resolved class
and 2) figure out how to differentiate which instance the user wants
to use, neither of which (AFAIK) are easy to do.

If we create instances of the class upon resolution then we'd need to
control the lifetime of those classes. Without a context duration for
the class that's kind of arbitrary, especially in an SE environment (I
guess it could be the lifetime of a thread and that cache could be
something like a thread local cache of class instances?).

>>> I think this would probably be enough to start the discussion.  :-)
>>>
>>> -Kin-man
>>>
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: el-next-unsubscribe_at_uel.dev.java.net
> For additional commands, e-mail: el-next-help_at_uel.dev.java.net
>
>



-- 
Jason Porter
Real Programmers think better when playing Adventure or Rogue.
PGP key id: 926CCFF5
PGP fingerprint: 64C2 C078 13A9 5B23 7738 F7E5 1046 C39B 926C CFF5
PGP key available at: keyserver.net, pgp.mit.edu