@Stateless vs @RequestScoped

时间:2013-12-13 02:34:29

标签: java java-ee jax-rs

我正在学习使用JAX-RS进行一些安静的api开发,并且我的资源类有问题。

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

如果我将我的资源类更改为无状态,那么一切都很好,实体管理器可以保持没有任何问题。

我还是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();

    }
}

2 个答案:

答案 0 :(得分:13)

Matthias就是现场。

@Stateless带注释的bean是一个EJB,默认情况下提供Container-Managed-Transactions。如果EJB的客户端没有提供新事务,CMT将默认创建一个新事务。

  

必需属性如果客户端在事务中运行,并且   调用企业bean的方法,该方法在   客户的交易。如果客户端没有与之关联   在事务中,容器在运行之前启动一个新事务   方法

     

Required属性是所有人的隐式事务属性   使用容器管理的事务运行的企业bean方法   划界。除非您通常不设置Required属性   您需要覆盖另一个事务属性。因为   事务属性是声明性的,您可以轻松地更改它们   后面。

在最近的jax-rs上的java-ee-7 tuturial中,Oracle有使用EJB的例子(@Stateless)。

  

...... EJB的@ javax.ejb.Asynchronous注释和。的组合   @Suspended AsyncResponse启用异步执行   业务逻辑,最终通知感兴趣的客户。   任何JAX-RS根资源都可以使用@Stateless或注释   @Singleton注释,实际上可以作为EJB ..

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

答案 1 :(得分:3)

如果您不想将根源作为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;
}