MokaByte 75 - Giugno 2003 
Setup di architetture J2EE
JBossCMP il modulo di JBoss 2.4.x per la gestione della persistenza degli entity bean
di
Davide Brusamolino
Attraverso il CMP (Container-Managed Persistence) il container si occupa della persistenza del bean. Il supporto alla persistenza fornito dal server EJB varia da produttore a produttore, a seconda degli strumenti piu' o meno sofisticati utilizzati per mappare i campi del bean all'interno del database. Lo sviluppo di entity bean utilizzando la CMP permette allo sviluppatore di concentrarsi solo sulla business logic tralasciando la parte di interazione col database poiché gestita dal container.

JAWS
Il Just Another Web Storege è l'object-to-relational (O-R) utilizzato da JBoss per la gestione CMP degli entity beans. JAWS permette al container di JBoss di utilizzare una sorgente JBDC per rendere persistente il mio EJB, ovvero svolge il compito di mappatura tra gli oggetti e/o primitivi java della mia applicazione con i tipi di dati gestiti dalla mia sorgente JDBC.
Questo compito è svolto da un file 'globale' di default fornito da JBoss, 'standardjaws.xml', posto nella directory jboss\conf\default.
La configurazione di standardjaws.xml è tale per utilizzare come risorsa JDBC HypersonicDB; se voglio apportare una modifica a questo ambiente posso o cambiare questo file globale o creare per ogni applicazione un proprio file chiamato jaws.xml.
E' superfluo ricordare che una modifica di standardjaws.xml ricade su ogni applicazione attiva in jboss. Quindi per una maggior elasticità del sistema è utile all'occorrenza creare un proprio jaws.xml e metterlo nella directory META-INF del jar file che contiene i miei EJB.
La struttura sia di standardjaws.xml che di jaws.xml è la seguente:


Figura 1

La traccia da seguire per creare un nuovo file jaws è la seguente:
1) DataSource e mappatura Java-SQL
2) Opzioni globali
3) Entity bean
4) Metodi di finder


DataSource e mappatura Java-SQL
Questo elemento mi specifica il JNDI name associato alla mia risorsa JDBC. Il valore di default è data da 'java:/DefaultDS' che si rifà al valore dell'MBean di default per la gestione del pool, specificato nel file jboss.jcml (articolo aprile 2003).
Se cambio questo nome di default nel file jboss.jcml ( es OracleDS ) anche qui devo specificare il nuovo nome 'java:/OracleDS'.

Se la nuova sorgente JDBC utilizza una mappatura dati non specificata nel file standardjaws.xml devo o rifarmi ad una esistente (se uguale a quella del nuovo sorgente JDBC) o specificare la nuova all'interno del nuovo file jaws.xml.
Es standardjaws.xml:

<jaws>
<datasource>java:/DefaultDS</datasource>
<type-mapping>Hypersonic SQL</type-mapping>
<debug>false</debug>

<default-entity>
<create-table>true</create-table>
<remove-table>false</remove-table>
<tuned-updates>true</tuned-updates>
<read-only>false</read-only>
<time-out>300</time-out>
<select-for-update>false</select-for-update>
</default-entity>

<type-mapping>
<name>Oracle8</name>
<mapping>
<java-type>java.lang.Boolean</java-type>
<jdbc-type>BIT</jdbc-type>
<sql-type>NUMBER(1)</sql-type>
</mapping>
<mapping>
<java-type>java.lang.Byte</java-type>
<jdbc-type>NUMERIC</jdbc-type>
<sql-type>NUMBER(3)</sql-type>
</mapping>
…………
………… …….
…….
</type-mapping>
</jaws>

In particolare attraverso il tag java-type specifico il dato primitivo o la classe java; jdbc-type è la mappatura tra la classe java e il tipo jdbc, in fine sql-type mi specifica il tipo che utilizzo nel database per mappare il mio dato di partenza.

 

Opzioni globali
Queste opzioni sono facoltative e possono servire all'utente per svariati motivi. Per esempio il tag debag se specificato permette all'utente di controllare l'attività SQL su file di log e tenerne quindi traccia.

Entity bean
JAWS di default associa ad una tabella di database un EJB e ad ogni campo del mio EJB una colonna della mia tabella.
Per far questo pone il nome della tabella uguale a quella del mio EJB e il nome della colonna uguale al campo del mio EJB.
E' possibile tramite JAWS creare questa tabella se non esiste e gestirne la sua persistenza durante il ciclo di vita della mia applicazione.
Se voglio ottenere un comportamento differente (es. il nome della tabella differente a quello del mio EJB) devo crearmi il file jaws.xml relativo alla mia applicazione.

 

Metodi di finder
Di default vengono supportati da JAWS i metodi findByPrimaryKey, findAll, findBy<nome campo>.
Qualsiasi altro metodo di ricerca deve essere specificato nel mio file jaws.xml.

Vediamo un esempio riassuntivo:

Bean1Home:

import Collection;

public interface Bean1Home extends javax.ejb.EJBHome
{
Bean1 findByPrimaryKey(int id) throws
RemoteException, FinderException;
Collection findMetodo1(int id) throws RemoteException,
FinderException;
Bean1 create(String par1, int id) throws RemoteException,
CreateException;
}


Bean1Remote:

public interface Bean1Remote extends javax.ejb.EJBObject
{
public int metodo1(int par) throws
java.rmi.RemoteException;
public String metodo2() throws java.rmi.RemoteException;
public int metodo3 () throws java.rmi.RemoteException;
}


jaws.xml:

<?xml version="1.0" encoding="Cp1252"?>
<jaws>
<!- Sorgente JDBC associata al file jboss.xml -->
<datasource>java:/OracleDS</datasource>
<type-mapping>Oracle8</type-mapping>

<!-Non dichiaro nessuna mappatura perché è in standardjaws.xml -->
<type-mappings></type-mappings>

<enterprise-beans>
<entity>
<ejb-name>Bean1</ejb-name>
<table-name>nome_tabelle</table-name>
<!-Crea la tabella associata a Bean1-->
<create-table>true</create-table>

<remove-table>false</remove-table>
<tuned-updates>false</tuned-updates>
<read-only>false</read-only>
<time-out>300</time-out>
<pk-constraint>false</pk-constraint>
<!- campi tabella corrispondenti a quelli dell' EJB -->
<cmp-field>
<field-name>id</field-name>
<column-name> nome_colonna1</column-name>
<sql-type>NUMBER</sql-type>
<jdbc-type>INTEGER</jdbc-type>
</cmp-field>
<cmp-field>
<field-name>par1</field-name>
<column-name>nome_colonna2</column-name>
<sql-type>VARCHAR(20)</sql-type>
<jdbc-type>VARCHAR</jdbc-type>
</cmp-field>
<!- Metodo personalizzato non presente in standardjaws.xml -->
<finder>
<name>findMetodo1</name>

<!--(condizione: where id > parametro che passo al metodo findMetodo1) -->
<query>id > {0}</query>

<!-order by par1-->
<order>par1</order>
</finder>
</entity>
</enterprise-beans>
</jaws>


ejb-jar.xml:

<?xml version="1.0"?>

<!DOCTYPE ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN' 'http://java.sun.com/j2ee/dtds/ejb-jar_1_1.dtd'>

<ejb-jar>
<enterprise-beans>
<entity>
<ejb-name>Bean1</ejb-name>
<home> Bean1Home</home>
<remote> Bean1Remote</remote>
<ejb-class> Bean1</ejb-class>
<persistence-type>Container</persistence-type>
<prim-key-class>java.lang.String</prim-key-class>
<reentrant>False</reentrant>
<cmp-field><field-name>par1</field-name></cmp-field>
<cmp-field><field-name>id</field-name></cmp-field>
<primkey-field>id</primkey-field>
<resource-ref>
<res-ref-name>jdbc/OracleJDBC</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</entity>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>Bean1</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>

Nel caso particolare in cui il mio dato sia un oggetto ci sono piccoli cambiamanti da fare.
Supponiamo di avere un JavaBean che rappresenta il mio dato:

public class Persona
implements Serializable{

private String nome;
private String cognome;

public String getNome(){ return nome; }
public void setNome(String nome){ this.nome = nome; }

public String getCognome(){ return hours; }
public void setCognome (String cognome){ this.cognome = cognome; }

}


Il corrispondente tratto di codice nel file ejb-jar.xml:

<ejb-jar>
<display-name>Persona</display-name>
<enterprise-beans>
<entity>
...
<cmp-field><field-name>persona</field-name></cmp-field>
...
</entity>
</enterpris
e-beans>
</ejb-jar>


nel file jaws.xml avrò:

<jaws>
<enterprise-beans>
<entity>
...
<cmp-field>
<field-name>persona.nome</field-name>
<column-name>colonna1</column-name>
</cmp-field>
<cmp-field>
<field-name> persona.cognome </field-name>
<column-name> colonna2 </column-name>
</cmp-field>
...
</entity>
</enterprise-beans>
</jaws>

Conclusioni
Sfortunatamente la versione 2.4.x di JBoss non supporta le specifiche EJB 2.0. Solo con il passaggio alla versione 3.x si può rimediare a questa mancanza.


Bibliografia
[1] "Manual - online HTML version"- www.jboss.org
[2] SCOTT STARK, MARC FLEURY "JBoss Administration and Development "- JBoss Group
[3] Davide Brusamolino "Configurare una connessione a db con JBoss 2.4.x" - Mokabyte Aprile 2003

MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it