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.

Friday, July 13, 2007

Interactive exploration of .NET XML programing with F#

In preparing to upload content into the blog, I ran into a lot problems in properly formatting the content. I have code content that I want to upload into the blog with the color syntax highlighting maintained. It might be that I just don't have the appropriate tools or know the appropriate tools, but it's been painful to get it right. I've must of tried posting this blog entry dozens of time and deleting it in frustration because the content did not come out correctly. I probably could have hand written the blog in html but it was too much manual work and it's not a repeatable process. So I look for ways to simplify this process. I normally write my blog content in Microsoft Word and then export it as html. I wanted to write a script that automatically clean up this exported Microsoft Word document into a form suitable for blog upload. Since my latest interest is in the area of functional programming, I decided to take a crack at this using F#. To my delight, I found that the F# Interactive mode (fsi) provides a great interactive environment for exploring .NET classes. Below is a transcript of how I used F# interactive shell to test out .NET classes:

  1. Starting the shell gives you the following:
  2. 
    MSR F# Interactive, (c) Microsoft Corporation, All Rights Reserved
    F# Version 1.9.1.9, compiling for .NET Framework Version v2.0.50727
    
    NOTE:
    NOTE: See 'fsi --help' for flags
    NOTE:
    NOTE: Commands: #r ;;    reference (dynamically load) the given DLL.
    NOTE:           #I ;;    add the given search path for referenced DLLs.
    NOTE:           #use ;;  accept input from the given file.
    NOTE:           #load  ...;;
    NOTE:                            load the given file(s) as a compilation unit.
    NOTE:           #time;;          toggle timing on/off.
    NOTE:           #types;;         toggle display of types on/off.
    NOTE:           #quit;;          exit.
    NOTE:
    NOTE: Visit the F# website at http://research.microsoft.com/fsharp.
    NOTE: Bug reports to fsbugs@microsoft.com. Enjoy!
    
    >
    
    
  3. Begin by importing a few critical namespaces
  4. > open System.IO;;
    > open System.Xml;;
    
  5. Load in the XML document to begin experimentation
  6. > let infile =  "test.htm";;
    
    val infile : string
    
    > let xmldoc = new XmlDocument();;
    
    val xmldoc : XmlDocument
    
    > xmldoc.Load(infile);;
    val it : unit = ()
    >
    
  7. Test searching out all <span> elements
  8. > let spanlist = xmldoc.GetElementsByTagName("span");;
    
    val spanlist : XmlNodeList
    
    >
    
  9. Verify that we got something back from the document
  10. > spanlist.Count;;
    val it : int = 278
    

    Indeed, we got back 278 <span> elements from this xml document. Let's trying examining one of these elements. Let's take a look at the 200th element.

    > spanlist.Item(200).InnerXml;;
    val it : string
    = "<span style=\"mso-spacerun:yes\" xmlns=\"http://www.w3.org/TR/REC-html40\"></span>"
    >
    

Notice how I did not need to go through the code/compile/debug cycle to test things out. The entire .NET class framework is available for scripting. I hope this little example demonstrated the utility of the F# interactive framework. Of course, to use this requires that you learn F#, which is modified OCaml. I guess I'm just geeky enough to want to learn new languages so that this is not a hinderance for me. For more information on F#, check out this site : http://research.microsoft.com/fsharp/fsharp.aspx

Okay, I need go back and finish the F# script to help me post my original blog entry that I'm working on.