2013-12-13 6 views
11

uczę się korzystać z JAX-RS jakiegoś spokojnego rozwoju API i mieć problem odnośnie klas moich zasobów.@Stateless vs @RequestScoped

Rozumiem, że moja klasa zasobów powinna być RequestScoped, jednak , gdy jest RequestScoped moje wezwanie do metody trwałej menedżera encji, wyrzuca wyjątek TransactionRequiredException.

Jeśli zmienię moją klasę zasobów być Stateless wtedy wszystko jest w porządku i kierownik podmiotu może utrzymywać się bez problemu.

wciąż jestem nowy na JavaEE i chcieliby wiedzieć, dlaczego tak się dzieje i co robi @Stateless adnotacji, który pozwala kontekst wytrwałość wstrzyknąć poprawnie. Chciałbym również wiedzieć, czy istnieje jakiś problem z klasami zasobów JAX-RS będącymi bezstanowymi, zamiast z RequestScoped, ponieważ większość samouczków, które widziałem, ma je.

I zawierały przykładzie poniżej dla zilustrowania.

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

    } 
} 
+4

myślę, że jeśli masz Stateless Bean i dont używać Adnotacje np transakcyjne (wymagane) Twój ApplicationServer zamierza stosować w oparciu transakcja na jego EJB. Zażądaj Scoped Beans znajdują się w Servlet Container, który nie zapewnia transakcji opartych na kontenerach (myślę). –

Odpowiedz

8

Matthias jest na miejscu.

@Stateless opisywane fasola EJB który normalnie stanowi Container-Managed-Transactions. CMT domyślnie utworzy nową transakcję, jeśli klient EJB jej nie dostarczył.

wymagany atrybut Jeśli klient jest uruchomiony w ramach transakcji i wywołuje metodę fasoli przedsiębiorstwa, metoda wykonuje w ciągu transakcji w klienta. Jeśli klient nie jest powiązany z transakcją , kontener rozpoczyna nową transakcję przed uruchomieniem metody .

Wymagany atrybut jest niejawnym atrybutem transakcji dla wszystkich metod komponentu EJB z , obsługiwanych za pomocą zarządzanej kontenera transakcji . Zazwyczaj nie ustawia się wymaganego atrybutu, chyba że trzeba zastąpić inny atrybut transakcji. Ponieważ atrybuty transakcji są deklaratywne, można je później łatwo zmienić .

W ostatnim Java-ee-7 tuturial na JAX Rs, Oracle przykład z wykorzystaniem EJB (@Stateless).

... kombinacja adnotacji @ javax.ejb.Asynchronous EJB i @Suspended AsyncResponse umożliwia asynchroniczne wykonanie logiki biznesowej z ewentualnym powiadomieniu zainteresowanego klienta. żadnej grani JAX zasobem-R mogą być opatrzone @Stateless lub @Singleton opisów i może, w rzeczywistości, działać jako EJB ..

Główna różnica pomiędzy @RequestScoped vs @Stateless w tym przypadku będzie to, że pojemnik może łączyć EJB i unikać kosztownych operacji konstruowania/niszczenia, które mogą być potrzebne dla ziaren, które w innym przypadku byłyby budowane na każde żądanie.

+0

Co jest lepsze, a co bardziej skuteczne w odniesieniu do wydajności? To powinno być @Stateless, ponieważ jest możliwe do połączenia, prawda? Jaką wadę ma to w przypadku resouce? - Byłbym szczęśliwy, gdybyś mógł uwzględnić ten aspekt w swojej odpowiedzi - dzięki! Już wcześniej głosowałem z góry ... :) – badera

+0

Wątpię, czy zauważysz jakiekolwiek różnice w życiu w odniesieniu do wydajności tutaj. Teoretycznie, jeśli budowa fasoli jest kosztowna, zacznie działać połączenie. Jeśli używasz EJB i CMT w swojej aplikacji, użyj tego, ponieważ kod jest mniej szczegółowy –

2

Gdy nie chcesz, aby zasób główny był EJB (poprzez przypisanie go do numeru @Stateless), możesz użyć wartości 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; 
}