<?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 Tech Blog &#187; ATG</title>
	<atom:link href="http://www.digitalsanctuary.com/tech-blog/category/java/atg/feed" rel="self" type="application/rss+xml" />
	<link>http://www.digitalsanctuary.com/tech-blog</link>
	<description>Java, ATG, Seam, and related Technologies</description>
	<lastBuildDate>Thu, 01 Jul 2010 21:06:32 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Guide for Large Scale ATG Applications</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/atg/guide-for-large-scale-atg-applications.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/atg/guide-for-large-scale-atg-applications.html#comments</comments>
		<pubDate>Fri, 07 May 2010 02:34:01 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[ATG]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=631</guid>
		<description><![CDATA[Kelly Goetsch has written a very impressive 64 page guide on the development and deployment of very large scalable ATG e-Commerce applications.  There&#8217;s a ton of great information (a little bit came from me!) and it&#8217;s a worth-while read, even if your application isn&#8217;t running on 200 production servers.  Unfortunately you have to [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.kellygoetsch.com/">Kelly Goetsch</a> has written a very impressive 64 page guide on the development and deployment of very large scalable ATG e-Commerce applications.  There&#8217;s a ton of great information (a little bit came from me!) and it&#8217;s a worth-while read, even if your application isn&#8217;t running on 200 production servers.  Unfortunately you have to have an <a href="http://www.atg.com">atg.com</a> account AND be associated with an active support contract in order to read it.</p>
<p>If you do, check it out: <a href="https://community.atg.com/docs/DOC-1871">https://community.atg.com/docs/DOC-1871</a></p>
<p>Obligitory Spark::red <a href="https://www.sparkred.com">ATG Hosting</a> plug: The three founders all worked on AT&#038;T&#8217;s massive ATG e-Commerce cluster, so we understand how to scale ATG to hundreds of nodes, and how to squeeze out maximal performance and stability out of clusters of any size.</p>
<p class="facebook"><a href="http://www.facebook.com/share.php?u=http://www.digitalsanctuary.com/tech-blog/java/atg/guide-for-large-scale-atg-applications.html" target="_blank" title="Share on Facebook">Share on Facebook</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/atg/guide-for-large-scale-atg-applications.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ATG Newsletter Went Out</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/atg/atg-newsletter-went-out.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/atg/atg-newsletter-went-out.html#comments</comments>
		<pubDate>Thu, 22 Apr 2010 00:56:52 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[ATG]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[PCI]]></category>
		<category><![CDATA[Spark::red]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=625</guid>
		<description><![CDATA[Our first Spark::red ATG Newsletter was sent on Tuesday morning!  We&#8217;re pleased and proud to have delivered the first of many monthly ATG Newsletters.
In this newsletter we talk about the importance of improving your site performance, especially now that Google is using site performance as a search result ranking factor.  We talk about [...]]]></description>
			<content:encoded><![CDATA[<p>Our first <a href="https://www.sparkred.com/subscribe-atg-newsletter.xhtml">Spark::red ATG Newsletter</a> was sent on Tuesday morning!  We&#8217;re pleased and proud to have delivered the first of many monthly ATG Newsletters.</p>
<p>In this newsletter we talk about the importance of improving your site performance, especially now that Google is using site performance as a search result ranking factor.  We talk about Why, and provide several helpful links to help with How.  I&#8217;d be remiss if I didn&#8217;t plug the fantastic<a href="https://www.sparkred.com"> ATG Hosting that Spark::red</a> can provide, including extensive performance tuning at every level, web, app and database, using knowledge gained from 12 years of ATG experience.  </p>
<p>We also reveal our PCI Compliant ATG Encryption Module which is the first PCI complaint credit card encryption option for the ATG eCommerce Platform.  It handles strong encryption, key management, importing plain text and encrypted data, periodic re-keying/re-encryption, and more.  It&#8217;s the fastest and most affordable path to being able to pass a PCI audit for your ATG eCommerce application.  Contact us for more info: <a href="mailto:sales@sparkred.com">sales@sparkred.com</a>.</p>
<p>You can see the whole newsletter here: <a href="https://www.sparkred.com/static/atg-newsletter/Sparkred-ATG-Newsletter-1.pdf">Spark::red ATG Newsletter #1</a>, and if you haven&#8217;t already, I recommend signing up so you don&#8217;t miss the next one: <a href="https://www.sparkred.com/subscribe-atg-newsletter.xhtml">Sign Up for the Sparkred ATG Newsletter</a>!</p>
<p class="facebook"><a href="http://www.facebook.com/share.php?u=http://www.digitalsanctuary.com/tech-blog/java/atg/atg-newsletter-went-out.html" target="_blank" title="Share on Facebook">Share on Facebook</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/atg/atg-newsletter-went-out.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Sparkred Launches an ATG Mailing List</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/atg/sparkred-launches-an-atg-mailing-list.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/atg/sparkred-launches-an-atg-mailing-list.html#comments</comments>
		<pubDate>Tue, 16 Mar 2010 04:17:23 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[ATG]]></category>
		<category><![CDATA[Spark::red]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=605</guid>
		<description><![CDATA[Over at Spark::red ATG Hosting we&#8217;ve decided to launch a monthly newsletter.  Once a month we&#8217;ll send out an e-mail with some very useful ATG content, technical tips and source code, business tricks and advice on leveraging ATG products to increase sales.  We&#8217;ll talk about PCI compliance and how to reduce cart abandonment.
We [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_607" class="wp-caption alignright" style="width: 160px"><img src="http://www.digitalsanctuary.com/tech-blog/wp-content/uploads/2010/03/4181548138_42a74b20c3-150x150.jpg" alt="" title="Extra Extra, Read All About It" width="150" height="150" class="size-thumbnail wp-image-607" /><p class="wp-caption-text">photo by <a href='http://www.flickr.com/photos/realdeal09/'>The World Wants a Real Deal</a></p></div>
<p>Over at <a href="https://www.sparkred.com">Spark::red ATG Hosting</a> we&#8217;ve decided to launch a monthly newsletter.  Once a month we&#8217;ll send out an e-mail with some very useful <a href="http://www.atg.com">ATG</a> content, technical tips and source code, business tricks and advice on leveraging ATG products to increase sales.  We&#8217;ll talk about PCI compliance and how to reduce cart abandonment.</p>
<p>We won&#8217;t send more than one e-mail a month, we won&#8217;t spam you, bug you, bother you, or waste your time.  Each mailing will be as packed full of genuinely useful information as possible.  </p>
<p><a href="https://www.sparkred.com/atg-newsletter-signup.html">Sign up for the world&#8217;s best ATG Technology and Business Newsletter</a>!</p>
<p class="facebook"><a href="http://www.facebook.com/share.php?u=http://www.digitalsanctuary.com/tech-blog/java/atg/sparkred-launches-an-atg-mailing-list.html" target="_blank" title="Share on Facebook">Share on Facebook</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/atg/sparkred-launches-an-atg-mailing-list.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Make Google Ignore JSESSIONID</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/jboss/make-google-ignore-jsessionid.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/jboss/make-google-ignore-jsessionid.html#comments</comments>
		<pubDate>Wed, 17 Feb 2010 04:35:28 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[ATG]]></category>
		<category><![CDATA[JBoss]]></category>
		<category><![CDATA[Seam]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[GoogleBot]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=582</guid>
		<description><![CDATA[Search engines like Google will often index content with params like JSESSIONID and other session or conversation scope params.  This causes two problems: first the links returned in the Google search results can have these parameters in them, resulting in &#8220;session not found&#8221; or other incompatible session state issues.  Secondly it can cause [...]]]></description>
			<content:encoded><![CDATA[<p>Search engines like Google will often index content with params like JSESSIONID and other session or conversation scope params.  This causes two problems: first the links returned in the Google search results can have these parameters in them, resulting in &#8220;session not found&#8221; or other incompatible session state issues.  Secondly it can cause a single page of content, to be indexed multiple times (with differing parameters) this diluting your page&#8217;s rank.</p>
<p>I&#8217;ve posted two solutions to this issue in the past: <a href="http://www.digitalsanctuary.com/tech-blog/general/hiding-jsessionid-parameter-from-google.html">Using Apache to ReWrite URLs to remove JSESSIONID</a> and a more advanced solution of using a <a href="http://www.digitalsanctuary.com/tech-blog/general/jboss-jsessionid-parameter-remove.html">Servlet Filter to avoid adding JSESSIONID for GoogleBot Requests</a>.</p>
<p>Now there&#8217;s an even better way to handle this.  Google has added an amazing new feature to their Webmaster Tools which allows you to specify how the GoogleBot indexer should handle various parameters.  You can ignore certain parameters such as JSESSIONID, cid, and others, and also specifically not ignore other parameters such as productId, skuId, etc&#8230;</p>
<p>Log into your Google Webmaster Tools, and select the site you wish to work with.  Under &#8220;Site Configuration&#8221; -> &#8220;Settings&#8221; there is a new section at the bottom called &#8220;Parameter handling&#8221;.  Click on &#8220;adjust parameter settings&#8221; to expand the parameter handling configuration for your site.  Sometimes Google will suggest various parameters it has discovered while crawling your site, and other times you just enter the parameters you want Google to ignore or pay attention to.  </p>
<div id="attachment_583" class="wp-caption alignnone" style="width: 736px"><img src="http://www.digitalsanctuary.com/tech-blog/wp-content/uploads/2010/02/Parameter-Handling.png" alt="" title="Parameter Handling" width="726" height="280" class="size-full wp-image-583" /><p class="wp-caption-text">Google Webmaster Tools Parameter Handling Interface</p></div>
<p>This is a much more elegant solution to the JSESSIONID problem, and also allows you to easily handle other parameters your site may use for either session state or dynamic content generation correctly.  The only downside is that this only impacts Google, whereas with the correct configuration my older two solutions can handle any Search Engine Bot.  Maybe other search providers will or do provide a similar feature.</p>
<p class="facebook"><a href="http://www.facebook.com/share.php?u=http://www.digitalsanctuary.com/tech-blog/java/jboss/make-google-ignore-jsessionid.html" target="_blank" title="Share on Facebook">Share on Facebook</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/jboss/make-google-ignore-jsessionid.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Why ATG&#8217;s Core Based Licensing is Stupid</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/atg/why-atgs-core-based-licensing-is-stupid.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/atg/why-atgs-core-based-licensing-is-stupid.html#comments</comments>
		<pubDate>Wed, 03 Feb 2010 00:22:32 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[ATG]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=556</guid>
		<description><![CDATA[ATG, like most enterprise software companies started by licensing their product based on how many CPUs you ran it on.  Back in 1999 this was a pretty fair way to do things.  It meant that big companies running a very high traffic site on a big Sun E4500 or E10k paid a lot [...]]]></description>
			<content:encoded><![CDATA[<p><a href="https://www.atg.com/">ATG</a>, like most enterprise software companies started by licensing their product based on how many CPUs you ran it on.  Back in 1999 this was a pretty fair way to do things.  It meant that big companies running a very high traffic site on a big Sun E4500 or E10k paid a lot more than a smaller company running on a pair of E450s.  They handled more traffic and hence ideally made more money off of the site, and therefore paid more.  Overall it was a decently fair model, and very easy to enforce in the software.  Upon startup the software checks to see how many CPUs the server has and checks that against the license file and only starts if the license file matches or exceeds the CPU count.  Makes sense, right?  Most folks were doing the same thing at the time.</p>
<p>One aspect of this system is that year over year, as processors got faster and faster (from 250 MHz to 480 MHz for example), you got more power for the same licensing cost.  In generally this was partially or fully offset by the increasing complexity of the software you were running, but worst case scenario it kept you from LOSING request handling ability over time, and best case scenario you were able to increase your traffic handling ability a bit, as <a href="http://en.wikipedia.org/wiki/Moore's_law">Moore&#8217;s law</a> drove clock speeds up.</p>
<div id="attachment_557" class="wp-caption alignnone" style="width: 560px"><a href="http://www.digitalsanctuary.com/tech-blog/wp-content/uploads/2010/02/CPU.png"><img src="http://www.digitalsanctuary.com/tech-blog/wp-content/uploads/2010/02/CPU-550x548.png" alt="" title="CPU Speeds" width="550" height="548" class="size-medium wp-image-557" /></a><p class="wp-caption-text"><a href='http://www.gotw.ca/publications/concurrency-ddj.htm'>from http://www.gotw.ca/publications/concurrency-ddj.htm</a></p></div>
<p>On the chart above you see the green line which is the number of transistors on a CPU growing just like you&#8217;d expect from Moore&#8217;s law.  This line can be thought to translate roughly to performance, and has been on this trend for over 30 years.</p>
<p>However, the blue line, which is clock speed (MHz or GHz) does something very odd around 2003.  It flattens out.  What happened?</p>
<p>Processor design changed.  Due to some limitations in our current chip technology, going faster and faster (and smaller and smaller) couldn&#8217;t keep happening due to some physical and quantum limitations.  So instead, companies like Intel and AMD began designing and building CPUs that had multiple &#8220;cores&#8221;.  They went wider instead of faster.  Basically each core is like a mini-CPU that, if your software supports it, means you can get more work done per second without having to have a faster clock speed.  </p>
<p>Instead of a CPU with a single 3.4 GHz core, we have a CPU with four 2.66 GHz cores.  Now keep in mind that the actual useful performance of the CPU kept climbing as it has for the last 30 years.  It&#8217;s just that instead of faster clock speeds, we moved into multiple cores.  </p>
<p>The problem is that software reports each &#8220;core&#8221; as a CPU.  That means a server with a single quad-core CPU appears to be a 4 CPU server.  That means CPU/core based licensing now costs FOUR TIMES AS MUCH as it did last year for the same request handling ability.  We&#8217;re not taking hundreds of dollars here.  We&#8217;re talking hundreds of thousands or millions of dollars for each customer.</p>
<p>To make matters worse the latest generation of CPUs, Intel&#8217;s <a href="http://en.wikipedia.org/wiki/Nehalem_(microarchitecture)">Nehalems</a>, use something called <a href="http://en.wikipedia.org/wiki/Hyper-threading">HyperThreading</a> to make each core do more work.  The upside is this generation of chips performs better than the old ones, as they should.  The downside is they now report as twice as many actual cores, due to the HyperThreading.  A quad core single CPU now reports as 8 CPUs.  You can disable HyperThreading, but that actually introduces a 20-40% performance penalty (depending on how you benchmark it, etc&#8230;), so in most cases you&#8217;re actually getting LESS performance than you did from last years chips.  At that point you can either cough up another $500,000 in license costs, or have your brand new server be slower than your old one.  Great options.</p>
<p>Fortunately most companies saw this issue when it first reared its ugly head back in 2003, and have moved to socket based licensing.  They are basically licensing the same way they always have, just redefining the CPU as the &#8220;socket&#8221; or the physical spot on the motherboard the CPU plugs into, and getting away from things like cores, hyperthreading, and that whole mess.  Customers of companies which made that change (such as Oracle, JBoss, and many others) essentially end up paying the same as they always have, and everyone goes home happy.  The licensing cost/performance curve for those folks has stayed pretty stable over the past 10-15 years.  </p>
<p>Unfortunately ATG has not changed their licensing at all.  This means that ATG customers are paying 4-8 times as much for licenses than they would be in 2002.  And it&#8217;s only getting worse.  Processor design is continuing to go wider not faster, and ATG customers will continue to be massively penalized by this CPU architecture trend.</p>
<p>I&#8217;ve spoken to many people at ATG, and the response is generally the same:  &#8220;We understand what you&#8217;re saying, we are aware of CPU architecture changes.  But changing our licensing is a big deal and takes time to do right.&#8221;  Okay, I buy that.  You&#8217;ve had SEVEN years so far!  This has been a growing issue since ~2003 and one that pretty much all the other players in the space have handled since then.  </p>
<p>I posted about this almost two years ago in my <a href="http://www.digitalsanctuary.com/tech-blog/java/atg/rant-about-core-based-licensing.html">Rant About Core Based Licensing</a>, but unfortunately nothing has changed on the ATG front.</p>
<p>It&#8217;s getting harder and harder to get dual core CPU servers, and pretty soon you won&#8217;t be able to get anything smaller than a Nehalem quad with HyperThreading.  This means that out of the box, if you want two small servers (for redundancy) you will need 16 cores of ATG Commerce licensing.  That&#8217;s millions of dollars.  If you disable HyperThreading, and take the 20%+ performance penalty, you &#8220;only&#8221; need 8 cores of ATG Commerce licensing.  That&#8217;s still probably close to a million dollars (I don&#8217;t have actual costs handy).  Not only is ATG penalizing all of their existing customers, but they&#8217;re really forcing themselves out of the mid-market they are trying to target.</p>
<p>The ATG &#8220;starter&#8221; bundles are becoming impossible to implement due to this as well.  &#8220;two cores of commerce&#8221; means you can run a single server, which doesn&#8217;t offer any redundancy.  &#8220;four cores of commerce&#8221; means if you can manage to find new servers that still have a single dual core proc available, you&#8217;re limited to really old and slow chips.  For instance, looking at available single processor servers from one major hosting provider, the &#8220;best&#8221; dual core you can get is a Xeon 3060 dual core 2.4 GHz with a 4 MB cache and 667 MHz RAM bus speed.  The best single single processor available is a Nehalem 5570 with a quad 2.93 GHz HyperThreaded chip with 8 MB caches and 1333 MHz RAM bus speed.  Real world I&#8217;d expect the Nehalem to deliver at least four times the request handling ability as the 3060, if not more.  If you&#8217;re using Oracle, JBoss, or almost any other piece of enterprise commercial software out there, you, the customer, can leverage the best hardware and get more bang for your license buck.  You can upgrade and quadruple your real world performance for free (like you&#8217;ve been able to do for years and years).  If you&#8217;re on ATG, the modern server will quadruple your price instead.</p>
<p>So if you&#8217;re an ATG customer, ATG partner, or ATG employee, be aware of this issue, and try to get ATG to adopt socket based pricing.  Thanks.  Exponentially increasing software costs hurt the customers in the short term, and will hurt ATG in the long term.</p>
<p class="facebook"><a href="http://www.facebook.com/share.php?u=http://www.digitalsanctuary.com/tech-blog/java/atg/why-atgs-core-based-licensing-is-stupid.html" target="_blank" title="Share on Facebook">Share on Facebook</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/atg/why-atgs-core-based-licensing-is-stupid.html/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Terrible Code</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/atg/terrible-code.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/atg/terrible-code.html#comments</comments>
		<pubDate>Tue, 03 Nov 2009 02:57:34 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[ATG]]></category>
		<category><![CDATA[development practices]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=526</guid>
		<description><![CDATA[
request.setParameter(&#34;qualifySkus&#34;, getSkusRepository(d, cItem));


&#8220;qualifySkus&#8221; is confusing.  Is it an array/list/collection of &#8220;qualifiedSKUs&#8221; or a flag that&#8217;s a result of &#8220;qualifyingSkus&#8221; or&#8230;.  
&#8220;qualifySKus&#8221; should be a constant with a nice comment, not an in-line String.
The method getSkusRespository seems like it would return a catalog repository, doesn&#8217;t it?  Instead it takes in a List of [...]]]></description>
			<content:encoded><![CDATA[<pre class="brush: java;">
request.setParameter(&quot;qualifySkus&quot;, getSkusRepository(d, cItem));
</pre>
<ol>
<li>&#8220;qualifySkus&#8221; is confusing.  Is it an array/list/collection of &#8220;qualifiedSKUs&#8221; or a flag that&#8217;s a result of &#8220;qualifyingSkus&#8221; or&#8230;.  </li>
<li>&#8220;qualifySKus&#8221; should be a constant with a nice comment, not an in-line String.</li>
<li>The method getSkusRespository seems like it would return a catalog repository, doesn&#8217;t it?  Instead it takes in a List of String SkuIds, loads up the corresponding SKU RepositoryItems, removes any that have the property &#8220;isLive&#8221; set to false, and removes any that have a current inventory stock level of zero.  It then returns an ArrayList of those filtered SKU RepositoryItems.  Perhaps a better name might be &#8220;getLiveInStockSKUs&#8221;?</li>
<li>What on earth is &#8220;d&#8221;?  Even looking at the full code of this class, it&#8217;s very difficult to tell what d is meant to contain.  It&#8217;s actually a List of Strings of SkuIds that are qualifying skus for a given promo.  &#8220;qualifiedSkus&#8221; would be a better name.</li>
<li>cItem is a commerce item.  However it&#8217;s not actually used by the getSkusRepository method at all.  There&#8217;s no reason to pass it in.</li>
<li>This line is in an ATG droplet and shoves the result of the getSkusRepository method into a request param before servicing an oparam.  However, as you can see, it doesn&#8217;t inspect the output of the method.  As I explained above, the method actually filters a list of SKUs based on isLive and current inventory state.  It&#8217;s very possible that there will be no live and in-stock SKUs, and the param&#8217;s value will be null or an empty list.  In that case, we&#8217;d actually want to render a different oparam, which is defined and called elsewhere, but not here.  Validate your output!</li>
</ol>
<p>That&#8217;s six issues in one line.  Please don&#8217;t write code like this.</p>
<p class="facebook"><a href="http://www.facebook.com/share.php?u=http://www.digitalsanctuary.com/tech-blog/java/atg/terrible-code.html" target="_blank" title="Share on Facebook">Share on Facebook</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/atg/terrible-code.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<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 value for the cacheCheckSeconds parameter than you&#8217;d like, in order to prevent stale data after [...]]]></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> <img src='http://www.digitalsanctuary.com/tech-blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </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;">
/**
 * 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;">
$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;">
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>
<p class="facebook"><a href="http://www.facebook.com/share.php?u=http://www.digitalsanctuary.com/tech-blog/java/atg/flush-the-cache-droplet-upon-ca-deployments.html" target="_blank" title="Share on Facebook">Share on Facebook</a></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 Commerce MC Edition Hosting Bundle</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/atg/atg-commerce-mc-edition-hosting-bundle.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/atg/atg-commerce-mc-edition-hosting-bundle.html#comments</comments>
		<pubDate>Mon, 24 Aug 2009 16:27:06 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[ATG]]></category>
		<category><![CDATA[ecommerce]]></category>
		<category><![CDATA[hosting]]></category>
		<category><![CDATA[Spark::red]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=476</guid>
		<description><![CDATA[ATG offers a &#8220;starter pack&#8221; of their eCommerce solution for smaller customers called the MC Edition.  ATG Hosting provider Spark::red has just announced a special ATG eCommerce Hosting Bundle designed for customers with the ATG MC Edition eCommerce licenses.
Spark::red is pleased to offer a hosting package designed specifically for ATG MC4 customers.  By [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.atg.com" target="_new">ATG</a> offers a &#8220;starter pack&#8221; of their eCommerce solution for smaller customers called the MC Edition.  ATG Hosting provider Spark::red has just announced a special <a href="https://www.sparkred.com/solutions/atg_commerce_mc_edition_bundle.xhtml">ATG eCommerce Hosting Bundle</a> designed for customers with the ATG MC Edition eCommerce licenses.</p>
<blockquote><p>Spark::red is pleased to offer a hosting package designed specifically for ATG MC4 customers.  By providing an affordable solution tailored to the licenses and needs of the MC4 customer, and by delivering all of the required Oracle, JBoss, and RedHat licenses and support agreements, this package is the fastest way to launch an ATG Commerce application.</p></blockquote>
<p><a href="https://www.sparkred.com">Spark::red</a> is the only hosting provider with a package designed for ATG MC Edition customers.  This should make it much easier for mid-market customers to get started with ATG&#8217;s eCommerce software.</p>
<p class="facebook"><a href="http://www.facebook.com/share.php?u=http://www.digitalsanctuary.com/tech-blog/java/atg/atg-commerce-mc-edition-hosting-bundle.html" target="_blank" title="Share on Facebook">Share on Facebook</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/atg/atg-commerce-mc-edition-hosting-bundle.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ATG SEO &#8211; Search Engine Optimization</title>
		<link>http://www.digitalsanctuary.com/tech-blog/general/atg-search-engine-optimization-seo.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/general/atg-search-engine-optimization-seo.html#comments</comments>
		<pubDate>Mon, 27 Apr 2009 14:54:34 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[ATG]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[seo]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=296</guid>
		<description><![CDATA[
No matter how good your website or web application is, if people can&#8217;t find it, then it doesn&#8217;t do anyone any good.
The Secret to SEO
So how do you game Google?  How do you trick search engines to put you at the top?
You don&#8217;t.
The &#8220;secret&#8221; to search engines is that they are built to return [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.digitalsanctuary.com/tech-blog/wp-content/uploads/2009/04/3345754367_761b4f95a4jpg-150x150.jpg" alt="Search is Rocking" title="Search is Rocking" width="300" height="200" class="alignright size-full wp-image-367" /></p>
<p>No matter how good your website or web application is, if people can&#8217;t find it, then it doesn&#8217;t do anyone any good.</p>
<h2>The Secret to SEO</h2>
<p>So how do you game Google?  How do you trick search engines to put you at the top?</p>
<p><strong>You don&#8217;t.</strong></p>
<p>The &#8220;secret&#8221; to search engines is that they are built to return the most useful relevant results. All you have to do is to build your site in accordance with standards, common sense, and have it be helpful or useful. The upside to taking these elements into consideration is that not only will it help people find your site, but often it will improve the experience on the site as well.</p>
<p>I&#8217;m going to cover aspects of your site such as head tags, semantic tags, standards and accessibility, URL structures, limitations to be aware of, how to test what GoogleBot sees, tools to check your site with, and how to boost your Google ranking using means beyond just fixing up your site.</p>
<p>These pointers will apply to any website, but I will make some specific recommendations and provide some sample code for ATG sites, which are often not very SEO friendly, despite best intentions.</p>
<h2>Head Meta Tags &#8211; Title, Description, and Keywords</h2>
<p>The first important things that the search engine will see in your HTML are the tags in the head section of the HTML. There are three that we care about, Title, Description, and Keywords.</p>
<h4>Title</h4>
<p>The Title meta tag should uniquely identify the content of the page. Every page should have a different title, and the title should describe the content of the page accurately and succinctly. My preference is to put the site name after the unique portion of the title, like &#8220;Men&#8217;s Shoes &#8211; MyShoeStore.com&#8221; or &#8220;Men&#8217;s Fluevog Size 12 &#8211; MyShoeStore.com&#8221;. The content of the title should be relevant to the content on the page, words from the title should be found prominently within the page content.</p>
<p>When you&#8217;re using a template or including a shared header file, as is common in many dynamic sites, especially ATG sites, you need to pass in the unique title as a param.</p>
<p>Within your header page you use code like this:</p>
<pre class="brush: xml;">
&lt;title&gt;&lt;dsp:valueof param=&quot;title&quot;&gt;Shoes&lt;/dsp:valueof&gt; - MyShoeStore.com&lt;/title&gt;
</pre>
<p>And from within the calling page you pass in a title like this:</p>
<pre class="brush: xml;">
&lt;dsp:include page=&quot;fragments/page-header.jsp&quot;&gt;
     &lt;dsp:param name=&quot;title&quot; value=&quot;Contact Us&quot; /&gt;
&lt;/dsp:include&gt;
</pre>
<p>Or with catalog data, like this:</p>
<pre class="brush: xml;">
&lt;dsp:include page=&quot;fragments/page-header.jsp&quot;&gt;
     &lt;dsp:param name=&quot;title&quot; param=&quot;category.displayName&quot; /&gt;
&lt;/dsp:include&gt;
</pre>
<p>The other thing to keep in mind is that the Title is the default name of the bookmark if the user bookmarks the page. It needs to be clear, concise and helpful, and should make it easy for the user to find among their other bookmarks.</p>
<h4>Description</h4>
<p>The description meta tag should contain a longer description of the page content. It should be no longer than 160 characters, and should use terms that are highly relevant for the page content, and are repeated within the page.</p>
<p>For dynamic sites, including ATG, I recommend the same approach as above for the title tag.</p>
<h4>Keywords</h4>
<p>The keywords meta tag should contain close to eight keywords which best represent the content of the page, and terms that people might use to search for similar content. Those keywords should feature prominently within the page content itself.</p>
<p>For dynamic sites, including ATG, I recommend the same approach as above for the title tag.</p>
<h4>Tuning Your Head Tags</h4>
<p>It&#8217;s important to tune your description and keywords to get the right users to the right content. This is the great part: by using the best relevant terms, by providing helpful accurate terms and not trying to scam or spam traffic your way, you end up helping searchers to find what they are looking for, and you end up helping yourself to get more and higher quality traffic..</p>
<p>So in order to be more efficient, you need to figure out what people are searching for when they end up at your site. There are a couple ways to do this. The most basic is to use an analytics package, such as Google Analytics, and look at the keywords people are using that direct them to your site. Google Analytics makes this easy by also showing you the average time on the site, and number of pages visited by users divided by the keywords they searched for. This makes it easy to tell which keywords generate traffic of users who WANT to be on your site, and find it useful (and hence will come back, make purchases, etc&#8230;), and which keywords brought in the wrong people, people who were looking for something else.</p>
<p>Here is the Google Analytics keyword report for my site:?</p>
<p><a href="http://www.digitalsanctuary.com/tech-blog/wp-content/uploads/2009/04/picture-11.png"><img src="http://www.digitalsanctuary.com/tech-blog/wp-content/uploads/2009/04/picture-11-550x187.png" alt="Google Analytics Keyword Report" title="Google Analytics Keyword Report" width="550" height="187" class="aligncenter size-medium wp-image-361" /></a></p>
<p>You can see that people who come to my site when they&#8217;re searching for &#8220;create web service seam&#8221; only look at the first page they see, and have 100% bounce rate. That means one of two things: A) this group of people was really looking for something else and my site didn&#8217;t help (in which case I should probably change my keywords and content so they don&#8217;t waste their time on my site) or B) the first page answered all of their questions. In this case the page on my site is probably pretty helpful for people searching for those words, so I&#8217;m going to keep the keywords, but you understand the point.</p>
<p>These types of reports should allow you to tune your keywords to get the best quality traffic and the happiest users.</p>
<p>To be more advanced you can track the keywords that didn&#8217;t just lead people to your site, but led people who made purchases/other goals to your site. You can do this with Google Analytics by setting up Goals, or with other analytics packages.</p>
<p><strong>There will be three more posts on SEO coming in the next few days!</strong></p>
<p>&#8212;&#8212;&#8212;<br />
<a href="http://www.digitalsanctuary.com/tech-blog/general/atg-seo-accessibility-and-googlebot.html">ATG SEO – Accessibility and GoogleBot</a></p>
<p><a href="http://www.digitalsanctuary.com/tech-blog/general/atg-seo-url-formats-and-crawler-limits.html">ATG SEO – URL Formats and Crawler Limits</a></p>
<p><a href="http://www.digitalsanctuary.com/tech-blog/debian/atg-seo-tools-and-traffic.html">ATG SEO – Tools and Traffic</a></p>
<p class="facebook"><a href="http://www.facebook.com/share.php?u=http://www.digitalsanctuary.com/tech-blog/general/atg-search-engine-optimization-seo.html" target="_blank" title="Share on Facebook">Share on Facebook</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/general/atg-search-engine-optimization-seo.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Reduced Prices for ATG Hosting from Spark::red</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/atg/reduced-prices-for-atg-hosting-from-sparkred.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/atg/reduced-prices-for-atg-hosting-from-sparkred.html#comments</comments>
		<pubDate>Tue, 21 Apr 2009 03:10:43 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[ATG]]></category>
		<category><![CDATA[hosting]]></category>
		<category><![CDATA[Spark::red]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=383</guid>
		<description><![CDATA[
Spark::red, the best ATG Hosting provider around, is offering reduced pricing on ATG Hosting and is committed to being aggressively competitive on price in order to help clients save money during the current economic slump.
Check out the ATG Hosting Economic Stimulus Special Offer for more information on how you can save hundreds of thousands of [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://www.sparkred.com/img/h1.gif" alt="ATG Managed Hosting from Spark::red" /></p>
<p><a href="https://www.sparkred.com">Spark::red, the best ATG Hosting provider around</a>, is offering reduced pricing on ATG Hosting and is committed to being aggressively competitive on price in order to help clients save money during the current economic slump.</p>
<p>Check out the <a href="https://www.sparkred.com/pricing.html">ATG Hosting Economic Stimulus Special Offer</a> for more information on how you can save hundreds of thousands of dollars, and still get the highest quality managed ATG hosting around.</p>
<p class="facebook"><a href="http://www.facebook.com/share.php?u=http://www.digitalsanctuary.com/tech-blog/java/atg/reduced-prices-for-atg-hosting-from-sparkred.html" target="_blank" title="Share on Facebook">Share on Facebook</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/atg/reduced-prices-for-atg-hosting-from-sparkred.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
