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_cn
Articles_pt
Articles_zh
CreateActions
CreateActions_pt
CreateActions_zh
SpringControllerUnit...
SpringControllers_ko
ValidationAndListSpr...
...and 1 more




JSPWiki v2.2.33

[RSS]


Hide Menu

SpringControllers


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


Part III: Creating Controllers and JSPs - A HowTo for creating Spring Controllers 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 Spring Controller and JSP. It'll also demonstrate writing a JUnit Test to test the Controller. The Controller 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 JSPs into your webapp.
I will tell you how I do stuff in the Real World in text like this.

Let's get started by creating a new Controller and JSP in AppFuse's architecture. If you haven't installed the Spring MVC module at this point, do so by running ant install-springmvc.

Table of Contents

  • [1] Create a skeleton JSP using XDoclet
  • [2] Create PersonFormControllerTest to test our Controller
  • [3] Create PersonFormController
  • [4] Run the PersonFormControllerTest

Create a skeleton JSP using XDoclet [#1]

In this step, we'll generate a skeleton or our JSP for displaying information from the Person object. I say skeleton because it'll just be the <form> itself. It will contain table rows with Spring's "bind" tags for each property in Person.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 Form_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:

  • From the command-line, navigate to "extras/viewgen"
  • Execute ant -Dform.name=Person to generate three files in extras/viewgen/build:
    • Person.properties (labels for your form elements)
    • personForm.jsp (skeleton JSP file for viewing a single Person)
    • personList.jsp (skeleton JSP file for viewing a list of People)
  • Copy the contents of Person.properties into web/WEB-INF/classes/ApplicationResources_en.properties. Here is an example of what you might add to ApplicationResources_en.properties:
# -- person form --
person.firstName=First Name
person.id=Id
person.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.
The files in the "pages" directory will end up in "WEB-INF/pages" at deployment time. The container provides security for all files below WEB-INF. This applies to client requests, but not to forwards from the DispatchServlet. Placing all JSPs below WEB-INF ensures they are only accessed through Controllers, and not directly by the client or each other. This allows security to be moved up into the Controller, where it can be handled more efficiently, and out of the base presentation layer.

The web application security for AppFuse specifies that all *.html url-patterns should be protected. This guarantees 1) all Controllers are protected, and 2) you must go through a Controller to get to a JSP (or at least the ones in pages).

At this point, you won't be able to view the JSP in your browser because spring's "bind" tags require that the JSP is invoked from the DispatchServlet. Therefore, we need to create a Controller for this JSP, and we should practice TDD and write our Test before we write our Controller.

Create PersonFormControllerTest to test our Controller [#2]

To create a JUnit Test for our Controller, start by creating a PersonControllerTest.java file in the test/web/**/action directory.


package org.appfuse.webapp.action;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.servlet.ModelAndView;


public class PersonFormControllerTest extends BaseControllerTestCase {
    private static Log log = LogFactory.getLog(PersonFormControllerTest.class);
    private PersonFormController c;
    private MockHttpServletRequest request;
    private ModelAndView mv;

    protected void setUp() throws Exception {
        // needed to initialize a user
        super.setUp();
        c = (PersonFormControllerctx.getBean("personFormController");
    }

    protected void tearDown() {
        c = null;
    }

    public void testEdit() throws Exception {
        log.debug("testing edit...");
        request = newGet("/editUser.html");
        request.addParameter("username""tomcat");

        mv = c.handleRequest(request, new MockHttpServletResponse());

        assertEquals("personForm", mv.getViewName());
    }
}

Nothing will compile at this point (ant compile) since we need to create the PersonFormController that we're referring to in this test.

Create PersonFormController [#3]

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


package org.appfuse.webapp.action;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.appfuse.model.Person;
import org.appfuse.service.PersonManager;


public class PersonFormController extends BaseFormController {
    
    private static Log log = LogFactory.getLog(PersonFormController.class);
    private PersonManager mgr = null;
    
    public void setPersonManager(PersonManager mgr) {
        this.mgr = mgr;
    }
    
    protected Object formBackingObject(HttpServletRequest request)
            throws Exception {
        String id = request.getParameter("id");
        Person person = null;

        if (!StringUtils.isEmpty(id)) {
            person = mgr.getPerson(id);
        else {
            person = new Person();
        }

        return person;
    }
}

We're not putting much in PersonController at this point because we just want to 1) render the JSP and 2) verify our Test runs. Now we need to add a url-mapping for this controller in the web/WEB-INF/action-servlet.xml file. In the block below, the new line is at the bottom, with <prop key="/editPerson.html">:


    <bean id="urlMapping" 
        class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/editProfile.html">userFormController</prop>
                <prop key="/mainMenu.html">filenameController</prop>
                <prop key="/editUser.html">userFormController</prop> 
                <prop key="/selectFile.html">filenameController</prop>
                <prop key="/uploadFile.html">fileUploadController</prop>
                <prop key="/passwordHint.xml">passwordHintController</prop>
                <prop key="/signup.xml">signupController</prop>
                <prop key="/editPerson.html">personFormController</prop>
            </props>
        </property>
    </bean>

We also need to add the <bean> definition for personFormController in this same file:


    <bean id="personFormController" class="org.appfuse.webapp.action.PersonFormController">
        <property name="commandName"><value>person</value></property>
        <property name="commandClass"><value>org.appfuse.model.Person</value></property>
        <!--property name="validator"><ref bean="beanValidator"/></property-->
        <property name="formView"><value>personForm</value></property>
        <property name="successView"><value>editPerson.html</value></property>
        <property name="personManager"><ref bean="personManager"/></property>
    </bean>

The "validator" property is commented out in the above XML block because we haven't defined any validation rules for the Person object. We'll uncomment this value when we add validation.

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

Run the PersonFormControllerTest [#4]

Now, if you stop Tomcat, save everything, cd ../.. to the base directory and run ant test-web -Dtestcase=PersonFormController, the "testEdit" method should pass and you should see something like the following in your console:

 [echo] Testing web...
 [copy] Copying 1 file to C:\Source\appfuse-springmvc\build\appfuse\WEB-INF
[junit] [appfuse] DEBUG [main] PersonFormControllerTest.testEdit(27) | testing edit...
[junit] [appfuse] DEBUG [main] AbstractFormController.showNewForm(268) | Displaying new form
[junit] Testsuite: org.appfuse.webapp.action.PersonFormControllerTest
[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.297 sec

If you see the message below - Congratulations you've written your first Spring Controller!

BUILD SUCCESSFUL
Total time: 11 seconds

Next Up: Part IV: Configuring Tiles and FormController - Integrating personForm.jsp with Tiles, adding methods for saving, customizing the JSP so it looks good and finally - writing a WebTest to test the JSPs functionality.



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