Author: nbelaevski
Date: 2010-05-07 17:29:05 -0400 (Fri, 07 May 2010)
New Revision: 16935
Added:
root/framework/trunk/api/src/main/java/org/richfaces/application/ServiceReference.java
root/framework/trunk/api/src/test/java/org/richfaces/
root/framework/trunk/api/src/test/java/org/richfaces/application/
root/framework/trunk/api/src/test/java/org/richfaces/application/ServiceTrackerTest.java
root/framework/trunk/impl/src/main/java/org/richfaces/application/ServiceTrackerLockPhaseListener.java
Modified:
root/framework/trunk/api/src/main/java/org/richfaces/application/ServiceTracker.java
root/framework/trunk/impl/src/main/java/org/richfaces/application/InitializationListener.java
root/framework/trunk/impl/src/main/resources/META-INF/initialization-listener.faces-config.xml
Log:
https://jira.jboss.org/jira/browse/RF-8472
https://jira.jboss.org/jira/browse/RF-8473
Added:
root/framework/trunk/api/src/main/java/org/richfaces/application/ServiceReference.java
===================================================================
---
root/framework/trunk/api/src/main/java/org/richfaces/application/ServiceReference.java
(rev 0)
+++
root/framework/trunk/api/src/main/java/org/richfaces/application/ServiceReference.java 2010-05-07
21:29:05 UTC (rev 16935)
@@ -0,0 +1,50 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.application;
+
+/**
+ * <p>
+ * This interface is coupled with {@link ServiceTracker} class and provides reference to
service implementation,
+ * allowing delayed service initialization.
+ * </p>
+ *
+ * <p>Methods provided by this interface are expected to be called from multiple
concurrent threads
+ * without any synchronization aids.</p>
+ *
+ * @author Nick Belaevski
+ * @since 4.0
+ */
+public interface ServiceReference<T> {
+
+ /**
+ * <p>Returns instance of service referenced by <code>this</code>
object.</p>
+ *
+ * <p>Calling this method can cause delayed initialization of service.
+ * Clients of this class are not expected to store returned service implementation
object,
+ * so storing reference to the created service object to avoid repeated
initialization is the
+ * sole responsibility of this class.</p>
+ *
+ * @return referenced service implementation object
+ */
+ public T getService();
+
+}
Modified:
root/framework/trunk/api/src/main/java/org/richfaces/application/ServiceTracker.java
===================================================================
---
root/framework/trunk/api/src/main/java/org/richfaces/application/ServiceTracker.java 2010-05-07
19:02:35 UTC (rev 16934)
+++
root/framework/trunk/api/src/main/java/org/richfaces/application/ServiceTracker.java 2010-05-07
21:29:05 UTC (rev 16935)
@@ -30,92 +30,225 @@
/**
* <p>Tracker class to provide access to various framework implementation
services.
- * Examples of such services are: {@link org.richfaces.skin.SkinFactory}, TBD</p>
- * <p/>
- * <p><b>Note:</b> this class is not synchronized and presumes that all
modification operations
- * should be done in a single-thread (e.g. in initialization listener)</p>
+ * Examples of such services are: {@link org.richfaces.skin.SkinFactory}, TBD.</p>
+ *
+ * <p>Supports either direct placement of service implementation instances or lazy
+ * initialization via {@link ServiceReference} interface.</p>
+ *
+ * <p>This class represents application-scoped object that is replicated into
attributes
+ * of {@link FacesContext} during runtime for better performance.</p>
+ *
+ * <p>No modifications operations are allowed after {@link ServiceTracker} is
locked,
+ * and {@link IllegalStateException} is throws in this case.</p>
+ *
+ * <p><b>Note:</b> in initial state this class is not synchronized and
presumes that all
+ * modification operations are done in a context of single-thread (in JSF initialization
listener).
+ * In locked state read operations can be called from multiple threads concurrently
without no need
+ * to synchronize explicitly.</p>
*
* @author Nick Belaevski
* @since 4.0
*/
public final class ServiceTracker {
- private static final String SERVICES_MAP_ATTRIBUTE = ServiceTracker.class.getName();
+ private static final String SERVICE_TRACKER_ATTRIBUTE =
ServiceTracker.class.getName();
+ private volatile Map<Class<?>, Object> servicesMap = new
HashMap<Class<?>, Object>();
+
private ServiceTracker() {
//utility class private constructor
}
- public static Collection<Class<?>>
getRegisteredServiceClasses(FacesContext context) {
- Map<Class<?>, Object> servicesMap = getServicesMap(context, false);
- if (servicesMap != null) {
- return Collections.unmodifiableCollection(servicesMap.keySet());
+ private <T> T get(Class<T> serviceClass) {
+ Object serviceImplementation = null;
+ Object serviceObject = servicesMap.get(serviceClass);
+
+ if (serviceObject instanceof ServiceReference<?>) {
+ serviceImplementation = ((ServiceReference<?>)
serviceObject).getService();
} else {
- return Collections.emptySet();
+ serviceImplementation = serviceObject;
}
+
+ //TODO - null?
+ return serviceClass.cast(serviceImplementation);
+ }
+
+ private void put(Class<?> key, Object value) {
+ try {
+ servicesMap.put(key, value);
+ } catch (UnsupportedOperationException e) {
+ throw new IllegalStateException("Service tracker is locked, no
modification operation is allowed!");
+ }
}
- @SuppressWarnings("unchecked")
- public static <T> T getService(FacesContext context, Class<T>
serviceInterfaceClass) {
+ private Collection<Class<?>> getRegisteredServiceClasses() {
+ return Collections.unmodifiableCollection(servicesMap.keySet());
+ }
+
+ private synchronized void lockModification() {
+ servicesMap = Collections.unmodifiableMap(servicesMap);
+ }
+
+ /**
+ * Returns unmodifiable collection of registered service classes.
+ *
+ * @param context current instance of {@link FacesContext}
+ * @return collection of registered service classes
+ *
+ * @throws NullPointerException if <code>context</code> is
<code>null</code>
+ */
+ public static Collection<Class<?>>
getRegisteredServiceClasses(FacesContext context) {
if (context == null) {
throw new NullPointerException("context");
}
- if (serviceInterfaceClass == null) {
- throw new NullPointerException("serviceInterfaceClass");
+ ServiceTracker serviceTracker = getServiceTracker(context);
+ return serviceTracker.getRegisteredServiceClasses();
+ }
+
+ /**
+ * Lookup registered service implementation by service class.
+ *
+ * @param context current instance of {@link FacesContext}
+ * @param serviceClass class for which implementation has been registered.
+ * @return registered implementation or <code>null</code>
+ *
+ * @throws NullPointerException if <code>context</code> or
<code>serviceClass</code> is <code>null</code>
+ */
+ public static <T> T getService(FacesContext context, Class<T>
serviceClass) {
+ if (context == null) {
+ throw new NullPointerException("context");
}
- T serviceImplementation = null;
-
- Map<Class<?>, Object> servicesMap = getServicesMap(context, false);
- if (servicesMap != null) {
- serviceImplementation = (T) servicesMap.get(serviceInterfaceClass);
+ if (serviceClass == null) {
+ throw new NullPointerException("serviceClass");
}
- //TODO - factories support
- //TODO - null?
- return serviceImplementation;
+ ServiceTracker serviceTracker = getServiceTracker(context);
+ return serviceTracker.get(serviceClass);
}
+ /**
+ * Registers service implementation for the given service class.
+ *
+ * @param context current instance of {@link FacesContext}
+ * @param serviceClass class for which implementation is to be registered
+ * @param serviceImplementation service implementation
+ *
+ * @throws NullPointerException if <code>context</code>,
<code>serviceClass</code> or
+ * <code>serviceImplementation</code> is <code>null</code>
+ * @throws IllegalStateException if current {@link ServiceTracker} is in locked
state.
+ */
public static <T> void setService(FacesContext context,
- Class<T> serviceInterfaceClass,
- T serviceImplementation) {
+ Class<T> serviceClass,
+ T serviceImplementation) {
if (context == null) {
throw new NullPointerException("context");
}
- if (serviceInterfaceClass == null) {
- throw new NullPointerException("serviceInterfaceClass");
+ if (serviceClass == null) {
+ throw new NullPointerException("serviceClass");
}
if (serviceImplementation == null) {
throw new NullPointerException("serviceImplementation");
}
- Map<Class<?>, Object> servicesMap = getServicesMap(context, true);
- servicesMap.put(serviceInterfaceClass, serviceImplementation);
+ ServiceTracker serviceTracker = getServiceTracker(context);
+ serviceTracker.put(serviceClass, serviceImplementation);
}
+ /**
+ * Registers {@link ServiceReference} for the given service class.
+ *
+ * @param context current instance of {@link FacesContext}
+ * @param serviceClass class for which reference is to be registered
+ * @param serviceReference instance of service reference
+ *
+ * @throws NullPointerException if <code>context</code>,
<code>serviceClass</code> or
+ * <code>serviceReference</code> is <code>null</code>
+ * @throws IllegalStateException if current {@link ServiceTracker} is in locked
state.
+ */
+ public static <T> void setServiceReference(FacesContext context,
+ Class<T> serviceClass,
+ ServiceReference<T> serviceReference) {
+
+ if (context == null) {
+ throw new NullPointerException("context");
+ }
+
+ if (serviceClass == null) {
+ throw new NullPointerException("serviceClass");
+ }
+
+ if (serviceReference == null) {
+ throw new NullPointerException("serviceReference");
+ }
+
+ ServiceTracker serviceTracker = getServiceTracker(context);
+ serviceTracker.put(serviceClass, serviceReference);
+ }
+
+ /**
+ * <p>Releases application-scoped {@link ServiceTracker}.</p>
+ * <p>Called during application shutdown; shouldn't be called explicitly by
user.</p>
+ *
+ * @param context current instance of {@link FacesContext}
+ */
public static void release(FacesContext context) {
- clearServicesMap(context);
+ removeServiceTracker(context);
}
- private static Map<Class<?>, Object> getServicesMap(FacesContext
facesContext, boolean createIfNull) {
- //TODO replicate in FacesContext map for better performance
- Map<String, Object> applicationMap =
facesContext.getExternalContext().getApplicationMap();
- @SuppressWarnings("unchecked")
- Map<Class<?>, Object> servicesMap = (Map<Class<?>,
Object>) applicationMap.get(SERVICES_MAP_ATTRIBUTE);
- if (servicesMap == null && createIfNull) {
- servicesMap = new HashMap<Class<?>, Object>();
- applicationMap.put(SERVICES_MAP_ATTRIBUTE, servicesMap);
+ /**
+ * <p>Switches application-scoped {@link ServiceTracker} to locked state,
preventing further modifications
+ * of registered services via {@link #setService(FacesContext, Class, Object)} or
+ * {@link #setServiceReference(FacesContext, Class, ServiceReference)}
methods.</p>
+ *
+ * <p>Called at the beginning of the very first application request life cycle;
shouldn't be called explicitly
+ * by user.</p>
+ *
+ * @param context current instance of {@link FacesContext}
+ */
+ public static void lockModification(FacesContext context) {
+ ServiceTracker serviceTracker = getServiceTracker(context);
+ serviceTracker.lockModification();
+ }
+
+ private static ServiceTracker getServiceTrackerFromApplicationMap(FacesContext
facesContext) {
+ Object appContext = facesContext.getExternalContext().getContext();
+
+ synchronized (appContext) {
+ ServiceTracker serviceTracker;
+ Map<String, Object> applicationMap =
facesContext.getExternalContext().getApplicationMap();
+ serviceTracker = (ServiceTracker)
applicationMap.get(SERVICE_TRACKER_ATTRIBUTE);
+ if (serviceTracker == null) {
+ serviceTracker = new ServiceTracker();
+ applicationMap.put(SERVICE_TRACKER_ATTRIBUTE, serviceTracker);
+ }
+
+ return serviceTracker;
}
+
+ }
+
+ private static ServiceTracker getServiceTracker(FacesContext facesContext) {
+ ServiceTracker serviceTracker = (ServiceTracker)
facesContext.getAttributes().get(SERVICE_TRACKER_ATTRIBUTE);
- return servicesMap;
+ if (serviceTracker == null) {
+ serviceTracker = getServiceTrackerFromApplicationMap(facesContext);
+
+ //replicate in FacesContext map for better performance
+ facesContext.getAttributes().put(SERVICE_TRACKER_ATTRIBUTE, serviceTracker);
+ }
+
+ return serviceTracker;
}
- private static void clearServicesMap(FacesContext facesContext) {
+ private static void removeServiceTracker(FacesContext facesContext) {
Map<String, Object> applicationMap =
facesContext.getExternalContext().getApplicationMap();
- applicationMap.remove(SERVICES_MAP_ATTRIBUTE);
+ applicationMap.remove(SERVICE_TRACKER_ATTRIBUTE);
+
+ facesContext.getAttributes().remove(SERVICE_TRACKER_ATTRIBUTE);
}
}
Added:
root/framework/trunk/api/src/test/java/org/richfaces/application/ServiceTrackerTest.java
===================================================================
---
root/framework/trunk/api/src/test/java/org/richfaces/application/ServiceTrackerTest.java
(rev 0)
+++
root/framework/trunk/api/src/test/java/org/richfaces/application/ServiceTrackerTest.java 2010-05-07
21:29:05 UTC (rev 16935)
@@ -0,0 +1,173 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.application;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.faces.context.FacesContext;
+import javax.servlet.ServletContext;
+
+import org.jboss.test.faces.mock.MockFacesEnvironment;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class ServiceTrackerTest {
+
+ private MockFacesEnvironment environment;
+
+ private FacesContext context;
+
+ private ServletContext servletContext;
+
+ private Map<String, Object> applicationMap;
+
+ private Map<Object, Object> contextMap;
+
+ private SkinServiceImpl skinServiceImpl;
+
+ private ConfigServiceImpl configServiceImpl;
+
+ private ConfigServiceReferenceImpl configServiceReference;
+
+ private static interface SkinService {};
+
+ private static class SkinServiceImpl implements SkinService {}
+
+ private static interface ConfigService {};
+
+ private static class ConfigServiceReferenceImpl implements
ServiceReference<ConfigService> {
+
+ private ConfigService service;
+
+ public ConfigServiceReferenceImpl(ConfigService service) {
+ super();
+ this.service = service;
+ }
+
+ public ConfigService getService() {
+ return service;
+ }
+ }
+
+ private static class ConfigServiceImpl implements ConfigService {}
+
+ private void setupRequestObjects() {
+
expect(environment.getExternalContext().getApplicationMap()).andStubReturn(applicationMap);
+
expect(environment.getExternalContext().getContext()).andStubReturn(servletContext);
+
+ contextMap = new HashMap<Object, Object>();
+ expect(environment.getFacesContext().getAttributes()).andStubReturn(contextMap);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ skinServiceImpl = new SkinServiceImpl();
+ configServiceImpl = new ConfigServiceImpl();
+ configServiceReference = new ConfigServiceReferenceImpl(configServiceImpl);
+
+ environment = MockFacesEnvironment.createEnvironment().withExternalContext();
+ context = environment.getFacesContext();
+
+ applicationMap = new HashMap<String, Object>();
+ servletContext = environment.createMock(ServletContext.class);
+
+ setupRequestObjects();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ skinServiceImpl = null;
+ configServiceImpl = null;
+ configServiceReference = null;
+
+ context = null;
+ applicationMap = null;
+ contextMap = null;
+
+ environment.verify();
+ environment.release();
+ environment = null;
+ }
+
+ @Test
+ public void testBasic() throws Exception {
+ environment.replay();
+
+ ServiceTracker.setService(context, SkinService.class, skinServiceImpl);
+ ServiceTracker.setServiceReference(context, ConfigService.class,
configServiceReference);
+
+ ServiceTracker.lockModification(context);
+
+ Collection<Class<?>> serviceClasses =
ServiceTracker.getRegisteredServiceClasses(context);
+ assertFalse(serviceClasses.isEmpty());
+
+ assertTrue(serviceClasses.contains(SkinService.class));
+ assertTrue(serviceClasses.contains(ConfigService.class));
+
+ assertSame(skinServiceImpl, ServiceTracker.getService(context,
SkinService.class));
+ assertSame(configServiceImpl, ServiceTracker.getService(context,
ConfigService.class));
+
+ environment.reset();
+ setupRequestObjects();
+ environment.replay();
+
+ serviceClasses = ServiceTracker.getRegisteredServiceClasses(context);
+ assertFalse(serviceClasses.isEmpty());
+
+ assertTrue(serviceClasses.contains(SkinService.class));
+ assertTrue(serviceClasses.contains(ConfigService.class));
+
+ assertSame(skinServiceImpl, ServiceTracker.getService(context,
SkinService.class));
+ assertSame(configServiceImpl, ServiceTracker.getService(context,
ConfigService.class));
+
+ ServiceTracker.release(context);
+ }
+
+ @Test
+ public void testLockModifications() throws Exception {
+ environment.replay();
+
+ ServiceTracker.lockModification(context);
+
+ try {
+ ServiceTracker.setService(context, SkinService.class, skinServiceImpl);
+
+ fail();
+ } catch (IllegalStateException e) {
+ }
+
+ ServiceTracker.release(context);
+ }
+}
\ No newline at end of file
Modified:
root/framework/trunk/impl/src/main/java/org/richfaces/application/InitializationListener.java
===================================================================
---
root/framework/trunk/impl/src/main/java/org/richfaces/application/InitializationListener.java 2010-05-07
19:02:35 UTC (rev 16934)
+++
root/framework/trunk/impl/src/main/java/org/richfaces/application/InitializationListener.java 2010-05-07
21:29:05 UTC (rev 16935)
@@ -21,13 +21,13 @@
*/
package org.richfaces.application;
-import org.ajax4jsf.cache.CacheManager;
-import org.ajax4jsf.renderkit.AJAXDataSerializer;
-import org.ajax4jsf.resource.util.URLToStreamHelper;
-import org.richfaces.log.RichfacesLogger;
-import org.richfaces.skin.SkinFactory;
-import org.richfaces.skin.SkinFactoryImpl;
-import org.slf4j.Logger;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.text.MessageFormat;
import javax.faces.FacesException;
import javax.faces.context.FacesContext;
@@ -36,14 +36,15 @@
import javax.faces.event.PreDestroyApplicationEvent;
import javax.faces.event.SystemEvent;
import javax.faces.event.SystemEventListener;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.text.MessageFormat;
+import org.ajax4jsf.cache.CacheManager;
+import org.ajax4jsf.renderkit.AJAXDataSerializer;
+import org.ajax4jsf.resource.util.URLToStreamHelper;
+import org.richfaces.log.RichfacesLogger;
+import org.richfaces.skin.SkinFactory;
+import org.richfaces.skin.SkinFactoryImpl;
+import org.slf4j.Logger;
+
/**
* @author Nick Belaevski
* @since 4.0
Added:
root/framework/trunk/impl/src/main/java/org/richfaces/application/ServiceTrackerLockPhaseListener.java
===================================================================
---
root/framework/trunk/impl/src/main/java/org/richfaces/application/ServiceTrackerLockPhaseListener.java
(rev 0)
+++
root/framework/trunk/impl/src/main/java/org/richfaces/application/ServiceTrackerLockPhaseListener.java 2010-05-07
21:29:05 UTC (rev 16935)
@@ -0,0 +1,49 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.application;
+
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+import javax.faces.lifecycle.Lifecycle;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class ServiceTrackerLockPhaseListener implements PhaseListener {
+
+ private static final long serialVersionUID = 3206929642757284003L;
+
+ public void afterPhase(PhaseEvent event) {
+ }
+
+ public void beforePhase(PhaseEvent event) {
+ ServiceTracker.lockModification(event.getFacesContext());
+ ((Lifecycle) event.getSource()).removePhaseListener(this);
+ }
+
+ public PhaseId getPhaseId() {
+ return PhaseId.ANY_PHASE;
+ }
+
+}
Modified:
root/framework/trunk/impl/src/main/resources/META-INF/initialization-listener.faces-config.xml
===================================================================
---
root/framework/trunk/impl/src/main/resources/META-INF/initialization-listener.faces-config.xml 2010-05-07
19:02:35 UTC (rev 16934)
+++
root/framework/trunk/impl/src/main/resources/META-INF/initialization-listener.faces-config.xml 2010-05-07
21:29:05 UTC (rev 16935)
@@ -11,5 +11,9 @@
<system-event-class>javax.faces.event.PostConstructApplicationEvent</system-event-class>
</system-event-listener>
</application>
+
+ <lifecycle>
+ <phase-listener>org.richfaces.application.ServiceTrackerLockPhaseListener</phase-listener>
+ </lifecycle>
</faces-config>
\ No newline at end of file