L'enorme diffusione della rete Internet
e l'introduzione del Word Wide Web (WWW) e del linguaggio
Java hanno portato ad una serie di architetture per lo
sviluppo di applicazioni che sono al tempo stesso potenti e
standard. Questo consente di costruire applicazioni di livello
professionale (Enterprise) con una notevole possibilita' di riutilizzo di
componenti ed esperienze.
Sul Web si trova tutta la documentazione tecnica specifica e di dettaglio ma
e' difficile trovare un'introduzione comune a tutte le diverse
possibilita'. In questo documento si cerca di dare una panoramica
semplice e veloce sulle principali architetture per lo sviluppo
di applicazioni Java su Internet.
Almeno spero!
Nel 1989 nasce al CERN
l'idea di scrivere e pubblicare documenti con simpatici link, nel
1991 il primo web server e' posto su Internet, nel 1994 e' disponibile il primo browser grafico
e da allora non ci si e' piu' fermati
...
L'architettura e' semplice ed utilizza tecnologie consolidate. Il
browser (il programma utilizzato dall'utente per consultare i documenti)
ed il web server (che ospita e pubblica i documenti) dialogano con il protocollo HTTP
(HyperText Transport Protocol) che e' un semplice
dialogo
TCP (domanda/risposta). Browser e Web Server si scambiano richieste (GET/POST) e repliche
in formato HTML (HyperText Markup Language). L'HTTP viene
definito un protocollo connection-less perche', anche se la
sessione TCP e' una normale connessione (tipicamente sulla porta
80), questa viene chiusa ogni volta.
Il browser richiede una
pagina al web server e si occupa di visualizzarla in modo
adeguato. Il server si occupa di reperire in modo efficiente le
pagine che sono file posti su directory. I path indicati
nell'URL (Universal Resource Locator) corrispondono a
virtual directory che vengono mappate in directory
reali sul web server dove vengono pubblicati i documenti.
Le pagine scaricate sul browser contengono testi, immagini
(eg. GIF, JPG), TAG di formattazione e di link ad altre
pagine.
Un esempio di pagina HTML (preso dal documento Hello World... ditelo coi fiori!):
<html> <head> <! Esempio in HTML> <title>Ditelo con ... HTML</title> </head> <body> <p>Ti amo! <p>Ti amo! <p><b>Ti amo!</b> </body> </html> |
Naturalmente le pagine possono essere abbellite a
piacere con immagini e fogli di stile (ottimi esempi sull'uso
degli Style Sheet si trovano nel CSS Zen Garden).
Nel tempo sono
stati sviluppati diversi Plug-in che consentono di arricchire le
capacita' dei browser. Tra questi i due che voglio citare sono
l'Acrobat Reader per la lettura di documenti PDF ed il
Flash Player per la visione dei filmati realizzati con
Macromedia Flash.
La presentazione di pagine statiche, anche grazie a sofisticati
strumenti di caching, e' molto efficiente. Percio', oltre che
manualmente, spesso le pagine HTML vengono preparate in
automatico, con procedure batch.
Anche sul semplice HTML vi sono state evoluzioni. L'esempio
riportato e' "vecchio" e non rispetta le regole del piu' recente
HTML 4.1. Sono stati definiti sucessivamente
XML
(Extensible Markup Language), XHTML(Extensible
HyperText Markup Language), regole per l'accessibilita' ai siti
web WCAG (Web Content Accessibility Guide),
e' possibile rendere, in parte, dinamico il contenuto
del sito con linguaggi di scripting che vengono interpretati
dal browser come Java Script
e VB Script
...
La presentazione di soli contenuti statici, anche se rappresenta ancora adesso di gran lunga il maggior utilizzo del web, non e' sufficiente. E' necessario anche poter riportare dati dinamici.
Per tale ragione e'
stata definita un'interfaccia cui debbono soddisfare i programmi
per essere attivati da un web server. L'interfaccia CGI (Common
Gateway Interface) e' molto semplice e consente il passaggio dei
parametri al programma che deve restituire una pagina HTML.
Quindi dal punto di vista del browser non cambia nulla, vi e'
sempre una normale pagina HTML da presentare. La differenza e'
nel web server che, anziche' reperire l'informazione su un file,
utilizza un virtual mapping per reperire il programma da lanciare
e che si occupa di "generare" la pagina HTML.
Un esempio di programma CGI:
#!/bin/sh # Esempio di programma CGI in Bourne shell echo "Content-type: text/html" echo echo "<html>" echo "<body>" i=0 while [ $i -lt 3 ] do echo "<br>Ti Amo!" i=`expr $i + 1` done echo "</body>" echo "</html>" |
Dal punto di vista di
configurazione l'utilizzo dei CGI e' molto semplice. Deve essere
solo definita sul web server la directory in cui risiedono in
programmi (tipicamente nella directory cgi-bin).
Poiche' con il CGI viene eseguito sul web server un programma,
questo puo' essere complesso a piacere e quindi accedere a basi
dati, collegarsi ad altri sistemi, ...
L'utilizzo del CGI e del metodo di POST dell'HTML consente di costruire applicazioni complete e complesse a piacere.
Un'architettura simile al CGI e' quella dei moduli di estensione del Web Server. La differenza fondamentale e' che i moduli sono librerie dinamiche e vengono eseguiti dai thread del web server anziche' essere processi distinti come avviene con il CGI. Il LAMP e' l'esempio piu' diffuso.
Fino ad ora il browser si e' solo preoccupato di mostrare contenuti, statici o dinamici, preparati dal server. E se fosse utile avere un programma che gira sul client? Dal 1995 si puo' con un Applet!
Prima di descrivere un
Applet e' necessario parlare un poco del linguaggio che si
utilizza per scriverlo: Java.
Il linguaggio Java e' universale nel senso che i programmi java
compilati (il compilatore javac genera un file
file .class) vengono eseguiti indifferentemente e
con gli stessi identici risultati, su qualsiasi piattaforma HW/SW
che ospiti la Java Virtual Machine (JVM). Il compilatore genera
un file in formato bytecode (con il suffisso .class) che puo'
essere eseguito con java nomeProgramma (naturalmente se e'
stato definito in modo corretto il CLASSPATH). Si tratta di un
linguaggio ad oggetti, compilato (su un bytecode che viene
interpretato dalla JVM per essere piu' precisi) adatto a
costruire applicazioni o programmi scaricati da Internet ed
eseguiti da un browser: gli applet!
Il linguaggio Java
consente di produrre particolari programmi detti Applet, che
possono essere scaricati da Internet ed eseguiti all'interno dei
piu' comuni "navigatori" o browser (eg. Netscape o Internet
Explorer). La differenza fondamentale tra un'applicazione Java ed
un applet Java sta nel fatto che l'applet viene eseguito su un
browser. La JVM del browser consente un limitato accesso alle
funzioni di sistema da parte del programma java (sandbox) in modo
da evitare virus o altri problemi da parte di programmi
maliziosi.
I limiti imposti dalla sandbox sono molto importanti dal punto di
vista architetturale. Infatti tipicamente un applet puo' aprire
connessioni solo verso il sistema da cui e' stato caricato e non
puo' modificare gli archivi locali del sistema su cui e'
eseguito.
Un esempio di Applet
/** Esempio di Applet Java */ import java.awt.*; public class Dimmelo extends java.applet.Applet { public void paint(Graphics g) { int i; for (i=0; i<3; ) g.drawString("Ti amo!", 1, 16*++i); } } |
Per ospitare tale programma su web e' necessario includerlo in una pagina HTML come quella che segue:
<html> <head> <! Esempio con un Java Applet>: <title>Ditelo con ... un applet</title> </head> <body> <applet code=dimmelo.class HEIGHT=100 WIDTH=100> </applet>Ti amo! </body> </html> |
Pur girando in una JVM
limitata (per ragioni di sicurezza viene limitata alla sandbox)
un'applet puo' essere
un'applicazione complessa a piacere. Ad esempio puo' accedere a
database esterni via JDBC(l'API di accesso ai
DB in Java), dialogare via socket con servizi posti
in rete, richiamare servizi via RMI...
L'evoluzione del linguaggio Java e' stata notevole nel tempo. Non
tanto nel bytecode, che e' la base comune, quanto nelle librerie,
nell'ambiente di sviluppo (JDK) e nelle componenti architetturali
come vedremo nel seguito.
Oltre agli applet esistono altri modi per "programmare" i
browser. Vi sono infatti linguaggi di scripting (eg. Java Script,
VB Script), plug-in (eg. Flash Player), ... ma il discorso
diventerebbe assai lungo!
Caricare un'applicazione
completa sulla JVM del browser risulta pesante ed, in ogni caso,
l'accesso ai dati e' complesso. Meglio quindi un'architettura in
cui la logica applicativa sia ospitata principalmente sul
server.
Un difetto notevole dell'utilizzo di un programma CGI e' il fatto
che debba essere attivato un processo per ogni richiesta. Questo
risulta notevolmente penalizzante dal punto di vista
prestazionale.
Sono state quindi studiate architetture alternative maggiormente
performanti (eg. ASPdell'IIS o Plug-in del
Netscape Server). Tali soluzioni sono valide dal punto di vista
prestazionale ed architetturale ma sono proprietarie...
Le specifiche J2EE hanno introdotto i Servlet che sono
applicazioni Java che vengono eseguite in una JVM detta Servlet
Container. All'interno di un singolo processo sempre attivo
vengono istanziati una volta ed eseguiti piu' volte i thread
relativi ai vari servlet. In questo modo l'utilizzo dei thread
richiede un overhead minimo e tutte le risorse del server sono
dedicate ad implementare le logiche applicative.
Un esempio di Servlet:
/* * @(#)ILoveYouServlet.java 1.00 03/02/14 * * Copyright (c) 2001-2003 Meo * * CopyrightVersion 1.0 */ import java.io.*; import javax.servlet.*; import javax.servlet.http.*; /** * I Love You. This servlet simply says I love You! * * Since I am a very strong man it says I love You three times... */ public class ILoveYou extends HttpServlet { public void doGet (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { int i; res.setContentType("text/html"); ServletOutputStream out = res.getOutputStream(); out.println("<html>"); out.println("<head><title>I Love You</title></head>"); out.println("<body>"); for (i=0; i<3; ) out.println("I love You!"); out.println("</body></html>"); } public String getServletInfo() { return "Create a page that says I love You! three times"; } } |
Dall'esempio si puo'
comprendere che il programmatore ha il completo controllo della
pagina generata. Alcuni Java Container (eg. BEA, WebSphere, ...)
offrono librerie aggiuntive per semplificare la generazione
dell'HTML e la gestione della grafica, ma la logica di base e
l'architettura non cambiano.
Un Servlet e' un'applicazione Java completa senza limiti
particolari (se non quelli imposti con la configurazione del
Servlet Container) e quindi puo' utilizzare JDBC (per l'accesso a
DB), RMI (per il
richiamo remoto di metodi), EJB (per il richiamo di
Enterprise Bean), ... quindi le potenzialita' sono notevoli.
E' opportuno spendere una parola in piu' sugli EJB (Enterprise
Java Bean). Oltre ad essere componenti riutilizzabili e
facilmente programmabili con un IDE (come i Java Bean),
consentono di limitare la programmazione alle componenti di
logica applicativa. Infatti per l'autenticazione, la gestione
delle transazioni, l'accesso alle basi dati ... possono/debbono
struttare i servizi dell'EJB Container.
Poiche' la fase di connessione ai DB e' particolarmente pesante
la tecnica comunemente utilizzata e' quella del Connection
Pooling. Ovvero vengono mantenute attive una serie di connessioni
ai DB ed i servlet accedono a tali risorse condivise anziche'
aprirne di proprie. Questa e' una delle soluzioni piu' utilizzate
poiche' consente di coniugare la massima efficenza e sicurezza
utilizzando un'architettura a tre livelli.
L'EJB Container fornisce anche altri servizi. Ad esempio il
naming richiamabile
con l'API JNDI (Java Naming and Directory Interface) o la
sicurezza JAAS (Java Authentication and Authorization Service).
Per non parlare di prodotti...
Tomcat e' un Servlet/JSP Container; JBOSS, BEA, WebSphere, Oracle OC4J,
sono invece EJB Container.
Una nota sul deploy. Le specifiche J2EE prevedono una struttura
di directory precisa ed il rilascio in automatico di file
.WAR o .EAR.
Le tecniche viste fino
ad ora possono essere utilizzate nella costruzione di
architetture applicative complesse. E' ad esempio possibile
utilizzare un Applet che realizza la grafica dell'applicazione e
che, via RMI, richiama un Servlet che gestisce la logica di
Business e che, a sua volta,
utilizza EJB per l'accesso ad una base dati con le
API JDBC...
Ma piu' di tante parole vale forse qualche esempio (non completo
come nei casi precedenti ma solo relativo al richiamo RMI, JDBC e
EJB.
Un esempio di richiamo RMI (componente server):
public class MyServerImpl implements myServer { void receiveRequest(myClient client, String message) throws RemoteException { String reply = ""; Int i; for (i=0;i<3;) reply = reply+"Ti amo!\n" client.receive(reply); } } |
E la parte client:
public class MyClientImpl implements myClient { MyServer server; public MyClientImpl(String Server_IOR, ORB orb) throws Exception { server = (MyServer) PortableRemoteObject.narrow( orb.string_to_object(Server_IOR), MyServer.class); } void receiveReply(String message) throws RemoteException { System.out.println(message); } public void talk(String conversation) { server.receiveRequest(this, conversation); } } the_client.talk("Dimmelo!"); |
Un esempio di accesso JDBC:
import java.sql.*; public class Dimmelo { public static void main( String[] args ) throws SQLException { int i; DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver()); Connection conn = DriverManager.getConnection( "jdbc:oracle:thin:@127.0.0.1:1521:orcl", "SCOTT", "TIGER" ); Statement stmt = conn.createStatement(); for (i=0; i<3; i++) stmt.executeUpdate( "INSERT INTO dimmelo(testo) VALUES('Ti Amo!')" ); stmt.executeUpdate( "COMMIT" ); } } |
Un esempio di utilizzo EJB (definzione EJB):
package oracle.ejb30; import javax.ejb.Stateless; @Stateless public class HelloWorldBean implements HelloWorld { public void sayHello() { int i; for (i=0; i<3; i++) System.out.println("Ti amo!"); } } |
Ed il richiamo dell'EJB:
Context context = new InitialContext(); HelloWorld helloWorld = (HelloWorld)context.lookup("java:comp/env/ejb/HelloWorld"); helloWorld.sayHello(); |
Insomma si puo' fare di tutto ma non e' cosi semplice...
Con i servlet si puo'
realizzare un'applicazione comunque complessa e si puo' mantenere
il massimo livello di efficenza ma... scrivere un servlet non e'
poi cosi' semplice e richiede tempo. Certo sarebbe piu' facile
scrivere in HTML!
Le Java Server Pages (JSP) vengono incontro a questa esigenza di
semplificazione della programmazione. Un servlet permette
il massimo controllo ma risulta molto piu' complesso dell'HTML
per la gestione della grafica. Una pagina JSP e' facile (quasi) come
una pagina HTML e potente (quasi) come un programma servlet.
Dal punto di vista di programmazione una pagina JSP e' analoga ad una pagina HTML in cui si utilizzano alcuni TAG aggiuntivi (eg. <%) per le parti di programmazione o il richiamo ad oggetti esterni. Quindi e' molto semplice da utilizzare e di immediata comprensione.
Dal punto di vista architetturale una pagina JSP viene
compilata in modo automatico in un servlet la prima volta che
viene richiamata. Tale compilazione avviene una sola volta e non
e' piu' necessaria, a meno di una modifica nella pagina
stessa.
Percio' con le pagine JSP si hanno al tempo stesso la semplicita'
delle pagine HTML e l'efficenza dei servlet.
Un esempio di pagina JSP:
<html> <head> <! Esempio in JSP> <title>Ditelo con ... JSP</title> </head> <body> <% for (int i=0; i<3; i++) { %> <p>Ti amo! <% } %> </body> </html> |
L'utilizzo degli
Enterprise Java Bean e' possibile in qualsiasi programma Java
(purche' recente) ed e' anche possibile dalle pagine JSP con
opportuni TAG. Il loro utilizzo e' particolarmente utile nelle
applicazioni di grandi dimensioni per isolare la logica di
accesso ai dati.
L'architettura risultante e' la seguente:
Il modello di
programmazione visto fino ad ora permette di generare pagine HTML
in modo efficiente e relativamente semplice. Ma e' possibile
un'ulteriore evoluzione.
Tale evoluzione, detta modello 2, utilizza la logica Model View
Controller (MVC).
L'idea di base e' quella di separare in modo netto la parte di
presentazione dalla business logic. La parte di presentazione
deve consentire una facile ed efficiente gestione della grafica e
sara' programmata da figure con skill rivolti all'interfaccia
utente ed alla grafica. La business logic deve avere
caratteristiche di robustezza ed efficenza e sara' programmata da
figure con skill differenti.
L'implementazione piu' diffusa di tale modello e'
Struts. Si tratta di un'implementazione basata su
componenti standard ma non e' uno standard. Si tratta infatti
"solo" di un'implementazione Open Source (Jakarta Apache) di un
modello.
L'idea di base e' quella di separare con chiarezza la parte di
presentazione dalla logica applicativa e dall'accesso ai dati e
di utilizzare lo strumento migliore per ogni
parte.
La
parte di presentazione viene realizzata con pagine JSP che sono
di semplice generazione e possono essere arricchite a piacere per
realizzare una grafica di qualita'.
La logica applicativa viene realizzata in java, linguaggio che
permette il massimo livello di controllo da parte del
programmatore, creando una servlet.
L'accesso ai dati viene realizzato con gli EJB che forniscono
un'interfaccia adatta agli IDE e possono essere richiamati in
modo ugualmente semplice dalle pagine JSP e dai
servlet.
L'utilizzo di Struts non e' immediato e richiede competenze specifiche su alcuni argomenti non certo semplici... Tuttavia, superata la fase iniziale, struts consente la realizzazione di applicazioni complesse, la suddivisione in sotto-progetti del lavoro e l'utilizzo di gruppi di lavoro, anche ampi numericamente, con differenti specializzazioni.
Un'architettura SOA
(Service Oriented Architecture) e' composta da diverse
applicazioni (un esempio di Applicazione SOAP) che
colloquiano tra loro con il protocollo SOAP (Simple Object
Access Protocol).
SOAP e' un protocollo basato sull'HTTP (HyperText Transfer
Protocol) tra applicazioni che si scambiano dati in formato XML
(eXtented Markup Language) per inviare richieste e risposte. Le
richieste vengono inviate ad un SOAP Server che pubblica l'elenco
dei servizi forniti con un documento WSDL (Web Services
Description Language).
Le idee di base sono molto semplici ed, utilizzando un IDE, e'
anche semplice sviluppare applicazioni. Inoltre l'utilizzo
dell'HTTP rende semplice ospitare le applicazioni nelle reti
aziendali. Si tratta infatti di uno dei protocolli piu' diffusi e
che viene tipicamente lasciato aperto su firewall ed instradato
dai proxy.
Non vi ricorda nulla questa architettura? Se lasciamo stare il WSDL e l'XML... e' la stessa architettura di un normale servizio web! Al posto di un browser ora c'e' un Client che richiede servizi. Tutto qui!
Un particolare utilizzo
dell'architettura SOA e' quella per la realizzazioni di Portali
individuata dallo standard WSRP.
Nella costruzione Portali web le componenti di infrastruttura (la
presentazione grafica, la profilazione degli utenti, il Single
Sign-On) sono gestite con un servizio centralizzato, mentre i
diversi contenuti possono essere forniti da applicazioni esterne
dette Portlet.
La differenza fondamentale tra un Servlet ed un Portlet e' che
mentre un Servlet genera un'intera pagina HTML ed ha quindi un
controllo completo dell'interazione con l'utente, un Portlet ha
il compito di fornire una parte di contenuto e restituisce quindi
un XML (XHTML). Un Portlet non puo' effettuare riderizioni o
accedere in modo diretto alla profilazione dell'utente: deve
utilizzare le Portlet API per ogni richiesta in modo da non
danneggiare il Portlet container che li ospita. Un Portlet e'
tipicamente amministrato in modo molto piu' flessibile rispetto
ad servlet: le applicazioni non cambiano spesso, i contenuti
si.
I primi ambienti per la
creazioni di portali utilizzavano API proprietarie o erano un
evoluzione di sistemi di Content Management.
Gli attuali standard prevedono l'utilizzo di un protocollo
specifico (il WSRP) tra le applicazioni Portlet (WSRP Producer)
ed il Portale (WSRP Consumer). Lo scambio di informazioni avviene
con file XML In questo modo e' possibile far colloquiare
applicazioni realizzate su ambienti ed architetture
differenti.
Naturalmente il WSRP e'
un protocollo SOAP.
E' pertanto possibile realizzare applicazioni utilizzando le API
standard (JSR-168) oppure un framework proprietario, purche' sia
compatibile WSRP.
Un esempio di portlet:
public void doView (RenderRequest request, RenderResponse response) throws PortletException, IOException { response.setContentType("text/html"); String jspName = getPortletConfig().getInitParameter("jspView"); PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(jspName); rd.include(request,response); } |
In pratica il portlet implementa un metodo per ogni azione corrispondente ad un modo di visualizzazione. Per rendere il codice per la parte grafica piu' semplice viene quindi lanciata una pagina JSP:
<%@ page session="false" %> <%@ page import="javax.portlet.*"%> <%@ page import="java.util.*"%> <%@ taglib uri='/WEB-INF/tld/portlet.tld' prefix='portlet'%> <portlet:defineObjects/> <p>Ti amo!</p> <p>Ti amo!</p> <p>Ti amo!</p> Portlet Mode: <%=portletRequest.getPortletMode()%> |
Quanto riportato in questo documento sono solo alcuni esempi tra le architetture piu' diffuse per la realizzazione di applicazioni web (molte mancano all'appello come linguaggi di scripting, Ajax, ... ma sarebbe diventato troppo lungo e noiso per descriverle tutte). L'idea era quella di fornire spunti ed indicazioni per la comprensione delle piu' attuali architetture... spero di esserci riuscito!
Testo: Sette
architetture in cerca d'autore
Data: 25 Dicembre 2005
Versione: 1.0.4 - 29 Febbraio 2007
Autore: Meo
Bogliolo