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


Difference between version 117 and version 71:

At line 6 changed 1 line.
This tutorial will show you how to create a Struts Action, a JUnit Test (using [StrutsTestCase|http://strutstestcase.sourceforge.net/]), and a JSP for the form. The Action we create will talk to the PersonManager we created in the [Creating Managers|CreateManager] tutorial. This tutorial will simplify everything - we will not actually be rendering any data or making the UI look pretty. The [next tutorial|ConfiguringTiles] will show you how to integrate your new JSP into your webapp.
This tutorial will show you how to create a Struts Action, a JUnit Test (using [StrutsTestCase|http://strutstestcase.sourceforge.net/]), and a JSP for the form. The Action we create will talk to the PersonManager we created in the [Creating Managers|CreateManager] tutorial.
At line 8 changed 1 line.
By default, AppFuse ships with [Struts|http://struts.apache.org] as its web framework. As of 1.6, you can use [Spring|http://www.springframework.org] or [WebWork|http://opensymphony.org/webwork] as your web framework. Tapestry and JSF are planned for 1.7 and 1.8 respectively.
By default, AppFuse ships with [Struts|http://struts.apache.org] as its web framework. As of 1.6+, you can use [Spring|http://www.springframework.org] or [WebWork|http://opensymphony.org/webwork] as your web framework. In 1.7, support was added for using [JSF|http://myfaces.apache.org] or [Tapestry|http://jakarta.apache.org/tapestry].
At line 10 changed 1 line.
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:
To install any of these web frameworks instead of Struts, simply navigate to the ''extras'' directory and into the directory of the framework you want to install. The README.txt file in this directory has further instructions. The tutorials for these other frameworks are listed below.
At line 12 changed 2 lines.
* <span style="color: green">__Spring MVC:__</span> [Creating Controllers and JSPs|SpringControllers]
* <span style="color: blue">__WebWork:__</span> [Creating Actions and JSPs|WebWorkActions]
* __<span style="color: green">Spring:</span>__ [Creating Spring Controllers and JSPs|SpringControllers]
* __<span style="color: blue">WebWork:</span>__ [Creating WebWork Actions and JSPs|WebWorkActions]
* __<span style="color: purple">JSF:</span>__ [Creating JSF Beans and JSPs|JSFBeans]
* __<span style="color: orange">Tapestry:</span>__ [Creating Tapestry Pages and Templates|TapestryPages]
At line 29 changed 1 line.
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):
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 tag (use User.java if you need an example):
At line 42 added 2 lines.
Now if you run __ant gen-forms__, Ant (and XDoclet) will generate a PersonForm.java for you in build/web/gen/**/form.
At line 41 changed 1 line.
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 &lt;form&gt; itself. It will contain table rows and Struts' &lt;html:text&gt; tags for each property in PersonForm.java. The tool that we use to do this was written by [Erik Hatcher|http://www.blogscene.org/erik/]. 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.
In this step, you'll generate a JSP page to display information from the Person object. It will contain Struts' JSP tags that render table rows for each property in Person.java. The [AppGen] tool that's used to do this is based off a StrutsGen tool - which was originally written by [Erik Hatcher|http://www.blogscene.org/erik/]. It's basically just a couple of classes and a bunch of XDoclet templates. All these files are located in extras/appgen.
At line 45 changed 8 lines.
* 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:
* From the command-line, navigate to "extras/appgen"
* Execute __ant -Dobject.name=Person -Dappgen.type=pojo -Dapp.module=__ to generate a bunch of files in extras/appgen/build/gen. In fact, it'll generate all the files you need to complete this tutorial. However, let's just grab the ones you need.
** web/WEB-INF/classes/Person.properties (labels for your form elements)
** web/pages/personForm.jsp (JSP file for viewing a single Person)
** web/pages/personList.jsp (JSP file for viewing a list of People)
* Copy the contents of Person.properties into web/WEB-INF/classes/ApplicationResources.properties. These are all the keys you will need for titles/headings and form properties. Here is an example of what you should add to ApplicationResources.properties:
At line 56 removed 1 line.
personForm.firstName=First Name
At line 59 added 1 line.
personForm.firstName=First Name
At line 59 removed 3 lines.
}}}
</div>
* 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.''
At line 63 changed 2 lines.
%%note __NOTE:__ If you want to customize the CSS for a particular page, you can add &lt;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 } }}}%%
person.added=Person has been added successfully.
person.updated=Person has been updated successfully.
person.deleted=Person has been deleted successfully.
At line 66 changed 2 lines.
* 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.
# -- person list page --
personList.title=Person List
personList.heading=Persons
At line 69 removed 3 lines.
Open web/WEB-INF/classes/ApplicationResources_en.properties and add the following to the bottom of the file:
{{{
At line 74 added 2 lines.
</div>
* Copy personForm.jsp to web/pages/personForm.jsp. Copy personList.jsp to web/pages/personList.jsp.
At line 77 changed 1 line.
;:''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.
;: ''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 Struts' ActionServlet. Placing all JSPs below WEB-INF ensures they are only accessed through Actions, and not directly by the client or each other. This allows security to be moved up into the Action, where it can be handled more efficiently, and out of the base presentation layer.''
At line 79 changed 1 line.
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!''
The web application security for AppFuse specifies that all *.html url-patterns should be protected (except for /signup.html and /passwordHint.html). This guarantees that clients must go through an Action to get to a JSP (or at least the ones in ''pages'').
At line 81 added 2 lines.
%%note __NOTE:__ If you want to customize the CSS for a particular page, you can add &lt;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 } }}}%%
At line 82 changed 2 lines.
!!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.
* Add keys in ApplicationResources.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). These fields are provided above with key names of personDetail.title and personDetail.heading.
At line 85 changed 1 line.
;:%%(color: blue)''As usual, copy &rarr; save as an existing ActionTest (i.e. UserActionTest). Replace [[Uu]ser with [[P]erson. You might want to make sure [Cactus|http://jakarta.apache.org/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.''%%
''Just above, we added "personForm.*" keys to this file, so why do I use personDetail instead of personForm for the titles and headings? 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.
At line 87 changed 1 line.
;:%%(color: blue)''If you do copy UserActionTest, make sure and change {{UserFormEx}} to {{PersonForm}}. [UserFormEx|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/webapp/form/UserFormEx.java.html] is an extension of UserForm that has a String[[] setter for Roles. Since the UserForm is generated, it's not very feasible to do it in the User.java object.''%%
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!''
At line 91 added 4 lines.
!!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:
At line 104 changed 1 line.
addRequestParameter("action", "Edit");
addRequestParameter("method", "Edit");
At line 115 changed 1 line.
addRequestParameter("action", "Edit");
addRequestParameter("method", "Edit");
At line 125 changed 1 line.
addRequestParameter("action", "Save");
addRequestParameter("method", "Save");
At line 139 changed 1 line.
addRequestParameter("action", "Delete");
addRequestParameter("method", "Delete");
At line 163 changed 1 line.
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:
In src/web/**/action, create a PersonAction.java file with the following contents:
At line 211 changed 3 lines.
new ActionMessage("person.deleted",
personForm.getFirstName() + ' ' +
personForm.getLastName()));
new ActionMessage("person.deleted"));
At line 215 changed 1 line.
saveMessages(request, messages);
// save messages in session, so they'll survive the redirect
saveMessages(request.getSession(), messages);
At line 266 changed 3 lines.
new ActionMessage("person.added",
personForm.getFirstName() + " " +
personForm.getLastName()));
new ActionMessage("person.added"));
At line 276 changed 3 lines.
new ActionMessage("person.updated",
personForm.getFirstName() + " " +
personForm.getLastName()));
new ActionMessage("person.updated"));
At line 292 changed 1 line.
;:''If you are running Eclipse, you might have to "refresh" the project in order to see PersonForm. It lives in build/web/gen, which should be one of your project's source folders. This is the only way for Eclipse to see and import PersonForm, since it is generated by XDoclet and does not live in your regular source tree. You can find it at build/web/gen/org/appfuse/webapp/form/PersonForm.java.''
;:''If you are running Eclipse, you might have to "refresh" the project in order to see PersonForm. It lives in build/web/gen, which should be one of your project's source folders. This is the only way for Eclipse to see and import PersonForm, since it is generated by XDoclet and does not live in your regular source tree. You can find it at build/web/gen/org/appfuse/webapp/form/PersonForm.java.
At line 295 added 2 lines.
;:You can also configure Eclipse to auto-refresh your workspace using: Window > Preferences > General > Workspace > Refresh Automatically.''
At line 307 changed 1 line.
* @struts.action-forward name="edit" path=".personDetail"
* @struts.action-forward name="edit" path="/WEB-INF/pages/personForm.jsp"
At line 314 removed 11 lines.
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:
;:''I usually add these under the {{# -- success messages --}} comment.''
{{{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 could use generic ''added'', ''deleted'' and ''updated'' messages, whatever works for you. It's nice to have separate messages in case these need to change on a per-entity basis.''
At line 353 changed 1 line.
Now if you run __ant test-cactus -Dtestcase=PersonAction__ - everything should work as planned. Make sure Tomcat isn't running before you try this.
Now if you run __ant test-web -Dtestcase=PersonAction__ - everything should work as planned. Make sure Tomcat isn't running before you try this.
At line 359 removed 1 line.
First, let's clean up our personForm.jsp by making the "id" property a hidden field. Remove the following code block:
At line 361 changed 1 line.
[{Java2HtmlPlugin
Now let's clean up the generated personForm.jsp. Change the ''action'' of the &lt;html:form&gt; 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).
At line 363 changed 9 lines.
<tr>
<th>
<appfuse:label key="personForm.id"/>
</th>
<td>
<html:text property="id" styleId="id"/>
</td>
</tr>
}]
Another thing you will need to do is comment out the following lines at the bottom of the personForm.jsp. This is because the Validator will throw an exception if a formName is specified and no validation rules exist for it.
At line 373 changed 1 line.
And add the following before the &lt;table&gt; tag:
;:''Personally, I think this is [a bug|http://nagoya.apache.org/bugzilla/show_bug.cgi?id=27316], but the Struts Committers disagreed.''
At line 375 changed 1 line.
[{Java2HtmlPlugin
{{{<html:javascript formName="personForm" cdata="false"
dynamicJavascript="true" staticJavascript="false"/>
<script type="text/javascript"
src="<html:rewrite page="/scripts/validator.jsp"/>"></script>}}}
At line 377 changed 2 lines.
<html:hidden property="id"/>
}]
Now if you execute __ant db-load deploy__, start Tomcat and point your browser to [http://localhost:8080/appfuse/editPerson.html?id=1], you should see something like this:
At line 380 removed 4 lines.
You should change the ''action'' of the &lt;html:form&gt; 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:
At line 388 removed 1 line.
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 &lt;fmt:message&gt;) at the top of the personForm.jsp page.
At line 370 added 4 lines.
%%note __NOTE:__ Use the __deploy-web__ target if you've changed any files under the ''web'' directory. Otherwise, use __deploy__ which compiles and deploys.%%
Finally, to make this page more user friendly, you may want to add a message for your users at the top of the form, which can easily be done by adding text (using &lt;fmt:message&gt;) at the top of the personForm.jsp page.
At line 427 added 1 line.
<verifytext description="verify success message" text="${person.updated}"/>
At line 462 changed 2 lines.
<verifytext description="verify success message"
text="Information for &lt;strong&gt;Abbie Raible&lt;/strong&gt; has been added successfully."/>
<verifytext description="verify success message" text="${person.added}"/>
At line 460 added 1 line.
<prepareDialogResponse description="Confirm delete" dialogType="confirm" response="true"/>
At line 462 added 1 line.
<verifyNoDialogResponses/>
At line 478 changed 2 lines.
<verifytext description="verify success message"
text="Information for &lt;strong&gt;Matt Canoo&lt;/strong&gt; has been deleted successfully."/>
<verifytext description="verify success message" text="${person.deleted}"/>

Back to CreateActions, or to the Page History.