Java @Stateless 与 @RequestScoped

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20558125/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 02:48:08  来源:igfitidea点击:

@Stateless vs @RequestScoped

javajakarta-eejax-rs

提问by Bltucker

I am learning to use JAX-RS for some restful api development and have an issue regarding my resource classes.

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

My understanding is that my resource class should be RequestScoped, however, when it is RequestScoped my call to the entity manager's persist method it throws a TransactionRequiredException.

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

If I change my resource class to be Stateless then everything is fine and the entity manager can persist without any issue.

如果我将我的资源类更改为无状态,那么一切都很好,实体管理器可以毫无问题地坚持下去。

I am still new to JavaEE and would like to know why this happens and what the @Stateless annotation does that allows the persistence context to inject correctly. I would also like to know if there is any problem with JAX-RS resource classes being stateless instead of RequestScoped as most of the tutorials I've seen have them.

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

I have included some example code below to illustrate.

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

@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();

    }
}

采纳答案by Aksel Willgert

Matthias is spot on.

马蒂亚斯就在现场。

A @Stateless annotated bean is an EJB which by default provides Container-Managed-Transactions. CMT will by default create a new transaction if the client of the EJB did not provide one.

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

Required AttributeIf the client is running within a transaction and invokes the enterprise bean's method, the method executes within the client's transaction. If the client is not associated with a transaction, the container starts a new transaction before running the method.

The Required attribute is the implicit transaction attribute for all enterprise bean methods running with container-managed transaction demarcation. You typically do not set the Required attribute unless you need to override another transaction attribute. Because transaction attributes are declarative, you can easily change them later.

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

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

In the recent java-ee-7 tuturialon jax-rs, Oracle has example of using EJBs (@Stateless).

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

... the combination of EJB's @javax.ejb.Asynchronous annotation and the @Suspended AsyncResponse enables asynchronous execution of business logic with eventual notification of the interested client. Any JAX-RS root resource can be annotated with @Stateless or @Singleton annotations and can, in effect, function as an EJB ..

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

Main difference between @RequestScoped vs @Stateless in this scenario will be that the container can pool the EJBs and avoid some expensive construct/destroy operations that might be needed for beans that would otherwise be constructed on every request.

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

回答by Jin Kwon

When you don't want to make your root resource as an EJB (by annotating it with @Stateless), you can use a UserTransaction.

当您不想将根资源设为 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;
}