Example 10-2 ListAccountsAction execute method public ActionForward execute ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response throws Except
Trang 1import itso.bank.exception.*;
import itso.bank.facade.*;
import itso.bank.model.*;
import java.util.*;
Replace the execute method with the contents in:
\sg246957\sampcode\dev-struts\initial\actions\ListAccountsAction.txt The code is shown in Figure 10-2
Example 10-2 ListAccountsAction execute method public ActionForward execute( ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception { ActionErrors errors = new ActionErrors();
ActionForward forward = new ActionForward();
// return value CustomerInfoForm customerInfoForm = (CustomerInfoForm) form;
try { // Get input parameter customerNumber and keep it on the HTTP session String customerNumber = customerInfoForm.getCustomerNumber();
HttpSession session = request.getSession();
if (customerNumber == null) customerNumber = (String) session.getAttribute("customerNumber"); else
session.setAttribute("customerNumber", customerNumber);
session.removeAttribute("accountNumber");
// Create the new banking façade, get Customer and Accounts Banking banking = new Banking();
Customer customer = banking.getCustomer(customerNumber);
Account[] accounts = banking.getAccounts(customerNumber);
// Populate the CustomerInfo Form Bean for display customerInfoForm.setCustomerName( customer.getFirstName()+"
"+customer.getLastName());
String[] accountNumbers = new String[accounts.length];
for (int i=0; i<accounts.length; i++) accountNumbers[i] = accounts[i].getId();
customerInfoForm.setAccountNumbers( accountNumbers );
// set first account number to check the first radio button // customerInfoForm.setAccountNumber( accountNumbers[0] );
// Store the bean in the correct scope
if ("request".equals(mapping.getScope())) request.setAttribute(mapping.getName(), customerInfoForm);
else session.setAttribute(mapping.getName(), customerInfoForm);
Trang 2} catch (CustomerDoesNotExistException e) {
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError("error.customerDoesNotExistException"));
} catch (Exception e) {
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError("error.genericException"));
}
if (!errors.empty()) {
saveErrors(request, errors);
forward = mapping.getInputForward();
} else {
forward = mapping.findForward("success");
}
// Finish with
return (forward);
}
This action class follows the normal sequence most action classes do:
It first creates ActionError and ActionForward objects to hold the keys for any errors that may occur and the forward that will be returned to Struts at the end of the method The forward determines the page to be displayed next
It then retrieves the form bean that Struts has populated before calling the execute method The form bean is populated with all properties that Struts could retrieve from the input form and has a getter/setter on the form bean
The action then performs similar business logic as the ListAccounts servlet from the RedBank application (that is, retrieve the accounts for this customer)
After the business logic is performed, the action stores the information necessary to display the resulting JSP in the form bean and then places this form bean into the request or session scope, depending on what was
configured in the Struts configuration file In our case we used the request scope for this
Should any exceptions occur (for example, the customer number entered does not exist) a new ActionError object is created with the key
corresponding to the error message, and this ActionError is added to the ActionErrors object An ActionErrors object can therefore hold multiple ActionError objects, each describing a specific error condition
Finally, the method checks if any errors were added to the ActionErrors object and, if so, saves the ActionErrors object to the request so the Struts
<html:errors> tag can find and display them It also determines the forward that control should be passed to In case of an error we return to the input
Trang 3page (we will soon define the input page for our actions) for correction and if successful we progress to the forward called success
If an action should return null as its forward, this tells Struts that the rendering
of the page has already been performed by the action itself and that no JSP needs to be displayed
Save the ListAccountsAction.java file and close the Java editor
Implement the other action classes
Implement the two action classes, AccountDetailsAction and PerformTransactionAction, using the same method Copy the Java code from the \sg246956\sampcode\dev-struts\initial\actions directory and paste into the corresponding action class you create
When you have implemented all the components on the Web diagram, there should be no errors in the Task view
Before we have a fully working application we need to add a few more forwards
We will do that using the Struts configuration file editor
Using the Struts configuration file editor
Application Developer provides an editor for the Struts configuration file,
\WEB-INF\struts-config.xml Using this editor you can add new form beans and actions and customize the their attributes You can also directly edit the XML source file should you prefer to do it by hand instead of using the wizards
We will use this editor to add a forward called cancel to the accountDetails and performTransaction actions This forward is used by the actions to determine where to go in case the user clicks Cancel
We also specify the input attribute for all our actions This attribute specifies which page should be displayed if the validate method of a form bean found errors Usually you want to display the input page where the user entered the data so they can correct their entry
Double-click the Web Content\WEB-INF\struts-config.xml file to open the configuration file editor
Note: The two commented lines (in italic) can be used to pre-select the
account number in the selection list This way we could make sure that an account number would always be selected We did not want to do this here, as
we wanted to show you how to use the validate method instead
Trang 4 The editor has tabs to navigate between the different Struts artifacts (actions, form beans, global forwards, data sources) it supports
Make sure the Actions tab is displayed and then select the /listAccounts
action In the Input field enter /index.jsp (Figure 10-30)
Figure 10-30 Specifying action input attribute
Select the accountDetails action and specify /listAccounts.do as the input attribute for this action We recreate the list of accounts if errors occur
Scroll down and click New to Specify forwards This opens the Create New Forward dialog as shown in Figure 10-31 Enter cancel as the name and /index.jsp as the path for this forward Then click OK to close this window
Note: The Redirect check box allows you to select if a redirect or forward call should be made A forward call keeps the same request with all
attributes it contains and just passes control over to the path specified A redirect call tells the browser to make a new HTTP request which creates a new request object (and you lose any attributes set in the original request)
A forward call does not change the URL in the browser’s address field, as it
is unaware that the server has passed control to another component With
a redirect call, however, the browser updates the URL in its address field to reflect the requested address
Trang 5Figure 10-31 Creating new Forward
Use the same method to specify /accountDetails.jsp as the input attribute for the performTransaction action and add a new forward called cancel with a path of /listAccounts.do
When done, press Ctrl-S to save the configuration file
Now click the XML Source tab on the editor to take a look at the Struts configuration file we have created during this session (Figure 10-32)
Note: You can redirect or forward also to other actions It does not
necessarily have to be a JSP The cancel forward can point to either /listAccounts.do (the action) or /listAccounts.jsp (the JSP)
Going to the JSP may require that the form bean is in the session instead
of the request
Trang 6<! Data Sources >
<data-sources>
</data-sources>
<! Form Beans >
<form-beans>
<form-bean name="customerInfoForm" type="itso.strutsweb.forms.CustomerInfoForm">
</form-bean>
<form-bean name="transactionForm" type="itso.strutsweb.forms.TransactionForm">
</form-bean>
</form-beans>
<! Global Exceptions >
<global-exceptions>
</global-exceptions>
<! Global Forwards >
<global-forwards>
</global-forwards>
<! Action Mappings >
<action-mappings>
<action name="customerInfoForm" path="/listAccounts" scope="request"
type="itso.strutsweb.actions.ListAccountsAction" input="/index.jsp">
<forward name="success" path="/listAccounts.jsp"></forward>
</action>
<action name="customerInfoForm" path="/accountDetails" scope="request"
type="itso.strutsweb.actions.AccountDetailsAction"
input="/listAccounts.do">
<forward name="success" path="/accountDetails.jsp"></forward>
<forward name="cancel" path="/index.jsp"></forward>
</action>
<action name="transactionForm" path="/performTransaction" scope="request"
type="itso.strutsweb.actions.PerformTransactionAction"
input="/accountDetails.jsp">
<forward name="withdraw" path="/accountDetails.jsp"></forward>
<forward name="transfer" path="/accountDetails.jsp"></forward>
<forward name="deposit" path="/accountDetails.jsp"></forward>
<forward name="listTransactions" path="/listTransactions.jsp"></forward>
<forward name="cancel" path="/listAccounts.do"></forward>
</action>
</action-mappings>
<! Message Resources >
<message-resources parameter="itso.strutsweb.resources.ApplicationResources"/>
</struts-config>
Trang 7As you can see, the Struts tools have defined our two form beans in the
<form-beans> section and our three actions in the <action-mappings> section Our JSPs, however, are not specified in the Struts configuration file, they are completely separate form the Struts framework (only the forwarding information
is kept in the configuration file) At the end of the file is the name of the application resources file where our texts and error messages are stored The Struts configuration editor does roundtrip editing, so if you edit something in the XML view it is reflected in the other views
The forwards we use are local to each action, meaning that only the action associated with the forward can look it up In the <global-forwards> section you can also specify global forwards that are available for all actions in the
application Normally you have a common error page to display any severe error messages that may have occurred in your application and that prevents it from continuing Pages like these are good targets for global forwards and so are any other commonly used forward Local forwards override global forwards
You can now close the configuration file editor
As we have now added a few more forwards we should update the Web diagram to show them as well If the Web diagram is not open, open it by double-clicking \Web Content\WEB-INF\strutsbank.gph In the Web diagram select the listAccounts action and Draw -> Draw Selected From its context menu Select “input” > /index.jsp as shown in Figure 10-33 and click OK
Figure 10-33 Selecting a forward to draw This draws a red line from the listAccounts action back to index.jsp, indicating the input page
For the accountDetails and performTransaction actions, draw both the input and cancel paths This draws a red line indicating the input page and a black line indicating a normal forward for each of these two actions
Select the lines and drag the small dot in the middle of the line to avoid the lines from crossing over other components in the Web diagram
Trang 8When finished, you should have the Web diagram as shown in Figure 10-34.
Figure 10-34 Completed Web diagram for Struts application
Save the Web diagram by pressing Ctrl-S
We are now ready to test our application using the built-in WebSphere Test Environment
Trang 9Testing the application
To run the application using Application Developer’s built-in test environment, select Run on Server from the context menu of the ItsoProGuideStrutsWeb project When launched, it should look similar to the RedBank application that it
is based on
Notes:
It is recommended that all requests for JSPs go through an action class so that you have control over the flow and can prepare the view beans (form beans) necessary for the JSP to display properly Struts provides simple forwarding actions that you can use to accomplish this However, your users can still bypass your actions and access the JSPs directly, which is not what you want One way of making sure that your users cannot access the JSPs directly is to place them under the WEB-INF directory which, according to the J2EE specifications, is not directly accessible A good place to put your JSPs (other than index.jsp) is \WEB-INF\jsp However, if you put them there, the Application Developer Struts tools do not seem to find them either, so you will not get the same support when developing your application You could, however, keep your JSPs in the root of the Web Content directory during development to get full support from Application Developer and then— when you are getting ready to package and ship your application—move them to a protected directory under WEB-INF If properly designed (and not links hard coded) it should just be a simple search and replace action in the Struts configuration file
In our example we do not perform any customization on the Struts action servlet (org.apache.struts.action.ActionServlet) If you have to do any initialization (for example initialize data sources) you would want to create your own action servlet, extending the ActionServlet class, and override the init and destroy methods You would then also modify the
\WEB-INF\web.xml file and replace the name of the Struts action servlet with the name of your action servlet class
When adding Struts 1.1 beta 2 support the JAR file jdbc2_0-stdext.jar is added to the Web Content\WEB-INF\lib directory This file contains classes from the javax.sql package and comes with Struts 1.1 However, these classes are also shipped with WebSphere Application Server If the Struts supplied classes are in the lib directory, they take precedence over the WebSphere classes We have seen problems with these classes and using WebSphere data sources If you experience any JDBC-related problems, try removing this file and see if it helps
Trang 10A sample run is shown in Figure 10-35.