Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Struts Wiki" for change 
notification.

The following page has been changed by MichaelJouravlev:
http://wiki.apache.org/struts/StrutsManualActionWebComponentAsync

------------------------------------------------------------------------------
  
  == Component Configuration ==
  
+ Same as for [:StrutsManualActionWebComponentSync:synchronous] version.
- First let us define the Login Component in {{{struts-config.xml}}} file:
- 
- {{{
- <struts-config>
- 
-   <form-beans>
-     <!-- Login form -->
-     <form-bean name = "loginform" type="samples.login.LoginForm"/>
-   </form-beans>
- 
-   <action-mappings>
- 
-       <!-- Composite page containing login component -->
-       <action path="/login-struts"
-               forward="/login-struts/index.jsp"/>
- 
-       <!-- Login component -->
-       <action component = "Login"
-               view = "/login-struts/loginComponent.jsp"
-               path = "/logincomponent"
-               type = "samples.login.LoginAction"
-               form = "loginform"
-               scope = "session"
-               validate  = "false">
-           <event name="loginEvent" handler="login"/>
-           <event name="logoutEvent" handler="logout"/>
-       </action>
- 
-   </action-mappings>
- </struts-config>
- }}}
- 
- Notice action mapping attributes and properties that are new for Struts 1.4:
- 
-    * "component" attribute contains the name of a component. This name is 
used by <comp:component> tag that generates DIV element around component 
markup. The ID of this DIV is assigned to the component name. When application 
returns updated markup, Javascript helper matches ID of returned markup with ID 
of enclosing element in composite page. Another role of component name is to 
identify an action as a component manager, it is processed differently than a 
regular action or behavioral action.
-    * "component" attribute identifies an action as a component manager, such 
actions are processed differently by Action class. This name is also used in 
generated HTML for in-place update in Ajax mode.
-    * "view" attribute identifies a default view for a component. Must be a 
JSP page. Often consists from several subviews, in our case the Login Component 
has two subviews "Not Logged In" and "Logged In", they will be defined in JSP 
file.
-    * "form" is just another name for "name" property
-    * "event" property allows to define request parameters as events, and 
corresponding method handlers. This is made possible by supporting dispatching 
functionality directly in Action class.
  
  == Component Action ==
  
+ Same as for [:StrutsManualActionWebComponentSync:synchronous] version. Event 
handlers should always return null, they cannot return an {{{ActionForward}}} 
object. It is not possible to forward or redirect to another page if request is 
sent in asynchronous mode.
- The action class is deceptively simple. It handles only two events, the 
corresponding handlers are called automatically by Action class. The location 
of component's view is defined in the action mapping, so render method is not 
needed. On the other hand, most non-trivial components need to process data 
before rendering themselves or to exchange data with other components. For 
these cases you can use render" method. Its default implementation does nothing.
- 
- {{{
- public class LoginAction extends Action {
- 
-     public ActionForward login (ActionMapping mapping,
-                                 ActionForm form,
-                                 HttpServletRequest request,
-                                 HttpServletResponse response) throws 
Exception {
- 
-         HttpSession session = request.getSession();
-         LoginForm inputForm = (LoginForm) form;
- 
-         // Log out current user first
-         request.getSession().removeAttribute("USER");
- 
-         // Validation is turned off in struts-config.xml,
-         // so explicitly validate user input;
-         ActionMessages errors = inputForm.validate(mapping, request);
- 
-         if (errors != null) {
-             saveErrors(session, errors);
-         } else {
-             // Use this session attribute to hold user's name
-             session.setAttribute("USER", inputForm.getUsername());
-         }
- 
-         // Always return null.
-         return null;
-     }
- 
-     public ActionForward logout (ActionMapping mapping,
-                                  ActionForm form,
-                                  HttpServletRequest request,
-                                  HttpServletResponse response) throws 
Exception {
- 
-         LoginForm inputForm = (LoginForm) form;
- 
-         // Clean name and password in the input/output form bean
-         inputForm.setUsername(null);
-         inputForm.setPassword(null);
- 
-         // Remove dialog name from session, effectively logging out
-         request.getSession().removeAttribute("USER");
- 
-         // Always return null.
-         return null;
-     }
- }
- }}}
  
  == Component Form Bean ==
  
+ Same as for [:StrutsManualActionWebComponentSync:synchronous] version. 
- Nothing exciting here, just a session-scoped form to hold user name and to 
validate credentials:
- 
- {{{
- public class LoginForm extends ActionForm {
- 
-     private String username;
-     public String getUsername() {return username;}
-     public void setUsername(String username) {this.username = username;}
- 
-     private String password;
-     public String getPassword() {return password;}
-     public void setPassword(String password) {this.password = password;}
- 
-     // Generate the error messages in the same manner as usual,
-     // but do not forget to turn "validate" property of the action mapping 
off.
-     public ActionErrors validate(ActionMapping mapping, HttpServletRequest 
request) {
-         if (!"guest".equalsIgnoreCase(username) ||
-             !"pass".equalsIgnoreCase(password)) {
-             ActionErrors errors = new ActionErrors();
-             errors.add("ERROR", new ActionMessage("login.badpassword"));
-             return errors;
-         } else {
-             return null;
-         }
-     }
- }
- }}}
  
  == Login/Logout JSP page ==
  
- The Login/Logout component has two subviews, both defined in one JSP page. 
Notice that content type is set to "text/xml", this is important for Ajax mode.
+ The differences from [:StrutsManualActionWebComponentSync:synchronous] 
version are:
+ 
+  * content type must be set to "text/xml"
+  * component markup must be valid XHTML
+  * Content of JSP file must be wrapped into <comp:component> element
+  * <html:form> and <html:input> elements must have {{{styleClass}}} attribute 
set to "strutsCommand", this enables runtime binding of Ajax functionality to 
these elements.
  
  {{{
  <%@ page contentType="text/xml;charset=UTF-8" language="java" %>
@@ -203, +95 @@

  
  == Composite Page ==
  
- Now we need to include the Login Component into a larger page (composite 
page). This is done with JSTL c:import tag. Do not use jsp:include, it may not 
work on some containers:
+ The differences from [:StrutsManualActionWebComponentSync:synchronous] 
version are:
+ 
+  * <c:import> that includes a component, must be wrapped into a DIV or 
another element with ID equal to component name. This ensures that component 
markup is properly updated in-place.
  
  {{{
  <%@ page contentType="text/html;charset=UTF-8" language="java" %>
@@ -230, +124 @@

  
  == Done! ==
  
- This is pretty much it. Now run the application and navigate to composite 
page. The included component will evaluate user's state and will display a 
login form. Try to log in. The submitted credentials are sent directly to a 
component, if they are not correct, the composite page is redisplayed. How? 
Behind the scenes the improved Action class as well as JSP tags work together 
to distinguish the address of a composite page during first render. This 
address is saved automatically. Then after component finishes, it reloads the 
composite page using saved address. Now you can develop independent Struts 
components!
+ Now you can develop independent Struts components!
  

Reply via email to