[Struts Wiki] Update of "StrutsManualActionClasses" by MichaelJouravlev
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/StrutsManualActionClasses -- == Action Classes == + The goal of an Action class is to process a request and return an ActionForward object. Action class can either implement a ''stateless service'', or can manage a logical ''web resource''. !ActionForward object identifies where control should be transferred to provide the appropriate response, and usually designate either another Action (see [:ActionChaining:action chaining]) or a presentation page. Struts is agnostic to presentation technology, so response can be generated using JSP file, Tile definition, Velocity template, XSLT stylesheet or other source. - The goal of an Action class is to process a request and return an ActionForward object. !ActionForward object identifies where control should be transferred to provide the appropriate response. - - !ActionForward object usually designate another Action (see [:ActionChaining:action chaining]) or a presentation page. Struts is agnostic to presentation technology, so response can be generated from JSP file, Tile definition, Velocity template, XSLT stylesheet or other source. !ActionForward object represents a logical outcome of processing a request. By not defining a specific menu choice or a page URL it is possible to separate state of a resource from its visual representation. @@ -18, +16 @@ Consider the Action that performs a search. The author of this code should not care about how the search results are presented, his only job is to say "what happened" when the search took place. - Logically, there are three interesting outcomes we might want to describe: + Logically, there are three interesting outcomes: - * No results at all were found => outcome "none". + * No results were found => outcome "none". * Exactly one result was found => outcome "single". * More than one result was found => outcome "multiple". @@ -29, +27 @@ * If there's exactly one response, go to the details page to display the corresponding data. * If there's more than one response, go to the list page (as per the previous behavior). - Note that the code of the search action is not affected by this decision. In Struts the outcomes returned by an action are much more stable than the target locations. On contrary, in ASP.NET the outcome is the page that was requested. + Note that the code of the search action is not affected by this decision. In Struts the outcomes returned by an action are much more stable than the presentation locations. On contrary, in ASP.NET the outcome is simply the page that was requested. == Action As Service == - In its simplest form Action class handles all incoming requests with one callback method, {{{execute()}}}. Two overloaded versions of this method are available. Choosing one or another depends on your servlet environment. A non-HTTP execute() method has been provided for applications that are not specifically geared towards the HTTP protocol, but most projects will only use the HTTP version since the majority of teams using the framework are focused on building web applications: + In its simplest form Action class handles all incoming requests with one callback method, {{{execute()}}}. Two overloaded versions of this method are available. Choosing one or another depends on your servlet environment: {{{public ActionForward execute(ActionMapping mapping, + ActionForm form, + ServletRequest request, + ServletResponse response) + throws Exception; + + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception;}}} + Since the majority of teams using the framework are focused on building web applications, most projects will only use the "!HttpServletRequest" version. A non-HTTP execute() method has been provided for applications that are not specifically geared towards the HTTP protocol. == Action And Setup/Submit Pattern == - A request/response sequence of an interactive web application has two phases. On render phase (or output phase) browser requests a web resource to render itself. On input phase (or submit phase) browser sends input data to a web resource, usually by submitting an HTML form. These two phases are closely related to GET and POST methods of HTTP request. + A request/response sequence of an interactive web application is typically composed out of two phases. - HTTP specification recommends to use POST fo
svn commit: r417452 - /struts/action2/trunk/core/src/main/java/org/apache/struts/action2/components/Component.java
Author: tmjee Date: Tue Jun 27 06:27:15 2006 New Revision: 417452 URL: http://svn.apache.org/viewvc?rev=417452&view=rev Log: WW-1340 - added more javadoc to some of the methods Modified: struts/action2/trunk/core/src/main/java/org/apache/struts/action2/components/Component.java Modified: struts/action2/trunk/core/src/main/java/org/apache/struts/action2/components/Component.java URL: http://svn.apache.org/viewvc/struts/action2/trunk/core/src/main/java/org/apache/struts/action2/components/Component.java?rev=417452&r1=417451&r2=417452&view=diff == --- struts/action2/trunk/core/src/main/java/org/apache/struts/action2/components/Component.java (original) +++ struts/action2/trunk/core/src/main/java/org/apache/struts/action2/components/Component.java Tue Jun 27 06:27:15 2006 @@ -228,6 +228,9 @@ /** * Finds a value from the OGNL stack based on the given expression. + * Will always evaluate expr against stack except when expr + * is null. If altsyntax (%{...}) is applied, simply strip it off. + * * @param expr the expression. Returns null if expr is null. * @return the value, null if not found. */ @@ -260,8 +263,10 @@ /** * Evaluates the OGNL stack to find an Object value. * - * If the given expression is null a error is logged and a RuntimeException is thrown - * constructed with a messaged based on the given field and errorMsg paramter. + * Function just like findValue(String) except that if the + * given expression is null a error is logged and + * a RuntimeException is thrown constructed with a + * messaged based on the given field and errorMsg paramter. * * @param expr OGNL expression. * @param field field name used when throwing RuntimeException. @@ -290,7 +295,10 @@ } /** - * Evaluates the OGNL stack to find an Object of the given type. + * Evaluates the OGNL stack to find an Object of the given type. Will evaluate + * expr the portion wrapped with altSyntax (%{...}) + * against stack when altSyntax is on, else the whole expr + * is evaluated against the stack. * * This method only supports the altSyntax. So this should be set to true. * @param expr OGNL expression.
[Struts Wiki] Update of "StrutsWidgets" by MichaelJouravlev
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/StrutsWidgets -- + == HTML Link == + + Use tag to create HTML A element. + + To specify more than one query parameters you need to create a Map, where map key corresponds to request parameter key, and map value corresponds to request parameter value. + + You can specify parameter map with scriptlet like this: + + {{{<% + HashMap params = new HashMap(); + params.put("param1", param1Value); + params.put("param2","param2Value"); + pageContext.setAttribute("linkParams", params); + %> + Click Me}}} + + Instead of using Struts tag you can try JSTL to build link's URL: + + {{{ + + + }}} + == Dropdown box == Use tag to create HTML SELECT element that can be rendered either as dropdown box or a listbox. To create a dropdown box set ''size'' less than 2 or do not specify ''size'' at all. @@ -147, +170 @@ == References == - For more elaborate explanation see [http://javaboutique.internet.com/tutorials/strutsform/index.html Advanced Forms Handling in Struts 1.1] + [http://javaboutique.internet.com/tutorials/strutsform/index.html Advanced Forms Handling in Struts 1.1] + [http://www.jguru.com/faq/view.jsp?EID=877089 jGuru Q&A] +
[Struts Wiki] Update of "StrutsManualActionClasses" by MichaelJouravlev
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/StrutsManualActionClasses -- == Action Classes == - The goal of an Action class is to process a request and return an ActionForward object. Action class can either implement a ''stateless service'', or can manage a logical ''web resource''. !ActionForward object identifies where control should be transferred to provide the appropriate response, and usually designate either another Action (see [:ActionChaining:action chaining]) or a presentation page. Struts is agnostic to presentation technology, so response can be generated using JSP file, Tile definition, Velocity template, XSLT stylesheet or other source. + The goal of an Action class is to process a request and return an ActionForward object. Action class can either implement a ''stateless service'', or can manage a logical ''web resource''. + + !ActionForward object identifies where control should be transferred to provide the appropriate response, and usually designates either another Action (see [:ActionChaining:action chaining]) or a presentation page. Struts is agnostic to presentation technology, so response can be generated using JSP file, Tile definition, Velocity template, XSLT stylesheet or using other means. !ActionForward object represents a logical outcome of processing a request. By not defining a specific menu choice or a page URL it is possible to separate state of a resource from its visual representation. - The following picture illustrates the difference between Struts and ASP.NET using a simple "render page" use case. In ASP.NET the request means "Display a page", in Struts request means "Display a view that corresponds to current status of an Action". + The following picture illustrates the difference between Struts and ASP.NET using a simple "render page" use case. In Struts this means something like "Process request and transfer control to appropriate location, like a JSP page that corresponds to current status of the Action". In ASP.NET this simply means "Display that page". inline:basic_action_asp.gif '''Example''' - Consider the Action that performs a search. The author of this code should not care about how the search results are presented, his only job is to say "what happened" when the search took place. + Consider the Action that performs a search. The author of this code should not bother about specifics of presentation of the search results. His only job is to say "what happened" after the search took place. Logically, there are three interesting outcomes: * No results were found => outcome "none". @@ -31, +33 @@ == Action As Service == - In its simplest form Action class handles all incoming requests with one callback method, {{{execute()}}}. Two overloaded versions of this method are available. Choosing one or another depends on your servlet environment: + Base Action class handles all incoming requests with one callback method, {{{execute()}}}. Two overloaded versions of this method are available. Choosing one or another depends on your servlet environment: {{{public ActionForward execute(ActionMapping mapping, ActionForm form, @@ -54, +56 @@ * On ''render phase'' (''output phase'', ''render response phase'') the browser requests a web resource to render itself. * On ''input phase'' (''submit phase'', ''event phase'', ''apply request values phase'') the browser sends input data to a web resource, usually by submitting an HTML form. - These two phases correspond closely to GET and POST methods of HTTP request. HTTP specification recommends to use POST for non-idempotent requests, and to use GET for requests that can be repeated several times with the same outcome. In simpler terms, POST requests should be generally used to modify application state, while GET requests should be used to render a view. + In Struts a web resource is represented with Action or Action/!ActionForm combination. + These two phases correspond closely to HTTP GET and POST methods. HTTP specification recommends to use POST method for non-idempotent requests, like those that modify application state. GET method should be used for requests that can be safely repeated several times, like rendering a web page. - In Struts a logical web resource is represented with Action or Action/!ActionForm combination, and two-phase request/response approach is traditionally implemented with setup/submit pattern: - * ''setup action'' (''pre-action'', ''output action'', ''render action'') prepares output data before displaying; - * ''submit action'' (''post-action'', ''input action'', ''accept action'', ''event action'') accepts and handles user input.
[Struts Wiki] Update of "StrutsManualActionClasses" by MichaelJouravlev
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/StrutsManualActionClasses -- == Improving Setup/Submit Pattern == - * Use !ActionForm object to store both input and output data. Use the same !ActionForm object in both setup and submit actions. Declaratively (via {{{struts-config.xml}}}) associate the action form with submit action only, do not associate the action form with setup action. + Use !ActionForm object to store both input and output data. Use the same !ActionForm object in both setup and submit actions. Declaratively (via {{{struts-config.xml}}}) associate the action form with submit action only, do not associate the action form with setup action. + - * On setup phase, prepare the action form with output data and forward to a view. When a user submits HTML form, Struts will populate the action form that is associated with submit action. This is the same form that was used to render a page. + On setup phase, prepare the action form with output data and forward to a view. When a user submits HTML form, Struts will populate the action form that is associated with submit action. This is the same form that was used to render a page. + - * If input data is not valid, do not redisplay the page from submit action. Instead, update application state if needed, generate error messages, and forward control to setup action. It is the job of setup action to prepare and display views; the job of submit action is to handle the input and to update application state. + If input data is not valid, do not redisplay the page from submit action. Instead, update application state if needed, generate error messages, and forward control to setup action. It is the job of setup action to prepare and display views; the job of submit action is to handle the input and to update application state. + - * If action form was associated with setup action, it would be repopulated by Struts. Remember, that action form has not been associated with setup action, so it will not be repopulated when control is forwarded to setup action from submit action. Setup action will render the page along with error messages that have been generated by submit action. + If action form was associated with setup action, it would be repopulated by Struts. Remember, that action form has not been associated with setup action, so it will not be repopulated when control is forwarded to setup action from submit action. Setup action will render the page along with error messages that have been generated by submit action. + - * Instead of forwarding to success '''page''', forward to '''setup action''' of success web resource. + Instead of forwarding to success '''page''', forward to '''setup action''' of success web resource. The above steps will allow to cleanly separate concerns between actions, as well as to keep input/output data in one place. + + inline:setup_submit_improved.gif == Action As Event Dispatcher ==
svn commit: r417663 - in /struts/shale/trunk/shale-clay/src: main/java/org/apache/shale/clay/component/ main/java/org/apache/shale/clay/component/chain/ test/java/org/apache/shale/clay/config/
Author: gvanmatre Date: Tue Jun 27 21:04:20 2006 New Revision: 417663 URL: http://svn.apache.org/viewvc?rev=417663&view=rev Log: Fix for issue SHALE-201 reported by Ryan Wynn. Modified: struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/Clay.java struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AbstractCommand.java struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/CreateComponentCommand.java struts/shale/trunk/shale-clay/src/test/java/org/apache/shale/clay/config/SymbolsTestCase.java Modified: struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/Clay.java URL: http://svn.apache.org/viewvc/struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/Clay.java?rev=417663&r1=417662&r2=417663&view=diff == --- struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/Clay.java (original) +++ struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/Clay.java Tue Jun 27 21:04:20 2006 @@ -302,6 +302,8 @@ Map symbolTable = new TreeMap(); symbolTable.putAll(getSymbols()); clayContext.setSymbols(symbolTable); +//evaluate nested symbols +AbstractCommand.realizeSymbols(clayContext); //resolve the literal "@managed-bean-name" String expr = AbstractCommand.replaceMnemonic(clayContext, getShapeValidator()); @@ -338,6 +340,9 @@ symbolTable.putAll(getDisplayElementRoot().getSymbols()); symbolTable.putAll(getSymbols()); clayContext.setSymbols(symbolTable); + +//evaluate nested symbols +AbstractCommand.realizeSymbols(clayContext); clayContext.setRootElement(getDisplayElementRoot()); clayContext.setParent(this); Modified: struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AbstractCommand.java URL: http://svn.apache.org/viewvc/struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AbstractCommand.java?rev=417663&r1=417662&r2=417663&view=diff == --- struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AbstractCommand.java (original) +++ struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AbstractCommand.java Tue Jun 27 21:04:20 2006 @@ -19,8 +19,13 @@ package org.apache.shale.clay.component.chain; import java.net.URL; +import java.util.ArrayList; import java.util.Iterator; +import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; import org.apache.commons.chain.Catalog; import org.apache.commons.chain.CatalogFactory; @@ -87,6 +92,150 @@ public static String replaceMnemonic(ClayContext context) { return replaceMnemonic(context, context.getAttribute().getValue()); } + +/** + * Evaluates nested symbols. These are symbols that have references to other + * symbols as their values. The nested symbols evaluation is sensitive to dependencies. + * The current scoped symbol table is found in the [EMAIL PROTECTED] ClayContext}. + */ +public static void realizeSymbols(ClayContext context) { +Map symbols = context.getSymbols(); +if (symbols == null || symbols.isEmpty()) +return; + +Iterator si = symbols.entrySet().iterator(); + +Map dependenciesMap = new TreeMap(); +TreeSet allNestedSymbols = new TreeSet(); + +while (si.hasNext()) { +Map.Entry e = (Map.Entry) si.next(); +SymbolBean symbol = (SymbolBean) e.getValue(); +if (symbol.getValue() != null) { +List symbolDependencies = findSymbols(context, symbol.getValue()); +if (!symbolDependencies.isEmpty()) { +dependenciesMap.put(symbol.getName(), symbolDependencies); +allNestedSymbols.addAll(symbolDependencies); +allNestedSymbols.add(symbol.getName()); +} +} +} + +List allNestedSymbolsOrdered = getOrderedByDependencies(allNestedSymbols, dependenciesMap); +for (int i = 0; i < allNestedSymbolsOrdered.size(); i++) { +String symbolName = (String) allNestedSymbolsOrdered.get(i); +SymbolBean sourceSymbol = (SymbolBean) symbols.get(symbolName); +if (sourceSymbol != null && sourceSymbol.getValue() != null) { +String value = replaceMnemonic(context, sourceSymbol.getValue()); +SymbolBean targetSymbol = new SymbolBean(); +targetSymbol.setDescription(sourceSymbol.getDesc
svn commit: r417670 - in /struts/shale/trunk/shale-tiger/src: main/java/org/apache/shale/tiger/faces/LifecycleListener.java main/java/org/apache/shale/tiger/managed/config/ManagedPropertyConfig.java t
Author: craigmcc Date: Tue Jun 27 22:07:41 2006 New Revision: 417670 URL: http://svn.apache.org/viewvc?rev=417670&view=rev Log: Fix botched support for @Property ... need to recognize the default value ("") for the name attribute, as well as null. Modified: struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/faces/LifecycleListener.java struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/managed/config/ManagedPropertyConfig.java struts/shale/trunk/shale-tiger/src/test/java/org/apache/shale/tiger/config/TestBean.java Modified: struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/faces/LifecycleListener.java URL: http://svn.apache.org/viewvc/struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/faces/LifecycleListener.java?rev=417670&r1=417669&r2=417670&view=diff == --- struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/faces/LifecycleListener.java (original) +++ struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/faces/LifecycleListener.java Tue Jun 27 22:07:41 2006 @@ -598,16 +598,19 @@ default: break; } -// FIXME - should we look for inherited fields with @Value too? +// FIXME - should we look for inherited fields with @Property/@Value too? for (Field field : clazz.getDeclaredFields()) { if (log().isTraceEnabled()) { log().trace(" Scanning field '" + field.getName() + "'"); } Property property = (Property) field.getAnnotation(Property.class); if (property != null) { +if (log().isDebugEnabled()) { +log().debug(" Field '" + field.getName() + "' has a @Property annotation"); +} ManagedPropertyConfig mpc = new ManagedPropertyConfig(); String name = property.name(); -if (name == null) { +if ((name == null) || "".equals(name)) { name = field.getName(); } mpc.setName(name); @@ -618,17 +621,17 @@ } // Support deprecated @Value annotation as well Value value = (Value) field.getAnnotation(Value.class); -if (value == null) { +if (value != null) { +if (log().isDebugEnabled()) { +log().debug(" Field '" + field.getName() + "' has a @Value annotation"); +} +ManagedPropertyConfig mpc = new ManagedPropertyConfig(); +mpc.setName(field.getName()); +mpc.setType(field.getType().getName()); // FIXME - primitives, arrays, etc. +mpc.setValue(value.value()); +mbc.addProperty(mpc); continue; } -if (log().isDebugEnabled()) { -log().debug(" Field '" + field.getName() + "' has a @Value annotation"); -} -ManagedPropertyConfig mpc = new ManagedPropertyConfig(); -mpc.setName(field.getName()); -mpc.setType(field.getType().getName()); // FIXME - primitives, arrays, etc. -mpc.setValue(value.value()); -mbc.addProperty(mpc); } config.addManagedBean(mbc); } Modified: struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/managed/config/ManagedPropertyConfig.java URL: http://svn.apache.org/viewvc/struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/managed/config/ManagedPropertyConfig.java?rev=417670&r1=417669&r2=417670&view=diff == --- struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/managed/config/ManagedPropertyConfig.java (original) +++ struts/shale/trunk/shale-tiger/src/main/java/org/apache/shale/tiger/managed/config/ManagedPropertyConfig.java Tue Jun 27 22:07:41 2006 @@ -178,4 +178,20 @@ this.mapEntries = mapEntries; } + +/** + * Pretty printing toString() method. + */ +public String toString() { + +StringBuffer sb = new StringBuffer("ManagedPropertyConfig"); +sb.append("[name=" + getName()); +sb.append(",type=" + getType()); +sb.append(",value=" + getValue()); +sb.append(",nullValue=" + isNullValue()); +return sb.toString(); + +} + + } Modified: struts/shale/trunk/shale-tiger/src/test/java/org/apache/shale/tiger/config/TestBean.java URL: http://svn.apache.org/viewvc/struts/shale/trunk/shale-tiger/src/test/java/org/apache/shale/tiger/config/TestBean.java?rev=417670&r1=417669&r2=417670&view=diff ==
svn commit: r417671 - /struts/sandbox/trunk/archetypes/shale-blank/
Author: wsmoak Date: Tue Jun 27 22:15:43 2006 New Revision: 417671 URL: http://svn.apache.org/viewvc?rev=417671&view=rev Log: Bring back the shale-blank archetype for comparison with the multi-module shale-starter archetype. Added: struts/sandbox/trunk/archetypes/shale-blank/ - copied from r415248, struts/sandbox/trunk/archetypes/shale-blank/
[Struts Wiki] Update of "StrutsManualActionClasses" by MichaelJouravlev
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/StrutsManualActionClasses -- == Action Classes == - The goal of an Action class is to process a request and return an ActionForward object. Action class can either implement a ''stateless service'', or can manage a logical ''web resource''. + The goal of an Action class is to process a request and return an ActionForward object. Action class can either implement a ''stateless service'' like "search", or can manage a logical ''web resource'' like "Customer". - !ActionForward object identifies where control should be transferred to provide the appropriate response, and usually designates either another Action (see [:ActionChaining:action chaining]) or a presentation page. Struts is agnostic to presentation technology, so response can be generated using JSP file, Tile definition, Velocity template, XSLT stylesheet or using other means. + !ActionForward object identifies where control should be transferred to provide the appropriate response, and usually designates either another Action (see [:ActionChaining:action chaining]) or a presentation page. Struts is agnostic to presentation technology, so response can be generated using JSP file, Tile definition, Velocity template, XSLT stylesheet or other rendering engine. !ActionForward object represents a logical outcome of processing a request. By not defining a specific menu choice or a page URL it is possible to separate state of a resource from its visual representation. - The following picture illustrates the difference between Struts and ASP.NET using a simple "render page" use case. In Struts this means something like "Process request and transfer control to appropriate location, like a JSP page that corresponds to current status of the Action". In ASP.NET this simply means "Display that page". + The following picture illustrates a simple "render page" use case implemented with Struts and ASP.NET. In Struts the requests means something like "Process request data and transfer control to a JSP page that corresponds to result of the processing". In ASP.NET the request simply means "Display the page". inline:basic_action_asp.gif @@ -31, +31 @@ Note that the code of the search action is not affected by this decision. In Struts the outcomes returned by an action are much more stable than the presentation locations. On contrary, in ASP.NET the outcome is simply the page that was requested. - == Action As Service == - - Base Action class handles all incoming requests with one callback method, {{{execute()}}}. Two overloaded versions of this method are available. Choosing one or another depends on your servlet environment: + Action class handles all incoming requests with one callback method, {{{execute()}}}. Two overloaded versions of this method are available. Choosing one or another depends on your servlet environment: {{{public ActionForward execute(ActionMapping mapping, ActionForm form, @@ -49, +47 @@ Since the majority of teams using the framework are focused on building web applications, most projects will only use the "!HttpServletRequest" version. A non-HTTP execute() method has been provided for applications that are not specifically geared towards the HTTP protocol. + == Action And Web Forms == + + The most common use case in an interactive web application is submitting of HTML form. A user expects that if input data is not valid, the form would be redisplayed, keeping information entered by the user, and displaying relevant error messages. + + This use case is so common and so important that it gave name to a certain web framework developed by a company from Redmond. This company spent significant amount of time making sure that developing for Web is as easy as designing a desktop application. How does Struts fare? + + First, a brief recap of HTTP specification. HTTP defines eight request methods, two of these directly relate to handling of web forms. Below are relevant quotes from RFC 2616, abridged and slightly edited for readability: + + '''GET:''' The GET method means retrieve whatever information is identified by the Request-URI. GET method SHOULD NOT have the significance of taking an action other than retrieval [and] ought to be considered "safe". + + '''POST:''' The POST method is used to request the server to accept the entity enclosed in the request. POST is designed to allow a uniform method to ... post a message to a bulletin board, newsgroup, mailing list ... [or] to provide a block of data, such as the result of submitting a form, to a data-handling process. + + The HTTP specification defines a fundamental concept of web interaction in
[Struts Wiki] Update of "StrutsManualActionClasses" by MichaelJouravlev
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/StrutsManualActionClasses -- * An attempt to refresh a page after it has been redisplayed causes double submit. * Success page where submit action forwards to, often corresponds to a logically different resource. It is impossible to tell which logical resource is managed by which Action classes. The M:M relationship between actions and pages leads to a spaghetti code both in Java code as well as in {{{struts-config.xml}}} file. + inline:icon_alert.gif This chapter discussed the improved Setup/Submit Pattern. To see the original Setup/Submit Pattern click here. + == Improving Setup/Submit Pattern == Use !ActionForm object to store both input and output data. Use the same !ActionForm object in both setup and submit actions. Declaratively (via {{{struts-config.xml}}}) associate the action form with submit action only, do not associate the action form with setup action.
[Struts Wiki] Update of "StrutsManualActionClasses" by MichaelJouravlev
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/StrutsManualActionClasses -- * ''submit action'' (''post-action'', ''input action'', ''accept action'', ''event action'') processes input data from web form and redisplays the web form if errors has been found. If input does not contain errors, submit action updates application state and forwards to a success page. One of the reasons of splitting this functionality into two actions is that Action class uses just one {{{execute()}}} method to handle all kinds of requests. (Servlet has separate {{{doGet()}}} and {{{doPost()}}} methods.) - - inline:setup_submit.gif A typical Setup Action will often implement the following logic in its {{{execute}}} method:
[Struts Wiki] Update of "StrutsManualActionClasses" by MichaelJouravlev
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/StrutsManualActionClasses -- One of the reasons of splitting this functionality into two actions is that Action class uses just one {{{execute()}}} method to handle all kinds of requests. (Servlet has separate {{{doGet()}}} and {{{doPost()}}} methods.) + inline:setup_submit_improved.gif + + inline:icon_alert.gif The above diagram shows the improved Setup/Submit Pattern. To see the original Setup/Submit Pattern click here (TODO). + A typical Setup Action will often implement the following logic in its {{{execute}}} method: * Make sure that a user is allowed to see the content of a web page that corresponds to the action. @@ -79, +83 @@ A typical Submit Action will often implement the following logic in its {{{execute}}} method: - * Validate the form bean properties as needed. If a problem is found, store the appropriate error message keys as a request (or session) attribute, and forward (or redirect) control to the input form so that the errors can be corrected. + * Validate the form bean properties as needed. If a problem is found, store the appropriate error message keys as a request (or session) attribute, and forward (or redirect) control to the setup action so that the errors can be corrected. * If input data is valid, perform the business task such as saving a row into a database. This can be done by logic code embedded within the Action class itself, but should generally be performed by calling an appropriate method of a business logic bean. * Update the server-side objects that will be used to create the next page of the user interface. These objects would typically be request scope or session scope beans, depending on how long you need to keep these items. - * Return an appropriate !ActionForward object that identifies the presentation page to be used to generate this response, based on the newly updated beans. Typically, you will acquire a reference to such an object by calling findForward on either the ActionMapping object you received (if you are using a logical name local to this mapping), or on the controller servlet itself (if you are using a logical name global to the application). + * Return an appropriate !ActionForward object that identifies the next web resource. The flip side of Struts flexibility is greater complexity of a most common request/response cycle comparing to similar ASP.NET request/response cycle: inline:asp_render_submit.gif - - Besides the sheer complexity, original Struts setup/submit pattern has other design and usability implications: - * Most developers program actions as simple services, not as part of a logical web resource. Thus one Action often deals with only one message, like {{{updateCustomer.do}}} handles "Update Customer" event, {{{deleteCustomer.do}}} handles "Delete Customer" event. - * Output data is often scattered in an uncontrolled manner throughout request and session scope. - * In case of error the data entry form is redisplayed by a submit action. This means that submit action duplicates setup functionality of setup action. - * This pattern often relies to automatic validation. The downside of this approach is that in case of error the submit action class is never get called and cannot affect the workflow. - * One page is represented with two different URLs in the browser. - * An attempt to refresh a page after it has been redisplayed causes double submit. - * Success page where submit action forwards to, often corresponds to a logically different resource. It is impossible to tell which logical resource is managed by which Action classes. The M:M relationship between actions and pages leads to a spaghetti code both in Java code as well as in {{{struts-config.xml}}} file. - - inline:icon_alert.gif This chapter discussed the improved Setup/Submit Pattern. To see the original Setup/Submit Pattern click here. - - == Improving Setup/Submit Pattern == - - Use !ActionForm object to store both input and output data. Use the same !ActionForm object in both setup and submit actions. Declaratively (via {{{struts-config.xml}}}) associate the action form with submit action only, do not associate the action form with setup action. - - On setup phase, prepare the action form with output data and forward to a view. When a user submits HTML form, Struts will populate the action form that is associated with submit action. This is the same form that was used to render a page. - - If input data is not valid, do not redisplay the page from submit action. Instead, update application state if needed, generate error messages, and forward control to setup action. It is the job of setup action to p