The MysteryCoder has written up a little article discussing one often missed feature in Rails – Tapestry style components.
In it he discusses some of the features he misses in WebObjects/Tapestry style components such as re-usable view logic, component composition and binding parameters.
I know another rails developer (who I’ll leave anonymous to save him from the shame of being associated with java
) that also wanted a way to create Tapestry style components in Rails but I’ve not heard him mention that side project again so I’m assuming it still hasn’t been done.
Does anyone know of any ruby projects that might help save MysteryCoder some time / effort before he gets too far trying to develop something like this? (or reasoning that shows how Rails doesn’t need this particular component feature?)
Not knowing where else to announce it I thought I should mention that version 2.7.2 of OGNL was quietly released yesterday and is now available via ibiblio. Special thanks to Toby Tmjee for his recent contributions and help on the project.
The number of issues being reported related to expression compilation seems to have gone way down – so it may tentatively be safe to say this feature is “becoming stable”.
The javacc grammar parser code was also re-generated for this recent release using some of the new improvements that Tom Copeland mentions here.
As I’ve not really done a good job posting updates about releases I’ll go ahead and dump the full 2.7 – 2.7.2 jira issue log here as well. The good majority of issues fixed have been related to the expression compiler work – but there is still a lot of good stuff in there that projects using it without expression compilation will still find very useful. (from straight up bug fixes to substantial performance / concurrency improvements and even full Java 5 support for generics and varargs)
Release Notes – OGNL – Version 2.7.2
Bug
- [OGNL-80] – CastCastException when setting properties on objects that use generics in superclass properties
- [OGNL-121] – Race condition in SimpleNode#evaluateGetValueBody(OgnlContext, Object)
- [OGNL-122] – OGNL Double to BigDecimal type conversion
- [OGNL-124] – When OgnlException is wrapped in another exception, any exception wrapped by the OgnlException appears to be swallowed
- [OGNL-125] – When OgnlException is wrapped in another exception, any exception wrapped by the OgnlException appears to be swallowed
- [OGNL-126] – Don’t call setter properly
- [OGNL-127] – can’t find methods with varargs parameter
- [OGNL-128] – remainder expression doesn’t look for child syntax expressions
- [OGNL-129] – Collision property and method with same name
- [OGNL-130] – Array syntax error
- [OGNL-134] – primitive character conversion in statement compilation
- [OGNL-136] – Ignore synthetic methods when using getDeclaredMethods()
- [OGNL-141] – Very serious OgnlRuntime scalability and concurrency bug in versions greater than 2.6.10
- [OGNL-142] – scope=provided on javassist dependency leads to NoClassDefFoundError
New Feature
- [OGNL-7] – Full Java 5 Support for OGNL
Task
- [OGNL-133] – bring back old OgnlContext.callMethod parameter
- [OGNL-137] – Port OGNL docs from ogn.org to OpenSymphony’s OGNL confluence space
Release Notes – OGNL – Version 2.7.1
Bug
- [OGNL-96] – object equality b0rken
- [OGNL-97] – Compile OGNL expressions often require #this
- [OGNL-98] – Simple ognl expressions like comparison “==” or divide “/” cause errors
- [OGNL-103] – Unable to find correct readMethod named is…()
- [OGNL-104] – object equality still broken
- [OGNL-105] – Compiled OGNL using bracket notation requires #this
- [OGNL-106] – Null Pointer Exception when parsing enum constant
- [OGNL-107] – CLONE -ClassCastException in ASTChain
- [OGNL-108] – Console Stack traces when using instanceof in OGNL
- [OGNL-110] – Subtracting or multiplying two doubles causes error in log, though the calculation is correct
- [OGNL-112] – Unable to find getter when multiple getters exist with similar naming
- [OGNL-113] – Object with null toString() causes NPE in OGNL
- [OGNL-114] – fails method name resolution for boolean JavaBean properties
Release Notes – OGNL – Version 2.7
Bug
- [OGNL-6] – When setting fields type conversion returning null falsly reports a NoSuchPropertyException
- [OGNL-9] – Cannot handle hivemind’s messages.format
- [OGNL-10] – Calling methods with parameters containing more calls ?
- [OGNL-11] – ClassCastException in ASTChain
- [OGNL-12] – expression compilation problem
- [OGNL-13] – Class loading issue with in OGNL 2.6.7+ when multiple classloaders
- [OGNL-14] – Ternary expression, NPE
- [OGNL-16] – Unable to parse OGNL expressio
- [OGNL-17] – OR expression compile error
- [OGNL-18] – bad array index selectedPresenters[index]
- [OGNL-19] – expression concatenated via “and” / “&&” is not evaluated correctly
- [OGNL-20] – expressions compilation complains about a null setter body
- [OGNL-21] – another “setter body: null ” error
- [OGNL-25] – Expression stop working in Tapestry 4.1.2
- [OGNL-26] – Try to access to the hidden class java.util.HashMap$Entry
- [OGNL-27] – Bug in new version of OGNL
- [OGNL-28] – CLONE -OR expression compile error
- [OGNL-29] – String concatenation of different types fails in ternary expression
- [OGNL-30] – NOT with OR fails
- [OGNL-31] – Caching problem when looping over different implementations of the same interface
- [OGNL-32] – Contatenation of single character string results in wrong outcome
- [OGNL-33] – problem evaluating an expression on an abstract class not implementing all methods of an implemented interface
- [OGNL-35] – CLONE -expression concatenated via “and” / “&&” is not evaluated correctly
- [OGNL-36] – Another “getter body: null setter body: null ” Error in combination with “||”
- [OGNL-37] – messages.format with 3 parameters causes ArrayIndexOutOfBoundsException
- [OGNL-38] – CLONE -NOT with OR fails
- [OGNL-39] – Ternary expression with date formatting causes Mismatched stack types error
- [OGNL-40] – Error appending strings
- [OGNL-41] – javassist CannotCompileException for Expression ” value || !okOnly “
- [OGNL-43] – getValue() not called on second parameter to && if the first returns true
- [OGNL-44] – Appending a Long, String, and int results in error
- [OGNL-46] – CLONE -Caching problem when looping over different implementations of the same interface
- [OGNL-47] – Using a property from an enum constant as a method argument fails
- [OGNL-48] – ognl string concatenation + static syntax does not render properly
- [OGNL-49] – VerifyError: wrong return type in function
- [OGNL-50] – Nullcheck with && and ! fails
- [OGNL-52] – setAccessible(false) threading bug
- [OGNL-53] – OR fails with boolean expression as first condition
- [OGNL-54] – Calling method of object and passing a ‘conditional’ expression as parameter
- [OGNL-55] – Calling method of object with String parameter
- [OGNL-56] – the NOT of complex expression fails
- [OGNL-57] – The compilation of expressions with negate symbol (!) causes javassist exception
- [OGNL-58] – Ternary that appends multiple types fails
- [OGNL-59] – Target is null for method
- [OGNL-60] – messages.format with one parameter on a component fails
- [OGNL-61] – Method call gets some (javassist?) code fragment passed as argument instead of the evaluated expression
- [OGNL-62] – Boolean property with is() and toggle() methods causes failsafe error
- [OGNL-63] – IllegalArgumentException
- [OGNL-64] – Appending a Long with dot notation, a String, and an int creates failsafe error
- [OGNL-65] – OR expression with && and comparisons causes failsafe error
- [OGNL-66] – Ternary evaluates unused expression
- [OGNL-67] – Invalid Types error for inequality operator (!=) when used in Ternary Expression
- [OGNL-69] – Tapestry Exception with a map object
- [OGNL-70] – CLONE -Ternary evaluates unused expression
- [OGNL-72] – Wrong return type in function
- [OGNL-73] – Ternary evaluates unused expression with date formatting
- [OGNL-74] – Error in ASTProperty when running in JDK1.4
- [OGNL-75] – Ognl Exception source is null for getProperty(null, “mapKey”) when using split on a map
- [OGNL-76] – Iterating over an Object Array in a For causes NoClassDefFoundError
- [OGNL-77] – javassist classname error
- [OGNL-78] – Appending strings in ternary causes failsafe error
- [OGNL-81] – Boolean expression not evaluated
- [OGNL-82] – java.lang.Integer.valueOf() failling in 1.4 jre
- [OGNL-83] – Can’t get object properties returned from Map
- [OGNL-84] – Indexed expressions (“prop[index]“) do not lookup for the getProp(int index) method in the right class
- [OGNL-85] – constructor signature matching problem (int <-> java.lang.Integer)
- [OGNL-86] – use of incorrect expression root object in some arithmetic expressions
- [OGNL-87] – Get an ognl.InappropriateExpressionException when negating a boolean
- [OGNL-89] – expression compilation problem
- [OGNL-90] – cannot create empty list using {}
- [OGNL-91] – compilation problem in case of minus operator
- [OGNL-92] – “incompatible array types” with enum values
- [OGNL-93] – expression compilation problem
- [OGNL-94] – Tacos:Tree does not work with the current snapshot
Improvement
There, I said it. I don’t know about you, but every time I read another article where someone touts their java web framework for its likeness to programming in Swing I want to vomit all over my monitor – and then the person doing the touting.
Swing? …Really?
Before I make all Swing developers / lovers hate me I should say that there are many nice things about Swing as well, and some very clever people doing really cool stuff with it – but it has a number of hateful warts to it as with any technology…and this is before you bring the abstraction to web applications. (which have slim to no correlation to desktop applications)
What’s the worst part about Swing programming for me personally? The layout managers…sigh….Yeah, you know exactly what I’m talking about. GridBag#$@#$# damnit! Where are the rendering hints yo? Signal/slot connections? (it’s a pity the closure stuff wasn’t there in the beginning – function pointers are useful sometimes)
So…with that all in mind – what is the most important end-product that a web based framework should probably make pretty damn important? HTML! Yes, and…what does HTML dictate? Layout / content / everything.
What kind of framework makes HTML/javascript less important than your java code? The kinds that emulate Swing perhaps? I’m sorry but a “Panel” doesn’t do justice to all the nuances and behaviours possible with a block level HTML element.
This is one area that I don’t think enough people really appreciate / know about Tapestry. It really does care about your HTML and making managing it as easy / natural for you as possible. For instance, did you know that you can do stuff like this in a Tapestry html template, and that for the most part almost any component in the framework can automatically do this because it’s built in?
<ul class="items"> <li jwcid="@For" source="ognl:users" value="ognl:user" class="itemList view" style="margin-right: 10%"> <span jwcid="@Insert" value="ognl:user.name" /> </li> </ul>
The output from this example would pretty much look like this:
<ul class="items">
<li class="itemList view" style="margin-right: 10%">
Fred Smith
</li>
<li class="itemList view" style="margin-right: 10%">
Bob Johnson
</li>
</ul>
Did you notice how the css class and style attributes were written out exactly as I had typed them? And that the components involved know nothing about these attributes or that they’re being used? It’s a small thing I know, but it makes a big difference in every day development. It’s also a feature that doesn’t exist in a lot of web frameworks. Perhaps because they’d prefer to do it in java? (wtf is wrong with you?):
void someGodAwfulMethod(DomWriter dom) {
// i think in reality it's even harder than this, but I can't make myself do it even in pseudo code
for (User in getSource()) {
dom.writeSomeCrap("<li>").writeSomeMore(user.getName()).andMore("</li>");
}
} ..........or how about?
void paintMyHtml(Context context) {
ListPanel panel = new ListPanel("What were they thinking?");
for (User in getSource()) {
panel.addItem(new ListItem(user.getName()));
}
}
Those examples are contrived but are probably close enough to get the general picture. Want to edit that html just a little bit to exert some more control over it? Too bad. Want to just be able to layout your html using “html and css” of all things? Too bad. Better flex those fingers and get ready to write some more java code buddy. You do like writing Java code right? I mean, you enjoy the actual act of typing of lines and lines of code for the sure joy of it?
end of rant..
In a previous post I got a little excited about a new Aesop Rock album, but after digging around a little deeper I’ve figured out that I wasn’t as much of a fan of Aesop as the guy producing the album – Blockhead.
I haven’t been able to stop listening to his albums since discovering his music. The majority of them are purely instrumental and completely unique and engrossing. Nothing at all like the kind of hip hop you may be used to hearing on the radio.
It wasn’t surprising to find out that he also produced some work for another artist I like – Murs.
I guess I’m going through a sort of rediscovery-of-underground-hip-hop phase – but I’m so blown away by the quality of music these guys are creating that I thought I’d share.
You should also check out Blu & Exile if you get a chance.
Well well well..With some free time on my hands and a couple google searches later I’ve stumbled upon the roots of this whole “closures” debate fiasco.
Warning: I have nothing but respect for the people I am about to reference, and am probably slightly out of my league in discussing these features – but the debate seems so pointless and obvious that it deserves at least a quick note.
The debate seems to focus around this and this. The summary result of which was described well in Neal’s latest blog post example code snippets of the two:
/**
* An object with a function accepting pairs of objects, one of
* type T and one of type U, returning those of type V
*/
interface Combiner<T,U,V> {
V combine(T t, U u);
}
class ParallelArray<T> {
/**
* Returns a ParallelArray containing results of applying
* combine(thisElement, otherElement) for each element.
*/
<U,V> ParallelArray<V> combine(
ParallelArray<U> other,
Combiner<? super T, ? super U, ? extends V> combiner) { ... }
}
vs this:
class ParallelArray<T> {
/**
* Returns a ParallelArray containing results of applying
* combine(thisElement, otherElement) for each element.
*/
<U,V> ParallelArray<V> combine(
ParallelArray<U> other,
{ T, U => V } combiner) { ... }
}
You’ll notice in one definition we are forced to create a new type to represent the “closure”, while in the other the type information is bound using this new type syntax of “T, U => V”. Someone actually put this example up during a presentation and asked which people would prefer to see with a straight face.
So, the first solution is a watered down version of anonymous inner classes that sets out to provide closure-like functionality without hurting developers with new programming concepts – ie ” no new concepts to learn, just a more concise syntax for something they already do”.
I think there are lots of things that could be classified as bad in the first example. Let’s start a list:
- It isn’t a closure. (that tends to make things harder when trying to propose something that doesn’t qualify as the definition of the thing it is proposing to do)
- I’d argue that it actually does the opposite of what it strives to do – adds more confusion. Why do we need to define a new type for the thing we were trying to define in an interface already? How the hell does that make sense to people?
- It’s irresponsible. The definition of closures has been pretty well established in the programming community already, how are people going to carry that knowledge over to this new feature? What are our dynamic language friends going to say when they see us typing up our vs. 1 closures? They’re going to make fun of us is what they will do. Because it isn’t a closure and everyone knows it. One more nail in the coffin for the language. It’s embarassing.
I’ll admit that there are probably lots of pragmatic implementation concerns surrounding how hard it will be to implement the second version in the jdk – but it seems like with something as important as a language level feature the old saying “if you aren’t going to do something right, don’t do it at all” really applies. At least if your interest is in furthering the shelf life of this language and not applying a quick band aid that will quickly peel off at the first sign of water/trouble.
For a long time now I’ve very badly wanted to work for the goog, but my physical location(washington d.c.) has pretty much elminated that possibility. The recruiters have made it very clear that working for google means moving to CA. It’s such torture looking around at work in this area and hearing about all the fun things the google engineers are working on – like Android (have I mentioned that I have some experience with arm based linux systems?..). I mean wtf, who else is working on as many even remotely interesting things as they are?
This assumes of course that they would even hire me, which is just another small torture to live with. Don’t get me wrong, I like CA and everything. I did spend a few years in that general area and grew up in southern ca…It’s the wife and family thing. Not that I don’t like her parents, they just don’t happen to currently be interested in moving to CA and so here we are.
I did recently discover that Sergey actually grew up in the same area – even attended a montessori school like my daughter does. Don’t his parents miss him hanging out over in CA so much? Aren’t you worried that the mild CA climate is making you soft? Not that the winters have been very wintery here for a few years anyways..
There are certainly enough engineers here to start a small / modest development group of some sort isn’t there? Maybe we can rent a single small room in a shared office space as the start of the new google d.c. group? I’m not picky.
Well anyways, back to work. I hear there are lots of fun jobs working for the government or various research groups. (shudders)
Latest Entries
- script to vacuum os x sqlite databases
- updated foxylicious extension for Firefox 3
- how to fix butt ugly ubuntu hardy heron fonts
- Where are our java leader’s opinions on closures?
- Tapestry 4.1.5 Released && various Tacos project releases (like Seam / jQuery support)
- painting by numbers, or how html cowards hide behind CSS
- Rails component envy
- OGNL 2.7.2 Released
- news flash – Swing is a terrible API to emulate in web development
- hip hop is neat