Search code examples
struts2interceptor

Struts2 interceptor (After View Rendered Interceptor ) is not called before the redirect request comes back from browser


In a webapp we have transaction management using struts2 interceptor

pseudo code of the interceptor

public String intercept(ActionInvocation invocation) throws Exception {
    TransactionService.startTransaction();
    invocation.invoke();
    TransactionService.commitTransaction();
}

when the action returns 'redirect' (302), sometimes the redirected request comes to the server before 'TransactionService.commitTransaction()' is called. ( looks like network call is faster than stack unwinding )

below log message captured explains this

2017-10-04 09:18:37,693 [task-37] DEBUG (interceptors)  TransactionInterceptor begin
2017-10-04 09:18:37,949 [task-38] DEBUG (interceptors)  TransactionInterceptor begin
2017-10-04 09:18:37,963 [task-37] DEBUG (interceptors)  TransactionInterceptor commit 
2017-10-04 09:18:37,955 [task-38] ERROR (interceptors)  SecurityInterceptor: Failed to execute Action:

in the above log Task-37 ( thread ) suppose to save/update some records in DB and issue a redirect to refresh the view, its interceptor will commit the transaction.

But the redirect thread ( Task - 38 ) reached the server before commit happened.

I am looking at PreResultListener or 'Chain Result'. ( both options have its own issues) I greatly appreciate any input to solve this issue

Thanks in advance.


Solution

  • Here is a working code, kind a worked around with PreResultListener.

    public String intercept(ActionInvocation invocation) throws Exception {
        invocation.addPreResultListener(new PreResultListener() {
            @Override
            public void beforeResult(ActionInvocation invocation, String resultCode) {
                try {
    
                    // commit based on the resultCode comparision 
                    if (StringUtils.equals(resultCode,"302_redirect")  {
                        TransactionService.commitTransaction();
                    }
                    // or commparision based on the redirect handler 
                    // Class names are from struts-default.xml
                    /*
                    String resultConfigClassName = invocation.getProxy().getConfig().getResults().get(resultCode).getClassName();
                    if (StringUtils.equals(resultConfigClassName,"org.apache.struts2.dispatcher.ServletRedirectResult")
                            || StringUtils.equals(resultConfigClassName, "org.apache.struts2.dispatcher.ServletActionRedirectResult")) {
                        TransactionService.commitTransaction();
                    }
                    */
                }
                catch (Exception e) {
                    // Ignore don't do anything
                }
            }
        });
    
        TransactionService.startTransaction();
        invocation.invoke();
        TransactionService.commitTransaction();
    }