2

i have override validate method and added errors using addFieldError("test", "test print");

and in jsp used <s:fielderror />

but the errors are not displayed in input.jsp.

Also my jsp content type is <%@ page contentType="text/html; charset=UTF-8"%>

My struts.xml is like

            <action name="test" class="ListInfo">
                 <result>/input.jsp</result>
            </action>

    <action name="Proceed" class="Details">
    <interceptor-ref name="defaultStack"/>
            <interceptor-ref name="execAndWait">
                <param name="delay">100</param>
            </interceptor-ref>
           <result name="wait">Wait.jsp</result>
        <result name="success">/Summary.jsp</result>
        <result name="input" type="chain">test</result>
        <result name="failure" type="chain">test</result>
    </action>
saket
  • 694
  • 5
  • 10
  • 20
  • 1
    I don't recall if action errors are kept during default chaining. Chaining is almost always bad, btw. – Dave Newton Apr 05 '12 at 13:29
  • @DaveNewton: good point, i completely missed it :) – Umesh Awasthi Apr 05 '12 at 14:15
  • @saket Better approach instead of using chain, redirect to test action and use messageStore interceptor to preserve actionError's and fieldErrors. – MohanaRao SV Apr 05 '12 at 15:31
  • Field errors must be referenced by name... you are supplying a name in the field right? – Quaternion Apr 05 '12 at 19:30
  • Provided an answer using chain, message store only brings over the messages if the OP wants other computed values chain is still required (well... as required as redirect any ways). – Quaternion Apr 05 '12 at 20:17
  • @DaveNewton, Chaining, If it's a bad practice then why struts2 still supporting it. It should be obsolete, I guess. – MohanaRao SV Apr 06 '12 at 06:39
  • @MohanaRaoSV Backwards-compatibility for one thing, and as I stated, it is *almost* always a bad idea. This is an instance where it's almost certainly a bad idea because there's a different solution. – Dave Newton Apr 06 '12 at 12:49

2 Answers2

3

Turns out that errors (field and action are NOT maintained across a chain.

Following proves this (assumes struts2-conventions-plugin-VERSION):

Action foo always chains to action bar (so we only need a view for action bar)

Action foo

package com.quaternion.action;

import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.Result;

/** #1 SOMETHING WILL BE ADDED HERE TO FIX THE ISSUE**/

@Result(name="input", type="chain", location="bar")
public class Foo extends ActionSupport{
    private String name;

    @Override
    public void validate(){
        super.addActionError("Just an action error");
        super.addFieldError("name", "Name is all ways wrong... for no good reason.");
    }

    public String getName(){
        return name;
    }

    public void setName(String name){
        this.name = name;
    }
}

Action bar

package com.quaternion.action;

import com.opensymphony.xwork2.ActionSupport;

/** #2 SOMETHING WILL BE ADDED HERE TO FIX THE ISSUE**/

public class Bar extends ActionSupport{  
}

view for bar: /WEB-INF/content/bar.jsp

<%@taglib prefix="s" uri="/struts-tags"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <body>
        <h1>Action Bar</h1>
        <s:actionerror/>
        <s:fielderror name="name"/>
    </body>
</html>

Testing the above we see nothing show up in the errors.

To fix the issue we use the store interceptor: http://struts.apache.org/2.0.14/struts2-core/apidocs/org/apache/struts2/interceptor/MessageStoreInterceptor.html

In the first action (#1) we will need to add annotations and the imports to support them:

import org.apache.struts2.convention.annotation.InterceptorRef;
import org.apache.struts2.convention.annotation.InterceptorRefs;

@InterceptorRefs({
    @InterceptorRef(value = "store", params = {"operationMode","STORE"}),
    @InterceptorRef("defaultStack"),
})

In the second action (#2) we will need to add annotations and the imports to support them:

import org.apache.struts2.convention.annotation.InterceptorRef;
import org.apache.struts2.convention.annotation.InterceptorRefs;

@InterceptorRefs({
    @InterceptorRef(value = "store", params = {"operationMode","RETRIEVE"}),
    @InterceptorRef("defaultStack"),
})

And now it works.

Quaternion
  • 10,380
  • 6
  • 51
  • 102
  • HI i changed my struts.xml as follows ` RETRIEVE /input.jsp STORE /Summary.jsp test ` but it's redirecting properly but still not showing errors. – saket Apr 06 '12 at 08:29
  • in validate method `addFieldError("Description", "Error should be printed");` in jsp `` – saket Apr 06 '12 at 08:36
  • thanx it works.. I tried it with a simple example.. but it is not working when i include my header.jsp. can u provide any hint what may be going wrong.. – saket Apr 06 '12 at 08:58
  • 1
    The [chaining interceptor](http://struts.apache.org/2.x/docs/chaining-interceptor.html) *does* allow keeping field errors and action errors/messages as detailed in the docs. – Dave Newton Apr 06 '12 at 12:48
  • If the OP makes a habit of chaining... then the one size fits all approach to the chaining interceptor can introduce issues. There is a reason carrying over errors is not the general case, the validation of one action may not often have much to do with validation on the second... In that case still using store is more specific. From a user perspective it would be best if the two had congruent behaviour in this matter. – Quaternion Apr 06 '12 at 16:30
  • @DaveNewton Gah, things keep changing but in a good way... the most up to date link: http://struts.apache.org/2.3.1.2/docs/chaining-interceptor.html shows that the behaviour _is_ now congruent! – Quaternion Apr 23 '12 at 08:37
2

If you're going to use action chaining anyway (which IMO is almost never required, almost never a good idea, and almost always leads to unintended coupling between actions), use what the chaining interceptor already provides and avoid configuring something besides "chain".

As per the docs:

  • struts.xwork.chaining.copyErrors - set to true to copy Action Errors
  • struts.xwork.chaining.copyFieldErrors - set to true to copy Field Errors
  • struts.xwork.chaining.copyMessages - set to true to copy Action Messages
Dave Newton
  • 158,873
  • 26
  • 254
  • 302
  • I set struts.xwork.chaining.copyErrors to be true in my application, and then whenever I add some errors thru addActionError(), Struts2 would look for "input" instead of the result returned by the action method. Any idea? – user6332430 Jul 19 '16 at 20:55
  • 1
    @Will The default work flow interceptor, IIRC, will go to the `"input"` result if there are errors. So this appears to be working by design. (In fairness, I may not be remembering correctly.) – Dave Newton Jul 19 '16 at 21:33