<?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>Benjamin McCann - Development Blog &#187; Java</title>
	<atom:link href="http://www.benmccann.com/dev-blog/category/java/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.benmccann.com/dev-blog</link>
	<description>The software development weblog of Benjamin McCann.</description>
	<lastBuildDate>Mon, 01 Feb 2010 18:18:33 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Using Struts 2 on Google App Engine</title>
		<link>http://www.benmccann.com/dev-blog/using-struts-2-on-google-app-engine/</link>
		<comments>http://www.benmccann.com/dev-blog/using-struts-2-on-google-app-engine/#comments</comments>
		<pubDate>Sun, 20 Dec 2009 07:50:15 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[Struts 2]]></category>

		<guid isPermaLink="false">http://www.benmccann.com/dev-blog/?p=240</guid>
		<description><![CDATA[Google App Engine (GAE) has some great benefits such as scalability and the fact that it&#8217;s free to start.  When using Struts 2 with Google App Engine there a few things to keep in mind.
The first is that it runs inside a security sandbox that is more restrictive than your typical Java environment.  This means [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://code.google.com/appengine/">Google App Engine (GAE)</a> has some great benefits such as scalability and the fact that it&#8217;s free to start.  When using <a href="http://struts.apache.org/2.x/index.html">Struts 2</a> with Google App Engine there a few things to keep in mind.</p>
<p>The first is that it runs inside a security sandbox that is more restrictive than your typical Java environment.  This means that <a href="http://www.opensymphony.com/ognl/">OGNL</a>, the expression language that Struts 2 uses, will not work correctly out of the box.  You can fix this by adding a listener as described in <a href="http://programmingpanda.blogspot.com/2009/07/struts-2-ongl-issue-on-google-app.html">this article</a>.  An example listener can be found <a href="http://code.google.com/p/usaopengov/source/browse/trunk/src/org/usaopengov/action/security/OgnlFixListener.java">here</a> and is used in <a href="http://code.google.com/p/usaopengov/source/browse/trunk/war/WEB-INF/web.xml">this web.xml file</a>.</p>
<p>The second problem is that Google App Engine has some special URLs that it uses.  If you try to visit them, Struts 2 will attempt to process the request as if it&#8217;s a Struts 2 Action and will bomb out when the Action can&#8217;t be found.  You can add an exclusion filter to your struts.xml to counteract this problem:</p>
<pre><code>&lt;constant name="struts.action.excludePattern" value="/_ah/.*"/&gt;</code></pre>
<p>﻿</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/using-struts-2-on-google-app-engine/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Case Study: Usable and Unusable APIs</title>
		<link>http://www.benmccann.com/dev-blog/case-study-good-and-bad-apis/</link>
		<comments>http://www.benmccann.com/dev-blog/case-study-good-and-bad-apis/#comments</comments>
		<pubDate>Sun, 26 Jul 2009 00:13:50 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.benmccann.com/dev-blog/?p=210</guid>
		<description><![CDATA[It was the best of times, it was the worst of times&#8230;
It was the age of wisdom, it was the season of light.  A great library called dom4j was written with its users in mind.  It included a quick start guide and a cookbook for people that actually wanted to get things done.  Converting a [...]]]></description>
			<content:encoded><![CDATA[<p>It was the best of times, it was the worst of times&#8230;</p>
<p>It was the age of wisdom, it was the season of light.  A great library called <a href="http://www.dom4j.org/dom4j-1.6.1/guide.html">dom4j</a> was written with its users in mind.  It included a <a href="http://www.dom4j.org/dom4j-1.6.1/guide.html">quick start guide</a> and a <a href="http://www.dom4j.org/dom4j-1.6.1/cookbook.html">cookbook</a> for people that actually wanted to get things done.  Converting a document to a String took 15 characters: document.asXML().  But there were too many competing XML parsing implementations, so a <a href="http://java.sun.com/j2se/1.5.0/docs/api/org/w3c/dom/Document.html">standard</a> was created.  And sadly, dom4j has not been updated to adhere to that standard.</p>
<p>It was the age of foolishness, it was the epoch of incredulity.  15 characters to turn a document into a string?  That is far too few.  What will we tell our managers when they ask how many lines of code we have written?  We have a better way and it is called <a href="http://xerces.apache.org/xerces-j/">Xerces</a>:<br />
<code>
<pre>import java.io.StringWriter;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Node;

public final class XmlUtil {

  private static final TransformerFactory factory = TransformerFactory.newInstance();

  public static String toString(Node node) {
    if (node == null) {
      return null;
    }
    try {
      Source source = new DOMSource(node);
      StringWriter stringWriter = new StringWriter();
      Result result = new StreamResult(stringWriter);
      Transformer transformer = factory.newTransformer();
      transformer.transform(source, result);
      return stringWriter.getBuffer().toString();
    } catch (TransformerConfigurationException e) {
      e.printStackTrace();
    } catch (TransformerException e) {
      e.printStackTrace();
    }
    return null;
  }

}</pre>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/case-study-good-and-bad-apis/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Sample log4j.properties file</title>
		<link>http://www.benmccann.com/dev-blog/sample-log4j-properties-file/</link>
		<comments>http://www.benmccann.com/dev-blog/sample-log4j-properties-file/#comments</comments>
		<pubDate>Sat, 18 Jul 2009 21:45:14 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[log4j]]></category>

		<guid isPermaLink="false">http://www.benmccann.com/dev-blog/?p=206</guid>
		<description><![CDATA[I always find the hardest part of getting started with log4j is creating a log4j.properties file.  For that reason, I&#8217;ve posted an example below. This file configures log4j to log any messages of level info or higher to the console except for classes under the com.dappit.Dapper.parser or org.w3c.tidy packages.
#------------------------------------------------------------------------------
#
#  The following properties set [...]]]></description>
			<content:encoded><![CDATA[<p>I always find the hardest part of getting started with log4j is creating a log4j.properties file.  For that reason, I&#8217;ve posted an example below. This file configures log4j to log any messages of level info or higher to the console except for classes under the com.dappit.Dapper.parser or org.w3c.tidy packages.</p>
<pre><code>#------------------------------------------------------------------------------
#
#  The following properties set the logging levels and log appender.  The
#  log4j.rootCategory variable defines the default log level and one or more
#  appenders.  For the console, use 'S'.  For the daily rolling file, use 'R'.
#  For an HTML formatted log, use 'H'.
#
#  To override the default (rootCategory) log level, define a property of the
#  form (see below for available values):
#
#        log4j.logger. =
#
#    Available logger names:
#      TODO
#
#    Possible Log Levels:
#      FATAL, ERROR, WARN, INFO, DEBUG
#
#------------------------------------------------------------------------------
log4j.rootCategory=INFO, S

log4j.logger.com.dappit.Dapper.parser=ERROR
log4j.logger.org.w3c.tidy=FATAL

#------------------------------------------------------------------------------
#
#  The following properties configure the console (stdout) appender.
#  See http://logging.apache.org/log4j/docs/api/index.html for details.
#
#------------------------------------------------------------------------------
log4j.appender.S = org.apache.log4j.ConsoleAppender
log4j.appender.S.layout = org.apache.log4j.PatternLayout
log4j.appender.S.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n

#------------------------------------------------------------------------------
#
#  The following properties configure the Daily Rolling File appender.
#  See http://logging.apache.org/log4j/docs/api/index.html for details.
#
#------------------------------------------------------------------------------
log4j.appender.R = org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File = logs/bensApps.log
log4j.appender.R.Append = true
log4j.appender.R.DatePattern = '.'yyy-MM-dd
log4j.appender.R.layout = org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n

#------------------------------------------------------------------------------
#
#  The following properties configure the Rolling File appender in HTML.
#  See http://logging.apache.org/log4j/docs/api/index.html for details.
#
#------------------------------------------------------------------------------
log4j.appender.H = org.apache.log4j.RollingFileAppender
log4j.appender.H.File = logs/bensApps.html
log4j.appender.H.MaxFileSize = 100KB
log4j.appender.H.Append = false
log4j.appender.H.layout = org.apache.log4j.HTMLLayout</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/sample-log4j-properties-file/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Printing a Stack Trace anywhere in Java</title>
		<link>http://www.benmccann.com/dev-blog/printing-a-stack-trace-anywhere-in-java/</link>
		<comments>http://www.benmccann.com/dev-blog/printing-a-stack-trace-anywhere-in-java/#comments</comments>
		<pubDate>Fri, 03 Jul 2009 21:40:59 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Tips and Tricks]]></category>

		<guid isPermaLink="false">http://www.benmccann.com/dev-blog/?p=202</guid>
		<description><![CDATA[You don&#8217;t need to catch an Exception in order to print a stack trace in Java.  Sometimes they can be helpful for debugging and logging purposes.  Here&#8217;s an example of how to print a stack trace at any moment:

new Exception().printStackTrace();

If you want more control over the output, you can build some code off the following:

 [...]]]></description>
			<content:encoded><![CDATA[<p>You don&#8217;t need to catch an Exception in order to print a stack trace in Java.  Sometimes they can be helpful for debugging and logging purposes.  Here&#8217;s an example of how to print a stack trace at any moment:<br />
<code>
<pre>new Exception().printStackTrace();</pre>
<p></code></p>
<p>If you want more control over the output, you can build some code off the following:<br />
<code>
<pre>  System.out.println("Printing stack trace:");
  StackTraceElement[] elements = Thread.currentThread().getStackTrace();
  for (int i = 1; i < elements.length; i++) {
    StackTraceElement s = elements[i];
    System.out.println("\tat " + s.getClassName() + "." + s.getMethodName()
        + "(" + s.getFileName() + ":" + s.getLineNumber() + ")");
  }</pre>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/printing-a-stack-trace-anywhere-in-java/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Maven on Eclipse Tutorial</title>
		<link>http://www.benmccann.com/dev-blog/maven-on-eclipse-tutorial/</link>
		<comments>http://www.benmccann.com/dev-blog/maven-on-eclipse-tutorial/#comments</comments>
		<pubDate>Sun, 12 Apr 2009 23:25:32 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.benmccann.com/dev-blog/?p=183</guid>
		<description><![CDATA[Install Java and Maven
First off, make sure you have a Java JDK installed and that your JAVA_HOME environment variable points to it.  You can check by typing &#8220;echo %JAVA_HOME%&#8221; in Windows or &#8220;echo $JAVA_HOME&#8221; in Linux.  You&#8217;ll next want to download and install Maven by following the directions on their website.  Once Maven [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Install Java and Maven</strong></p>
<p>First off, make sure you have a Java JDK installed and that your JAVA_HOME environment variable points to it.  You can check by typing &#8220;echo %JAVA_HOME%&#8221; in Windows or &#8220;echo $JAVA_HOME&#8221; in Linux.  You&#8217;ll next want to <a href="http://maven.apache.org/download.html">download and install Maven</a> by following the directions on their website.  Once Maven is installed, you&#8217;ll want to create a settings.xml file in your .m2 directory, which is located at ~/.m2 in Linux or C:\Documents and Settings\%USER%\.m2 on Windows.  You can do this by copying the settings.xml file from the directory where Maven in installed to you .m2 directory.</p>
<p><strong>Install m2eclipse</strong></p>
<p>You&#8217;ll want to make sure your Eclipse installation is pointint at your JDK.  You can check by going to Window &gt; Preferences &gt; Java &gt; Installed JREs.  You&#8217;ll also want to set the -vm flag in your eclipse.ini file which is located at the root of your Eclipse installation.  Here&#8217;s what my file looks like:</p>
<pre><code>-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
256M
-framework
plugins\org.eclipse.osgi_3.4.0.v20080605-1900.jar
-vm
C:\Program Files\Java\jdk1.6.0_11\bin\javaw.exe
-vmargs
-Dosgi.requiredJavaVersion=1.5
-Xms40m
-Xmx512m</code></pre>
<p>Finally, you get to install <a href="http://m2eclipse.codehaus.org/">m2eclipse</a> by opening up Eclipse and selecting Help &gt; Software Updates&#8230; &gt; Available Software &gt; Add Site&#8230;  Then enter http://m2eclipse.sonatype.org/update/, check the newly added boxes, and press Install.</p>
<p><strong>Create Your First Maven Project</strong></p>
<p>Now for the fun.  You can create a Maven project in Eclipse by selecting New &gt; Project&#8230; &gt; Maven &gt; Maven Project.  Check &#8220;Create a simple project&#8221; on the first screen and hit Next.  Enter the Group Id, Artifact Id, and Name.  For example, &#8220;com.benmccann.robot&#8221;, &#8220;window-robot&#8221;, &#8220;Window Robot&#8221;.  Now, at long last, you can do some actual programming.</p>
<p><strong>Add Dependencies<br />
</strong></p>
<p>It won&#8217;t be long before you&#8217;ll want to add dependancies.  Open the Maven Indexes View by selecting Window &gt; Show View &gt; Other&#8230; &gt; Maven &gt; Maven Indexes.  You&#8217;ll want to make sure you have the Maven Central Repository, so right-click the view and choose &#8220;Add Index&#8221;.  Enter http://repo1.maven.org/maven2/ for the Repository URL and hit Retrieve to fill in the Repository Id of central.  Now you can right-click the project and choose Maven &gt; Add Dependancy.  We&#8217;ll add jUnit since you&#8217;ll probably want it anyway.  Type junit and you should see it populated into the box below.  Use the dropdown at the bottom to set a scope of &#8220;test&#8221; and hit OK.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/maven-on-eclipse-tutorial/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Using the GWT ClickListener on an Element</title>
		<link>http://www.benmccann.com/dev-blog/using-the-gwt-clicklistener-in-an-html-table/</link>
		<comments>http://www.benmccann.com/dev-blog/using-the-gwt-clicklistener-in-an-html-table/#comments</comments>
		<pubDate>Mon, 24 Nov 2008 19:34:23 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[GWT]]></category>

		<guid isPermaLink="false">http://www.benmccann.com/dev-blog/?p=139</guid>
		<description><![CDATA[GWT uses what it calls a ClickListener instead of the standard HTML onclick attribute.  The normal way to use a GWT CLickListener would be as follows:
focusWidget.addClickListener(new ClickListener() {
  public void onClick(Widget sender) {
    // do something here
  }
});
Unfortunately, this seems not to work on an HTML Element.  Luckily, you can [...]]]></description>
			<content:encoded><![CDATA[<p>GWT uses what it calls a <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/1.5/com/google/gwt/user/client/ui/ClickListener.html">ClickListener</a> instead of the standard HTML onclick attribute.  The normal way to use a GWT CLickListener would be as follows:</p>
<pre><code>focusWidget.addClickListener(new ClickListener() {
  public void onClick(Widget sender) {
    // do something here
  }
});</code></pre>
<p>Unfortunately, this seems not to work on an HTML Element.  Luckily, you can use JSNI to write some native JavaScript and get around the problem:</p>
<pre><code>/**
 * Example of adding an onlick attribute to an element.
 */
public native void addClickListener(Element element) /*-{
  element.onclick = function() {
    // do something here
    return false;
  };
}-*/;</code></pre>
<p>Just be careful about what your onclick is doing in order to avoid possible memory leaks.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/using-the-gwt-clicklistener-in-an-html-table/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Struts 2 AJAX Tutorial &#8211; Dojo Autocompleter Example</title>
		<link>http://www.benmccann.com/dev-blog/struts-2-ajax-tutorial-dojo-autocompleter-example/</link>
		<comments>http://www.benmccann.com/dev-blog/struts-2-ajax-tutorial-dojo-autocompleter-example/#comments</comments>
		<pubDate>Sun, 21 Sep 2008 00:46:46 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[Dojo Toolkit]]></category>
		<category><![CDATA[Struts 2]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.lumidant.com/blog/?p=104</guid>
		<description><![CDATA[This tutorial was written for Struts 2.1.2.  A lot has changed in newer versions.  The Dojo Plugin is no longer officially supported by the Struts 2 team.  Also, please see Muhammad&#8217;s comment in the comment section if you&#8217;re using the latest version of Struts 2.
Struts 2 comes with a Dojo Toolkit plugin [...]]]></description>
			<content:encoded><![CDATA[<p>This tutorial was written for Struts 2.1.2.  A lot has changed in newer versions.  The Dojo Plugin is no longer officially supported by the Struts 2 team.  Also, please see Muhammad&#8217;s comment in the comment section if you&#8217;re using the latest version of Struts 2.</p>
<p>Struts 2 comes with a <a href="http://dojotoolkit.org/">Dojo Toolkit</a> plugin which makes developing an AJAX application easier than ever.  In addition, the AJAX plugin I would most recommend is the <a href="http://cwiki.apache.org/S2PLUGINS/json-plugin.html">Struts 2 JSON plugin</a>.  In this example, we will use the two side-by-side to create an autocompleter.  In order to use the Ajax support provided in Struts 2, I would recommend Struts 2.1.2 or later.  Include struts2-dojo-plugin-2.1.2.jar and jsonplugin-0.30.jar in your WEB-INF/lib directory.</p>
<p>First, we will create the action for the field that we wish to autocomplete:</p>
<pre><code>package com.lumidant.tutorial.struts2.action;

import java.util.HashMap;
import java.util.Map;

import com.opensymphony.xwork2.ActionSupport;
import com.lumidant.tutorial.struts.dao.*;

public class AutocompleteField extends ActionSupport {

    private String city;
    private Map&lt;String,String&gt; json;

    public String execute() throws Exception() {
        return SUCCESS;
    }

    public String getCities() throws Exception() {
        json = new HashMap&lt;String,String&gt;();

        if(city != null &amp;&amp; city.length() &gt; 0) {
            CityDao dao = new CityDao();
            List&lt;City&gt; cities = dao.getCitiesStartingWith(city);
            for(City city : cities) {
                json.put(city.getId(), city.getName() + ", " + city.getState().getAbbreviation());
            }
        }

        return SUCCESS;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public Map&lt;String,String&gt; getJson() {
        return json;
    }

}
</code></pre>
<p>The getCities method in our action acts on the input String city that we&#8217;re given and creates a Map of cities starting with that text.  The key of our Map is going to be the hidden option value while the value of our Map is going to be our option text.</p>
<p>Next, we will modify our struts.xml configuration file to utilize the JSON plugin by extending json-default:</p>
<pre><code>&lt;package name="example" extends="json-default"&gt;
  &lt;action name="AutocompleteField" class="com.lumidant.tutorial.struts2.action.AutocompleteField"&gt;
    &lt;result type="json&gt;&lt;param name="root"&gt;json&lt;/param&gt;&lt;/result&gt;
  &lt;/action&gt;
&lt;/package&gt;</code></pre>
<p>The root parameter that we specify is the name of the variable from our Action that we want to have converted and serialized to a JSON output.</p>
<p>And finally, we get to create our .jsp view:</p>
<pre><code>&lt;%@ taglib prefix="s" uri="/struts-tags" %&gt;
&lt;%@ taglib prefix="sx" uri="/struts-dojo-tags" %&gt;

&lt;html&gt;
  &lt;head&gt;
    &lt;sx:head /&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;s:url id="cityList" action="AutocompleteField" method="getCities" /&gt;
    &lt;sx:autocompleter name="city" theme="ajax" href="%{cityList}" size="24" /&gt;
  &lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>For any of the Dojo plug-in features that you use, you will need to include the &lt;sx:head /&gt; tag, which includes the relevant JavaScript tags into your page&#8217;s head tag.  Then you can see that the autocompleter&#8217;s name attribute aligns with the city field in our Action and the url&#8217;s method attribute aligns with our Action&#8217;s getCities method.  Now, when you visit your new page and start typing in the text box, you should see the field autocompleting.  There are some other cool built-in Dojo tags that you should look at as well like the datetimepicker, which provides a really nice calendar.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/struts-2-ajax-tutorial-dojo-autocompleter-example/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Struts 2 Tutorial &#8211; Validation and Error Handling</title>
		<link>http://www.benmccann.com/dev-blog/struts-2-tutorial-validation-and-error-handling/</link>
		<comments>http://www.benmccann.com/dev-blog/struts-2-tutorial-validation-and-error-handling/#comments</comments>
		<pubDate>Sat, 20 Sep 2008 23:33:40 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.lumidant.com/blog/?p=102</guid>
		<description><![CDATA[Validation is an important part of any web framework because it is one of the most painfully repetitive things to have to continually recreate.  In Struts 2, validation is handled by creating an Action-validation.xml file.  So, if we have an AddUser Action then we would create an AddUser-validation.xml file:
&#60;!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
 [...]]]></description>
			<content:encoded><![CDATA[<p>Validation is an important part of any web framework because it is one of the most painfully repetitive things to have to continually recreate.  In Struts 2, validation is handled by creating an Action-validation.xml file.  So, if we have an AddUser Action then we would create an AddUser-validation.xml file:</p>
<pre><code>&lt;!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"&gt;

&lt;validators&gt;
  &lt;field name="userId"&gt;
    &lt;field-validator type="requiredstring"&gt;
      &lt;message&gt;Username is required&lt;/message&gt;
    &lt;/field-validator&gt;
  &lt;/field&gt;
&lt;/validators&gt;</code></pre>
<p>It is important that you have both a getter and setter for the field you are validating.  For example, AddUser would need both of the following method signatures for validation to work properly: &#8220;public String getUserId()&#8221; and &#8220;public void setUserId(String userId)&#8221;.  You can get more information about the other types of validators from the <a href="http://struts.apache.org/2.x/docs/validation.html">Struts 2 documentation</a>.</p>
<p>You can also control error handling from your Action class.  For example, let&#8217;s say that the user picks a username which is already registered.  We wouldn&#8217;t be able to determine this with validation alone, but would need to check the database in our Action class.  So when we determine that we can call &#8220;addActionError(String message)&#8221; from our class.  Then when we want to print any errors out on our page, we simply use the tag:</p>
<pre><code>&lt;s:actionerror /&gt;</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/struts-2-tutorial-validation-and-error-handling/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Struts 2 Tutorial &#8211; Struts Configuration</title>
		<link>http://www.benmccann.com/dev-blog/struts-2-tutorial-struts-configuration/</link>
		<comments>http://www.benmccann.com/dev-blog/struts-2-tutorial-struts-configuration/#comments</comments>
		<pubDate>Sat, 20 Sep 2008 18:16:47 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Struts 2]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.lumidant.com/blog/?p=100</guid>
		<description><![CDATA[The struts.xml file defines the relationship between actions and .jsp views, the inclusion of interceptors, and possible result types.  It&#8217;s essential that you be able to handle at least basic configuration changes, so we&#8217;ll demonstrate the most important and frequently used below.
Packages: Extension, Namespaces, and More
For more complex applications, you will likely want to split [...]]]></description>
			<content:encoded><![CDATA[<p>The struts.xml file defines the relationship between actions and .jsp views, the inclusion of <a href="http://www.lumidant.com/blog/struts-2-tutorial-interceptors/">interceptors</a>, and possible result types.  It&#8217;s essential that you be able to handle at least basic configuration changes, so we&#8217;ll demonstrate the most important and frequently used below.</p>
<p><strong>Packages: Extension, Namespaces, and More</strong></p>
<p>For more complex applications, you will likely want to split the configuration between multiple packages.  In Struts 2.0.x, the the default package is <a href="http://struts.apache.org/2.0.11.2/docs/struts-defaultxml.html">struts-default</a>.  Most of the time, extending this package is a pretty good place to start from.</p>
<pre><code>&lt;package name="example" extends="struts-default"&gt;
</code><code>  &lt;interceptors&gt;
    &lt;interceptor name="authorization" class="com.lumidant.tutorial.struts2.interceptor.AuthorizationInterceptor"&gt;

    &lt;interceptor-stack name="authStack"&gt;
      &lt;interceptor-ref name="authorization" /&gt;
      &lt;interceptor-ref name="defaultStack" /&gt;
    &lt;/interceptor-stack&gt;
  &lt;/interceptors&gt;
</code><code>
  &lt;global-results&gt;</code><code>
    &lt;result name="error"&gt;/WEB-INF/pages/error.jsp&lt;/result&gt;
</code><code>  &lt;/global-results&gt;</code>

<code>&lt;/package&gt;</code></pre>
<p>In the package above, we did not define any action mappings, but rather we defined some more general properties that we can share between other packages.   We can now extend the package we just defined when creating new packages.  This package and any that extend it will have all Action.ERROR results go to error.jsp.  We also defined a new interceptor and interceptor stack that our actions and packages can make use of.  In this example, you could imagine that we would have two other packages extending this one.  One package would contain pages that any user could visit.  The other package could contain pages requiring the user to be logged in, so we would set the default-interceptor-ref to &#8220;authStack&#8221; as shown below:</p>
<pre><code>&lt;package name="admin" namespace="/admin" extends="example"&gt;
  &lt;default-interceptor-ref name="authStack"/&gt;

  &lt;action name="DeleteSomething_*" method="{1}" class="com.lumidant.tutorial.struts2.action.DeleteSomething"&gt;
    &lt;result name="input"&gt;/WEB-INF/pages/deleteSomething.jsp&lt;/result&gt;
    &lt;result&gt;/WEB-INF/pages/deleteSuccessful.jsp&lt;/result&gt;
  &lt;/action&gt;
&lt;/package&gt;</code></pre>
<p>We also introduced additional new topics in this example.  Firstly, you&#8217;ll see that we created a namespace.  That means that all the actions in this package will be accessed through a spearate URL.  In this example it is an &#8220;/admin&#8221; URL.  Also, you&#8217;ll see that we put the &#8220;*&#8221; wildcard in the action name.  What this is doing is taking what was located in the * and replacing the &#8220;{1}&#8221; with that string.  Since the &#8220;{1}&#8221; is located in the method attribute, we will be calling a method on our action.  So let&#8217;s say the user accesses /admin/DeleteSomething_input.action.  Then the input method of the DeleteSomething.java action will be called.  Assuming we did not define our own input method, then we will inherit the input method from ActionSupport, which will take us to the result named &#8220;input&#8221;, which in this example is the deleteSomething.jsp page.</p>
<p><strong>Action Chaining</strong></p>
<pre><code>&lt;action name="LogIn_*" method="{1}" class="com.lumidant.tutorial.struts2.action.LogIn"&gt;
  &lt;result type="chain"&gt;ShowHomepage&lt;/result&gt;
&lt;/action&gt;</code></pre>
<p>What happens when we don&#8217;t want to show a .jsp page as the result of our action, but instead want to continue on directly to another action?  We simply use the result type &#8220;chain&#8221; to forward to another action.</p>
<p><strong>Redirect After Post</strong></p>
<pre><code>&lt;action name="SubmitOrder_*" method="{1}" class="com.lumidant.tutorial.struts2.action.SubmitOrder"&gt;
</code>  &lt;result name="redirect" type="redirect-action"&gt;
    &lt;param name="actionName"&gt;DisplayOrder&lt;/param&gt;
    &lt;param name="namespace"&gt;/user&lt;/param&gt;
  &lt;/result&gt;
<code>&lt;/action&gt;</code></pre>
<p>Very often, after an action is taken, we want to redirect the user to a separate action.  For example, let&#8217;s say the user submits an order.  If we leave the URL in their browser as SubmitOrder.action and they hit refresh, then the order could be submitted a second time.  So after they submit an order, it&#8217;s probably better if we redirect them to another action, such as one displaying the order they just placed with a thank you message.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/struts-2-tutorial-struts-configuration/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Struts 2 Tutorial &#8211; Interceptors</title>
		<link>http://www.benmccann.com/dev-blog/struts-2-tutorial-interceptors/</link>
		<comments>http://www.benmccann.com/dev-blog/struts-2-tutorial-interceptors/#comments</comments>
		<pubDate>Sat, 20 Sep 2008 04:48:35 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Struts 2]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.lumidant.com/blog/?p=85</guid>
		<description><![CDATA[Interceptors are my favorite aspect of Struts 2.  They inspect and/or act on a user&#8217;s request.  There are three main uses cases that I&#8217;ll discuss here: intercepting before the action, between the action and view, and after the view.  At the end, I&#8217;ll show you how to add your brand spankin&#8217; new [...]]]></description>
			<content:encoded><![CDATA[<p>Interceptors are my favorite aspect of Struts 2.  They inspect and/or act on a user&#8217;s request.  There are three main uses cases that I&#8217;ll discuss here: intercepting before the action, between the action and view, and after the view.  At the end, I&#8217;ll show you how to add your brand spankin&#8217; new interceptor to your struts.xml file so that it is called on each request.</p>
<p><strong>Intercepting Before the Action:</strong></p>
<pre><code>package org.lumidant.tutorial.struts2.interceptor;

import java.util.Map;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ValidationAware;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class AuthorizationInterceptor extends AbstractInterceptor {

	private static final String USER_KEY = "user";

	public String intercept(ActionInvocation invocation) throws Exception {
		Map session = invocation.getInvocationContext().getSession();
		if(session.get(USER_KEY) == null) {
			addActionError(invocation, "You must be authenticated to access this page");
			return Action.ERROR;
		}

		return invocation.invoke();
	}

	private void addActionError(ActionInvocation invocation, String message) {
		Object action = invocation.getAction();
		if(action instanceof ValidationAware) {
			((ValidationAware) action).addActionError(message);
		}
	}

}</code></pre>
<p>You can see that we check to see if the user is authorized and present an error message if he/she is not logged in.  We do this by adding an ActionError, which can be displayed on your view.  If the user is logged in, then he/she proceeds normally.</p>
<p><strong>Intercepting Between the Action and Generation of View:</strong></p>
<pre><code>package org.lumidant.tutorial.struts2.interceptor;

import java.util.Map;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.interceptor.PreResultInterceptor;
import org.apache.struts2.ServletActionContext;

public class WirelessInterceptor extends AbstractInterceptor {

	private static final String RESULT_CODE_SUFFIX_WIRELESS = "Wireless";
	private static final String REQUEST_HEADER_ACCEPT = "Accept";
	private static final String ACCEPT_HEADER_WIRELESS = "vnd.wap";

	public String intercept(ActionInvocation invocation) throws Exception {

		invocation.addPreResultListener()(new PreResultListener() {
			public void beforeResult(ActionInvocation invocation, String resultCode) {

				// check if a wireless version of the page exists
				// by looking for a wireless action mapping in the struts.xml
				Map results = invocation.getProxy().getConfig().getResults();
				if(!results.containsKey(resultCode + RESULT_CODE_SUFFIX_WIRELESS)) {
					return;
				}

				// send to wireless version if wireless device is being used
				final String acceptHeader = ServletActionContext.getRequest().getHeader(REQUEST_HEADER_ACCEPT);
				if(acceptHeader != null &amp;&amp; acceptHeader.toLowerCase().contains(ACCEPT_HEADER_WIRELESS)) {
					invocation.setResultCode(resultCode + RESULT_CODE_SUFFIX_WIRELESS);
				}
			}
		});

		return invocation.invoke();
	}
}</code></pre>
<p>In this example, the action has already been taken, but we have not generated the view that the user will see yet.  This allows us to send the user to a separate page if he/she is using a Blackberry.  We check the Accept HTML header to see if the string &#8220;vnd.wap&#8221; is present and if so then we append &#8220;Wireless&#8221; to the result code.  So if the action was going to send the user to the result &#8220;Success&#8221; then we will instead show them the result &#8220;SuccessWireless&#8221;.  We could easily adopt this technique for a Google Android or an iPhone as well.</p>
<p><strong>Intercepting after View Creation:</strong></p>
<pre><code>package org.lumidant.tutorial.struts2.interceptor;

import java.util.Map;

import org.hibernate.Transaction;
import org.marketcharts.data.dao.util.HibernateSessionFactory;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class HibernateInterceptor extends AbstractInterceptor {

	public String intercept(ActionInvocation invocation) throws Exception {
		try {
			return invocation.invoke();
		} catch(Exception e) {
			Transaction tx = HibernateSessionFactory.getSession().getTransaction();
			if(tx != null &amp;&amp; tx.isActive()) {
				tx.rollback();
			}
			return Action.ERROR;
		} finally {
			HibernateSessionFactory.getSession().close();
		}
	}

}</code></pre>
<p>This example uses Hibernate, an Object Relational Mapper (ORM), which is library for easy database access.  Hibernate needs an open session when the view is created (Open Session in View Pattern) because it lazily accesses the database.  If the session is closed and we go to access the database, then Hibernate will throw an Exception.  So this interceptor provides a method to close the session after the view has already been created and all the database calls have been made.</p>
<p><strong>Adding an Interceptor to your struts.xml:</strong></p>
<pre><code>&lt;package name="example" extends="struts-default"&gt;
  &lt;interceptors&gt;
    &lt;!--
      One possible use of an interceptor is to send the user to special version of the .jsp
  	view if they are using a Blackberry as shown above.
    --&gt;
    &lt;interceptor name="wireless" class="com.lumidant.tutorial.struts2.interceptor.WirelessInterceptor"&gt;

    &lt;interceptor-stack name="wirelessStack"&gt;
      &lt;interceptor-ref name="exception" /&gt;
      &lt;interceptor-ref name="servlet-config" /&gt;
      &lt;interceptor-ref name="i18n" /&gt;
      &lt;interceptor-ref name="chain" /&gt;
      &lt;interceptor-ref name="params" /&gt;
      &lt;interceptor-ref name="wireless" /&gt;
    &lt;/interceptor-stack&gt;
  &lt;/interceptors&gt;

  &lt;default-interceptor-ref name="wirelessStack" /&gt;
&lt;/package&gt;</code></pre>
<p>In this example, we&#8217;ve change the default interceptor stack to be a custom stack which we&#8217;ve created.  You can also extend existing stacks.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmccann.com/dev-blog/struts-2-tutorial-interceptors/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
	</channel>
</rss>
