MokaByte 97 - Giugno 2005
  MokaByte 97 - Giugno 2005  

 

 

 

Oracle Java Stored procedures

Quando si progetta una applicazione complessa basata su database molto spesso si utilizzano stored procedure per eseguire determinate operazioni all'interno del RDBMS. Oracle, a partire dalla versione 8.1.5, permette di scrivere stored procedure direttamente in Java consentendo di riutilizzare conoscenze già acquisite e di svolgere compiti che in precedenza erano possibili solo ricorrendo all'uso di programmi scritti in C. Lo scopo dell'articolo è capire i meccanismi di funzionamento e gli ambiti delle stored procedure scritte in Java.

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/