@无状态与@RequestScoped



我正在学习使用JAX-RS进行一些restful api开发,但我的资源类存在问题。

我的理解是,我的资源类应该是RequestScoped,但是,当它被RequestScoped时,我对实体管理器的持久方法的调用会抛出TransactionRequiredException。

如果我将资源类更改为Stateless,那么一切都很好,并且实体管理器可以在没有任何问题的情况下持续存在。

我还是JavaEE的新手,我想知道为什么会发生这种情况,以及@Stateless注释是如何允许持久性上下文正确注入的。我还想知道JAX-RS资源类是无状态的,而不是我看过的大多数教程中的RequestScoped,是否有任何问题。

我在下面包含了一些示例代码来进行说明。

@Path("Things")
//@Stateless //works just fine when em.persist() is called
@RequestScoped //throws transactionrequiredexception when em.persist() is called
public class ThingsResource{
    @PersistenceContext(unitName = "persistenceUnitName")
    EntityManager em;

    public ThingsResource() { }
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public Response postThing(ThingDTO thing){
        ThingEntity newThing = new ThingEntity(thing);
        em.persist(newThing);
        em.flush();
        return Response.created(new URI("/" + newThing.getId()).build();
    }
}

Matthias在上

@Stateless注释bean是一个EJB,默认情况下它提供容器管理事务。如果EJB的客户端没有提供一个新事务,CMT将默认创建一个新的事务。

必需属性如果客户端在事务中运行,并且调用企业bean的方法,该方法在客户的交易。如果客户端未与事务,容器在运行方法

Required属性是所有使用容器管理事务运行的企业bean方法界线除非您需要覆盖另一个事务属性。因为事务属性是声明性的,您可以很容易地更改它们后来

在最近关于jax-rs的java-ee-7教程中,Oracle有使用EJB(@Stateless)的示例。

EJB的@javax.EJB.异步注释和@Suspended AsyncResponse允许异步执行业务逻辑,并最终通知感兴趣的客户端。任何JAX-RS根资源都可以用@Stateless或@Singleton注释,实际上可以充当EJB。。

在这种情况下,@RequestScoped和@Stateless之间的主要区别在于,容器可以池化EJB,并避免一些昂贵的构造/销毁操作,这些操作可能是在每个请求上构造的bean所需要的。

当您不想将根资源作为EJB(通过用@Stateless对其进行注释)时,可以使用UserTransaction

@Path("/things")
@RequestScoped
public class ThingsResource{
    @POST
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    public Response create(final Thing thing){
        utx.begin();
        em.joinTransaction();
        final ThingEntity thingEntity = new ThingEntity(thing);
        em.persist(thing);
        utx.commit();
        final URI uri = uriInfo.getAbsolutePathBuilder()
            .path(Long.toString(thingEntity.getId())).build();
        return Response.created(uri).build();
    }
    @PersistenceContext(unitName = "somePU")
    private transient EntityManager em;
    @Resource
    private transient UserTransaction ut;
    @Context
    private transient UriInfo uriInfo;
}

最新更新