Thursday, July 19, 2007

Create a minimalist Apache Struts 2.0 web application with Eclipse

I was recently asked by a colleague what I know about Apache Struts 2.0. I know that Apache Struts 2.0 was heavily redesigned and incorporated many elements of WebWork into it, but I don't have first hand experience with it. So I decided to start looking into it and get some first hand experience with Struts 2.0. This blog entry documents my first attempt at building a minimalist Struts 2.0 web application to be used as blank template for future web applications.

I started out by creating a new dynamic web project in Eclipse

I then copied over the following jar files into <project root>\WebContent\WEB-INF\lib folder (you can find these jar files in the struts blank application) :

  • antlr-2.7.2.jar
  • commons-logging-1.1.jar
  • freemarker-2.3.8.jar
  • ognl-2.6.11.jar
  • struts2-core-2.0.8.jar
  • xwork-2.0.3.jar

I replaced the Eclipse autogenerated web.xml with the following content:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4" 
 xmlns="http://java.sun.com/xml/ns/j2ee" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <display-name>My Sample Strust Web Application </display-name>

    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>

</web-app>

This web.xml file tells the tomcat server to apply the master Struts filter to all resources on the server. The FilterDispatch filter does the following

  • Execute actions
  • Clean up ActionContext (can cause problems with SiteMesh)
  • Serve static content
  • Start XWork's interceptor chain for the request cycle

I created the file struts.xml and put it in the <project root>\src folder with the following content :

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

    <constant name="struts.enable.DynamicMethodInvocation" value="false" />
    <constant name="struts.devMode" value="true" />

    <include file="example.xml"/>

    <!-- Add packages here -->

</struts>

The parameter struts.enable.DynamicMethodInvocation is to enable backward compatibility with WebWork 2. I would set this to false for new web applications. If I enable struts.devMode by setting it to true, I get the following:

  • Resource bundles are reloaded on every request. Which means you can change your properties file and see the changes on the next request.
  • Xml configuration files, validations files are reloaded on every request.
  • Exceptions will be thrown to normally ignorable problems.
  • Remember to turn this off in production!

Since I'm testing this out in development mode, I would set it to true. As you have probably noticed in the struts.xml file, I separated the application configuration to the include file example.xml. We'll begin with a basic example of hello world.

I created the file example.xml in the folder into <project root>\src with the following content :

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

    <package name="examples" namespace="/examples" extends="struts-default">

 <!--  Hellow world example -->
        <action name="HelloWorld">
            <result>/examples/helloworld.jsp</result>
        </action>

        <!-- Add actions here -->
    </package>
</struts>

For those of you who had experiences with Struts 1.x, notice how sensible defaults shorten the configuration significantly. If we do not specify the class attribute in the action tag, it defaults automatically to the default ActionSupport class, which always returns success. If we do not explicitly name the results tag, it defaults to "success" automatically. These sensible defaults allows us to write the above minimalist configuration file.


        <action name="HelloWorld">
            <result>/examples/helloworld.jsp</result>
        </action>

Compare the above configuration with an equivalent Struts 1.x configuration:

        <action path="/examples/HelloWorld"
                name="HelloWorld"
                type="examples.HelloWorldAction"
                validate="false"
            <forward name="HelloWorld" path="/examples/helloworld.jsp" />
        </action>

On top of the extra configuration, I would have also needed to implement HelloWorldAction class.

Testing out the code, I get :

Voila! I have my minimalist Struts 2.0 web application.

2 comments:

Anonymous said...

this is the most informative post ive read this has been so helpful. its generous of you to shareyour knowledge.

Cheers,
Lannie

digital certificate said...

Excellent! Thanks for this - I've been looking at this feature for ages. Followed your instructions and it works a treat!