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.