Java EE 6 @ javax.annotation.ManagedBean vs @ javax.inject.Named vs @ javax.faces.ManagedBean

107

Czuję, że w specyfikacji Java EE 6 jest trochę bałaganu. Istnieje kilka zestawów adnotacji.

Mamy javax.ejbadnotacje takie jak @Statefuli @Statelessdo tworzenia EJB.

Istnieje również @javax.annotation.ManagedBeanmożliwość stworzenia zarządzanej fasoli.

Są adnotacje w javax.enterprise.contextjak @SessionScopedi @RequestScoped.

Co więcej, w pakiecie znajdują się również @ManagedBeani @SessionScoped/ @RequestScopedadnotacje javax.faces.bean.

Aby jeszcze bardziej skomplikować sprawę, przygotowaliśmy pakiet javax.injectz @Namedadnotacjami.

Czy ktoś mógłby opisać, jak są ze sobą spokrewnieni?

Gdzie mogę używać @EJB, @Injectalbo @ManagedProperywstrzyknąć innych ziaren?

Piotr Gwiazda
źródło
Zobacz też: stackoverflow.com/questions/4684112/…
Arjan Tijms

Odpowiedzi:

194

Przede wszystkim pozwolę sobie wyjaśnić:

Definicja zarządzanej fasoli : ogólnie zarządzana fasola to obiekt, którego cyklem życia (budowa, zniszczenie itp.) Zarządza pojemnik.

W Java ee mamy wiele kontenerów, które zarządzają cyklem życia ich obiektów, takich jak kontener JSF, kontener EJB, kontener CDI, kontener serwletów itp.

Wszystkie te kontenery działają jakby niezależnie, uruchamiają się podczas inicjalizacji serwera aplikacji i skanują klasy wszystkich artefaktów, w tym plików jar, ejb-jar, war i ear, w czasie wdrażania oraz gromadzą i przechowują niektóre metadane na ich temat, a następnie gdy potrzebujesz obiektu klasy w czasie wykonywania dadzą ci instancje tych klas, a po zakończeniu zadania, zniszczą je.

Możemy więc powiedzieć, że mamy:

  • Fasola zarządzana przez JSF
  • Fasola zarządzana przez CDI
  • Fasola zarządzana przez EJB
  • Nawet serwlety są zarządzanymi komponentami bean, ponieważ są tworzone i niszczone przez kontener, który jest kontenerem serwletów.

Więc kiedy widzisz słowo Managed Bean, powinieneś zapytać o kontekst lub typ tego (JSF, CDI, EJB itp.)

Następnie możesz zapytać, dlaczego mamy wiele z tych kontenerów: AFAIK, faceci z Java EE chcieli mieć framework do wstrzykiwania zależności, ale nie mogli zebrać wszystkich wymagań w jednej specyfikacji, ponieważ nie mogli przewidzieć przyszłych wymagań i stworzyli EJB 1.0, a następnie 2.0, potem 3.0, a teraz 3.1, ale celem EJB było tylko spełnienie niektórych wymagań (transakcje, rozproszony model komponentów itp.).

W tym samym czasie (równolegle) zdali sobie sprawę, że muszą również obsługiwać JSF, a następnie stworzyli fasolę zarządzaną przez JSF i inny kontener dla fasoli JSF i uznali to za dojrzały kontener DI, ale nadal nie był to kompletny i dojrzały kontener.

Potem Gavin King i kilku innych sympatycznych gości;) stworzył CDI, który jest najbardziej dojrzałym kontenerem DI, jaki widziałem. CDI (zainspirowane przez Seam2, Guice i Spring) zostało stworzone, aby wypełnić lukę między JSF i EJB i wieloma innymi przydatnymi rzeczami, takimi jak wtrysk pojo, metody producenta, przechwytywacze, dekoratory, integracja SPI, bardzo elastyczny itp. I może nawet to zrobić co robią fasola zarządzana przez EJB i JSF, możemy mieć tylko jeden dojrzały i potężny kontener DI. Ale z pewnych wstecznej kompatybilności i powodów politycznych, faceci Java EE chcą je zachować !!!

Tutaj możesz znaleźć różnice i przypadki użycia dla każdego z tych typów:

Fasola zarządzana JSF, fasola CDI i EJB

JSF został początkowo opracowany z własnym mechanizmem zarządzanego komponentu bean i wstrzykiwania zależności, który został ulepszony dla JSF 2.0 w celu uwzględnienia komponentów bean opartych na adnotacjach. Kiedy CDI został wydany z Java EE 6, był uważany za zarządzany framework bean dla tej platformy i oczywiście EJB przestarzał je wszystkie, ponieważ były dostępne od ponad dekady.

Problem polega oczywiście na tym, aby wiedzieć, którego użyć i kiedy ich używać.

Zacznijmy od najprostszej, zarządzanej fasoli JSF.

Fasola zarządzana JSF

Krótko mówiąc, nie używaj ich, jeśli tworzysz dla Java EE 6 i używasz CDI. Zapewniają prosty mechanizm wstrzykiwania zależności i definiowania komponentów bean wspierających dla stron internetowych, ale są znacznie mniej wydajne niż fasole CDI.

Można je zdefiniować za pomocą @javax.faces.bean.ManagedBeanadnotacji, która przyjmuje opcjonalny parametr nazwy. Tej nazwy można użyć do odniesienia do ziarna ze stron JSF.

Zakres można zastosować do komponentu bean przy użyciu jednego z różnych zakresów zdefiniowanych w javax.faces.beanpakiecie, które obejmują żądanie, sesję, aplikację, widok i niestandardowe zakresy.

@ManagedBean(name="someBean")
@RequestScoped
public class SomeBean {
    ....
    ....
}

Ziarna JSF nie mogą być mieszane z innymi rodzajami ziaren bez jakiegoś ręcznego kodowania.

Fasola CDI

CDI to platforma do zarządzania komponentami bean i wstrzykiwania zależności, która została wydana jako część Java EE 6 i zawiera kompletne, kompleksowe narzędzie do zarządzania komponentami bean. Fasola CDI jest znacznie bardziej zaawansowana i elastyczna niż prosta fasola zarządzana przez JSF. Potrafią posługiwać się przechwytywaczami, zakresem konwersacji, zdarzeniami, bezpiecznym wtryskiem typu, dekoratorami, stereotypami i metodami producenta.

Aby wdrożyć komponenty bean CDI, należy umieścić plik o nazwie beans.xml w folderze META-INF w ścieżce klas. Gdy to zrobisz, każda fasola w opakowaniu stanie się ziarnem CDI. W CDI jest wiele funkcji, zbyt wiele, aby je tutaj omówić, ale jako szybkie odniesienie do funkcji podobnych do JSF, możesz zdefiniować zakres komponentu bean CDI za pomocą jednego z zakresów zdefiniowanych w javax.enterprise.contextpakiecie (a mianowicie żądanie, rozmowa , zakresy sesji i aplikacji). Jeśli chcesz użyć fasoli CDI ze strony JSF, możesz nadać jej nazwę za pomocą javax.inject.Namedadnotacji. Aby wstrzyknąć ziarno do innego ziarna, należy opisać pole javax.inject.Injectadnotacją.

@Named("someBean")
@RequestScoped
public class SomeBean {

    @Inject
    private SomeService someService;
}

Automatyczne wstrzykiwanie, takie jak zdefiniowane powyżej, można kontrolować za pomocą kwalifikatorów, które mogą pomóc w dopasowaniu określonej klasy, którą chcesz wstrzyknąć. Jeśli masz wiele typów płatności, możesz dodać kwalifikator określający, czy jest on asynchroniczny, czy nie. Chociaż możesz użyć @Namedadnotacji jako kwalifikatora, nie powinieneś, ponieważ jest ona przewidziana dla ujawniania fasoli w EL.

CDI obsługuje wstrzykiwanie ziaren o niedopasowanych zakresach za pomocą serwerów proxy. Z tego powodu można wstrzyknąć komponent bean o zasięgu żądania do komponentu bean o zasięgu sesji, a odwołanie będzie nadal ważne dla każdego żądania, ponieważ dla każdego żądania serwer proxy ponownie łączy się z aktywnym wystąpieniem komponentu bean o zasięgu żądania.

CDI obsługuje również przechwytywacze, zdarzenia, nowy zakres konwersacji i wiele innych funkcji, co czyni go znacznie lepszym wyborem niż fasolki zarządzane przez JSF.

EJB

EJB są starsze niż fasole CDI i są w pewnym sensie podobne do fasoli CDI, a pod innymi względami bardzo się różnią. Przede wszystkim różnice między fasolami CDI i EJB polegają na tym, że EJB to:

  • Transakcyjne
  • Zdalnie lub lokalnie
  • Potrafi pasywować stanowe fasole, zwalniając zasoby
  • Potrafi korzystać z timerów
  • Może być asynchroniczny

Te dwa typy EJB nazywane są bezpaństwowymi i stanowymi. Bezstanowe komponenty EJB można traktować jako bezpieczne wątkowo elementy bean jednorazowego użytku, które nie zachowują żadnego stanu między dwoma żądaniami sieci Web. Stanowe EJB zachowują stan i mogą być tworzone i pozostawać w pobliżu tak długo, jak są potrzebne, dopóki nie zostaną usunięte.

Definiowanie EJB jest proste, wystarczy dodać adnotację javax.ejb.Statelesslub javax.ejb.Statefuldo klasy.

@Stateless
public class BookingService {

  public String makeReservation(Item Item, Customer customer) {
    ...
    ...
  }
}

Bezstanowe komponenty bean muszą mieć zależny zakres, podczas gdy stanowe komponenty bean sesji mogą mieć dowolny zasięg. Domyślnie są to transakcje transakcyjne, ale można użyć adnotacji atrybutu transakcji.

Podczas gdy komponenty EJB i ziarna CDI są bardzo różne pod względem funkcji, pisanie kodu w celu ich integracji jest bardzo podobne, ponieważ ziarna CDI można wstrzyknąć do EJB, a EJB można wstrzyknąć do ziaren CDI. Nie ma potrzeby robienia rozróżnienia przy wstrzykiwaniu jednego do drugiego. Ponownie, różne zakresy są obsługiwane przez CDI przy użyciu proxy. Jedynym wyjątkiem jest to, że CDI nie obsługuje wstrzykiwania zdalnych EJB, ale można to zaimplementować, pisząc dla niego prostą metodę producenta.

javax.inject.NamedAdnotacji, jak również wszelkie kwalifikacje mogą być wykorzystane na EJB, aby dopasować go do punktu wtrysku.

Kiedy używać jakiej fasoli

Skąd wiesz, kiedy użyć której fasoli? Prosty.

Nigdy nie używaj fasoli zarządzanych przez JSF, chyba że pracujesz w kontenerze serwletów i nie chcesz próbować uruchomić CDI w Tomcat (chociaż istnieją na to archetypy Mavena, więc nie ma wymówki).

Ogólnie rzecz biorąc, powinieneś używać komponentów bean CDI, chyba że potrzebujesz zaawansowanych funkcji dostępnych w EJB, takich jak funkcje transakcyjne. Możesz napisać własny przechwytywacz, aby tworzyć transakcje ziaren CDI, ale na razie łatwiej jest używać EJB, dopóki CDI nie otrzyma transakcyjnych ziaren CDI, które są tuż za rogiem. Jeśli utkniesz w kontenerze serwletów i używasz CDI, wtedy albo ręcznie napisane transakcje, albo twój własny przechwytywacz transakcji jest jedyną opcją bez EJB.

Jeśli potrzebujesz użyć @ViewScopedw CDI, powinieneś

  • użyj powierzchni szwów lub modułu MyFaces CODI . po prostu dodaj jeden z nich do swojej ścieżki klas i @ViewScopedbędzie działać w CDI. MyFaces CODI ma jeszcze solidniejszą obsługę @ViewScoped
  • użyj MyFaces CODI @ViewAccessScoped, jest to rozszerzenie napisane na CDI przez Apache, po prostu pobierz i użyj @ViewAccessScopedadnotacji zamiast @ViewScoped.
  • Użyj CDI @ConversationScopedi spraw, by działało długo. Więcej informacji znajdziesz tutaj .
  • Użyj adnotacji Omnifaces @ViewScoped

Niektóre części okradano stąd .

Mehdi
źródło
3
To jest świetne! Dzięki! Aby zakończyć, po prostu powiedz, jak wstrzyknąć ziarno CDI lub EJB do fasoli JSF. Czy to @ManagedProperty("#{someBean})"właściwy sposób?
Piotr Gwiazda
2
Nie! to nie zadziała. wystarczy włączyć JSF zarządzanego fasoli do CDI udało fasoli przez opisywanie go za pomocą @Namedi @javax.enterprise.context.RequestScopedi stosowanie wtrysku CDI korzystając @Inject adnotacji. nie używaj zarządzanych fasoli jsf, jeśli nie musisz;).
Mehdi
3
> Chłopaki JEE chcą je zatrzymać !!! - To jest trochę bardziej subtelne. CDI zakończyło się dość późno w cyklu Java EE 6 i oba JSF 2 i JAX-RS były już gotowe. Wzmocnili resp. wprowadzili już własny, zarządzany zakład fasoli. Gdyby CDI był dostępny trochę wcześniej, mogłoby to wyglądać inaczej. W Java EE 7 JSF przyjmie CDI, a javax.faces.bean zostanie ostatecznie przestarzały (jednak przestarzały proces w Java EE jest powolny, co jest zarówno dobre, jak i złe).
Arjan Tijms
3
Kiedy mówisz: Aby wdrożyć fasolę CDI, musisz umieścić plik o nazwie beans.xml w folderze META-INF w ścieżce klas. Gdy to zrobisz, każda fasola w opakowaniu stanie się ziarnem CDI. Czy masz na myśli, że każda fasola staje się także ziarnem CDI oprócz tego, czym była? Co jeśli mam JSF ManagedBeans z ManagedBean i ViewScoped. Nadal są zarządzanymi fasolami JSF, prawda?
Koray Tugay
3
Ktoś może zrobić aktualizację dla Java EE 7 w tym świetnym artykule?
Martijn Burger
7

Tak, to może być mylące.

Dla niektórych Ehm względów historycznych JSF i CDI są przy użyciu tych samych adnotacje na teleskopach, ale z różnych pakietów.

Jak zapewne się domyślasz, te z javax.faces.beanpochodzą ze specyfikacji JSF i nie są związane z CDI. Nie używaj ich, chyba że masz ku temu dobry powód. I nigdy, przenigdy nie mieszaj ich z adnotacjami CDI od javax.ejb. Stworzy to niekończące się listy błędów i subtelnych anomalii.

Generalnie zalecam przejrzenie pierwszych kilku (lub nawet więcej) stron doskonałej dokumentacji spawania . To powinno skierować Cię na ścieżkę do Java EE 6.

Zachęcamy do zadawania dalszych pytań tutaj.

jan groth
źródło
Właściwie mam dwa pytania: 1. Często uważam, że zakres widoku jest bardzo przydatny. Muszę więc używać adnotacji JSF? 2. Oznacza to, że @javax.annotation.ManagedBeanjest to bezużyteczne, ponieważ CDI traktuje wszystkie klasy jako fasolki zarządzane, mam rację?
Piotr Gwiazda
Nie do końca. Będziesz musiał połączyć zakresy JSF z CDI za pomocą np. Seam Faces. I tak, @ManagedBeans nie są potrzebne, jeśli masz plik beans.xml w odpowiednim pliku jar. Aha, a jeśli masz dalsze pytania, lepiej rozpocząć nowy wątek, zanim zgubimy się w sekcji komentarzy.
Jan Groth
3

Ponieważ nie ma konkretnych odpowiedzi na ten temat @javax.annotation.ManagedBean, oto link do odpowiedzi na podobne pytanie: Fasola zapasowa (@ManagedBean) lub Fasola CDI (@Named)? . Specyfikację można znaleźć pod adresem http://download.oracle.com/otndocs/jcp/managed_beans-1.0-fr-eval-oth-JSpec/ . Więc wydaje mi się, że @javax.annotation.ManagedBeanmiało to być uogólnienie @javax.faces.bean.ManagedBean.

Z tego, co zebrałem, zarządzane fasole JSF są wycofywane na rzecz fasoli CDI (być może przestarzałe z JSF 2.3?), Więc @javax.annotation.ManagedBeanwydaje mi się, że teraz staje się coraz bardziej przestarzałe.

Hein Blöd
źródło
@Namedzastąpi @ManagedBeanw przyszłości?
Thufir
1
Przeczytałem kilka wypowiedzi różnych ekspertów Java EE, którzy przewidują, że @Namedziarna CDI zastąpią JSF @ManagedBeans, np. W stackoverflow.com/questions/4347374/ ... BalusC mówi: „Oczekujemy, że @ManagedBean i przyjaciele zostaną wycofani zgodnie z Javą EE 8. ”.
Hein Blöd