Excerpt | ||
---|---|---|
| ||
Struts Actions |
Panel | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
The Controller Classes
The controller classes are actions and forms. It's the action's job to take biz objects from the service and convert them (if necessary) for display on the screen, and take data from the jsp and convert it to biz objects to send to the service. An action should do only one thing, i.e. we aren't doing actions the "multiple method" way.
Forms should be request based unless they are carried across more than one page, e.g. as in a wizard. Most of the time, you should be able to stuff biz objects directly into a form (and not flatten them out; i.e. create fields in the form for each field in the biz object). Struts should be able to deal with populating and returning nested objects.
A form's job is data input. It should not be used for data output unless some of that data is used as input too (this does not mean dropdowns, etc). Output data should be stuffed into the request by using request.setAttribute. You can then access the data in the jsp using the c taglib. Any data that is required for more than one screen, e.g. dropdown data that doesn't change, etc, can be stored in the session.
For apps that use SAP, all your actions should be subclasses of SAPBaseAction. This provides automatic RFC error message handling (i.e. it takes all rfc messages and stores them into the struts actionmessages automatically). It will stop any time an rfc returns an error message. In the rare case you need to do something else (like continue other processing) when an rfc error message occurs, you can wrap a try catch on MessageRuntimeException around your service execute calls.
TBD - talk about how to go to different actions from the jsp using the hidden thingy
Spring Configuration
The spring config for actions should be done in action-servlet.xml.
This file should contain a bean entry for every action in your app and they should be singletons. There is normally a base action class that is injected with the service all your actions will call. You can use mock services by overriding this.
Your app can have any number of entry points. Each of the entry points would have an action that can just be configured in spring to use the class edu.mit.mortar.controller.action.GlobalEntryAction. However, they must be named XXXEntryAction (where XXX is some name you choose), otherwise the session restart mechanism will cause your app to loop infinitely.
For SAP apps, your base action should be the class edu.mit.mortar.controller.action.SAPBaseAction (which is usually the default in the skeleton).
Struts Configuration
The struts config should have some defaults setup for your app.
Your app can have multple entry points. Each of these should be like the EntryAction example provided.
For each action that accepts input from the user there should be a form attached to it, and a jsp/tile to go back to in case of errors should be specified as the input attribute (see SearchPeople for an example).
For actions that don't need input, they should not have a form.
Tiles Configuration
Tiles config comes preconfigured with some building blocks for your pages.
In Struts 1.2 projects, actions are defined as singletons which means that they should not have instance variables unless the instance variables are static variables whose values are meant to be shared across users.
For apps that use SAP, all your actions should be subclasses of SAPBaseAction which is, in turn, a subclass of IDDAction which is a subclass of Strut's Action. (org.apache.struts.action is the core of the struts framework, providing the "Controller" aspect of a MVC model. Action is one of the classes in this core code.)
If the action is an entry point (i.e., chained to /EntryAction or /XXXEntryAction which is associated with the class edu.mit.mortar.controller.action.GlobalEntryAction in the action-servlet.xml) the following steps automatically happen when someone launches your application via this entry point:
- The method edu.mit.mortar.controller.action.GlobalEntryAction.execute is called and a session is created and the following session attributes are set:
- GlobalKeys.SAP_SYSTEM_ID (e.g., SF2)
- GlobalKeys.WAS_SYSTEM_ID (web application server system id - is this null for OAS apps?)
- GlobalKeys.WAS_HOST (web application server host - is this null for OAS apps?)
- GlobalKeys.USER_HOME (gateway page?)
- Your action (which has been configured to chain after /EntryAction) is called which immediately calls the method IDDAction.execute which sets the following session attributes:
- GlobalKeys.CERT (user's certificate)
- GlobalKeys.USERNAME (e.g., Carolyn A Fuller)
- GlobalKeys.KERBID (e.g., fuller)
- At the end of IDDAction, SAPBaseAction.doProcess is called which opens a connection to SAP.
- At the end of SAPBaseAction, your action's method doAction is called within a MessageRuntimeException try catch.
- If your action's method doAction calls a SAP RFC, SAPServiceSupport.execute is called.
- If an error message is returned from the SAP RFC at this point, processing will stop and the user will either stay on the same page displaying the error message if an action input has been defined correctly in the struts-config or they will be sent to the GlobalKeys.FAIL jsp page with a MessageRuntimeException. In the rare case that you don't want to stop processing and display the error message you should wrap your service call in a try...catch statement intercepting any MessageRuntimeException messages.
BAPIExceptions will be sent to the GlobalKeys.FAIL jsp page. - The value associated with the ActionMapping findForward method (i.e., "SearchResultsPage") should exactly match the forward name associated with the action's path (i.e., /SearchPeople) in struts-config.
Your action can access the session attributes set in IDDAction or GlobalEntryAction with code similar to the following:
String kerbid = (String)request.getSession().getAttribute(GlobalKeys.KERBID));
This provides automatic RFC error message handling (i.e. it takes all rfc messages and stores them into the struts actionmessages automatically).
Notice that above, this action is setting a request attribute "searchResults" with the Collection, results, which is being returned by the service.
Below the business object, CumulativeReport, is being set as an attribute, cumulativeReport, in the request.
If your action is associated with an ActionForm, you can set the values of instance variables within this ActionForm. Below SafoForm is the ActionForm associated with this Action in the struts-config.xml configuration file.
Pages you create should extend sapweb.standard; see oasskeleton.enter_search_criteria for an example. You must specify a default pageAction that the page will go to.