Wednesday, August 13, 2008

Navigation: No hard dependencies, no type dependencies, no code dependencies, Why?

In Java, first we had servlets, and each one of them answered to request made to a particular url (or an url matching a particular expression), but it was hard to create pages that way, and it was even harder to create a system composed of many “pages” (note the conceptual jump from servlets answering url requests to "pages”)

Then, JSPs were created, take a look at them and you will see that each JSP page knows nothing about any other, JSP was designed thinking that the best way to deal with many pages was to handle it them as “independent”: lets make each page unaware of what page is next (and what page was previously). Just as servlets were somehow unaware or each other.

After that, JSF was invented, this new technology sees "Pages" as components (composed of other simpler components) forming a component tree. All the components in the same page collaborate to give life to a JSF page (but it does it in a pretty limited way, unless you use Facelets, but they weren't invented until later, and they didn't help much with navigation). By now, we should be far far away from the servlets with which we started... but still each page is unaware of what page is next (and what page was previously). Just as servlets were somehow unaware or each other.

Why?

Then, we got Seam, with its powerful bijection, to help us deal with the job of exchanging information between pages. And its pages.xml files, to help us deal with the limited navigational capabilities available with plain JSF. But still each page is unaware of what page is next (and what page was previously). Just as servlets were somehow unaware or each other.

Why?

In a somewhat parallel universe, perhaps in the Twilight Zone, WebObjects was created, in WebObjects, we have no servlets, "Pages" are components (composed of other simpler components) forming a component tree. All the components in the same page collaborate to give life to a WO page. And if you want, you can treat a WO page as a WO Component, they are pretty much the same thing, at it is trivial to change from one to the other, and create libraries of WO Components (comparatively creating JSF components is so hard that is mind boggling). And each page is aware of what page is next (and what page was previously). Let me state that again: The code in each page is aware of what page is next (and what page was previously). Here is a pseudo code example:

public WOComponent gotoProfilePage(){

ProfilePage profilePage = new ProfilePage();

profilePage.setUser(this.getSelectedUser());
return profilePage;

}


And that's it, that is how you send the currently selected user from the current page into the next page, plain and simple, you just create an object of the type of the page where you want to go, and use its getters and setters go share state with it... what could be simpler than that? why I have been unable to find a framework that deals with page navigation like this? Well, you might say, it is not that flexible, what if you want configurable navigation? Well, then you can do it like this:

public WOComponent gotoProfilePage(){

WOComponent profilePage = this.getPageWithName("ProfilePage");

profilePage.takeValueForKey(this.getSelectedUser(),"user");
return profilePage;

}


Any page with the name "ProfilePage" that has a "user" attribute will used for this navigation action. So... the question is still in the air... why? why I have been unable to find a web framework that deals with navigation in this way... why? We have frameworks that create dependencies between otherwise only dynamically related stuff, like Hibernate, creating properties in java objects that mimic the dynamic relations in a database, but we refuse to offer the same services for page navigation... I don't get why... this seems as such a natural way to deal with this kind of problem... is there a disadvantage here that I am not seeing? Or was WebObjects really created in the Twilight Zone?





Update: Just discovered another disadvantage of xml based navigation in JSF/Seam: It is not possible to use the java debugger or logging frameworks "out of the box" to debug the conditionals in the xml file, one has to wait for (or build) a custom debugger/logger for JSF/Seam navigation.

7 comments:

Eelco Hillenius said...

Exactly. I'm still amazed by that the 'web mvc' frameworks don't recognize that the navigation/ flow mechanism they provide are really a left over of the document-oriented roots of the web. It makes no sense in modern GUIs. :-)

Matt Raible said...

The problem I've seen with this approach is when you have a huge application (1000+ pages) and you want to break it up into smaller webapps. It's very difficult to do when you reference pages statically. Of course, if you always develop smaller, modular applications - this isn't a problem. But no one realizes they need to do that until they've developed the huge one. ;-)

Eelco Hillenius said...

If you need that bit of flexibility, do it through introspection, even throw in a configuration file if you wish. The problem with a lot of web frameworks is that they force their navigation principals through your throat, making it difficult or even impossible to bend it to your will (sure you can hack around Struts' or JSF's ways, but it won't be pretty), while the other way around - not assuming too much to start with - makes for more flexibility.

Luxspes said...

Matt Raible, I agree with you that "no one realizes they need to do that [always develop smaller, modular applications] until they've developed the huge one".

But what currently happens is that you we use overkill solutions for navigation, that only payoff for huge applications, even if we need to build a far smaller thing. We have all seen what happens if an API is designed only for the huge applications that "need it all" you end up with a monster like J2EE 1.4 .

Also, with the API I propose in this blog post, I show it is possible to switch between dynamic and static navigation with little change, but currently, in JSF, there is no way to easy way to go incrementally from static to dynamic navigation. And frameworks like Seam or Shale do heroic efforts to deal with information exchange between page using annotations in exotic ways, when simple setter and getters could do the job.

I feel we going down the wrong path again...

Rafael Ponte said...

It's possible with JSF and its ajax components works through of "states oriented navigation", hence all logic on navigation belongs in managed beans.

You may see about it here,
http://www.rponte.com.br/2008/04/10/utilizando-ajax-com-jsf-de-maneira-eficiente/

Unfortunately that post was written in portuguese, but I think that you'll achieve to understand the codes.

It's a solution better than the common "pages oriented navigation"

Luxspes said...

Interesting link Rafael Ponte.The idea of state oriented navigation seems nice, but I do not get how (or if it) helps with information exchange between pages in a typesafe way. Can you provide me with further explanation?

The Traveler said...

As you wisely told me once, WebObjects makes application development for the Web as easy as it is for the desktop