Author: lukaszlenart Date: Sat Jul 17 10:10:46 2010 New Revision: 965050 URL: http://svn.apache.org/viewvc?rev=965050&view=rev Log: Resolved WW-3467 - Improve performance for page rendering by refactoring freemarker cache
Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java struts/struts2/trunk/core/src/main/java/org/apache/struts2/views/freemarker/FreemarkerManager.java Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java?rev=965050&r1=965049&r2=965050&view=diff ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java (original) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java Sat Jul 17 10:10:46 2010 @@ -82,9 +82,13 @@ public final class StrutsConstants { /** The org.apache.struts2.views.freemarker.FreemarkerManager implementation class */ public static final String STRUTS_FREEMARKER_MANAGER_CLASSNAME = "struts.freemarker.manager.classname"; - /** Cache Freemarker templates */ + @Deprecated + /** Cache Freemarker templates, this cache is managed by struts2,instead of native freemarker cache,set STRUTS_FREEMARKER_MRU_MAX_STRONG_SIZE >0&&STRUTS_FREEMARKER_TEMPLATES_CACHE_UPDATE_DELAY>0*/ public static final String STRUTS_FREEMARKER_TEMPLATES_CACHE = "struts.freemarker.templatesCache"; + /** Update freemarker templates cache in seconds*/ + public static final String STRUTS_FREEMARKER_TEMPLATES_CACHE_UPDATE_DELAY = "struts.freemarker.templatesCache.updateDelay"; + /** Cache model instances at BeanWrapper level */ public static final String STRUTS_FREEMARKER_BEANWRAPPER_CACHE = "struts.freemarker.beanwrapperCache"; Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java?rev=965050&r1=965049&r2=965050&view=diff ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java (original) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java Sat Jul 17 10:10:46 2010 @@ -23,16 +23,14 @@ package org.apache.struts2.components.te import java.io.IOException; import java.io.Writer; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArraySet; +import java.util.Map; +import java.util.List; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts2.ServletActionContext; -import org.apache.struts2.StrutsConstants; import org.apache.struts2.views.freemarker.FreemarkerManager; import com.opensymphony.xwork2.ActionContext; @@ -54,10 +52,6 @@ public class FreemarkerTemplateEngine ex static Class bodyContent = null; protected FreemarkerManager freemarkerManager; - protected final Map<String, freemarker.template.Template> templates = new ConcurrentHashMap<String, freemarker.template.Template>(); - protected final Set<String> missingTemplates = new CopyOnWriteArraySet<String>(); - protected boolean freemarkerCaching = false; - static { try { bodyContent = ClassLoaderUtil.loadClass("javax.servlet.jsp.tagext.BodyContent", @@ -97,24 +91,6 @@ public class FreemarkerTemplateEngine ex Exception exception = null; for (Template t : templates) { templateName = getFinalTemplateName(t); - if (freemarkerCaching) { - if (!isTemplateMissing(templateName)) { - try { - template = findInCache(templateName); // look in cache first - if (template == null) { - // try to load, and if it works, stop at the first one - template = config.getTemplate(templateName); - addToCache(templateName, template); - } - break; - } catch (IOException e) { - addToMissingTemplateCache(templateName); - if (exception == null) { - exception = e; - } - } - } - } else { try { // try to load, and if it works, stop at the first one template = config.getTemplate(templateName); @@ -129,7 +105,6 @@ public class FreemarkerTemplateEngine ex exception = e; } } - } } if (template == null) { @@ -189,39 +164,5 @@ public class FreemarkerTemplateEngine ex return "ftl"; } - protected void addToMissingTemplateCache(String templateName) { - missingTemplates.add(templateName); - } - - protected boolean isTemplateMissing(String templateName) { - return missingTemplates.contains(templateName); - } - protected void addToCache(String templateName, - freemarker.template.Template template) { - templates.put(templateName, template); - } - - protected freemarker.template.Template findInCache(String templateName) { - return templates.get(templateName); - } - - /** - * Enables or disables Struts caching of Freemarker templates. By default disabled. - * Set struts.freemarker.templatesCache=true to enable cache - * @param cacheTemplates "true" if the template engine should cache freemarker template - * internally - */ - @Inject(StrutsConstants.STRUTS_FREEMARKER_TEMPLATES_CACHE) - public void setCacheTemplates(String cacheTemplates) { - freemarkerCaching = "true".equals(cacheTemplates); - } - - /** - * Clear the templates and missing templates cache - */ - public void clearTemplatesCache() { - templates.clear(); - missingTemplates.clear(); - } } Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java?rev=965050&r1=965049&r2=965050&view=diff ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java (original) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java Sat Jul 17 10:10:46 2010 @@ -26,7 +26,6 @@ import java.util.StringTokenizer; import org.apache.struts2.StrutsConstants; import org.apache.struts2.components.UrlRenderer; -import org.apache.struts2.dispatcher.DefaultStaticContentLoader; import org.apache.struts2.dispatcher.StaticContentLoader; import org.apache.struts2.dispatcher.mapper.ActionMapper; import org.apache.struts2.dispatcher.multipart.MultiPartRequest; @@ -222,6 +221,7 @@ public class BeanSelectionProvider imple props.setProperty(StrutsConstants.STRUTS_I18N_RELOAD, "true"); props.setProperty(StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD, "true"); props.setProperty(StrutsConstants.STRUTS_FREEMARKER_TEMPLATES_CACHE, "false"); + props.setProperty(StrutsConstants.STRUTS_FREEMARKER_TEMPLATES_CACHE_UPDATE_DELAY, "0"); // Convert struts properties into ones that xwork expects props.setProperty("devMode", "true"); } else { Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/views/freemarker/FreemarkerManager.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/views/freemarker/FreemarkerManager.java?rev=965050&r1=965049&r2=965050&view=diff ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/views/freemarker/FreemarkerManager.java (original) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/views/freemarker/FreemarkerManager.java Sat Jul 17 10:10:46 2010 @@ -50,14 +50,12 @@ import freemarker.cache.FileTemplateLoad import freemarker.cache.MultiTemplateLoader; import freemarker.cache.TemplateLoader; import freemarker.cache.WebappTemplateLoader; -import freemarker.ext.beans.BeansWrapper; import freemarker.ext.jsp.TaglibFactory; import freemarker.ext.servlet.HttpRequestHashModel; import freemarker.ext.servlet.HttpRequestParametersHashModel; import freemarker.ext.servlet.HttpSessionHashModel; import freemarker.ext.servlet.ServletContextHashModel; import freemarker.template.*; -import freemarker.core.Configurable; import freemarker.template.utility.StringUtil; @@ -117,7 +115,6 @@ public class FreemarkerManager { // Note these names start with dot, so they're essentially invisible from a freemarker script. private static final String ATTR_REQUEST_MODEL = ".freemarker.Request"; private static final String ATTR_REQUEST_PARAMETERS_MODEL = ".freemarker.RequestParameters"; - private static final String ATTR_SESSION_MODEL = ".freemarker.Session"; private static final String ATTR_APPLICATION_MODEL = ".freemarker.Application"; private static final String ATTR_JSP_TAGLIBS_MODEL = ".freemarker.JspTaglibs"; @@ -169,6 +166,7 @@ public class FreemarkerManager { protected boolean altMapWrapper; protected boolean cacheBeanWrapper; protected int mruMaxStrongSize; + protected String templateUpdateDelay; protected Map<String,TagLibrary> tagLibraries; @Inject(StrutsConstants.STRUTS_I18N_ENCODING) @@ -191,6 +189,11 @@ public class FreemarkerManager { mruMaxStrongSize = Integer.parseInt(size); } + @Inject(value = StrutsConstants.STRUTS_FREEMARKER_TEMPLATES_CACHE_UPDATE_DELAY, required = false) + public void setTemplateUpdateDelay(String delay) { + templateUpdateDelay = delay; + } + @Inject public void setContainer(Container container) { Map<String,TagLibrary> map = new HashMap<String,TagLibrary>(); @@ -229,7 +232,7 @@ public class FreemarkerManager { return contentType; } - public synchronized freemarker.template.Configuration getConfiguration(ServletContext servletContext) { + public synchronized Configuration getConfiguration(ServletContext servletContext) { if (config == null) { try { init(servletContext); @@ -287,15 +290,17 @@ public class FreemarkerManager { * * @param servletContext */ - protected freemarker.template.Configuration createConfiguration(ServletContext servletContext) throws TemplateException { - freemarker.template.Configuration configuration = new freemarker.template.Configuration(); + protected Configuration createConfiguration(ServletContext servletContext) throws TemplateException { + Configuration configuration = new Configuration(); configuration.setTemplateExceptionHandler(TemplateExceptionHandler.HTML_DEBUG_HANDLER); if (mruMaxStrongSize > 0) { - configuration.setSetting(freemarker.template.Configuration.CACHE_STORAGE_KEY, "strong:" + mruMaxStrongSize); + configuration.setSetting(Configuration.CACHE_STORAGE_KEY, "strong:" + mruMaxStrongSize); + } + if (templateUpdateDelay != null) { + configuration.setSetting(Configuration.TEMPLATE_UPDATE_DELAY_KEY, templateUpdateDelay); } - if (encoding != null) { configuration.setDefaultEncoding(encoding); } @@ -333,17 +338,8 @@ public class FreemarkerManager { // Create hash model wrapper for session HttpSession session = request.getSession(false); - HttpSessionHashModel sessionModel; if (session != null) { - sessionModel = (HttpSessionHashModel) session.getAttribute(ATTR_SESSION_MODEL); - if (sessionModel == null) { - sessionModel = new HttpSessionHashModel(session, wrapper); - session.setAttribute(ATTR_SESSION_MODEL, sessionModel); - } model.put(KEY_SESSION, new HttpSessionHashModel(session, wrapper)); - } else { - // no session means no attributes ??? - // model.put(KEY_SESSION_MODEL, new SimpleHash()); } // Create hash model wrapper for the request attributes @@ -525,19 +521,4 @@ public class FreemarkerManager { } } - /** - * If the parameter "nocache" was set to true, generate a set of headers - * that will advise the HTTP client not to cache the returned page. - */ - private void setBrowserCachingPolicy(HttpServletResponse res) { - if (nocache) { - // HTTP/1.1 + IE extensions - res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, " - + "post-check=0, pre-check=0"); - // HTTP/1.0 - res.setHeader("Pragma", "no-cache"); - // Last resort for those that ignore all of the above - res.setHeader("Expires", EXPIRATION_DATE); - } - } }