Gdzie używać EJB 3.1 i CDI?

Robię produkt oparty na Java EE, w którym używam GlassFish 3 i EJB 3.1.

Moja aplikacja ma session beans , scheduler i korzysta z usług internetowych. Niedawno dowiedziałem się o Apache TomEE, który obsługuje Contexts i Dependency Injection (CDI). Pojemnik GlassFish obsługuje również CDI.

Czy mogę zastąpić session beans tam, gdzie nie wymagam żadnej funkcji, której CDI jeszcze nie zapewnia? A jeśli wtedy, to jakie są korzyści jakie mogę uzyskać?

Author: Basil Bourque, 2012-11-21

2 answers

Tak, możesz dowolnie mieszać zarówno CDI, jak i EJB i osiągnąć wspaniałe rezultaty. Wygląda na to, że używasz @WebService i @Schedule, co jest dobrym powodem do dodania EJB do miksu.

Jest tam wiele zamieszania, więc tutaj jest kilka ogólnych informacji na temat EJB i CDI, ponieważ odnoszą się one do każdego razem.

EJB > = CDI

Zauważ, że EJB fasolami CDI i dlatego mają wszystkie zalety CDI. Odwrotność nie jest prawdą (jeszcze). Więc zdecydowanie nie wchodź do nawyk myślenia "EJB vs CDI", ponieważ ta logika naprawdę przekłada się na "EJB+CDI vs CDI", co jest dziwnym równaniem.

W przyszłych wersjach Java EE będziemy je nadal dostosowywać. Co to znaczy pozwalać ludziom robić to, co już potrafią, tylko Bez @Stateful, @Stateless lub @Singleton adnotacja na górze.

EJB i CDI w Warunkach implementacji

Ostatecznie, EJB i CDI mają tę samą podstawową konstrukcję, że są komponentami proxy. Kiedy dostaniesz odniesienie do EJB lub CDI bean, to nie jest prawdziwa fasola. Raczej dany obiekt jest fałszywy (proxy). Gdy wywołujesz metodę na tym fałszywym obiekcie, wywołanie przechodzi do kontenera, który wyśle wywołanie przez przechwytywacze, dekoratory itp. jak również dbać o wszelkie transakcje lub kontrole bezpieczeństwa. Gdy wszystko zostanie zrobione, połączenie w końcu przechodzi do rzeczywistego obiektu, a wynik jest przekazywany z powrotem przez proxy do dzwoniącego.

Różnica polega tylko na tym, jak obiekt do be called is resolved. Przez "rozwiązany" rozumiemy po prostu, gdzie i jak kontener szuka prawdziwej instancji do wywołania.

W CDI kontener wygląda w "zakresie", który będzie w zasadzie hashmapą, która żyje przez określony czas (na żądanie @RequestScoped, na sesję HTTP @SessionScoped, na aplikację @ApplicationScoped, konwersację JSF @ConversationScoped lub na niestandardową implementację zakresu).

W EJB kontener wygląda również na hashmapę, jeśli fasola jest typu @Stateful. Fasola może też użyj dowolnej z powyższych adnotacji, powodując, że obiekt żyje i umiera wraz ze wszystkimi innymi fasolami w zakresie. W EJB {[2] } jest w zasadzie" każdy zakres". @Stateless jest w zasadzie pulą instancji-otrzymujesz instancję z puli na czas trwania jednego wywołania. @Singleton jest zasadniczo @ApplicationScoped

Więc na poziomie podstawowym, wszystko, co można zrobić z fasolą "EJB", powinno być w stanie zrobić z fasolą "CDI". Pod kołdrą ciężko je odróżnić. Wszystkie hydraulika jest taka sama, z wyjątkiem sposobu rozwiązywania instancji.

Obecnie nie są one takie same pod względem usług, jakie kontener będzie oferował podczas tego proxyowania, ale jak mówię, pracujemy nad tym na poziomie specyfikacji Java EE.

Notka o wydajności

Lekceważ wszelkie "Lekkie " lub" ciężkie " obrazy mentalne, które możesz mieć. To wszystko marketing. W większości mają tę samą konstrukcję wewnętrzną. Rozdzielczość instancji CDI jest być może nieco bardziej złożona, ponieważ jest nieco bardziej dynamiczny i kontekstowy. Rozdzielczość instancji EJB jest dość statyczna, głupia i prosta w porównaniu.

Mogę ci powiedzieć z perspektywy implementacji w TomEE, jest o zerowej różnicy wydajności między wywołaniem EJB a wywołaniem CDI bean.

Default to POJOs, then CDI, then EJB

Oczywiście nie używaj CDI lub EJB, gdy nie ma korzyści. Dodaj CDI, gdy zaczniesz chcieć wtrysku, zdarzeń, przechwytujących, dekoratorów, śledzenia cyklu życia i takie tam. W większości przypadków.

Poza tymi podstawami, istnieje wiele przydatnych usług kontenerowych, z których możesz skorzystać tylko wtedy, gdy sprawisz, że Twój CDI bean będzie również EJB, dodając @Stateful, @Stateless, albo @Singleton na nim.

Oto krótka lista kiedy wyłamuję EJB.

Za pomocą JAX-WS

Odsłanianie JAX-WS @WebService. Jestem leniwy. Gdy @WebService jest również EJB, nie musisz go wypisywać i mapować jako servlet w pliku web.xml. To dla mnie praca. Dodatkowo dostaję możliwość skorzystania z jednej z innych funkcjonalności wymienionych poniżej. Więc dla mnie nie ma o czym myśleć.

Dostępne tylko dla @Stateless i @Singleton.

Za pomocą JAX-RS

Odsłanianie zasobów JAX-RS poprzez @Path. Nadal jestem leniwy. Gdy usługa RESTful jest również EJB, ponownie otrzymujesz automatyczne wykrywanie i nie musisz dodawać go do podklasy JAX-RS Application lub czegoś podobnego. Dodatkowo mogę wystawić dokładnie taką samą fasolę jak @WebService, jeśli chcę lub użyję jakiegoś wielkiego funkcje wymienione poniżej.

Dostępne tylko dla @Stateless i @Singleton.

Logika startowa

Załaduj przy starcie przez @Startup. Obecnie nie ma odpowiednika tego w CDI. W jakiś sposób przegapiliśmy dodanie czegoś w rodzaju zdarzenia AfterStartup w cyklu życia kontenera. Gdybyśmy to zrobili, po prostu mogłeś mieć @ApplicationScoped fasolkę, która tego słuchała i która byłaby faktycznie taka sama jak @Singleton z @Startup. Znajduje się na liście CDI 1.1.

Dostępny do @Singleton tylko.

Praca równolegle

@Asynchronous wywołanie metody. Uruchamianie wątków jest Nie-Nie w każdym środowisku po stronie serwera. Posiadanie zbyt wielu wątków jest poważnym zabójcą wydajności. Ta adnotacja pozwala na równoległe wykonywanie czynności przy użyciu puli wątków kontenera. To jest niesamowite.

Dostępne dla @Stateful, @Stateless i @Singleton.

Planowanie pracy

@Schedule lub {[39] } jest w zasadzie funkcją cron lub Quartz. Również bardzo niesamowite. Większość kontenerów wystarczy użyć kwarcu pod kołdrą. Większość ludzi nie wie jednak, że planowanie pracy w Java EE jest transakcyjne! Jeśli zaktualizujesz bazę danych, zaplanuj jakąś pracę, a jedna z nich się nie powiedzie, obie zostaną automatycznie wyczyszczone. Jeśli wywołanie EntityManager persist nie powiedzie się lub wystąpi problem, nie ma potrzeby odwoływania pracy. Yay, transakcje.

Dostępne tylko dla @Stateless i @Singleton.

Wykorzystanie Entitymanagerów w transakcji JTA

Powyższa uwaga na transakcje oczywiście wymagają użycia JTA zarządzanego EntityManager. Można ich używać ze zwykłym "CDI" , ale bez transakcji zarządzanych kontenerem może to być naprawdę monotonne powielanie UserTransaction logiki commit/rollback.

Dostępne dla wszystkich komponentów Java EE, w tym CDI, JSF @ManagedBean, @WebServlet, @WebListener, @WebFilter, itd. @TransactionAttribute adnotacja jest jednak dostępna dla @Stateful, @Stateless i tylko @Singleton.

Utrzymanie JTA zarządzane EntityManager

Zarządzany EXTENDED pozwala należy zachować EntityManager otwarte między JTA transakcji i nie stracić danych buforowanych. Dobra funkcja w odpowiednim czasie i miejscu. Używaj odpowiedzialnie:)

Dostępne tylko dla @Stateful.

Łatwa synchronizacja

Kiedy potrzebujesz synchronizacji, adnotacje @Lock(READ) i @Lock(WRITE) są całkiem doskonałe. Pozwala to uzyskać współbieżne zarządzanie dostępem za darmo. Pomiń wszystkie ReentrantReadWriteLock hydraulika. W tym samym wiadrze jest @AccessTimeout, co pozwala powiedzieć, jak długo thread powinien poczekać na dostęp do instancji bean przed poddaniem się.

Dostępne tylko dla @Singleton fasoli.

 344
Author: David Blevins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-22 01:42:13

Jeśli naprawdę nie używasz żadnej z funkcji ejb 3.1, odpowiedź jest prosta. ale zgaduj, że twoje pytanie wskazuje, że podejrzewasz, że istnieją koncepcje ejb 3.1, z których czerpiesz korzyści, nie będąc o nich świadomym. jednym z przykładów może być to, że kontener może zachować pulę slsb gotową do użycia, tak aby połączenia jms i bazy danych nie musiały być wstrzykiwane jako część request

 2
Author: Aksel Willgert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-21 08:18:10