CERCA SITEMAP FEED RSS 1280
Ultimo aggiornamento: 30 Agosto 2009

Session bean stateless

I session bean stateless non mantengono alcuno stato della conversazione con il client.
Essi sono tipicamente organizzati dal conteiner in un pool: ad ogni richiesta da parte del client un’istanza del session bean di tipo stateless viene recuperata dal pool e assegnata al client, quando la richiesta si conclude, l’istanza torna al pool per un successivo riutilizzo.
Questo significa che un numero relativamente piccolo di istanze di session bean di tipo stateless può essere usato per servire un grande numero di client.
Supponiamo di voler creare un semplice session bean stateless la cui interfaccia espone un metodo che restituisce la data corrente.
Supponendo di voler accedere al bean localmente (ovvero da componenti che si trovano all’interno dello stesso container EJB) possiamo definire la seguente interfaccia:
package miopackage;
  
@Local
public interface MiaIntSLSBLocal 
{
  String data();
}
Quindi occorre implementare l’interfaccia attraverso un POJO (Plain Old Java Object) annotato con @Stateless:
package miopackage;
   
import java.util.Date;
import javax.ejb.Stateless;
   
@Stateless
public class MioSLSB implements MiaIntSLSBLocal 
{
  @Override
  public String data() 
  {
    Date data = new Date();
    return "Data di oggi: "+data.getDay()+"/"+data.getMonth()+"/"+data.getYear();         
  }
}
L’annotazione @Stateless comunica al container EJB che l’implementazione costituisce un session bean di tipo stateless.

L’annotazione @Stateless è definita nel seguente modo:
@Target(TYPE) @Retention(RUNTIME)
public @interface Stateless 
{
  String name() default "";
  String mappedName() default "";
  String description() default "";
}
Tutti e tre i parametri (name, mappedName e description) sono opzionali motivo per cui nell’esempio abbiamo potuto scrivere:
@Stateless
public class MioSLSB implements MiaIntSLSBLocal 
...
Infatti se il parametro name viene omesso il container EJB automaticamente assegna il nome della classe.
Il parametro mappedName è il vendor-specific name che viene assegnato all’EJB.

Utilizzo dei session bean stateless

Supponiamo di voler invocare il metodo data() del session bean stateless da una servlet.
Le specifiche EJB consentono di poter ottenere mediante dependency injection dei riferimenti ad EJB che appartengono allo stesso container mediante l’annotazione @EJB così definita:
@Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
public @interface EJB 
{
  String name() default "";
  Class beanInterface() default Object.class;
  String beanName() default "";
}
Tutti e tre i parametri (name, beanInterface e beanName) sono opzionali: name suggerisce il nome JNDI da usare per collegare l’EJB referenziato al naming context dell’ambiente, beanInterface specifica l’interfaccia business usata per accedere all’EJB, beanName invece è utilizzato per distinguere fra EJB che implementano la stessa interfaccia business.
La dependency injection è possibile solo in ambienti gestiti e solo se il client risiede nello stesso container del session bean injected.
In realtà le servlet sono gestite dal web container e non dal container ejb, però le specifiche consentono di poter applicare la dependency injection anche in questo caso evitando le operazioni di look up JNDI.

Possiamo quindi implementare la sevlet nel seguente modo:
package miopackageweb;
   
import java.io.IOException;
import java.io.PrintWriter;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import miopackage.MiaIntSLSBLocal;
   
public class MiaServletSLSBLocal extends HttpServlet 
{
  private static final long serialVersionUID = 1L;
   
  @EJB
  private MiaIntSLSBLocal miobean;
        
  public MiaServletSLSBLocal() 
  {
  }
   
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
  {
    PrintWriter out = response.getWriter();
    out.println( "<html><body>"+miobean.data()+"</body></html>" );
    out.close();
  }
   
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
  {
  }
}
Come è possibile notare, l’annotazione @EJB viene applicata ad una variabile privata dello stesso tipo dell’interfaccia locale di business del session bean stateless.
Un container è quindi in grado di risolvere il riferimento e di restituire un’istanza del session bean dal pool.
L’istanza viene quindi utilizzata all’interno del metodo doGet per restituire la data corrente.

Business Interface

Le applicazioni client possono invocare un session bean di tipo stateless in tre distinti modi: accanto all’invocazione locale esiste infatti l’invocazione mediante RMI e quella tramite Web Services.
A ciascuno di questi tre tipi di accessi corrispondono tre tipi di interfacce business e tre distinte annotazioni da utilizzare.
Un’interfaccia locale viene definita per consentire l’accesso ai client che si trovano nello stesso container dell’istanza.

Come abbiamo visto nell’esempio, per definire un’interfaccia business locale si usa l’annotazione @Locale:
@Local
public interface MiaInterfaccia
...
I client che risiedono al di fuori del container in cui si trova l’istanza del session bean possono accedervi mediante Java RMI utilizzando un’interfaccia remota.

Per fare ciò occorre utilizzare l’annotazione @Remote:
@Remote
public interface MiaInterfaccia
...
Nel caso di interfacce remote è opportuno sottolineare che tutti i parametri e i tipi restituiti dai metodi devono essere serializzabili, ciò perché soltanto gli oggetti serializzabili possono essere inviati attraverso la rete usando RMI.
Il terzo tipo di interfaccia è specifico per i session bean di tipo stateless ed espone il session bean come un servizio SOAP-based marcandolo con l’annotazione @java.jws.WebService.
@WebService
public interface MiaInterfaccia
...
Sebbene non sia possibile marcare la stessa interfaccia con più di un’annotazione che ne specifichi il tipo di accesso (@Locate, @Remote, @WebService) è comunque possibile definire più interfacce che espongono gli stessi identici metodi marcate con annotazioni differenti.

Ciclo di vita di un session bean stateless

Il container EJB gestisce i session bean di tipo stateless nel seguente modo:
  • ne crea un’istanza utilizzando il costruttore di default quando è necessario
  • gestisce le dependency injection delle risorse
  • inserisce l’istanza nel pool
  • preleva un’istanza dal pool quando perviene una richiesta da parte di un client
  • esegue il metodo richiesto dal client attraverso l’interfaccia business
  • quando la richiesta si conclude l’istanza viene reinserita nel pool
  • se necessario l’istanza del bean viene distrutta.
E’ possibile utilizzare le annotazioni @PostConstruct e @PreDestroy per annotare i metodi che il container deve invocare alla costruzione e alla distruzione del session bean stateless.
@PostConstruct
public void inizializza() 
{
  ...
}
   
@PreDestroy
public void rilascia() 
{
  ...
}