Sette architetture in cerca d'autore

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!


HTTP

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.

Architettura HTTP

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 ...


CGI

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.

Architettura CGI

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.


Applet

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.

Architettura Applet

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!


Servlet

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.

Architettura servlet

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...


JSP

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.

Architettura JSP

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:

Architettura JSP-EJB


Struts

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.

Architettura Struts

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.


SOA

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.

Architettura SOA

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.

Portlet

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()%>


Tutto qui?

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