Hi there folks!
even though this blog is pretty much dead as I'm a happy Grails developer now from time to time friends keep sending me links to other blogs about JSF and its nightmares.
Today I've been given this link:
http://www.dzone.com/links/r/top_10_reasons_why_i_dont_like_jsf.html
I think the author is way to polite but he's got the main issues nicely laid out.
Good job, Bruno!
Sunday, December 12, 2010
Sunday, July 11, 2010
This is the end!
Hi all,
this is the final post on this blog. My adventure with JSF has finally come to an end. No more nonsenses, no more pain...
I'm working with Ruby on Rails and Grails now and I strongly recommend if you're not a total convert as of now to start learning those platforms ASAP. You'll see life having a new, better taste and a whole new meaning!
A big thanks to all of you who posted comments, visited my blog and linked to it. Thanks!
Rust in Peace JSF!
this is the final post on this blog. My adventure with JSF has finally come to an end. No more nonsenses, no more pain...
I'm working with Ruby on Rails and Grails now and I strongly recommend if you're not a total convert as of now to start learning those platforms ASAP. You'll see life having a new, better taste and a whole new meaning!
A big thanks to all of you who posted comments, visited my blog and linked to it. Thanks!
Rust in Peace JSF!
Tuesday, June 1, 2010
Custom Components strike back!
Hi all you JSF haters! Here's yet another heresy about writing JSF components you might want to know before you step into the ugly world of creation of reusable parts.
First of all if there's someone you know that knows for a fact that writing custom components is easy please direct that person to me so we can shed some light on why he/she things so. In my opinion having a 32 pages long manual just to achieve the simplest possible result (like this one) is just plain crazy. Please note that all this component does is it can show/hide itself from the resulting HTML, it can "bind" itself to a server-side bean and has a handful of properties most of which contradict with the actual well-known attribute names from HTML (for example styleClass where the well-known name for this is simply class).
Secondly one needs to notice that beautiful picture on page 10 that shows the necessary bits and pieces to make it work. Actually it shows the "simplified" version without separate renderers!
So what we need to have is 2 classes (the so called "Tag" class and the actual "Component" class) and 2 xml files (one being a tag library descriptor and the other one being the faces-config.xml).
Oh! And btw if you're wondering if they made any progress on that one in JSF 2.0 I rush to explain that they didn't! They only switched from the tag library descriptor to Facelets descriptor which has pretty much the same content, just more catchy name!
After going through the painful, unrefactorable xml bush we're presented with the powerful class model that we need to work with.
At this stage I really need to ask this question: was it really so damn hard to implement a pass-through for arguments??? I mean, come on guys! It's like stone age compared to what's available in other frameworks.
Back to classes...
The TickerTag class begins pretty simple - a field, getter, setter,... and then - the setProperties and release methods. "setProperties - what's that" you might ask. Well my friend, the fact of having a getter and setter is just not enough to make it work! You need a separate method that again contains some non-refactorable code simply to use it in the actual component tag... It doesn't get any worse than that, really...
But anyway... Let's see how we can implement the famous binding to bean properties!
In setProperties there's an if-statement to decide if it really _is_ a binding or a value. That thing could have been done one level down and not force the component writers to do this crazy check all over the place. One might ask at this point that since we're already storing the value why not re-use that in the actual code so that we don't multiply the instance of our values (once in the backing bean and once in the actual component itself). Well - keep askin'! That's simply how things are - period.
JSF component creation is a literal pain in the a$$. The actual model is plain stupid, does not provide an easy way to do simple things and requires one to write tons of stuff, possibly wrong at first (that's when nothing works). By comparison the model for creation user controls in ASP.NET is easier because every component is just a class that inherits from some other class (UserControl to be precise) and has both parts (the composition from other controls and custom rendering) simply built in. It is so easy that if you once go ASP.NET you'll never go back (at least not to JSF).
Back to reality - meaning to JSF :)
Beyond the simple, 32 pages long tutorial there are topics that are way more complicated like processing user input or action components. If you have the guts to go there please share your experience with the rest of us because the amount of tutorials and walk-throughs out there is just not enough.
First of all if there's someone you know that knows for a fact that writing custom components is easy please direct that person to me so we can shed some light on why he/she things so. In my opinion having a 32 pages long manual just to achieve the simplest possible result (like this one) is just plain crazy. Please note that all this component does is it can show/hide itself from the resulting HTML, it can "bind" itself to a server-side bean and has a handful of properties most of which contradict with the actual well-known attribute names from HTML (for example styleClass where the well-known name for this is simply class).
Secondly one needs to notice that beautiful picture on page 10 that shows the necessary bits and pieces to make it work. Actually it shows the "simplified" version without separate renderers!
So what we need to have is 2 classes (the so called "Tag" class and the actual "Component" class) and 2 xml files (one being a tag library descriptor and the other one being the faces-config.xml).
Oh! And btw if you're wondering if they made any progress on that one in JSF 2.0 I rush to explain that they didn't! They only switched from the tag library descriptor to Facelets descriptor which has pretty much the same content, just more catchy name!
After going through the painful, unrefactorable xml bush we're presented with the powerful class model that we need to work with.
At this stage I really need to ask this question: was it really so damn hard to implement a pass-through for arguments??? I mean, come on guys! It's like stone age compared to what's available in other frameworks.
Back to classes...
The TickerTag class begins pretty simple - a field, getter, setter,... and then - the setProperties and release methods. "setProperties - what's that" you might ask. Well my friend, the fact of having a getter and setter is just not enough to make it work! You need a separate method that again contains some non-refactorable code simply to use it in the actual component tag... It doesn't get any worse than that, really...
But anyway... Let's see how we can implement the famous binding to bean properties!
In setProperties there's an if-statement to decide if it really _is_ a binding or a value. That thing could have been done one level down and not force the component writers to do this crazy check all over the place. One might ask at this point that since we're already storing the value why not re-use that in the actual code so that we don't multiply the instance of our values (once in the backing bean and once in the actual component itself). Well - keep askin'! That's simply how things are - period.
JSF component creation is a literal pain in the a$$. The actual model is plain stupid, does not provide an easy way to do simple things and requires one to write tons of stuff, possibly wrong at first (that's when nothing works). By comparison the model for creation user controls in ASP.NET is easier because every component is just a class that inherits from some other class (UserControl to be precise) and has both parts (the composition from other controls and custom rendering) simply built in. It is so easy that if you once go ASP.NET you'll never go back (at least not to JSF).
Back to reality - meaning to JSF :)
Beyond the simple, 32 pages long tutorial there are topics that are way more complicated like processing user input or action components. If you have the guts to go there please share your experience with the rest of us because the amount of tutorials and walk-throughs out there is just not enough.
Thursday, April 22, 2010
RichFaces - "beautiful" code
I'm extending the rich:calendar control today trying to put its definition into a table (for reasons that are not important here). The outcome should be as easy as input in one cell and the icon in another. Sounds easy, right?
Nothing could be further from the truth!
How I'd envision generation of HTML in such a case would be a container class having things like name, attributes collection, possibly even child controls (if it's a container for other controls) with one method "render(where...)" that would make use of those contained properties.
But it turns out that the guys from RichFaces didn't get the memo, that code duplication is bad. In fact they missed it so much that getting the whole thing to do what I want it to do takes a copy and paste, then refactoring and at the end implementation of the stuff I need.
Here's an example of how the render for example attributes of a control:
getUtils().writeAttribute(writer, "accesskey",
component.getAttributes().get("accesskey"));
getUtils().writeAttribute(writer, "class", "rich-calendar-input " +
convertToString(component.getAttributes().get("inputClass")));
getUtils().writeAttribute(writer, "disabled",
variables.getVariable("disabled"));
getUtils().writeAttribute(writer, "id",
convertToString(clientId) + "InputDate");
getUtils().writeAttribute(writer, "maxlength",
component.getAttributes().get("maxlength"));
getUtils().writeAttribute(writer, "name",
convertToString(clientId) + "InputDate");
getUtils().writeAttribute(writer, "onblur",
component.getAttributes().get("oninputblur"));
getUtils().writeAttribute(writer, "onchange",
component.getAttributes().get("oninputchange"));
getUtils().writeAttribute(writer, "onclick",
component.getAttributes().get("oninputclick"));
getUtils().writeAttribute(writer, "onfocus",
component.getAttributes().get("oninputfocus"));
getUtils().writeAttribute(writer, "onkeydown",
component.getAttributes().get("oninputkeydown"));
getUtils().writeAttribute(writer, "onkeypress",
component.getAttributes().get("oninputkeypress"));
getUtils().writeAttribute(writer, "onkeyup",
component.getAttributes().get("oninputkeyup"));
getUtils().writeAttribute(writer, "onmouseout",
component.getAttributes().get("oninputmouseout"));
getUtils().writeAttribute(writer, "onmouseover",
component.getAttributes().get("oninputmouseover"));
getUtils().writeAttribute(writer, "onselect",
component.getAttributes().get("oninputselect"));
getUtils().writeAttribute(writer, "size",
component.getAttributes().get("inputSize"));
getUtils().writeAttribute(writer, "style",
"vertical-align: middle; " + convertToString(component.getAttributes().get("inputStyle")));
getUtils().writeAttribute(writer, "tabindex",
component.getAttributes().get("tabindex"));
getUtils().writeAttribute(writer, "type",
variables.getVariable("type"));
getUtils().writeAttribute(writer, "value",
getInputValue(context, component));
I mean who does that in the 21th century in an object-oriented programming language?!?!?!?!?
Here's another example of pure madness:
writer.writeText(convertToString(
"dayListTableId: '" +
convertToString(clientId) +
"Day', \n weekNumberBarId: '" +
convertToString(clientId) +
"WeekNum', \n weekDayBarId: '" +
convertToString(clientId) +
"WeekDay',\n currentDate: " +
convertToString(getCurrentDate(context, component, currentDate)) +
", \n selectedDate: " +
convertToString(getSelectedDate(context, component)) +
", \n datePattern: '" +
convertToString(component.getDatePattern()) +
"',\n jointPoint: '" +
convertToString(component.getJointPoint()) +
"',\n direction: '" +
convertToString(component.getDirection()) +
"',\n boundaryDatesMode:'" +
convertToString(component.getBoundaryDatesMode()) +
"',\n popup: " +
convertToString(component.isPopup()) +
",\n enableManualInput: " +
convertToString(component.getAttributes().get("enableManualInput")) +
",\n showInput: " +
convertToString(component.getAttributes().get("showInput")) +
",\n disabled: " +
convertToString(component.isDisabled()) +
",\n readonly: " +
convertToString(component.getAttributes().get("readonly")) +
",\n ajaxSingle: " +
convertToString(component.getAttributes().get("ajaxSingle")) +
",\n verticalOffset:" +
convertToString(component.getVerticalOffset()) +
",\n horizontalOffset: " +
convertToString(component.getHorizontalOffset()) +
",\n style:'z-index: " +
convertToString(component.getAttributes().get("zindex")) +
"; " +
convertToString(component.getAttributes().get("style")) +
"',\n firstWeekDay: " +
convertToString(getFirstWeekDay(context, component)) +
", \n minDaysInFirstWeek: " +
convertToString(getMinDaysInFirstWeek(context, component)) +
",\n todayControlMode:'" +
convertToString(component.getAttributes().get("todayControlMode")) +
"',\n showHeader:" +
convertToString(component.getAttributes().get("showHeader")) +
",\n showFooter:" +
convertToString(component.getAttributes().get("showFooter")) +
",\n showWeeksBar:" +
convertToString(component.getAttributes().get("showWeeksBar")) +
",\n showWeekDaysBar:" +
convertToString(component.getAttributes().get("showWeekDaysBar")) +
",\n showApplyButton:" +
convertToString(component.getAttributes().get("showApplyButton")) +
",\n resetTimeOnDateSelect:" +
convertToString(component.getAttributes().get("resetTimeOnDateSelect")) +
",\n defaultTime:" +
convertToString(getPreparedDefaultTime(component))), null);
Finally please note that both fragments come from the same single method and that's just a fraction of that method!
Now you tell me: would you ever use stuff that looks like that underneath the skin?
Nothing could be further from the truth!
How I'd envision generation of HTML in such a case would be a container class having things like name, attributes collection, possibly even child controls (if it's a container for other controls) with one method "render(where...)" that would make use of those contained properties.
But it turns out that the guys from RichFaces didn't get the memo, that code duplication is bad. In fact they missed it so much that getting the whole thing to do what I want it to do takes a copy and paste, then refactoring and at the end implementation of the stuff I need.
Here's an example of how the render for example attributes of a control:
getUtils().writeAttribute(writer, "accesskey",
component.getAttributes().get("accesskey"));
getUtils().writeAttribute(writer, "class", "rich-calendar-input " +
convertToString(component.getAttributes().get("inputClass")));
getUtils().writeAttribute(writer, "disabled",
variables.getVariable("disabled"));
getUtils().writeAttribute(writer, "id",
convertToString(clientId) + "InputDate");
getUtils().writeAttribute(writer, "maxlength",
component.getAttributes().get("maxlength"));
getUtils().writeAttribute(writer, "name",
convertToString(clientId) + "InputDate");
getUtils().writeAttribute(writer, "onblur",
component.getAttributes().get("oninputblur"));
getUtils().writeAttribute(writer, "onchange",
component.getAttributes().get("oninputchange"));
getUtils().writeAttribute(writer, "onclick",
component.getAttributes().get("oninputclick"));
getUtils().writeAttribute(writer, "onfocus",
component.getAttributes().get("oninputfocus"));
getUtils().writeAttribute(writer, "onkeydown",
component.getAttributes().get("oninputkeydown"));
getUtils().writeAttribute(writer, "onkeypress",
component.getAttributes().get("oninputkeypress"));
getUtils().writeAttribute(writer, "onkeyup",
component.getAttributes().get("oninputkeyup"));
getUtils().writeAttribute(writer, "onmouseout",
component.getAttributes().get("oninputmouseout"));
getUtils().writeAttribute(writer, "onmouseover",
component.getAttributes().get("oninputmouseover"));
getUtils().writeAttribute(writer, "onselect",
component.getAttributes().get("oninputselect"));
getUtils().writeAttribute(writer, "size",
component.getAttributes().get("inputSize"));
getUtils().writeAttribute(writer, "style",
"vertical-align: middle; " + convertToString(component.getAttributes().get("inputStyle")));
getUtils().writeAttribute(writer, "tabindex",
component.getAttributes().get("tabindex"));
getUtils().writeAttribute(writer, "type",
variables.getVariable("type"));
getUtils().writeAttribute(writer, "value",
getInputValue(context, component));
I mean who does that in the 21th century in an object-oriented programming language?!?!?!?!?
Here's another example of pure madness:
writer.writeText(convertToString(
"dayListTableId: '" +
convertToString(clientId) +
"Day', \n weekNumberBarId: '" +
convertToString(clientId) +
"WeekNum', \n weekDayBarId: '" +
convertToString(clientId) +
"WeekDay',\n currentDate: " +
convertToString(getCurrentDate(context, component, currentDate)) +
", \n selectedDate: " +
convertToString(getSelectedDate(context, component)) +
", \n datePattern: '" +
convertToString(component.getDatePattern()) +
"',\n jointPoint: '" +
convertToString(component.getJointPoint()) +
"',\n direction: '" +
convertToString(component.getDirection()) +
"',\n boundaryDatesMode:'" +
convertToString(component.getBoundaryDatesMode()) +
"',\n popup: " +
convertToString(component.isPopup()) +
",\n enableManualInput: " +
convertToString(component.getAttributes().get("enableManualInput")) +
",\n showInput: " +
convertToString(component.getAttributes().get("showInput")) +
",\n disabled: " +
convertToString(component.isDisabled()) +
",\n readonly: " +
convertToString(component.getAttributes().get("readonly")) +
",\n ajaxSingle: " +
convertToString(component.getAttributes().get("ajaxSingle")) +
",\n verticalOffset:" +
convertToString(component.getVerticalOffset()) +
",\n horizontalOffset: " +
convertToString(component.getHorizontalOffset()) +
",\n style:'z-index: " +
convertToString(component.getAttributes().get("zindex")) +
"; " +
convertToString(component.getAttributes().get("style")) +
"',\n firstWeekDay: " +
convertToString(getFirstWeekDay(context, component)) +
", \n minDaysInFirstWeek: " +
convertToString(getMinDaysInFirstWeek(context, component)) +
",\n todayControlMode:'" +
convertToString(component.getAttributes().get("todayControlMode")) +
"',\n showHeader:" +
convertToString(component.getAttributes().get("showHeader")) +
",\n showFooter:" +
convertToString(component.getAttributes().get("showFooter")) +
",\n showWeeksBar:" +
convertToString(component.getAttributes().get("showWeeksBar")) +
",\n showWeekDaysBar:" +
convertToString(component.getAttributes().get("showWeekDaysBar")) +
",\n showApplyButton:" +
convertToString(component.getAttributes().get("showApplyButton")) +
",\n resetTimeOnDateSelect:" +
convertToString(component.getAttributes().get("resetTimeOnDateSelect")) +
",\n defaultTime:" +
convertToString(getPreparedDefaultTime(component))), null);
Finally please note that both fragments come from the same single method and that's just a fraction of that method!
Now you tell me: would you ever use stuff that looks like that underneath the skin?
Wednesday, April 14, 2010
JSF - a component framework only the mother can love
Hi there,
this is another JSF nonsense - the component creation style.
I'm just sick an tired of going over the renderers that don't render anything, the component tags (like it's not enough to have just one of those guys)... I mean come on!!!
For those of you that say that JSF 2.0 make a difference I rush to clarify that it is so not true - the component model didn't change even a bit! What they added is Facelets which is what most people were already using anyway.
What's screwd though is that Facelets is a templating engine and they try to use it for component creation. That's grouse!!!
this is another JSF nonsense - the component creation style.
I'm just sick an tired of going over the renderers that don't render anything, the component tags (like it's not enough to have just one of those guys)... I mean come on!!!
For those of you that say that JSF 2.0 make a difference I rush to clarify that it is so not true - the component model didn't change even a bit! What they added is Facelets which is what most people were already using anyway.
What's screwd though is that Facelets is a templating engine and they try to use it for component creation. That's grouse!!!
Tuesday, July 14, 2009
Trinidad + Richfaces = Problem (solution)
Finally after 3 days of googling and a trial-and-error approach I've found out how to overcome the problem with links in a table being stripped from javascript code after an Ajax call (for example for pagination or sorting columns).
The answer to that is a4j:htmlCommandLink (instead of h:commandLink) inside an a4j:form (instead of h:form). Don't ask me why - it's to complex to describe the actual bits and pieces behind some sick concepts in those libraries. The final fact is that h:commandLink ain't working but the a4j:htmlCommandLink is. Period.
Later today I'll attach a working project with the solution. For now you're just going to have to trust me on that one :D
The answer to that is a4j:htmlCommandLink (instead of h:commandLink) inside an a4j:form (instead of h:form). Don't ask me why - it's to complex to describe the actual bits and pieces behind some sick concepts in those libraries. The final fact is that h:commandLink ain't working but the a4j:htmlCommandLink is. Period.
Later today I'll attach a working project with the solution. For now you're just going to have to trust me on that one :D
Monday, July 13, 2009
RichFaces 3.3.1 Bug
Another day got lost because of some guy trying to make things that work better. This time it's sorting of columns generated from list. All used to work until version 3.3.0.CR1 and then, all of the sudden, it stopped. You can click the damn header all you want and nothing happens.
Components involved: rich:dataTable and rich:columns
O my gosh how I hate those days...
Components involved: rich:dataTable and rich:columns
O my gosh how I hate those days...
Subscribe to:
Posts (Atom)