Raible's Wiki
Raible Designs AppFuseHomepage- Korean - Chinese - Italian - Japanese QuickStart Guide User Guide Tutorials Other ApplicationsStruts ResumeSecurity Example Struts Menu
Set your name in
UserPreferences
Referenced by
JSPWiki v2.2.33
Hide Menu |
This is version 70.
It is not the current version, and thus it cannot be edited. Part III: Creating Actions and JSPs - A HowTo for creating Struts Actions and JSPs in the AppFuse architecture.
About this TutorialThis 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.
Table of Contents
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):
Create skeleton JSPs 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:
# -- person form -- personForm.firstName=First Name personForm.id=Id personForm.lastName=Last Name
body#pageName element.class { background-color: blue }
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
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 PersonActionTest to test PersonAction [#3]To create a StrutsTestCase Test for PersonAction, start by creating a PersonActionTest.java file in the test/web/**/action directory.
Plugin insertion failed: The current page does not have an attachment 'PersonActionTest.java' You will need to add PERSON_KEY as a variable to the src/dao/**/Constants.java class. The name, "personForm", matches the name given to the form in the struts-config.xml file.
If you try to run this test, you will get a number of NoSuchMethodErrors - so let's define the edit, save, and delete methods in the PersonAction class. Create PersonAction [#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: Plugin insertion failed: The current page does not have an attachment 'PersonAction.java' You'll notice in the code above that there are many calls to to convert a PersonForm or a Person object. The convert method is in BaseAction.java (which calls ConvertUtil.convert()) and uses BeanUtils.copyProperties to convert POJOs → ActionForms and ActionForms → POJOs.
Now you need to add the edit forward and the savePerson action-mapping, both which are specified in in the PersonActionTest. To do this, add a couple more XDoclet tags to the top of the PersonAction.java file. Do this right above the class declaration. You should already have the XDoclet tag for the editPerson action-mapping, but I'm showing it here so you can see all the XDoclet tags at the top of this class.
The main difference between the editPerson and savePerson action-mappings is that savePerson has validation turned on (see validation="true") in the XDoclet tag above. Note that the "input" attribute must refer to a forward, and cannot be a path (i.e. /editPerson.html). If you'd prefer to use the save path for both edit and save, that's possible too. Just make sure validate="false", and then in your "save" method - you'll need to call form.validate() and handle errors appropriately. There are a few keys (ActionMessages) that we need to add to ApplicationResources_en.properties to display the success messages. This file is located in web/WEB-INF/classes - open it and add the following:
person.added=Information for <strong>{0}</strong> has been added successfully. person.deleted=Information for <strong>{0}</strong> has been deleted successfully. person.updated=Information for <strong>{0}</strong> has been updated successfully.
You might notice that the code you're using to call the PersonManager is the same as the code used in the PersonManagerTest. Both PersonAction and PersonManagerTest are clients of PersonManagerImpl, so this makes perfect sense. Everything is almost done for this tutorial, let's get to running the tests! Run PersonActionTest [#5]If you look at our PersonActionTest, all the tests depend on having a record with id=1 in the database (and testRemove depends on id=2), so add that to our sample data file (metadata/sql/sample-data.xml). I'd add it at the bottom - order is not important since it (currently) does not relate to any other tables. <table name='person'> <column>id</column> <column>first_name</column> <column>last_name</column> <row> <value>1</value> <value>Matt</value> <value>Raible</value> </row> <row> <value>2</value> <value>James</value> <value>Davidson</value> </row> </table> DBUnit loads this file before we run any of our tests, so this record will be available to the PersonActionTest. Now if you run ant test-cactus -Dtestcase=PersonAction - everything should work as planned. Make sure Tomcat isn't running before you try this. BUILD SUCCESSFULTotal time: 1 minute 21 seconds Clean up the JSP to make it presentable [#6]First, let's clean up our personForm.jsp by making the "id" property a hidden field. Remove the following code block:
And add the following before the <table> tag:
You should change the action of the <html:form> to be "savePerson" so validation will be turned on when saving. Also, change the focus attribute from focus="" to focus="firstName" so the cursor will be in the firstName field when the page loads (this is done with JavaScript). Now if you execute ant db-load deploy-web, start Tomcat and point your browser to http://localhost:8080/appfuse/editPerson.html?id=1, you should see something like this: Finally, to make this page more user friendly, you may want to add a message for your users at the top of the form, but this can easily be done by adding text (using <fmt:message>) at the top of the personForm.jsp page. [Optional] Create a Canoo WebTest to test browser-like actions [#7]The final (optional) step in this tutorial is to create a Canoo WebTest to test the JSPs.
You can use the following URLs to test the different actions for adding, editing and saving a user.
Canoo tests are pretty slick in that they're simply configured in an XML file. To add tests for add, edit, save and delete, open test/web/web-tests.xml and add the following XML. You'll notice that this fragment has a target named PersonTests that runs all the related tests.
After adding this, you should be able to run ant test-canoo -Dtestcase=PersonTests with Tomcat running or ant test-jsp -Dtestcase=PersonTests if you want Ant to start/stop Tomcat for you. To include the PersonTests when all Canoo tests are run, add it as a dependency to the "run-all-tests" target. You'll notice that there's no logging in the client-side window by Canoo. If you'd like to see what it's doing, you can add the following between </webtest> and </target> at the end of each target. <loadfile property="web-tests.result" srcFile="${test.dir}/data/web-tests-result.xml"/> <echo>${web-tests.result}</echo>BUILD SUCCESSFUL Total time: 11 seconds Next Up: Part IV: Adding Validation and List Screen - Adding validation logic to the personForm so that firstName and lastName are required fields and adding a list screen to display all person records in the database. Attachments:
|