Raible's Wiki

Raible Designs
Wiki Home
News
Recent Changes

AppFuse

Homepage
  - Korean
  - Chinese
  - Italian
  - Japanese

QuickStart Guide
  - Chinese
  - French
  - German
  - Italian
  - Korean
  - Portuguese
  - Spanish
  - Japanese

User Guide
  - Korean
  - Chinese

Tutorials
  - Chinese
  - German
  - Italian
  - Korean
  - Portuguese
  - Spanish

FAQ
  - Korean

Latest Downloads

Other Applications

Struts Resume
Security Example
Struts Menu

Set your name in
UserPreferences


Referenced by
Articles
Articles_pt
CreateActions_zh
CreateManager
CreateManager_es
SpringControllers_ko
ValidationAndList




JSPWiki v2.2.33

[RSS]


Hide Menu

CreateActions


This is version 51. It is not the current version, and thus it cannot be edited.
[Back to current version]   [Restore this version]


Part III: Creating Actions and JSPs - A HowTo for creating Struts Actions and JSPs in the AppFuse architecture.
This tutorial depends on Part II: Creating new Managers.

About this Tutorial

This tutorial will show you how to create a Struts Action, a JUnit Test (using StrutsTestCase), and a JSP for the form. The Action we create will talk to the PersonManager we created in the Creating Managers tutorial. This tutorial will simplify everything - we will not actually be rendering any data or making the UI look pretty. The next tutorial will show you how to integrate your new JSP into your webapp.

By default, AppFuse ships with Struts as its web framework. As of 1.6, you can use Spring or WebWork as your web framework. Tapestry and JSF are planned for 1.7 and 1.8 respectively.

To install Spring MVC, navigate to extras/spring, and view the README.txt. For WebWork, see extras/webwork/README.txt. You can easily install these options in your project by running "ant install-springmvc" or "ant install-webwork". This tutorial using these two options can be found at:

Let's get started by creating a new Struts Action and JSP your AppFuse project.

I will tell you how I do stuff in the Real World in text like this.

Table of Contents

  • [1] Add XDoclet Tags to Person to generate PersonForm
  • [2] Create a skeleton JSP using XDoclet
  • [3] Create a new ActionTest to test our Action
  • [4] Create a new Action
  • [5] Display the JSP in a browser and run the ActionTest

Add XDoclet Tags to Person to generate PersonForm [#1]

Now let's generate our PersonForm object for Struts and our web tier. To do this, we need to add XDoclet tags to the Person.java Object to create our Struts ActionForm. In the JavaDoc for the Person.java file, add the following @struts.form tags (use User.java if you need an example):


* @struts.form include-all="true" extends="BaseForm"

We extend org.appfuse.webapp.form.BaseForm because it has a toString() method that allows us to call log.debug(formName) to print out a reader-friendly view of the Form object.
If you haven't renamed the "org.appfuse" packages to "com.company" or otherwise don't have your model class in the default package, you may need to fully-qualify the reference to org.appfuse.webapp.form.BaseForm in the @struts.form tag.

Create a skeleton JSP using XDoclet [#2]

In this step, we'll generate a skeleton or our JSP for displaying information from the PersonForm. I say skeleton because it'll just be the <form> itself. It will contain table rows and Struts' <html:text> tags for each property in PersonForm.java. The tool that we use to do this was written by Erik Hatcher. It's basically just a single class (FormTagsHandler.java) and a couple of XDoclet templates (FormKeys.xdt and StrutsForm_jsp.xdt). All these files are located in extras/viewgen.

Here are the simple steps to generating the JSP and a properties file containing the labels for the form elements:

  • Execute ant compile - this generates the PersonForm.java from the Person.java POJO.
  • From the command-line, navigate to "extras/viewgen"
  • Execute ant -Dform.name=PersonForm to generate three files in extras/viewgen/build:
    • PersonForm.properties (labels for your form elements)
    • personForm.jsp (skeleton JSP file for viewing a single Person)
    • PersonFormList.jsp (skeleton JSP file for viewing a list of People)
  • Copy the contents of PersonForm.properties into web/WEB-INF/classes/ApplicationResources_en.properties. Here is an example of what you might add to ApplicationResources_en.properties:
# -- person form --
personForm.firstName=First Name
personForm.id=Id
personForm.lastName=Last Name
  • Copy personForm.jsp to web/pages/personForm.jsp. Copy PersonFormList.jsp to web/pages/personList.jsp. Notice that each of the new filename's first character is lowercase.
If you want to customize the CSS for a particular page, you can add <body id="pageName"/> to the top of the file. This will be slurped up by SiteMesh and put into the final page. You can then customize your CSS on a page-by-page basis using something like the following:
body#pageName element.class { background-color: blue 
  • Add keys in ApplicationResources_en.properties the titles and headings in the JSPs
In the generated JSPs, there are two keys for the title (top of the browser window) and the header (heading in the page). We now need to add these two keys (personDetail.title and personDetail.heading) to ApplicationResources_en.properties.

Open web/WEB-INF/classes/ApplicationResources_en.properties and add the following to the bottom of the file:

# -- person detail page --
personDetail.title=Person Detail
personDetail.heading=Person Information
NOTE: Just above, we added "personForm.*" keys to this file, so why do I use personForm and personDetail? The best reason is because it gives a nice separation between form labels and text on the page. Another reason is because all the *Form.* give you a nice representation of all the fields in your database. I recently had a client who wanted all fields in the database searchable. This was fairly easy to do. I just looked up all the keys in ApplicationResources.properties which contained "Form." and then put them into a drop-down. On the UI, the user was able to enter a search term and select the column they wanted to search. I was glad I followed this Form vs. Detail distinction on that project!

Create a new ActionTest to test our Action [#3]

To create a StrutsTestCase Test for our Action, start by creating a PersonActionTest.java file in the test/web/**/action directory.
As usual, copy → save as an existing ActionTest (i.e. UserActionTest). Replace [Uu]ser with [P]erson. You might want to make sure Cactus (StrutsTestCase is an extension of Cactus] tests are running before you copy an existing one. Run ant test-cactus -Dtestcase=UserAction to verify the UserAction works. Stop Tomcat before you do this.

If you did copy UserActionTest, make sure and change UserFormEx to PersonForm. The reason for UserFormEx is to support a String setter for Roles. Since the UserForm is generated, it's not very feasible to do it in the User.java object.


package org.appfuse.webapp.action;

public class PersonActionTest extends BaseStrutsTestCase {
    
    public PersonActionTest(String name) {
        super(name);
    }

    public void testExecute() {
        // test execute method
        setRequestPathInfo("/editPerson");
        addRequestParameter("id""1");
        actionPerform();
        verifyNoActionErrors();
    }
}

Everything should compile at this point (ant compile) since we're not referring to the PersonAction directly in our test. However, if you try to run ant test-cactus -Dtestcase=PersonAction, it won't work (make sure Tomcat is not running if you decide to try this).

Create a new Action [#4]

Now we have to create an Action (a.k.a. the Controller) to talk to our Manager and retrieve/save our data. In src/web/**/action, create a PersonAction.java file with the following contents:


package org.appfuse.webapp.action;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;


/**
 * @struts.action name="personForm" path="/editPerson" scope="request"
 *  validate="false" parameter="action" input="mainMenu"
 */
public final class PersonAction extends BaseAction {

    public ActionForward execute(ActionMapping mapping, ActionForm form,
                                 HttpServletRequest request,
                                 HttpServletResponse response)
    throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("Entering 'execute' method");
        }

        // return nothing (yet)
        return null;
    }
}

We're not putting much in PersonAction at this point because we just want to 1) render the JSP and 2) verify our Test runs. The XDoclet tags (beginning with @struts.action) will generate the following XML in the build/appfuse/WEB-INF/struts-config.xml file (when you run ant webdoclet):


<action path="/editPerson" type="org.appfuse.webapp.action.PersonAction"
    name="personForm" scope="request"  input="mainMenu"
    parameter="action" unknown="false" validate="false">
</action>

I formatted the XML above the the purposes of the tutorial. No content has changed.

Everything is almost done for this tutorial, let's get to running our tests!

Display the JSP in a browser and run the ActionTest [#5]

To test the JSP visually in your browser, save everything, run ant deploy, start Tomcat, and navigate to http://localhost:8080/appfuse/personForm.jsp. You should see something similar to the following image in your browser:

personForm-plain.png
There is also a deploy-web target in build.xml that will allow you to just deploy the files in the web directory. Nothing gets compiled or generated when you use this target. If you'd like, you can learn more about available ant targets.

Now, if you stop Tomcat and run ant test-cactus -Dtestcase=PersonAction, that should work too!

BUILD SUCCESSFUL
Total time: 51 seconds
Look in your console's log for PersonAction.execute(33) | Entering 'execute' method. This is the log.debug statement we put in our execute method. You should also be able to view personForm.jsp (make sure Tomcat is running and you've logged into AppFuse) and click the "Save" button to see the same debug message. You may have to login after clicking "Save" since all actions are protected.

Next Up: Part IV: Configuring JSP and Action CRUD methods - Integrating personForm.jsp with Struts, replacing execute with different CRUD methods (add, edit, delete), customizing the JSP so it looks good and finally - writing a WebTest to test the JSPs functionality.


Attachments:


Go to top   More info...   Attach file...
This particular version was published on 06-Nov-2006 13:52:29 MST by MattRaible.