Since we were just talking about the
Action that forwarded to
ShowRecipe.jsp, let's
discuss Actions in more detail.
In struts-config.xml,
we defined two <action> elements:
ShowRecipe and FindRecipe.
ShowRecipe is an instance of
org.apache.struts.actions.ForwardAction,
so we don't have to write any code for it; it just
redirects to the page specified by the
parameter attribute, which is
FindRecipe.jsp in this
case. In contrast, ShowRecipe provides
custom functionality, so we need to write our own
class extending
org.apache.struts.action.Action instead
of using a pre-defined Action like
FindRecipe did. We call that class
com.skillfusion.examples.struts.actions.ShowRecipeAction.
001 /*
002 * ShowRecipeAction.java created on Apr 27, 2005 at 10:02:21 AM
003 *
004 * strutsExample is a simple web application that allows a user to search and
005 * view a set of recipes.
006 * Copyright (C) 2005 SkillFusion Software
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License as published by
010 * the Free Software Foundation; either version 2 of the License, or
011 * (at your option) any later version.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, write to the Free Software
020 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
021 */
022 package com.skillfusion.examples.struts.actions;
023
024 import javax.servlet.http.HttpServletRequest;
025 import javax.servlet.http.HttpServletResponse;
026
027 import org.apache.struts.action.Action;
028 import org.apache.struts.action.ActionForm;
029 import org.apache.struts.action.ActionForward;
030 import org.apache.struts.action.ActionMapping;
031 import org.apache.struts.action.ActionMessage;
032 import org.apache.struts.action.ActionMessages;
033
034 import com.skillfusion.examples.struts.bizobjs.Recipe;
035 import com.skillfusion.examples.struts.forms.ShowRecipeForm;
036 import com.skillfusion.examples.struts.serviceobjimpls.RecipeFactoryImpl;
037
038 /**
039 * Adapter to parse out the name from the request, request a <code>Recipe</code>
040 * of that name from the service layer, and forward the results to a
041 * <tt>JSP</tt>.
042 *
043 * @author hank
044 */
045 public class ShowRecipeAction extends Action {
046
047 /**
048 * Pulls the name of a <code>Recipe</code> out of the request, gets it
049 * using the appropriate service object, and forwards to the show recipe JSP
050 * page. If no matching <code>Recipe</code> could be found, it adds an
051 * error message to the response.
052 *
053 * @param mapping
054 * The <code>ActionMapping</code> used to select this instance
055 * @param form
056 * The optional <code>ActionForm</code> bean for this request
057 * (if any)
058 * @param request
059 * The HTTP request we are processing
060 * @param response
061 * The HTTP response we are creating
062 * @return <code>ActionForward</code> instance describing where and how
063 * control should be forwarded, or <tt>null</tt> if the response
064 * has already been completed
065 * @throws Exception
066 * if the application business logic throws an exception
067 * @see org.apache.struts.action.Action#perform(
068 * org.apache.struts.action.ActionMapping,
069 * org.apache.struts.action.ActionForm,
070 * javax.servlet.http.HttpServletRequest,
071 * javax.servlet.http.HttpServletResponse)
072 */
073 public final ActionForward execute(final ActionMapping mapping,
074 final ActionForm form, final HttpServletRequest request,
075 final HttpServletResponse response) throws Exception {
076
077 // Cast the form bean to its actual type
078 ShowRecipeForm f = (ShowRecipeForm) form;
079
080 // Pull the name off the form
081 String name = f.getName();
082
083 // Try to pull a recipe matching this name
084 RecipeFactory recipeFactory = RecipeFactoryImpl.getInstance();
085 Recipe recipe = recipeFactory.getRecipeByName(name);
086 if (null == recipe) {
087 // Add an error message - use ActionMessage and its ilk as it is now
088 // favored over ActionError
089 ActionMessages messages = new ActionMessages();
090 messages.add("name", new ActionMessage(
091 "error.nonexistent.name"));
092 saveMessages(request, messages);
093 // Forward control to the specified failure target
094 return (mapping.findForward("failure"));
095 }
096
097 // Add the Recipe to the session
098 request.setAttribute("recipe", recipe);
099
100 // Forward control to the specified success target
101 return (mapping.findForward("success"));
102 }
103 }
|
org.apache.struts.actions.Action and
the classes that extend it are loosely built on the
Adapter design pattern. For more information
on Adapter, check out the definitive book
on design patterns,
Design Patterns: Elements of Reusable Object-Oriented Software.
Generally speaking, objects built on the
Adapter pattern convert the interface of
a class into a different interface expected by
another class. If that sounds complicated, don't
worry; it's a lot easier than it sounds. In the
specific case of Struts Actions, they
take an incoming request and transform the
information it contains into the sort of information
expected by the beans containing the logic the user
wants to execute.
ShowRecipeAction is fairly simple.
On line 78, it casts the generic
ActionForm it receives down to the more
specific ShowRecipeForm, then pulls the
value of the name property off it on
line 81. On line 86, it uses that value to request a
Recipe object from the
RecipeFactory. If the
RecipeFactory can't find the requested
Recipe, the Action adds an
ActionMessage to a collection of such
messages named error on the
HttpServletRequest and forward to the
failure target we defined in
struts-config.xml. If the
Action does find the requested
Recipe, it sets it as an attribute on
the HttpServletRequest and then
forwards to the success target we defined in
struts-config.xml.