Egg Framework i Manifest Październikowy
Dobry projekt w javie powinien charakteryzować się, moim zdaniem, dobrym upakowaniem. Idealną sytuacją jest taka w której cały projekt mieści się w jednym pliku jar. Niestety osiągnięcie takiego stanu rzeczy jest w praktyce niemożliwe. Sun jak na razie nie uszczęśliwił nas możliwością ładowania pliku .jar z innego pliku .jar. Jest to niezły wrzód na tyłku. Na całe szczęście w manifeście można dodać pole Class-Path. Nie jest to oczywiście rozwiązanie problemu ponieważ pliki manifestu mają, wbrew obiegowym opiniom, dość skomplikowaną budowę oraz istnieją dość poważne obostrzenia w tworzeniu tych plików. Jednym z najważniejszych jest maksymalna długość pojedynczej linii w pliku ograniczona do 72 bajtów dla wartości i 70 dla klucza. Ze specyfikacji:
No line may be longer than 72 bytes (not characters), in its UTF8-encoded form. If a value would make the initial line longer than this, it should be continued on extra lines (each starting with a single SPACE).
Można niewątpliwie kur#@!$ się niepomiernie w momencie gdy chcemy dodać więcej niż jedną, dwie zależności. Zazwyczaj lądujemy wtedy z jakimś dziwnym błędem w stylu LineTooLongException lub IOException. Oczywiście specyfikacja pozwala na deklarowanie wartości w wielu liniach, jednak jest to dość skomplikowane (wina durnego windowsa ze swoim \r\n). Lepiej zwalić to na mavena.
Egg – konfiguracja manifestu
Każda aplikacja napisana w Egg bezwzględnie musi mieć na podorędziu wszelkie biblioteki od których jest zależna. Pełen spis bibliotek wymaganych do ruszenia „gołej” aplikacji:
- egg-0.9M3.jar
- servlet-api-2.4.jar
- 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
- 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
- spring-aop-1.2.5.jar
- spring-beans-1.2.5.jar
- spring-context-1.2.5.jar
- spring-core-1.2.5.jar
- spring-web-1.2.5.jar
- standard-1.0.6.jar
- xml-apis-1.0.b2.jar
Do tego należy dodać jeszcze jara ze sterownikami do bazy danych i inne biblioteki z których korzystamy. Jak widać trochę tego jest dlatego też warto do pom.xml dorzucić odpowiedni fragment kodu:
Listing 1. Konfiguracja maven-jar-plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<finalName>egg-example</finalName>
<includes>
C:\Java\jars\egg-0.9M3\lib\*.jar,C:\Java\jars\egg-0.9M3\*.jar
</includes>
<archive>
<manifest>
<mainClass>eu.runelord.Main</mainClass>
<addClasspath>true</addClasspath>
</manifest>
<manifestEntries>
<Class-Path>
lib/egg-0.9M3.jar lib/servlet-api-2.4.jar
lib/aopalliance-1.0.jar
lib/avalon-framework-4.1.3.jar
lib/commons-beanutils-1.6.jar
lib/commons-collections-2.1.jar
lib/commons-digester-1.7.jar
lib/commons-fileupload-1.2.jar
lib/commons-io-1.2.jar lib/commons-logging-1.1.jar
lib/ehcache-1.2.jar
lib/jasper-compiler-4.2.20RC0.jar
lib/jasper-runtime-4.2.20RC0.jar
lib/javassist-3.0.jar lib/jsp-api-2.0.jar
lib/jstl-1.0.jar lib/junit-3.8.1.jar
lib/log4j-1.2.12.jar lib/logkit-1.0.1.jar
lib/org.mortbay.jetty-5.1.9.jar lib/oro-2.0.8.jar
lib/spring-aop-1.2.5.jar lib/spring-beans-1.2.5.jar
lib/spring-context-1.2.5.jar
lib/spring-core-1.2.5.jar lib/spring-web-1.2.5.jar
lib/standard-1.0.6.jar lib/xml-apis-1.0.b2.jar
</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
Następnie w linii poleceń wołamy mavena:
mvn clean compile jar:jar
i mamy jara w katalogu target, ale jest jeszcze nie do końca wszytko bangla. Fajnie by było gdybyśmy nie musieli ręcznie kopiować wszystkich jarów z src/lib do target/lib. No to zapędzimy naszego M2 do roboty. W pom.xml wystarczy dodać:
Listing 2. Konfiguracja maven-antrun-plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<id>run-copy</id>
<goals>
<goal>run</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
<configuration>
<tasks>
<copy todir="target/lib/">
<fileset dir="src/lib/" includes="*.jar" />
</copy>
</tasks>
</configuration>
</plugin>
i po problemie.
Teraz wystarczy tylko wejść do katalogu target i wywołać:
java -jar egg-example
i wszytko działa 🙂
Na teraz koniec.