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/StrutsManualActionWebComponentSync

------------------------------------------------------------------------------
  
  == Component Configuration ==
  
- First let us define the Login Component in {{{struts-config.xml}}} file:
+ Defining configuration before creating a component seems backwards, but 
different configuration options affect component itself, so for the sake of 
this example let us first define the parameters composite page and the login 
component in {{{struts-config.xml}}} file. Do not forget to turn automatic 
validation off, otherwise an event handler will not be called if associated 
form bean failed validation. In Struts 1.4 event definitions are first-class 
elements of an action mapping:
  
- {{{
- <struts-config>
+ {{{<struts-config>
  
    <form-beans>
      <!-- Login form -->
@@ -46, +45 @@

  </struts-config>
  }}}
  
- Notice action mapping attributes and properties that are new for Struts 1.4:
+ Observe attributes and properties that are new for Struts 1.4:
  
-    * "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.
+    * "component" attribute contains the name of a component. It identifies an 
action as a component manager, it is processed differently than a regular 
action or behavioral action.
     * "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.
+    * "event" property allows to define request parameters as events, and 
corresponding method handlers.
+ 
+ In Struts 1.2.9 - 1.3.x Action class does not implement dispatching 
functionality, and action mapping does not allow to define events. It is 
recommended to use EventDispatchAction to handle incoming events, its events 
are configured through {{{parameter}}} attribute:
+ 
+ '''Struts 1.2.9, 1.3.x:'''
+ {{{<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 path = "/logincomponent"
+               type = "samples.login.LoginAction"
+               name = "loginform"
+               scope = "session"
+               validate  = "false"
+               parameter = 
"loginEvent=login,logoutEvent=logout,default=unspecified">
+           <forward name = "view" path = "/login-struts/loginComponent.jsp"/>
+       </action>
+ 
+   </action-mappings>
+ </struts-config>
+ }}}
+ 
+ Of course, Struts 1.2.9, 1.3.x do not support new "component", "view", "form" 
and "event" properties. Use regular {{{forward}}} element to define a component 
view. Use {{{name}}} attribute to define associated form bean.
  
  == Component Action ==
  
- 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.
+ With Struts 1.4 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 {
@@ -102, +133 @@

  
          // Always return null.
          return null;
+     }
+ }
+ }}}
+ 
+ In Struts 1.2.9 - 1.3.x Action class does not implement dispatching 
functionality, you need to extend a dispatching action. Use EventDispatchAction 
as the simplest and the most flexible. Another difference is that you need to 
specify an {{{ActionForward}}} object that points to a component view. You must 
do it in {{{unspecified}}} method or whatever method you selected as default in 
event definition.
+ 
+ Using EventDispatchAction to dispatch events gets you only halfway, because 
there code that automatically distinguishes the address of a composite page and 
then redirects to it is not present in older Struts versions. You need an 
add-on library that contains this code. Then you need to call it from 
{{{execute}}} method of your action. '''TODO'''
+ 
+ '''Struts 1.2.9, 1.3.x:'''
+ {{{
+ public class LoginAction extends EventDispatchAction {
+ 
+     public ActionForward execute (...) throws Exception {
+         ComponentUtils.componentReload(...); // TODO
+     }
+ 
+     public ActionForward login (...) throws Exception {
+         ...
+     }
+ 
+     public ActionForward logout (...) throws Exception {
+         ...
+     }
+ 
+     public ActionForward unspecified (ActionMapping mapping,
+                                       ActionForm form,
+                                       HttpServletRequest request,
+                                       HttpServletResponse response) throws 
Exception {
+         return "view";
      }
  }
  }}}
@@ -136, +196 @@

  }
  }}}
  
- == Login/Logout JSP page ==
+ A common misconception is that components must use session-scoped form beans. 
This is not exactly true, but you might want to save data between request 
somehow, because Struts uses redirection to reload the composite page. Whether 
you store the data in session-scoped form bean or in database or in disk file 
is your choice. Obviously, request-scoped data will be lost after redirect.
  
- 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.
+ == Login And Logout Views ==
+ 
+ The Login Component has two subviews, one for a non-logged-in user, another 
for a logged-in user. In this example views are defined in one JSP page. It is 
possible to define them in different JSP files, but in this case you will not 
be able to use {{{view}}} attribute of an action mapping, and you will have to 
explicitly forward to view locations in similar manner as Struts 1.3.x 
{{{unspecified}}} method does.
  
  {{{
  <%@ page contentType="text/xml;charset=UTF-8" language="java" %>
- 
- <%@ page import="java.util.ArrayList, org.apache.struts.Globals"%>
  <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"; %>
  <%@ taglib uri="http://struts.apache.org/tags-bean"; prefix="bean" %>
  <%@ taglib uri="http://struts.apache.org/tags-html"; prefix="html" %>
@@ -164, +224 @@

      </html:messages>
    </logic:messagesPresent><br/>
  
+   <html:form action="/loginintegrated.do">
-   <%-- "strutsCommand" CSS class is a hook for Ajax-mode handler, it is set
-        in runtime using Behaviour library. --%>
- 
-   <html:form method="get" styleClass="strutsCommand" 
action="/loginintegrated.do">
      <label for="username">Username:</label>
-     <input type="text" name="username" value="${loginform.username}" 
class="datavalue"/><br/>
+     <input type="text" name="username" value="${loginform.username}"/>
  
      <label for="password">Password:</label>
-     <input type="text" name="password" value="" class="datavalue"/><br/>
+     <input type="text" name="password" value="" class="datavalue"/>
  
-     <input type="submit" name="loginEvent" value="Log In" 
class="strutsCommand"/>
+     <input type="submit" name="loginEvent" value="Log In"/>
    </html:form>
-   <p><em>Username is "guest", password is "pass".</em></p>
  </c:if>
  
  <%-- "Logged In" subview --%>
@@ -184, +240 @@

  <c:if test='${not empty USER}'>
    <h3>User Information</h3>
  
+   <html:form action="/loginintegrated.do">
+     Current user: ${USER} <br/>
-   <html:form method="post" styleClass="strutsCommand" 
action="/loginintegrated.do">
-     <label>Current user:</label>
-     <div class="datavalue">${USER}</div><br/>
-     <input type="submit" name="logoutEvent" value="Log Out" 
class="strutsCommand"/><br/>
+     <input type="submit" name="logoutEvent" value="Log Out"/><br/>
    </html:form>
  </c:if>
  
@@ -196, +251 @@

  
  == 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:
+ 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:
  
- {{{
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
+ {{{<%@ page contentType="text/html;charset=UTF-8" language="java" %>
  <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"; %>
- <%@ taglib uri="http://struts.apache.org/tags-html"; prefix="html" %>
- <%@ taglib uri="http://struts.apache.org/tags-comp"; prefix="comp" %>
  
  <html>
    <body>
      <p>This paragraph is defined directly in the parent page
      and should precede the content of login control.</p>
  
-     <%-- The login component, notice that DIV has the same ID as
-          the component's name --%>
-     <div id="Login">
-       <c:import url="/loginintegrated.do" />
+     <c:import url="/loginintegrated.do" />
-     </div>
  
      <p>This paragraph is defined directly in the parent page
      and should follow the content of login control.</p>
    </body>
- </html>
+ </html>}}}
- }}}
  
  == 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!
+ This is pretty much it. 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 does 
it happen? The improved Action class as well as JSP tags work together behind 
the scenes 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. 
  
+ Next:  [:StrutsManualActionWebComponentAsync:Building dual-mode Struts web 
component]
+ 

Reply via email to