SeamFramework.orgCommunity Documentation

Capitolo 5. Scope e contesti

5.1. Tipi di scope
5.2. Scope predefiniti
5.3. Lo scope conversazione
5.3.1. Demarcazione della conversazione
5.3.2. Propagazione della conversazione
5.3.3. Timeout della conversazione
5.4. Pseudo-scope dipendente
5.4.1. Annotazione @New

Finora si sono visti pochi esempi di annotazioni di tipi di scope. Gli scope di un Web Bean determinano il ciclo di vita del Web Bean. Lo scope determina anche quali client fanno riferimento a quali istanze di Web Bean. Secondo la specifica Web Bean, uno scope determina:

  • Quando una nuova istanza di un Web Bean con tale scope viene creata

  • Quando un'istanza esistente di un Web Bean con tale scope viene distrutta

  • Quali riferimenti iniettati puntano a istanze di un Web Bean con tale scope

Per esempio, se esiste un Web Bean con scope di sessione, CurrentUser, tutti i Web Bean che vengono chiamati nel contesto della medesima HttpSession vedranno la stessa istanza di CurrentUser. Quest'istanza verrà automaticamente creata la prima volta che in tale sessione occorre CurrentUser, e verrà distrutta automaticamente quando la sessione termina.

Web Bean fornisce un modello di contesto estensibile. E' possibile definire nuovi scope creando una nuova annotazione di un tipo di scope.

@Retention(RUNTIME)

@Target({TYPE, METHOD})
@ScopeType
public @interface ClusterScoped {}

Sicuramente questa è la parte facile del lavoro. Affinché questo tipo di scope sia utile, avremo bisogno di definire un oggetto Contesto che implementi lo scope! Implementare un Contesto è compito molto tecnico, inteso solo per lo sviluppo di framework.

Si può applicare un'annotazione con un tipo scope ad una classe di implementazione Web Bean per specificare lo scope del Web Bean:

@ClusterScoped

public class SecondLevelCache { ... }

Solitamente si userà uno degli scopi predefiniti di Web Beans.

Web Beans definisce quattro scope predefiniti:

Per un'applicazione web che impiega Web Beans:

Gli scope di richiesta ed applicazione sono pure attivi:

Se l'applicazione prova ad invocare un Web Bean con scope che non ha un contesto attivo, una ContextNotActiveException viene lanciata a runtime dal manager Web Bean.

Tre dei quattro scope predefiniti dovrebbero essere estremamente familiari ad ogni sviluppatore Java EE, quindi non si procede oltre nella discussione. Uno degli scope è comunque nuovo.

Lo scope di conversazione di Web Beans è un pò come il tradizionale scope di sessione in cui viene mantenuto lo stato associato all'utente del sistema, e vengono create richiest multiple al server. Comunque, a differenza dello scope di sessione, lo scope di conversazione:

Una conversazione rappresenta un task, un'unità di lavoro dal punto di vista dell'utente. Il contesto di conversazione mantiene uno stato associato all'utente che sta lavorando. Se l'utente sta facendo più cose contemporaneamente ci saranno più conversazioni.

Il contesto di conversazione è attivo durante ogni richiesta JSF. Comunque, la maggior parte delle conversazioni vengono distrutte alla fine della richiesta. Se una conversazione deve mantenere lo stato nel corso richieste multiple, deve esplicitamente essere promossa a conversazione long-running.

Web Beans fornisce un Web Bean predefinito per controllare il ciclo di vita delle conversazioni in un'applicazione JSF. QUesto Web Bean può essere ottenuto per iniezione:

@Current Conversation conversation;

Per promuovere a long-running la conversazione associata alla richiesta corrente, occorre chiamare il metodo begin() dal codice dell'applicazione. Per schedulare la distruzione del contesto attuale della conversazione long-running, si chiami end().

Nel seguente esempio un Web Bean con scope di conversazione controlla la conversazione alla quale è associato:

@ConversationScoped @Stateful

public class OrderBuilder {
    private Order order;
    private @Current Conversation conversation;
    private @PersistenceContext(type=EXTENDED) EntityManager em;
    
    @Produces public Order getOrder() {
        return order;
    }
    public Order createOrder() {
        order = new Order();
        conversation.begin();
        return order;
    }
    
    public void addLineItem(Product product, int quantity) {
        order.add( new LineItem(product, quantity) );
    }
    public void saveOrder(Order order) {
        em.persist(order);
        conversation.end();
    }
    
    @Remove
    public void destroy() {}
    
}

Questo Web Bean è capace di controlla il proprio ciclo di vita attraverso l'uso della API Conversation. Ma altri Web BEan hanno un ciclo di vita che dipende completamente da un altro oggetto.

In aggiunta ai quattro scope predefiniti, Web Bean fornisce il cosiddetto pseudo-scope dipendente. Questo è lo scope di default per un Web Bean che non dichiara esplicitamente un tipo di scope.

Per esempio questo Web Bean ha uno scope di tipo @Dependent:

public class Calculator { ... }

Quando un punto di iniezione di un Web Bean risolve verso un Web Bean dipendente, viene creata una nuova istanza di Web Bean dipendente ogni volta che il primo Web Bean viene istanziato. Le istanze dei Web Beans dipendenti non vengono mai condivise tra Web Bean differenti o punti di iniezione differenti. Sono oggetti dipendenti di altre istanze Web Bean.

Istanze Web Bean dipendenti vengono distrutte quando viene distrutta l'istanza da cui dipendono.

Web Beans facilità l'ottenimento di un'istanza dipendente di una classe Java o bean EJB, anche se la classe o bean EJB sono già dichiarati come Web Bean con qualche altro tipo di scope.