Very early Apache Shale came up with the idea of providing a view controller that allowed to execute dedicated methods (annotated, etc.) during various JSF life-cycle (phase) events for doing initialization work upfront for example. As Shale was hibernated, Apache Orchestra stepped in and added many more useful features. Both frameworks are based on the idea of having a dedicated page bean (a JSF managed bean per view) that would control important processing steps for the entire view (page). It requires following naming conventions in order to associate a page bean to a view, optionally a view controller mapper provided the ability of explicitely associating page beans and views.
In many projects I found the situation that the client didn’t want to pull in another framework just for that little feature. Also for distributing responsibilities, I usually have multiple managed beans per view. So another “artificial” page bean is required just for controlling the others. So I came up with a fairly simple solution that allows to directly invoke those life-cycle callbacks on any managed bean used on a single page.
The <f:phaseListener> tag allows to bind a JSF PhaseListener. You can even bind multiple phase listeners (one for each managed bean; you get the idea).
So each of the beans would provide a reference to a phase listener that would take care to perform the proper processing for the bean itself. Every bean then would use a set of annotations (like @PreRenderView, @PostRestoreView, @PreInvokeApplication, etc.) to mark those methods that should be called during a specific phase.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
The code above is partially showing a base class from which many of my managed bean are subclassed. Key is the ViewControllerPhaseListener which hides all of the details of doing the reflection job for finding (and then caching) the annotated methods to invoke during a specific phase. For brevity I’m showing only the key elements of this class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
In a few projects this has proven to be quite versatile. Currently I have a couple of interesting phase listener components, from the simple DebugPhaseListener to the OpenTransactionInViewPhaseListener. I can just throw them into any view as they are required.