JBoss 7 ed EclipseLink 2: una coppia quasi perfetta – Parte II (a.k.a weaving statico con Maven)

Recentemente abbiamo visto le difficoltà incontrate nel far andare d’amore e d’accordo JBoss 7.0.2 ed EclipseLink 2.3. Probabilmente i problemi incontrati dipendevano dal fatto che la versione 7.0.2 non era completamente Java EE complinant, ma lo era solo per il profilo web. Con la nuova versione di JBoss (al momento 7.1.1) le cose sono leggermente migliorate ma, come anticipato, è meglio aggiornare anche EclipseLink alla versione 2.4. Vediamo perché.

La nuova coppia: JBoss AS 7.1.x e EclipseLink 2.4

Partendo dalla situazione del post precedente, se proviamo ad aggiornare esclusivamente il server, al momento del deploy la console ci avvisa che non è presente il modulo per il Persistence Provider specificato! Questa è una novità rispetto a prima! Non possiamo quindi più tenere il jar di EclipseLink nel nostro EAR, ma dobbiamo creare per forza un modulo JBoss. Niente di più facile, come spiega un tutorial di JBoss (che consiglia almeno la versione 2.3.3 di EclipseLink). Basta scaricare EclipseLink e copiare il file eclipselink.jar (magari rinominandolo in eclipselink-2.4.0.jar per tenere traccia della versione) nella cartella del server $JBOSS_HOME/modules/org/eclipse/persistence/main. Sempre in questa cartella, creare il file module.xml con il seguente contenuto:

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="org.eclipse.persistence">
 <resources>
  <resource-root path="eclipselink-2.4.0.jar"/>
 </resources>
 <dependencies>
  <module name="asm.asm"/>
  <module name="javax.api"/>
  <module name="javax.persistence.api"/>
  <module name="javax.transaction.api"/>
  <module name="javax.validation.api"/>
  <module name="javax.xml.bind.api"/>
  <module name="org.antlr"/>
  <module name="org.apache.commons.collections"/>
  <module name="org.dom4j"/>
  <module name="org.javassist"/>
  <module name="org.jboss.logging"/>
 </dependencies>
</module>

Fatto! Il modulo è creato! Nel persistence.xml possiamo mettere tranquillamente la target platform di default (che a differenza di JBoss 7.0.2 questa volta funziona):

<property name="eclipselink.target-server" value="JBoss"/>

Riavviamo il server e se avete l’ultima versione non ci dovrebbero essere problemi.

Lazy Loading che passione

Se usiamo infatti una versione di EclipseLink inferiore alla 2.3.3, anche con weaving statico attivato con Ant (come visto nel post precedente) i comportamenti lazy vengono clamorosamente ignorati…

Purtroppo il mancato funzionamento del weaving dinamico dipende da un bug che gli sviluppatori di JBoss fisseranno nella versione 7.2. Nel frattempo, armiamoci di pazienza e di Ant.. oppure di Maven! Infatti esiste un plugin Maven che ci permette di evitare il lancio dello script Ant visto nel post precedente ad ogni modifica del nostro progetto JPA, eseguendo per noi il weaving statico in modo trasparente in fase di compilazione. Questa magia è possibile grazie al plugin eclipselink-staticweave-maven-plugin. Per prima cosa, nel pom.xml (non sapete cos’è un pom? Niente paura! C’è un post giusto giusto per voi…) dobbiamo aggiungere un nuovo repository:

<repositories>
  <repository>
    <id>eclipselink</id>
    <url>http://download.eclipse.org/rt/eclipselink/maven.repo/</url>
  </repository>
</repositories>

Aggiungiamo poi EclipseLink

<dependencies>
   <dependency>
      <groupId>org.eclipse.persistence</groupId>
      <artifactId>eclipselink</artifactId>
      <version>${version.eclipselink}</version>
      <scope>provided</scope>
   </dependency>
</dependencies>

con scope provided, perché lo abbiamo già caricato come modulo in JBoss, e versione regolata dalla property:

<properties>
   <version.eclipselink>2.4.0</version.eclipselink>
</properties>

Infine, aggiungiamo il plugin, con la sua dipendenza da EclipseLink:

<build>
   <plugins>
      <plugin>
         <groupId>au.com.alderaan</groupId>
         <artifactId>eclipselink-staticweave-maven-plugin</artifactId>
         <version>1.0.3</version>
         <executions>
            <execution>
               <phase>process-classes</phase>
               <goals>
                  <goal>weave</goal>
               </goals>
               <configuration>
                  <logLevel>ALL</logLevel>
               </configuration>
            </execution>
         </executions>
         <dependencies>
            <dependency>
               <groupId>org.eclipse.persistence</groupId>
               <artifactId>eclipselink</artifactId>
               <version>${version.eclipselink}</version>
            </dependency>
            <dependency>
               <groupId>org.eclipse.persistence</groupId>
               <artifactId>javax.persistence</artifactId>
               <version>2.0.0</version>
            </dependency>
         </dependencies>
      </plugin>
   </plugins>
</build>

Se stiamo usando Maven da Eclipse, probabilmente ci saranno diversi warning: per metterli a tacere aggiungere il seguente codice per m2eclipse prima della chiusura del blocco build:

<pluginManagement>
  <plugins>
    <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
    <plugin>
      <groupId>org.eclipse.m2e</groupId>
      <artifactId>lifecycle-mapping</artifactId>
      <version>1.0.0</version>
      <configuration>
        <lifecycleMappingMetadata>
          <pluginExecutions>
            <pluginExecution>
              <pluginExecutionFilter>
                <groupId>
                  au.com.alderaan
                </groupId>
                <artifactId>
                  eclipselink-staticweave-maven-plugin
                </artifactId>
                <versionRange>
                  [1.0.3,)
                </versionRange>
                <goals>
                  <goal>weave</goal>
                </goals>
              </pluginExecutionFilter>
              <action>
                <execute/>
              </action>
            </pluginExecution>
          </pluginExecutions>
        </lifecycleMappingMetadata>
      </configuration>
    </plugin>
  </plugins>
</pluginManagement>

Se questo non bastasse… ignorate il resto 😉

A questo punto non resta che rifare un build del progetto e farsi un giro nell’applicazione con un occhio alle query in console! Se per caso avete problemi di risorse out-of-sync, ricordatevi di abilitare il refresh automatico all’accesso delle risorse in Eclipse: Settings > General > Workspace > Refresh On Access.

Conclusioni

Usare EclipseLink con JBoss sicuramente è più facile con le ultime versioni. Usare inoltre Maven per rendere completamente trasparente il weaving statico (e non solo…) è sicuramente molto più comodo di ricordarsi di lanciare lo script Ant ad ogni modifica.
Attendiamo con ansia la versione 7.2 di JBoss per vedere se finalmente potremmo abbandonare tutte le soluzioni, anche se quest’ultima non “disturba” affatto!

Andrea Como

Sono un software engineer focalizzato nella progettazione e sviluppo di applicazioni web in Java. Presso OmniaGroup ricopro il ruolo di Tech Leader sulle tecnologie legate alla piattaforma Java EE 5 (come WebSphere 7.0, EJB3, JPA 1 (EclipseLink), JSF 1.2 (Mojarra) e RichFaces 3) e Java EE 6 con JBoss AS 7, in particolare di CDI, JAX-RS, nonché di EJB 3.1, JPA2, JSF2 e RichFaces 4. Al momento mi occupo di ECM, in particolar modo sulla customizzazione di Alfresco 4 e sulla sua installazione con tecnologie da devops come Vagrant e Chef. In passato ho lavorato con la piattaforma alternativa alla enterprise per lo sviluppo web: Java SE 6, Tomcat 6, Hibernate 3 e Spring 2.5. Nei ritagli di tempo sviluppo siti web in PHP e ASP. Per maggiori informazioni consulta il mio curriculum pubblico. Follow me on Twitter - LinkedIn profile - Google+

  • Ciao, ti vorrei chiedere perchè usare EclipseLink invece di usare la soluzione più naturale con jboss, e cioè Hibernate?

    • Ciao,
      la scelta di Eclipselink rispetto ad Hibernate può essere abbastanza indifferente se ci si limita ad usare le funzionalità coperte dalla specifica JPA. Personalmente ho cominciato ad usare Eclipselink per motivi di lavoro, perché supporta le chiamate alle stored procedure Oracle. 
      Nel tempo ho cominciato però a preferire questa implementazione JPA per qualche sua differenza rispetto ad Hibernate: non “soffre” della LazyInitializationException, rispetta i fetch hint che specifichi nelle relazioni OneToOne (per esempio), permette di creare convertitori sui tipi in modo dichiarativo senza implementare interfacce tipo UserType per intendersi…
      E soprattutto vengono mostrati i binding dei valori delle query direttamente in console senza impazzire!

      Spero di averti convinto 😉

      • Interessante… lo terrò in considerazione. Grazie