Can I propagate struts2 ActionErrors between different action classes?
Asked Answered
H

10

13

If I have an action where the result is a redirectAction to another action in a different class, is it possible to get validation errors to display in the resulting action? E.g. in the following example, if a user executes actionA (which has no views associated with it), and there are errors, is there any way to display those errors in the actionB result (foo.jsp)? Or am I going about this in completely the wrong way?

<package name="a" extends="struts-default" namespace="/a">
    <action name="actionA" class="actionAClass">
        <result name="input" type="redirectAction">
            <param name="actionName">actionB</param>
            <param name="namespace">/b</param>
        </result>
        <result type="redirectAction">
            <param name="actionName">actionB</param>
            <param name="namespace">/b</param>
        </result>
    </action>
</package>
<package name="b" extends="struts-default" namespace="/b">
    <action name="actionB" class="actionBClass">
        <result>/foo.jsp</result>
    </action>
</package>
Hellenize answered 1/7, 2009 at 16:29 Comment(1)
Try using MessageStore Interceptor - struts.apache.org/release/2.3.x/docs/…Explain
I
4

There may be a way to do that, but I don't think it's a very good way to use struts. If actionA is failing validation, you most likely would want to either have a non-redirect input result for it that shows the errors, or perhaps a global error page that can show it.

I suppose you could store the action errors somewhere like the session in between the redirect, but you wouldn't really be using the framework how it was designed.

Inbreeding answered 9/7, 2009 at 3:54 Comment(0)
D
11

Struts2 by default has a store interceptor. It stores the actionMessages, actionErrors and fieldErrors in session in STORE mode and you can retrieve the same in the next redirect by using the same interceptor by using it in RETRIEVE mode. More details can be found here

Dame answered 1/5, 2012 at 19:37 Comment(0)
F
7

Basically you have to use predefined interceptors called store which takes operationMode: store and retrieve:

<package name="a" extends="struts-default" namespace="/a">
    <action name="actionA" class="actionAClass">
        <!-- Here you are storing the Error messages -->
        <interceptor-ref name="store">
            <param name="operationMode">STORE</param>
        </interceptor-ref>

        <!-- include your default stack in case you need to load other interceptors -->
        <interceptor-ref name="defaultStack" />

        <result name="input" type="redirectAction">
            <param name="actionName">actionB</param>
            <param name="namespace">/b</param>
        </result>
        <result type="redirectAction">
            <param name="actionName">actionB</param>
            <param name="namespace">/b</param>
        </result>
    </action>
</package>
<package name="b" extends="struts-default" namespace="/b">
    <action name="actionB" class="actionBClass">

        <interceptor-ref name="store">
            <param name="operationMode">RETRIEVE</param>
        </interceptor-ref>

        <!-- include your default stack in case you need to load other interceptors -->
        <interceptor-ref name="defaultStack" />

        <result>/foo.jsp</result>
    </action>
</package>
Fante answered 15/7, 2009 at 1:34 Comment(0)
P
6

I find a better solution to pass action errors and messages on actionRedirect result type. It is working for me.

<action name="action1" class="action.Action1" >
    <result>/abc.jsp</result>
    <result name="input" type="redirectAction">
    <param name="actionName">action2</param>
    <param name="param1">${param1}</param>
    <param name="param2">${param2}</param>
    <param name="actionErrors">${actionErrors}</param>
    </result>
    </action>
    <action name="action2" class="action.Action2" >
    <result>/def.jsp</result>
    <result name="input">/def.jsp</result>
     </action/>

This is it ..... Happy coding

Piecedyed answered 14/7, 2014 at 10:20 Comment(4)
<param name="actionErrors">${actionErrors}</param> this does all the magic.Piecedyed
Does this pass both the action errors and messages or do you need <param name="actionMessages">${actionMessages}</param> to pass a message?Kratzer
<param name="actionMessages">${actionMessages}</param> does pass the messages. Thanks!Kratzer
You should point out, that you will always end up in result "input" of action2 and the execute method of this action is not called...Penang
I
4

There may be a way to do that, but I don't think it's a very good way to use struts. If actionA is failing validation, you most likely would want to either have a non-redirect input result for it that shows the errors, or perhaps a global error page that can show it.

I suppose you could store the action errors somewhere like the session in between the redirect, but you wouldn't really be using the framework how it was designed.

Inbreeding answered 9/7, 2009 at 3:54 Comment(0)
H
3

Use ActionContext.getContext().getSession().put(key, value) in the first action and retrieve it using ActionContext.getContext().getSession().get(key) in the redirectedAction and addActionErrors to the main Action

Hatching answered 12/12, 2012 at 5:38 Comment(2)
I guess MessageStoreInterceptor would be a much better way.Explain
MessageStoreInterceptor - struts.apache.org/release/2.3.x/docs/…Explain
T
3

Result type chain will copy messages/errors to resulting action if you do following in struts.xml or struts.properties file -

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

Example (struts.xml)-

<constant name="struts.xwork.chaining.copyErrors" value="true"/>
Tizzy answered 24/8, 2014 at 6:44 Comment(0)
H
2

The store interceptor (MessageStoreInterceptor) can be used to store and retrieve actionErrors, actionMessages and fieldErrors.

You can change the operation of store interceptor on the fly by passing the operationMode parameter to action

http://localhost/sample.action?operationMode=STORE

You can set the store interceptor in STORE mode in your default stack which enables all action message to be stored in the session.

    <interceptor-ref name="store">
           <param name="operationMode">STORE</param>
    </interceptor-ref>

To get the messages you need to add store interceptor in RETRIEVE mode to the specific action which needs these messages.

This is a sample global error page which is redirected to, this action can read actionErrors, fieldErrors and actionMessages when we add the store interceptor to it and set the operationMode to RETRIEVE :

@Action(value = "error-page" , 
                interceptorRefs = 
                  {@InterceptorRef(value = "store", params = {"operationMode", "RETRIEVE"})}
            )
 public String execute() throws Exception {    
  LOG.error("An error accrued during action ActionErrors '{}' , FieldErrors '{}' " , getActionErrors() , getFieldErrors());
  //Rest of the code
}

The MessageStoreInterceptor remove previous errors before adding new ones.

You can set the store in AUTOMATIC in you default stack. In this way all messages are stored always and will automatically retried when the action result is type of ServletRedirectResult (For example if the action 'redirectAction', 'redirect') So you don't need to define an explicit store interceptor in RETRIEVE mode.

Although it is not a good approach but you can access the store messages in the session with these keys.

session.get(MessageStoreInterceptor.fieldErrorsSessionKey)
session.get(MessageStoreInterceptor.actionErrorsSessionKey)
session.get(MessageStoreInterceptor.actionMessagesSessionKey)
Hygienics answered 27/1, 2016 at 5:6 Comment(0)
F
0

This functionality is not supported by Struts2 by default. Solution exists though (it is done by simple struts interceptor that stores messages in session).

solution with source code

Fey answered 11/7, 2009 at 9:42 Comment(0)
P
0

You can use result type "chain".

<action name="delete" class="com.example.Delete">   
    <result name="error" type="chain">
        <param name="actionName">show</param>
    </result>           
</action>   
<action name="show" class="com.example.Show">
    <result name="success" type="dispatcher">/jsp/show.jsp</result>                     
</action>

in show.jsp you can display action errors or action messages that you set in delete action

Pen answered 11/2, 2014 at 8:39 Comment(1)
Using chain is discouraged.Sinter
S
0

This work in me

add this line in struts.xml :

<constant name="struts.xwork.chaining.copyErrors" value="true"/>
<constant name="struts.xwork.chaining.copyMessages" value="true"/>

use result type "chain" and add result with name "input" :

<package name="a" extends="struts-default" namespace="/a">
    <action name="actionA" class="actionAClass">
        <result name="input" type="chain">
            <param name="actionName">actionB</param>
            <param name="namespace">/b</param>
        </result>
        <result type="chain">
            <param name="actionName">actionB</param>
            <param name="namespace">/b</param>
        </result>
    </action>
</package>
<package name="b" extends="struts-default" namespace="/b">
    <action name="actionB" class="actionBClass">
      <result>/foo.jsp</result>
      <result name="input">/foo.jsp</result>
    </action>
</package>
Slogan answered 18/3, 2015 at 9:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.