2

私が今日経験した問題があります。Hibernateトランザクションを開始してコミットするインターセプターがあり、コミット時に例外がスローされる場合があります(org.hibernate.StaleObjectStateExceptionたとえば)。つまり、例外をスローすることはできますが、例外はハンドラーに到達しません。コードに問題があると思いました。しかし、それから私は簡単なテストを書きました、そしてここにそれはあります

のパッケージ定義struts.xml

<package name="basicstruts2" namespace="/" extends="struts-default">
    <interceptors>
        <interceptor name="dummy" class="test.TestInterceptor"/>

        <interceptor-stack name="myStack">
            <interceptor-ref name="defaultStack" />
            <interceptor-ref name="dummy" />
        </interceptor-stack>
    </interceptors>

    <default-interceptor-ref name="myStack"/>

    <global-results>
        <result name="exception" type="chain">exceptionHandler</result>
    </global-results>

    <global-exception-mappings>
        <exception-mapping exception="java.lang.Exception" result="exception" />
    </global-exception-mappings>

    <action name="test" class="test.TestAction">
        <result>result.jsp</result>
    </action>

    <action name="exceptionHandler" class="test.ExceptionHandler">
        <result>DebugErrorPage.jsp</result>
    </action>
</package>

TestAction.java

package test;

public class TestAction extends ActionSupport {

    private BusinessLogic logic = new BusinessLogic();

    public String execute() {
        logic.test();
        return SUCCESS;
    }
}

TestInterceptor.java

package test;

public class TestInterceptor implements Interceptor {

    @Override
    public String intercept(ActionInvocation arg0) throws Exception {
        String result = null;
        try {
            result = arg0.invoke();
            boolean flag = true;
            if (flag) throw new RuntimeException("qwerty");
        } catch (Exception e) {
            System.out.println("exception catched in interceptor, rethrowing " + e);
            throw e;
        }
        return result;
    }

}

ExceptionHandler.java

package test;

public class ExceptionHandler extends ActionSupport {

    private Exception exception;

    public void setException(Exception e) {
        exception = e;
        System.out.println("setting exception");
    }

    public String execute() {
        System.out.println("exeption in handler " + exception);
        return SUCCESS;
    }

}

BusinessLogic.java

package test;

public class BusinessLogic {
    public void test() {
        System.out.println("test logic");
//      boolean flag = true;
//      if (flag) throw new RuntimeException("qwerty");
    }
}

したがって、コンソール出力:

test logic
exception catched in interceptor, rethrowing java.lang.RuntimeException: qwerty

ただし、BusinnesLogicによって例外がスローされた場合は、コードのコメントを解除できます。

BusinessLogic.java

package test;

public class BusinessLogic {
    public void test() {
        System.out.println("test logic");
        boolean flag = true;
        if (flag) throw new RuntimeException("qwerty");
    }
}

インターセプターのコードをコメントアウトします。

@Override
        public String intercept(ActionInvocation arg0) throws Exception {
            String result = null;
            try {
            result = arg0.invoke();
        //  boolean flag = true;
        //  if (flag) throw new RuntimeException("qwerty");
            } catch (Exception e) {
                System.out.println("exception catched in interceptor, rethrowing " + e);
                throw e;
            }
            return result;
        }

出力は次のようになります。

test logic
exception catched in interceptor, rethrowing java.lang.RuntimeException: qwerty
setting exception
exeption in handler java.lang.RuntimeException: qwerty

そして、エラーページが表示されます。

それで、誰かがこの振る舞いについて良い説明をすることができますか?他のインターセプターによってスローされた例外を処理できない場合、デフォルトのストラットスタックの一番上に例外インターセプターを配置する意味は何ですか?なぜ??良い答えをいただければ幸いです。

編集: 私が問題を抱えているコードがあります:

public String intercept(ActionInvocation arg0) throws Exception {
    String result = null;

    try {

        sf.getCurrentSession().beginTransaction();

        result = arg0.invoke();

        sf.getCurrentSession().getTransaction().commit();

    } catch (StaleObjectStateException staleEx) {
        if (sf.getCurrentSession().getTransaction().isActive()) {
            sf.getCurrentSession().getTransaction().rollback();
        }
        throw staleEx;

    } catch (Exception ex) {
        ex.printStackTrace();
        try {
            if (sf.getCurrentSession().getTransaction().isActive()) {
                sf.getCurrentSession().getTransaction().rollback();
            }
        } catch (Throwable rbEx) {
        }

        // Let others handle it... maybe another interceptor for exceptions?
        throw new ServletException(ex);
    }

    return result;
}

スローされた例外を処理したい場合はどうすればよいcommit()ですか?

4

2 に答える 2

3

例外は、アクションの呼び出しと結果のレンダリングのTestInterceptor にスローされます。

ライティングインターセプターページのメモから:

結果が呼び出された後(たとえば、JSPがレンダリングされた後)にinvokeが返されることに注意してください。これにより、ビュー内セッションのオープンパターンなどに最適です。結果が呼び出される前に何かを実行したい場合は、PreResultListenerを実装する必要があります。

于 2012-07-05T01:20:28.023 に答える
1

ExceptionMappingInterceptorのコア機能

このインターセプターは、例外処理機能のコア機能を形成します。例外処理を使用すると、予期しない例外をスローする代わりに、アクションが結果コードを返したかのように、例外を結果コードにマップできます。例外が発生すると、ExceptionHolderでラップされてスタックにプッシュされ、結果内から例外に簡単にアクセスできるようになります。注:構成ファイルでいつでも例外マッピングを構成できますが、このインターセプターがアクションのインターセプタースタックにない場合、構成は効果がありません。このインターセプターをスタックの最初のインターセプターにして、他のインターセプターによって引き起こされたものであっても、例外をキャッチするためのフルアクセスを確保することをお勧めします。

コード例:

   <xwork>
     <package name="default" extends="xwork-default">
         <global-results>
             <result name="error" type="freemarker">error.ftl</result>
         </global-results>

         <global-exception-mappings>
             <exception-mapping exception="java.lang.Exception" result="error"/>
         </global-exception-mappings>

         <action name="test">
             <interceptor-ref name="exception"/>
             <interceptor-ref name="basicStack"/>
             <exception-mapping exception="com.acme.CustomException" result="custom_error"/>
             <result name="custom_error">custom_error.ftl</result>
             <result name="success" type="freemarker">test.ftl</result>
         </action>
     </package>
   </xwork>
于 2012-07-05T00:22:13.027 に答える