Sprężyste jaja na wiosnę – cz. 1 – potrzebne produkty
Po dłuższej nieobecności na łamy bloga wraca Egg Framework. Wraca w postaci dłuższego tutoriala poświęconego tworzeniu aplikacji Egg + Spring. Tutorial będzie składał się z kilku części. Pierwsza z nich będzie poświęcona przygotowaniom do pracy oraz stworzę w niej najprostszą aplikację Eggową. W drugiej części przedstawię podstawy wiązania Egga i Springa, a w trzeciej dokończymy pisać naszą aplikację wzbogacając ją o szablony i przygotowując paczkę dystrybucyjną.
Co nam będzie potrzebne.
Aplikacje będziemy budowali za pomocą Mavena 2. Jeżeli go nie masz to ściągnij i zainstaluj. Następnie należy pobrać Egg Framwork ze strony projektu. Po rozpakowaniu archiwum otrzymamy dostęp do źródeł oraz przygotowanych zawczasu plików jar. W linii poleceń wchodzimy do katalogu sources/egg2 i następnie uruchamiamy proces kompilacji i instalacji egga:
Listing 1
mvn clean compile install
Egg zainstaluje się w lokalnym repo mavena. Ważne dla nas informacje znajdują się na samym początku logu:
Listing 2
[INFO] Scanning for projects...<br></br>[INFO] Reactor build order:<br></br>[INFO] Egg Framework 2.0<br></br>[INFO] Egg 2 Core<br></br>[INFO] Egg 2 Tests Support<br></br>[INFO] Egg 2 Model<br></br>[INFO] Egg 2 View<br></br>[INFO] Egg 2 Controller<br></br>[INFO] Egg 2 Xhtml View Tags<br></br>[INFO] Egg 2 Server<br></br>[INFO] Egg 2 Controller Examples<br></br>[INFO] Egg 2 View Examples<br></br>[INFO] Egg 2 View Spring MVC Integration<br></br>[INFO] Egg 2 View SpringMVC Examples<br></br>[INFO] Egg 2 Xhtml View Examples<br></br>[INFO] Egg 2 Xhtml Prototype Support (AJAX)<br></br>[INFO] Egg 2 Xhtml Prototype Examples (AJAX examples)
Jest to spis wszystkich dostępnych modułów egga. Cały proces budowania trwał na moim kompie około 2 i pół minuty. Mamy już główną zalezność dla naszego przyszłego projektu, ale nadal nie mamy samego projektu. Czas zatem utworzyć nowy projekt w mavenie.
Przygotowanie projektu
Wystarczy w linii poleceń wydać komendę:
Listing 3
mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes /<br></br>-DgroupId=org.runelord.tutorials.egg -DartifactId=egg-spring-tutorial
Po około 3 sekundach zostanie utworzony katalog egg-spring-tutorial o następującej strukturze:
Listing 4
\egg-spring-tutorial<br></br> |-pom.xml<br></br> \src<br></br> \main<br></br> \java<br></br> \org<br></br> \runelord<br></br> \tutorial<br></br> \egg<br></br> |-App.java<br></br> \test<br></br> \java<br></br> \org<br></br> \runelord<br></br> \tutorial<br></br> \egg<br></br> |-AppTest.java
Jak widać utworzony został plik pom.xml oraz testowa klasa i test do niej. Kolejnym krokiem jest przerobienie naszego projektu na projekt Eclipse:
Listing 5
mvn eclipse:eclipse
Jako że mamy wolność to możemy też zrobić projekt netbeansowy lub dowolny inny o ile będziemy wiedzieli jak. Z tego też powodu nie będę wspierał się screeenshotami. Zapewne połowa z was będzie ruszała netbeansa zatem nie ma to sensu. Następnie w katalogu src/main musimy dodać kilka karalogów by w końcu otrzymać taki oto projekt:
Listing 6
\egg-spring-tutorial<br></br> |-.classpath<br></br> |-.project<br></br> |-pom.xml<br></br> \src<br></br> \main<br></br> \java<br></br> \org<br></br> \runelord<br></br> \tutorial<br></br> \egg<br></br> |-App.java<br></br> \lib<br></br> \resources<br></br> \webapp<br></br> \test<br></br> \java<br></br> \org<br></br> \runelord<br></br> \tutorial<br></br> \egg<br></br> |-AppTest.java<br></br> \target<br></br> |-mvn-eclipse-cache.properties
Teraz należy dodać kilka zależności do naszego pliku pom.xml, aby w rezultacie otrzymać coś takiego:
Listing 7
<project xmlns="http://maven.apache.org/POM/4.0.0"<br></br> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br></br> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><br></br> <modelVersion>4.0.0</modelVersion><br></br> <groupId>org.runelord.tutorial.egg</groupId><br></br> <artifactId>egg-spring-tutorial</artifactId><br></br> <packaging>jar</packaging><br></br> <version>1.0-SNAPSHOT</version><br></br> <name>egg-spring-tutorial</name><br></br> <url>http://maven.apache.org</url><br></br> <properties></properties><br></br> <build><br></br> <outputDirectory><br></br> ${basedir}/target/WEB-INF/classes<br></br> </outputDirectory><br></br> <plugins><br></br> <plugin><br></br> <groupId>org.apache.maven.plugins</groupId><br></br> <artifactId>maven-compiler-plugin</artifactId><br></br> <configuration><br></br> <source>1.5</source><br></br> <target>1.5</target><br></br> <encoding>${project.encoding}</encoding><br></br> </configuration><br></br> </plugin><br></br> </plugins><br></br> </build><br></br> <dependencies><br></br> <dependency><br></br> <groupId>junit</groupId><br></br> <artifactId>junit</artifactId><br></br> <version>[3.8.1, )</version><br></br> <scope>test</scope><br></br> </dependency><br></br> <dependency><br></br> <groupId>org.springframework</groupId><br></br> <artifactId>spring</artifactId><br></br> <version>[2.0.7, )</version><br></br> </dependency><br></br> <dependency><br></br> <groupId>org.eggframework</groupId><br></br> <artifactId>egg2-core</artifactId><br></br> <version>2.0M1-SNAPSHOT</version><br></br> </dependency><br></br> <dependency><br></br> <groupId>org.eggframework</groupId><br></br> <artifactId>egg2-server</artifactId><br></br> <version>2.0M1-SNAPSHOT</version><br></br> </dependency><br></br> <dependency><br></br> <groupId>org.eggframework</groupId><br></br> <artifactId>egg2-view-springmvc</artifactId><br></br> <version>2.0M1-SNAPSHOT</version><br></br> </dependency><br></br> <dependency><br></br> <groupId>org.eggframework</groupId><br></br> <artifactId>egg2-view-xhtml</artifactId><br></br> <version>2.0M1-SNAPSHOT</version><br></br> </dependency><br></br> </dependencies><br></br></project>
Kolejnym krokiem będzie uruchomienie mavena w celu ściągnięcia zależności.
Listing 8
mvn compile
Dlaczego teraz? Otóż jeżeli będzie nam brakowało jakiejś zależności to zostanie ona pobrana z netu. Może być to proces czasochłonny, a zatem warto zrobić to już na samym początku, by później móc skupić się na pisaniu kodu.
Mamy już gotowe wstępne środowisko dla naszego projektu. Jednak, aby całość banglała jak skowronek o poranku należy wykonać jeszcze jedną rzecz. Do katalogu src/lib musimy skopiować następujące pliki:
- aopalliance-1.0.jar
- avalon-framework-4.1.3.jar
- commons-beanutils-1.6.jar
- commons-collections-2.1.jar
- commons-digester-1.7.jar
- commons-fileupload-1.2.jar
- commons-io-1.2.jar
- commons-logging-1.1.jar
- egg2-2.0M1-SNAPSHOT.jar
- egg2-controller-2.0M1-SNAPSHOT.jar
- egg2-controller-springmvc-2.0M1-SNAPSHOT.jar
- egg2-core-2.0M1-SNAPSHOT.jar
- egg2-model-2.0M1-SNAPSHOT.jar
- egg2-server-2.0M1-SNAPSHOT.jar
- egg2-view-2.0M1-SNAPSHOT.jar
- egg2-view-springmvc-2.0M1-SNAPSHOT.jar
- egg2-view-xhtml-2.0M1-SNAPSHOT.jar
- ehcache-1.2.jar
- jasper-compiler-4.2.20RC0.jar
- jasper-runtime-4.2.20RC0.jar
- javassist-3.0.jar
- jsp-api-2.0.jar
- jstl-1.0.jar
- junit-3.8.1.jar
- log4j-1.2.12.jar
- logkit-1.0.1.jar
- org.mortbay.jetty-5.1.9.jar
- oro-2.0.8.jar
- servlet-api-2.4.jar
- spring-2.0.7.jar
- standard-1.0.6.jar
- stax-1.2.0.jar
- stax-api-1.0.1.jar
- xml-apis-1.0.b2.jar
Dzięki temu w późniejszych etapach będziemy mogli stworzyć archiwum dystrybucyjne war. Czas na pierwszą prostą aplikację
Przystępujemy do gotowania
Wielką zaletą egga jest wbudowany serwer Jetty. Wystarczy zatem napisać małą klasę , która uruchomi się jak zwykła aplikacja. Najprostszy sposób na uruchomienie naszego serwera to implementacja metody main:
Listing 9
package org.runelord.tutorial.egg;<br></br><br></br>import org.eggframework2.server.EggServer;<br></br><br></br>public class Main {<br></br> public static void main( String[] args ) throws Exception<br></br> {<br></br> EggServer.startWebApp(18080, "/egg", "target");<br></br> }<br></br>}
Jak widać serwer będzie działał na porcie 18080, kontekst /egg,/samp>, a aplikacji należy szukać w katalogutarget. Uruchamiamy i…
Listing 10
log4j:WARN No appenders could be found for logger (org.mortbay.util.Container).<br></br>log4j:WARN Please initialize the log4j system properly.
… no i dupa mówiąc krótko. W rzeczywistości, świadomie, pominąłem jedną dość istotną czynność. Nigdzie nie utworzyłem pliku web.xml. Czas zatem powrócić do edycji pliku pom.xml. Jego nowa wersja wzbogaciła się o fragment:
Listing 11
<plugin><br></br> <groupId>org.apache.maven.plugins</groupId><br></br> <artifactId>maven-antrun-plugin</artifactId><br></br> <version>1.1</version><br></br> <executions><br></br> <execution><br></br> <id>run</id><br></br> <goals><br></br> <goal>run</goal><br></br> </goals><br></br> <phase>compile</phase><br></br> <configuration><br></br> <tasks><br></br> <copy todir="${basedir}/target/WEB-INF"><br></br> <fileset<br></br> dir="${basedir}/src/main/webapp/WEB-INF/" includes="*.xml" /><br></br> <fileset dir="${basedir}/src/main/resources/"<br></br> includes="*.properties" /><br></br> </copy><br></br> <copy todir="${basedir}/target/WEB-INF/lib"><br></br> <fileset dir="${basedir}/src/main/lib/"<br></br> includes="*.jar" /><br></br> </copy><br></br> <copy todir="${basedir}/target/template"><br></br> <fileset<br></br> dir="${basedir}/src/main/webapp/WEB-INF/template/"<br></br> includes="*.html" /><br></br> </copy><br></br> <copy todir="${basedir}/target/"><br></br> <fileset dir="${basedir}/src/main/webapp/html"<br></br> includes="*.html" /><br></br> </copy><br></br> </tasks><br></br> </configuration><br></br> </execution><br></br> </executions><br></br></plugin>
Spowoduje to, że w trakcie kompilacji zostaną skopiowane pliki properties, xml i jar do odpowiednich katalogow w katalogu target. Dodatkowo należy jeszcze utworzyć plik web.xml w katalogu src/main/webapp/WEB-INF. Bedzie on wyglądał w następujacy sposób:
Listing 12
<?xml version="1.0" encoding="UTF-8"?><br></br><br></br><web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"<br></br> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br></br> xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee<br></br> http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"><br></br><br></br> <servlet id="egg"><br></br> <servlet-name>example</servlet-name><br></br> <servlet-class><br></br> org.springframework.web.servlet.DispatcherServlet<br></br> </servlet-class><br></br> <load-on-startup>1</load-on-startup><br></br> </servlet><br></br><br></br> <servlet-mapping><br></br> <servlet-name>egg</servlet-name><br></br> <url-pattern>*.egg</url-pattern><br></br> </servlet-mapping><br></br><br></br> <welcome-file-list><br></br> <welcome-file>/index.egg</welcome-file><br></br> <welcome-file>/index.html</welcome-file><br></br> </welcome-file-list><br></br></web-app>
Skoro mamy już serwlet egg i klasę dispatchera ze springa to musimy jeszcze w tym samym katalogu utworzyć plik egg-servlet.xml:
Listing 13
<?xml version="1.0" encoding="UTF-8"?><br></br><br></br><beans><br></br> <!-- view resolver --><br></br> <bean id="viewResolver"<br></br> class="org.eggframework2.view.springmvc.EggSiteViewResolver"><br></br> </bean><br></br></beans>
Przy okazji dodałem odrazu konfigurację view resolvera. Dobra teraz czas to wszytko uruchomić
Listing 14
mvn clean compile
Poszło. Nieźle o fakcie kopiowania plików poinformował mnie maven:
Listing 15
[INFO] [antrun:run {execution: run}]<br></br>[INFO] Executing tasks<br></br> [copy] Copying 3 files to D:\tutorials\Egg2\egg-spring-tutorial\target\WEB-INF<br></br> [copy] Copying 34 files to D:\tutorials\Egg2\egg-spring-tutorial\target\WEB-INF\lib
No dobra… tego jeszcze nie da się uruchomić z linii poleceń, ale zostało skompilowane poprawnie. Na tym etapie poprawna kompilacja nas zadowala. Uruchamiać będziemy aplikaję z poziomu IDE.
Ten ostatni akt wali ze środowiskiem skupił się na dodaniu do źródeł katalogu src/main/resources/ i wskazaniu katalogu docelowego na target/WEB-INF/classes. Naciskamy Alt+Shift+x a potem j i…
Listing 16
INFO - Version Jetty/5.1.9<br></br>INFO - Checking Resource aliases<br></br>WARN - Invalid welcome file: /index.egg<br></br>WARN - Invalid welcome file: /index.html<br></br>INFO - Started org.mortbay.jetty.servlet.WebApplicationHandler@8c436b<br></br>INFO - Parent class loader is: sun.misc.Launcher$AppClassLoader@18e3e60<br></br>INFO - Scratch dir for the JSP engine is: C:\DOCUME~1\koziolek\LOCALS~1\Temp\Jetty__18080__egg<br></br>INFO - IMPORTANT: Do not modify the generated servlets<br></br>INFO - Initializing Spring FrameworkServlet 'egg'<br></br>INFO - Started WebApplicationContext[/egg,/egg]<br></br>INFO - Started SocketListener on 0.0.0.0:18080<br></br>INFO - Started org.mortbay.jetty.Server@121cc40
… a pod adresem http://localhost:18080/egg/…