javastruts2struts2-interceptors

Struts 2 Interceptor Response Header Not Being Set


Struts 2.5.18

I am having an issue with setting a header in a Struts 2 interceptor and the client not receiving the header back. I am using the exact same interceptor in another Struts 2 project without issue.

I did stumble across this post How can I configure HTTP Response Headers in a Struts2 Interceptor? which had the same issue and resolved it by switching getting the response from ServletActionContext.getResponse() to getting it from the invocation context invocation.getInvocationContext().get(StrutsStatics.HTTP_RESPONSE)

This ended up with the same result of the header still not getting sent back to the browser. I am using the developer tools to monitor the response header and it is not present.

Also, I put a debug message in right after calling setHeader() in the response to see if the response contained the new header using containsHeader(). containsHeader() is resulting in a FALSE as if the setHeader is not working at all.

Does anyone have any suggestions on what may be happening with the response object? The intercept() method is below

public String intercept(ActionInvocation invocation) throws Exception {
    String result = invocation.invoke();
    Boolean hasValidationErrors = Boolean.FALSE;
    Object action = invocation.getAction();
    if(action instanceof ValidationAware) {
        ValidationAware validationAware = (ValidationAware) action;
        hasValidationErrors = validationAware.hasErrors();

    }

    HttpServletResponse response = (HttpServletResponse) invocation.getInvocationContext().get(StrutsStatics.HTTP_RESPONSE);
    response.setHeader(VALIDATION_FLAG_HEADER_NAME, String.valueOf(hasValidationErrors));

    if (log.isDebugEnabled()) log.debug("Does response contain new header? " + response.containsHeader(VALIDATION_FLAG_HEADER_NAME));

    return result;
}

Update: working code after applying Dave's Fix

  public String intercept(ActionInvocation invocation) throws Exception {

        invocation.addPreResultListener((actionInvocation, resultCode) -> {
            // perform operation necessary before Result execution
            Boolean hasValidationErrors = Boolean.FALSE;
            Object action = invocation.getAction();
            if(action instanceof ValidationAware) {
                ValidationAware validationAware = (ValidationAware) action;
                hasValidationErrors = validationAware.hasErrors();

            }

            HttpServletResponse response = (HttpServletResponse) invocation.getInvocationContext().get(StrutsStatics.HTTP_RESPONSE);
            response.setHeader(VALIDATION_FLAG_HEADER_NAME, String.valueOf(hasValidationErrors));

            if (log.isDebugEnabled()) log.debug("Does response contain new header? " + response.containsHeader(VALIDATION_FLAG_HEADER_NAME));

        });

        return invocation.invoke();
    }

Solution

  • You're setting the header after calling invoke, by which point the response has been rendered.

    From https://struts.apache.org/core-developers/writing-interceptors.html:

    Keep in mind that invoke will return after the result has been called (eg. after you JSP has been rendered), making it perfect for things like open-session-in-view patterns. If you want to do something before the result gets called, you should implement a PreResultListener.

    Set the header before you call invoke, or implement a PreResultListener.