Archiwum tagu ‘Maven’
Spring, JAXB oraz Maven – czyli łatwe i przyjemne budowanie oraz konfigurowanie aplikacji
Jakiś czas temu stanąłem przed koniecznością napisania aplikacji, która miała mieć możliwość konfigurowania z zewnętrznego pliku XML. Wybór formatu XML był podyktowany złożoną strukturą informacji, które należało wczytać. Aplikacja była oparta o szkielet Spring a zależnościami i budowaniem zajmował się Maven. Pozostał wybór narzędzia, które przeniesie mi w wygodny sposób dane z pliku XML do aplikacji. Wybór padł na JAXB – Java Architecture for XML Binding. JAXB to technologia pozwalająca wygenerować klasy języka Java, które pomogą nam odwzorować plik XML na obiekty.
Nie będę się skupiał nadto na opisie każdego z wymienionych narzędzi lecz skupię się raczej na pokazaniu jak zaprząc je razem do działania.
Budowanie aplikacji za pomocą Mavena
Kiedy pisałem o instalacji Seama wspomniałem, o instalacji narzędzia Maven, które może mi się przydać w przyszłości. I oto nadeszła ta chwila. Czytając jakiś czas temu poradnik Developing a Spring Framework MVC application pomyślałem, że fajnie byłoby zamienić narzędzie do budowania projektu z Anta na Mavena, który zajmie się przy okazji zależnościami.
Korzystam z Eclipse‘a jako IDE więc do zabawy przydadzą mi się dwa pluginy:
- Spring IDE – Przyda się do utworzenia Hello World oraz na przyszłość;
- Maven Integration for Eclipse – Zautomatyzuje nam to trochę czynności oraz dostaniemy bardzo ładny edytor plików POM.
Po zainstalowaniu powyższych tworzymy zalążek projektu w Eclipse. Wybieramy File > New > Other a później Spring Project. Podajemy nazwę projektu, niech to jExample oraz zmieniamy lokalizację Source Folder Name z src na src/main/java a Output Folder Name z bin na target/classes. Zmiany te wynikają z domyślnych ustawień pluginów Mavena, z których będziemy korzystać.
W następnej kolejności aktywujemy zarządzanie projektem za pomocą Mavena. W tym celu wybieramy Maven Enable Dependency Managment po uprzednim kliknięciu prawym klawiszem myszy na projekcie.
Kluczowym elementem pracy z Mavenem jest plik POM, który stanowi konfigurację zawierającą informacje o projekcie, jego zależnościach, e.t.c. Kreator tworzenia pliku POM uruchomi się zaraz po aktywacji Mavena. Jedyną zmianą jakiej dokonujemy to zamiana pakowania projektu z jar na war. Oto plik, który będzie wynikiem:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>jExample</groupId>
<artifactId>jExample</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
</project>
Utwórzmy teraz naprawdę bardzo prostą aplikację internetową. Niech jej jedyną funkcją będzie przywitanie nas słowami … Hello World. W pierwszej kolejności tworzymy deskryptory.
src/main/webapp/WEB-INF/web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>jExample</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jExample</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
src/main/webapp/WEB-INF/jExample-servlet.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean name="/index.html" class="pl.michalmech.jexample.web.HelloController"/>
</beans>
Oraz src/main/webapp/WEB-INF/applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
</beans>
Dodajemy jeszcze szybko widok (src/main/webapp/index.jsp):
<html>
<head>
<title>jExample</title>
</head>
<body>
<h1>jExample :: Hello World</h1>
</body>
</html>
Oraz na koniec niewielki kontroler:
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
public class HelloController implements Controller {
protected final Log logger = LogFactory.getLog(getClass());
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
logger.info("Returninag hello view");
return new ModelAndView("index.jsp");
}
}
Niestety jedyne co ma dla nas Eclipse to błędy wynikające z braku klas, których potrzebujemy:
Jest to okazja do wykorzystania wreszcie Mavena, który dostarczy nam zależności, których potrzebujemy. Chcielibyśmy przede wszystkim skorzystać ze Spring MVC (niech to będzie najnowsza wersja) oraz API związanego z sewletami. Dodajemy do pliku POM następujący wpis (możemy oczywiście w tym celu użyć edytora plików POM):
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>

Zapisanie pliku sprawi, że Maven pobierze ze swojego lokalnego repozytorium wymagane zależności i dostarczy do projektu. W przypadku braku wymaganych paczek, zostaną one wcześniej pobrane z sieci (http://repo2.maven.org/maven2) oraz zainstalowane w repozytorium lokalnym Mavena. Warto zaznaczyć, że Maven dostarczył nam również inne wymagane pośrednio zależności: commons-logging, spring-core, e.t.c. My nie musimy się niczym martwić. Projekt już nie świeci się na czerwono od błędów.
W związku z tym, że dążymy do ujrzenia naszej aplikacji działającej przydałoby sie teraz utworzyć plik WAR. W tym celu wykonujemy w konsoli (będąc w loklizacji, w której znajduje się nasz projekt) polecenie:
mvn clean package
Wynikiem wykonania tego polecenia powinno być coś takiego:
F:\workspace\jExample>mvn clean package [INFO] Scanning for projects... [INFO] ------------------------------------------------------------------------ [INFO] Building Unnamed - jExample:jExample:war:0.0.1-SNAPSHOT [INFO] task-segment: [clean, package] [INFO] ------------------------------------------------------------------------ [INFO] [clean:clean] [INFO] Deleting directory F:\workspace\jExample\target [INFO] [resources:resources] [INFO] Using default encoding to copy filtered resources. [INFO] [compiler:compile] [INFO] Compiling 1 source file to F:\workspace\jExample\target\classes [INFO] [resources:testResources] [INFO] Using default encoding to copy filtered resources. [INFO] [compiler:testCompile] [INFO] No sources to compile [INFO] [surefire:test] [INFO] No tests to run. [INFO] [war:war] [INFO] Packaging webapp [INFO] Assembling webapp[jExample] in [F:\workspace\jExample\target\jExample-0.0.1-SNAPSHOT] [INFO] Processing war project [INFO] Webapp assembled in[171 msecs] [INFO] Building war: F:\workspace\jExample\target\jExample-0.0.1-SNAPSHOT.war [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ [INFO] Total time: 5 seconds [INFO] Finished at: Wed Apr 08 23:51:16 CEST 2009 [INFO] Final Memory: 11M/20M [INFO] ------------------------------------------------------------------------
Teraz krótkie wyjaśnienie. Maven w pierwszej kolejności wyczyścił wszystko to co mogło być do tej pory skompilowane i umieszczone w folderze target. Po to było polecenie clean. W dalszej części Maven zajmuje się pakowaniem projektu (polecenie package). Plan tej czynności zakłada wykonanie kilku czynności wcześniej. Jest to przede wszystkim kompilacja źródeł, zebranie zasobów, wykonanie testów jednostkowych oraz wreszcie zebranie wszystkiego do kupy w WAR Pomimo tego, że w tym przypadku niewiele faktycznie jest do zrobienia, Maven informuje nas o każdej czynności i wynikach jej wykonania.
Każda z czynności jest realizowana przez oddzielny plugin Mavena, który możemy w szczególności skonfigurować wedle naszych życzeń.
Do Hello World krzyczącego do nas z okna przeglądarki zostało bardzo niewiele. Podobnie jak w tutorialu, o którym wspomniałem na początku, my również skorzystamy z kontenera aplikacji Apache Tomcat (instalacja jest niezwykle prosta więc pominę jej opis).
Przy tej okazji chciałbym zwrócić uwagę na konfigurację zależności servlet-api. Przestrzeń (ang. scope) jest zdefiniowana jako provided. Dzieje się tak ponieważ Tomcat dostarcza już tą paczkę wśród swoich bibliotek więc aplikacja, która jest rozmieszczana (ang. deploy) na serwerze nie musi jej zawierać.
W folderze domowym instalacji Mavena, w folderze conf znajduje się plik z globalną konfiguracją: settings.xml. W bloku zawierającym definicje serwerów servers/servers dodajmy opis lokalnego Tomcata:
<server>
<id>tomcat.local</id>
<username>admin</username>
<password></password>
</server>
Identyfikator serwera jest dowolny natomiast login oraz hasło (a dokładniej jego brak) wynika z domyślnych wartości dla standardowej instalacji Tomcataa. Aby umieścić naszą aplikację na serwer skorzystamy z pluginu Tomcat Maven Plugin. Aby wykonać całą robotę, czyli kompilację, spakowanie oraz rozmieszczenie (ang. deploy) projektu na serwer wystarczy wykonać polecenie:
mvn clean package tomcat:deploy
W zasadzie to wystarczy ponieważ Maven pobierze ze swojego repozytorium i zainstaluje wspomniany plugin jak tylko będzie go potrzebował. Podczas wykonywania polecenia zobaczymy to w konsoli:
[INFO] Searching repository for plugin with prefix: 'tomcat'. [INFO] org.codehaus.mojo: checking for updates from central [INFO] artifact org.codehaus.mojo:tomcat-maven-plugin: checking for updates from central Downloading: http://repo1.maven.org/maven2/org/codehaus/mojo/tomcat-maven-plugin/1.0-beta-1/tomcat-maven-plugin-1.0-beta-1.pom 5K downloaded Downloading: http://repo1.maven.org/maven2/org/codehaus/mojo/mojo-parent/20/mojo-parent-20.pom 18K downloaded Downloading: http://repo1.maven.org/maven2/org/codehaus/mojo/tomcat-maven-plugin/1.0-beta-1/tomcat-maven-plugin-1.0-beta-1.jar 48K downloaded
Niemniej jednak gdybyśmy chcieli wskazać jakieś inne repozytorium, które Maven ma przeszukiwać w chwili kiedy czegoś potrzebuje, możemy je zdefiniować w pliku POM:
<repositories>
<repository>
<id>mojo</id>
<name>Mojo Project</name>
<url>http://repository.codehaus.org</url>
</repository>
</repositories>
Podobnie ma się rzecz z uruchomieniem plugin. Użyta będzie domyślna konfiguracja. Aby ją zmienić powinniśmy odpowiednio zmodyfikować POM. Oto przykład jak jawnie podać nazwę serwera, na którym umieszczamy (ang. deploy) aplikację:
<build>
<plugins>
<plugin>
<groupid>org.codehaus.mojo</groupid>
<artifactid>tomcat-maven-plugin</artifactid>
<configuration>
<server>tomcat.local</server>
</configuration>
</plugin>
</plugins>
</build>
Konfiguracja oczywiście będzie będzie wzięta z ustawień globalnych Mavena.
W zasadzie to wszystko. Wykonanie wspomnianego polecenia (mvn clean package tomcat:deploy) powinno dać następujący wynik:
... [INFO] Building war: F:\workspace\jExample\target\jExample-0.0.1-SNAPSHOT.war [INFO] [tomcat:deploy] [INFO] Deploying war to http://localhost:8080/jExample [INFO] OK - Deployed application at context path /jExample [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------
Uruchomienie w przeglądarce adresu http://localhost:8080/jExample/index.html pozwoli nam upewniść się, że aplikacja działa.
To co opisałem, to zaledwie kropla w morzu możliwości Mavena, który posiada ich oczywiście dużo więcej, dzięki różnorodnym pluginom. Możemy dzięki niemu nie tylko zarządzać budowaniem projektu i zależnościami ale również generować dokumentację czy nawet sprawdzać styl kodowania.
Instalacja frameworka JBoss Seam
Pierwszą czynnością wymaganą do nauki frameworka JBoss Seam jest oczywiście jego instalacja. Framework to tylko narzędzie służące do budowania aplikacji, które przecież działają w jakimś środowisku, zaczniemy więc od instalacji środowiska, zarówno uruchomieniowego jak i środowiska programistycznego (Integrated Development Environment). Ja wybrałem serwer a JBoss, jako serwer aplikacji oraz Eclipse jako moje IDE. Instalację Eclipse’a pominę, skupię się na instalacji JBoss’a oraz JBoss Seam’a. Wszystkie opisy dotyczą systemu Windows.
Instalację serwera JBoss przeprowadzamy za pomocą JEMS Installer. Jest to narzędzie, służące do instalacji wszelkich produktów firmy JBoss. Aby uruchomić instalator wystarczy pobrać i uruchomić najnowszy plik JAR (w chwili pisania tego tekstu jest to plik 1.2.1.CR4.jar) lub uruchomić go poprzez Java Web Start.
Pierwszym etapem instalacji jest ekran powitalny, na którym śmiało klikamy Next. Proces instalacji jest rozłożony na 17 ekranów i na niemal wszystkich zachowujemy domyślne, zaznaczone opcje i klikamy Next.
Jedynym odstępstwem od “domyślna wartość + Next” jakie poczyniłem to miejscem instalacji serwera uczyniłem lokalizację C:Program FilesJBoss-4.2.2.GA.
Po instalacji serwera JBoss należy ustawić zmienną środowiskową JBOSS_HOME. Jak łatwo się domyślić powinna to być ścieżka wskazująca na zainstalowany serwer. U mnie jest to C:Program FilesJBoss-4.2.2.GA. Na tym etapie warto ustawić zmienną środowiskową JAVA_HOME i jako wartość podać lokalizacją, w której zainstalowaliśmy Javę. U mnie zmienna ta ma wartość C:Program FilesJavajdk1.6.0_07
Pozostaje nam teraz uruchomić serwer wykonując polecenie:
C:\Program Files\JBoss-4.2.2.GA\bin>run
Po uruchomieniu serwera wpisujemy w przeglądarce adres http://localhost:8080. Powinniśmy ujrzeć stronę, której zrzut prezentuję obok.
Kolejnym etapem jest instalacja frameworka JBoss Seam. Słowo instalacja jest tutaj mocno nad wyraz ponieważ cały proces polega na pobraniu archiwum (w chwili pisania tego tekstu najnowszym plikiem był jboss-seam-2.1.1.GA.zip) i rozpakowaniu jego zawartości w wybranym przez nas miejscu. Ja wybrałem lokalizację C:Program FilesJBoss-seam-2.1.1.GA.
Do pracy będzie potrzebny również Anta. Pobieramy wersję 1.7.0 (w chwili pisania tego tekstu najnowszy jest jest to najnowsza wersja akceptowana przez Seam’a). Odradzam instalowanie wersji 1.7.1. Seam może nas później ukarać komunikatem:
You are using Apache Ant version 1.7.1 compiled on June 27 2008. You must use Ant 1.7.0 to build Seam. Ant 1.7.1 has known bugs.
Rozpakowujemy zawartość archiwum (apache-ant-1.7.0-bin.zip) w wybranym przez nas miejscu. Ja zdecydowałem się na C:Program FilesApache Software FoundationAnt. Przyda nam się zmienna środowiskowa ANT_HOME. Jej wartość w moim przypadku to oczywiście C:Program FilesApache Software FoundationAnt. Aby polecenie ant było dostępne należy do zmiennej środowiskowej Path dodać %ANT_HOME%/bin
Wykonanie polecenia:
ant -version
powinno spowodować wyświetlenie:
Apache Ant version 1.7.0 compiled on December 13 2006
Na przyszłość zainstalowałem sobie Mavena. Procedura identyczna jak w przypadku Anta. Pobieramy archiwum z binarkami i rozpakowujemy je do wybranej lokalizacji (u mnie jest to C:Program FilesApache Software FoundationMaven 2) oraz tworzymy zmienną środowiskową MAVEN_HOME (o wartości C:Program FilesApache Software FoundationMaven 2) a do zmiennej Path dodajemy %MAVEN_HOME%/bin
Polecenie:
mvn -version
powinno poskutkować wyświetleniem się:
Maven version: 2.1.0-M1 Java version: 1.6.0_07 Default locale: pl_PL, platform encoding: Cp1250 OS name: "windows xp" version: "5.1" arch: "x86" family: "windows"
Super! Mamy wszystko czego trzeba. Spróbujmy uruchomić jeden z przykładów dostarczonych razem z frameworkiem JBoss Seam. Przechodzimy do folderu examples/booking w folderze domowym Seam’a i uruchamiamy w konsoli polecenie:
ant deploy
Wynik tego polecenia to:
Buildfile: build.xml initcopy: initpoms: [echo] Setting up dependencies [copy] Copying 1 file to C:Program FilesJBoss-seam-2.1.1.GAclassespoms [artifact:install] [INFO] Installing C:Program FilesJBoss-seam-2.1.1.GAclassespomsroot.pom to C:Documents and SettingsMike.m2repositoryorgjbossseamroot2.1.1.GAroot-2.1.1.GA.pom [copy] Copying 1 file to C:Program FilesJBoss-seam-2.1.1.GAclassespoms [artifact:install] [INFO] Installing C:Program FilesJBoss-seam-2.1.1.GAclassespomsparent.pom to C:Documents and SettingsMike.m2repositoryorgjbossseamparent2.1.1.GAparent-2.1.1.GA.pom [copy] Copying 1 file to C:Program FilesJBoss-seam-2.1.1.GAclassespoms [copy] Copying 1 file to C:Program FilesJBoss-seam-2.1.1.GAclassespoms [copy] Copying 1 file to C:Program FilesJBoss-seam-2.1.1.GAclassespoms [copy] Copying 1 file to C:Program FilesJBoss-seam-2.1.1.GAclassespoms [copy] Copying 1 file to C:Program FilesJBoss-seam-2.1.1.GAclassespoms [copy] Copying 1 file to C:Program FilesJBoss-seam-2.1.1.GAclassespoms [copy] Copying 1 file to C:Program FilesJBoss-seam-2.1.1.GAclassespoms [copy] Copying 1 file to C:Program FilesJBoss-seam-2.1.1.GAclassespoms [copy] Copying 1 file to C:Program FilesJBoss-seam-2.1.1.GAclassespoms [copy] Copying 1 file to C:Program FilesJBoss-seam-2.1.1.GAclassespoms [copy] Copying 1 file to C:Program FilesJBoss-seam-2.1.1.GAclassespoms [copy] Copying 1 file to C:Program FilesJBoss-seam-2.1.1.GAclassespoms [copy] Copying 1 file to C:Program FilesJBoss-seam-2.1.1.GAclassespoms [copy] Copying 1 file to C:Program FilesJBoss-seam-2.1.1.GAclassespoms [copy] Copying 1 file to C:Program FilesJBoss-seam-2.1.1.GAclassespoms copyseam: copyseamdependencies: gettrinidad: getelri: copyextradependencies: init: [echo] Building Seam on JBoss Booking Example 2.1 select-compiler: compile: jar: init.war: war: jboss.war: distributable.war: ear: archive: datasource: service: meldware: deploy: BUILD SUCCESSFUL Total time: 6 seconds
Jak widać wszystko poszło bez zakłóceń. W przeglądarce wpisujemy adres http://localhost:8080/seam-booking i cieszymy się pierwszą aplikacją napisaną w JBoss Seam, którą udało na się uruchomić.
W stronę J2EE
Jest to pierwszy post, który tu zamieszczam i jednocześnie jest to swego rodzaju “o blogu”.
Programowanie to mój zawód, który wykształcił się z pasji, którą było tworzenie stron www. Od kilku lat pracuję nieustannie jako programista PHP. Miałem w swojej karierze również epizod z Javą (ten epizod to ponad półtora roku programowania) lecz nie były to zastosowania webowe lecz programowanie aplikacji standalone.
Od jakiegoś czasu, chciałbym powrócić do Javy tyle, że w kontekście aplikacji www. Przejście takie nie jest łatwe, nawet pomimo pewnego doświadczenia, które posiadam. Praca w ciągu dnia zawodowo w jednej technologii pochłania dużo czasu, który jest potrzebny na nauczenie się drugiej. Z tego powodu czekają mnie długie, pasjonujące wieczory oraz z tęsknotą wyczekiwane weekendy, kiedy będę mógł zgłębiać tajniki J2EE. W skrócie: ciężka praca. Praca, na którą bardzo się cieszę.
W pierwszej kolejności postanowiłem opanować framework JBoss Seam, który jest typowym frameworkiem webowym, w przeciwieństwie, na przykład do Springa. Oczywiście, jeśli chcę myśleć poważnie o odnalezieniu się w świecie J2EE Spring jest jazdą obowiązkową ale na początek uraczę się czymś mniejszym. Myślę, że to dobry początek. Nauka frameworka JBoss Seam będzie świetną okazją do odświeżenia sobie wiedzy związanej z narzędziami takimi jak Hibernate, Maven czy Ant. Poza tym Seam łączy w sobie przede wszystkim JSF (podstawy znam) oraz EJB, których znajomość wydaje mi się podstawą. Jak już opanuję Seama w stopniu mnie satysfakcjonującym przejdę dalej.
Na końcu, po co jest ten blog? Otóż postanowiłem go założyć żeby mieć miejsce na publikowanie własnych spostrzeżeń, pytań oraz wniosków nasuwających mi się podczas nauki J2EE. Mam nadzieję, że będzie to taki notatnik. Czy będę publikował często i sensownie? Nie wiem, ja tu dopiero ledwie sprzątam.
P.S.
W miejscu tego bloga prowadziłem kiedyś bloga związanego z PHP. Nie była to długa przygoda ale udało mi się “popełnić” kilka ciekawych (w moim mniemaniu) tekstów. Jeśli ktoś chciałby je odnaleźć może skorzystać z serwisu Internet Archive, gdzie znajduje się ostatnia wersja tamtego bloga.

