Embeddable EJB 3.1 z GlassFish 3.1 i NetBeans IDE 7.0
Z Jacek Laskowski - Wiki Projektanta Java EE
Rozdział 22. Embeddable Usage specyfikacji Enterprise JavaBeans (EJB) 3.1 opisuje nową cechę specyfikacji, która pozwala na uruchomienie kontenera EJB i zarządzanych przez niego komponentów EJB poza serwerem aplikacyjnym Java EE 6 - jedynie na poziomie środowiska Java SE. W ten sposób autorzy specyfikacji przewidują (a my programiści im wierzymy) uproszczenie procesu testowania, przetwarzania wsadowego (w którym użycie transakcji jest kluczowe) czy użycie EJB w samodzielnych aplikacjach desktopowych. Innymi słowy, mamy wszystko, co oferuje kontener EJB 3.1 bez konieczności uruchamiania pełnego serwera aplikacyjnego Java EE, którego sama konfiguracja uruchomieniowa mogła przyprawić o ból głowy.
Jest to duża zmiana w stosunku do poprzednich wersji specyfikacji EJB, które nie dosyć, że wymagały pełnego serwera aplikacyjnego, to były tak nietrywialne w użyciu (EJB 2.1 i starsze), że zwykło się je marginalizować na rzecz rozwiązań alternatywnych - najczęściej na korzyść zestawu Spring Framework i Hibernate (zresztą, jak wielu z nas pamięta, to właśnie bolączki przy pracy z EJB 1.1 sprowokowały do powstania Spring Framework).
W trybie wbudowanym (zanurzonym?, ang. embedded) odpowiedzialność za uruchomienie kontenera EJB oraz wskazanie komponentów EJB do uruchomienia spoczywa na programiście - specyfikacja EJB 3.1 określa dedykowane API w pakiecie javax.ejb.embeddable. Na chwilę obecną nie znajdziemy tam wiele (pod względem liczby klas), bo udostępnia się jedynie javax.ejb.embeddable.EJBContainer, ale owe "tylko tyle" wystarczy, aby móc uruchomić pełnoprawny kontener EJB 3.1 z usługami zarządzania (wstrzykiwania/przekazywania) zależnościami, zarządzanie transakcjami, bezpieczeństwo, utrwalanie danych, zarządzanie stanem i inne usługi, które sprawiały, że wybór serwera aplikacyjnego (często wyłącznie celem użycia kontenera EJB) był uzasadniony.
W tym artykule skorzystamy z referencyjnej implementacji dla specyfikacji Java EE 6, którym jest GlassFish 3.0.1 (którego podmienimy na najnowszą rozwojową wersję 3.1-b35) oraz najnowszą, rozwojową wersję NetBeans IDE 7.0 (z dnia 15.12.2010). Poza NetBeans IDE wszystkie składowe zostaną pobrane ze zdalnych repozytoriów przez Apache Maven i właśnie z tego powodu, w trakcie pierwszego uruchomienia testów, podłączenie do Sieci jest niezbędne.
Kompletny projekt jest dostępny jako nb7-ejb31-gf31-embeddable-ejb.zip.
Spis treści |
Utworzenie projektu ziarna EJB - calculator-ejb
Dobrze jest korzystać z efektów pracy już wykonanej i nie inaczej będzie z naszą nauką. Podeprzemy się artykułem EJB 3.1 z OpenEJB 3.1 i NetBeans IDE 7.0, w którym znajdziesz, jak stworzyć bezstanowe ziarno sesyjne bez dedykowanego typu dla interfejsu biznesowego (użycie nowej cechy EJB 3.1 - @LocalBean).
Wykonaj kroki opisane w sekcji Stworzenie projektu calculator-ejb oraz Stworzenie bezstanowego ziarna sesyjnego EJB - Calculator.
Można również pobrać gotowy projekt nb7-ejb31-openejb-no-interface-view.zip i rozpakować do odpowiedniego katalogu, po czym wykonać import projektu do NetBeans.
Stworzenie projektu testującego - calculator-test
Stwórz osobny projekt testujący calculator-test, którego celem jest skorzystanie z uruchomienia wbudowanego kontenera EJB 3.1 do przetestowania naszego komponentu EJB - Calculator z projektu calculator-ejb. W ten sposób oddzielamy projekty i umożliwiamy testowanie ziarna EJB w ramach różnych kontenerów EJB 3.1 (tym razem GlassFish, ale w kolejnych artykułach dowiesz się o innych, chociażby Apache OpenEJB 3.1, JBoss AS 6 czy IBM WebSphere Application Server 8).
Wciśnij Cmd+Shift+N i z kategorii Maven wybierz Java Application.
Podaj dane projektu. Zwróć uwagę na pakiet - pl.jaceklaskowski.jee6.calculator (domyślnie pl.jaceklaskowski.jee6.calculatortest).
Wciśnij przycisk Finish.
Po chwili, w widoku Projects pojawi się kolejny projekt calculator-test.
Deklaracja zależności projektowych
Projekt calculator-ejb
Z menu kontekstowego Test Dependencies wybierz Add Dependency...
Przejdź do zakładki Open Projects (domyślnie wybrana jest Search). Wskaż na projekt calculator-test.
Z nieznanych mi powodów, zależność nie jest w pełni uzupełniona poprawnie i zawiera ${project.groupId} oraz ${project.version}. Jeśli groupId oraz version projektu calculator-test oraz calculator-ejb odpowiadają sobie, to nic nie szkodzi, ale proponuję zamienić na pl.jaceklaskowski.jee6 oraz 1.0-SNAPSHOT, odpowiednio. Skonsultuj pom.xml dla projektu calculator-ejb (nie wiesz, o czym tutaj się pisze? Skontaktuj się z autorem).
Zatwierdź przyciskiem Add.
Test Dependencies powinna zawierać dwie pozycje - calculator-ejb oraz junit.
Repozytorium mavenowe glassfish-repository
W katalogu Project Files znajdziesz plik pom.xml.
Otwórz go.
Poniżej sekcji (znacznika) dependencies wklej poniższą sekcję repositories:
<repositories> <repository> <id>glassfish-repository</id> <url>http://download.java.net/maven/glassfish</url> </repository> </repositories>
Zapisz zmianę i zamknij plik.
org.glassfish/javax.ejb/3.1-b35
Z menu kontekstowego Test Dependencies wybierz Add Dependency... i podaj dane zależności org.glassfish/javax.ejb/3.1-b35.
Zwróć uwagę, że zależność jest na poziomie (Scope) provided (potrzebujących wyjaśnienia uprasza się o kontakt z autorem w ramach pogłębiania znajomości :)).
Zatwierdź wybór przyciskiem Add.
org.glassfish.extras/glassfish-embedded-all/3.1-b35
Kolejną zależnością jest główna zależność pozwalająca na użycie wbudowanego kontenera EJB 3.1 - org.glassfish.extras/glassfish-embedded-all/3.1-b35.
Podobnie, jak wcześniej, wybierz Test Dependencies, później Add Dependency... i podaj dane zależności.
Zatwierdź wybór przyciskiem Add.
JUnit 4.8.2
Jakkolwiek już mamy zdefiniowaną zależność projektową JUnit 3.8.1 to możliwości JUnit 4.8.2 są nie do przecenienia (przede wszystkim adnotacje) i to właśnie tę wersję użyjemy - zastąpimy istniejącą, starszą na nowszą.
Wybierz Add Dependency... z menu kontekstowego Test Dependencies i zdefiniuj zależność junit/junit/4.8.2 w wybrany przez siebie sposób - podając bezpośrednio Group ID, Artifact ID i Version, jak poprzednio lub korzystając z wyszukiwarki poniżej podając junit, 4.8.2 w polu Query i wybierając właściwy element.
Zatwierdź wybór przyciskiem Add.
Aktualna zależność JUnit w wersji niższej zostanie podmieniona na wyższą.
Podsumowanie - Test Dependencies oraz pom.xml
Projekt poprawnie zdefiniowany zależnościowo powinien prezentować się jak poniżej:
Plik konfiguracyjny pom.xml powinien wyglądać jak poniżej z jedną zmianą - zdefiniowaną zmienną glassfish.version tak, aby uprościć późniejsze zmiany, kiedy pojawi się nowsza wersja.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>pl.jaceklaskowski.jee6</groupId> <artifactId>calculator-test</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>calculator-test</name> <url>http://www.jaceklaskowski.pl/wiki</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <glassfish.version>3.1-b35</glassfish.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.2</version> <scope>test</scope> </dependency> <dependency> <groupId>pl.jaceklaskowski.jee6</groupId> <artifactId>calculator-ejb</artifactId> <version>1.0-SNAPSHOT</version> <scope>test</scope> </dependency> <dependency> <groupId>org.glassfish</groupId> <artifactId>javax.ejb</artifactId> <version>${glassfish.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.glassfish.extras</groupId> <artifactId>glassfish-embedded-all</artifactId> <version>${glassfish.version}</version> <scope>test</scope> </dependency> </dependencies> <repositories> <repository> <id>glassfish-repository</id> <url>http://download.java.net/maven/glassfish</url> </repository> </repositories> </project>
Utworzenie klasy testującej - CalculatorTest
Z menu kontekstowego Test Packages wybierz New > Other... i dalej w kategorii JUnit wybierz JUnit Test (niestety Test for Existing Class jest jedynie dla klas ze źródłami w bieżącym projekcie).
Wciśnij przycisk Next >.
Podaj dane klasy testowej jak poniżej z opcjonalnym odznaczeniem opcji w Generated Code oraz Generated Comments - po prostu i tak nie będziesz z nich korzystał.
Zatwierdź zmiany przyciskiem Finish.
Zmień zawartość klasy na poniższą.
package pl.jaceklaskowski.jee6.calculator; import java.util.logging.Level; import java.util.logging.Logger; import javax.naming.NamingException; import org.junit.After; import org.junit.Before; import javax.ejb.embeddable.EJBContainer; import javax.naming.Context; import org.junit.Test; import static org.junit.Assert.*; /** * @author Jacek Laskowski */ public class CalculatorTest { EJBContainer ejbContainer; Context ctx; @Before public void setUp() { // Uruchomienie wbudowanego kontenera EJB 3.1 ejbContainer = EJBContainer.createEJBContainer(); // Dostanie się do kontekstu JNDI ctx = ejbContainer.getContext(); } @Test public void testMultiply() throws Exception { // Dane testowe int x = 2; int y = 4; // Wyszukanie ziarna Calculator w kontekście java:global Calculator calculator = (Calculator) ctx.lookup("java:global/classes/Calculator"); // Uruchomienie metody ziarna EJB int result = calculator.multiply(x, y); // Sprawdzenie poprawności wykonania metody biznesowej int expected = x * y; assertEquals(expected, result); } @After public void tearDown() { try { ctx.close(); } catch (NamingException ex) { Logger.getLogger(CalculatorTest.class.getName()).log(Level.SEVERE, null, ex); } ejbContainer.close(); } }
Testy, testy, testy - uruchomienie CalculatorTest
Wybierz Test File z menu kontekstowego klasy testowej CalculatorTest lub po prostu wciśnij kombinację klawiszy Cmd+F6 (zakładając, że projekt jest głównym projektem - jego nazwa jest wtedy wytłuszczona).
W widoku Test Results pojawi się poprawnie wykonany test CalculatorTest.
Gratulacje!
UWAGA: Czasami konieczne jest najpierw uruchomienie testu w ramach pełnego uruchomienia testowego w projekcie, tj. poprzez wspomniane Cmd+F6 lub Run > Test Project (calculator-test). Dopiero wtedy możliwe jest uruchomienie testu pojedynczo i to często również wymaga zmiana nazwy JNDI. U Ciebie może być inaczej.

















