2013-05-13 50 views
5

想象一下,您有一个过滤器,用于启动数据库事务,处理请求,然后尝试提交事务。你能用JAX-RS/Jersey做传统的Servlet过滤吗?

doFilter(...) { 
    ... 
    transaction.begin(); 
    filterChain.doFilter(request, response); 
    transaction.commit(); 
} 

使用泽西,也存在一些问题:

  1. 使用过滤器,泽西Servlet容器提交/刷新执行返回到过滤器,然后响应。因此,如果提交失败,则无法将返回码修​​改为失败。此外,异常不会被JAX-RS ExceptionMapper捕获。
  2. 使用ContainerRequestFilter/ContainerResponseFilter。

    公共ContainerRequest滤波器(ContainerRequest请求){ ... }
    公共ContainerResponse滤波器(ContainerRequest请求,响应ContainerResponse){ ... }

这允许例外冒泡到一个ExceptionMapper,但是将逻辑分成两个独立的方法/接口。问题是如果有一个异常没有映射到响应,那么ContainerResponseFilter永远不会被调用,所以你无法清理。

在JAX-RS环境中处理这种情况的首选方法是什么?有没有办法配置刷新响应,还是有我忽略的类或接口?

+0

您描述的内容通常称为“开放会议”(反)模式。请参阅[此SO问题](http://stackoverflow.com/q/1103363/131929)进行讨论。还请转到JBoss(Hibernate/Seam)以获得更多讨论,例如https://community.jboss.org/docs/DOC-13954 – 2013-05-13 21:07:02

+0

对于“视图”究竟构成了什么,肯定存在一些争议,但这只是一个REST应用程序。 jax-rs资源方法是服务层,它们直接使用持久性。响应对象是服务调用的结果。我试图避免在每种方法中都进行事务管理,答案或者是类似于过滤器的东西,或者是我连接CDI拦截(如果可以的话,我希望在此项目中避免这种情况)。 – Shaun 2013-05-14 09:38:13

回答

3

我一直在研究这一点以及JAX-RS/RESTEasy应用程序。这两个选项我正在考虑读这个问题之前:

  1. 写一个ExceptionMapper<Throwable>(或ExceptionMapper<DaoException>使用自定义DaoException),并处理它有或将获得因为ExceptionMapper<?>处理所有异常的执行ContainerResponseFilter
  2. transaction.begin()之前,请检查事务的当前状态,并在需要时回滚到那里。

这两个选项都存在问题。

  1. 我找到一个ExceptionMapper<Throwable>太广,而ExceptionMapper<DaoException>可能会错过一些其他异常,再次离开交易没有清理。
  2. 在下一个请求中回滚事务可能需要很长时间,可能会导致其他事务的锁定问题。

所以阅读您的问题后,我正在想:

  • 使用ContainerRequestFilter开始交易(与@NameBinding注解建设相结合)。
  • 使用ContainerResponseFilter来提交事务(如果资源方法尚未关闭它)。
  • 使用Filter确保交易已关闭,如果没有,请将其回滚。
+0

你是指“ExceptionMapper太宽泛”?如果您只是在ExceptionMapper 中检查活动事务的会话,则可以确定出现问题并回滚。如果没有活动的交易,什么都不做。 我看到的问题是,如果在ContainerResponseFilter中transaction.commit()失败,则必须更改响应对象。不知道如果在ContainerResponseFilter中抛出异常会发生什么情况,它是否会被ExceptionMapper捕获? – joscarsson 2013-10-09 21:01:56

+0

太宽泛了,您可能也有一个'ExceptionMapper '。哪个'ExceptionMapper '将处理异常?首先是'SpecificException',然后是'Throwable'?或者后者是否会吞下'SpecificException'? – drvdijk 2013-10-10 17:08:31