Author: craigmcc Date: Fri Jun 30 15:27:58 2006 New Revision: 418397 URL: http://svn.apache.org/viewvc?rev=418397&view=rev Log: SHALE-197 -- Allow phase listeners to be automatically registered (at startup time) by virtue of implementing the @FacesPhaseListener annotation, rather than having to be configured in a faces-config.xml file. Building the unit test for this feature also necessitated implementing the phase listener registration methods in MockLifecycle in the shale-test module.
Modified: struts/shale/trunk/shale-test/src/main/java/org/apache/shale/test/mock/MockLifecycle.java struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/faces/LifecycleListener.java struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/register/package.html struts/shale/trunk/shale-tiger/src/test/java/org/apache/shale/tiger/faces/LifecycleListenerTestCase.java Modified: struts/shale/trunk/shale-test/src/main/java/org/apache/shale/test/mock/MockLifecycle.java URL: http://svn.apache.org/viewvc/struts/shale/trunk/shale-test/src/main/java/org/apache/shale/test/mock/MockLifecycle.java?rev=418397&r1=418396&r2=418397&view=diff ============================================================================== --- struts/shale/trunk/shale-test/src/main/java/org/apache/shale/test/mock/MockLifecycle.java (original) +++ struts/shale/trunk/shale-test/src/main/java/org/apache/shale/test/mock/MockLifecycle.java Fri Jun 30 15:27:58 2006 @@ -16,6 +16,8 @@ package org.apache.shale.test.mock; +import java.util.ArrayList; +import java.util.List; import javax.faces.FacesException; import javax.faces.context.FacesContext; import javax.faces.event.PhaseListener; @@ -36,12 +38,15 @@ // ------------------------------------------------------ Instance Variables + private List listeners = new ArrayList(); + + // ------------------------------------------------------- Lifecycle Methods public void addPhaseListener(PhaseListener listener) { - throw new UnsupportedOperationException(); + listeners.add(listener); } @@ -55,14 +60,14 @@ public PhaseListener[] getPhaseListeners() { - throw new UnsupportedOperationException(); + return (PhaseListener[]) listeners.toArray(new PhaseListener[listeners.size()]); } public void removePhaseListener(PhaseListener listener) { - throw new UnsupportedOperationException(); + listeners.remove(listener); } Modified: struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/faces/LifecycleListener.java URL: http://svn.apache.org/viewvc/struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/faces/LifecycleListener.java?rev=418397&r1=418396&r2=418397&view=diff ============================================================================== --- struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/faces/LifecycleListener.java (original) +++ struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/faces/LifecycleListener.java Fri Jun 30 15:27:58 2006 @@ -31,6 +31,9 @@ import javax.faces.FactoryFinder; import javax.faces.application.Application; import javax.faces.application.ApplicationFactory; +import javax.faces.event.PhaseListener; +import javax.faces.lifecycle.Lifecycle; +import javax.faces.lifecycle.LifecycleFactory; import javax.faces.render.RenderKit; import javax.faces.render.RenderKitFactory; import javax.faces.render.Renderer; @@ -49,8 +52,10 @@ import org.apache.shale.tiger.managed.config.ManagedPropertyConfig; import org.apache.shale.tiger.register.FacesComponent; import org.apache.shale.tiger.register.FacesConverter; +import org.apache.shale.tiger.register.FacesPhaseListener; import org.apache.shale.tiger.register.FacesRenderer; import org.apache.shale.tiger.register.FacesValidator; +import org.apache.shale.tiger.register.faces.PhaseListenerAdapter; import org.apache.shale.util.Messages; import org.xml.sax.SAXException; @@ -88,6 +93,12 @@ private transient Messages messages = null; + /** + * <p>The <code>ServletContext</code> instance for this application.</p> + */ + private transient ServletContext servletContext = null; + + // ------------------------------------------------------ Manifest Constants @@ -146,11 +157,9 @@ log().info(messages().getMessage("lifecycle.destroyed")); } - // Get a reference to the application ServletContext - ServletContext servletContext = event.getServletContext(); - // Clean up our allocated application scope attributes servletContext.removeAttribute(FACES_CONFIG_CONFIG); + servletContext = null; } @@ -180,7 +189,7 @@ } // Get a reference to the application ServletContext - ServletContext servletContext = event.getServletContext(); + servletContext = event.getServletContext(); // Create an empty FacesConfigConfig instance and stash it as // an application scope attribute @@ -434,6 +443,27 @@ } + private Lifecycle lifecycle = null; + + + /** + * <p>Return the <code>Lifecycle</code> for this application.</p> + */ + private Lifecycle lifecycle() { + + if (lifecycle == null) { + String lifecycleId = servletContext.getInitParameter("javax.faces.LIFECYCLE_ID"); + if (lifecycleId == null) { + lifecycleId = LifecycleFactory.DEFAULT_LIFECYCLE; + } + lifecycle = ((LifecycleFactory) FactoryFinder. + getFactory(FactoryFinder.LIFECYCLE_FACTORY)).getLifecycle(lifecycleId); + } + return lifecycle; + + } + + /** * <p>Return the <code>Log</code> instance to be used for this class, * instantiating a new one if necessary.</p> @@ -532,6 +562,23 @@ log().trace("addConverter(" + conv.value() + "," + clazz.getName() + ")"); } application().addConverter(conv.value(), clazz.getName()); + } + + FacesPhaseListener list = (FacesPhaseListener) clazz.getAnnotation(FacesPhaseListener.class); + if (list != null) { + try { + Lifecycle lifecycle = lifecycle(); + Object instance = clazz.newInstance(); + if (instance instanceof PhaseListener) { + lifecycle.addPhaseListener((PhaseListener) instance); + } else { + lifecycle.addPhaseListener(new PhaseListenerAdapter(instance)); + } + } catch (FacesException e) { + throw e; + } catch (Exception e) { + throw new FacesException(e); + } } FacesRenderer rend = (FacesRenderer) clazz.getAnnotation(FacesRenderer.class); Modified: struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/register/package.html URL: http://svn.apache.org/viewvc/struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/register/package.html?rev=418397&r1=418396&r2=418397&view=diff ============================================================================== --- struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/register/package.html (original) +++ struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/register/package.html Fri Jun 30 15:27:58 2006 @@ -20,11 +20,12 @@ <p>This package contains Java SE 5 <em>annotations</em> that allow you to register several types of JavaServer Faces artifacts (components, converters, -renderers, and validators) without having to define them in a configuration -resource. Because the JavaServer Faces runtime does not support classes with -arbitrary inheritance hierarchies to implement particular features, the +phase listeners, renderers, and validators) without having to define them in +a configuration resource. Because the JavaServer Faces runtime does not support +classes with arbitrary inheritance hierarchies to implement particular features, the actual classes themselves must also extend the corresponding JavaServer Faces -APIs to be usable.</p> +APIs to be usable (with the exception of annotated phase listeners, in which +case an adapter instance will be interposed if necessary.</p> <p>To declare a JavaServer Faces <code>UIComponent</code> class:</p> <pre> @@ -55,6 +56,24 @@ @FacesValidator("com.mycompany.mytypes.MY_VALIDATOR_ID") public class MyValidator implements Validator { + ... + } +</pre> + +<p>To declare a JavaServer Faces <code>PhaseListener</code> class (the +<code>BeforePhase</code> and <code>AfterPhase</code> event handers are both +optional, and need only be specified if you are interested in that event):</p> +<pre> + import org.apache.shale.tiger.register.AfterPhase; + import org.apache.shale.tiger.register.BeforePhase; + import org.apache.shale.tiger.register.FacesPhaseListener; + + @FacesPhaseListener(phaseId=PhaseId.RENDER_RESPONSE) + public class MyPhaseListener { + ... + @BeforePhase public void myBeforePhase(PhaseEvent event) { ... } + ... + @AfterPhase public void myAfterPhase(PhaseEvent event) { ... } ... } </pre> Modified: struts/shale/trunk/shale-tiger/src/test/java/org/apache/shale/tiger/faces/LifecycleListenerTestCase.java URL: http://svn.apache.org/viewvc/struts/shale/trunk/shale-tiger/src/test/java/org/apache/shale/tiger/faces/LifecycleListenerTestCase.java?rev=418397&r1=418396&r2=418397&view=diff ============================================================================== --- struts/shale/trunk/shale-tiger/src/test/java/org/apache/shale/tiger/faces/LifecycleListenerTestCase.java (original) +++ struts/shale/trunk/shale-tiger/src/test/java/org/apache/shale/tiger/faces/LifecycleListenerTestCase.java Fri Jun 30 15:27:58 2006 @@ -21,6 +21,7 @@ import java.util.Set; import javax.faces.component.UIComponent; import javax.faces.convert.Converter; +import javax.faces.event.PhaseListener; import javax.faces.render.Renderer; import javax.faces.validator.Validator; import javax.servlet.ServletContextEvent; @@ -31,6 +32,7 @@ import org.apache.shale.tiger.config.FacesConfigConfig; import org.apache.shale.tiger.managed.config.ManagedBeanConfig; import org.apache.shale.tiger.managed.config.ManagedPropertyConfig; +import org.apache.shale.tiger.register.faces.PhaseListenerAdapter; /** * <p>Test case for <code>org.apache.shale.tiger.faces.LifecycleListener</code>.</p> @@ -378,6 +380,12 @@ assertNotNull(rend); Validator val = application.createValidator("foo.MyValidator"); assertNotNull(val); + + // Check our lifecycle instance as well + PhaseListener listeners[] = lifecycle.getPhaseListeners(); + assertNotNull(listeners); + assertEquals(1, listeners.length); + assertTrue(listeners[0] instanceof PhaseListenerAdapter); // Finalize the servlet context listener listener.contextDestroyed(event);