@Stateless vs @RequestScoped
Я изучаю использование 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();
}
}
Ответы
Ответ 1
Маттиас находится на месте.
A @Stateless annotated bean - это EJB, который по умолчанию предоставляет Контейнер-управляемые транзакции. CMT по умолчанию создаст новую транзакцию, если клиент EJB не предоставил ее.
Обязательный атрибут. Если клиент работает в транзакции и вызывает метод предприятия bean s, метод выполняется в пределах клиентов. Если клиент не связан с транзакции, контейнер запускает новую транзакцию перед запуском Метод.
Обязательный атрибут - это неявный атрибут транзакции для всех enterprise bean методы, выполняемые с транзакцией, управляемой контейнером демаркация. Обычно вы не устанавливаете атрибут Required, если вам необходимо переопределить другой атрибут транзакции. Потому как атрибуты транзакций являются декларативными, их можно легко изменить позже.
В недавнем java-ee-7 tuturial на jax-rs у Oracle есть пример использования EJB (@Stateless).
... комбинация EJB @javax.ejb.Асинхронная аннотация и @Suspended AsyncResponse позволяет асинхронное выполнение бизнес-логику с возможным уведомлением заинтересованного клиента. Любой корневой ресурс JAX-RS можно аннотировать с помощью @Stateless или @Singleton и может, по сути, функционировать как EJB..
Основное различие между @RequestScoped vs @Stateless в этом сценарии будет состоять в том, что контейнер может объединить EJB и избежать некоторых дорогостоящих операций построения/уничтожения, которые могут потребоваться для beans, которые в противном случае были бы построены для каждого запроса.
Ответ 2
Если вы не хотите, чтобы ваш корневой ресурс был 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;
@Resuorce
private transient UserTransaction ut;
@Context
private transient UriInfo uriInfo;
}