0

Roman C. Please see my most recent comment.

---Original message follows---

There are MANY questions and answers about "Response already committed", but I don't find any related to my issue; specifically my application does not touch the ServletResponse.

I have a Struts2/Tiles2 application running on WebLogic 10.3.0 with 2 Interceptors,

  1. AuthenticationInterceptor ensures the user is logged in and has a role which allows access to the app.
  2. AgreementInterceptor presents a user agreement page.

This interceptor pair works in all scenarios on my Windows laptop running WebLogic 10.3.0.

However, on our clustered server running on Linux I get "IllegalStateException: Response already committed" when a user who needs to accept the user agreement logs in. The error occurs when control returns to the AuthenticationInterceptor.

Users who do not need to accept the agreement, either because they have a role that is perpetually authorized or because they have an active acceptance, do not get this error.

The difference is that when the agreement is required then the Interceptor chain is ended by the AgreementInterceptor returning "agreement" instead of returning the result from ActionInvocation.invoke().

struts.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
        "http://struts.apache.org/dtds/struts-2.3.dtd">

<!-- Struts 2.3.34 with Tiles 2.2.2 -->
<struts>
  <constant name="struts.action.extension"                     value="action"/>
  <constant name="struts.configuration.xml.reload"             value="true"/>
  <constant name="struts.custom.i18n.resources"                value="i18n.layout,i18n.systemError"/>
  <constant name="struts.devMode"                              value="true"/>
  <constant name="struts.mapper.action.prefix.enabled"         value="true"/>
  <constant name="struts.mapper.action.prefix.crossNamespaces" value="false"/>
  <constant name="struts.ui.theme"                             value="simple"/>

  <package name="app-name" namespace="/" extends="json-default">
    <result-types>
      <result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult"/>
    </result-types>

    <interceptors>
      <interceptor name="app-user-auth" class="com.domain.app.interceptor.AuthenticationInterceptor"/>
      <interceptor name="agreement" class="com.domain.app.interceptor.AgreementInterceptor"/>
      <interceptor-stack name="main-stack">
        <interceptor-ref name="jsonValidationWorkflowStack"/>
        <interceptor-ref name="defaultStack"/>
        <interceptor-ref name="app-user-auth"/>
      </interceptor-stack>

      <interceptor-stack name="second-stack">
        <interceptor-ref name="main-stack"/>
        <interceptor-ref name="agreement"/>
      </interceptor-stack>
    </interceptors>

    <default-interceptor-ref name="main-stack"/>

    <default-action-ref name="home_execute"/>

    <global-results>
      <result name="error">/public/jsp/systemError.jsp</result>
      <result name="denied">/public/jsp/accessDenied.jsp</result>
    </global-results>
    <global-exception-mappings>
      <exception-mapping result="error" exception="java.lang.Exception"/>
    </global-exception-mappings>

    <action name="home_*" method="{1}" class="com.domain.app.action.HomeAction">
      <interceptor-ref name="second-stack"/>
      <result name="success">/home.jsp</result>
      <result name="results" type="json"/>
      <result name="agreement" type="redirectAction">
        <param name="actionName">agreement_execute</param>
      </result>
    </action>

    <action name="agreement_*" method="{1}" class="com.domain.app.action.AgreementAction">
      <result name="success">/agreement.jsp</result>
      <result name="accepted" type="redirectAction">
        <param name="actionName">home_execute</param>
      </result>
    </action>

    ...

  </package>
</struts>

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5"
  xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

  <display-name>AppName</display-name>

  <context-param>
    <param-name>org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG</param-name>
    <param-value>/WEB-INF/config/tiles-def.xml</param-value>
  </context-param>

  <filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
    <init-param>
      <param-name>actionPackages</param-name>
      <param-value>com.domain.app.action</param-value>
    </init-param>
  </filter>

  <filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>*</url-pattern>
  </filter-mapping>

  <listener>
    <listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class>
  </listener>

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  ...

</web-app>

AuthenticationInterceptor.java:

public String intercept(ActionInvocation actionInvocation) throws Exception {
    Logger.debug(this, "intercept: Begin");
    boolean debug = Logger.canLogDebug(this);

    Map<String, Object> session = actionInvocation.getInvocationContext().getSession();

    User user = (User) session.get(Constants.SESSION_USER);
    if (user == null) {
        //This is the first time they are accessing the app.
        //Need to lookup the user and check functional entitlements.
        String employeeId = ServletActionContext.getRequest().getHeader(Constants.EMPLOYEE_ID);

        if (StringUtils.isNullOrEmpty(employeeId)) {
            Logger.warn(this, "No Employee ID in headers, access denied");
            return "denied";
        }

        try {
            Logger.debug(this, "Looking up User with employeeId " + employeeId);
            user = userDelegate.getUser(employeeId);
        } catch( Exception e) {
            Logger.error(this, "Exception looking up User with employeeId " + employeeId, e);
            return Action.ERROR;
        }

        if (user == null) {
            Logger.error(this, "User with employeeId " + employeeId + " was not found.");
            return "denied";
        }

        boolean hasFunction = false;
        for (FunctionalEntitlement function : FunctionalEntitlement.values()) {
            if (user.hasFunction(function)) {
                hasFunction = true;
                break;
            }
        }
        if (!hasFunction) {
            Logger.warn(this, "User " + employeeId +
                              " attempted to access App without an appropriate role.");
            return "denied";
        }

        session.put(Constants.SESSION_USER, user);
    }

    Action action = (Action)actionInvocation.getAction();
    if (action instanceof UserAware) {
        if (debug) {
            Logger.debug(this,
                    "Injecting user on the UserAware Action " +
                    action.getClass().getSimpleName());
        }

        ((UserAware)action).setUser(user);
    }

    if (debug) {
        Logger.debug(this,
                "calling ActionInvocation.invoke() for " +
                actionInvocation.getClass().getSimpleName());
    }
    String result = actionInvocation.invoke(); //****Line 156****
    if (debug) {
        Logger.debug(this, "ActionInvocation resultCode = " + actionInvocation.getResultCode());
        Logger.debug(this, "returning \"" + result + "\"");
        Logger.debug(this, "intercept: End");
    }
    return result;
}

AgreementInterceptor.java:

    private static final int DEFAULT_EXPIRE_DAYS = 182;
    private static final List<String> requiresAgreement;
    private static final Map<String, String> agreementUrls = new HashMap<String, String>();
    private static final Map<String, Integer> agreementExpireDays = new HashMap<String, Integer>();

    ...

    public String intercept(ActionInvocation actionInvocation) throws Exception {
        Logger.debug(this, "intercept: Begin");
        boolean debug = Logger.canLogDebug(this);

        Map<String, Object> session = actionInvocation.getInvocationContext().getSession();

        Boolean agreementAccepted = (Boolean)session.get(Constants.AGREEMENT_ACCEPTED_OR_NOT_NEEDED);
        if (agreementAccepted != null && agreementAccepted) {
            if (debug) {
                Logger.debug(this,
                        "calling (1) ActionInvocation.invoke() for " +
                        actionInvocation.getClass().getSimpleName());
            }
            String result = actionInvocation.invoke();
            if (debug) {
                Logger.debug(this, "User agreement previously accepted or not required");
                Logger.debug(this, "ActionInvocation resultCode = " + actionInvocation.getResultCode());
                Logger.debug(this, "returning \"" + result + "\"");
                Logger.debug(this, "intercept: End");
            }
            return result;
        }

        User user = (User) session.get(Constants.SESSION_USER);
        Role[] userRoles = user.getAllRoles();

rolechk:
        for (Role role : userRoles) {
            String roleCode = role.getRoleType();
            if (requiresAgreement.contains(roleCode)) {
                if (debug) {
                    Logger.debug(this, "Role " + roleCode + " requires a user agreement");
                    Logger.debug(this, "Checking last agreement acceptance date");
                }

                Integer numDays = agreementExpireDays.get(roleCode);
                if (numDays == null) {
                    Logger.error(this,
                            "intercept: No expire days for role code " + 
                            roleCode + ", defaulting to " + DEFAULT_EXPIRE_DAYS);
                    numDays = DEFAULT_EXPIRE_DAYS;
                }

                for (DynamicAttribute attr : user.getDynamicAttributes()) {
                    if (Constants.APP_AGREEMENT_DATE_TYPE.equals(attr.getAttrType())) {
                        Calendar currDate = Calendar.getInstance();
                        Calendar acceptDate = null;
                        String acceptDateStr = attr.getAttrValuesAsList().get(0);
                        if (StringUtils.isNullOrEmpty(acceptDateStr)) {
                            // Treat this situation as if the agreement was never accepted
                            Logger.error(this,
                                    Constants.APP_AGREEMENT_DATE_TYPE +
                                    " dynamic attribute not set for user " + user.getEmployeeId());
                            // Invoke AccessAgreementAction
                            if (debug) {
                                Logger.debug(this, "returning \"agreement\"");
                                Logger.debug(this, "intercept: End");
                            }
                            return "agreement"; 
                        }

                        try {
                            acceptDate = Calendar.getInstance();
                            acceptDate.setTime(
                                  Constants.AGREEMENT_DATE_FORMAT.parse(acceptDateStr));
                            // The user acceptance expires numDays from the date of previous
                            // acceptance regardless of the time of day that the acceptance
                            // was executed
                            acceptDate.set(Calendar.HOUR_OF_DAY, 0);
                            acceptDate.set(Calendar.MINUTE, 0);
                            acceptDate.set(Calendar.SECOND, 0);
                            acceptDate.set(Calendar.MILLISECOND, 0);
                            acceptDate.add(Calendar.DATE, numDays);
                            if (currDate.before(acceptDate)) {
                                if (debug) {
                                    Logger.debug(this,
                                            "Prior acceptance date " + acceptDateStr +
                                            " for " + user.getEmployeeId() + 
                                            " is still valid");
                                }
                                // Agreement accepted recently, continue with action
                                break rolechk;
                            }
                        } catch (ParseException e) {
                            // Treat this situation as if the agreement was never accepted
                            Logger.error(this,
                                    "Found invalid " +
                                    Constants.APP_AGREEMENT_DATE_TYPE +
                                    " \"" + acceptDateStr + "\" for " + user.getEmployeeId());
                        }
                    }
                }
                // Need user to accept App User Agreement
                String agreementUrl = agreementUrls.get(roleCode);
                if (StringUtils.isNullOrEmpty(agreementUrl)) {
                    Logger.error(this,
                            "No agreement URL found for role " + roleCode +
                            ", treating as if agreement is not required");
                    break rolechk;
                }

                session.put(Constants.AGREEMENT_DOC_URL, agreementUrl);
                session.put(Constants.AGREEMENT_ROLE_CODE, roleCode);

                // Invoke AccessAgreementAction
                if (debug) {
                    Logger.debug(this, "agreementUrl = " + agreementUrl);
                    Logger.debug(this, "roleCode     = " + roleCode);
                    Logger.debug(this, "returning \"agreement\"");
                    Logger.debug(this, "intercept: End");
                }
                return "agreement"; 
            }
        }

        // User agreement not required, or previous acceptance is still valid.
        // Note that fact in the session.
        session.put(Constants.AGREEMENT_ACCEPTED_OR_NOT_NEEDED, Boolean.TRUE);
        if (debug) {
            Logger.debug(this,
                    "calling (2) ActionInvocation.invoke() for " +
                    actionInvocation.getClass().getSimpleName());
        }
        String result = actionInvocation.invoke();
        if (debug) {
            Logger.debug(this, "ActionInvocation resultCode = " + actionInvocation.getResultCode());
            Logger.debug(this, "returning \"" + result + "\"");
            Logger.debug(this, "intercept: End");
        }
        return result;
    }

Log file content:

2017-12-14 15:33:27,375|DEBUG |m.domain.app.interceptor.AuthenticationInterceptor|intercept: Begin
2017-12-14 15:33:27,375|DEBUG |m.domain.app.interceptor.AuthenticationInterceptor|Looking up user with employeeId E111385
2017-12-14 15:33:29,623|DEBUG |m.domain.app.interceptor.AuthenticationInterceptor|Injecting user on the UserAware Action com.domain.app.action.HomeAction
2017-12-14 15:33:29,623|DEBUG |m.domain.app.interceptor.AuthenticationInterceptor|calling ActionInvocation.invoke() for DefaultActionInvocation
2017-12-14 15:33:29,628|DEBUG |   com.domain.app.interceptor.AgreementInterceptor|intercept: Begin
2017-12-14 15:33:29,628|DEBUG |   com.domain.app.interceptor.AgreementInterceptor|Role BASIC_USER requires a user agreement
2017-12-14 15:33:29,628|DEBUG |   com.domain.app.interceptor.AgreementInterceptor|Checking last agreement acceptance date
2017-12-14 15:33:29,628|DEBUG |   com.domain.app.interceptor.AgreementInterceptor|agreementUrl = https://server.domain.com/userdocs/agreement.pdf
2017-12-14 15:33:29,629|DEBUG |   com.domain.app.interceptor.AgreementInterceptor|roleCode     = BASIC_USER
2017-12-14 15:33:29,629|DEBUG |   com.domain.app.interceptor.AgreementInterceptor|returning "agreement"
2017-12-14 15:33:29,629|DEBUG |   com.domain.app.interceptor.AgreementInterceptor|intercept: End
2017-12-14 15:33:29,678|ERROR |            jsp_servlet._public._jsp.__systemerror|java.lang.IllegalStateException: Response already committed
    at weblogic.servlet.internal.ServletResponseImpl.objectIfCommitted(ServletResponseImpl.java:1553)
    at weblogic.servlet.internal.ServletResponseImpl.sendRedirect(ServletResponseImpl.java:838)
    at org.apache.struts2.dispatcher.ServletRedirectResult.sendRedirect(ServletRedirectResult.java:257)
    at org.apache.struts2.dispatcher.ServletRedirectResult.doExecute(ServletRedirectResult.java:229)
    at org.apache.struts2.dispatcher.StrutsResultSupport.execute(StrutsResultSupport.java:191)
    at org.apache.struts2.dispatcher.ServletRedirectResult.execute(ServletRedirectResult.java:164)
    at org.apache.struts2.dispatcher.ServletActionRedirectResult.execute(ServletActionRedirectResult.java:182)
    at com.opensymphony.xwork2.DefaultActionInvocation.executeResult(DefaultActionInvocation.java:369)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:273)
==> at com.domain.app.interceptor.AuthenticationInterceptor.intercept(AuthenticationInterceptor.java:156)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at org.apache.struts2.interceptor.DeprecationInterceptor.intercept(DeprecationInterceptor.java:41)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:256)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:167)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265)
    at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:76)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:229)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:229)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:191)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:73)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at org.apache.struts2.interceptor.DateTextFieldInterceptor.intercept(DateTextFieldInterceptor.java:125)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:91)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:253)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:139)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:193)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:189)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:167)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at org.apache.struts2.json.JSONValidationInterceptor.doIntercept(JSONValidationInterceptor.java:116)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265)
    at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:76)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at org.apache.struts2.interceptor.DeprecationInterceptor.intercept(DeprecationInterceptor.java:41)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:229)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:229)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:73)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at org.apache.struts2.interceptor.DateTextFieldInterceptor.intercept(DateTextFieldInterceptor.java:125)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:91)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:189)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54)
    at org.apache.struts2.components.ActionComponent.executeAction(ActionComponent.java:288)
    at org.apache.struts2.components.ActionComponent.end(ActionComponent.java:172)
    at org.apache.struts2.views.jsp.ComponentTagSupport.doEndTag(ComponentTagSupport.java:43)
    at jsp_servlet.__index._jsp__tag0(__index.java:106)
    at jsp_servlet.__index._jspService(__index.java:70)
    at weblogic.servlet.jsp.JspBase.service(JspBase.java:35)
    at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
    at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
    at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
    at weblogic.servlet.internal.ServletStubImpl.onAddToMapException(ServletStubImpl.java:409)
    at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:318)
    at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:27)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:43)
    at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:96)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:43)
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3496)
    at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
    at weblogic.security.service.SecurityManager.runAs(Unknown Source)
    at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2180)
    at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2086)
    at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1406)
    at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
    at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)

2017-12-14 15:33:29,678|ERROR |            jsp_servlet._public._jsp.__systemerror|Response already committed
Mike M
  • 43
  • 1
  • 6
  • I must be thick as a whale omelette, but I don't see how the linked question and its answer relate to my question. I am not uploading or downloading a file. I'm returning an "agreement" response, so returning Action.NONE is not an option. I do not see where in the above my response is already committed (this is probably my flaw, but I don't see it). When the AuthenticationInterceptor returns "denied" and when the AgreementInterceptor returns the result from ActionInvocation.invoke() there is no error. – Mike M Dec 17 '17 at 17:42
  • I believe the issue must be in my struts.xml. I updated AgreementInterceptor.intercept to immediately return "agreement" and the issue persisted. I made sure "agreement" isn't some sort of special word by changing the return value to "appAgreementRequired" in the interceptor and in struts.xml, but the problem persisted. I then changed the AgreementInterceptor to immediately return "denied" and the app acted correctly, showing the access denied page. – Mike M Dec 18 '17 at 14:42
  • Did I not respond correctly to Roman C? Is Roman C's marking of this question as a duplicate the last word? Is there something I missed in the question linked to by Roman C? – Mike M Dec 19 '17 at 13:52
  • @Roman C you got some feedback from the OP – fedorqui Jan 29 '18 at 15:03
  • I added a comment saying someone else can add the answer I found. But really, I should do it when an answer can be added. Sorry. I'm kind of frustrated. – Mike M Jan 29 '18 at 19:47
  • @fedorqui It makes no sense the question is off-topic. I've closed it as duplicate because there's already a good answer to this problem. – Roman C Jan 29 '18 at 23:49
  • [Roman C](https://stackoverflow.com/users/573032/roman-c), your "good answer" assumes that the ServletResponse was closed or committed by the developer's code. My code does not touch the response. While waiting, I have discovered that on WebLogic 10.3.x (x=0, 5 or 6) running on Linux that the ServletResponse is committed when the Interceptor.intercept method is entered. This does not occur in WebLogic 10.3.x running on Windows. I'm working on opening a bug report with Oracle. You are incorrect that your linked question answers my issue. – Mike M Jan 30 '18 at 14:21
  • If I am wrong, then please enlighten me. – Mike M Jan 30 '18 at 14:37
  • [Roman C](https://stackoverflow.com/users/573032/roman-c), If my question is off topic then can you suggest a better forum? – Mike M Jan 30 '18 at 21:40
  • @Mike It's not a forum. SO is Q/A site. If you need to learn more see [help](/help). – Roman C Jan 31 '18 at 01:18
  • Fine, I'm done. My comment about what I found will have to stand as the answer for this question because you can't possibly be wrong. – Mike M Jan 31 '18 at 17:44
  • And, you can't be bothered to explain to me where I'm wrong. – Mike M Jan 31 '18 at 17:55
  • Why should I bothering you where you ate wrong? You should do it yourself. – Roman C Feb 03 '18 at 23:20
  • As I said on 12/17, "I don't see how the linked question and its answer relate to my question. I am not uploading or downloading a file. I'm returning an "agreement" response, so returning Action.NONE is not an option. I do not see where in the above my response is already committed (this is probably my flaw, but I don't see it). When the AuthenticationInterceptor returns "denied" and when the AgreementInterceptor returns the result from ActionInvocation.invoke() there is no error." I've addressed every point in the answer that you identify. I do not see how your answer addresses my question. – Mike M Feb 04 '18 at 19:33
  • And, since then I've determined that the problem is probably a bug in WebLogic 10.3.x. I could be wrong, but I don't see where my mistake is. – Mike M Feb 04 '18 at 19:34
  • To be precise, there is probably a bug in WebLogic 10.3.x running on Linux. The problem does not occur in WebLogic 10.3.x running on Windows. BTW, x=0, 5, or 6. Those are the versions that we run at my location. – Mike M Feb 04 '18 at 19:49

0 Answers0