On 5/5/06, Don Brown <[EMAIL PROTECTED]> wrote:
These are very good points. How does JSF handle the multiple renders?
For the implementation questions below, my answers are based on the jsf-portlet bridge code in the RI's java.net project. AFAICT, the implementations inside MyFaces and the portals.apache.org bridges project are pretty similar, but might not be identical. The JSF lifecycle is implemented by a single portlet with the two standard lifecycle methods. The portlet container calls processAction() for the portlet that processes the form post, which is mapped to a call to JSF's Lifecycle.process() method. This in turn triggers the Restore View through Invoke Application phases of the standard JSF lifecycle (in "action framework" terms, that is everything up to and including calling the action method). Then, the portlet container will call render() on the JSF portlet for *every* portlet on the page, which gets mapped to a call to JSF's Lifecycle.render() method, which does the Render Response phase of the lifecycle (i.e. the moral equivalent of forwarding to the JSP page that you navigated to). The net effect is that one portlet runs through both phases of the portlet lifecycle, while all the other portlets only run through the rendering phase. Do you
have to ensure your backing bean is session scoped? Wouldn't a request scope mean the data would be lost at the end of the processAction()?
Yes, you would lose request attribute data at the end of processAction() -- the container is explicitly prohibited from carrying them forward. But, when you think about it, this actually makes sense. A portlet *always* needs to be prepared to rerender its current state, because it might not be the one that receives the next GET or POST request, so it needs to save enough state information (in session scope or cookies or ...) to make that possible. There's one other subtlety to sessions in portlets -- it turns out there are two kinds. You can have session attributes in "portlet scope" (specific to a particular instance of a particular portlet) or in "applicaton scope" (per user, like a servlet session). The former is useful for the kind of state saving referenced above, while the latter is used the same way we use session scope in webapps. The point here, though, is we'd need to decide whether or not to expose both concepts in an abstraction API (JSF did not, and I'm not sure this was the right long term choice.) How would you
expect a portlet lifecycle to be supported with a stateless Action-based framework?
I would think we'd want to support some explicit notion of a "setup" phase right before rendering, and a "cleanup" phase afterwards. That way, you can do things like open a Hibernate session and do a query that's needed to populate a table, then clean up the session afterwards. (JSF makes this possible with "before phase" and "after phase' event listeners, while Shale exposes these concepts directly as callbacks to the prerender() and destroy() methods on your backing bean if it implements ViewController.) With this structure, the Action framework would actually have two controllers in a portlet environment ... one for the processAction() part and one for the render() part. In a webapp, it would all be just one, essentially concatenating the processing steps. We would also want some sort of environment-independent "action context" object that was implemented differently for the two environments, but that seems likely to be desireable anyway. Don Craig