私が今日経験した問題があります。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()
ですか?