|
|
||
Jacob Hookom's BlogSeptember 2005 ArchivesVariable Soup - Mmmm Tasty!Posted by jhook on September 22, 2005 at 08:01 AM | Permalink | Comments (1)At this point, I would like to show you some of the JSP pages we have in our application, but I'm sure there's a clause somewhere in my contract that says otherwise. Over the long term maintenance and feature-adds on large web applications, your JSP pages can start to look like variable soup. You have 10 to 15 variables being accessed that may have come from any scope, set by any action, somewhere in the process of using that site. Maybe that variable came from a filter somewhere? Eventually things can become difficult to keep track of. With traditional MVC2-- Struts and WebWork, we are able to tie the request scope back to some semblance of an action. But as we move into rich component UIs, where the lines between URL and scope are blurred, what can a developer do to bring some variable continuity and identity into large applications? One way you can provide scope over your variables is to use stronger grained references. This means that you possible introduce the concept of a page bean, where all variables you need are located. Here's an example:
Some developers encourage providing scope prefixing in general across their pages, such as What would be nice is if with each of the ELResolvers or VariableResolvers used within JSF, that the developers would provide a scope variable. So a Spring VariableResolver would provide a The next step would be to provide semantic scopes that are meaningful to your domain model. This way you can create and use scopes like Does anyone else experience this tracability issue with the 'global variable' phenomenon within large web applications? Does anyone have any suggestions on how to make variables in the view more maintainable? Seam: EJB 3 and JSF, Driving the Java EE StackPosted by jhook on September 18, 2005 at 07:42 PM | Permalink | Comments (4)There's been some chatter online about using JSF-specific annotations to drive application coordination. But, really it's your enterprise business model (EJB 3) that should be at the wheel. Within your business/domain objects, this is where all of your 'glue' coding happens, so lets extend EJB 3 a bit into a proper framework that starts to tie together the whole Java EE stack from the middle. Makes sense right? Welcome to Seam. When you start talking about IoC, validation, business coordination, and persistence: you really don't want all of that expressed within the view, but you want the view to be able to leverage those concerns. 'Seam' makes JSF completely aware of those concerns while allowing you to consolidate your business model into 'one kind of stuff' within the EJB tier. The application layer separation is up to you as you can keep things as simple as you want with writing web applications. It's worth checking out. You can probably get a better sense of it from this tutorial. Oh, and did I mention that there's really no XML? Everything stays neat and tidy with your business objects. BTW, the public demo was written with Java.net's Facelets-- how's that for bleeding edge, open source collaboration? In relation to my arch nemisis, Ruby on Rails, while RoR is driven from the persistence layer (which often times you don't have control over), Seam is driven by your object model to greatly simplify development for Java on the web. Lets see if we can't get something like JSF Avatar rolling too to champion the Java EE stack! JSF Avatar vs. MS Atlas (Updated)Posted by jhook on September 18, 2005 at 08:51 AM | Permalink | Comments (14)In my last blog entry, I 'kind of' complained about how JSF's component model was maintained and all the overhead involved. Really, I can't think of it as overhead, because it is tremendously richer in what it can do than other component frameworks. With JSF, each component has control over each step in the request cycle. But this is only half true. When I started to look at ways to efficiently handle partial component tree requests, there really isn't any way for components to also have control over other component's lifecycles. Example, an autocomplete component that wants to be refreshed, but not require the rest of the tree to be processed. Current SolutionsCurrently, the JEE blueprints suggest alternate servlets or phaselisteners that deliver 'xml model' data back to the page over AJAX for further processing before rendering. MS's Atlas does the same kind of processing and the only thing I can say is, "Why??" What if there was a way to simply 'refresh' components without requiring any translation or behavioral injection outside of the component itself? So JSF would be able to selectively update and re-draw the one autocomplete component instead of the whole tree. No phaselisteners, no alternate response renderers, no need to have knowledge of AJAX-- just redraw yourself. Sounds very swing-ish? Black-box ComponentsWell, I originally started development on a solution under Facelets called, "Avatar" that would do this. But this ran into problems. As I stated before, JSF's components are so rich (that they are essentially black-boxes) and it's hard for a framework to externally dictate component processing (UIData for example). What JSF does right now is just walks the whole tree to allow each black-box component to do its thing. Again, this isn't very efficient for AJAX requests-- hence all of the solutions in JEE blueprints and online that require extra, unique cases. In PracticeAnyways, back to 'Avatar'-- the idea is to carry JSF's event handling over into the concept of ProcessingContexts. A ProcessingContext acts as a pointer to a branch or leaf in the component tree and exposes the same processXXXX methods as the UIComponent has. Just like events are gained and broadcast through the component tree, a ViewHandler could ask the component tree for one or more ProcessingContexts by client id. So take that autocomplete component's ID, pass it up in an AJAX request, ask the component tree for a ProcessingContext for that single ID and just operate on that one. So basically, Everything in JSF operates as normal, just that the Root Component (UIViewRoot) now only operates on these ProcessingContext pointers instead of the whole tree (by default, the whole tree though). The end result is that UIComponents are request-type agnostic, allowing everything in JSF to suddenly be 'AJAX' capable with only a few small API changes (UIComponent, UIComponentBase, UIViewRoot). // custom viewhandler Because this processing is delegated within UIViewRoot, everything else in JSF stays intact. You could even have components or Actions add additional components to render during the lifecycle to say, "When action X is fired, re-render components A and B on the screen." Again, the best part is that components wouldn't need to know/care about AJAX and they should all be able to continue to work in this alternate processing method. The whole component tree is still there, referenceable, just that we are selectively processing events. How to Get There?More discussion would have to come up as to how we could standardize this secondary communication over AJAX, but this would could also work for things like XUL too! You could have a rich UI that is defined in a single page (or with Facelet templates) that never needs to be fully refreshed. Now the overhead from JSF's component model doesn't sound bad at all, and actually quite useful! I was wrong, JSF is [near] perfect :-) I would like to get a mod-ed version of JSF 1.2 prototype working, but again, this requires an official spec enhancement-- how about it? JSF 1.2a for Avatar? Updated!I setup some initial unit tests for a medium sized page with lots of static text and a couple data tables, displaying 40 developers in two, separate spots. My example is automatically updating the DB when a single field in the column loses focus, so rendering one component back in the AJAX response. Some of my initial results where:
Now, was it fair for me to use such a large document? Nope, but it helps to emphasize my point! The same document was processed in both cases, but since we only wanted one part of it actually updated back to the client (or visa versa), there was a much smaller request to be processed under the SAME lifecycle. No special phaselisteners, or separate documents or servlets-- again, there's only one document being used with the same components as everyone uses from the JSF API (h:dataTable, h:inputText, h:panelGrid, etc). In relation to Facelets, this isn't a Facelets specific solution. In my own tests, tree building requirements are nothing (<< 1 ms) compared to the rendering time. I don't see this cost being any different with JSF 1.2 and JSP 2.1. Declarative UI and Principles of RESTPosted by jhook on September 14, 2005 at 11:21 PM | Permalink | Comments (3)I've been racking my brain lately, tossing around ideas. I've been working tons with Facelets technology with trying to push JSF into new directions, but it still sits on top of JSF. Not that there's anything wrong with what JSF does, it's really rich, almost too rich. JSF really 'gets' the concept of a component. It allows you to mingle components and accessory concerns such as listeners, validators, and converters within the same document. Great. But... As a carry over from JSP, you place JSF in a non-declarative environment, which means that if you are using JSP, then you must handle the fact that there could be predicate logic that may or may not include some component or some action listener for a given page evaluation (JSTL or custom tags). JSF gets around this by capturing the component models state and either storing it in the session or serializing over your precious bandwidth. Tapestry seems to handle things slightly different such that anything that should be declarative, is, and externalized into a separate document. Correct me if I'm wrong, but Tapestry basically says that I don't want to have to worry about capturing uneccessary state for declarative artifacts, so I'm not going to put them into the 'view' where imperative logic is present. It does clean things up logically, but somewhat scatters UI concerns into multiple places. The benefit of JSF in this case is that everything can be expressed in the same document and collaborate with almost any other logic. So which is better? I don't have an opinion either way, both of them have their strengths. Let me present the use case that has been pushing this reflection. You want to iterate over 50 products, but use AJAX to refresh only one of the products in the page. With JSF, the product iteration is a transient process-- your JSP model is different than the rendered HTML markup basically. So there's no efficient way to selectively evaluate only one product without reproducing the iterative process. Because of imperative semantics that JSF accomodates, you can only re-evaluate the component model as a whole in attempt to capture that tiny bit of state you wanted to refresh. A really good example of my point is lets say that you are using Struts. When I request, 'product.do?id=333343&view=detail', it's a simple, straight Map look up to find the associated stateless action and process those parameters. Now lets apply this to JSF. Your struts-config now allows predicate logic like c:if's or c:forEaches around your action-mappings. In addition, each Action can provide logic in selection. Now, how easy is it to translate that URI to the correct Action and guarantee it's evaluated correctly? Think about it. That's what JSF and these rich component models have to deal with in managing all of that imperative overhead. I guess I can't completely blame imperative logic poisoning declarative component models, because there's enough trouble as is translating component 'trees' over HTTP's 'flat' request string. JSF does a lot with rendering id's and names to translate those unique id's back to the component tree during evaulation. Well, what if you were to take id management to the next step? Imagine if you were to write a truely stateless/declarative compiler, such that id management is built where given a unique id, you can 'reach into' the compiled page and selectively choose components to evaluate. Basically what you are doing by staying strictly declarative in your component models is that your framework can start to draw presumptions and inference behavior/state that doesn't need to be preserved in the way that JSF does. Like I said before, JSF is really rich with what you can do. But it's that richness and all the possibilities it provides will also create overhead. Reading about the principles behind REST, there's a lot of genuine truths there that make me think that Struts/WebWork are partially right with being able to handle pure URI navigation. In the process, that purity allows them to inference a lot of things and produce lighter weight/stateless artifacts. There really isn't much room for that in the JSF API, but it does a really nice job of handling the fact that it can't really presume anything from its developers. ADF RoaRPosted by jhook on September 08, 2005 at 02:30 PM | Permalink | Comments (9)Ruby on Rails: love it or hate it, but it does have a lot of fresh ideas. One of the really great things that RoR has done is presented AJAX functionality in an easy to use API. John Reynolds provided a nice list of AJAX/JavaScript sites in one of his last blog entries, one of which was script.aculo.us. The site includes RoR AJAX examples with source code. While light weight, I was suprised to see that much of the grunt work in some of that functionality was delegated to another freely available JavaScript library, called Prototype. So what RoR is able to do is just generate a couple method calls to Prototype's excellent AJAX API to make requests to other pages. Hmm. Don't you think a developer could do the same with a JSP tag or a Struts action without much effort at all? Oracle's ADF FrameworkI started asking around to see if JSF had any of that functionality in relation to components and AJAX. The idea of refreshing any component on the page. By clicking a button or pressing a key, it will go out and auto complete or change/valdidate text on the fly auto-magically. It seems do-able, but how come no one's done it yet? Well, Oracle did do it and I am really impressed with what they call 'partial-page rendering' or PPR within their ADF JSF Component Framework.
There's a lot more functionality within the ADF framework and their releases have deployable wars that show off all this. They also came out of the gates with Facelets support for their EA19 release a couple weeks back, so you would be able to use ADF along side all of those templating features from Facelets. ConclusionWhile JSF doesn't have the components yet to provide the visual candy that RoR has in demonstration, from a practical application standpoint, Oracle's ADF Component framework is a already there. One thing to take note is that Oracle's ADF library didn't have to delegate rendering to separate page as in some of the RoR demos at script.aculo.us. ADF really blows away the traditional request/response constraints that web developers are so familiar with while being able to provide a richer experience for users. What I would like to explore is enhancing the concept of PPR within Facelets' stateless architecture. I think there's a lot of opportunity there to really blur the lines between a page and a component within the JSF architecture as a whole. Tomorrow's Webtop ApplicationPosted by jhook on September 05, 2005 at 10:59 AM | Permalink | Comments (16)Let me give you a hypothetical project that involves two groups. One group develops a thin client, that is delivered over the web. This thin client works in conjunction with a fat, installed client that the other group developed. The first beta hits, both groups have a couple kinks to work out. The thin client group makes their changes from their cubicle and tells the beta customer to refresh their screen. Done. The fat client group is in for a much more difficult change and has to repackage and send a new CD out to the beta client. That might not even solve the installation issues. Fast forward months later. The beta customer wants a new feature. For the thin client group, they can just add it and have it 'deployed' instantaneously to their customers. What about the fat client? How versatile was their solution long term? A web page isn't always going to work out for thin client development, but you have a large web-development team that isn't experienced with Swing/SWT based development. Where do you go with the most knowledge transfer? Start looking at webtop solutions such as XUL. Webtop Solutions?XUL works exactly like a web page, except that it's markup is representative of a desktop application. Developers can use all of their familiar JavaScript/DOM skills within a browser environment to handle menus, toolbars, sortable tables and trees, etc. DeploymentDeployment wise, XUL is the foundation of Mozilla's product platform. Firefox, Mozilla, and Firebird are written in or use XUL. To think for a second, all of the different platforms that run Mozilla's product line could also run your webtop application. You may also reference resources online just like you would a web page-- import CSS information and JavaScript files, along with RDF data and JPGs or GIFs. Here's the kicker, you can mix HTML and XUL together in a single document too! XUL Example
Dynamic XULXUL does a nice job of separating presentation, structure, and behavior; more so than HTML. To provide dynamic data and behavior, you may use RDF technology which would be like writing a bunch of AJAX code to interpret/use XML data to manipulate the HTML DOM stucture, except all you need to do is point at the RDF data source and everything is take care of. If the data changes, just tell that RDF data source to refresh itself via JavaScript and you're done. There are places where RDF isn't what you need and you want server-side DOM manipulation. For this, you could use technologies like JSPX, JavaServer Faces, or Facelets which are markup agnostic. Roger Kitain, JSF co-spec lead, co-published an article at java.sun.com on using XUL, HTML, and SVG at once within a component-based application. Moving ForwardWhen would you want to use a webtop application and how are you going to get there? Just like your customer/company would be required to have Java installed to run your application, installing Mozilla isn't too far fetched. Install Mozilla and point your browser [here] to use your live application. When you are dealing with interactive, tabular/spreadsheet data, it might be a good idea to seriously consider a webtop solution with XUL. For those who don't want a desktop look, you can always use CSS to make the background a different color or make the buttons red or bold some text. It really is a win-win situation if you can get around supporting IE. Again, since there's tons of knowledge transfer from web development to webtop development with XUL, your team can continue to be higly productive. Also, you can use familiar frameworks such as JavaServer Faces to deliver your application to the browser. This blog was spurred on by reading Jonas Jacobi's entry on Rich Internet Clients (who made much more intelligent points ;-). | ||
|
|