Tworzenie aplikacji Java EE 5 z Eclipse IDE i GlassFish
Z Jacek Laskowski - Wiki Projektanta Java EE
Rozczytując się w specyfikacji JSR 220: Enterprise JavaBeans 3.0 postanowiłem sprawdzić, co do zaoferowania ma Eclipse IDE. Do tej pory do tworzenia oprogramowania korzystając z Java EE 5 jako zintegrowane środowisko programistyczne (ang. IDE - integrated development environment) zawsze wybierałem NetBeans IDE 5.5 ze względu na jego zaawansowanie we wsparciu dla tej specyfikacji (bądź służbowo IBM Rational Application Developer V7.0). Skoro wymagania Java EE 5 znacznie zmalały, tj. komponenty EJB mogą być (i zazwyczaj są) dystrybuowane jako pliki jar bez dodatkowych elementów (np. /META-INF/ejb-jar.xml) zmieniają się nasze wymagania dla zintegrowanych środowisk programistycznych . Pora zatem sprawdzić co można stworzyć w Java EE 5 korzystając z Eclipse IDE 3.3 i GlassFish v2.
Spis treści |
Zanim rozpoczniemy...
Poprzednia wersja artykułu dotyczyła Eclipse IDE 3.3M3. Po ostatnich wydaniach wtyczek okazało się, że instrukcja działa również dla wersji Eclipse IDE 3.3M4 z tym, że potrzebne jest korzystanie z nowszych wersji wtyczek. Uaktualnieniu podlegają następujące pakiety:
- Eclipse IDE 3.3M4
- Eclipse Web Tools Platform (WTP) 2.0M4
- Eclipse EMF, SDO i XSD SDK 2.3.0M4
- Eclipse GEF SDK 3.3M4
Dodatkowo należy zaktualizować pliki link, które wskazują na właściwe katalogi wtyczek. Pozostałe kroki instalacyjne pozostają bez zmian.
Oprogramowanie
i kilka zależności potrzebnych do zestawienia gotowego środowiska z w/w projektami, tj.
- Eclipse Web Tools Platform (WTP) 2.0M3
- Eclipse EMF, SDO i XSD 2.3.0M3
- Eclipse GEF 3.2.1
- Eclipse Java EMF Model 1.2.1
- Eclipse Data Tools Platform 1.0
- Eclipse Java Server Faces (JSF) 2.0M3
- Eclipse Java Persistence API (JPA) 2.0M3 (nie wiem jaka jest różnica od Eclipse Dali)
Wszystko uruchamiane na MS Windows XP i stąd odnośniki wskazują na wersje dystrybucyjne dla tej platformy (gdzie wymagane).
Konfiguracja środowiska
Po pobraniu wszystkich wymienionych wyżej wersji dystrybucyjnych projektów, które złożą się na kompletne środowisko do tworzenia aplikacji Java EE 5 przystępujemy do ich konfiguracji.
Instalacja Eclipse IDE
Katalog domowy (katalog instalacyjny) Eclipse IDE to c:\eclipse. Instalacja Eclipse to po prostu rozpakowanie wersji dystrybucyjnej na dysk c:.
Instalacja GlassFish
Katalog domowy GlassFish to c:\glassfish. Instalacja GlassFish składa się z dwóch kroków doskonale opisanych na stronie projektu - Instructions to unbundle and configure GlassFish.
Instalacja GlassFish Plugin for Eclipse IDE i zależności
Włączenie wtyczek do Eclipse IDE nastąpi poprzez wykorzystanie funkcjonalności Eclipse o nazwie Extension Location.
Wszystkie pozostałe wersje dystrybucyjne pobranych projektów (które de facto wszystkie są zestawem wtyczek i funkcjonalności Eclipse) rozpakowujemy do wybranego katalogu, np. c:\eclipse-plugins-javaee5 zachowując nazwę paczki, np. wtp-S-2.0M3-200611170109.zip rozpakowujemy do katalogu C:\eclipse-plugins-javaee5\wtp-S-2.0M3-200611170109, który z kolei będzie zawierał katalog eclipse. Postępujemy tak z każdą z wtyczek poza (niesforną) dystrybucją wtyczki GlassFish Plugin for Eclipse IDE. Dla niej postępujemy specjalnie, tzn. rozpakowujemy ją do katalogu C:\eclipse-plugins-javaee5\glassfish-eclipse-plugin_0_3, ale skoro podkatalog to plugins, tworzymy równorzędny katalog eclipse i do niego przenosimy katalog plugins.
Podczas rozpakowywania mogą pojawić się błędy związane z długością ścieżki pliku/katalogu. Można je zignorować, gdyż dotyczą niewykorzystywanej części wersji dystrybucyjnej danej wtyczki, przez co poprawność jej działania jest zachowana.
Korzystając z WinRAR (albo innego narzędzia graficznego do obsługi spakowanych plików) nazwy katalogów będą tworzone na podstawie nazw paczek, stąd ich pomoc jest nieoceniona.
W katalogu eclipse, który zawarty jest w każdym z podkatalogów w katalogu c:\eclipse-plugins-javaee5 umieszczamy pusty plik .eclipseextension.
Ostatecznie zawartość katalogu c:\eclipse-plugins-javaee5 powinna zawierać następujące katalogi (które z kolei zawierają podkatalog eclipse z podkatalogami features i plugins oraz obowiązkowo plik .eclipseextension):
GEF-SDK-3.2.1 JEM-SDK-1.2.1 dali-R-0.5-200606282232 dtp_1.0_200612211 emf-sdo-xsd-SDK-2.3.0M3 glassfish-eclipse-plugin_0_3 wtp-S-2.0M3-200611170109 wtp-jpa-S-2.0M3-200611170109 wtp-jsf-S-2.0M3-200611170109
Zakładamy katalog links w katalogu domowym Eclipse i umieszczamy tam wskazania na katalogi wtyczek tak, że podczas kolejnego uruchomienia Eclipse wtyczki będą aktywne. Poniżej znajduje się zawartość katalogu c:\eclipse\links.
GEF-SDK-3.2.1.link JEM-SDK-1.2.1.link dali-R-0.5-200606282232.link dtp_1.0_200612211.link emf-sdo-xsd-SDK-2.3.0M3.link glassfish-eclipse-plugin_0_3.link wtp-S-2.0M3-200611170109.link wtp-jpa-S-2.0M3-200611170109.link wtp-jsf-S-2.0M3-200611170109.link
Każdy z plików zawiera wyłącznie pojedyńczą linię w formacie path=<katalog z wtyczki>, np. zawartość glassfish-eclipse-plugin_0_3.link przedstawia się następująco (z dokładnością do nazwy katalogu, gdzie rozpakowano wtyczki):
path=c:/apps/eclipse-plugins-javaee5/glassfish-eclipse-plugin_0_3
Uruchamiamy Eclipse IDE i dla upewnienia się, że poprawnie zainstalowano wszystkie wtyczki wybieramy menu Help->Software Updates->Manage Configuration, gdzie powinny ukazać się włączone katalogi wtyczek jak na poniższym obrazku (z dokładnością do nazwy katalogu, gdzie rozpakowano wtyczki).
Mimo, że nie jest to perfekcyjnie działające środowisko (próba uaktualnienia wtyczek zgłasza błąd konfiguracji, choć nigdzie nie mogę znaleźć dokładnego zgłoszenia błędu poza lakonicznym The current configuration contains errors and this operation can have unpredictable results. Do you want to continue?), przystępujemy do stworzenia przykładowego projektu Java EE 5 w Eclipse IDE.
Aplikacja Java EE 5 - Egzaminy
Definicja serwera GlassFish w Eclipse
Otwieramy widok Servers, tj. wybieramy menu Window->Show View->Other... i w okienku dialogowym wybieramy widok Server->Servers. Pojawi się pusty widok zdefiniowanych serwerów.
Następnie definiujemy serwer GlassFish, tj. wybieramy menu File->New->Other..., wpisujemy server w pole Wizards, a następnie wybieramy Server (wtedy uaktywni się przycisk Next >).
Wciskamy przycisk Next > i z listy dostępnych typów serwerów wybieramy GlassFish Java EE 5 (jeśli tej pozycji nie ma, jest to wynik błędnej instalacji wtyczek Eclipse WTP bądź, jeśli istnieją inne typy serwerów, GlassFish plugin for Eclipse).
Wciskamy przycisk Next >.
W polu Sun Application Server Directory podajemy katalog domowy GlassFish, np. c:/apps/glassfish.
Jeśli korzystasz z wersji GlassFish większej niż 26 możesz spodziewać się wystąpienia komunikatu błędu o niedostępności biblioteki appserv-ws.jar, która zgodnie z ogłoszeniem GFv2 - Removal of appserv-ws.jar binary na grupie GlassFish Users została usunięta. Informacja o usunięciu biblioteki została wydana po opublikowaniu wtyczki GlassFish Plugin for Eclipse stąd ta niedogodność. Obejściem jest utworzenie brakującego pliku na bazie kopii pliku webservices-rt.jar w katalogu bibliotek GlassFish.
C:\apps\glassfish>cd lib C:\apps\glassfish\lib>cp webservices-rt.jar appserv-ws.jar
Zmiana wpisu w Sun Application Server Directory i ponowne wprowadzenie katalogu (który poprzednio powodował zgłoszenie błędu) nie kończy się tym razem błędem.
Wciskamy przycisk Finish (zakładając, że interesują nas wartości domyślne - nazwa domeny, hasła, porty, etc.) i w widoku Servers pojawia się GlassFish.
Utworzenie aplikacji internetowej - EgzaminyWeb
Wybieramy File->New->Other..., w pole Wizards wpisujemy web i wybieramy pozycję Dynamic Web Project.
Wciskamy przycisk Next >.
Jako Project name podajemy EgzaminyWeb, resztę pozostawiając bez zmian.
Wciskamy przycisk Finish (zapytani o zmianę perspektywy na J2EE, zgadzamy się wciskając przycisk Yes).
W projekcie EgzaminyWeb tworzymy stronę startową - index.jsp. W menu kontekstowym projektu wybieramy New->JSP.
W pole File name wpisujemy index.jsp i wciskamy przycisk Finish.
Podmieniamy treść strony index.jsp na poniższą.
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Egzaminy</title>
</head>
<body>
<form action="ExecuteEjbServlet">
<input type="submit" value="Dostępne egzaminy" />
</form>
<hr>
<c:forEach items="${exams}" var="exam">
<p><a href="ExecuteEjbServlet?exam=${exam.name}">${exam.name}</a></p>
</c:forEach>
</body>
</html>
Zapisujemy (kombinacja klawiszy Ctrl-Shift-S wydaje się być najkorzystniejszym rozwiązaniem).
Podobnie jak miało to miejsce z plikiem index.jsp, tworzymy nowy servlet, którego zadaniem będzie przechwytywanie zleceń ze strony i wywoływanie akcji na komponencie EJB.
W polu Java package wpisujemy pl.jaceklaskowski.servlet, a w Class name wpisujemy ExecuteEjbServlet.
Wciskamy przycisk Finish.
Podmieniamy zawartość servletu na poniższą.
package pl.jaceklaskowski.servlet;
import java.io.IOException;
import java.util.List;
import javax.ejb.EJB;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ExecuteEjbServlet extends HttpServlet {
@EJB
private ExamScheduler examScheduler;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
String page = "/index.jsp";
List<Exam> exams = examScheduler.getExams();
request.setAttribute("exams", exams);
RequestDispatcher rd = getServletContext().getRequestDispatcher(page);
rd.forward(request, response);
}
}
Ponownie zapisujemy.
UWAGA Czasami zdarzało się, że podmiana (kombinacja Ctrl-A, Ctrl-C i Ctrl-V) kończyła się niekompletnym przekopiowaniem źródła servletu z artykułu.
I podnosimy wersję specyfikacji zgodnej z naszą aplikacją internetową do wersji 2.5. Innymi słowy modyfikujemy plik web.xml tak, aby ostatecznie wyglądał jak poniżej (plik znajduje się w katalogu WebContent/WEB-INF projektu).
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name>EgzaminyWeb</display-name> <servlet> <description></description> <display-name>ExecuteEjbServlet</display-name> <servlet-name>ExecuteEjbServlet</servlet-name> <servlet-class> pl.jaceklaskowski.servlet.ExecuteEjbServlet </servlet-class> </servlet> <servlet-mapping> <servlet-name>ExecuteEjbServlet</servlet-name> <url-pattern>/ExecuteEjbServlet</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> </web-app>
Tymczasowo akceptujemy błędy, które wynikają z nieistniejącej klasy komponentu EJB. Naprawimy to za moment.
Utworzenie modułu EJB - EgzaminyEjb
Komponenty EJB w nowej specyfikacji EJB3 są po prostu zwykłymi projektami Java (plikami jar), więc tworzenie ich nie różni się wiele od tworzenia zwykłego projektu Java, którego wynikiem będzie plik jar.
Z menu głównego wybieramy File->New->Other..., wpisujemy java w pole Wizards i wybieramy Java Project.
Wciskamy przycisk Next >.
W polu Project name wpisujemy EgzaminyEjb, resztę pozostawiając bez zmian.
Wciskamy przycisk Finish (zgadzamy się na zmianę perspektywy na perspektywę Java wciskając Yes).
Tworzymy interfejs biznesowy - ExamScheduler, czyli innymi słowy najzwyklejszy interfejs Java. Wybieramy z menu kontekstowego projektu menu New->Interface.
W pole Package wpisujemy pl.jaceklaskowski.exam.scheduler, natomiast ExamScheduler w pole Name.
Wciskamy przycisk Finish.
Podmieniamy zawartość interfejsu ExamScheduler na poniższy.
package pl.jaceklaskowski.exam.scheduler;
import java.util.List;
public interface ExamScheduler {
List<Exam> getExams();
}
Zapisujemy.
Pojawią się błędy związane z niedostępnością klasy Exam, którą właśnie teraz stworzymy.
Z menu kontekstowego projektu EgzaminyEjb wybieramy menu New->Class.
W pole Package wpisujemy pl.jaceklaskowski.exam.beans, natomiast Exam w pole Name.
Wciskamy przycisk Finish.
Podmieniamy zawartość klasy Exam na poniższą.
package pl.jaceklaskowski.exam.beans;
public class Exam {
private String name;
public Exam(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Nie zapominamy o zapisywaniu zmian (najlepiej korzystać z kombinacji klawiszy Ctrl-Shift-S).
Z menu kontekstowego projektu EgzaminyEjb wybieramy menu Source->Organize Imports.
Błędy w projekcie EgzaminyEjb powinny zostać naprawione.
Tworzymy klasę komponentu EJB - ExamSchedulerBean.
Z menu kontekstowego projektu wybieramy New->Class i w pole Package wpisujemy pl.jaceklaskowski.exam.scheduler oraz ExamSchedulerBean w pole Name.
Wciskamy przycisk Finish.
Podmieniamy zawartość klasy ExamSchedulerBean na poniższą.
package pl.jaceklaskowski.exam.scheduler;
import java.util.ArrayList;
import java.util.List;
import pl.jaceklaskowski.exam.beans.Exam;
@Stateless
public class ExamSchedulerBean implements ExamScheduler {
private final List<Exam> exams = new ArrayList<Exam>();
{
Exam exam = new Exam("Sun Certified Java Programmer (SCJP)");
exams.add(exam);
exam = new Exam("Sun Certified Java Developer (SCJD)");
exams.add(exam);
exam = new Exam("Sun Certified Web Component Developer (SCWCD)");
exams.add(exam);
exam = new Exam("Sun Certified Business Component Developer (SCBCD)");
exams.add(exam);
exam = new Exam("Sun Certified Developer For Java Web Services (SCDJWS)");
exams.add(exam);
exam = new Exam("Sun Certified Enterprise Architect (SCEA)");
exams.add(exam);
}
public List<Exam> getExams() {
return exams;
}
}
Zapisujemy.
Pojawi się błąd związany z brakiem definicji annotacji @Stateless, która znajduje się w pakiecie javax.ejb dostarczanym (w naszym przypadku) przez definicję serwera GlassFish w Eclipse.
W menu kontekstowym projektu wybieramy menu Build Path->Add Libraries....
Wybieramy pozycję Server Runtime.
Wciskamy przycisk Next >. Wybieramy GlassFish Java EE 5 z listy (wtedy dopiero uaktywni się przycisk Finish).
I ostatecznie wciskamy przycisk Finish.
Ponownie z menu kontekstowego projektu wybieramy menu Source->Organize Imports, co rozwiąże nasze problemy z brakującą definicją annotacji @Stateless.
Nadal będą zgłoszone błędy związane z projektem EgzaminyWeb, ale do tego wrócimy za moment.
Tym samym skończyliśmy tworzenie komponentu EJB o nazwie ExamSchedulerBean z interfejsem biznesowym (lokalnym) - ExamScheduler.
Utworzenie projektu aplikacji przemysłowej - EgzaminyEAR
Z menu głównego wybieramy File->New->Other..., wpisujemy enterprise w pole Wizards i wybieramy Enterprise Application Project.
Wciskamy przycisk Next >.
W polu Project name wpisujemy EgzaminyEar, resztę pozostawiając bez zmian.
Wciskamy przycisk Next > dwukrotnie, aż dojdziemy do formatki J2EE Modules to Add to the EAR, gdzie zaznaczamy wszystkie z dostępnych projektów (EgzaminyEjb i EgzaminyWeb) wciskając przycisk Select All.
Wciskamy przycisk Finish (i zgadzamy się na zmianę perspektywy na perspektywę J2EE).
Modyfikujemy zawartość deskryptora instalacji application.xml na poniższą (plik znajduje się w katalogu EarContent/META-INF).
<?xml version="1.0" encoding="UTF-8"?> <application version="5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_5.xsd"> <display-name>EgzaminyEar</display-name> <module> <web> <web-uri>EgzaminyWeb.war</web-uri> <context-root>/EgzaminyWeb</context-root> </web> </module> <module> <ejb>EgzaminyEjb.jar</ejb> </module> </application>
Zapisujemy zmiany.
Pojawi się kolejny błąd związany z brakiem deskryptora instalacji dla naszego modułu EJB, ale szczęśliwie nie będzie on nam kolidował z możliwością uruchomienia projektu, kiedy będziemy już do tego gotowi. Innymi słowy: ignorujemy go.
Związanie projektów EgzaminyWeb i EgzaminyEjb
Projekt EgzaminyWeb zależy (choć jeszcze nieformalnie) od EgzaminyEjb. Przypomnę, że korzystamy z annotacji @EJB w servlecie ExecuteEjbServlet do wstrzelenia zależności przez serwer aplikacyjny.
Wróćmy zatem do naszego projektu EgzaminyWeb i zdefiniujmy zależność projektową z EgzaminyEjb.
Z menu kontekstowego projektu EgzaminyWeb wybieramy menu Properties.
Wybieramy pozycję J2EE Module Dependencies, gdzie zaznaczamy projekt EgzaminyEjb.
Wciskamy przycisk OK.
W ten sposób rozwiązaliśmy błędy związane z niedostępnością klas w projekcie EgzaminyWeb, zgłaszane przez Eclipse. Możemy przystąpić do uruchomienia aplikacji.
Uruchomienie
Z menu kontekstowego projektu EgzaminyWeb wybieramy pozycję Run As->Run On Server.
Wybieramy GlassFish Java EE 5.
Wciskamy przycisk Finish (rozpoczynając naszą, ulubioną w takich chwilach, modlitwę o pomyślne uruchomienie projektu).
Po chwili na konsoli powinny pojawić się wpisy o uruchamianiu GlassFish'a oraz postęp wykonania skryptu instalującego aplikację.
Buildfile: C:\.eclipse\javaee5-glassfish\.metadata\.plugins\org.eclipse.jst.server.generic.core\serverdef\sunappsrv-ant.xml
deploy.j2ee.web:
[echo] C:/.eclipse/javaee5-glassfish/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/EgzaminyWeb
[jar] Building jar: C:\.eclipse\javaee5-glassfish\.metadata\.plugins\org.eclipse.jst.server.generic.core\serverdef\EgzaminyWeb.war
tools:
deploy:
[exec] Command deploy executed successfully.
deploy-url-message:
[echo] Application Deployed at: http://127.0.0.1:8080/EgzaminyWeb
BUILD SUCCESSFUL
Total time: 5 seconds
Jeśli wszystko przejdzie pomyślnie, Eclipse otworzy okno przeglądarki z pierwszą stroną naszej aplikacji.
Wybierając przycisk Dostępne egzaminy upewniamy się, że aplikacja działa (wywoła ona komponent EJB, który zwróci listę dostępnych egzaminów).
Na zakończenie zmodyfikujmy klasę ExamSchedulerBean, która zawiera statyczną listę dostępnych egzaminów i wykonajmy ponowne uruchomienie projektu (ot, takie końcowe sprawdzenie, że konfiguracja Eclipse pozwala na dalszą pracę). Okazuje się, że ponowna instalacja aplikacji zabiera kilka sekund i...działa! Powodzenia w poznawaniu specyfikacji EJB3 i Java EE 5 w ogólności korzystając z Eclipse IDE 3.3M3 i GlassFish v2.


