|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Jacob Hookom's BlogNovember 2006 ArchivesExtending EL SyntaxPosted by jhook on November 27, 2006 at 02:08 AM | Permalink | Comments (6)I've been working a bit on extending EL, but found that the API is missing a few features desired to fully make the language pluggable by third parties. First is method invocations. Caching reflected data is so difficult to do without causing some kind of memory leak. I really wish JSE had some kind of ClassLoader listener API as a safer alternative to statically scoped data in web containers. Maybe others have more experience in this area? Anyways, performance of method invocation is pretty fast, it takes the same time to do To be safe, I did add some logic for finding the best match if there are multiple methods with the same name. Tis better than nothing :-) The more important addition is projections: Projections are useful in the presentation tier for binding sets of properties instead of requiring two parts: items="#{a}" var="v", value="#{v.b}". Actually, it may be more performant with the equivalent projection if you were to do: items="#{a.{x|x.b}}" var="v", value="#{v}". Anyways, there's a subtle difference in my implementation of projections as opposed to others. Here's our model: A company has many departments, which have many employees. If I wanted to generate a list of employee names, I would do something like this:
The OGNL equivalent is a little lighter in syntax:
..but produces a List of a List of Strings:
That's not what we wanted! With the EL implementation, you instead get:
Which seems more correct to me. The main reason is that EL is supposed to represent pointers to instances, so if I take the pointer (ValueExpression) and call the setValue on it-- I would expect that my target (each employee's name) would be set. So why would I return a List of Lists then? Another cool feature of projections under the EL-API is the use of MethodExpressions. MethodExpressions work perfectly for hooking into Framework APIs as JSF has with generic actions, validators, etc. So lets say your backing model had a collection of Validators, but you didn't want to express each one separately?
What I'd really like to see added to the EL-API though is pluggable type conversion and method invocation. Right now you can plug in your own property resolution, but the strange thing is that if you take the expression #{a.b} as a value, you can customize the resolution of (b), but if you take it as a method, then you cannot customize the resolution of (b), so the method must always exist on that instance in accordance with the EL implementation's rules. To correct these two missing pieces, I would like to see two methods added to the ELResolver API which allow near everything to be customized with:
The execution of these methods would work the same as the other ELResolver methods, requiring the propertyResolved to be set to 'true'. It'd be great then to allow customized extensions of Iterable/Collections/Maps such that one could do:
Which would call into the ELResolver chain with the following:
This would allow you to treat closures as value-types for some pretty extreme customization with mixing your own Java code into the execution of 'inlined' EL without requiring full API changes within the JSE. Basically, these are just some future ideas for EL, whenever it becomes it's own JSR. With Facelets and custom EL-API implementations, such as this one, you can just set one property on the compiler and away you go with the added features. (I have to start releasing stuff again) Trying out NetBeans 5.5Posted by jhook on November 26, 2006 at 02:49 PM | Permalink | Comments (11)I use Eclipse both at home and at work, but finally decided to give NetBeans a spin. Overall, the IDE is solid, but some of the features seem too 'literal'. For lack of a better word, let me use an example instead. When I'm writing test cases, I'll constantly comment and uncomment lines. Instead of providing one comment toggle control, NetBeans has two different ones:
Two things: does T and D have anything to do with the noun 'comment', and why isn't the IDE smart enough to do this with one command? Consequently, running the comment command multiple times will keep on adding more '//' to the beginning of your lines. Great. Hotkeys aside, I'll always try to right click to find associated features. This is fairly confusing in NetBeans for common tasks such as implementing abstract methods or generating bean accessors. When you are writing APIs and deal with inner classes, this only adds additional confusion with the IDE. Right-clicking on a Class, under the Refactor sub-menu, you are presented with a list of options for all Java types-- including: Extract Method and Change Method Parameter types-- what does that have to do with a Class declaration? Feel free to pick these options, but you will be presented with an error. If I'm declaring a new class, or add an additional abstract method, why can't I right-click and implement those methods. Yes, the option is on the top menu, under 'Source', but I'm concerned with the context of my cursor in the code-- may it be a method or class file, not 'mousing' away from it to the top menu under 'Source'. Finally, many of the options around refactoring are always forced into a review dialog before committing the changes. If I want to generate getters and setters, and select the fields I want, why always force me to review in a second dialog? I've gotten caught off guard so many times because that bottom pane has everything loaded into it for output, junit results, etc. Clicking on 'next' in the pop-up dialogs, closes the dialog, then adds yet another tabbed panel to the bottom with the next step to confirm what I just said I wanted to do. It seems unecessary and should be an optional flow-- and even if I wanted confirmation, why close the dialog and put the next step in another panel? Overall, NetBeans isn't bad. It's just not as intuitive as others I've used. It's still never obvious to me with what classes have errors and which ones don't without hitting the recompile button. EL ComparisonsPosted by jhook on November 16, 2006 at 12:28 PM | Permalink | Comments (12)Updated 11/17/2006 with JEXL and upgraded MVEL and added Serialized size I decided to test the following EL libraries available today:
Here's a table of features I thought were pertinent:
Pretty obvious things that stand out are that OGNL and MVEL have a lot more syntax features compared to the standardized EL. I think this is largely impart to the fact that EL was only intended for simple notation within the View counterparts and not as a scripting language. I will say that there's absolutely no reason why these other syntax features shouldn't be added to future releases. Pertaining to pluggability of syntax evaluation, OGNL is the most expressive with Method, Property, Index, etc. The new EL-API has similar capabilities for Property and Index Accessors with chainable ELResolvers. *Factory Cached means the API's factory method inherently cache expressions to some degree and do not re-parse on every call. API Use: Commons-EL
OGNL
MVEL
EL-RI
JEXL
Finally, I have some performance numbers at 10,000 iteration, average time in milliseconds:
*re-use means take the Expression returned from the factory and keep evaluating that instance instead of going back to the factory again. This didn't show much of a difference for those EL libraries that cache within their factories, but it did show a big improvement with OGNL and JEXL. Serialization can be important for some libraries and the EL-RI was optimized for use with JSF's state-saving architecture. I'm sure other frameworks may have similar concerns. Here are the sizes in bytes for the couple libraries that were actually Serializable.
Synchronization was another thing I wanted to test, but haven't yet. Supposedly OGNL has some unwanted synchronization blocks and JEXL has not been optimized at the Factory level at all-- putting a synchronization block around expression creation, with calls to commons-logging. In summary, here's just my observations from an afternoon of testing. While I'm not an expert on all of the libraries listed, feel free to comment on where I might have missed a point or gotten things wrong. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|