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>
</enterprise-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
|