<?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; JBoss</title>
	<atom:link href="http://www.digitalsanctuary.com/tech-blog/tag/jboss/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>JBoss Performance Tuning and MasterTheBoss</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/jboss/jboss-performance-and-mastertheboss.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/jboss/jboss-performance-and-mastertheboss.html#comments</comments>
		<pubDate>Tue, 02 Nov 2010 15:36:59 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[JBoss]]></category>
		<category><![CDATA[books]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=716</guid>
		<description><![CDATA[I review technical book manuscripts for a few different publishers, and recently had the pleasure of working on an upcoming book called JBoss Performance Tuning by Francesco Marchioni.  It&#8217;s coming out in December 2010 and will be a must have &#8230; <a href="http://www.digitalsanctuary.com/tech-blog/java/jboss/jboss-performance-and-mastertheboss.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I review technical book manuscripts for a few different publishers, and recently had the pleasure of working on an upcoming book called <a title="JBoss Performance Tuning Book" href="http://www.mastertheboss.com/jboss-server/255-announcing-jboss-performance-tuning-book.html" target="_blank">JBoss Performance Tuning by Francesco Marchioni</a>.  It&#8217;s coming out in December 2010 and will be a must have addition to your bookshelf if you deploy applications on JBoss.</p>
<p>The book contains extensive performance/load test results giving you hard data to work with when deciding which changes to make in your environment.  Some of the results were very surprising and the book has a lot of valuable data.</p>
<p>The author, Francesco Marchioni, also runs a popular <a title="MasterTheBoss Blog" href="http://www.mastertheboss.com" target="_blank">JBoss related blog called MasterTheBoss.com</a>.  There are a ton of great articles and posts there, so check it out!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/jboss/jboss-performance-and-mastertheboss.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JBoss JMS Doesn&#8217;t Create Tables with XA Datasource</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/jboss/jboss-jms-doesnt-create-tables-with-xa-datasource.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/jboss/jboss-jms-doesnt-create-tables-with-xa-datasource.html#comments</comments>
		<pubDate>Thu, 01 Jul 2010 20:21:08 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[JBoss]]></category>
		<category><![CDATA[JMS]]></category>
		<category><![CDATA[oracle]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=657</guid>
		<description><![CDATA[The JBoss Messaging service (at least on JBoss 4.3 EAP) defaults to using a local Hypersonic database. For production use you&#8217;ll want to switch away from Hypersonic to a real database, such as Oracle (in this example). If you&#8217;re using &#8230; <a href="http://www.digitalsanctuary.com/tech-blog/java/jboss/jboss-jms-doesnt-create-tables-with-xa-datasource.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The JBoss Messaging service (at least on JBoss 4.3 EAP) defaults to using a local Hypersonic database.  For production use you&#8217;ll want to switch away from Hypersonic to a real database, such as Oracle (in this example).</p>
<p>If you&#8217;re using XA datasources in general, it&#8217;s tempting to go ahead and create the new DefaultDS datasource definition as an XA datasource (like the example one jboss-eap-4.3/docs/examples/jca/oracle-xa-ds.xml ).  However, I&#8217;ve just discovered that if you do that the JMS startup service won&#8217;t successfully create the tables it needs.  The HILOSEQUENCES and TIMERS tables get created by the UUID key generator service, but the JMS table creation silently fails and then you get errors like this:</p>
<pre class="brush: plain; title: ; notranslate">
11:16:32,161 ERROR [ExceptionUtil] ServerPeer[0] startService
java.sql.SQLException: ORA-00942: table or view does not exist
</pre>
<p>Switch the DefaultDS definition to a non-XA version, and it will create all of the JBM_* tables successfully.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/jboss/jboss-jms-doesnt-create-tables-with-xa-datasource.html/feed</wfw:commentRss>
		<slash:comments>2</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 &#8230; <a href="http://www.digitalsanctuary.com/tech-blog/java/jboss/make-google-ignore-jsessionid.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></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>
]]></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>Setting Cache Headers from JBoss</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/jboss/setting-cache-headers-from-jboss.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/jboss/setting-cache-headers-from-jboss.html#comments</comments>
		<pubDate>Thu, 15 Jan 2009 19:15:20 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[ATG]]></category>
		<category><![CDATA[JBoss]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=214</guid>
		<description><![CDATA[Having control over the HTTP response headers allows you to set cache related headers in responses for various content you&#8217;d like cached on the browser (or an intermediary proxy). I created the ATG Cache Control DAS pipeline Servlet a year &#8230; <a href="http://www.digitalsanctuary.com/tech-blog/java/jboss/setting-cache-headers-from-jboss.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Having control over the HTTP response headers allows you to set cache related headers in responses for various content you&#8217;d like cached on the browser (or an intermediary proxy).  I created the <a href="http://www.digitalsanctuary.com/tech-blog/java/atg/atg-cache-header-control-module.html">ATG Cache Control DAS pipeline Servlet</a> a year ago, but when you&#8217;re using JBoss you need another solution.</p>
<p>Since the DAF pipeline is only executed for JSPs the pipeline Servlet it doesn&#8217;t allow you to set headers for the static media items you&#8217;re more likely to want to cache.  I created a Servlet Filter which allows you to set cache headers in JBoss based on URI patterns.  It doesn&#8217;t allow the same fine grained control that the old pipeline Servlet does, but it should work for most situations.</p>
<p>Servlet Filters are very similar to ATG pipeline Servlets in that they are executed within the lifecycle of a request and can read the request and modify the response.  The filter I created gets configured from the web.xml and sets the response headers relating to caching.  You can configure different instances of the filter for each cache time you need, an hour, a day, or a week, and map different URL patterns to the appropriate instances.</p>
<p>I&#8217;ve added the filter into <a href="https://developer.sparkred.com/confluence/display/ATGDC/Foundation">Foundation</a>, the open source ATG e-commerce framework project, which is hosted at the <a href="http://sparkred.com/">Spark::red</a> <a href="https://developer.sparkred.com">Development Community</a>.</p>
<p>The Servlet filter code looks like this:</p>
<pre class="brush: java; title: ; notranslate">
package org.foundation.servlet.filter;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

/**
 * The Class CacheHeaderFilter.
 *
 * @author Devon Hillard
 */
public class CacheHeaderFilter implements Filter {

    /**
     * The Constant MILLISECONDS_IN_SECOND.
     */
    private static final int MILLISECONDS_IN_SECOND = 1000;

    /** The Constant POST_CHECK_VALUE. */
    private static final String POST_CHECK_VALUE = &quot;post-check=&quot;;

    /** The Constant PRE_CHECK_VALUE. */
    private static final String PRE_CHECK_VALUE = &quot;pre-check=&quot;;

    /** The Constant MAX_AGE_VALUE. */
    private static final String MAX_AGE_VALUE = &quot;max-age=&quot;;

    /** The Constant ZERO_STRING_VALUE. */
    private static final String ZERO_STRING_VALUE = &quot;0&quot;;

    /** The Constant NO_STORE_VALUE. */
    private static final String NO_STORE_VALUE = &quot;no-store&quot;;

    /** The Constant NO_CACHE_VALUE. */
    private static final String NO_CACHE_VALUE = &quot;no-cache&quot;;

    /** The Constant PRAGMA_HEADER. */
    private static final String PRAGMA_HEADER = &quot;Pragma&quot;;

    /** The Constant CACHE_CONTROL_HEADER. */
    private static final String CACHE_CONTROL_HEADER = &quot;Cache-Control&quot;;

    /** The Constant EXPIRES_HEADER. */
    private static final String EXPIRES_HEADER = &quot;Expires&quot;;

    /** The Constant LAST_MODIFIED_HEADER. */
    private static final String LAST_MODIFIED_HEADER = &quot;Last-Modified&quot;;

    /** The Constant CACHE_TIME_PARAM_NAME. */
    private static final String CACHE_TIME_PARAM_NAME = &quot;CacheTime&quot;;

    /** The Static HTTP_DATE_FORMAT object. */
    private static final DateFormat HTTP_DATE_FORMAT = new SimpleDateFormat(&quot;EEE, dd MMM yyyy HH:mm:ss z&quot;, Locale.US);

static {
HTTP_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone(&quot;GMT&quot;));
}

    /** The reply headers. */
    private String[][] mReplyHeaders = { {} };

    /** The cache time in seconds. */
    private Long mCacheTime = 0L;

    /**
     * Initializes the Servlet filter with the cache time and sets up the unchanging headers.
     *
     * @param pConfig the config
     *
     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
     */
    public void init(final FilterConfig pConfig) {
        final ArrayList&lt;String[]&gt; newReplyHeaders = new ArrayList&lt;String[]&gt;();
        this.mCacheTime = Long.parseLong(pConfig.getInitParameter(CACHE_TIME_PARAM_NAME));
        if (this.mCacheTime &gt; 0L) {
            newReplyHeaders.add(new String[] { CACHE_CONTROL_HEADER, MAX_AGE_VALUE + this.mCacheTime.longValue() });
            newReplyHeaders.add(new String[] { CACHE_CONTROL_HEADER, PRE_CHECK_VALUE + this.mCacheTime.longValue() });
            newReplyHeaders.add(new String[] { CACHE_CONTROL_HEADER, POST_CHECK_VALUE + this.mCacheTime.longValue() });
        } else {
            newReplyHeaders.add(new String[] { PRAGMA_HEADER, NO_CACHE_VALUE });
            newReplyHeaders.add(new String[] { EXPIRES_HEADER, ZERO_STRING_VALUE });
            newReplyHeaders.add(new String[] { CACHE_CONTROL_HEADER, NO_CACHE_VALUE });
            newReplyHeaders.add(new String[] { CACHE_CONTROL_HEADER, NO_STORE_VALUE });
        }
        this.mReplyHeaders = new String[newReplyHeaders.size()][2];
        newReplyHeaders.toArray(this.mReplyHeaders);
    }

    /**
     * Do filter.
     *
     * @param pRequest the request
     * @param pResponse the response
     * @param pChain the chain
     *
     * @throws IOException Signals that an I/O exception has occurred.
     * @throws ServletException the servlet exception
     *
     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse,
     *      javax.servlet.FilterChain)
     */
    public void doFilter(final ServletRequest pRequest, final ServletResponse pResponse, final FilterChain pChain)
            throws IOException, ServletException {
        // Apply the headers
        final HttpServletResponse httpResponse = (HttpServletResponse) pResponse;
        for (final String[] replyHeader : this.mReplyHeaders) {
            final String name = replyHeader[0];
            final String value = replyHeader[1];
            httpResponse.addHeader(name, value);
        }
        if (this.mCacheTime &gt; 0L) {
            final long now = System.currentTimeMillis();
             final DateFormat httpDateFormat = (DateFormat) HTTP_DATE_FORMAT.clone();
            httpResponse.addHeader(LAST_MODIFIED_HEADER, httpDateFormat.format(new Date(now)));
            httpResponse.addHeader(EXPIRES_HEADER, httpDateFormat.format(new Date(now
                    + (this.mCacheTime.longValue() * MILLISECONDS_IN_SECOND))));
        }
        pChain.doFilter(pRequest, pResponse);
    }

    /**
     * Destroy all humans!
     *
     * @see javax.servlet.Filter#destroy()
     */
    public void destroy() {
    }

}
</pre>
<p>And the web.xml configuration looks like this:</p>
<pre class="brush: xml; title: ; notranslate">
	&lt;filter&gt;
		&lt;filter-name&gt;CacheFilterOneWeek&lt;/filter-name&gt;
		&lt;filter-class&gt;org.foundation.servlet.filter.CacheHeaderFilter&lt;/filter-class&gt;
		&lt;init-param&gt;
			&lt;param-name&gt;CacheTime&lt;/param-name&gt;
			&lt;param-value&gt;604800&lt;/param-value&gt;
		&lt;/init-param&gt;
	&lt;/filter&gt;

	&lt;filter&gt;
		&lt;filter-name&gt;CacheFilterOneDay&lt;/filter-name&gt;
		&lt;filter-class&gt;org.foundation.servlet.filter.CacheHeaderFilter&lt;/filter-class&gt;
		&lt;init-param&gt;
			&lt;param-name&gt;CacheTime&lt;/param-name&gt;
			&lt;param-value&gt;86400&lt;/param-value&gt;
		&lt;/init-param&gt;
	&lt;/filter&gt;

	&lt;filter&gt;
		&lt;filter-name&gt;CacheFilterOneHour&lt;/filter-name&gt;
		&lt;filter-class&gt;org.foundation.servlet.filter.CacheHeaderFilter&lt;/filter-class&gt;
		&lt;init-param&gt;
			&lt;param-name&gt;CacheTime&lt;/param-name&gt;
			&lt;param-value&gt;3600&lt;/param-value&gt;
		&lt;/init-param&gt;
	&lt;/filter&gt;

.......

&lt;filter-mapping&gt;
		&lt;filter-name&gt;CacheFilterOneDay&lt;/filter-name&gt;
		&lt;url-pattern&gt;*.js&lt;/url-pattern&gt;
	&lt;/filter-mapping&gt;
	&lt;filter-mapping&gt;
		&lt;filter-name&gt;CacheFilterOneDay&lt;/filter-name&gt;
		&lt;url-pattern&gt;*.css&lt;/url-pattern&gt;
	&lt;/filter-mapping&gt;
	&lt;filter-mapping&gt;
		&lt;filter-name&gt;CacheFilterOneWeek&lt;/filter-name&gt;
		&lt;url-pattern&gt;*.jpg&lt;/url-pattern&gt;
	&lt;/filter-mapping&gt;
	&lt;filter-mapping&gt;
		&lt;filter-name&gt;CacheFilterOneWeek&lt;/filter-name&gt;
		&lt;url-pattern&gt;*.gif&lt;/url-pattern&gt;
	&lt;/filter-mapping&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/jboss/setting-cache-headers-from-jboss.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>ATG License IP Checks on JBoss</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/atg/atg-license-ip-checks-on-jboss.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/atg/atg-license-ip-checks-on-jboss.html#comments</comments>
		<pubDate>Fri, 23 May 2008 18:45:50 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[ATG]]></category>
		<category><![CDATA[JBoss]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=117</guid>
		<description><![CDATA[Some ATG product licenses are bound to a specific list of IP addresses. However, it may validate that in a somewhat counter-intuitive manner, at least under Linux. If, for example, you are running ATG within JBoss on a server with &#8230; <a href="http://www.digitalsanctuary.com/tech-blog/java/atg/atg-license-ip-checks-on-jboss.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Some ATG product licenses are bound to a specific list of IP addresses.  However, it may validate that in a somewhat counter-intuitive manner, at least under Linux.</p>
<p>If, for example, you are running ATG within JBoss on a server with multiple IP addresses (or multiple NICs), you might expect that if you bind JBoss to a specific IP address, that will be the IP that is used in the license check, since clearly that is the real IP the server is listening on.</p>
<p>Not so.  It appears that instead of checking the IP address(es) of the J2EE container, it looks at the machine&#8217;s hostname.  So if your hostname is configured to a name that is mapped to a different IP in your /etc/hosts file, your license will fail to validate.</p>
<p>The fix is relatively simple, just change the hostname of the server to match the name mapped to the licensed IP address in your /etc/hosts file, and start up JBoss again.  </p>
<p>However, since this essentially alters the &#8220;identity&#8221; of your server it can have other repercussions on your server.  So be warned.  It may make more sense to get the licenses issued with IPs matching your hostname, not the actual IP you intend to run JBoss/ATG on.</p>
<p>I think this is a bit of a bug, in my opinion.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/atg/atg-license-ip-checks-on-jboss.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>JBoss jsessionid Query Parameter Removal</title>
		<link>http://www.digitalsanctuary.com/tech-blog/general/jboss-jsessionid-parameter-remove.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/general/jboss-jsessionid-parameter-remove.html#comments</comments>
		<pubDate>Tue, 20 May 2008 23:33:48 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[JBoss]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[jsessionid]]></category>
		<category><![CDATA[seo]]></category>
		<category><![CDATA[tomcat]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=109</guid>
		<description><![CDATA[Instead of just using the Apache mod_rewrite rules from my post on &#8220;Hiding jsessionid parameters from Google&#8220;, which uses redirects, wouldn&#8217;t it be better to simply not output the jsessionid parameter into the URLs? First, what are those jsessionid params, &#8230; <a href="http://www.digitalsanctuary.com/tech-blog/general/jboss-jsessionid-parameter-remove.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Instead of just using the Apache mod_rewrite rules from my post on &#8220;<a href="http://www.digitalsanctuary.com/tech-blog/general/hiding-jsessionid-parameter-from-google.html" target="_new">Hiding jsessionid parameters from Google</a>&#8220;, which uses redirects, wouldn&#8217;t it be better to simply not output the jsessionid parameter into the URLs?</p>
<p>First, what are those jsessionid params, and why are they there?  </p>
<p>For a web application to have state, i.e. remember things from one page request to the next (such as that you&#8217;re logged in, who you are, what is in your shopping cart, etc&#8230;), most web applications have something called a session.  The session starts when you hit the website at first, sticks with you while you are on the site, and expires after you have either logged out or have been idle (i.e. not clicked on anything) for a set period of time (perhaps 30 minutes).</p>
<p>In general the actual session data is held on the server, things like your shopping cart, your user profile, all of that.  However, in order to associate requests from your web browser with the correct session, your browser needs to pass something for the web application to recognize which session is yours.  This is traditionally done in two ways:  </p>
<p>firstly and primarily using a session-life browser cookie (or two) which hold a session identifier and optionally some additional security token(s).  The browser receives this cookie from the web application, and then sends the cookie back to the web application with each page request.  The web application looks at the cookie, and figures out which session is yours, and handles your page request appropriately.</p>
<p>secondly, and usually only as a fall-back for browsers which do not support cookies or whose cookie support has been turned off, is to rewrite every link in the web application which points to another page in the same web application with a special session id added to the URI of the link.  This is usually done as a path parameter (following a &#8216;;&#8217;), but sometimes is also done as a query parameter (following a &#8216;?&#8217;).  </p>
<p>Since on the first request to a web application, the browser is not sending a session cookie, the web application has no way of knowing if the browser actually supports cookies or not.  So for the first page, the web application will usually send back the session cookie AND rewrite all of the links on the page with the jsessionid just in case the cookie is not returned.</p>
<p>So what&#8217;s the problem?</p>
<p>Search engine spiders, like Google&#8217;s GoogleBot, usually do not support cookies.  This means that they see the site with the jsessionid parameter in every link and every requested URL.  So this leads to three related problems.  First, the links that show up in a Google search include an ugly &#8216;jsessionid=xxxxxx&#8217; which looks ugly.  Second, Google doesn&#8217;t recognize that the jsessionid parameter doesn&#8217;t change the page content, and as such each time the GoogleBot hits the site, and gets a different jsessionid, it indexes all of the pages again.  This leads to getting multiple result listings for the same page in search results.  For instance you might see the same page listed 7 times in a row.  Third, by having multiple instances of the same page with the same content, the Google PageRank of the actual page is severely diluted and perhaps even penalized due to the multiple presentations.</p>
<p>Because of these problems, we do not want the GoogleBot to see the jsessionid URI parameters.  </p>
<p>In my earlier post, linked to above, I used Apache mod_rewrite to look for requests from GoogleBot, and send a redirect back to GoogleBot, redirecting it to the same URI it had initially requested, just stripped of the jsessionid parameter.</p>
<p>This time I&#8217;m going to use a Servlet Filter to prevent the jsessionid parameter from being inserted into the URL links on the page for GoogleBot requests.  This is more elegant since there are no redirects.</p>
<p>First, I want to link to the web page which provided the starting point for the solution I used:  <a href="http://randomcoder.com/articles/jsessionid-considered-harmful" target="_new">JSESSIONID considered harmful</a></p>
<p>I took that approach and modified the filter code to only do this for GoogleBot requests, which will allow users who don&#8217;t support or allow cookies to still use the site.</p>
<p>I have one Java class: <a href='http://www.digitalsanctuary.com/tech-blog/wp-content/uploads/2008/05/disableurlsessionfilter1.java' target="_new">DisableUrlSessionFilter.java</a></p>
<pre class="brush: java; title: ; notranslate">
package com.digitalsanctuary.util;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

/**
 * Servlet filter which disables URL-encoded session identifiers.
 *
 *
 * Copyright (c) 2006, Craig Condit. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot;
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * Modified by Devon Hillard (devon@digitalsanctuary.com) to only filter for GoogleBot,
 * not for users without cookies enabled.
 *
 */
@SuppressWarnings(&quot;deprecation&quot;)
public class DisableUrlSessionFilter implements Filter {

    /**
     * The string to look for in the User-Agent header to identify the GoogleBot.
     */
    private static final String GOOGLEBOT_AGENT_STRING = &quot;googlebot&quot;;

    /**
     * The request header with the User-Agent information in it.
     */
    private static final String USER_AGENT_HEADER_NAME = &quot;User-Agent&quot;;

    /**
     * Filters requests to disable URL-based session identifiers.
     *
     * @param pRequest
     *                the request
     * @param pResponse
     *                the response
     * @param pChain
     *                the chain
     *
     * @throws IOException
     *                 Signals that an I/O exception has occurred.
     * @throws ServletException
     *                 the servlet exception
     */
    public void doFilter(final ServletRequest pRequest, final ServletResponse pResponse, final FilterChain pChain)
	    throws IOException, ServletException {
	// skip non-http requests
	if (!(pRequest instanceof HttpServletRequest)) {
	    pChain.doFilter(pRequest, pResponse);
	    return;
	}

	HttpServletRequest httpRequest = (HttpServletRequest) pRequest;
	HttpServletResponse httpResponse = (HttpServletResponse) pResponse;

	boolean isGoogleBot = false;

	if (httpRequest != null) {
	    String userAgent = httpRequest.getHeader(USER_AGENT_HEADER_NAME);
	    if (StringUtils.isNotBlank(userAgent)) {
		if (userAgent.toLowerCase().indexOf(GOOGLEBOT_AGENT_STRING) &gt; -1) {
		    isGoogleBot = true;
		}
	    }
	}

	if (isGoogleBot) {
	    // wrap response to remove URL encoding
	    HttpServletResponseWrapper wrappedResponse = new HttpServletResponseWrapper(httpResponse) {
		@Override
		public String encodeRedirectUrl(final String url) {
		    return url;
		}

		@Override
		public String encodeRedirectURL(final String url) {
		    return url;
		}

		@Override
		public String encodeUrl(final String url) {
		    return url;
		}

		@Override
		public String encodeURL(final String url) {
		    return url;
		}
	    };

	    // process next request in chain
	    pChain.doFilter(pRequest, wrappedResponse);
	} else {
	    pChain.doFilter(pRequest, pResponse);
	}
    }

    /**
     * Unused.
     *
     * @param pConfig
     *                the config
     *
     * @throws ServletException
     *                 the servlet exception
     */
    public void init(final FilterConfig pConfig) throws ServletException {
    }

    /**
     * Unused.
     */
    public void destroy() {
    }
}
</pre>
<p>and the servlet filter configuration in my web.xml file:</p>
<pre class="brush: xml; title: ; notranslate">
	&lt;filter&gt;
		&lt;filter-name&gt;DisableUrlSessionFilter&lt;/filter-name&gt;
		&lt;filter-class&gt;
			com.digitalsantuary.util.DisableUrlSessionFilter
		&lt;/filter-class&gt;
	&lt;/filter&gt;

....

	&lt;filter-mapping&gt;
		&lt;filter-name&gt;DisableUrlSessionFilter&lt;/filter-name&gt;
		&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
	&lt;/filter-mapping&gt;
</pre>
<p>So far, it seems to be working beautifully.  It only impacts the GoogleBot, and it successfully strips the jsessionid parameter from the links on the site.</p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/general/jboss-jsessionid-parameter-remove.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Hiding jsessionid parameter from Google</title>
		<link>http://www.digitalsanctuary.com/tech-blog/general/hiding-jsessionid-parameter-from-google.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/general/hiding-jsessionid-parameter-from-google.html#comments</comments>
		<pubDate>Mon, 19 May 2008 21:39:34 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[JBoss]]></category>
		<category><![CDATA[mod_rewrite]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=106</guid>
		<description><![CDATA[If you&#8217;re running a website on JBoss you may discover that Google has indexed your pages with a jsessionid query parameter in the links. The Google crawl bot does not support cookies, therefore JBoss uses the jsessionid query parameter in &#8230; <a href="http://www.digitalsanctuary.com/tech-blog/general/hiding-jsessionid-parameter-from-google.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re running a website on JBoss you may discover that Google has indexed your pages with a jsessionid query parameter in the links.  </p>
<p>The Google crawl bot does not support cookies, therefore JBoss uses the jsessionid query parameter in order to maintain a session state without cookies.  These query parameters can impact your Google rank and indexing efficiency as the same page can be indexed multiple times with different session ids, and dilute your ranking.  Also, it leads to ugly links.</p>
<p>If you want to still be able to support non-cookie using users, but would like Google to see cleaner links, you can use Apache&#8217;s mod_rewrite to modify the links for the Google bot only, leaving the normal functionality available to the rest of your users.</p>
<p>Assuming you have mod_rewrite enabled in your Apache instance, use this configuration in your apache config:</p>
<pre class="brush: plain; title: ; notranslate">
	# This should strip out jsessionids from google
	RewriteCond %{HTTP_USER_AGENT} (googlebot) [NC]
	ReWriteRule ^(.*);jsessionid=[A-Za-z0-9]+(.*)$ $1$2 [L,R=301]
</pre>
<p>This rule says for request where the user agent contains &#8220;googlebot&#8221; (with case insensitive matching), rewrite the URL without the jsessionid.  It seems to work nicely.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/general/hiding-jsessionid-parameter-from-google.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>10MinuteMail upgraded again</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/jboss/10minutemail-upgraded-again.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/jboss/10minutemail-upgraded-again.html#comments</comments>
		<pubDate>Sat, 03 Nov 2007 10:17:51 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[10MinuteMail]]></category>
		<category><![CDATA[JBoss]]></category>
		<category><![CDATA[Seam]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/java/jboss/10minutemail-upgraded-again.html</guid>
		<description><![CDATA[Moved up to Seam 2.0 CR3, and JBoss 4.2.2. I also optimized some code, got rid of some useless error logging, etc&#8230; Hopefully it will perform a little better:) So far it seems to process incoming e-mail much faster, which &#8230; <a href="http://www.digitalsanctuary.com/tech-blog/java/jboss/10minutemail-upgraded-again.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Moved up to Seam 2.0 CR3, and JBoss 4.2.2.  I also optimized some code, got rid of some useless error logging, etc&#8230;  </p>
<p>Hopefully it will perform a little better:)  So far it seems to process incoming e-mail much faster, which was a bottleneck under load.</p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/jboss/10minutemail-upgraded-again.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Top Ten Tools</title>
		<link>http://www.digitalsanctuary.com/tech-blog/general/top-ten-tools.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/general/top-ten-tools.html#comments</comments>
		<pubDate>Sat, 06 Oct 2007 21:30:54 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[adium]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[emacs]]></category>
		<category><![CDATA[gtd]]></category>
		<category><![CDATA[igtd]]></category>
		<category><![CDATA[itunes]]></category>
		<category><![CDATA[JBoss]]></category>
		<category><![CDATA[pages]]></category>
		<category><![CDATA[postgres]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/general/top-ten-tools.html</guid>
		<description><![CDATA[I was surfing around today, and saw this article about the top ten tools you use. As far as getting work done on the computer (I&#8217;m taking the computer for granted and not counting it as a tool, although for &#8230; <a href="http://www.digitalsanctuary.com/tech-blog/general/top-ten-tools.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I was surfing around today, and saw <a href="http://www.cogniview.com/convert-pdf-to-excel/post/top-10-tools-i-cant-live-without/" title="Top Ten Tools" target="_blank">this article</a> about the top ten tools you use.</p>
<p>As far as getting work done on the computer (I&#8217;m taking the computer for granted and not counting it as a tool, although for it all to come together it&#8217;s worth noting I use an Apple MacBookPro with 4GB of RAM) my top applications are:</p>
<ol>
<li><a href="http://www.eclipse.org/" title="Eclipse" target="_blank">Eclipse</a>: my favorite Java IDE with a good set of plugins (JBoss Tools, MyEclipseIDE, WTP, Mylyn, and others)</li>
<li><a href="http://bargiel.home.pl/iGTD/" title="iGTD" target="_blank">iGTD</a>:  a great GTD task manager for the Mac.  I use it for work, personal projects, home errands, etc&#8230;  I used to use KinklessGTD in OmniOutliner, but now I swear by iGTD.  The upcoming Omni Focus will have to bring something amazing to the table to get to me to pay to switch.</li>
<li><a href="http://www.openssh.com/" title="SSH" target="_blank">SSH/SCP</a>/Terminal: I manage and deploy to many servers.  Being able to SSH into them and move files securely is critical.  I&#8217;m handy with the command line, bash scripting, and all that, so I end up doing things that way often.</li>
<li><a href="http://www.gnu.org/software/emacs/" title="Emacs" target="_blank">Emacs</a>: I can handle vi, but when I&#8217;m on a remote server making changes or looking through files trying to figure something out, Emacs is my favorite tool for the job.</li>
<li><a href="http://www.apple.com/safari/" title="Safari" target="_blank">Safari</a>: I spend a lot of time on the web researching, reading, and looking at the applications I&#8217;m building.  I also use <a href="http://caminobrowser.org/" title="Camino" target="_blank">Camino</a>, but Safari 3 is my favorite browser and is always open.</li>
<li><a href="http://www.adiumx.com/" title="Adium" target="_blank">Adium</a>: I love staying in touch with my friends, family, and co-workers.  Adium lets me keep in touch on AIM, Yahoo, MSN, GTalk, and more in a very nice application.</li>
<li><a href="http://www.apple.com/itunes/" title="iTunes" target="_blank">iTunes</a>: Music helps me get into the zone and keeps me happy.  Plus I like to watch the occasional TV show:)</li>
<li><a href="http://www.apple.com/iwork/pages/" title="Pages" target="_blank">Pages</a>: as an architect I often have to generate documentation around projects.  I also write letters (yes the non-e-mail kind).  Pages is a great word processor and making professional looking easy to read documents is a snap.</li>
<li><a href="http://www.jboss.org/" title="JBoss" target="_blank">JBoss</a>: JBoss is a fantastic application server.  It&#8217;s free, open source, fast, and powerful.</li>
<li><a href="http://www.postgresql.org/" title="Postgres" target="_blank">Postgres</a>: Postgres is a database with all the great attributes I listed for JBoss.  I used to use MySQL but at the time I switched it was lacking many critical features (sub-selects, foreign keys, etc..).  After using postgres for a while, I haven&#8217;t looked back.</li>
</ol>
<p>Those are the applications that I have running on my laptop basically 24/7 and I use each of them every single day.</p>
<p>What are yours?  I&#8217;m not trying to get into an emacs versus vi flamewar, but I&#8217;d like to hear about what applications get you through your day a little easier.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/general/top-ten-tools.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JBoss Tools Properties Editor Surprise</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/jboss/jboss-tools-properties-editor-surprise.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/jboss/jboss-tools-properties-editor-surprise.html#comments</comments>
		<pubDate>Mon, 20 Aug 2007 05:12:50 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[JBoss]]></category>
		<category><![CDATA[eclipse]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/java/jboss/jboss-tools-properties-editor-surprise.html</guid>
		<description><![CDATA[No, not the kind of surprise with cake. The latest JBoss Tools Eclipse plugin, which if like me you are running on a platform that they haven&#8217;t released RedHat Developer Studio for is a pretty good option, which can be &#8230; <a href="http://www.digitalsanctuary.com/tech-blog/java/jboss/jboss-tools-properties-editor-surprise.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>No, not the kind of surprise with cake.</p>
<p>The latest JBoss Tools Eclipse plugin, which if like me you are running on a platform that they haven&#8217;t released RedHat Developer Studio for is a pretty good option, which can be installed through Eclipse using this update URL:</p>
<p>http://download.jboss.org/jbosstools/updates/development</p>
<p>Sets up your default editor of .properties files to be the new Red Hat Properties Editor.  It looks very snazzy.  However, at least on my machine (Eclipse 3.3, JDK 1.5, OS X 10.4.10), whenever it opens a properties file, it happily strips out all of the equals signs separating property names from their values.  They still look good in the graphical portion of the Red Hat Editor, but of course don&#8217;t work very well anywhere else.</p>
<p>You can fix this by going into the Eclipse Preferences, General, Editors, File Associations, scrolling down until you see the &#8220;*.properties&#8221; entry and choosing the &#8220;Properties File Editor&#8221; as your default.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/jboss/jboss-tools-properties-editor-surprise.html/feed</wfw:commentRss>
		<slash:comments>5</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/45 queries in 0.012 seconds using disk: basic
Object Caching 827/927 objects using disk: basic

Served from: www.digitalsanctuary.com @ 2012-02-06 23:52:55 -->
