Introduzione
Quando si realizza una applicazione Java che si basa
su RDMBS spesso si tende a modellarla su due o più
livelli confinando il codice Java negli strati esterni
al database; tale scelta è giustificata dal fatto
che il nostro linguaggio preferito si presta molto bene
sia per creare interfacce utente siano esse a finestre
o basate su pagine web, sia la logica che vi sta dietro.
Per il colloquio con il database si utilizza l'API JDBC
che permette di scambiare dati fra lo strato di memorizzazione
quelli di logica applicativa. In realtà quando
il database lo consente e/o se l'applicazione è
complessa una parte di logica risiede sul database sotto
forma stored procedure, di solito implementate tramite
un linguaggio proprietario del RDBMS. Se il database
utilizzato è Oracle 8.1.5 o superiore esiste
la possibilità di codificare le stored procedure
direttamente in Java. Lo scopo dell'articolo è
quello di mostrare quali sono i meccanismi che ci consentono
di utilizzare questa possibilità e di stabilire
alcuni criteri in base ai quali valutare l'effettiva
efficacia delle stored procedure Java. L'articolo partirà
da semplici esempi necessari a capire il funzionamento
di base di Java all'interno del database, fino ad esplorare
argomenti più complessi come la gestione dello
stato delle sessioni, il passaggio di tipi di dati strutturati
e l'utilizzo di jar esterni.
Prerequisiti
Per poter utilizzare le java stored procedure è
necessario che il database Oracle sia stato creato con
il supporto java. La seguente select eseguita come utente
system indica se il supporto Java è abilitato
o meno:
select
* from v$option where parameter='Java'
Nel
caso Java non sia caricato è possibile aggiungerlo
lanciando uno specifico script, che nel caso di Oracle
10 è
ORACLE_HOME\db\javavm\install\initjvm.sql
Tutti
gli esempi dell'articolo sono stati eseguiti con un
utente Oracle javatest (si faccia riferimento ai file
allegati per la sua creazione)
Ancora
Hello World
Il primo esempio, propedeutico per capire come funzionano
le Java stored procedure, è il classico programma
che stampa Hello World. I passi che permettono la sua
esecuzione ci consentono di addentrarci con gradualità
all'interno dell'argomento che vogliamo esplorare. Partiamo
dalla scrittura del codice Java creando una classe HelloWorld:
public
class HelloWorld {
public static String helloWorld() {
return "Hello, world!";
}
}
Già
dalle prime poche righe di codice notiamo subito una
diversità rispetto al classico HelloWorld che
ci saremmo aspettati: il metodo incaricato di svolgere
il compito della classe non è main, bensì
un metodo statico generico.
Perchè?
La risposta sta nel fatto che l'ambiente di esecuzione
del codice Java non è la classica JVM del sistema
operativo, ma una macchina virtuale che risiede all'interno
del database che viene attivata da Oracle per eseguire
le stored procedure. Secondo questa impostazione è
molto più comodo, visto che lo scopo è
invocare una sequenza di comandi, poter chiamare vari
metodi direttamente, consentendo così il passaggio
di parametri ed il ritorno di valori.
Poichè il nostro codice viene eseguito dalla
JVM all'interno del database deve essere possibile specificare
dove la macchina virtuale trova il bytecode (è
possibile anche caricare il sorgente e farlo compilare
all'interno del RDBMS) che deve essere eseguito; questo
porta alla seconda operazione da eseguire per poter
invocare la nostra stored procedure: il collegamento
fra OracleJVM e il nostro bytecode. Tale operazione
si può eseguire tramite il programma di sistema
operativo loadjava, nel caso del nostro HelloWorld la
procedura da eseguire è:
c:\java\classes>loadjava
-user javatest/javatest HelloWorld.class
il
parametro -user javatest/javatest specifica i dati di
connessione dell'utente da utilizzare per l'esecuzione
della stored procedure. Cosa fa esattamente il comando
loadjava? Essenzialmente carica il bytecode all'intero
del database in maniera che possa essere successivamente
eseguito; questo significa che una copia del bytecode
che si trova su filesystem viene salvata all'interno
degli oggetti dell'utente specificato. Il motivo di
tale copia risiede nel fatto che la JVM Oracle cerca
le risorse di cui ha bisogno all'interno del database
e non del file system; l'impatto concettuale di questa
impostazione è elevato perchè il programmatore
java è abituato a pensare in termini di file
system per l'accesso alle classi ed alle risorse necessarie.
La Oracle JVM non ha il concetto di classpath come le
macchine virtuali a cui siamo abituati, anche se fornisce
meccanismi molto simili. Loadjava preleva il bytecode
e lo inserisce all'interno dell'analogo del classpath
della Oracle JVM. Tale impostazione è valida
per singolo utente, ovvero il bytecode non è
direttamente caricabile/eseguibile da altri utenti.
Una volta che il bytecode è stato inserito all'interno
del database Oracle non ci resta che eseguirlo; in realtà
per rendere la stored procedure chiamanbile dai programmi
SQL è necessario "pubblicare" la procedura,
ovvero istruire il motore SQL che la procedura da chiamare
è di tipo Java e non PL/SQL (linguaggio proprietario
Oracle per l'accesso ai dati). L'istruzione da eseguire
(da parte dell'utente specificato nella riga di comando
loadjava) è la seguente:
create
or replace function helloWorld
RETURN
VARCHAR2
AS LANGUAGE JAVA NAME 'HelloWorld.helloWorld() return
java.lang.String';
/
A questo punto è possibile invocare la procedura:
C:\Documents and Settings\Giovanni>sqlplus javatest/javatest
SQL*Plus:
Release 10.1.0.4.0 - Production on Mon Apr 25 16:00:30
2005
Copyright
(c) 1982, 2005, Oracle. All rights reserved.
Connected
to:
Oracle Database 10g Enterprise Edition Release 10.1.0.4.0
- Production
With the Partitioning, OLAP and Data Mining options
SQL>
select helloworld from dual;
HELLOWORLD
---------------------------------------------------------------------
Hello,
world!
SQL>
Questo
primo esempio ha mostrato tutti passi necessari per
creare le java stored procedure cercando di spiegare
il perchè di ogni fase. Il resto dell'articolo
proseguirà cercando di introdurre nuovi esempi
che introducono nuova complessità fino ad arrivare
a procedure realmente utilizzabili.
Qualcosa di più....
L'esempio HelloWorld ha mostrato i passi per eseguire
una semplice stored procedure, ma per scrivere qualcosa
di riutilizzabile occorre approfondire alcuni aspetti,
come il mantenimento dello stato della classe fra due
chiamate, la gestione delle risorse (file aperti, etc)
e il caricamento delle classi. Come già evidenziato
dall'esempio precedente una stored procedure è
costituita da un metodo static di un oggetto; questo
implica che se si vuole mantenere uno stato fra due
esecuzioni della stessa procedura si deve far riferimento
ad una variabile anch'essa di tipo static. Un semplice
esempio che illustra il concetto è una classe
contatore. La classe ha un metodo per impostare il valore
iniziale ed uno che incrementa tale valore restituendolo
al chiamante.Vediamo gli effetti di invocazioni successive
di tale classe una vota che è stata caricata
ed è stata pubblicata all'interno del db.
C:\Documents
and Settings\Giovanni>sqlplus javatest/javatest
SQL*Plus:
Release 10.1.0.4.0 - Production on Mon Apr 25 16:38:26
2005
Copyright
(c) 1982, 2005, Oracle. All rights reserved.
Connected to:
Oracle Database 10g Enterprise Edition Release 10.1.0.4.0
- Production
With the Partitioning, OLAP and Data Mining options
SQL>
create or replace procedure setinitialvalue(start_in
in number)
2 AS LANGUAGE JAVA NAME 'SimpleCounter.setInitialValue(int)';
3 /
Procedure
created.
SQL>
SQL> create or replace function incrementvalue
2 RETURN NUMBER
3 AS LANGUAGE JAVA NAME 'SimpleCounter.incrementValue()
return int';
4 /
Function
created.
SQL>
exec setinitialvalue(10);
PL/SQL
procedure successfully completed.
SQL>
select incrementvalue from dual;
INCREMENTVALUE
--------------
10
SQL>
select incrementvalue from dual;
INCREMENTVALUE
--------------
11
SQL>
select incrementvalue from dual;
INCREMENTVALUE
--------------
12
SQL>
Come mostrato dall'esempio una variabile static di classe
può essere utilizzata per mantenere lo stato
fra due invocazioni differenti; a questo punto è
lecito chiedersi cosa succede se due sessioni contemporanee
eseguono la stessa stored procedure che fa riferimento
ad una variabile static? Entrambe le sessioni vengono
eseguite all'interno dello stesso database. Con l'altra
finestra ancora aperta proviamo ad invocare increment
value:
C:\Documents
and Settings\Giovanni>sqlplus javatest/javatest
SQL*Plus:
Release 10.1.0.4.0 - Production on Mon Apr 25 17:00:11
2005
Copyright
(c) 1982, 2005, Oracle. All rights reserved.
Connected
to:
Oracle Database 10g Enterprise Edition Release 10.1.0.4.0
- Production
With the Partitioning, OLAP and Data Mining options
SQL>
select incrementvalue from dual;
INCREMENTVALUE
--------------
0
SQL>
Come si può vedere il valore della variabile
static non è condiviso fra le sessioni, ogni
connessione al database opera in un ambito completamente
isolato dalle altre. Il comportamento dell JVM Oracle
è di isolare ogni sessione in maniera analoga
a quanto fanno gli application server J2EE con i contesti
dedicati alle applicazioni; le risorse aperte sono gestite
nello stesso modo, sono separate, ma ognuna di esse
concorre a far parte del numero massimo utilizzabile.
E' fondamentale che ogni risorsa di questo tipo venga
liberata prima della fine della sessione altrimenti
il numero disponibile andrà ad esaurirsi lentamente
causando un errore difficile da tracciare.
Ora che abbiamo visto come avviene il mantenimento dello
stato all'interno delle sessioni è giunto il
momento di esplorare come passare parametri complessi
alle stored procedure, l'esempio scelto è l'elenco
dei file in una directory, tale procedura permette al
chiamante di avere la lista dei nomi dei file presenti
in una directory. E' importante notare che tale funzionalità
non è fornita a livello di PL/SQL e quindi a
meno di non aspettare una delle prossime release del
database l'unico modo per realizzarla è utilizzare
una java stored procedure. L'interfaccia della procedura
è relativamente semplice, dato un path in ingresso
viene restituita una lista di stringhe come contenuto
in uscita.
La difficoltà maggiore consiste nel passare l'array
di stringhe contenente i nomi dei file fra l'ambiente
SQL e la stored procedure Java; infatti non esiste una
corrispondenza diretta fra array PL/SQL e array Java.
Per poter passare array fra i due ambienti è
necessario utilizzare la classe oracle.sql.ARRAY e a
livello SQL un tipo TABLE OF. I passi da seguire sono:
1) Dichiarazione di un tipo dati SQL che rappresenta
l'output della stored procedure Java
C:\Documents
and Settings\Giovanni>sqlplus javatest/javatest
SQL*Plus:
Release 10.1.0.4.0 - Production on Mon Apr 25 17:00:11
2005
Copyright
(c) 1982, 2005, Oracle. All rights reserved.
Connected to:
Oracle Database 10g Enterprise Edition Release 10.1.0.4.0
- Production
With the Partitioning, OLAP and Data Mining options
SQL>create
or replace type dirlist as table of varchar2(255);
/
2) Scrittura della stored procedure che riceve un parametro
oracle.sql.ARRAY (come l'esempio riportato di seguito)
e suo caricamento tramite loadjava
public
static void dirList(String dirName,oracle.sql.ARRAY[]
arrayout ) throws SQLException{
Connection conn = new OracleDriver().defaultConnection();
try {
ArrayDescriptor descriptor=
ArrayDescriptor.createDescriptor("JAVATEST.DIRLIST",
conn );
File dir=new File(dirName);
if (dir.isDirectory()) {
String[] dirContents=dir.list();
arrayout[0] = new ARRAY( descriptor, conn, dirContents);
} else {
throw new RuntimeException(dirName + " is not a
directory");
}
} finally {
conn.close();
}
}
3)
Dichiarazione a livello SQL del fatto che l'implementazione
della stored procedure è Java
Connected
to:
Oracle Database 10g Enterprise Edition Release 10.1.0.4.0
- Production
With the Partitioning, OLAP and Data Mining options
create
or replace procedure dirlistproc(dirname in varchar2,
list out dirlist)
AS LANGUAGE JAVA NAME 'DirList.dirList(java.lang.String,oracle.sql.ARRAY[])';
/
E'
possible testare la stored procedure tramite il seguente
script SQL
declare
a dirlist;
begin
dirlistproc('c:\',a);
FOR i IN a.FIRST .. a.LAST
loop
dbms_output.put_line(a(i));
end loop;
end;
/
Chi
ha provato ad eseguire i passi elencati e a testare
lo script molto probabilmente avrà ottenuto il
seguente errore:
errore
ORA-29532:
Java call terminated by uncaught Java exception: java.security.AccessControlException:
the Permission (java.io.FilePermission c:\ read) has
not been granted to JAVATEST. The PL/SQL to grant this
is dbms_java.grant_permission( 'JAVATEST', 'SYS:java.io.FilePermission',
'c:\', 'read' )
ORA-06512: at 'JAVATEST.DIRLISTPROC', line 1
ORA-06512: at line 4
La
causa dell'errore sono i permessi che la JVM Oracle
assegna di default; tutte le operazioni di accesso a
risorse esterne sono verificate da un modulo di gestione
della sicurezza in maniera tale da impedire accessi
non desiderati. Nel nostro caso l'utente javatest non
può leggere la directory c:; per concedere le
grant è sufficiente come utente system di Oracle
lanciare il seguente comando:
exec
dbms_java.grant_permission( 'JAVATEST', 'SYS:java.io.FilePermission',
'c:\*', 'read' );
Se
si riesegue lo script di test è possibile visualizzare
il contenuto della directory c:\
L'esempio che abbiamo analizzato ha permesso di mostrare
come sia possibile un array di stringhe da un Java all'ambiente
SQL, tale operazione necessita a livello di codice Java
della creazione di strutture dati che Oracle utilizza
per la conversione dei dati. La riga di codice:
ArrayDescriptor
descriptor=ArrayDescriptor.createDescriptor("JAVATEST.DIRLIST",
conn );
indica alla JVM Oracle di creare una classe che "descrive"
il tipo di dato JAVATEST.DIRLIST, mentre la riga
arrayout[0] = new ARRAY( descriptor, conn, dirContents);
crea la struttura dati vera e propria consentendo di
tradurre un array di stringhe in una variabile del tipo
JAVATEST.DIRLIST.
In
molti casi un semplice array di oggetti primitivi non
è sufficiente, ma c'è la necessità
di passare strutture dati più articolate. Si
supponga per esempio di non essere interessati solo
ai nomi dei file presenti in una directory, ma anche
alla data di creazione, alla dimensione, etc. Si possono
impostare due soluzioni:
1)
passare alla stored procedure una serie di array ognuno
dei quali contiene un attributo, la chiamata Java sarebbe
qualcosa di simile a
public static void dirList(String dirName,oracle.sql.ARRAY[]
fileNamesOut, oracle.sql.ARRAY[] fileSizesOut) throws
SQLException{
2) creare una struttura dati più complessa contenente
tutti gli attributi necessari e passare un array di
tale struttura
La seconda scelta è probabilmente la più
elegante e ci consente anche di fare un ulteriore passo
avanti nell'esplorazione del passaggio di tipi di dati
complessi fra SQL e Java.
Le
operazioni necessarie sono concettualmente le stesse
dell'implementazione precedente
Dichiarazione di un tipo dati SQL che rappresenta l'output
della stored procedure Java
C:\Documents
and Settings\Giovanni>sqlplus javatest/javatest
SQL*Plus:
Release 10.1.0.4.0 - Production on Mon Apr 25 17:00:11
2005
Copyright
(c) 1982, 2005, Oracle. All rights reserved.
Connected to:
Oracle Database 10g Enterprise Edition Release 10.1.0.4.0
- Production
With the Partitioning, OLAP and Data Mining options
SQL>create
or replace type FileDesc as OBJECT (
name varchar2(255),
last_modified date,
bytes_size number,
isDirectory number(1,1)
);
/
SQL>create
or replace type dircontent as table of FileDesc;
/
In questo caso il tipo di dati è più complesso,
è un array di oggetti invece di essere un array
di varchar2
Scrittura della stored procedure che riceve un parametro
oracle.sql.ARRAY (come l'esempio riportato di seguito)
e suo caricamento tramite loadjava
public
static void dirList2(String dirName,oracle.sql.ARRAY[]
arrayout ) throws SQLException{
Connection conn = new OracleDriver().defaultConnection();
try {
ArrayDescriptor descriptor=
ArrayDescriptor.createDescriptor("JAVATEST.DIRCONTENT",
conn );
StructDescriptor structDescriptor=
StructDescriptor.createDescriptor("JAVATEST.FILEDESC",conn);
File dir=new File(dirName);
if (dir.isDirectory()) {
File[] dirContents=dir.listFiles();
STRUCT[] files=new STRUCT[dirContents.length];
for (int i=0;i<dirContents.length;i++) {
java.lang.Object[] fileDesc=new Object[4];
fileDesc[0]=dirContents[i].getName();
fileDesc[1]=new Date(dirContents[i].lastModified());
fileDesc[2]=new Long(dirContents[i].length());
fileDesc[3]=new Integer(dirContents[i].isDirectory()?1:0);
STRUCT struct = new STRUCT(structDescriptor, conn, fileDesc);
files[i]=struct;
}
System.out.println("Found " + dirContents.length
+ " files");
arrayout[0] = new ARRAY(descriptor, conn, files);
} else {
throw new RuntimeException(dirName + " is not a
directory");
}
} finally {
conn.close();
}
}
Dichiarazione
a livello SQL del fatto che l'implementazione della
stored procedure è Java
Connected to:
Oracle
Database 10g Enterprise Edition Release 10.1.0.4.0 -
Production
With the Partitioning, OLAP and Data Mining options
SQL>create
or replace procedure dirlistproc2(dirname in varchar2,
list out dircontent)
AS LANGUAGE JAVA NAME 'DirList.dirList2(java.lang.String,oracle.sql.ARRAY[])';
/
E'
possible testare la stored procedure tramite il seguente
script SQL
set serveroutput on size 100000
declare
a dircontent;
begin
dirlistproc2('c:\',a);
FOR i IN a.FIRST .. a.LAST
loop
dbms_output.put_line('File ' || a(i).name ||
' size ' || a(i).bytes_size ||
' last modified ' || to_char(a(i).last_modified,'dd/mm/yyyy
hh24:mi'));
end loop;
end;
/
Rispetto all'esempio precedente è stata aggiunta
un array di tipo STRUCT che consente di creare una struttura
dati più complessa (rappresentata da un array
di Object) in cui si memorizzano i valori da assegnare
alle variabili dell'oggetto Oracle JAVATEST.FILEDESC.
Anche in questo caso il passaggio vero e proprio avviene
in due passi: il primo che consiste nella creazione
di un descrittore della struttura dati e il secondo
che permette la creazione della struttura vera e propria.
La seconda versione di dirList ha permesso di mostrare
come passare strutture dati articolate fra SQL e Java,
vediamo ora come è possibile caricare jar all'interno
della Oracle JVM. Lo strumento utilizzato per caricare
le librerie all'interno del classpath (o class resolver
come viene definito dalla documentazione Oracle) è
sempre loadjava, basta specificare il nome della classe
o quello del jar. Una volta caricate esse sono disponibili
per tutte le sessioni di quel determinato utente. L'esempio
scelto per l'utilizzo dei jar è l'invio di e-mail
dall'interno del database; capita infatti di leggere
con una certa frequenza sui forum/newsgroup dedicati
ad Oracle domande circa l'invio di e-mail tramite stored
procedure, se è possibile e con quali limitazioni.
Fino alla versione 9 inclusa Oracle forniva solo un
package UTL_SMTP che implementa il protocollo SMTP tramite
primitive di basso livello che ne limitano un immediato
utilizzo. Java invece fornisce tramite l'api Java Mail
un supporto decisamente più completo ed intuitivo
da utilizzare. Per dotare la nostra applicazione Oracle
della possibilità di inviare mail in maniera
semplice e diretta è possibile scrivere un package
(ovvero una serie di stored procedure che fanno parte
di un unico blocco logico), che sfrutta le API Java
Mail.
Supponiamo di aver già a disposizione una classe
per l'invio di e-mail (si veda la classe Mailer allegata)
e di volerla utilizzare al nostro scopo; le operazioni
necessarie sono quattro:
1) creare una classe Java wrapper della classe Mailer
vera e propria che viene chiamata dal motore SQL di
Oracle, tale classe in sostanza ha tutti metodi statici
che altro non fanno che redirigere la chiamata ad una
istanza (anch'essa statica) della classe Mailer
2)
eseguire il loadjava delle classi (MailerWrapper e Mailer
) e dei jar necessari (Mail.jar e Activation.jar forniti
da Sun per l'API JavaMail) all'esecuzione
3)
creare un package PL/SQL (allegato di seguito) specificando
che l'implementazione dei metodi/procedure è
Java
create
or replace package mail as
procedure mail(host in varchar2);
procedure addAttachment(filename in varchar2);
procedure addRecipient(recipient in varchar, type in
varchar2);
procedure sendMessage(addressfrom in varchar2, subject
in varchar2, messagetext in varchar2);
end mail;
/
create
or replace package body mail as
procedure mail(host in varchar2)
AS LANGUAGE JAVA NAME 'MailWrapper.Mail(java.lang.String)';
procedure addattachment(filename in varchar2)
AS LANGUAGE JAVA NAME 'MailWrapper.addAttachment(java.lang.String)';
procedure addrecipient(recipient in varchar, type in
varchar2)
AS LANGUAGE JAVA NAME 'MailWrapper.addRecipient(java.lang.String,java.lang.String)';
procedure sendmessage(addressfrom in varchar2, subject
in varchar2, messagetext in varchar2)
AS LANGUAGE JAVA NAME 'MailWrapper.sendMessage(java.lang.String,java.lang.String,java.lang.String)';
end mail;
/
4)
concedere i permessi (collegandosi come utente system
di Oracle) di resolve e connect all'utente javatest
per consentire alle procedure Java di collegarsi al
mail server e di leggere dalla directory degli attachment.
dbms_java.grant_permission( 'JAVATEST', 'SYS:java.net.SocketPermission',
'*', 'resolve' )
dbms_java.grant_permission( 'JAVATEST', 'SYS:java.net.SocketPermission',
'*', 'connect' )
exec dbms_java.grant_permission( 'JAVATEST', 'SYS:java.io.FilePermission',
'c:\temp\*', 'read' );
Per
testare il package è sufficiente il seguente
script:
declare
begin
mail.mail('server_smtp_di_posta');
mail.addrecipient('nome@dominio','to');
mail.sendmessage('from','oggetto della mail','testo
della mail');
end;
/
o il seguente se si vogliono inviare mail con attachment
declare
begin
mail.mail('server_smtp_di_posta');
mail.addrecipient('nome@dominio','to');
mail.addattachment('path_file_da_allegare');
mail.sendmessage('from','oggetto della mail','testo
della mail');
end;
/
E' possibile che eseguendo i test che il server SMTP
segnali con un errore il fatto che per inviare e-mail
è necessario autenticarsi. Tale funzionalità
è già presente nella classe Mailer, ma
non è stata implementata a livello di MailWrapper
e di conseguenza a livello di package PL/SQL. I lettori
volenterosi ed interessati possono provare ad aggiungere
i metodi che mancano per sfruttare tutte le funzionalità
della classe originale.
Cosa
manca?
A questo punto più di un lettore si sarà
chiesto, stiamo parlando di Java ed Oracle ed abbiamo
visto come caricare classi, jar e passare tipi di dati
strutturati, ma non si è ancora parlato di accesso
ai dati, come mai?
La ragione è che per ogni tipo di problema è
consigliabile utilizzare lo strumento più adatto
alla sua soluzione e all'interno del database Oracle
lo strumento migliore per accedere ai dati non è
Java bensì PL/SQL che offre già un serie
di funzionalità (es. uso automatico delle bind
variables, utilizzo diretto delle variabili all'interno
delle istruzioni SQL) che lo rendono decisamente consigliabile.
Questo non significa che non ci siano casi in cui è
necessario utilizzare JDBC all'interno di una stored
procedure, di solito essi hanno un ambito più
limitato; un tipico esempio è quello che richiede
lo scambio di dati da un database non Oracle ad uno
Oracle. Una soluzione possibile è scrivere una
stored procedure Java che si collega al database esterno
(che può essere di qualsiasi tipo, deve solo
fornire un driver JDBC) ed inserisce i dati remoti all'interno
di tabelle locali. Le stored procedure Java infatti
sono molto utili e soprattutto convenienti quando si
devono eseguire operazioni all'interno del database
che non sono possibili con il PL/SQL; di solito queste
operazioni consistono in una interazione con il sistema
operativo, come la lettura/scrittura di file, l'apertura
di socket e così via. Riconsiderando l'esempio
della mail, se si vuole leggere la posta oltre che spedirla,
una stored procedure Java è il candidato ideale,
in quanto il PL/SQL è focalizzato sull'accesso
ai dati ed fornisce un accesso alle risorse di rete
di basso livello tramite il package UTL_TCP.
Conclusioni
Oracle offre già da parecchi anni la possibilità
di scrivere Java stored procedure per realizzare funzionalità
che altrimenti non sarebbero possibili in PL/SQL. L'articolo
ha mostrato, partendo da semplici esempi fino ad arrivare
alla realizzazione di funzionalità realmente
utilizzabili come l'invio di e-mail all'interno del
database, come sia possibile sfruttare tale caratteristica.
Le stored procedure Java sono il candidato ideale per
la soluzioni di problemi legati all'interazione fra
database e sistema operativo o per l'accesso a database
esterni dotati di driver JDBC. Le funzionalità
Java che Oracle mette a disposizione non finiscono qui,
per ulteriori approfondimenti si consiglia la lettura
del manuale Oracle 'Java Developers's Guide'; è
utile ricordare che Oracle mette liberamente a disposizione
software e documentazione, basta registrarsi all'indirizzo
http://www.oracle.com/technology/index.html.
Giovanni Cuccu è
laureato in ingegneria informatica a Bologna. Attualmente
svolge attività di consulenza per lo svilppo
di applicazioni web tramite Java, Oracle. Si interessa
di applicazioni open source, usa Linux regolarmente
ed è autore di un Oracle session profiler open
source (scritto in Java) scaricaile da http://sourceforge.net/projects/oraresprof/
|