Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 7 di 68
  • livello ninja
Indice lezioni

Session Bean Stateful

Session Bean Stateful: risolviamo il problema della necessità di gestire un processo a più step senza perdere informazioni di stato sulla sessione.
Session Bean Stateful: risolviamo il problema della necessità di gestire un processo a più step senza perdere informazioni di stato sulla sessione.
Link copiato negli appunti

Session Bean Stateful e passivazione

I session beans stateful mantengono uno stato conversazionale che li lega
ad uno specifico client per la durata di una sessione, quella aperta con il client.
Le variabili di istanza della classe del bean sono utilizzate per
mantenere lo stato e, se la passivazione è attiva, devono essere serializzabili (interfaccia Serializable). La più grande differenza tra session bean stateful e gli altri tipi di
session bean è che per essi il server non usa l'instance pooling.

Una caratteristica importante è la funzionalità di passivazione. Se vi è inattività tra client
e bean stateful e la sessione è ancora attiva, il server può decidere di rimuovere dalla memoria il session bean stateful e di salvare
il suo stato su disco (passivazione). Successivamente, alla richiesta di esecuzione di un metodo da parte del client,
il server lo riattiva creando un oggetto in memoria con lo stato salvato precedentemente (attivazione).

L'EJB Object di un session bean stateful rimane connesso con
il client, mentre l'istanza può essere rimossa dalla memoria nei
periodi di inattività dal garbage collector. Le annotation @PrePassivate e @PostActivate possono essere applicate su
metodi del bean da eseguire prima della passivazione e dopo l'attivazione,
metodi ideali per rilasciare e recuperare risorse utilizzate dal bean.

L'annotation @Remove
consente al client di concludere la sessione con il bean satateful, il client invoca il metodo
del bean marcato con essa e permette la chiusura della sessione e la rimozione del bean
dalla memoria.

Disattivare la passivazione

La novità introdotta
da Ejb 3.2 è la possibilità di disattivare la passivazione. Il bean, quindi, rimane in memoria
anche nei periodi di inattività senza essere serializzato su disco. La passivazione non attiva può essere
utile nei casi in cui il bean deve rimanere attivo per processi applicativi o per utilizzare variabili di istanza non serializzabili. La disattivazione della passivazione è possibile
con l'uso dell'attributo passivationCapable dell'annotation @Stateful.

Con un session bean stateful possiamo ad esempio risolvere il problema della realizzazione di
un componente carrello della spesa da riutilizzare in diversi applicativi. Un carrello della spesa
è utilizzato da moduli in esecuzione nella JVM
dell'Ejb stateful che andiamo a realizzare. Scegliamo quindi per esso un'interfaccia di tipo local.

Tuttavia, per quanto detto in precedenza, vogliamo poter effettuare degli unit test con JUnit per i componenti
EJB, decidiamo quindi di dotare il bean anche di un'interfaccia di tipo remote.

Definiamo l'interfaccia che rappresenta il contratto verso un client del session bean stateful/carrello della spesa. Nel progetto EJB ProgettoEjb1 creiamo il package it.html.progetto1.stateful.ejb32 e, al suo interno,
l'interfaccia ShoppingCart (contratto) e le interfacce ShoppingCartLocal e ShoppingCartRemote dotate rispettivamente di annotatione local e remote che estendono
ShoppingCart:

package it.html.progetto1.stateful.ejb32;
import java.util.List;
public interface ShoppingCart<T> {
    void addItem(T item);
    void removeItem(T item);
    List<T> getItems();
    void releaseShoppingCart();
}

Interfacce local e remote:

package it.html.progetto1.stateful.ejb32;
import javax.ejb.Local;
@Local
public interface ShoppingCartLocal<T> extends ShoppingCart<T> {}

package it.html.progetto1.stateful.ejb32;
import javax.ejb.Remote;
@Remote
public interface ShoppingCartRemote<T> extends ShoppingCart<T> {}

Implementiamo quindi il contratto verso client come descritto per i session bean stateless illustrando
la disabilitazione della passivazione:

package it.html.progetto1.stateful.ejb32;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Remove;
import javax.ejb.Stateful;
@Stateful(passivationCapable=false)
public class ShoppingCartBean implements ShoppingCartLocal<String>, ShoppingCartRemote<String> {
    private List<String> items;
    public ShoppingCartBean(){
        items=new ArrayList<String>();
    }
    @Override
    public void addItem(String item) {
        items.add(item);
    }
    @Override
    public void removeItem(String item) {
        items.remove(item);
    }
    @Override
    public List<String> getItems() {
      return items;
    }
    @Override
    @Remove
    public void releaseShoppingCart(){
	    items.clear();
	    items=null;
    }
}

Modifichiamo poi la classe di test aggiungendo un unit test per il bean del carrello rinominandola in IntegrationTest:

package it.html.progetto1.test;
import java.util.Properties;
import javax.naming.*;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import it.html.progetto1.ejb30.ConverterBeanRemote;
import it.html.progetto1.singleton.ejb32.NewsSingleton;
import it.html.progetto1.singleton.ejb32.NewsSingletonRemote;
import it.html.progetto1.stateful.ejb32.ShoppingCartRemote;
import junit.framework.TestCase;
public class IntegrationTestCase {
    private static Context namingContext;
    private static ConverterBeanRemote converteBeanRemote;
    private static ShoppingCartRemote<String> shoppingCartRemote;	
    private static final String CONVERTER_REMOTE_JNDI_NAME="/Progetto1Ear/ProgettoEjb1/ConverterBean!it.html.progetto1.ejb30.ConverterBeanRemote";
    private static final String SHOPPING_CART_REMOTE_JNDI_NAME="/Progetto1Ear/ProgettoEjb1/ShoppingCartBean!it.html.progetto1.stateful.ejb32.ShoppingCartRemote";
    @BeforeClass
    public static void obtainProxyReferences() throws NamingException{
        Properties jndiProperties = new Properties();
        jndiProperties.put("jboss.naming.client.ejb.context", true);
        jndiProperties.put(Context.PROVIDER_URL, "http-remoting://127.0.0.1:8080");
        jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
        namingContext = new InitialContext(jndiProperties);
    }
    @Test
    public void testConverter() throws NamingException{
        converteBeanRemote = (ConverterBeanRemote)namingContext.lookup(CONVERTER_REMOTE_JNDI_NAME);
        TestCase.assertEquals(converteBeanRemote.celsiusToFahrenheit(30.0f), 86.0f);
        TestCase.assertEquals(converteBeanRemote.fahrenheitToCelsius(86.0f), 30.0f);
    }
    @SuppressWarnings("unchecked")
    @Test
    public void testShoppingCart() throws NamingException{
        shoppingCartRemote = (ShoppingCartRemote<String>)namingContext.lookup(SHOPPING_CART_REMOTE_JNDI_NAME);
        System.out.println("Aggiunta elemento 1");
        shoppingCartRemote.addItem("Item1");
        System.out.println("Aggiunta elemento 2");
        shoppingCartRemote.addItem("Item2");
        System.out.println("Lista elementi:");
        for(String item : shoppingCartRemote.getItems()){
            System.out.println(item);
        }
        System.out.println("Rimozione elemento 1");
        shoppingCartRemote.removeItem("Item1");
        System.out.println("Lista elementi:");
        for(String item : shoppingCartRemote.getItems()){
            System.out.println(item);
        }
        shoppingCartRemote.releaseShoppingCart();
    }
    @AfterClass
    public static void tearDownClass() throws NamingException {
        namingContext.close();
    }
}

Ti consigliamo anche