<?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/category/java/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>Seam Identity Management</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/seam-identity-management.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/seam-identity-management.html#comments</comments>
		<pubDate>Mon, 11 Jul 2011 15:34:32 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[Seam]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=761</guid>
		<description><![CDATA[During a recent coding getaway to Maine (see my post on the 2011 HackFestaThon) I decided to write a basic Seam project as a starting point for my future Seam based web applications.  The idea is to provide common features &#8230; <a href="http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/seam-identity-management.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>During a recent coding getaway to Maine (see my post on the <a title="Coding Weekend in Maine 2011" href="http://www.digitalsanctuary.com/blog/uncategorized/weekend-in-maine.html" target="_blank">2011 HackFestaThon</a>) I decided to write a basic Seam project as a starting point for my future Seam based web applications.  The idea is to provide common features such as Login, Logout, Registration, Forgot Password, User Management, Audit Logging, Image Upload Handling, Video Upload Handling, etc&#8230; so next time I have an idea that I want to hack together I won&#8217;t have to re-write or copy-paste in basic functionality like that.</p>
<p>I spent about a day working on things before I discovered that I really should be using the <a title="Seam 2.2 Identity Management" href="http://docs.jboss.org/seam/2.2.2.Final/reference/en-US/html/security.html#d0e9101" target="_blank">Seam framework&#8217;s Identity Management</a> feature.  So I threw out everything I&#8217;d done, and started by re-reading the docs, and went from there.  Seam&#8217;s Identity Management framework is VERY powerful, but is also a little complicated to get going and in many cases it seems like it would easier to just write stuff from scratch.  I&#8217;m banking on the powerful stuff being worth the initial learning curve and a little extra pain.</p>
<p>When I get the starter project in a more complete state I will be open sourcing the whole thing to help others along, but I wanted to share a few things I&#8217;ve learned so far:</p>
<p>In order to use the Email address as the login instead of a username, you need to remove the username property from your UserAccount entity and annotate the Email address property like so:</p>
<pre class="brush: java; title: ; notranslate">
@NotNull
@UserPrincipal
@Email
public String getEmail() {
    return email;
}
</pre>
<p>Actions like Registration need a RunAsOperation inner class to handle the fine grained security controls that the Identity Management framework enforces:</p>
<pre class="brush: java; title: ; notranslate">
    public void register() {
	verified = (confirm != null &amp;&amp; confirm.equals(password));

	if (!verified) {
	    FacesMessages.instance().addToControl(&quot;confirmPassword&quot;, &quot;Passwords do not match&quot;);
	}
	new RunAsOperation() {
	    public void execute() {
		try {
		    // Check if email address has already been used
		    if (identityManager.userExists(getEmail())) {
			FacesMessages.instance().addToControl(&quot;email&quot;, &quot;Email has already been used.&quot;);
			return;
		    }
		    identityManager.createUser(email, password, mFirstName, mLastName);
		} catch (IdentityManagementException e) {
		    // TODO Auto-generated catch block
		    e.printStackTrace();
		}
		identityManager.grantRole(email, &quot;member&quot;);
	    }
	}.addRole(&quot;admin&quot;).run();

	// Login the user
	identity.getCredentials().setUsername(email);
	identity.getCredentials().setPassword(password);
	identity.login();
    }
</pre>
<p>Populating custom properties on the User during things like registration requires observing events:</p>
<pre class="brush: java; title: ; notranslate">
    @Observer(JpaIdentityStore.EVENT_PRE_PERSIST_USER)
    public void prePersistUser(UserAccount pNewUser) {
	// Setup additional UserAccount properties before the user is created
	pNewUser.setRegistrationDate(new Date());
	pNewUser.setOptIn(isOptIn());
    }
</pre>
<p>You can log audit events with the user&#8217;s IP address by doing things like this:</p>
<pre class="brush: java; title: ; notranslate">
@Scope(ScopeType.EVENT)
@Name(&quot;userEvents&quot;)
public class UserEvents {
    @Logger
    private Log mLog;

    @Observer(JpaIdentityStore.EVENT_USER_AUTHENTICATED)
    public void loginSuccessful(UserAccount pUser) {
	mLog.info(&quot;User logged in with email: #0&quot;, pUser.getEmail());
	pUser.setLastLoginDate(new Date());
	Contexts.getSessionContext().set(&quot;currentUser&quot;, pUser);
	AuditEvent loginEvent = new AuditEvent(((ServletRequest) FacesContext.getCurrentInstance().getExternalContext()
		.getRequest()).getRemoteAddr(), pUser.getId(), &quot;Login Success&quot;, null);
	Events.instance().raiseEvent(&quot;auditEvent&quot;, loginEvent);
    }
}
</pre>
<p>Hopefully I&#8217;ll have the starter project ready soon and will share it with you all.  In the meantime, happy hacking!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/seam-identity-management.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>First brush with Ruby On Rails</title>
		<link>http://www.digitalsanctuary.com/tech-blog/general/first-brush-with-ruby-on-rails.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/general/first-brush-with-ruby-on-rails.html#comments</comments>
		<pubDate>Tue, 31 May 2011 03:31:22 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Seam]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=732</guid>
		<description><![CDATA[Earlier this week I was hanging out with a friend talking about a project he was working on and I decided to poke at it a bit with him, and as such got my first hands on experience with Ruby &#8230; <a href="http://www.digitalsanctuary.com/tech-blog/general/first-brush-with-ruby-on-rails.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Earlier this week I was hanging out with a friend talking about a project he was working on and I decided to poke at it a bit with him, and as such got my first hands on experience with Ruby on Rails.</p>
<p>Ruby on Rails or RoR obviously has huge buzz and is a very popular web application development framework lately.  Lots of people have praised it and lots of great sites have been built using it.  I&#8217;ve never bothered to learn it myself for a few reasons.  First I&#8217;m a Java guy (ATG and Seam) and have been for years.  Given limited time and limited brain capacity I&#8217;d rather learn more Java/Java Frameworks/etc&#8230; than try to learn a whole new language.  Secondly many trusted friends advised me that while RoR does somethings REALLY well and makes some things REALLY easy, once you need to try to break outside of the pre-imagined structure/features that RoR provides out of the box, things rapidly go downhill.  Those reasons aside, the high level of buzz has meant I&#8217;ve always been somewhat curious, so this opportunity to finally get my hands a little dirty with RoR was welcome.</p>
<p>Getting started with RoR on Mac OS X is very easy.  It&#8217;s pre-installed and works right out of the box.  However after upgrading Rails and the gems I ran into a known blocking bug which after some Googling I was able to fix by downgrading rake to 0.8.7 in the Gemfile.  So not a 100% smooth start, but not too bad.</p>
<p>The Rails generate scaffold commands make it very easy to create a data object, the related schema changes (managed through the rake migration mechanism), and related CRUD pages and controllers.  You can be up and running very quickly and creating, browsing, editing, and deleting records.  This can make it very easy to get a basic application laid out, and provides lots of plumbing automatically.</p>
<p>I didn&#8217;t get much farther than some simple controller modifications, outbound e-mail sending, etc&#8230;  so I&#8217;m far from a real RoR developer.  However I ran into enough pain points so far that I don&#8217;t think RoR is for me.  I don&#8217;t want to start any language/framework wars, but here is what I ran into:</p>
<p>A lot of the &#8220;magic&#8221; seems great at first, but as soon as you want go outside of the box or tweak how things are working, it becomes a massive liability.  For instance when using the generate scaffold command to create data objects you can setup relationships/foreign keys by passing in a column name that matches the form OtherClass_id:integer, which will be interpreted to be a FK association to the other class&#8217;s id column to join the objects.  This is great.  However, what if you want to add two relationships to the same Other class?  For instance an Message has a Sender and a Recipient, both of which are Users.  I can use user_id:integer for one, but how do I do the other?  How do I use column/property names that don&#8217;t fit that naming convention, for instance I&#8217;d want sender_id and recipient_id.  None of the getting started guides I was able to find covered that.  Googling for things like &#8220;scaffold multiple foreign keys&#8221; didn&#8217;t answer the question, etc&#8230;  I&#8217;m sure it&#8217;s possible, but finding out how wasn&#8217;t easy, and the default way hides and obscures the actual plumbing so it&#8217;s not easy to figure out how to make simple changes or additions.</p>
<p>Data object classes in the app/model area all extend ActiveRecord::Base and as generated by generate scaffold are completely empty.  There&#8217;s no clue or indication of the fields, any logic available, any relationships, property types, etc&#8230;</p>
<p>Emailer classes use magic mappings between method names and e-mail templates.  Because it&#8217;s &#8220;magic&#8221; I have no idea how to change a template file name if I wanted to.  App/helper classes are created, but they&#8217;re empty, so I have no idea what they are doing, or meant to do.  And so on.  If I was an expert RoR developer I&#8217;m sure I&#8217;d know, or if I read a few books I&#8217;d understand, but starting from scratch and trying to learn as I go, it proved very frustrating.</p>
<p>The much touted RoR Community proved to be more of a liability than an asset to me.  Especially when combined with the many, rapid, backwards incompatible, RoR releases that have come out so far.  When looking for information, guides, and answers related to RoR you end up finding things spread all over: blogs, forums, mailing lists, Ruby sites, RoR sites, groups, etc&#8230;  Most of these posts/documents refer to older versions of RoR.  Most of them don&#8217;t have dates or specify which version they are working with.  Many questions on forums are unanswered.  The end result is you find what you hope is a reasonable solution for an issue only to find that the code sample or directions are written for a previous version of RoR, and trying to follow the instructions or paste the code in the current RoR version results in weird errors or worse.</p>
<p>Each new version of RoR seems to massively change and/or break common APIs and change how things are supposed to be done, etc&#8230;  I ran into several situations where it seems like a method was renamed, with no backwards compatible alias left in place, for no other reason than they wanted to change the name, which breaks older code for  no real purpose.</p>
<p>I&#8217;m also not a fan of weakly typed languages.  Strongly typed languages provide compile time validation, IDE auto-completion, and easy to navigate API documentation.  With larger, more complex projects, or projects involving many developers, or projects utilizing many 3rd party libraries, these advantages become significant in my opinion.</p>
<p>So from my standpoint, JBoss Seam provides most of the advantages of RoR, including several improvements, without many of the liabilities.  Plus it&#8217;s in Java which is my strongest programming language.  I&#8217;ll stick with Seam, but I&#8217;ll still respect the creations of folks who use other tools, including RoR.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/general/first-brush-with-ruby-on-rails.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<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>10MinuteMail and Form Submission Charsets in Seam/JSF</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/10minutemail-and-form-submission-charsets-in-seamjsf.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/10minutemail-and-form-submission-charsets-in-seamjsf.html#comments</comments>
		<pubDate>Thu, 04 Mar 2010 22:44:25 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[10MinuteMail]]></category>
		<category><![CDATA[Seam]]></category>
		<category><![CDATA[internationalization]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=598</guid>
		<description><![CDATA[I launched a minor update to 10MinuteMail.com last night. It contained: Changed the mail domain to owlpic.com Updated the Russian language translation (thanks to Vladimir) Fixed a bug where replying to an e-mail using a non-latin character set would result &#8230; <a href="http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/10minutemail-and-form-submission-charsets-in-seamjsf.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I launched a minor update to <a href="http://10minutemail.com">10MinuteMail.com</a> last night.  It contained:</p>
<ol>
<li>Changed the mail domain to owlpic.com</li>
<li>Updated the Russian language translation (thanks to Vladimir)</li>
<li>Fixed a bug where replying to an e-mail using a non-latin character set would result in an unreadable e-mail (also thanks to Vladimir for pointing this out)</li>
</ol>
<p>This last issue was an odd one to fix, so I wanted to document it here (although the same fix can be found elsewhere on the net).</p>
<p>10MinuteMail.com is pretty well internationalized.  The site content is translated into over 30 languages and the pages are served as UTF-8.  Incoming e-mails are also displayed using UTF-8 and display non-latin character sets correctly.  However, until this latest release, if you replied to an e-mail using non-latin characters, the resulting e-mail contained gibberish instead of the correct characters.</p>
<p>I started off by adding UTF-8 as the specified character set for outgoing e-mails.  That didn&#8217;t help.  I added UTF-8 encoding declaration attribute to the form element.  That didn&#8217;t help.  Finally after some frustration, googling, and trying a ton of things, I discovered that for some reason, and I&#8221;m not sure if the bug is in JBoss, JSF, Seam, or where exactly, but you have to set the request objects character encoding programmatically for each request, otherwise it will use the wrong encoding on the form contents and you end up with gibberish.  The easiest way to solve this that I&#8217;ve found so far is to create a small Servlet Filter that sets the encoding on the request, and add that filter in before your Seam filter in your web.xml.  It worked for me.</p>
<p>The filter:</p>
<pre class="brush: java; title: ; notranslate">
package com.digitalsanctuary.seam;

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;

/**
 * The Class UTF8Filter.
 */
public class UTF8Filter implements Filter {

    /** The Constant UTF_8. */
    private static final String UTF_8 = &quot;UTF-8&quot;;

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

    /**
     * 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(ServletRequest pRequest, ServletResponse pResponse, FilterChain pChain) throws IOException,
	    ServletException {
	pRequest.setCharacterEncoding(UTF_8);
	pChain.doFilter(pRequest, pResponse);
    }

    /**
     * Inits the.
     *
     * @param arg0
     *            the arg0
     * @throws ServletException
     *             the servlet exception
     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
     */
    public void init(FilterConfig arg0) throws ServletException {
    }

}
</pre>
<p>An excerpt of web.xml:</p>
<pre class="brush: xml; title: ; notranslate">
....
	&lt;filter&gt;
		&lt;filter-name&gt;UTF8 Filter&lt;/filter-name&gt;
		&lt;filter-class&gt;com.digitalsanctuary.seam.UTF8Filter&lt;/filter-class&gt;
	&lt;/filter&gt;

	&lt;filter-mapping&gt;
		&lt;filter-name&gt;UTF8 Filter&lt;/filter-name&gt;
		&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
	&lt;/filter-mapping&gt;

	&lt;filter&gt;
		&lt;filter-name&gt;Seam Filter&lt;/filter-name&gt;
		&lt;filter-class&gt;org.jboss.seam.servlet.SeamFilter&lt;/filter-class&gt;
	&lt;/filter&gt;

	&lt;filter-mapping&gt;
		&lt;filter-name&gt;Seam Filter&lt;/filter-name&gt;
		&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
	&lt;/filter-mapping&gt;
....
</pre>
<p>Does anyone have a better fix or know exactly why this happens?  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/10minutemail-and-form-submission-charsets-in-seamjsf.html/feed</wfw:commentRss>
		<slash:comments>3</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>Seam 2.x Web Development</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/seam-2x-web-development.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/seam-2x-web-development.html#comments</comments>
		<pubDate>Wed, 03 Jun 2009 00:14:02 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[Seam]]></category>
		<category><![CDATA[book]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=431</guid>
		<description><![CDATA[Packt Publishing just sent me a copy of their new Seam book entitled Seam 2.x Web Development. Authored by David Salter, it seems to be a well laid out practical guide to building web apps with Seam 2. I&#8217;ve only &#8230; <a href="http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/seam-2x-web-development.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<div id="attachment_432" class="wp-caption alignright" style="width: 160px"><a href="http://www.digitalsanctuary.com/tech-blog/wp-content/uploads/2009/06/184719592x.jpg"><img src="http://www.digitalsanctuary.com/tech-blog/wp-content/uploads/2009/06/184719592x-150x150.jpg" alt="Seam 2.x Web Development by David Salter" title="Seam 2.x Web Development" width="150" height="150" class="size-thumbnail wp-image-432" /></a><p class="wp-caption-text">Seam 2.x Web Development by David Salter</p></div>
<p>Packt Publishing just sent me a copy of their new Seam book entitled Seam 2.x Web Development.  Authored by David Salter, it seems to be a well laid out practical guide to building web apps with Seam 2.  I&#8217;ve only skimmed it so far, but will be posting an in-depth review once I&#8217;m able to read through it.  </p>
<p>It&#8217;s great to have a book that covers the new features of Seam 2 and provides examples of common Web 2.0 requirements such as OpenID integration, AJAX/RIA interfaces, and multi-tabbed browsing support using conversation scoped components.  Personally I&#8217;m interested in reading about the new(ish) Identity Manager API (which I haven&#8217;t played with yet) and trying to add OpenID support for the application I am currently building.</p>
<p>You can read the second chapter online here: <a href="http://www.packtpub.com/files/seam-2-x-web-development-sample-chapter-2-developing-seam-applications.pdf">Chapter 2: Developing Seam Applications</a> and let me know what you think of it!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/seam-2x-web-development.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Environment specific mail auth and Seam&#8217;s MailSession</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/environment-specific-mail-auth-and-seams-mailsession.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/environment-specific-mail-auth-and-seams-mailsession.html#comments</comments>
		<pubDate>Wed, 20 May 2009 02:13:32 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[Seam]]></category>
		<category><![CDATA[email]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=416</guid>
		<description><![CDATA[If you are using Seam&#8217;s MailSession to send out going e-mail from your Seam application you can run into trouble if you have a mail server in any environment (dev, test, stage, prod) that allows outgoing mail based on the &#8230; <a href="http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/environment-specific-mail-auth-and-seams-mailsession.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>If you are using Seam&#8217;s MailSession to send out going e-mail from your Seam application you can run into trouble if you have a mail server in any environment (dev, test, stage, prod) that allows outgoing mail based on the client&#8217;s IP address and does not use username and password based authentication.  </p>
<p>The standard configuration for the MailSession is in the components.xml file and looks like this (if you&#8217;ve used SeamGen to create your project):</p>
<pre class="brush: xml; title: ; notranslate">
	&lt;mail:mail-session host=&quot;@mailhost@&quot; port=&quot;@mailport@&quot; username=&quot;@mailusername@&quot; password=&quot;@mailpassword@&quot; /&gt;
</pre>
<p>Then each of your environments has a components-{env}.properties file, which is deployed out and used to populate the @variable@ placeholders in the components.xml file.  For instance your components.dev.properties file might look like this:</p>
<pre class="brush: plain; title: ; notranslate">
jndiPattern=YourApp/#{ejbName}/local
debug=true
mailhost=mail.mydomain.com
mailport=25
mailusername=mailus3r
mailpassword=mailp4ss
</pre>
<p>Which works great.  However, if for instance your production environment uses IP based mail authentication for outbound e-mail, you might try to set your components-prod.properties file to look like this:</p>
<pre class="brush: plain; title: ; notranslate">
jndiPattern=YourApp/#{ejbName}/local
debug=false
mailhost=prodmail.mydomain.com
mailport=25
mailusername=
mailpassword=
</pre>
<p>However, that ends up setting empty strings into the username and password member variables of the MailSession component, and unfortunately the logic which determines whether or not to authenticate with the mail server checks for nulls only.  So with empty strings, it attempts to authenticate with the mail server using a blank username and password.  Which fails, and causes an unhelpful Faces error (unless you turn on debug on the MailSession component).</p>
<p>I&#8217;ve logged a Jira ticket about it here: <a href="https://jira.jboss.org/jira/browse/JBSEAM-4176">JBSEAM-4176</a></p>
<p>You can do a simple workaround by overriding the MailSession component with your own sub-class of the MailSession class.  In your sub-class you can override the setUsername and setPassword methods, check for empty strings and set null into the member variable if the parameter is null or empty.  Luckily the Seam Install precedence system makes it very easy to override the default Seam component.</p>
<pre class="brush: java; title: ; notranslate">
package com.myapp.mail;

import static org.jboss.seam.ScopeType.APPLICATION;

import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.intercept.BypassInterceptors;

/**
 * The Class MailSession. This is an overriding class designed to work around
 * https://jira.jboss.org/jira/browse/JBSEAM-4176
 */
@Name(&quot;org.jboss.seam.mail.mailSession&quot;)
@Install(precedence = org.jboss.seam.annotations.Install.APPLICATION, classDependencies = &quot;javax.mail.Session&quot;)
@Scope(APPLICATION)
@BypassInterceptors
public class MailSession extends org.jboss.seam.mail.MailSession {

    @Override
    public void setPassword(String pPassword) {
	if (pPassword == null || pPassword.trim().length() == 0) {
	    super.setPassword(null);
	} else {
	    super.setPassword(pPassword);
	}
    }

    @Override
    public void setUsername(String pUsername) {
	if (pUsername == null || pUsername.trim().length() == 0) {
	    super.setUsername(null);
	} else {
	    super.setUsername(pUsername);
	}
    }

}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/environment-specific-mail-auth-and-seams-mailsession.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Make A Custom RichFaces Skin</title>
		<link>http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/make-a-custom-richfaces-skin.html</link>
		<comments>http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/make-a-custom-richfaces-skin.html#comments</comments>
		<pubDate>Thu, 09 Apr 2009 23:40:52 +0000</pubDate>
		<dc:creator>Devon</dc:creator>
				<category><![CDATA[Seam]]></category>
		<category><![CDATA[richfaces]]></category>

		<guid isPermaLink="false">http://www.digitalsanctuary.com/tech-blog/?p=337</guid>
		<description><![CDATA[Using RichFaces in your application makes it easy to build great rich interfaces without spending a ton of time writing custom JavaScript for the front end and the back-end support for the JavaScript calls. It ties into your JSF components &#8230; <a href="http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/make-a-custom-richfaces-skin.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Using RichFaces in your application makes it easy to build great rich interfaces without spending a ton of time writing custom JavaScript for the front end and the back-end support for the JavaScript calls.  It ties into your JSF components easily and makes dynamic interaction easy to build.  It also comes with a number of default skins which is great when you&#8217;re first starting to build out a new application because it gives it a nice polished look instead of just black and white unstyled elements.</p>
<p>However, once you you get your own site design in place, the RichFaces skins probably won&#8217;t match your design perfectly.  You can always override any of the particular element styles using CSS, but if you want to quickly change the global look and feel for all the RichFaces components, the easiest thing to do is to create a customized RichFaces skin.  </p>
<p>You should start with the RichFaces skin that most closely matches your design and build your custom skin based on that.  The skins are defined in properties files in the RichFaces jar file under /META-INF/skins/.  You can also just download them from here, to avoid having to unpack the jar file yourself: <a href='http://www.digitalsanctuary.com/tech-blog/wp-content/uploads/2009/04/richfaces-skins.zip'>richfaces-skins.zip</a>.</p>
<p>Copy the skin file that&#8217;s closest to your design into your project.  If you&#8217;re using a Seam project created with seam-gen, you&#8217;re in luck because the ant build file is already setup to deploy RichFaces skins if you have them.  Just drop the skinname.skin.properties file into the &#8220;resources&#8221; directory of your Seam project.  Rename it to a custom name for your site&#8217;s skin, i.e. mysite.skin.properties.  </p>
<p>Now you need to configure your application to use the new custom skin.  Edit /resources/WEB-INF/web.xml, and change the org.richfaces.SKIN param to the name of your new skin:</p>
<pre class="brush: xml; title: ; notranslate">
   &lt;context-param&gt;
      &lt;param-name&gt;org.richfaces.SKIN&lt;/param-name&gt;
      &lt;param-value&gt;mysite&lt;/param-value&gt;
   &lt;/context-param&gt;
</pre>
<p>Now you can edit the skin file to adjust the colors and look and feel of the skin to match your site&#8217;s design.  The ant build file will automatically deploy the custom skin file into the war file.</p>
<p>There are also other ways to customize RichFaces and build custom skins including extending an existing skin, or using the new <a href="http://www.jboss.org/file-access/default/members/jbossrichfaces/freezone/docs/devguide/en/html/ArchitectureOverview.html#PlugnSkin" target="_new">Plug-n-Skin</a> feature, or <a href="http://www.jboss.org/file-access/default/members/jbossrichfaces/freezone/docs/devguide/en/html/ArchitectureOverview.html#XCSSfileformat" target="_new">using XCSS,</a> etc&#8230;  But this should get you started!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.digitalsanctuary.com/tech-blog/java/jboss/seam/make-a-custom-richfaces-skin.html/feed</wfw:commentRss>
		<slash:comments>0</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>
	</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/48 queries in 0.014 seconds using disk: basic
Object Caching 814/910 objects using disk: basic

Served from: www.digitalsanctuary.com @ 2012-02-07 00:36:23 -->
