<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Devon Hillard&#039;s Digital Sanctuary &#187; cache</title>
	<atom:link href="http://www.digitalsanctuary.com/tech-blog/tag/cache/feed" rel="self" type="application/rss+xml" />
	<link>http://www.digitalsanctuary.com/tech-blog</link>
	<description>Java, ATG, Seam, and related Technologies</description>
	<lastBuildDate>Mon, 30 Jan 2012 23:04:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Flush the Cache Droplet Upon CA Deployments</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/atg/flush-the-cache-droplet-upon-ca-deployments.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/atg/flush-the-cache-droplet-upon-ca-deployments.html#comments</comments>
		<pubDate>Mon, 12 Oct 2009 18:41:09 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[ATG]]></category>
		<category><![CDATA[CA]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[Deployment]]></category>
		<category><![CDATA[droplet]]></category>
		<category><![CDATA[Event]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=515</guid>
		<description><![CDATA[Hopefully you&#8217;re already using the ATG Cache Droplet extensively in your ATG eCommerce application, as I recommended in my ATG Performance Tuning post on Improving JSP Serving Time for an ATG Application.  If you are, you&#8217;re probably using a smaller &#8230; <a href="http://www.digitalsanctuary.com/tech-blog/java/atg/flush-the-cache-droplet-upon-ca-deployments.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Hopefully you&#8217;re already using the ATG Cache Droplet extensively in your ATG eCommerce application, as I recommended in my <a title="Improving JSP Serving Time for an ATG Application" href="http://www.digitalsanctuary.com/tech-blog/java/atg/improving-jsp-serving-time-for-an-atg-application.html" target="_blank">ATG Performance Tuning post on Improving JSP Serving Time for an ATG Application</a>.  If you are, you&#8217;re probably using a smaller value for the cacheCheckSeconds parameter than you&#8217;d like, in order to prevent stale data after CA deployments update the catalog, media, or promo repositories.</p>
<p>You can solve this problem by using a component triggered by Deployment Events from the DeploymentAgent, which after a successful deployment flushes the Cache Droplet&#8217;s cache.  This should allow you to set a very long cache expiration time using the cacheCheckSeconds param, and not have to worry about displaying outdated data.</p>
<p>I&#8217;ve added this code into the <a title="Foundation the open source ATG eCommerce Framework" href="https://developer.sparkred.com/confluence/display/ATGDC/Foundation" target="_blank">open source ATG eCommerce framework Foundation</a>, hosted by <a title="Sparkred the best ATG Hosting Company" href="https://www.sparkred.com/" target="_blank">Spark::red, the best ATG Hosting Company</a> :)</p>
<p>There are three parts to this solution: the Java class, it&#8217;s properties file, and adding it to the DeploymentAgent&#8217;s list of event listeners.</p>
<p><strong>DeploymentEventCacheDropletInvalidator.java</strong></p>
<pre class="brush: java; title: ; notranslate">
/**
 * Copyright 2009 Devon Hillard (devon@digitalsanctuary.com)
 *
 * Licensed under the Apache License, Version 2.0 (the &amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;License&amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;AS IS&amp;amp;amp;amp;amp;amp;amp;amp;amp;quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package org.foundation.deployment;

import atg.deployment.common.event.DeploymentEvent;
import atg.deployment.common.event.DeploymentEventListener;
import atg.droplet.Cache;
import atg.nucleus.GenericService;
import atg.nucleus.ServiceException;

/**
 * The Class DeploymentEventCacheDropletInvalidator will flush the Cache droplet's cache upon a successful CA
 * deployment.
 *
 * @author Devon Hillard
 */
public class DeploymentEventCacheDropletInvalidator extends GenericService implements DeploymentEventListener {

    /** The Cache Droplet. */
    private Cache mCacheDroplet;

    /** The event state. */
    private int mEventState;

    /** The active. */
    private boolean mActive;

    /**
     * Deployment event handling method. This will flush the Cache droplet's cache after a CA deployment completes.
     *
     * @param pEvent the deployment event
     *
     * @see atg.deployment.common.event.DeploymentEventListener#deploymentEvent(atg.deployment.common.event.DeploymentEvent)
     */
    public void deploymentEvent(final DeploymentEvent pEvent) {
        if (isActive() &amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp; (pEvent.getNewState() == getEventState())) {
            if (isLoggingInfo()) {
                logInfo(&amp;amp;amp;quot;DeploymentEventCacheDropletInvalidator.deploymentEvent:&amp;amp;amp;quot; + &amp;amp;amp;quot;Deployment has completed.&amp;amp;amp;quot;);
            }
            getCacheDroplet().flushCache();
            if (isLoggingInfo()) {
                logInfo(&amp;amp;amp;quot;DeploymentEventCacheDropletInvalidator.deploymentEvent&amp;amp;amp;quot;
                        + &amp;amp;amp;quot;Cache droplet cache has been flushed.&amp;amp;amp;quot;;);
            }
        }
    }

    /**
     * Do start service.
     *
     * @throws ServiceException the service exception
     *
     * @see atg.nucleus.GenericService#doStartService()
     */
    @Override
    public void doStartService() throws ServiceException {
        if (isLoggingInfo()) {
            logInfo(&amp;amp;amp;quot;DeploymentEventCacheDropletInvalidator.doStartService:&amp;amp;amp;quot; + &amp;amp;amp;quot;starting up.&amp;amp;amp;quot;);
        }
        if (getCacheDroplet() == null) {
            throw new ServiceException(&amp;amp;amp;quot;DeploymentEventCacheDropletInvalidator: cache droplet was not set.&amp;amp;amp;quot;;);
        }
        if (getEventState() == 0) {
            throw new ServiceException(&amp;amp;amp;quot;DeploymentEventCacheDropletInvalidator: event state was not set.&amp;amp;amp;quot;);
        }
    }

    /**
     * Do stop service.
     *
     * @throws ServiceException the service exception
     *
     * @see atg.nucleus.GenericService#doStopService()
     */
    @Override
    public void doStopService() throws ServiceException {
        if (isLoggingInfo()) {
            logInfo(&amp;amp;amp;quot;DeploymentEventCacheDropletInvalidator.doStopService:&amp;amp;amp;quot; + &amp;amp;amp;quot;stopping.&amp;amp;amp;quot;);
        }
    }

    /**
     * Gets the Cache Droplet.
     *
     * @return the cacheDroplet
     */
    public Cache getCacheDroplet() {
        return this.mCacheDroplet;
    }

    /**
     * Sets the Cache Droplet.
     *
     * @param pCacheDroplet the cacheDroplet to set
     */
    public void setCacheDroplet(final Cache pCacheDroplet) {
        this.mCacheDroplet = pCacheDroplet;
    }

    /**
     * Gets the event state.
     *
     * @return the event state
     */
    public int getEventState() {
        return this.mEventState;
    }

    /**
     * Sets the event state.
     *
     * @param pEventState the new event state
     */
    public void setEventState(final int pEventState) {
        this.mEventState = pEventState;
    }

    /**
     * Checks if is active.
     *
     * @return true, if is active
     */
    public boolean isActive() {
        return this.mActive;
    }

    /**
     * Sets the active.
     *
     * @param pActive the new active
     */
    public void setActive(final boolean pActive) {
        this.mActive = pActive;
    }

}
</pre>
<p><strong>DeploymentEventCacheDropletInvalidator.properties</strong></p>
<pre class="brush: plain; title: ; notranslate">
$class=org.foundation.deployment.DeploymentEventCacheDropletInvalidator
$scope=global

# If true, this service will invalidate the Cache droplet's cache when the appropriate deployment event is fired.
active=true

# The cache droplet to invalidate.  Defaults to the standard Cache droplet.
cacheDroplet=/atg/dynamo/droplet/Cache

# The deployment event's newState to trigger a cache flush of the Cache droplet.
# IDLE = 1;
# DEPLOYMENT_COMPLETE = 2;
# DEPLOYMENT_DELETED = 7;
# EVENT_INTERRUPT = 6;
# ERROR = 3;
# BEGIN_LOCK = 201;
# DONE_LOCK = 202;
# ERROR_LOCK = 203;
# BEGIN_PREPARE = 301;
# DONE_PREPARE = 302;
# ERROR_PREPARE = 303;
# BEGIN_CREATE = 401;
# DONE_CREATE = 402;
# ERROR_CREATE = 403;
# BEGIN_INSTALL = 501;
# DONE_INSTALL = 502;
# ERROR_INSTALL = 503;
# BEGIN_LOAD = 601;
# DONE_LOAD = 602;
# ERROR_LOAD = 603;
# BEGIN_APPLY = 701;
# BEGIN_APPLY_COMMITTED = 702;
# DONE_APPLY = 703;
# ERROR_APPLY = 704;
# ERROR_APPLY_COMMITTED = 705;
# BEGIN_ACTIVATE = 801;
# DONE_ACTIVATE = 803;
# ERROR_ACTIVATE = 804;
# BEGIN_STOP = 901;
# DONE_STOP = 902;
# ERROR_STOP = 903;
eventState=1
</pre>
<p><strong>/atg/epub/DeploymentAgent.properties</strong></p>
<pre class="brush: plain; title: ; notranslate">
deploymentEventListeners+=\
	/foundation/deployment/DeploymentEventCacheDropletInvalidator
</pre>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Edit: at least in our cluster, the  DEPLOYMENT_COMPLETE (2) event is never triggered on the client side by the DeploymentAgent, so I&#8217;ve switched this to use the transition to IDLE (1).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/atg/flush-the-cache-droplet-upon-ca-deployments.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ATG Cache Header Control Module</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/atg/atg-cache-header-control-module.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/atg/atg-cache-header-control-module.html#comments</comments>
		<pubDate>Sun, 03 Feb 2008 03:30:05 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[ATG]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/java/atg/atg-cache-header-control-module.html</guid>
		<description><![CDATA[Many ATG application server static content, or semi-static content, from within the ATG application&#8217;s .war file. It is often much simpler to package CSS, JavaScript, Flash, Images, and other files in your web application than to try to manage them &#8230; <a href="http://www.digitalsanctuary.com/tech-blog/java/atg/atg-cache-header-control-module.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Many ATG application server static content, or semi-static content, from within the ATG application&#8217;s .war file.  It is often much simpler to package CSS, JavaScript, Flash, Images, and other files in your web application than to try to manage them separately and deploy correctly in development and production instances.</p>
<p>It is often desirable to set long cache times for static content and you may also want to ensure that certain other files or URIs are never cached.  Unfortunately ATG does not provide a mechanism for tuning the cache headers.</p>
<p>I have created a new ATG Module which allows you to easily adjust cache header times based on mime-types and URIs, including parent directories.  You can download it here: <a href='http://www.digitalsanctuary.com/tech-blog/wp-content/uploads/2008/02/dscachecontrol.zip' title='DSCacheControl ATG Cache Header Control Module' >DSCacheControl ATG Cache Header Control Module</a>.</p>
<p>I have built and tested it using ATG 7.1  I will be releasing one for ATG 2007.1 in a bit, which may be based on a Servlet Filter instead, but I haven&#8217;t decided yet.  This one may work on ATG 2007.1, I haven&#8217;t been able to test it yet.</p>
<p>It is very simple, with two classes: a pipeline servlet and a custom comparator, and two config files: the pipeline servlet&#8217;s configuration and an Initial.properties to start the servlet.  The source code is included in the module.</p>
<p>It allows you to control the cache time used to build the cache related response headers based on the requested asset&#8217;s mime-type and URI location.  It has an order of precedence of a default setting of 0 seconds (do not cache at all), then the mime-type settings are used, and then the URICacheMap is examined to find the most specific entry which is the specific URI or a parent directory.  This should allow you to setup basic settings, and override them for specific directories or files as needed.</p>
<p>Here are some example config settings to give you an idea:</p>
<p><code>mimeTypeCacheMap=image/png=604800, \<br />
				 image/jpeg=604800, \<br />
				 image/gif=604800, \<br />
			 	 application/x-javascript=604800, \<br />
  		 	 	 application/x-Shockwave-Flash=604800, \<br />
  		 	 	 flv-application/octet-stream=604800, \<br />
				 text/html=0, \<br />
				 text/css=604800</code></p>
<p><code> URICacheMap=/myapp/images=2592000, \<br />
			  /myapp/index.jsp=2342343, \<br />
			  /myapp/other.jsp=1342342, \<br />
			  /myapp/images/changing-image.jpg=3600, \<br />
			  /myapp/huge-static-jsp.jsp=2592000</code></p>
<p>To install it, simply download the zip file, unzip it, copy the module into your ATG 7.1 root directory and add the module to the list of DYNAMO_MODULES in your environment.sh (or add it using the -m option on the command line when you start ATG).  You will likely want to override the default configuration.  The .properties file is heavily commented and should be simple to understand.  You can edit it within the module if you like, although of course the better approach is to set your cache settings in your application module or in localconfig, depending.</p>
<p>If you try it, please give me your feedback.  If you enhance it, please share the code back with me.  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/atg/atg-cache-header-control-module.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced
Database Caching 1/13 queries in 0.003 seconds using disk: basic
Object Caching 321/347 objects using disk: basic

Served from: www.digitalsanctuary.com @ 2012-02-04 12:05:22 -->
