MokaByte 76 - Luglio Agosto 2003 
La nuova architettura
AOP di JBoss
di
Erlend Bųe
La nuova versione 4 di JBoss č basata su un framework AOP (Aspect Oriented Programming). JBoss 4 dą anche la possibilitą di usare AOP nelle nostre classi, permettendo ad una classe normale (non-EJB) di utilizzare servizi enterprise di tipo caching, replicazione, transazioni e sicurezza.

Introduzione
Oggi il contenitore EJB fornisce servizi alla nostra applicazione, per esempio sicurezza e gestione della persistenza.
Il server EJB intercetta le chiamate e gestisce l'ambiente per le nostre classi EJB, applicando gli aspetti ("servizi") richiesti.
Nella metodologia Object Oriented non è possibile esprimere questi aspetti in modo efficiente. L'unico modo è l'inserimento in più classi del codice a mano, con l'implicazione di una limitazione dela flessibilità avendo gli aspetti un impatto su più classi.
EJB è una soluzione standardizzata che aiuta a risolvere il problema negli aspetti più comuni.


Figura 1
- La architettura EJB

L'Aspect Oriented Programming (AOP) è una nuova tecnica di programmazione sviluppata nel 1997 da Kiczales et al. a Xerox Parc [1,2].
Gli ideatori di AOP hanno notato che esistono requisiti a livello design, che sono facili da esprimere, ma difficile da implementare perché hanno un impatto su più classi.
Per migliorare la qualità e facilitare la manutenzione del codice è utile scrivere in un punto solo il codice che implementa una funzionalità. Ma come si fa quando la funzionalità ha un impatto su più classi? La vera innovazione dell'AOP è la proposta di una soluzione per trattare questo problema. Con AOP si scrive il codice che implementa la funzionalità (chiamato "aspect" <-> "aspetto") una sola volta, insieme ad istruzioni che dicono come applicare la nuova funzionalità a più classi.
AOP introduce nuovi concetti e li esprime con nuovi vocaboli, consentendo così al programmatore di rappresentare i concetti EJB in un'altra prospettiva. AOP impatta soprattutto sull'implementazione del server EJB, e quindi non ha conseguenze importanti per il programmatore che utilizza EJB, ma per quest'ultimo è lo stesso utile conoscere i nuovi termini.
Per esempio se vogliamo gestire la sicurezza senza usare EJB, dobbiamo inserire in tante classi diverse codice che controlla se l'accesso è permesso: la sicurezza è un esempio tipico di "aspetto" AOP.
Ragionando in questo modo si può pensare anche agli altri servizi EJB come aspetti AOP, ed immaginare l'architettura EJB semplicemente come un'implementazione specializzata di AOP con i servizi EJB come aspetti preimpostati con un funzionamento standardizzato: in questo scenario il deployment descriptor descrive come applicare i servizi ("aspetti") EJB.

 

JBoss 4
Il gruppo JBoss ha pensato in questi termini nella realizzazione della versione 4.0, basata su un framework AOP. Per gli EJB, JBoss usa un class loader speciale che legge il file di configurazione (deployment descriptor) e aggiunge codice addizionale che chiama i servizi richiesti. Per un'applicazione EJB standard non è cambiato niente, solo il funzionamento interno di JBoss.
Gli sviluppatori hanno inoltre reso pubblico il funzionamento di JBoss AOP, permettendo ad una classe normale (non-EJB) di avere l'uso di servizi enterprise di tipo caching, replicazione, transazioni e sicurezza, utilizzando un semplice file XML molto simile ad un deployment descriptor.
JBoss AOP è un vero framework AOP che permette di intercettare le chiamate di metodi, costruttori e campi nelle classi, di introdurre metodi e campi, e di usare metadati.

 

Concetti AOP
AOP definisce nuovi vocaboli per poter esprimere i nuovi concetti. Per implementare i concetti AOP in Java occorre la manipolazione del byte-code o l'uso di un dynamic proxy (java.lang.reflect.Proxy). Questo può essere fatto in due modi: al momento della compilazione, con un compiler speciale, o a run-time con un class loader speciale.

Aspect
Un aspect è una decisione a livello di design che ha un impatto ortogonale al livello d'implementazione, ovvero il codice che realizza la funzione desiderata è disperso in più classi ("cross-cutting"). Implementato usando advice, introduction, metadata e pointcuts.

Advice/Interceptor
Un advice è un pezzo di codice aggiuntivo inserito nelle classi per implementare un aspetto o una parte di un aspetto. In JBoss è utilizzato un Interceptor: una classe che implementa l'interfaccia org.jboss.aop.Interceptor e che intercetta chiamate di metodi, costruttori e campi. Per esempio, nell'ambito EJB, il servizio di sicurezza può essere implementato usando uno o più advice, introduction e metadata.


Figura 2 - Interceptors


Introduction
L'Introduction permette di introdurre nuovi metodi e campi nella classe. E' anche possibile cambiare la superclasse ed le interfacce che la classe implementa. Finalmente arriva l'eredità multipla in Java!
L'Introduction è un concetto molto importante per l'AOP. Gli esperti dicono che il 50% di AOP è introduction.

Mixin
Mixin è una classe usata per implementare introduction. Essa contiene il codice dei metodi/campi da introdurre.

Metadata
I Metadati sono dati aggiuntivi che possono essere associati ad una classe o ad un oggetto staticamente o dinamicamente. I Metadati non sono un concetto strettamente collegato ad AOP, essendo definito in JSR 175 [3], ed introdotto in JDK 1.5.
Per esempio, per transazioni EJB è possibile specificare per ogni metodo nel deployment descriptor attributi come Required, Supports, ecc.
Un interceptor per le transazioni può usare questi dati per decidere come gestire le transazioni, e aggiungere dati (transaction context) dinamicamente per ogni oggetto coinvolto in una transazione.

Pointcuts
Un pointcut specifica dove (a quali classi, metodi) applicare advice, introduction e metadata alle classi normali Java. Per JBoss AOP un pointcut è definito usando XML in un modo molto simile ad un deployment descriptor. Questo vuol dire che non c'è bisogno di imparare un nuovo linguaggio per usare AOP. Per AspectJ (il primo è più famoso AOP per Java) invece, è necessario imparare una nuova sintassi per esprimere i concetti AOP.

Weawing
Il weawing consiste nel processo di effettuare inserimento del codice che implementa gli aspetti nelle classi normali Java.
Per JBoss AOP, il classloader legge il file di configurazione che contiene i pointcuts, e applica gli aspetti a run-time. AspectJ invece usa un compilatore speciale.

POJO
POJO è una classe normale (non-EJB) Java. (Plain Old Java Object).


JBoss AOP
Definire un Interceptor

L'interfaccia org.jboss.aop.Interceptor contiene solo due metodi, getName e invoke.
Per le classi per cui è applicato, JBoss inserisce una chiamata al metodo invoke, in altre parole invoke è chiamato per ogni invocazione, come mostrato nella figura 2.
Con JBoss AOP non è possibile dire che vogliamo usare l'interceptor solo per un particolare metodo. Questo vuol dire che dentro l'interceptor può essere necessario controllare il nome del metodo e prendere una decisione basata sul nome del metodo.

public interface Interceptor {
  public String getName();
  public InvocationResponse invoke(Invocation invocation)
                            throws Throwable;
}


Invocation contiene il nome del metodo/costruttore o campo, e i parametri.
Sotto è mostrata la classe TracingInterceptor dalla cartella docs/oreilly-aop/example1 fornita con JBoss-AOP

import org.jboss.aop.*;
import java.lang.reflect.*;

public class TracingInterceptor implements Interceptor {
  public String getName() { return "TracingInterceptor"; }

  public InvocationResponse invoke(Invocation invocation)
                            throws Throwable{
    String message = null;
    if (invocation.getType() == InvocationType.METHOD){
      Method method = MethodInvocation.getMethod(invocation);
      message = "method: " + method.getName();
    }
    else if (invocation.getType() == InvocationType.CONSTRUCTOR){
      Constructor c = ConstructorInvocation.
                      getConstructor(invocation);
      message = "constructor: " + c.toString();
    }
    else{
     // Do nothing for fields. Just too verbose
     return invocation.invokeNext();
    }
    System.out.println("Entering " + message);
    InvocationResponse rsp = invocation.invokeNext();
    System.out.println("Leaving " + message);
    return rsp;
  }
}

Tramite la classe helper org.jboss.aop.MethodInvocation, si può ottenere un riferimento al metodo. La TracingInterceptor non fa altro che scrivere un messaggio prima e dopo l'invocazione del metodo o costruttore. Si noti che è necessario inserire il codice "invocation.invokeNext()" in modo che JBoss AOP chiami altri Interceptor nella catena d'interceptor per una classe e finalmente il metodo/costruttore vero.

 

Definire dove applicare l'interceptor (il pointcut)
JBoss AOP usa un file XML per definire un pointcut. Si noti che è possibile definire il pointcut solo a livello di classe, non a livello di metodi nella classe.

<?xml version="1.0" encoding="UTF-8"?>
<aop>
<interceptor-pointcut class="POJO">
<interceptors>
<interceptor class="TracingInterceptor"/>
</interceptors>
</interceptor-pointcut>
</aop>

Per JBoss AOP standalone è necessario che il file XML abbia il nome META-INF/jboss-aop.xml. Per l'uso d'AOP dentro JBoss, è possibile fare il deploy di un file chiamato *-aop.xml, o un jar con META-INF/jboss-aop.xml.

 

Usare JBoss AOP fuori dell'application server JBoss (standalone)
Per fare funzionare l'esempio1 fuori da JBoss, è necessario di aggiungere al classpath javassist.jar, jboss-common.jar e jboss-aop.jar e usare un class loader speciale.

cd docs/oreilly-aop/example1
setenv CLASSPATH $CLASSPATH:.:
       $JBOSS_AOP/jboss-common.jar:
       $JBOSS_AOP/jboss-aop.jar:$JBOSS_AOP/javassist.jar
javac *.java
java -Djava.system.class.loader =
     org.jboss.aop.standalone.SystemClassLoader POJO

 

Metadata
Si possono aggiungere metadati nel file XML o nell'interceptor. Poiché l'interceptor intercetta tutte le chiamate per una classe, un uso interessante dei metadati è decidere quale metodi intercettare. Il Pointcut sotto fa parte dell'esempio2, e aggiunge metadata ai metodi get, set, e main della classe POJO.

<class-metadata group="tracing" class="POJO">
<method name="(get.*)|(set.*)">
<filter>true</filter>
</method>
<method name="main">
<filter>true</filter>
</method>
</class-metadata>

Per accedere ai metdadati dentro l'interceptor si usa il metodo getMetadata:

String filter = (String)invocation.getMetaData("tracing", "filter");
if (filter != null && filter.equals("true")) return invocation.invokeNext();


Conclusioni
Questa è sola una breve introduzione a JBoss AOP. La documentazione sul sito di JBoss [4,5] spiega in modo dettagliato come usare servizi standard JBoss, quali per esempio le transazioni. Il gruppo JBoss ha realizzato un prodotto all'avanguardia con la nuova versione 4 basata su AOP. Gli sviluppatori hanno inoltre reso pubblico il funzionamento di JBoss AOP, creando una alternativa interessante per chi usa JBoss.
L'uso d'AOP apre nuove possibilità per migliorare la qualità del codice e consente molto più controllo al programmatore che l'EJB.
Infatti, si può pensare ad EJB come un'implementazione ristretta di AOP.
Naturalmente EJB ha il grande vantaggio di essere standardizzato.
JBoss AOP ha lo svantaggio che è necessario usare un class loader JBoss. Questo vuol dire che per ora non è possibile utilizzarlo con un altro application server.
JBoss AOP ha il vantaggio di avere già servizi prescritti di tipo EJB che si può facilmente usare, ma per chi vuole usare AOP con qualsiasi server EJB, ci sono almeno tre alternative:

  • Nanning (http://nanning.snipsnap.org)
  • Aspectj(http://www.eclipse.org/aspectj)
  • AspectWerkz(http://aspectwerkz.codehaus.org/)
    AspectWerkz è simile a JBoss AOP poiché usa un file XML per specificare i pointcuts e un class loader speciale, ma è in grado di modificare anche le classi dentro un application server.


Bibliografia
[1] Kirczales et al - "Aspect-oriented programming", Springer-Verlag, Giugno 1997.
[2] http://aosd.net - Il sito ufficiale dell'AOSD steering committee.
[3] http://www.jcp.org/en/jsr/detail?id=175 - Sito SUN per JSR 175.
[4] http://www.jboss.org/developers/projects/jboss/aop - Home per JBoss AOP.
[5] http://www.onjava.com/pub/a/onjava/2003/05/28/aop_jboss.html - Articolo introduttivo.

MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it