Thursday, August 02, 2007

A sad story about UIInput

Some questions are asked much more often than others. Let me tell you the story about one particular detail of JSF component life cycle. The reason why I decided that is is deserve to be in my blog is simple – I've being asked so many times about it, that it become ridiculous.

If you have no relation to Java Server Faces at all, than perhaps, you better skip entire story. But if you do have some JSF knowledge, you are welcome to continue!

So let me tell the story.

Imagine the situation when you have a page with some input. It can be any variation of input – text input, select or check-box, it is irrelevant. Let say it is plain text input and you need do the following:

  1. User can enter value to the input and it will be processed as usual.

  2. In addition to that user can select some pre-defined value. Or in any other way to assign some particular value to the input and than, be able to see this new value on screen. After this user can press "enter" or by any other mean trigger normal processing.

It looks very simple, but when you dig a bit further, you will discover more nasty details.

If you want to skip directly to the working example – here is the link.

A simple solution is obvious – you can create action that will update model value. The only complication is to put immediate="true" so you action will be fired regardless of validation errors. You expect that after your action fires, the input will display new value. Nope!

The problem is the UIInput has complex internal structure. It keep internal values for the reason to preserve user input if there are some validation errors. For example if you have a credit card number that allow only numeric inputs, and you type "abc", than you expect to see some polite error message (like "invalid input, you stupid bastard!") - and your "abc" stay intact. The picture even more complex, because we have two internal values – "submitted" that hold exact user input and "local" that holds already converted and validated value before it will be pushed to the model. So, whenever component see non-null submitted value during rendering – it will use it; otherwise if there is non-null local value – it will use it; finally if no local or submitted values exists – component will use value from the model (it will evaluate value binding expression). That's it!

Hopefully now you can see the solution for our little nasty problem: all you need to do is to make sure that no submitted value exists during rendering.

The most obvious way to achieve that – just to reset submitted value in your action code. The other possible approach – to use Richfaces component a4j:region that can limit set of processed submitted values. Both cases are demonstrated here.


My best wishes!


Thursday, July 12, 2007

Do we really need JSF?

I spent past few weeks thinking and arguing with my fellow friends about one particular subject – what the problem with JSF? Why people again and again think that JSF is bad, slow and hard to use? What is wrong? Yes, I’m a member of JSR 314, we all have tons of ideas what is broken and how to fix it. Still I think we missing something fundamentally important, and here is my opinion – what is it.

I was a big fan of JSF from the very early days of it, when Craig McClanahan was blogging about Struts vs JSF. It was so long time ago, that it hard to believe that it actually happened. That days JSF proclaim to be “client” agnostic, you can use different Render Kits and have your great application on different clients for free. Does anyone recall these promises?

But than people realize that JSF went too far “ignoring” html. If you put plain html into the page – JSF simply throw it away. Finally everyone admit the fact, that people actually use the only one client – browser.

And yes, solution was found; now HTML is first class passenger in JSF vehicle.

But suddenly Ajax-mania happened. People get used to the idea that web applications may behave similar to desktop applications. That was great, because it happened to be the most obvious case for JSF – a technology for stateful, rich, intranet, business applications. And Ajax just comes naturally into that place.

But then we begin to feel PAIN! We pushed our DHTML JSF based applications to the very limits of technology, follow very painful learning curve of understanding fine differences between browsers, how to make that particular JavaScript run equally fast on both – IE and Mozilla, etc. And still, desktop applications can run circles around us!

The problem is obvious – browser and DHTML are the worse tools to solve such problems. Yes, there are a good number of cases where browser shine – but people normally use other technologies (not JSF) to build such applications. That happens because of some other JSF’s birth defects (stateful component tree, URL/REST difficulties and some others) – I will not discuss those problems here. At least we all agree that it can be fixed and we must fix it.

But for many other cases DHTML is at least useless, and sometime it is pure evil. In my experience it is vast majority of cases. Why do we need to translate tabular data from collections of beans to cumbersome text format with table, td and tr’s (and don’t forget tbody!) tags and then let browser painfully slow translate it to human readable form on the screen!

But JSF itself has nothing to do with such problem. Remember early days of JSF and promises of “client-agnostic” Server Faces? Ok, I believe now it a good time to take closer look to this promise.

I’m talking about simple idea – let’s create special client for JSF applications with Java!

Look, there is nothing new about this idea! Remember “write once, run anywhere”? We just combine similar approaches from the past and from not that distant past – and create ultimate solution, end-to-end Java, from client to server, powerful and dynamic, nice looking, snappy and easy to use!

Let me to dream a little bit about some features of such solution:

  • Application is hosted on server, when browser pointed to some application URL – special response generated, that will load Java WebStart application (our client) and put it into work
  • Variation may include browser plug-in that do basically the same, but run client inside of browser window
  • After client starts, it will establish communication with server (add more details there)
  • Client request view from server, server assembly component tree and send it to the client (for example in some compact serialized form)
  • Client render view; components are rendered using various Swing widgets etc.
  • Everything live, inputs accept input, transformers transforms, validators validates, some descent client life-cycle spins
  • Binding now become real bindings – when something changed on server, client immediately refreshed
  • Events (like ValueChange) flying between client and server, in all directions
  • Eventually some button clicked, server action executed and some outcome generated, passed thru Navigation Handler and another view become current
  • That view created, serialized and sent to the client

Such picture looks really attractive to me, and – yes, no DHTML allowed!

For sure such project will require some effort, hopefully not too much, we can re-use vast number of Swing artifacts, Java itself become more and more client-oriented with all this resent movements and plans for 7.

BTW, the answer for question is – yes, we do need JSF. That is by far the best tool for many cases – we just need to take browser and DHTML out of the picture. Ok, sure not for all cases, but at least for many of it!

WDYT?

Time to re-start this old buddy

Ok, I just realized that I have this blog on blogger started few years ago. I guess it a good time to reanimate it. Will see how it will fly...

Have fun with reading!

Igor.