You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Greg Lindholm <gl...@yahoo.com> on 2008/07/02 21:29:50 UTC

[S2] Preserving messages across a Redirect in Struts 2

Hi All,

I took a look at using MessageStoreInterceptor  to preserve messages across a redirect and didn't like what I saw, it's too hard to configure.  So I wrote an Interceptor RedirectMessageInterceptor (included below) that will automatically preserve messages across a redirect or redirectAction. 

The way it works is… it looks at the result type after
a action has executed and if the result was a redirect
(ServletRedirectResult) or a redirectAction
(ServletActionRedirectResult) and there were any errors, messages, or
fieldErrors they are stored in the session.  Before the next action
executes it will check if there are any messages stored in the session
and add them to the next action.


The one thing you need to be aware of is: The action you are
redirecting towards will need to configure a result with name=”input”
as the added messages will trigger the ‘workflow’ interceptor to return
a result of “input”.
I've also posted this here: 
http://glindholm.wordpress.com/2008/07/02/preserving-messages-across-a-redirect-in-struts-2/

Feel free to use or modify this as you see fit:

package my.struts.interceptor;
import java.util.Collection;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.dispatcher.ServletActionRedirectResult;
import org.apache.struts2.dispatcher.ServletRedirectResult;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.ValidationAware;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;

public class RedirectMessageInterceptor extends MethodFilterInterceptor
{
    private static final long serialVersionUID  = 
        -1847557437429753540L;

    public static String fieldErrorsSessionKey = 
        "RedirectMessageInterceptor_FieldErrors";
    public static String actionErrorsSessionKey = 
        "RedirectMessageInterceptor_ActionErrors";
    public static String actionMessagesSessionKey = 
        "RedirectMessageInterceptor_ActionMessages";

    public String doIntercept(ActionInvocation invocation) throws Exception
    {
        Object action = invocation.getAction();
        if (action instanceof ValidationAware)
        {
            before(invocation, (ValidationAware) action);
        }

        String result = invocation.invoke();

        if (action instanceof ValidationAware)
        {
            after(invocation, (ValidationAware) action);
        }
        return result;
    }

    /**
     * Retrieve the errors and messages from the session and add them 
     * to the action.
     */
    @SuppressWarnings("unchecked")
    protected void before(ActionInvocation invocation,
                          ValidationAware validationAware) throws Exception
    {
        Map session = invocation.getInvocationContext().getSession();

        Collection<String> actionErrors = 
            (Collection) session.get(actionErrorsSessionKey);
        Collection<String> actionMessages = 
            (Collection) session.get(actionMessagesSessionKey);
        Map<String, String> fieldErrors = 
            (Map) session.get(fieldErrorsSessionKey);

        session.remove(actionErrorsSessionKey);
        session.remove(actionMessagesSessionKey);
        session.remove(fieldErrorsSessionKey);

        if (actionErrors != null && actionErrors.size() > 0)
        {
            for (String error : actionErrors)
            {
                validationAware.addActionError(error);
            }
        }

        if (actionMessages != null && actionMessages.size() > 0)
        {
            for (String message : actionMessages)
            {
                validationAware.addActionMessage(message);
            }
        }

        if (fieldErrors != null && fieldErrors.size() > 0)
        {
            for (Map.Entry<String, String> entry : fieldErrors.entrySet())
            {
                validationAware.addFieldError(entry.getKey(), 
                                              entry.getValue());
            }
        }

    }

    /**
    * If the result is a redirect then store error and messages in the session.
    */
    @SuppressWarnings("unchecked")
    protected void after(ActionInvocation invocation,
                         ValidationAware validationAware) throws Exception
    {
        Result result = invocation.getResult();

        if (result instanceof ServletRedirectResult
            || result instanceof ServletActionRedirectResult)
        {
            ActionContext actionContext = 
                invocation.getInvocationContext();
            HttpServletRequest request = 
                (HttpServletRequest) actionContext.get(
                  StrutsStatics.HTTP_REQUEST);

            /*
            * If the session doesn't already exist then it's too late to 
           * create one as the response has already been committed.
           * 
           * This is really only to handle the 'unusual' case of a browser 
           * refresh after the session has expired. In this case the 
           * messages are lost :(
           */
            HttpSession session = request.getSession(false);
            if (session != null)
            {
                Collection actionErrors = 
                    validationAware.getActionErrors();
                if (actionErrors != null && actionErrors.size() > 0)
                {
                    session.setAttribute(actionErrorsSessionKey, 
                                         actionErrors);
                }

                Collection actionMessages = 
                    validationAware.getActionMessages();
                if (actionMessages != null && actionMessages.size() > 0)
                {
                    session.setAttribute(
                        actionMessagesSessionKey,
                        actionMessages);
                }

                Map fieldErrors = validationAware.getFieldErrors();
                if (fieldErrors != null && fieldErrors.size() > 0)
                {
                    session.setAttribute(fieldErrorsSessionKey, 
                                         fieldErrors);
                }
            }
        }
    }
}





      

Re: [S2] Preserving messages across a Redirect in Struts 2

Posted by Narayana S <na...@gmail.com>.
Hi,

      this is my framework problem, for certain reasons using default
servlet session is disabled, i thought it is struts error. sorry to all.

as session is disabled... can i do the same operation with
request.setAttribute(...) ?
can any one tell me where the values added in session are read and used in
new action, in this code?

On Wed, Nov 5, 2008 at 10:14 PM, Greg Lindholm <gl...@yahoo.com> wrote:

>
> There must have been a change in Struts 2.1.2.
> Here is an update to the after() method that uses the ActionContext session
> map:
>
>    protected void after(ActionInvocation invocation, ValidationAware
> validationAware)
>        throws Exception
>    {
>        Result result = invocation.getResult();
>
>        if (result instanceof ServletRedirectResult
>            || result instanceof ServletActionRedirectResult)
>        {
>             Map session = invocation.getInvocationContext().getSession();
>
>             Collection actionErrors = validationAware.getActionErrors();
>            if (actionErrors != null && actionErrors.size() > 0)
>            {
>                 session.put(ACTION_ERRORS_KEY, actionErrors);
>             }
>
>            Collection actionMessages = validationAware.getActionMessages();
>            if (actionMessages != null && actionMessages.size() > 0)
>            {
>                 session.put(ACTION_MESSAGES_KEY, actionMessages);
>             }
>
>            Map fieldErrors = validationAware.getFieldErrors();
>            if (fieldErrors != null && fieldErrors.size() > 0)
>            {
>                 session.put(FIELD_ERRORS_KEY, fieldErrors);
>            }
>        }
>    }
>
> The full interceptor source can be found here:
>
> http://glindholm.wordpress.com/2008/07/02/preserving-messages-across-a-redirect-in-struts-2/
>
>
>
> Mead Lai wrote:
> >
> > "java.lang.UnsupportedOperationException: Don't use default servlet
> > session".
> > Just use the session from ActionContext, don't use the servlet's.
> >
> > protected Map<String,String> getSession() {
> >         return ActionContext.getContext().getSession();//from
> > ActionContext
> > here!
> > }
> >
> > protected HttpServletRequest request(){
> >         return ServletActionContext.getRequest();
> >     }
> >
> >
> > On Wed, Nov 5, 2008 at 12:05 PM, Narayana S <na...@gmail.com>
> > wrote:
> >
> >> Hi,
> >>
> >>       i am using apache Tomcat 6.0.3, struts 2.1.2, and jdk 1.6. can any
> >> one help me solving this issue?
> >>
> >> Thanks in advance.
> >>
> >> On Tue, Nov 4, 2008 at 7:06 PM, Greg Lindholm <gl...@yahoo.com>
> >> wrote:
> >>
> >> >
> >> >
> >> >
> >> > Ganesh123 wrote:
> >> > >
> >> > >          Excellent work. i am looking for the same solution. i tried
> >> > > implementing your interceptor , but  it is throwing exception ...
> >> > >   "java.lang.UnsupportedOperationException: Don't use default
> servlet
> >> > > session".
> >> > >
> >> > > near session.setAttribute(ACTION_MESSAGES_KEY,actionMessages);
> >> > >
> >> > >
> >> >
> >> > Very strange, I've never seen a session where setAttribute() throws an
> >> > UnsupportedOperationException.  (And whats a "default servlet
> >> session"?)
> >> > I can only guess it's something to do with your container environment.
> >> >
> >> > You had better post your configuration information; platform,
> >> container,
> >> > cluster setup? etc. maybe someone on the list can help.
> >> >
> >> > Here are the relevant lines of code from the interceptor.
> >> >
> >> > ActionContext actionContext = invocation.getInvocationContext();
> >> > HttpServletRequest request = (HttpServletRequest)
> >> >  actionContext.get(StrutsStatics.HTTP_REQUEST);
> >> > HttpSession session = request.getSession(false);
> >> > if (session != null)
> >> > {
> >> >  ...
> >> >   Collection actionMessages = validationAware.getActionMessages();
> >> >  if (actionMessages != null && actionMessages.size() > 0)
> >> >  {
> >> >     session.setAttribute(ACTION_MESSAGES_KEY, actionMessages);
> >> >  }
> >> >   ...
> >> > }
> >> >
> >
> >
> >
> >
>
> --
> View this message in context:
> http://www.nabble.com/-S2--Preserving-messages-across-a-Redirect-in-Struts-2-tp18245061p20343444.html
> Sent from the Struts - User mailing list archive at Nabble.com.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
>
>

Re: [S2] Preserving messages across a Redirect in Struts 2

Posted by Greg Lindholm <gl...@yahoo.com>.
There must have been a change in Struts 2.1.2.
Here is an update to the after() method that uses the ActionContext session
map:

    protected void after(ActionInvocation invocation, ValidationAware
validationAware)
        throws Exception
    {
        Result result = invocation.getResult();

        if (result instanceof ServletRedirectResult
            || result instanceof ServletActionRedirectResult)
        {
            Map session = invocation.getInvocationContext().getSession();

            Collection actionErrors = validationAware.getActionErrors();
            if (actionErrors != null && actionErrors.size() > 0)
            {
                session.put(ACTION_ERRORS_KEY, actionErrors);
            }

            Collection actionMessages = validationAware.getActionMessages();
            if (actionMessages != null && actionMessages.size() > 0)
            {
                session.put(ACTION_MESSAGES_KEY, actionMessages);
            }

            Map fieldErrors = validationAware.getFieldErrors();
            if (fieldErrors != null && fieldErrors.size() > 0)
            {
                session.put(FIELD_ERRORS_KEY, fieldErrors);
            }
        }
    }

The full interceptor source can be found here: 
http://glindholm.wordpress.com/2008/07/02/preserving-messages-across-a-redirect-in-struts-2/



Mead Lai wrote:
> 
> "java.lang.UnsupportedOperationException: Don't use default servlet
> session".
> Just use the session from ActionContext, don't use the servlet's.
> 
> protected Map<String,String> getSession() {
>         return ActionContext.getContext().getSession();//from
> ActionContext
> here!
> }
> 
> protected HttpServletRequest request(){
>         return ServletActionContext.getRequest();
>     }
> 
> 
> On Wed, Nov 5, 2008 at 12:05 PM, Narayana S <na...@gmail.com>
> wrote:
> 
>> Hi,
>>
>>       i am using apache Tomcat 6.0.3, struts 2.1.2, and jdk 1.6. can any
>> one help me solving this issue?
>>
>> Thanks in advance.
>>
>> On Tue, Nov 4, 2008 at 7:06 PM, Greg Lindholm <gl...@yahoo.com>
>> wrote:
>>
>> >
>> >
>> >
>> > Ganesh123 wrote:
>> > >
>> > >          Excellent work. i am looking for the same solution. i tried
>> > > implementing your interceptor , but  it is throwing exception ...
>> > >   "java.lang.UnsupportedOperationException: Don't use default servlet
>> > > session".
>> > >
>> > > near session.setAttribute(ACTION_MESSAGES_KEY,actionMessages);
>> > >
>> > >
>> >
>> > Very strange, I've never seen a session where setAttribute() throws an
>> > UnsupportedOperationException.  (And whats a "default servlet
>> session"?)
>> > I can only guess it's something to do with your container environment.
>> >
>> > You had better post your configuration information; platform,
>> container,
>> > cluster setup? etc. maybe someone on the list can help.
>> >
>> > Here are the relevant lines of code from the interceptor.
>> >
>> > ActionContext actionContext = invocation.getInvocationContext();
>> > HttpServletRequest request = (HttpServletRequest)
>> >  actionContext.get(StrutsStatics.HTTP_REQUEST);
>> > HttpSession session = request.getSession(false);
>> > if (session != null)
>> > {
>> >  ...
>> >   Collection actionMessages = validationAware.getActionMessages();
>> >  if (actionMessages != null && actionMessages.size() > 0)
>> >  {
>> >     session.setAttribute(ACTION_MESSAGES_KEY, actionMessages);
>> >  }
>> >   ...
>> > }
>> >
> 
> 
> 
> 

-- 
View this message in context: http://www.nabble.com/-S2--Preserving-messages-across-a-Redirect-in-Struts-2-tp18245061p20343444.html
Sent from the Struts - User mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: [S2] Preserving messages across a Redirect in Struts 2

Posted by Mead Lai <la...@gmail.com>.
"java.lang.UnsupportedOperationException: Don't use default servlet
session".
Just use the session from ActionContext, don't use the servlet's.

protected Map<String,String> getSession() {
        return ActionContext.getContext().getSession();//from ActionContext
here!
}

protected HttpServletRequest request(){
        return ServletActionContext.getRequest();
    }


On Wed, Nov 5, 2008 at 12:05 PM, Narayana S <na...@gmail.com> wrote:

> Hi,
>
>       i am using apache Tomcat 6.0.3, struts 2.1.2, and jdk 1.6. can any
> one help me solving this issue?
>
> Thanks in advance.
>
> On Tue, Nov 4, 2008 at 7:06 PM, Greg Lindholm <gl...@yahoo.com> wrote:
>
> >
> >
> >
> > Ganesh123 wrote:
> > >
> > >          Excellent work. i am looking for the same solution. i tried
> > > implementing your interceptor , but  it is throwing exception ...
> > >   "java.lang.UnsupportedOperationException: Don't use default servlet
> > > session".
> > >
> > > near session.setAttribute(ACTION_MESSAGES_KEY,actionMessages);
> > >
> > >
> >
> > Very strange, I've never seen a session where setAttribute() throws an
> > UnsupportedOperationException.  (And whats a "default servlet session"?)
> > I can only guess it's something to do with your container environment.
> >
> > You had better post your configuration information; platform, container,
> > cluster setup? etc. maybe someone on the list can help.
> >
> > Here are the relevant lines of code from the interceptor.
> >
> > ActionContext actionContext = invocation.getInvocationContext();
> > HttpServletRequest request = (HttpServletRequest)
> >  actionContext.get(StrutsStatics.HTTP_REQUEST);
> > HttpSession session = request.getSession(false);
> > if (session != null)
> > {
> >  ...
> >   Collection actionMessages = validationAware.getActionMessages();
> >  if (actionMessages != null && actionMessages.size() > 0)
> >  {
> >     session.setAttribute(ACTION_MESSAGES_KEY, actionMessages);
> >  }
> >   ...
> > }
> >
> >
> >
> > --
> > View this message in context:
> >
> http://www.nabble.com/-S2--Preserving-messages-across-a-Redirect-in-Struts-2-tp18245061p20322352.html
> > Sent from the Struts - User mailing list archive at Nabble.com.
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> > For additional commands, e-mail: user-help@struts.apache.org
> >
> >
>



-- 
BestRegards,
Mead
http://yayisoft.com

Bill Vaughan  - "The tax collector must love poor people, he's creating so
many of them."

Re: [S2] Preserving messages across a Redirect in Struts 2

Posted by Nils-Helge Garli Hegvik <ni...@gmail.com>.
Could you show us the entire stack trace?

Nils-H

On Wed, Nov 5, 2008 at 5:05 AM, Narayana S <na...@gmail.com> wrote:
> Hi,
>
>       i am using apache Tomcat 6.0.3, struts 2.1.2, and jdk 1.6. can any
> one help me solving this issue?
>
> Thanks in advance.
>
> On Tue, Nov 4, 2008 at 7:06 PM, Greg Lindholm <gl...@yahoo.com> wrote:
>
>>
>>
>>
>> Ganesh123 wrote:
>> >
>> >          Excellent work. i am looking for the same solution. i tried
>> > implementing your interceptor , but  it is throwing exception ...
>> >   "java.lang.UnsupportedOperationException: Don't use default servlet
>> > session".
>> >
>> > near session.setAttribute(ACTION_MESSAGES_KEY,actionMessages);
>> >
>> >
>>
>> Very strange, I've never seen a session where setAttribute() throws an
>> UnsupportedOperationException.  (And whats a "default servlet session"?)
>> I can only guess it's something to do with your container environment.
>>
>> You had better post your configuration information; platform, container,
>> cluster setup? etc. maybe someone on the list can help.
>>
>> Here are the relevant lines of code from the interceptor.
>>
>> ActionContext actionContext = invocation.getInvocationContext();
>> HttpServletRequest request = (HttpServletRequest)
>>  actionContext.get(StrutsStatics.HTTP_REQUEST);
>> HttpSession session = request.getSession(false);
>> if (session != null)
>> {
>>  ...
>>   Collection actionMessages = validationAware.getActionMessages();
>>  if (actionMessages != null && actionMessages.size() > 0)
>>  {
>>     session.setAttribute(ACTION_MESSAGES_KEY, actionMessages);
>>  }
>>   ...
>> }
>>
>>
>>
>> --
>> View this message in context:
>> http://www.nabble.com/-S2--Preserving-messages-across-a-Redirect-in-Struts-2-tp18245061p20322352.html
>> Sent from the Struts - User mailing list archive at Nabble.com.
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
>> For additional commands, e-mail: user-help@struts.apache.org
>>
>>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: [S2] Preserving messages across a Redirect in Struts 2

Posted by Narayana S <na...@gmail.com>.
Hi,

       i am using apache Tomcat 6.0.3, struts 2.1.2, and jdk 1.6. can any
one help me solving this issue?

Thanks in advance.

On Tue, Nov 4, 2008 at 7:06 PM, Greg Lindholm <gl...@yahoo.com> wrote:

>
>
>
> Ganesh123 wrote:
> >
> >          Excellent work. i am looking for the same solution. i tried
> > implementing your interceptor , but  it is throwing exception ...
> >   "java.lang.UnsupportedOperationException: Don't use default servlet
> > session".
> >
> > near session.setAttribute(ACTION_MESSAGES_KEY,actionMessages);
> >
> >
>
> Very strange, I've never seen a session where setAttribute() throws an
> UnsupportedOperationException.  (And whats a "default servlet session"?)
> I can only guess it's something to do with your container environment.
>
> You had better post your configuration information; platform, container,
> cluster setup? etc. maybe someone on the list can help.
>
> Here are the relevant lines of code from the interceptor.
>
> ActionContext actionContext = invocation.getInvocationContext();
> HttpServletRequest request = (HttpServletRequest)
>  actionContext.get(StrutsStatics.HTTP_REQUEST);
> HttpSession session = request.getSession(false);
> if (session != null)
> {
>  ...
>   Collection actionMessages = validationAware.getActionMessages();
>  if (actionMessages != null && actionMessages.size() > 0)
>  {
>     session.setAttribute(ACTION_MESSAGES_KEY, actionMessages);
>  }
>   ...
> }
>
>
>
> --
> View this message in context:
> http://www.nabble.com/-S2--Preserving-messages-across-a-Redirect-in-Struts-2-tp18245061p20322352.html
> Sent from the Struts - User mailing list archive at Nabble.com.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
>
>

Re: [S2] Preserving messages across a Redirect in Struts 2

Posted by Greg Lindholm <gl...@yahoo.com>.


Ganesh123 wrote:
> 
>          Excellent work. i am looking for the same solution. i tried
> implementing your interceptor , but  it is throwing exception ...
>   "java.lang.UnsupportedOperationException: Don't use default servlet
> session".
> 
> near session.setAttribute(ACTION_MESSAGES_KEY,actionMessages);
> 
> 

Very strange, I've never seen a session where setAttribute() throws an 
UnsupportedOperationException.  (And whats a "default servlet session"?)
I can only guess it's something to do with your container environment.

You had better post your configuration information; platform, container, 
cluster setup? etc. maybe someone on the list can help.

Here are the relevant lines of code from the interceptor.

ActionContext actionContext = invocation.getInvocationContext();
HttpServletRequest request = (HttpServletRequest) 
  actionContext.get(StrutsStatics.HTTP_REQUEST);
HttpSession session = request.getSession(false);
if (session != null)
{
  ...
  Collection actionMessages = validationAware.getActionMessages();
  if (actionMessages != null && actionMessages.size() > 0)
  {
    session.setAttribute(ACTION_MESSAGES_KEY, actionMessages);
  }
  ...
}



-- 
View this message in context: http://www.nabble.com/-S2--Preserving-messages-across-a-Redirect-in-Struts-2-tp18245061p20322352.html
Sent from the Struts - User mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: [S2] Preserving messages across a Redirect in Struts 2

Posted by Narayana S <na...@gmail.com>.
Hi Greg,

         Excellent work. i am looking for the same solution. i tried
implementing your interceptor , but  it is throwing exception ...
  "java.lang.UnsupportedOperationException: Don't use default servlet
session".

near session.setAttribute(ACTION_MESSAGES_KEY,actionMessages);

can you help me solving this issue?

Thanks in advance.



On Mon, Jul 7, 2008 at 7:32 PM, Greg Lindholm <gl...@yahoo.com> wrote:

>
>
> dusty wrote:
> >
> > I have found
> >                 <interceptor-ref name="messages">
> >                     <param
> > name="operationMode">AUTOMATIC</param>
> >                 </interceptor-ref>
> > to work great for addActionMessage.  To tell you the truth I haven't
> tried
> > it for addActionError or fieldErrors.  You would redirect after an error
> > that should render input?  Really?
> >
> >
>
> Sorry, don't know what "messages" is, it's not part of the
> struts-default.xml (2.0.11.1).
>
> I wanted an Interceptor that didn't require any per-action configuration
> and
> would preserve all messages across a redirect.  I have it configured as
> part
> of my default stack.
> (I don't have a use-case where the fieldErrors would be useful across a
> redirect but somebody may and it was easy enough to include them.)
>
>
> --
> View this message in context:
> http://www.nabble.com/-S2--Preserving-messages-across-a-Redirect-in-Struts-2-tp18245061p18317448.html
> Sent from the Struts - User mailing list archive at Nabble.com.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
>
>

Re: [S2] Preserving messages across a Redirect in Struts 2

Posted by Greg Lindholm <gl...@yahoo.com>.

dusty wrote:
> 
> I have found 
>                 <interceptor-ref name="messages">
>                     &lt;param
> name="operationMode"&gt;AUTOMATIC&lt;/param&gt;
>                 </interceptor-ref>
> to work great for addActionMessage.  To tell you the truth I haven't tried
> it for addActionError or fieldErrors.  You would redirect after an error
> that should render input?  Really?
> 
> 

Sorry, don't know what "messages" is, it's not part of the
struts-default.xml (2.0.11.1). 

I wanted an Interceptor that didn't require any per-action configuration and
would preserve all messages across a redirect.  I have it configured as part
of my default stack.
(I don't have a use-case where the fieldErrors would be useful across a
redirect but somebody may and it was easy enough to include them.)


-- 
View this message in context: http://www.nabble.com/-S2--Preserving-messages-across-a-Redirect-in-Struts-2-tp18245061p18317448.html
Sent from the Struts - User mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: [S2] Preserving messages across a Redirect in Struts 2

Posted by dusty <du...@yahoo.com>.
I have found 
                <interceptor-ref name="messages">
                    AUTOMATIC
                </interceptor-ref>
to work great for addActionMessage.  To tell you the truth I haven't tried
it for addActionError or fieldErrors.  You would redirect after an error
that should render input?  Really?



Greg Lindholm wrote:
> 
> Hi All,
> 
> I took a look at using MessageStoreInterceptor  to preserve messages
> across a redirect and didn't like what I saw, it's too hard to configure. 
> So I wrote an Interceptor RedirectMessageInterceptor (included below) that
> will automatically preserve messages across a redirect or redirectAction. 
> 
> The way it works is… it looks at the result type after
> a action has executed and if the result was a redirect
> (ServletRedirectResult) or a redirectAction
> (ServletActionRedirectResult) and there were any errors, messages, or
> fieldErrors they are stored in the session.  Before the next action
> executes it will check if there are any messages stored in the session
> and add them to the next action.
> 
> 
> The one thing you need to be aware of is: The action you are
> redirecting towards will need to configure a result with name=”input”
> as the added messages will trigger the ‘workflow’ interceptor to return
> a result of “input”.
> I've also posted this here: 
> http://glindholm.wordpress.com/2008/07/02/preserving-messages-across-a-redirect-in-struts-2/
> 
> Feel free to use or modify this as you see fit:
> 
> package my.struts.interceptor;
> import java.util.Collection;
> import java.util.Map;
> import javax.servlet.http.HttpServletRequest;
> import javax.servlet.http.HttpSession;
> import org.apache.struts2.StrutsStatics;
> import org.apache.struts2.dispatcher.ServletActionRedirectResult;
> import org.apache.struts2.dispatcher.ServletRedirectResult;
> import com.opensymphony.xwork2.ActionContext;
> import com.opensymphony.xwork2.ActionInvocation;
> import com.opensymphony.xwork2.Result;
> import com.opensymphony.xwork2.ValidationAware;
> import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
> 
> public class RedirectMessageInterceptor extends MethodFilterInterceptor
> {
>     private static final long serialVersionUID  = 
>         -1847557437429753540L;
> 
>     public static String fieldErrorsSessionKey = 
>         "RedirectMessageInterceptor_FieldErrors";
>     public static String actionErrorsSessionKey = 
>         "RedirectMessageInterceptor_ActionErrors";
>     public static String actionMessagesSessionKey = 
>         "RedirectMessageInterceptor_ActionMessages";
> 
>     public String doIntercept(ActionInvocation invocation) throws
> Exception
>     {
>         Object action = invocation.getAction();
>         if (action instanceof ValidationAware)
>         {
>             before(invocation, (ValidationAware) action);
>         }
> 
>         String result = invocation.invoke();
> 
>         if (action instanceof ValidationAware)
>         {
>             after(invocation, (ValidationAware) action);
>         }
>         return result;
>     }
> 
>     /**
>      * Retrieve the errors and messages from the session and add them 
>      * to the action.
>      */
>     @SuppressWarnings("unchecked")
>     protected void before(ActionInvocation invocation,
>                           ValidationAware validationAware) throws
> Exception
>     {
>         Map session = invocation.getInvocationContext().getSession();
> 
>         Collection<String> actionErrors = 
>             (Collection) session.get(actionErrorsSessionKey);
>         Collection<String> actionMessages = 
>             (Collection) session.get(actionMessagesSessionKey);
>         Map<String, String> fieldErrors = 
>             (Map) session.get(fieldErrorsSessionKey);
> 
>         session.remove(actionErrorsSessionKey);
>         session.remove(actionMessagesSessionKey);
>         session.remove(fieldErrorsSessionKey);
> 
>         if (actionErrors != null && actionErrors.size() > 0)
>         {
>             for (String error : actionErrors)
>             {
>                 validationAware.addActionError(error);
>             }
>         }
> 
>         if (actionMessages != null && actionMessages.size() > 0)
>         {
>             for (String message : actionMessages)
>             {
>                 validationAware.addActionMessage(message);
>             }
>         }
> 
>         if (fieldErrors != null && fieldErrors.size() > 0)
>         {
>             for (Map.Entry<String, String> entry : fieldErrors.entrySet())
>             {
>                 validationAware.addFieldError(entry.getKey(), 
>                                               entry.getValue());
>             }
>         }
> 
>     }
> 
>     /**
>     * If the result is a redirect then store error and messages in the
> session.
>     */
>     @SuppressWarnings("unchecked")
>     protected void after(ActionInvocation invocation,
>                          ValidationAware validationAware) throws Exception
>     {
>         Result result = invocation.getResult();
> 
>         if (result instanceof ServletRedirectResult
>             || result instanceof ServletActionRedirectResult)
>         {
>             ActionContext actionContext = 
>                 invocation.getInvocationContext();
>             HttpServletRequest request = 
>                 (HttpServletRequest) actionContext.get(
>                   StrutsStatics.HTTP_REQUEST);
> 
>             /*
>             * If the session doesn't already exist then it's too late to 
>            * create one as the response has already been committed.
>            * 
>            * This is really only to handle the 'unusual' case of a browser 
>            * refresh after the session has expired. In this case the 
>            * messages are lost :(
>            */
>             HttpSession session = request.getSession(false);
>             if (session != null)
>             {
>                 Collection actionErrors = 
>                     validationAware.getActionErrors();
>                 if (actionErrors != null && actionErrors.size() > 0)
>                 {
>                     session.setAttribute(actionErrorsSessionKey, 
>                                          actionErrors);
>                 }
> 
>                 Collection actionMessages = 
>                     validationAware.getActionMessages();
>                 if (actionMessages != null && actionMessages.size() > 0)
>                 {
>                     session.setAttribute(
>                         actionMessagesSessionKey,
>                         actionMessages);
>                 }
> 
>                 Map fieldErrors = validationAware.getFieldErrors();
>                 if (fieldErrors != null && fieldErrors.size() > 0)
>                 {
>                     session.setAttribute(fieldErrorsSessionKey, 
>                                          fieldErrors);
>                 }
>             }
>         }
>     }
> }
> 
> 
> 
> 
> 
> 
> 

-- 
View this message in context: http://www.nabble.com/-S2--Preserving-messages-across-a-Redirect-in-Struts-2-tp18245061p18298761.html
Sent from the Struts - User mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: [S2] Preserving messages across a Redirect in Struts 2

Posted by Chris Pratt <th...@gmail.com>.
Greg, great work, I'd love to see that replace the store interceptor,
I think it's a lot clearer and easier to use.  For that matter it
could be put in the default stack since it doesn't require any
parameters to make it work.  Thanks for the post.
  (*Chris*)

On Wed, Jul 2, 2008 at 12:29 PM, Greg Lindholm <gl...@yahoo.com> wrote:
> Hi All,
>
> I took a look at using MessageStoreInterceptor  to preserve messages across a redirect and didn't like what I saw, it's too hard to configure.  So I wrote an Interceptor RedirectMessageInterceptor (included below) that will automatically preserve messages across a redirect or redirectAction.
>
> The way it works is… it looks at the result type after
> a action has executed and if the result was a redirect
> (ServletRedirectResult) or a redirectAction
> (ServletActionRedirectResult) and there were any errors, messages, or
> fieldErrors they are stored in the session.  Before the next action
> executes it will check if there are any messages stored in the session
> and add them to the next action.
>
>
> The one thing you need to be aware of is: The action you are
> redirecting towards will need to configure a result with name="input"
> as the added messages will trigger the 'workflow' interceptor to return
> a result of "input".
> I've also posted this here:
> http://glindholm.wordpress.com/2008/07/02/preserving-messages-across-a-redirect-in-struts-2/
>
> Feel free to use or modify this as you see fit:
>
> package my.struts.interceptor;
> import java.util.Collection;
> import java.util.Map;
> import javax.servlet.http.HttpServletRequest;
> import javax.servlet.http.HttpSession;
> import org.apache.struts2.StrutsStatics;
> import org.apache.struts2.dispatcher.ServletActionRedirectResult;
> import org.apache.struts2.dispatcher.ServletRedirectResult;
> import com.opensymphony.xwork2.ActionContext;
> import com.opensymphony.xwork2.ActionInvocation;
> import com.opensymphony.xwork2.Result;
> import com.opensymphony.xwork2.ValidationAware;
> import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
>
> public class RedirectMessageInterceptor extends MethodFilterInterceptor
> {
>     private static final long serialVersionUID  =
>         -1847557437429753540L;
>
>     public static String fieldErrorsSessionKey =
>         "RedirectMessageInterceptor_FieldErrors";
>     public static String actionErrorsSessionKey =
>         "RedirectMessageInterceptor_ActionErrors";
>     public static String actionMessagesSessionKey =
>         "RedirectMessageInterceptor_ActionMessages";
>
>     public String doIntercept(ActionInvocation invocation) throws Exception
>     {
>         Object action = invocation.getAction();
>         if (action instanceof ValidationAware)
>         {
>             before(invocation, (ValidationAware) action);
>         }
>
>         String result = invocation.invoke();
>
>         if (action instanceof ValidationAware)
>         {
>             after(invocation, (ValidationAware) action);
>         }
>         return result;
>     }
>
>     /**
>      * Retrieve the errors and messages from the session and add them
>      * to the action.
>      */
>     @SuppressWarnings("unchecked")
>     protected void before(ActionInvocation invocation,
>                           ValidationAware validationAware) throws Exception
>     {
>         Map session = invocation.getInvocationContext().getSession();
>
>         Collection<String> actionErrors =
>             (Collection) session.get(actionErrorsSessionKey);
>         Collection<String> actionMessages =
>             (Collection) session.get(actionMessagesSessionKey);
>         Map<String, String> fieldErrors =
>             (Map) session.get(fieldErrorsSessionKey);
>
>         session.remove(actionErrorsSessionKey);
>         session.remove(actionMessagesSessionKey);
>         session.remove(fieldErrorsSessionKey);
>
>         if (actionErrors != null && actionErrors.size() > 0)
>         {
>             for (String error : actionErrors)
>             {
>                 validationAware.addActionError(error);
>             }
>         }
>
>         if (actionMessages != null && actionMessages.size() > 0)
>         {
>             for (String message : actionMessages)
>             {
>                 validationAware.addActionMessage(message);
>             }
>         }
>
>         if (fieldErrors != null && fieldErrors.size() > 0)
>         {
>             for (Map.Entry<String, String> entry : fieldErrors.entrySet())
>             {
>                 validationAware.addFieldError(entry.getKey(),
>                                               entry.getValue());
>             }
>         }
>
>     }
>
>     /**
>     * If the result is a redirect then store error and messages in the session.
>     */
>     @SuppressWarnings("unchecked")
>     protected void after(ActionInvocation invocation,
>                          ValidationAware validationAware) throws Exception
>     {
>         Result result = invocation.getResult();
>
>         if (result instanceof ServletRedirectResult
>             || result instanceof ServletActionRedirectResult)
>         {
>             ActionContext actionContext =
>                 invocation.getInvocationContext();
>             HttpServletRequest request =
>                 (HttpServletRequest) actionContext.get(
>                   StrutsStatics.HTTP_REQUEST);
>
>             /*
>             * If the session doesn't already exist then it's too late to
>            * create one as the response has already been committed.
>            *
>            * This is really only to handle the 'unusual' case of a browser
>            * refresh after the session has expired. In this case the
>            * messages are lost :(
>            */
>             HttpSession session = request.getSession(false);
>             if (session != null)
>             {
>                 Collection actionErrors =
>                     validationAware.getActionErrors();
>                 if (actionErrors != null && actionErrors.size() > 0)
>                 {
>                     session.setAttribute(actionErrorsSessionKey,
>                                          actionErrors);
>                 }
>
>                 Collection actionMessages =
>                     validationAware.getActionMessages();
>                 if (actionMessages != null && actionMessages.size() > 0)
>                 {
>                     session.setAttribute(
>                         actionMessagesSessionKey,
>                         actionMessages);
>                 }
>
>                 Map fieldErrors = validationAware.getFieldErrors();
>                 if (fieldErrors != null && fieldErrors.size() > 0)
>                 {
>                     session.setAttribute(fieldErrorsSessionKey,
>                                          fieldErrors);
>                 }
>             }
>         }
>     }
> }
>
>
>
>
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org