
Le API (sigla di Application Programming Interface) sono meccanismi che consentono a due programmi di comunicare tra loro usando una serie di definizioni e protocolli.
Pensa, ad esempio, ai sistemi software che contengono i dati meteorologici giornalieri.
L’applicazione del meteo installata sul tuo cellulare parla con questi sistemi tramite API ed è grazie a questo meccanismo di comunicazione che è in grado di mostrarti gli aggiornamenti meteorologici quotidiani sul telefono.
Nel contesto delle API, quando si parla di applicazioni ci si riferisce a qualsiasi software con funzioni specifiche e si può pensare ad una interfaccia come ad un meccanismo attraverso il quale è possibile chiedere a questo software di fare ciò che sa fare.
Ciascuna interfaccia, per essere tale, stabilisce a priori come deve essere utilizzata: quali e quanti parametri accetta in ingresso (parliamo di request) e quali sono eventualmente gli output (response) generati.
La documentazione di una API (che ti consiglio SEMPRE di leggere) contiene spesso informazioni su come gli sviluppatori devono strutturare tali richieste e risposte.
Esistono API di diverso tipo: API Rest, SOAP, Java, ecc. Praticamente il tipo di API dipende dall’applicazione di riferimento.
Anche Oracle APEX dispone di numerose API che permettono agli sviluppatori di sfruttarlo al meglio, sia per accrescerne le funzionalità tramite lo sviluppo di estensioni e plugins, sia per evitare di riscrivere codice che risolve problemi già noti.
In questo articolo desidero spiegarti alcune delle API più utili che ti consiglio di imparare ad usare.
Sei pronto? Iniziamo!
IN QUESTO ARTICOLO
Le API di Oracle APEX Fondamentali
Abbiamo visto come Oracle APEX permetta di costruire API REST che possono essere utilizzate da sistemi esterni per comunicare con le nostre applicazioni.
Oggi però desidero parlarti di qualcosa di diverso.
Devi sapere, infatti, che quando installi Oracle APEX, non solo hai un potentissimo framework di sviluppo, ma hai a disposizione numerose librerie PL-SQL che puoi utilizzare all’interno di un qualsiasi programma sviluppato in PL-SQL oltre che, ovviamente, nelle applicazioni APEX che andrai a creare nel tempo.
APEX_WEB_SERVICE
La maggior parte delle applicazioni web moderne espongono servizi che possono essere usati da altre applicazioni per interagire con le stesse.
Per poter collegare una applicazione basata su Oracle APEX ad un web service puoi sfruttare il package APEX_WEB_SERVICE.
Puoi usarlo per eseguire sia chiamate REST che SOAP e funziona ugualmente bene sia per i servizi web basati su JSON che su XML.
APEX_DATA_PARSER
Come leggere un file di dati che poi deve essere importato all’interno del database?
Il package APEX_DATA_PARSER ti permette di leggere con una procedura PL-SQL files in formato CSV, JSON, XML e XLSX (Excel).
La funzionalità più importante di questo package è la funzione PARSE, che accetta come parametro in input il file e restituisce il suo contenuto tramite un oggetto di tipo apex_t_parser_table.
In questo modo puoi importare il contenuto di questi files direttamente all’interno di una tabella del database.
Leggi questo articolo per scoprire come usare la libreria APEX_DATA_PARSER.
APEX_DATA_EXPORT
Se la necessità di importare dati da un file è qualcosa di abbastanza comune, lo è altrettanto quella di poterli esportare.
Alcuni componenti grafici come l’Interactive Report o l’Interactive Grid hanno funzionalità di export native, tuttavia talvolta c’è bisogno di implementare delle funzionalità di export specifiche.
Grazie al package APEX_DATA_EXPORT puoi estrarre i dati del database e salvarli in un file che l’utente può scaricare.
I formati supportati sono PDF, XLSX, HTML, CSV, XML e JSON
APEX_MAIL
Puoi utilizzare il package APEX_MAIL per inviare e-mail da una applicazione Oracle APEX.
Questo package si basa sul package UTL_SMTP quindi un prerequisito affinché funzioni correttamente è che i servizi SMTP siano stati correttamente installati nel database.
Consiglio di utilizzare APEX_MAIL perché più flessibile di UTL_MAIL ed in generale più facile da utilizzare rispetto ad UTL_SMTP.
APEX_STRING
La gestione e manipolazione delle stringhe assume un ruolo fondamentale in qualsiasi linguaggio di programmazione ed è alla base di molti algoritmi e di tutta la programmazione in generale.
APEX_STRING è una libreria PL-SQL che offre alcune comode funzionalità di manipolazione delle stringhe tra cui spiccano STRING_TO_TABLE e TABLE_TO_STRING: vediamo come funziona.
STRING_TO_TABLE
La funzione STRING_TO_TABLE converte una stringa contenente valori separati da un carattere in un array di record.
declare
l_array apex_application_global.vc_arr2;
l_string varchar2(2000);
begin
l_array := apex_string.string_to_table('Mario Rossi;Paolo Gialli;Topolino;Paperino',';');
for i in 1..l_array.count loop
dbms_output.put_line('record ('|| i|| '): '|| l_array(i));
end loop;
end;
TABLE_TO_STRING
La funzione TABLE_TO_STRING trasforma un array di record in una stringa i cui valori sono separati da un carattere. Ecco uno script di esempio:
declare
l_array apex_application_global.vc_arr2;
l_string varchar2(2000);
begin
l_array := apex_string.string_to_table('Mario Rossi;Paolo Gialli;Topolino;Paperino',';');
for i in 1..l_array.count loop
dbms_output.put_line('record ('|| i|| '): '|| l_array(i));
end loop;
dbms_output.put_line(apex_string.table_to_string(l_array,'#'));
end;
SPLIT
La funzione SPLIT converte una stringa contenente valori separati da un carattere in un array di record (una tabella apex_t_varchar2) .
Se usata in combinazione con la funzione TABLE possiamo leggere i valori della stringa usando una query (utile se vogliamo fare un report partendo da una stringa).
select
val
from
( select
rownum as rn,
column_value as val
from
table ( apex_string.split(
'Mario Rossi;Paolo Gialli;Topolino;Paperino', ';'
) )
);
JOIN
La funzione JOIN converte una tabella apex_t_varchar2 in una stringa ottenuta concatenando i valori con un separatore.
select apex_string.join(
apex_string.split('Mario Rossi;Paolo Gialli;Topolino;Paperino', ';'),'#')
from dual;
GET_INITIALS
La funzione GET_INITIALS restituisce le iniziali delle prime n parole contenute nella stringa passata in input.
Può essere utile quando ad esempio vuoi mostrare le iniziali di una persona. Ecco un esempio:
select apex_string.get_initials('Daniele Trasarti' )
from dual;
GET_SEARCHABLE_PHRASES
Questa funzione è, secondo me, una piccola chicca.
Supponiamo che tu debba implementare una ricerca su una colonna di una tabella che contiene frasi che utilizzano il linguaggio comune (ad esempio potrebbe essere la descrizione di un articolo acquistabile dal tuo store on-line oppure un campo note).
Sarebbe interessante far si che la ricerca sia fatta sulle parole chiave contenute all’interno del testo senza considerare, ad esempio, la punteggiatura, i caratteri speciali, articoli e pronomi (in ambito informatico si parla di stop-words).
La funzione GET_SEARCHABLE_PHRASES arriva proprio in nostro aiuto perché è in grado di leggere il testo e scomporlo in una serie di frasi che contengono le sole parole chiave realmente utili.
Ciascuna frase sarà poi separata da un carattere speciale definito da noi a nostra scelta.
Facciamo un esempio:
select apex_string.join (
apex_string.get_searchable_phrases (
p_strings => apex_t_varchar2 ('Signora Robinson, sta cercando di sedurmi, vero?',
'La vita è come una scatola di cioccolatini. Non sai mai quello che ti capita.'),
p_max_words => 3,
p_language => 'it'
),':' )
from dual;
Questo sarà il risultato:
signora:signora robinson:robinson:sta:sta cercando:cercando:sedurmi:vero:vita:vita è:vita è come:è:è come:come:scatola:cioccolatini:non:non sai:non sai mai:sai:sai mai:mai:ti:ti capita:capita
È bene sapere che questa libreria implementa solo una piccola parte delle funzionalità messe a disposizione da Oracle Text che, qualora non lo sapessi, è un motore di ricerca e software di analisi del testo sviluppato da Oracle.
Le API di Oracle APEX per gli smanettoni
Arrivati a questo punto possiamo dire che conosci alcune delle librerie PL-SQL di Oracle APEX più utili in assoluto.
Anche se l’ho già detto, vorrei ribadirlo: non sei obbligato ad usarle solo in una applicazione Oracle APEX ma puoi sfruttarle in qualsiasi contesto in cui devi sviluppare un programma PL-SQL che dovrà essere eseguito nello stesso database dove è installato APEX.
Nei prossimi paragrafi ti mostrerò alcune API utili per realizzare funzionalità avanzate.
APEX_ZIP
Il package APEX_ZIP ti permette di manipolare file zip attraverso il PL-SQL.
Lo script PL/SQL seguente estrae dei file (BLOB) dalla tabella emp_files e li aggiunge ad un file compresso in formato zip e che viene salvato nella variabile b_zip_file.
declare
b_zip_file blob;
cursor c_files
is
select file_name,
file_content
from my_files
where file_name in('file1.mp3','file2.pdf','file3.txt');
begin
for c in c_files
loop
-- adds the each blob to b_zip_file blob one by one
apex_zip.add_file (
p_zipped_blob => b_zip_file,
p_file_name => c.file_name,
p_content => c.file_content );
end loop;
-- finalizes the blob
apex_zip.finish (p_zipped_blob => b_zip_file );
end;
Una volta generato il file compresso potrai salvarlo in una tabella oppure farlo scaricare all’utente via browser.
Per vedere il contenuto di un file zip puoi usare funzione GET_FILES che restituisce un array contenente i nomi dei files ed il percorso all’interno dell’archivio.
Infine, per recuperare un singolo file utilizzerai la funzione GET_FILE_CONTENT.
Ecco un esempio di script PL-SQL che esplora il un file zip ed estrae i files che sono contenuti nell’archivio.
declare
l_zip_file blob;
l_unzipped_file blob;
l_files apex_zip.t_files;
begin
select file_content
into l_zip_file
from my_zip_files
where file_name = 'my_file.zip';
l_files := apex_zip.get_files (p_zipped_blob => l_zip_file );
for i in 1 .. l_files.count loop
l_unzipped_file := apex_zip.get_file_content (
p_zipped_blob => l_zip_file,
p_file_name => l_files(i) );
insert into my_files ( file_name, file_content )
values ( l_files(i), l_unzipped_file );
end loop;
end;
APEX_AUTHENTICATION
Oracle APEX mette a disposizione diversi metodi di autenticazione.
Tuttavia, in alcuni casi è necessario sviluppare qualche meccanismo di autenticazione avanzato come, ad esempio il login-as (chiamato anche impersonificazione), che consente ad un amministratore di sistema di collegarsi come un altro utente.
Per sviluppare un meccanismo di questo tipo puoi creare un plugin che sfrutti le potenzialità del package APEX_AUTHENTICATION.
APEX_IR e APEX_IG
L’Interactive Report e l’Interactive Grid sono due tra i componenti più importanti e versatili di Oracle APEX.
Per questo motivo, non stupisce il fatto che siano stati messi a disposizione degli sviluppatori più intraprendenti delle API che permettano di controllarne il comportamento via codice:
Facciamo un esempio pratico per capire come usarli.
Supponiamo che tu abbia creato in Interactive Report e vuoi costruire un bottone che resetta tutti i filtri custom applicati dagli utenti.

Aggiungi alla pagina un bottone nella pagina chiamato RESET_REPORT con Action = Submit Page

Crea un Page Process di tipo PL-SQL

Usa il seguente script PL-SQL che rimuoverà dall’Interactive Report tutti i filtri applicati
DECLARE
l_region_id apex_application_page_regions.region_id%TYPE;
BEGIN
SELECT aapr.region_id
INTO l_region_id
FROM apex_application_page_regions aapr
WHERE aapr.application_id = :app_id
AND aapr.page_id = :app_page_id
AND aapr.static_id = 'employee_report';
apex_ir.reset_report (p_page_id => :app_page_id,
p_region_id => l_region_id,
p_report_id => NULL);
END;
Il codice seguente, invece, puoi usarlo per implementare l’aggiunta di un filtro.
DECLARE
l_region_id apex_application_page_regions.region_id%TYPE;
BEGIN
SELECT aapr.region_id
INTO l_region_id
FROM apex_application_page_regions aapr
WHERE aapr.application_id = :app_id
AND aapr.page_id = :app_page_id
AND aapr.static_id = 'employee_report';
apex_ir.add_filter (p_page_id => :app_page_id,
p_region_id => l_region_id,
p_report_column => 'FIRST_NAME',
p_filter_value => 'Milo',
p_operator_abbr => 'EQ',
p_report_id => NULL);
END;
Questo sarà il risultato finale:

APEX_JSON
APEX_JSON offre un nutrito set di funzionalità che permettono di generare, manipolare e leggere documenti in formato JSON.
Ecco un esempio che ti mostra come generare un JSON partendo dai dati salvati all’interno di una o più tabelle.
CREATE TABLE DEPT (
DEPTNO NUMBER(2) CONSTRAINT PK_DEPT PRIMARY KEY,
DNAME VARCHAR2(14),
LOC VARCHAR2(13)
) ;
CREATE TABLE EMP (
EMPNO NUMBER(4) CONSTRAINT PK_EMP PRIMARY KEY,
ENAME VARCHAR2(10),
JOB VARCHAR2(9),
MGR NUMBER(4),
HIREDATE DATE,
SAL NUMBER(7,2),
COMM NUMBER(7,2),
DEPTNO NUMBER(2) CONSTRAINT FK_DEPTNO REFERENCES DEPT
);
INSERT INTO DEPT VALUES (10,'ACCOUNTING','NEW YORK');
INSERT INTO DEPT VALUES (20,'RESEARCH','DALLAS');
INSERT INTO DEPT VALUES (30,'SALES','CHICAGO');
INSERT INTO DEPT VALUES (40,'OPERATIONS','BOSTON');
INSERT INTO EMP VALUES (7369,'SMITH','CLERK',7902,to_date('17-12-1980','dd-mm-yyyy'),800,NULL,20);
INSERT INTO EMP VALUES (7499,'ALLEN','SALESMAN',7698,to_date('20-2-1981','dd-mm-yyyy'),1600,300,30);
INSERT INTO EMP VALUES (7521,'WARD','SALESMAN',7698,to_date('22-2-1981','dd-mm-yyyy'),1250,500,30);
INSERT INTO EMP VALUES (7566,'JONES','MANAGER',7839,to_date('2-4-1981','dd-mm-yyyy'),2975,NULL,20);
INSERT INTO EMP VALUES (7654,'MARTIN','SALESMAN',7698,to_date('28-9-1981','dd-mm-yyyy'),1250,1400,30);
INSERT INTO EMP VALUES (7698,'BLAKE','MANAGER',7839,to_date('1-5-1981','dd-mm-yyyy'),2850,NULL,30);
INSERT INTO EMP VALUES (7782,'CLARK','MANAGER',7839,to_date('9-6-1981','dd-mm-yyyy'),2450,NULL,10);
INSERT INTO EMP VALUES (7788,'SCOTT','ANALYST',7566,to_date('13-JUL-87','dd-mm-rr')-85,3000,NULL,20);
INSERT INTO EMP VALUES (7839,'KING','PRESIDENT',NULL,to_date('17-11-1981','dd-mm-yyyy'),5000,NULL,10);
INSERT INTO EMP VALUES (7844,'TURNER','SALESMAN',7698,to_date('8-9-1981','dd-mm-yyyy'),1500,0,30);
INSERT INTO EMP VALUES (7876,'ADAMS','CLERK',7788,to_date('13-JUL-87', 'dd-mm-rr')-51,1100,NULL,20);
INSERT INTO EMP VALUES (7900,'JAMES','CLERK',7698,to_date('3-12-1981','dd-mm-yyyy'),950,NULL,30);
INSERT INTO EMP VALUES (7902,'FORD','ANALYST',7566,to_date('3-12-1981','dd-mm-yyyy'),3000,NULL,20);
INSERT INTO EMP VALUES (7934,'MILLER','CLERK',7782,to_date('23-1-1982','dd-mm-yyyy'),1300,NULL,10);
COMMIT;
Esegui il seguente script PL-SQL
DECLARE
l_deptno dept.deptno%TYPE := 10;
l_dept_row dept%ROWTYPE;
BEGIN
APEX_JSON.initialize_clob_output;
APEX_JSON.open_object; -- {
SELECT d.*
INTO l_dept_row
FROM dept d
WHERE d.deptno = l_deptno;
APEX_JSON.open_object('department'); -- department {
APEX_JSON.write('department_number', l_dept_row.deptno);
APEX_JSON.write('department_name', l_dept_row.dname);
APEX_JSON.open_array('employees'); -- employees: [
FOR cur_rec IN (SELECT * FROM emp e WHERE e.deptno = l_deptno)
LOOP
APEX_JSON.open_object; -- {
APEX_JSON.write('employee_number', cur_rec.empno);
APEX_JSON.write('employee_name', cur_rec.ename);
APEX_JSON.close_object; -- } employee
END LOOP;
APEX_JSON.close_array; -- ] employees
APEX_JSON.close_object; -- } department
APEX_JSON.open_object('metadata'); -- metadata {
APEX_JSON.write('published_date', TO_CHAR(SYSDATE, 'DD-MON-YYYY'));
APEX_JSON.write('publisher', 'oracle-base.com');
APEX_JSON.close_object; -- } metadata
APEX_JSON.close_object; -- }
DBMS_OUTPUT.put_line(APEX_JSON.get_clob_output);
APEX_JSON.free_output;
END;
/
Questo dovrebbe essere il risultato:
{
"department": {
"department_number": 10,
"department_name": "ACCOUNTING",
"employees": [
{
"employee_number": 7782,
"employee_name": "CLARK"
},
{
"employee_number": 7839,
"employee_name": "KING"
},
{
"employee_number": 7934,
"employee_name": "MILLER"
}
]
},
"metadata": {
"published_date": "04-APR-2016",
"publisher": "oracle-base.com"
}
}
APEX_ERROR
Grazie al package APEX_ERROR puoi gestire le eccezioni generate dalle procedure PL-SQL per mostrare agli utenti messaggi di errore personalizzati.
Ecco un esempio di come utilizzare questo package.
begin
apex_error.add_error(
p_message => 'This is the first error message'
, p_display_location => apex_error.c_inline_in_notification
);
apex_error.add_error(
p_message => 'This is the second error message'
, p_display_location => apex_error.c_inline_in_notification
);
apex_error.add_error(
p_message => 'This is the third error message'
, p_display_location => apex_error.c_inline_in_notification
);
end;
APEX_COLLECTION
In Oracle APEX le COLLECTIONS sono delle strutture dati temporanee che possono essere inizializzate durante la sessione e possono essere usate come delle tabelle virtuali.
I dati che vengono manipolati all’interno della collection non sono salvati nel database: sarai tu a doverlo fare via programma usando il package APEX_COLLECTION.
L’utilità delle COLLECTIONS sta nel fatto che ti consentono di lavorare e manipolare i dati senza che vengano realmente salvati nel database.
Per creare una COLLECTION puoi usare la seguente istruzione
apex_collection.create_collection('EMP_COLLECTION');
EMP_COLLECTION è il nome della COLLECTION e la identificherà in modo univoco per tutta la durata della sessione.
Per evitare di ottenere errori, qualora tu debba creare una COLLECTION chiamata EMP_COLLECTION, puoi verificarne l’esistenza usando l’istruzione apex_collection.collection_exists.
if not apex_collection.collection_exists('EMP_COLLECTION') then
apex_collection.create_collection('EMP_COLLECTION');
else
apex_collection.truncate_collection('EMP_COLLECTION');
end if;
L’istruzione apex_collection.truncate_collection serve per svuotare la COLLECTION.
Una volta che la COLLECTION è correttamente inizializzata puoi aggiungere un record usando l’istruzione apex_collection.add_member.
Nell’esempio seguente andremo ad aggiungere un record con 3 colonne che rappresentano rispettivamente l’identificativo di un dipendente, il suo nome e il suo stipendio mensile.
Ogni record di una COLLECTION sarà identificato da un ID univoco che viene salvato nella colonna SEQ_ID.
apex_collection.add_member(
p_collection_name => 'EMP_COLLECTION',
p_c001 => :P3_EMPNO,
p_c002 => :P3_ENAME,
p_c003 => :P3_ESAL
);
Questo è lo script completo per inizializzare e popolare una COLLECTION partendo dai dati di una tabella del database.
declare
Cursor c_emp
is
select empno, ename, sal from emp;
begin
if not apex_collection.collection_exists('EMP_COLLECTION') then
apex_collection.create_collection('EMP_COLLECTION');
else
apex_collection.truncate_collection('EMP_COLLECTION');
END IF;
for c in c_emp loop
apex_collection.add_member(
p_collection_name => 'EMP_COLLECTION',
p_c001 => c.empno,
p_c002 => c.ENAME,
p_c003 => c.sal
);
end loop;
end;
Per interrogare i dati salvati in una COLLECTION puoi usare una Query SQL fatta come nell’esempio seguente:
select
seq_id member_id,
c001 empno,
c002 ename,
c003 salary
from apex_collections
where collection_name = 'EMP_COLLECTION'
Puoi modificare un record di una collection usando l’istruzione apex_collection.update_member, dove il parametro p_seq rappresenta l’ID del record all’interno della COLLECTION.
BEGIN
apex_collection.update_member (
p_collection_name => 'EMP_COLLECTION',
p_seq => '2',
p_c001 => :P3_EMPNO,
p_c002 => :P3_ENAME,
p_c003 => :P3_ESAL);
END;
Per eliminare un record della COLLECTION usa l’istruzione apex_collection.delete_member
Begin
apex_collection.delete_member(
p_collection_name => 'EMP_COLLECTION',
p_seq => '2');
End;
Conclusioni
Come hai visto, ci sono diverse librerie PL-SQL che sfruttate a dovere possono aiutarti a risolvere problemi altrimenti molto più complicati da gestire.
Noi ne abbiamo viste alcune, quelle più significative, ma ce ne sono molte di più.
Puoi esplorarle tutte facendo riferimento alla documentazione ufficiale che viene costantemente aggiornata ogni volta che viene rilasciata una nuova release di Oracle APEX.
E tu, utilizzi le API?
Fammelo sapere nei commenti!
Un abbraccio
Daniele
Lascia un commento