Hopefully you’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’re probably using a smaller value for the cacheCheckSeconds parameter than you’d like, in order to prevent stale data after CA deployments update the catalog, media, or promo repositories.
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’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.
I’ve added this code into the open source ATG eCommerce framework Foundation, hosted by Spark::red, the best ATG Hosting Company :)
There are three parts to this solution: the Java class, it’s properties file, and adding it to the DeploymentAgent’s list of event listeners.
DeploymentEventCacheDropletInvalidator.java
[fusion_builder_container hundred_percent=”yes” overflow=”visible”][fusion_builder_row][fusion_builder_column type=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none”][java]
/**
* Copyright 2009 Devon Hillard ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* 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 "AS IS" 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() && (pEvent.getNewState() == getEventState())) {
if (isLoggingInfo()) {
logInfo("DeploymentEventCacheDropletInvalidator.deploymentEvent:" + "Deployment has completed.");
}
getCacheDroplet().flushCache();
if (isLoggingInfo()) {
logInfo("DeploymentEventCacheDropletInvalidator.deploymentEvent"
+ "Cache droplet cache has been flushed.";);
}
}
}
/**
* Do start service.
*
* @throws ServiceException the service exception
*
* @see atg.nucleus.GenericService#doStartService()
*/
@Override
public void doStartService() throws ServiceException {
if (isLoggingInfo()) {
logInfo("DeploymentEventCacheDropletInvalidator.doStartService:" + "starting up.");
}
if (getCacheDroplet() == null) {
throw new ServiceException("DeploymentEventCacheDropletInvalidator: cache droplet was not set.";);
}
if (getEventState() == 0) {
throw new ServiceException("DeploymentEventCacheDropletInvalidator: event state was not set.");
}
}
/**
* Do stop service.
*
* @throws ServiceException the service exception
*
* @see atg.nucleus.GenericService#doStopService()
*/
@Override
public void doStopService() throws ServiceException {
if (isLoggingInfo()) {
logInfo("DeploymentEventCacheDropletInvalidator.doStopService:" + "stopping.");
}
}
/**
* 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;
}
}
[/java]
DeploymentEventCacheDropletInvalidator.properties
[/fusion_builder_column][fusion_builder_column type=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none”][plain]
$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
[/plain]
/atg/epub/DeploymentAgent.properties
[/fusion_builder_column][fusion_builder_column type=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none”][plain]
deploymentEventListeners+=\
/foundation/deployment/DeploymentEventCacheDropletInvalidator
[/plain]
——————————
Edit: at least in our cluster, the DEPLOYMENT_COMPLETE (2) event is never triggered on the client side by the DeploymentAgent, so I’ve switched this to use the transition to IDLE (1).[/fusion_builder_column][/fusion_builder_row][/fusion_builder_container]
Leave a Reply