Showing posts with label Struts2. Show all posts
Showing posts with label Struts2. Show all posts

Friday, May 6, 2011

Extending ParametersInterceptor to get Request Header data

Sometimes, particularly when you work with OpenAM, you need to be pretty friendly with the request header. I am sure a lot of other things use it as well, but OpenAM is where I have seen it the most - once you log in, OpenAM passes user attributes back in the request header. This is very useful, however, it does present one annoyance when your web application makes use of Struts, and that is the fact that you need to extract the parameter from the request header.

This is not a big deal, just a little bit of an annoyance. Basically, you need to follow the steps here for making your action ServletRequestAware. This instructs Struts to inject the HttpServletRequest object into your action. Once you do that, you can simply call request.getHeader("headerName") to get the header object you are looking for.

That is nice and all, but being the inquisitive and annoying personality I am, I wanted something cleaner. I don't like having to deal with the HttpServletRequest object - that is one of the benefits of Struts, hiding that stuff. So I set out to make an interceptor to do it for me. As it turns out, it was quite a bit easier than I would have expected.

First off, lets define the goal. I wanted an interceptor that would read parameters from the request headers, and inject them into my action class. So, for example, if I want the user's uid attribute, I just want to have the following in my action class:
private String uid;

public void setUid(String uid)
{
    this.uid = uid;
}

public String getUid()
{
    return uid;
}

Since this functionality is very similar to what the params interceptor does for me already, I looked there first. The Struts params interceptor points to the class ParametersInterceptor, included in the Struts 2 library. This is a fairly beefy bit of code, but one thing jumped out in particular:
/**
 * Gets the parameter map to apply from wherever appropriate
 *
 * @param ac The action context
 * @return The parameter map to apply
 */
protected Map<String, Object> retrieveParameters(ActionContext ac) {
    return ac.getParameters();
}

As it turns out, the Struts authors have been very kind to us here, as the ParametersInterceptor is built to be quite easily overridable. So, to build our interceptor, the code can be quite simple, really. All you need is this:
public class RequestHeaderInterceptor extends ParametersInterceptor implements StrutsStatics {
    private static final long serialVersionUID = 1L;
 
    /**
     * Gets the parameter map to apply from wherever appropriate
     *
     * @param ac The action context
     * @return The parameter map to apply
     */
    @Override
    protected Map<String, Object> retrieveParameters(ActionContext ac) {
        Map<String, Object> params = new HashMap<String, Object>();
  
        HttpServletRequest request = (HttpServletRequest) ac.get(HTTP_REQUEST);
        Enumeration<String> names = request.getHeaderNames();
        while ( names.hasMoreElements() )
        {
            String name = (String)names.nextElement();
            String val = request.getHeader(name);
            params.put(name, val);
        }
  
        return params;
    }
}

One more minor annoyance to this is that the ParametersInterceptor, and therefore this new RequestHeaderInterceptor, needs to be in the middle of the interceptor stack. That means that you must forgo the use of the defaultStack, and roll you own instead. It would look a little something like this:
<interceptor-stack name="customDefaultStack">
    <interceptor-ref name="exception"/>
    <interceptor-ref name="alias"/>
    <interceptor-ref name="servletConfig"/>
    <interceptor-ref name="i18n"/>
    <interceptor-ref name="prepare"/>
    <interceptor-ref name="chain"/>
    <interceptor-ref name="debugging"/>
    <interceptor-ref name="scopedModelDriven"/>
    <interceptor-ref name="modelDriven"/>
    <interceptor-ref name="fileUpload"/>
    <interceptor-ref name="checkbox"/>
    <interceptor-ref name="multiselect"/>
    <interceptor-ref name="staticParams"/>
    <interceptor-ref name="actionMappingParams"/>
    <interceptor-ref name="requestHeader" />
    <interceptor-ref name="params">
      <param name="excludeParams">dojo\..*,^struts\..*</param>
    </interceptor-ref>
    <interceptor-ref name="conversionError"/>
    <interceptor-ref name="validation">
        <param name="excludeMethods">input,back,cancel,browse</param>
    </interceptor-ref>
    <interceptor-ref name="workflow">
        <param name="excludeMethods">input,back,cancel,browse</param>
    </interceptor-ref>
</interceptor-stack>

Nice and simple, and now you can get your request headers directly injected into your action.

One more optional step, if you don't want to have all of your actions injected but prefer a more manual step to request that they be injected, you can create a custom interceptor, like so:
public interface RequestHeaderParameterAware
{
}

Then you update your RequestHeaderInterceptor class, adding the following:
@Override
    public String doIntercept(ActionInvocation invocation) throws Exception {
        Object action = invocation.getAction();
        if (action instanceof RequestHeaderParameterAware) {
            return super.doIntercept(invocation);
        }
        return invocation.invoke();
    }

With that little bit of extra code, you now have a system in which any actions implementing the RequestHeaderParameterAware interface will have request headers automatically injected.

Thursday, February 10, 2011

Metadata Hell

I recently had the opportunity to attend JavaOne in San Francisco, which was a very great overall experience. One thing that I noticed, though, was the apparent love affair with annotations. It would seem that annotations are The Next Big Thing. In almost every session that I attended, there was some person going on and on about how great annotations are. Look, you can configure things on a single line! OOOH, you can configure properties in line with your code! Holy Crap, you can embed connection information into annotation tags directly in your java code!

No, I really was not kidding about that last one. Apparently, the new best practice in Java is to put all of your configuration information into annotations. By all, I really mean all configuration information, right down to your database connection strings. The very thing that I have been taught since I saw my first for loop, that which has been banged into me repeatedly as the worst danger in the world, is now best practice!

We are now hard coding this stuff in our code.

From what I can gather, this was put forth as the solution to what was commonly referred to as XML Hell. People didn't like all of the XML configuration that was having to occur to get applications running. I can understand this concern - XML files can be a pain in the rear end. I think, though, that the mark was missed a bit on this one. All we have really done is trade out one Hell for another.

My biggest concern with annotations is the unnecessary complication of the code files. Take the following example, taken from a Struts2 convention plug-in example:
package com.example.actions;

import com.opensymphony.xwork2.ActionSupport; 
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Actions;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;

@Results({
  @Result(name="failure", location="fail.jsp")
})
public class HelloWorld extends ActionSupport {
  @Action(value="/different/url", 
    results={@Result(name="success", location="http://struts.apache.org", type="redirect")}
  )
  public String execute() {
    return SUCCESS;
  }

  @Action("/another/url")
  public String doSomething() {
    return SUCCESS;
  }
}
Here is the exact same Action class, without the annotations:
package com.example.actions;

import com.opensymphony.xwork2.ActionSupport; 

public class HelloWorld extends ActionSupport {

  public String execute() {
    return SUCCESS;
  }

  public String doSomething() {
    return SUCCESS;
  }
}
That is a dramatic reduction in complexity, and that is just on a simple example application. What is more, it is now encouraged that every single third party library, framework, whatever, should now all use annotations. Look at the above code again: that is the added complexity from a single framework's configuration. What is going to happen when you have a framework and a handful of libraries and they all want to use different annotations?

The rub of it is, in my mind, that there was another solution available - simplify the XML. Having XML files isn't a problem; it provides a nice, isolated place to put the metadata of your application, keeping it separate from the logic of your application. However, most XML configuration is very complex, large, tree-like structures. Take, for example, the XML needed to configure a Java servlet:

    HelloWorld
    com.jspbook.HelloWorld


    HelloWorld
    /HelloWorld

Here is the annotation configuration version:
@WebServlet(name="HelloWorld", urlPatterns={"/HelloWorld"})
I can admit that the above configuration is more simple than the current configuration. However, here would be a proposed alternative in XML, which would also reduce it to a single line:
<servlet name="HelloWorld" urlPattern="/HelloWorld" class="com.jspbook.HelloWorld"/>
With that, you have the simplicity of a single line of configuration, but still safely tucked away in a separate XML file.

In fact, it is my theory that there is nothing that you can do with annotations that you can't do in just as few lines in an XML file. The only difference is that in the XML file you need to specify what class you are referring to. That is it.

In short, while I see the need for something to be done to reduce the configuration pains that we as developers currently experience, I absolutely do not think that the answer is to move that pain to a place where I have to stare at it and read through it every single day. There are other, better solutions out there, if we would but take the time to look for them.

Wednesday, February 2, 2011

Struts2 vertical radio list without custom template

I have seen a lot of questions sent out into the void of the internet, wondering how you could do something as simple in Struts2 as make a radiobutton list display vertically instead of the default horizontally. The answer always seems to be writing a custom template for it. While this is an effective solution, it often does not fit the problem at hand.

I had an issue not long ago where I had to put a radio list inside of a grid, interspersed with other form elements. In this case, writing a custom template with <br> tags after each radio button did not work. So I came up with another way of handling this pesky situation. It is not quite as elegant as writing a custom template, but it will get the job done.

Basically, what you have to do to lay the radios out vertically is to use multiple radio tags, each pointing to the same selector variable, each with a limited version of the actual list. Here is a simple example:
<s:radio name="valueField" list="#{'value1':'label1'}"/><br>
<s:radio name="valueField" list="#{'value2':'label2'}"/><br>
<s:radio name="valueField" list="#{'value3':'label3'}"/>
That will display one radio button per line, still connected as a single list. It will default if "valueField" is already set, and it will successfully post back into "valueField".

As a bit meatier of an example, take the following code. This code shows an Action class with a List of Objects, which we will then iterate over in the jsp page. This shows a more typical setup.

ListObject.java:
public class ListObject {
    private String key;
    private String label;

    public ListObject(key,label) {
        this.key = key;
        this.label = label;
    }

    public String getKey() {
        return this.key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getLabel() {
        return this.label;
    }

    public void setLabel(String label) {
        this.label = label;
    }
}
ListAction.java
public class ListAction extends ActionSupport {
    private List<ListObject> myList;
    private String mySelection;
    
    public String input() {
        myList = new ArrayList<ListObject>();
        myList.add(new ListObject("val1","label1"));
        myList.add(new ListObject("val2","label2"));
        myList.add(new ListObject("val3","label3"));

        mySelection = "val2";

        return INPUT;
    }

    public String execute() {
        // Do stuff with list here
        return SUCCESS;
    }

    public List<ListObject> getMyList() {
        return myList;
    }
    public void setMyList(List<ListObject> newList) {
        this.myList = newList;
    }

    public String getMySelection() {
        return mySelection;
    }
    public void setMySelection(String newSelection) {
        this.mySelection = newSelection;
    }
}
list.jsp

    <s:radio theme="simple" name="mySelection" list="#{key:label}"/> <br>


At the core of this method is the specifying of independent sublists for each radio tag. The syntax inside the list attribute is the way you specify an in place list - "#{'key':'value','key2':'value2'}". For our lists, though, instead of using string literals, we are pulling the values from our iterator. Inside an iterator tag, the iterator object is at the top of the value stack, so that just referencing the variable names of the data members of the object pulls out the value successfully. Then Struts magic takes care of combining all those radio tags with the same name to point to the single back end data member.

Creating custom templates can often be the better solution, but in situations where that doesn't work, this is a good way to go as well.

Tuesday, February 1, 2011

Creating a custom Struts2 validator

Recently I was working on a project which had a very specific validation requirement, that the Struts2 validation framework did not currently support. I had a dynamic collection of objects, and I needed to make sure that an attribute of that object was distinct across the entire collection.

I could have added a validate method to my action class and perform the validation there manually, but I wanted to keep everything in the xml validation. So I used the opportunity to learn how to write a custom Struts2 validator.

As it turns out, it is not nearly so complex as it sounds. To start things off, I created a new class that extended FieldValidatorSupport, since I wanted this validator to be a field validator. I then overrode the "validate" method, which does the actual validation. So here would be the very basic validator:
package my.package.name;

import com.opensymphony.xwork2.validator.ValidationException;
import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport;

public class UniqueCollectionValidator extends FieldValidatorSupport
{ 
    @Override
    public void validate(Object object) throws ValidationException
    {
    }
}

I am going to jump ahead now and show you how to hook up said validator, because that comes into play in building the validator. So, first step in wiring up a custom interceptor is adding a file called validators.xml to your project's classpath. The contents of the file should look like this:

    


Second step is just referencing the validator. Open up your action's validation.xml file and add the following validator underneath the field you want it to apply to:


That is everything needed to wire up your custom validator. Now we get to the fun part - making your validator, you know, validate something. First off, and this is the part that needed the wiring in place to properly show, is adding parameters. As it turns out, you can add as many parameters to your validator as needed, and it does not take much. In this case, we need as a parameter the name of the attribute on the object that we need to be distinct.

First step to adding a parameter is to add the private member variable to your validator class, and give it getters and setters, like so:
package my.package.name;

import com.opensymphony.xwork2.validator.ValidationException;
import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport;

public class UniqueCollectionValidator extends FieldValidatorSupport
{
    String uniqueFieldName = "";

    public String getUniqueFieldName()
    {
        return uniqueFieldName;
    }

    public void setUniqueFieldName(String uniqueFieldName)
    {
        this.uniqueFieldName = uniqueFieldName;
    }

    @Override
    public void validate(Object object) throws ValidationException
    {
    }
}

Once we have getters and setters in our validator, we populate them by simply adding those elements to our xml validator.

    <param name="uniqueFieldName">myUniqueFieldName</param>


All that is left now is filling in the details of the validator.
package my.package.name;

import com.opensymphony.xwork2.validator.ValidationException;
import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport;

public class UniqueCollectionValidator extends FieldValidatorSupport
{
    String uniqueFieldName = "";

    public String getUniqueFieldName()
    {
        return uniqueFieldName;
    }

    public void setUniqueFieldName(String uniqueFieldName)
    {
        this.uniqueFieldName = uniqueFieldName;
    }

    @Override
    public void validate(Object object) throws ValidationException
    {
        String fieldName = getFieldName();
        Object val = getFieldValue(fieldName, object);
        
        List collection = null;
        List<String> soFar = new ArrayList<String>();
        
        if ( val instanceof List )
        {
            collection = (List) val;
        }
        else
        {
            return;
        }
        
        for ( Object obj : collection )
        {
            String toCheck = "";
            
            if ( this.uniqueFieldName.length() == 0 )
            {
                toCheck = (String) obj;
            }
            else
            {
                toCheck = (String) getFieldValue(this.uniqueFieldName,obj);
            }
            
            if ( soFar.contains(toCheck) )
            {
                addFieldError(fieldName, object);
                return;
            }
            
            soFar.add(toCheck);
        }
    }
}
This is kind of a lot of code to just dump on you, but most of it is pretty straightforward. There are just a few useful little bits to point out.

First off, when you enter a field validator, the object passed in contains the field parameter we are trying to validate against. In order to get the specific field we are dealing with, we use two member functions of FieldValidatorSupport - getFieldName and getFieldValue.
String fieldName = getFieldName();
Object val = getFieldValue(fieldName, object);
This gets for you the name of the field that we are validating against, and the current value of that field.

This validator can only work against List objects, so the first thing I do after that is make sure that it is a List, and cast the val appropriately. If it is not a List, then I just return without validating anything.
if ( val instanceof List )
{
    collection = (List) val;
}
else
{
    return;
}

At that point, I am able to move forward with my logic for determining uniqueness. The only other key piece of information here is the way to fail validation. If you hit the case where your validation fails, you can simply do the following:
addFieldError(fieldName, object);
return;
This will tell Struts that validation failed on this field, and it will use the normal method of choosing what message to display from the validation xml file.

That's all there is to it.

Friday, January 28, 2011

Creating Custom Struts2 Interceptors

Now we're into it. The meaty stuff. If you have not read my post on Struts2 Interceptors, I recommend you head over that way first. With me so far? Great, lets dig in.

So, why would you want to create your own interceptor? Granted, there are a whole bunch of provided interceptors. There are several that are provided but are not used in the default interceptor stack, that might be worth checking out. Things like the LoggingInterceptor (logs when you enter and leave an action) and the TimerInterceptor (tracks how long an Action take to execute) are wonderful tools that should be looked into. So, what is left?

Basically, if you ever find yourself adding code or wishing you could add code to each of your actions, you have a valid candidate for a custom interceptor.

The case study we are going to follow today is a problem I ran into a while back. I had a standard jsp header and footer that were included in every page of my site. I wanted to be able to turn on some debugging features in those pages whenever the struts.devMode constant was set to true. However, I couldn't find any way to check the struts.devMode constant from the jsp page. Could be that there is a way, but I couldn't find it. I did find that you could grab it from within your action class, and that you could set it to a member of your action class and access that from your jsp. Eck.

So I decided to make a custom interceptor. This interceptor would be responsible for getting the current value of the struts.devMode constant, and putting that on the Value Stack. In naming this interceptor, I went a step further, and called it GenerateConstants, figuring I could use this to inject any of the struts constants that I might need in the future. To kick things off, I started with the following code inside a file called GenerateConstants.java:

package mypackage.interceptor;

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

public class GenerateConstants extends AbstractInterceptor {
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        // Perform pre-action stuff here
        String result = invocation.invoke();
        // Perform post-action stuff here
        return result;
    }
}

Excellent, we have the base structure. Time to fill it out a little bit. First we add the devMode property, and have struts inject it for us.

package mypackage.interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class GenerateConstants extends AbstractInterceptor {
    private String devMode;

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        // Perform pre-action stuff here
        String result = invocation.invoke();
        // Perform post-action stuff here
        return result;
    }

    @Inject("struts.devMode") 
    public void setDevMode(String devMode) {
        this.devMode = devMode;
    }
}

Finally, we push this value into the Value Stack

package my.package.name;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class GenerateConstants extends AbstractInterceptor {
    private String devMode;

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        // Perform pre-action stuff here
        if ( devMode != null )
        {
            invocation.getInvocationContext().put("devMode", devMode);
        }

        String result = invocation.invoke();
        // Perform post-action stuff here
        return result;
    }

    @Inject("struts.devMode") 
    public void setDevMode(String devMode) {
        this.devMode = devMode;
    }
}

That is the entire amount of interceptor code needed. There is still a little more work to be done, though. Now comes the fun part - hooking it up! Crack on open your struts.xml file, and we'll work on the plumbing.

First thing that you have to do is to declare the interceptor, so that struts is aware that it exists. Inside your struts.xml file, if it does not already exist, add the interceptors tag, and add your interceptor to it, like so:


    
        
            
        
        
    


Next we need to create a new interceptor stack to use the new interceptor. Remember the default stack we talked about before? We are going to add to that now.


    
        
            

            
                
                
            
        
        
    


So here we are using the "interceptor-stack" tag to define a new stack. The child tag "interceptor-ref" just points to either an interceptor or an interceptor stack that is already defined. So in this case, we are defining our new stack with "generateConstants" as the first interceptor, followed by the "defaultStack" interceptor stack, which is the default stack provided with struts.

Finally, we have one more step to carry out. Right now, we have our shiny new stack, but we still have not told anything to use it. In order to do that, we can either declare our stack inside each Action, or we can override the default stack for all actions. The first method can be useful if you have a stack that only needs to be executed on a handful of Actions. However, our interceptor should be used by all Actions, so we are going to update the default. To do that, all we need to do is add a single tag called "default-interceptor-ref", outside of the "interceptors" tag, like so:


    
        
            

            
                
                
            
        

        

        
    


That's all there is to it. A few XML tags and a little bit of code, and you have a new interceptor.

Thursday, January 27, 2011

Struts2 Interceptors

Interceptors are one of the most powerful, and yet seemingly least understood feature of Struts2. The Interceptor framework is basically the core of the Struts2 framework, and understanding how it works is the key to really unlocking the power of Struts2.

For any given web request, there is a series of Interceptors that get fired off before your Action class is called. Each Interceptor performs a specific job that is required for every action. Some of the core functionality of Struts2 lives in these Interceptors by default, such as populating the member variables of your action class, validating data and exception handling.

The Interceptors fire based off of what is known as the Interceptor Stack. The Stack is just an ordered list of Interceptors that need to be fired prior to entering the action. When you include the struts core library in your project, it includes a file called "struts-default.xml", which defines all of the core Interceptors and a default Interceptor Stack. Since these are set up by default, and they handle most use cases, most people do not really understand the Stack, because it "Just Works".

To understand how it works, you just need to look at what happens when struts receives a new request. It starts things off by creating an object called the ActionInvocation, and calling a method called "invoke" on that object. During the first trigger, invoke looks at the configured Stack, gets the first Interceptor configured, and fires that Interceptor's "intercept" method.

Inside "intercept" is where the Interceptor performs whatever tasks it needs to get done. For example, there is an Interceptor available for use called the LoggingInterceptor. Inside of this Interceptor's "intercept" method, the first thing that it does is log out an "Entering" message.

After performing any necessary operations, the interceptor then calls ActionInvocation.invoke again. Bear in mind the call stack we have going so far:
    ActionInvocation.invoke()
        Interceptor1.intercept()
            ActionInvocation.invoke()

Back inside invoke, the ActionInvocation class has kept track of what Interceptors it has already fired. In this case, it has made note of the fact that Interceptor1 has already been called. It looks again at the Stack, and finds the Interceptor configured to fire after Interceptor1, and calls that Interceptor's "intercept" method.

This continues on and on, until we reach the last interceptor. After the last interceptor performs whatever it needs to do, it again calls ActionInvocation.invoke. ActionInvocation now recognizes that all of the Interceptors have been called, and proceed to call the Action class's execute method. So the final call stack looks something like this:
    ActionInvocation.invoke()
        Interceptor1.intercept()
            ActionInvocation.invoke()
                Interceptor2.intercept()
                    ActionInvocation.invoke()
                        .
                        .
                        .
                        InterceptorN.intercept()
                            ActionInvocation.invoke()
                                Action.execute()

This is now the part that most people are familiar with - the Action class. Your Action does what it needs to do, then returns a String value. Something like "success", "error", "input", etc. These return values end up determining what page gets displayed to the user.

This String that gets returned by your Action class - where does it go? If we look up at our call stack, we will see that it will return to ActionInvocation.invoke. Interesting. Here is the fun part - both ActionInvocation.invoke and all of the Interceptors "intercept" methods return Strings as well. In fact, they return your String.

So now we start to unwind back up the Stack. This is another very important part of the framework. Do you ever remember seeing those weird Struts2 pictures, that show all of the Interceptors being fired twice? Once before the Action, and once after? Like this one:


This call stack is how that works. The Interceptors do not actually get fired twice. They are fired once, but the Action call occurs inside of them. Back to the above mentioned LoggingInterceptor now. As I said, this Interceptor logs out an "Entering" message when it starts, then it fires "invoke". After "invoke" returns, though, this Interceptor is not done - it also logs a "Leaving" message afterward.

Here is the complete code necessary in order to log an entering and leaving message before and after every single one of your Action calls:
@Override
public String intercept(ActionInvocation invocation) throws Exception {
        logMessage(invocation, START_MESSAGE);
        String result = invocation.invoke();
        logMessage(invocation, FINISH_MESSAGE);
        return result;
}

That's it. Instead of log lines inserted at the top and bottom of every single Action class, this one little snippet set up as an Interceptor does all that work for you.

I wanted to go over how to do a custom interceptor, but I have already prattled quite a bit longer than I thought I would. Hopefully I have given you a bit better understanding on how Interceptors work, and gotten you hungry to learn how you can start writing your own. More posts will follow.

The Struts2 Framework

I'll admit, when I first started web development, I didn't like frameworks. I was a do-it-yourself kind of guy. I didn't want to have to deal with learning the ins and outs of someone else's code. Now that I have begun to use frameworks, though, I would never go back.

My current framework of choice is Struts 2. I have a lot of respect for this framework, and I feel like it does a lot for me in a really elegant way. You will probably hear me blather on about it quite a bit, as it is where I spend most of my time these days.

Struts 2 is an MVC framework, or a Model-View-Controller. MVC is a design pattern that is used to separate the parts of a web application into separate layers. A layer is an isolation of a type of code that keeps it independent of the implementation of the other layers.

The View is the part of the code that actually handles how the data is presented. In Struts 2, this is typically handled by jsp files.

The Controller is what hooks up the View with the Model. It is what controls where the flow goes, what view to display, what business logic to execute. It is kind of the brain of the operation. In Struts 2, the Action class acts as the Controller. Your Action class should not have any business logic in it directly. Rather, it should call into a Service layer that executes your business logic, then alter the flow of the View based off of what it returns.

The Model is the parts of the code that actually contain the business logic. I typically isolate this into a Service layer, which is called from the Action class.

The beauty of the MVC design pattern is that these layers are totally isolated from one another. If we want to start using freemarker templates instead of jsps, we could do that, and we wouldn't have to touch our Action class or Service layer. If we want to change our business logic, it should not affect our Action class or View layer.

There are other MVC frameworks out there. What makes Struts 2 stand out from the others? Well, to start with, it is the one that my employer wants me to use - always a good incentive. That being said, I personally still prefer Struts 2 to any of the other frameworks I have tried. My only other experience has been with Spring MVC, which seems to be a good solution as well, but made less sense to me than Struts 2 does.

Struts 2 has a lot of features, and I have barely begun to scratch the surface on all that it can do. More posts will come in the future that start talking about the Interceptor concept, the built in validation framework, and many of the other features that Struts 2 has to offer.

I leave you today with the thing that most developers always want to see in a new technology - the Hello World.

The following clips were taken from http://struts.apache.org/2.x/docs/hello-world.html.

The Action class:
package tutorial;
import com.opensymphony.xwork2.ActionSupport;
public class HelloWorld extends ActionSupport {

    public static final String MESSAGE = "Struts is up and running ...";

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

    private String message;

    public void setMessage(String message){
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}

The struts.xml file:
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <package name="tutorial" extends="struts-default">
        <action name="HelloWorld" class="tutorial.HelloWorld">
            <result>/HelloWorld.jsp</result>
        </action>
        <!-- Add your actions here -->
    </package>
</struts>

The JSP file:
<%@ taglib prefix="s" uri="/struts-tags" %>

<html>
    <head>
        <title>Hello World!</title>
    </head>
    <body>
        <h2><s:property value="message" /></h2>
    </body>
</html>