You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by mc...@apache.org on 2010/06/30 22:26:31 UTC
svn commit: r959423 - in
/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces:
application/ApplicationImpl.java lifecycle/LifecycleImpl.java
view/facelets/FaceletViewDeclarationLanguage.java
view/facelets/FaceletViewHandler.java
Author: mconcini
Date: Wed Jun 30 20:26:31 2010
New Revision: 959423
URL: http://svn.apache.org/viewvc?rev=959423&view=rev
Log:
MYFACES-2780 - performance improvements for production deployments
Modified:
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/lifecycle/LifecycleImpl.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewHandler.java
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java?rev=959423&r1=959422&r2=959423&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java Wed Jun 30 20:26:31 2010
@@ -22,8 +22,10 @@ import java.beans.BeanDescriptor;
import java.beans.BeanInfo;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
@@ -159,15 +161,15 @@ public class ApplicationImpl extends App
// components, converters, and validators can be added at runtime--must
// synchronize, uses ConcurrentHashMap to allow concurrent read of map
- private final Map<String, Class<? extends Converter>> _converterIdToClassMap = new ConcurrentHashMap<String, Class<? extends Converter>>();
+ private final Map<String, Object> _converterIdToClassMap = new ConcurrentHashMap<String, Object>();
private final Map<Class<?>, String> _converterClassNameToClassMap = new ConcurrentHashMap<Class<?>, String>();
private final Map<String, org.apache.myfaces.config.impl.digester.elements.Converter> _converterClassNameToConfigurationMap = new ConcurrentHashMap<String, org.apache.myfaces.config.impl.digester.elements.Converter>();
- private final Map<String, Class<? extends UIComponent>> _componentClassMap = new ConcurrentHashMap<String, Class<? extends UIComponent>>();
+ private final Map<String, Object> _componentClassMap = new ConcurrentHashMap<String, Object>();
- private final Map<String, Class<? extends Validator>> _validatorClassMap = new ConcurrentHashMap<String, Class<? extends Validator>>();
+ private final Map<String, Object> _validatorClassMap = new ConcurrentHashMap<String, Object>();
private final Map<Class<? extends SystemEvent>, SystemListenerEntry> _systemEventListenerClassMap = new ConcurrentHashMap<Class<? extends SystemEvent>, SystemListenerEntry>();
@@ -175,7 +177,7 @@ public class ApplicationImpl extends App
private Map<String, String> _cachedDefaultValidatorsIds = null;
- private final Map<String, Class<? extends Behavior>> _behaviorClassMap = new ConcurrentHashMap<String, Class<? extends Behavior>>();
+ private final Map<String, Object> _behaviorClassMap = new ConcurrentHashMap<String, Object>();
private final RuntimeConfig _runtimeConfig;
@@ -187,6 +189,9 @@ public class ApplicationImpl extends App
private boolean _firstRequestProcessed = false;
+ private final Map<Class<?>, List<ListenerFor>> _classToListenerForMap = new HashMap<Class<?>, List<ListenerFor>>() ;
+ private final Map<Class<?>, List<ResourceDependency>> _classToResourceDependencyMap = new HashMap<Class<?>, List<ResourceDependency>>() ;
+
// ~ Constructors
// --------------------------------------------------------------------------
// -----
@@ -275,7 +280,15 @@ public class ApplicationImpl extends App
{
if (_validatorClassMap.containsKey(validatorId))
{
- _defaultValidatorsIds.put(validatorId, _validatorClassMap.get(validatorId).getName());
+ Object validatorClass = getObjectFromClassMap(validatorId, _validatorClassMap);
+ String className;
+ if(validatorClass instanceof String)
+ className = (String)validatorClass;
+
+ //otherwise validatorClass is an object of type Class<?>
+ className = ((Class<?>)validatorClass).getName();
+
+ _defaultValidatorsIds.put(validatorId, className);
_cachedDefaultValidatorsIds = null;
}
}
@@ -928,7 +941,7 @@ public class ApplicationImpl extends App
try
{
- _behaviorClassMap.put(behaviorId, ClassUtils.simpleClassForName(behaviorClass));
+ _behaviorClassMap.put(behaviorId, behaviorClass);
if (log.isLoggable(Level.FINEST))
log.finest("add Behavior class = " + behaviorClass + " for id = " + behaviorId);
}
@@ -950,7 +963,7 @@ public class ApplicationImpl extends App
try
{
- _componentClassMap.put(componentType, ClassUtils.simpleClassForName(componentClassName));
+ _componentClassMap.put(componentType, componentClassName);
if (log.isLoggable(Level.FINEST))
log.finest("add Component class = " + componentClassName + " for type = " + componentType);
}
@@ -971,7 +984,7 @@ public class ApplicationImpl extends App
try
{
- _converterIdToClassMap.put(converterId, ClassUtils.simpleClassForName(converterClass));
+ _converterIdToClassMap.put(converterId, converterClass);
if (log.isLoggable(Level.FINEST))
log.finest("add Converter id = " + converterId + " converterClass = " + converterClass);
}
@@ -1022,7 +1035,7 @@ public class ApplicationImpl extends App
try
{
- _validatorClassMap.put(validatorId, ClassUtils.simpleClassForName(validatorClass));
+ _validatorClassMap.put(validatorId, validatorClass);
if (log.isLoggable(Level.FINEST))
log.finest("add Validator id = " + validatorId + " class = " + validatorClass);
}
@@ -1038,15 +1051,16 @@ public class ApplicationImpl extends App
checkNull(behaviorId, "behaviorId");
checkEmpty(behaviorId, "behaviorId");
- final Class<? extends Behavior> behaviorClass = this._behaviorClassMap.get(behaviorId);
+ final Class<?> behaviorClass = getObjectFromClassMap(behaviorId, _behaviorClassMap);
+
if (behaviorClass == null)
{
throw new FacesException("Could not find any registered behavior-class for behaviorId : " + behaviorId);
}
-
+
try
{
- Behavior behavior = behaviorClass.newInstance();
+ Behavior behavior = (Behavior)behaviorClass.newInstance();
_handleAttachedResourceDependencyAnnotations(FacesContext.getCurrentInstance(), behavior);
@@ -1240,7 +1254,7 @@ public class ApplicationImpl extends App
checkNull(componentType, "componentType");
checkEmpty(componentType, "componentType");
- final Class<? extends UIComponent> componentClass = _componentClassMap.get(componentType);
+ final Class<?> componentClass = getObjectFromClassMap(componentType, _componentClassMap);
if (componentClass == null)
{
log.log(Level.SEVERE, "Undefined component type " + componentType);
@@ -1249,7 +1263,7 @@ public class ApplicationImpl extends App
try
{
- UIComponent component = componentClass.newInstance();
+ UIComponent component = (UIComponent)componentClass.newInstance();
_handleAnnotations(FacesContext.getCurrentInstance(), component, component);
return component;
}
@@ -1309,7 +1323,7 @@ public class ApplicationImpl extends App
checkNull(converterId, "converterId");
checkEmpty(converterId, "converterId");
- final Class<? extends Converter> converterClass = _converterIdToClassMap.get(converterId);
+ final Class<?> converterClass = getObjectFromClassMap(converterId, _converterIdToClassMap);
if (converterClass == null)
{
throw new FacesException("Could not find any registered converter-class by converterId : " + converterId);
@@ -1317,7 +1331,7 @@ public class ApplicationImpl extends App
try
{
- final Converter converter = converterClass.newInstance();
+ final Converter converter = (Converter)converterClass.newInstance();
setConverterProperties(converterClass, converter);
@@ -1614,7 +1628,7 @@ public class ApplicationImpl extends App
checkNull(validatorId, "validatorId");
checkEmpty(validatorId, "validatorId");
- Class<?> validatorClass = _validatorClassMap.get(validatorId);
+ Class<?> validatorClass = getObjectFromClassMap(validatorId, _validatorClassMap);
if (validatorClass == null)
{
String message = "Unknown validator id '" + validatorId + "'.";
@@ -1748,27 +1762,55 @@ public class ApplicationImpl extends App
}
private void _handleAnnotations(FacesContext context, Object inspected, UIComponent component)
+ {
+ boolean isProduction = getProjectStage().equals(ProjectStage.Production);
+ Class<?> inspectedClass = inspected.getClass();
+ _handleListenerForAnnotations(context, inspected, inspectedClass, component, isProduction);
+
+ _handleResourceDependencyAnnotations(context, inspectedClass, component, isProduction);
+ }
+
+ private void _handleListenerForAnnotations(FacesContext context, Object inspected, Class<?> inspectedClass, UIComponent component, boolean isProduction)
{
- _handleListenerFor(context, inspected, component, inspected.getClass().getAnnotation(ListenerFor.class));
+ List<ListenerFor> listenerForList = null;
+ boolean isCachedList = false;
+
+ if(isProduction && _classToListenerForMap.containsKey(inspectedClass))
+ {
+ listenerForList = _classToListenerForMap.get(inspectedClass);
+ if(listenerForList == null)
+ return; //class has been inspected and did not contain any listener annotations
+
+ isCachedList = true; // else annotations were found in the cache
+ }
- ListenersFor listeners = inspected.getClass().getAnnotation(ListenersFor.class);
- if (listeners != null)
+ if(listenerForList == null) //not in production or the class hasn't been inspected yet
{
- for (ListenerFor listenerFor : listeners.value())
+ ListenerFor listener = inspectedClass.getAnnotation(ListenerFor.class);
+ ListenersFor listeners = inspectedClass.getAnnotation(ListenersFor.class);
+ if(listener != null || listeners != null)
{
- _handleListenerFor(context, inspected, component, listenerFor);
+ //listeners were found using one or both annotations, create and build a new list
+ listenerForList = new ArrayList<ListenerFor>();
+
+ if(listener != null)
+ listenerForList.add(listener);
+
+ if(listeners != null)
+ listenerForList.addAll(Arrays.asList(listeners.value()));
}
- }
-
- _handleResourceDependency(context, component, inspected.getClass().getAnnotation(ResourceDependency.class));
- ResourceDependencies dependencies = inspected.getClass().getAnnotation(ResourceDependencies.class);
- if (dependencies != null)
+ }
+
+ if (listenerForList != null) //listeners were found through inspection or from cache, handle them
{
- for (ResourceDependency dependency : dependencies.value())
+ for (ListenerFor listenerFor : listenerForList)
{
- _handleResourceDependency(context, component, dependency);
+ _handleListenerFor(context, inspected, component, listenerFor);
}
}
+
+ if(isProduction && !isCachedList) //if we're in production and the list is not yet cached, store it
+ _classToListenerForMap.put(inspectedClass, listenerForList); //null value stored for listenerForList means no annotations were found
}
private void _handleListenerFor(FacesContext context, Object inspected, UIComponent component,
@@ -1832,6 +1874,49 @@ public class ApplicationImpl extends App
}
}
+ private void _handleResourceDependencyAnnotations(FacesContext context, Class<?> inspectedClass, UIComponent component, boolean isProduction)
+ {
+ List<ResourceDependency> dependencyList = null;
+ boolean isCachedList = false;
+
+ if(isProduction && _classToResourceDependencyMap.containsKey(inspectedClass))
+ {
+ dependencyList = _classToResourceDependencyMap.get(inspectedClass);
+ if(dependencyList == null)
+ return; //class has been inspected and did not contain any resource dependency annotations
+
+ isCachedList = true; // else annotations were found in the cache
+ }
+
+ if(dependencyList == null) //not in production or the class hasn't been inspected yet
+ {
+ ResourceDependency dependency = inspectedClass.getAnnotation(ResourceDependency.class);
+ ResourceDependencies dependencies = inspectedClass.getAnnotation(ResourceDependencies.class);
+ if(dependency != null || dependencies != null)
+ {
+ //resource dependencies were found using one or both annotations, create and build a new list
+ dependencyList = new ArrayList<ResourceDependency>();
+
+ if(dependency != null)
+ dependencyList.add(dependency);
+
+ if(dependencies != null)
+ dependencyList.addAll(Arrays.asList(dependencies.value()));
+ }
+ }
+
+ if (dependencyList != null) //resource dependencies were found through inspection or from cache, handle them
+ {
+ for (ResourceDependency dependency : dependencyList)
+ {
+ _handleResourceDependency(context, component, dependency);
+ }
+ }
+
+ if(isProduction && !isCachedList) //if we're in production and the list is not yet cached, store it
+ _classToResourceDependencyMap.put(inspectedClass, dependencyList); //null value stored for dependencyList means no annotations were found
+ }
+
private void _handleResourceDependency(FacesContext context, UIComponent component, ResourceDependency annotation)
{
// If this annotation is not present on the class in question, no action must be taken.
@@ -2097,4 +2182,33 @@ public class ApplicationImpl extends App
return list;
}
}
+
+ /*
+ * private method to look for config objects on a classmap. The objects can be either a type string
+ * or a Class<?> object. This is done to facilitate lazy loading of config objects.
+ * @param id
+ * @param classMap
+ * @return
+ */
+ private Class<?> getObjectFromClassMap(String id, Map<String, Object> classMap)
+ {
+ Object obj = classMap.get(id);
+
+ if(obj == null){
+ return null; //object for this id wasn't found on the map
+ }
+
+ if(obj instanceof Class<?>)
+ {
+ return (Class<?>)obj;
+ }else if (obj instanceof String ){
+ Class<?> clazz = ClassUtils.simpleClassForName((String)obj);
+ classMap.put(id, clazz);
+ return clazz;
+ }
+
+ //object stored in the map for this id is an invalid type. remove it and return null
+ classMap.remove(id);
+ return null;
+ }
}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/lifecycle/LifecycleImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/lifecycle/LifecycleImpl.java?rev=959423&r1=959422&r2=959423&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/lifecycle/LifecycleImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/lifecycle/LifecycleImpl.java Wed Jun 30 20:26:31 2010
@@ -24,6 +24,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.FacesException;
+import javax.faces.application.ProjectStage;
import javax.faces.context.FacesContext;
import javax.faces.context.Flash;
import javax.faces.event.ExceptionQueuedEvent;
@@ -81,15 +82,15 @@ public class LifecycleImpl extends Lifec
{
try
{
- // refresh all configuration information if according web-xml parameter is set.
- // TODO: Performance wise, shouldn't the lifecycle be configured with a local boolean attribute
- // specifying if the system should look for file modification because this code seems like
- // a developement facility, but at the cost of scalability. I think a context param like
- // Trinidad is a better idea -= Simon Lessard =-
- WebXml.update(facesContext.getExternalContext());
-
- new FacesConfigurator(facesContext.getExternalContext()).update();
-
+ // check for updates of web.xml and faces-config descriptors
+ // only on a first request or if project state is not production
+ if(!_firstRequestProcessed || !facesContext.getApplication().getProjectStage().equals(ProjectStage.Production) )
+ {
+ WebXml.update(facesContext.getExternalContext());
+ new FacesConfigurator(facesContext.getExternalContext()).update();
+ }
+
+
PhaseListenerManager phaseListenerMgr = new PhaseListenerManager(this, facesContext, getPhaseListeners());
for (PhaseExecutor executor : lifecycleExecutors)
{
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java?rev=959423&r1=959422&r2=959423&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java Wed Jun 30 20:26:31 2010
@@ -141,6 +141,7 @@ public class FaceletViewDeclarationLangu
public static final String CHARACTER_ENCODING_KEY = "javax.faces.request.charset";
public final static long DEFAULT_REFRESH_PERIOD = 2;
+ public final static long DEFAULT_REFRESH_PERIOD_PRODUCTION = -1;
public final static String DEFAULT_CHARACTER_ENCODING = "UTF-8";
@@ -1352,8 +1353,12 @@ public class FaceletViewDeclarationLangu
ExternalContext eContext = context.getExternalContext();
// refresh period
- long refreshPeriod = _getLongParameter(eContext, PARAM_REFRESH_PERIOD, PARAM_REFRESH_PERIOD_DEPRECATED, DEFAULT_REFRESH_PERIOD);
-
+ long refreshPeriod;
+ if(context.getApplication().getProjectStage().equals(ProjectStage.Production))
+ refreshPeriod = _getLongParameter(eContext, PARAM_REFRESH_PERIOD, PARAM_REFRESH_PERIOD_DEPRECATED, DEFAULT_REFRESH_PERIOD_PRODUCTION);
+ else
+ refreshPeriod = _getLongParameter(eContext, PARAM_REFRESH_PERIOD, PARAM_REFRESH_PERIOD_DEPRECATED, DEFAULT_REFRESH_PERIOD);
+
// resource resolver
ResourceResolver resolver = new DefaultResourceResolver();
String faceletsResourceResolverClassName = _getStringParameter(eContext, PARAM_RESOURCE_RESOLVER, PARAM_RESOURCE_RESOLVER_DEPRECATED);
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewHandler.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewHandler.java?rev=959423&r1=959422&r2=959423&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewHandler.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewHandler.java Wed Jun 30 20:26:31 2010
@@ -31,6 +31,7 @@ import java.util.logging.Logger;
import javax.el.ELException;
import javax.faces.FacesException;
+import javax.faces.application.ProjectStage;
import javax.faces.application.StateManager;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
@@ -69,6 +70,7 @@ public class FaceletViewHandler extends
protected final static Logger log = Logger.getLogger(FaceletViewHandler.class.getName());
public final static long DEFAULT_REFRESH_PERIOD = 2;
+ public final static long DEFAULT_REFRESH_PERIOD_PRODUCTION = -1;
public final static String PARAM_REFRESH_PERIOD = "facelets.REFRESH_PERIOD";
@@ -235,8 +237,14 @@ public class FaceletViewHandler extends
{
// refresh period
- long refreshPeriod = DEFAULT_REFRESH_PERIOD;
FacesContext ctx = FacesContext.getCurrentInstance();
+ long refreshPeriod;
+
+ if(ctx.getApplication().getProjectStage().equals(ProjectStage.Production))
+ refreshPeriod = DEFAULT_REFRESH_PERIOD_PRODUCTION;
+ else
+ refreshPeriod = DEFAULT_REFRESH_PERIOD;
+
String userPeriod = ctx.getExternalContext().getInitParameter(PARAM_REFRESH_PERIOD);
if (userPeriod != null && userPeriod.length() > 0)
{