Terzo articolo su Web Beans, un insieme di servizi per Java EE, nati per rendere più agevole lo sviluppo di applicazioni. Dopo avere affrontato le specifiche e gli scope, stavolta focalizzeremo l‘attenzione sui deployment types e sugli stereotipi.
Deployment types
Spesso può capitare che, all’interno di una stessa applicazione, ci siano diverse implementazioni di un certo type. L’implementazione usata a runtime può essere diversa al variare del deployment del sistema. Perciò è possibile associare una particolare implementazione di un bean type con un determinato scenario di deployment. E quindi un dato deployment type rappresenta uno scenario di deployment. I bean possono essere classificati in base al deployment type e di conseguenza associati a diversi tipi di scenari di deployment. Il container è in grado di identificare quali bean devono essere abilitati all’utilizzo in un particolare deployment del sistema proprio grazie ai deployment types.
Le specifiche Web Beans prevedono un set di deployment types built-in
@javax.inject.Production e @javax.inject.Standard
È comunque possibile estendere tale set.
Un deployment type è una annotation definita come
@Target({TYPE, METHOD, FIELD})
e
@Retention(RUNTIME)
Inoltre tutti i deployment type devono specificare anche la meta-annotation
@javax.inject.DeploymentType
Vediamo qualche esempio.
Il seguente deployment type potrebbe identificare beans che vengono usati solo per un particolare site in cui è stato effettuato il deploy di un’applicazione.
@DeploymentType @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME) public @interface Portuguese{}
Invece il seguente può essere utilizzato da framework terze parti che interagiscono con il container:
@DeploymentType @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME) public @interface iBatisFramework{}
Un deployment type di un bean viene dichiarato annotandone la classe. Un bean può specificare al massimo un solo deployment type. Qualora si tenti di specificarne più di uno, il container scatena una eccezione di tipo javax.inject.DefinitionException al momento del deploy. Nel caso in cui i bean vengano dichiarati all’interno del file beans.xml, il deployment type può essere specificato usando il tag dedicato, indicando il nome dell’annotation type. Esempio:
Anche in questi casi, se si specifica più di un deployment type per un bean, il container scatena una eccezione di tipo javax.inject.DefinitionException.
Bean names
Un bean può avere un nome. Un bean può essere referenziato da un altro in Unified Expression Language (EL) tramite il suo nome. Un nome valido è composto da una lista di identificatori EL validi separati da punti. In questo modo i bean possono essere usati direttamente all’interno di una pagina JSP o JSF. Se, per esempio, abbiamo un bean avente come nome products, allora può essere utilizzato nel seguente modo:
Il nome di un bean viene specificato tramite l’annotation
@javax.annotation.Named
Tornando all’esempio del bean products:
@Named("products") public class ProductList implements DataModel { ... }
Se l’annotation @Named non specifica alcun valore, allora viene preso in considerazione il nome di default. Se i bean vengono dichiarati all’interno del file beans.xml, il nome può essere specificato tramite il tag . Esempio:
products
Se il tag è vuoto, allora viene preso in considerazione il nome di default.
Ad un bean deve essere assegnato un nome di default da parte del container nei seguenti casi:
- la definizione della classe del bean presenta l’annotation @Named senza che però sia stato indicato un nome come valore di tale annotation;
- la definizione del bean all’interno del file XML presenta il tag vuoto;
- il bean dichiara uno stereotipo il quale dichiara una annotation @Named vuota e il bean non ne specifica esplicitamente il nome. Gli stereotipi saranno l’argomento del prossimo paragrafo.
Un bean non ha nome quando non viene specificata alcuna annotation @Named o alcun tag , sia dal bean stesso che dai suoi stereotipi.
Stereotipi
In molti sistemi il ricorso a pattern architetturali produce un insieme di ruoli ricorrenti per i bean. Uno stereotipo consente di individuare un ruolo e di dichiarare alcuni metadati comuni per tutti i bean aventi quel determinato ruolo come ruolo principale. Uno stereotipo incapsula una qualsiasi combinazione di un default deployment type, di un default scope, di una restrizione dello scope del bean, di un requisito riguardo l’estensione o l’implementazione di un certo type da parte di un bean e di un insieme di interceptor bindings. Uno stereotipo può anche specificare che tutti i bean con quello stereotipo abbiano nomi di default. Un bean può dichiarare nessuno o più di uno stereotipo.
Uno stereotipo è una Java annotation definita come
@Target({TYPE, METHOD, FIELD}) @Target(TYPE), @Target(METHOD) @Target(Field) @Target({METHOD, FIELD}) @Retention(RUNTIME)
Può essere dichiarato specificando la meta-annotation
@javax.annotation.Stereotype
Esempio:
@Stereotype @Target(TYPE) @Retention(RUNTIME) public @interface Action {}
Nel caso in cui i bean vengano dichiarati all’interno del file beans.xml uno stereotipo può essere dichiarato tramite il tag :
Uno stereotipo non può dichiarare binding annotation, altrimenti il container scatena una DefinitionException al momento del deploy. Uno stereotipo può dichiarare al più uno scope, altrimenti il container scatena una DefinitionException al momento del deploy. Stessa cosa per quanto riguarda i deployment type.
Uno stereotipo può dichiarare una annotation @Named vuota. Se invece uno stereotipo dichiara una annotation @Named vuota il container scatena una DefinitionException al momento del deploy. Un bean avente uno stereotipo che dichiara una @Named vuota ha il default name se esso non specifica alcun name.
Uno stereotipo può dichiarare altri stereotipi. Le dichiarazioni di stereotipi sono transitive: uno stereotipo dichiarato come secondo stereotipo è ereditato da tutti i bean e dagli altri stereotipi che lo dichiarano. Solo gli stereotipi dichiarati come
@Target(TYPE)
non possono essere applicati a stereotipi dichiarati come
@Target({TYPE, METHOD, FIELD}) @Target(METHOD) @Target(FIELD) @Target({METHOD, FIELD})
Gli stereotipi possono essere dichiarati tramite annotation o, nel caso di bean dichiarati all’interno del file beans.xml, come tag XML.
Uno stereotipo può aggiungere delle restrizioni ai bean che lo dichiarano. Se uno stereotipo dichiara un requiredType, e il bean che lo dichiara non include quel tipo, il container scatena una DefinitionException al momento del deploy. Anche nel caso in cui uno stereotipo dichiara in maniera esplicita un set di scope types che usano supportedScopes e lo scope del bean che lo dichiara non è compreso in tale set il container scatena una DefinitionException al momento del deploy. Un bean che dichiara più stereotipi deve soddisfare tutte le restrizioni da essi dichiarate.
Quando per un bean non viene esplicitamente dichiarato un deployment type, viene preso in considerazione quello di default. Questo dipende dagli stereotipi che il bean dichiara:
- se un bean non dichiara alcuno streotipo dichiarante un deployment type di default, @Production viene considerato come default deployment type;
- altrimenti viene preso in considerazione il default deployment type con la più alta precedenza dichiarato da uno degli stereotipi.
Se invece un bean dichiara un deployment type in maniera esplicita, ogni altro default deployment type dichiarato dagli stereotipi viene ignorato.
In un dato deployment solo alcuni deployment type sono enabled. Il container esamina tutti i deployment type di ciascun bean esistente in quel dato deployment per stabilire se un bean è enabled oppure no. In caso affermativo un’istanza di un bean può essere ottenuta tramite lookup, injection o risoluzione EL. In caso negativo il container non istanzierà mai quel bean. Per default solo i deployment type built-in sono enabled. Per rendere enabled un custom deployment type bisogna aggiungere il tag nella dichiarazione del bean all’interno del file beans.xml e il deployment type deve essere dichiarato usando l’annotation type name. Esempio:
In un dato deployment tutti i deployment type enabled sono ordinati in termini di precedenza. Qualora venga specificato il tag , l’ordine di dichiarazione dei deployment type ne determina la precedenza: quelli che compaiono in fondo alla lista hanno la precedenza su quelli che compaiono in cima. Il deployment type @Standard deve apparire per primo ed ha sempre una precedenza inferiore rispetto a tutti gli altri. Se il tag non viene specificato, il deployment type @Production ha precedenza più alta rispetto a @Standard.
Conclusioni
Con questo terzo articolo abbiamo terminato la trattazione delle caratteristiche principali dei Web Beans. Per ultimo abbiamo visto i deployment types, i names e gli stereotipi. Nel prossimo articolo vedremo l’implementazione di alcuni Web Beans.
Riferimenti
[1] JSR-299 Expert Group, “JSR-299: Context and Dependency Injection for Java”