streda 2. septembra 2009

Jednoduché generovanie manifestu pomocou nástroja ANT


Pohľad na bojové pole
Na jednej strane je J2EE aplikácia zabalená ako EAR, vygenerovaná seam-gen skriptom, ktorá obsahuje EJB modul JAR a webovú časť aplikácie WAR.
Zjednodušená štruktúra aplikácie:
  • myapp.ear
    • myapp-ejb.jar
    • lib
      • richfaces-api.jar
      • ...
    • myapp-web.war
      • WEB-INF
        • lib
          • richfaces-ui.jar
          • richfaces-impl.jar
          • ...
  • myapp.ear/lib - je adresár, ktorý obsahuje knižnice implicitne viditeľné iba z myapp-ejb.jar
  • myapp.ear/myapp-web.war/WEB-INF/lib - knižnice v tomto adresári sú naopak viditeľné len pre myapp-web.war
Na druhej strane, je celkom bežná potreba, použiť niektoré knižnice na oboch miestach. Ako riešiť túto situáciu? Skopírovanie danej knižnice do oboch lib adresárov problém nerieši. Pretože sa môže napríklad stať, že trieda z danej knižnice je návratovou hodnotu metódy session beanu použitej v servlete. V tomto prípade by si web kontajner sťažoval, že trieda, ktorú mu vrátil session bean do servletu nieje tá, ktorú skutočne očakával.

Riešenie
Jedno z riešení spočíva v tom, že knižnice z adresáru myapp.ear/myapp-web.war/WEB-INF/lib okopírujeme do myapp.ear/lib a vytvoríme manifest súbor s classpath a umiestnime ho sem myapp.ear/myapp-web.war/META-INF/MANIFEST.MF.
Modifikovaná štruktúra aplikácie:
  • myapp.ear
    • myapp-ejb.jar
    • lib
      • richfaces-api.jar
      • richfaces-ui.jar
      • richfaces-impl.jar
      • ...
    • myapp-web.war
      • META-INF
        • MANIFEST.MF
Pričom obsah súboru MANIFEST.MF by vyzeral takto:

Class-Path: lib/richfaces-impl.jar lib/richfaces-ui.jar

Za povšimnutie stojí, že cesta v manifeste, je relatívna ku koreňu EAR súboru. Výsledkom je, že všetky knižnice sú viditeľné pre EJB modul a pre web modul sú viditeľné knižnice richfaces-impl.jar a richfaces-ui.jar. Tento manifest súbor sa dá samozrejme napísať aj ručne, ale zvyčajne je v classpath-e oveľa viac záznamov a keďže povolená dĺžka riadku je v manifest špecifikácii je obmedzená ľahko sa môže stať, že ručne napísaný manifest bude chybný.

Generovanie MANIFEST.MF s classpath pomocou ANT
Projekt vygenerovaný seam-gen skriptom používa na kopírovanie knižníc do war súboru následujúcu časť kódu.
<copy todir="${war.dir}/WEB-INF/lib">
  <fileset dir="${lib.dir}">
      <includesfile name="deployed-jars-war.list"/>
      <exclude name="jboss-seam-gen.jar"/>
      <exclude name="jboss-seam-debug.jar" unless="is.debug"/>
  </fileset>
</copy>
  • deployed-jars-war.list je textový súbor, ktorý obsahuje zoznam knižníc, ktoré sa kopírujú do myapp.ear/myapp-web.war/WEB-INF/lib (na jednom riadku je jedno meno knižnice)
V tomto prípade by deployed-jars-war.list vyzeral takto:

richfaces-impl.jar
richfaces-ui.jar


Modifikovaný ANT skript, ktorý nič nekopíruje, ale namiesto toho vytvorí manifest súbor s classpath záznamom.
<path id="war.classpath.path">
   <fileset dir="${lib.dir}">
       <includesfile name="deployed-jars-war.list"/>
       <exclude name="jboss-seam-gen.jar"/>
       <exclude name="jboss-seam-debug.jar" unless="is.debug"/>
   </fileset>
</path>

<manifestclasspath property="war.classpath" jarfile="${project.name}_war">
   <classpath refid="war.classpath.path" />
</manifestclasspath>

<mkdir dir="${war.dir}/META-INF"/>

<manifest file="${war.dir}/META-INF/MANIFEST.MF">
   <attribute name="Class-path" value="${war.classpath}"/>
</manifest>