Home   |   Archivio   |   Chi siamo   |   Contatti
Stefano Rossini
Client EJB
Realizzazione di client EJB: stand-alone, servlet e JSP
di
Stefano Rossini
In questo articolo viene mostrato come realizzare un client EJB sia come applicazione stand-alone sia come componente web. Il filo conduttore è l’esempio del bean Concat già presentato nell’articolo sui Session EJB.

In [SEJB] è stato presentato un esempio di Session EJB, sia stateless che stateful.

Per testare il Session Stateless bean Concat in [SEJB] è stata sviluppata un’applicazione stand-alone client, ConcatClient.java, che, una volta localizzato l’EJB, ne invocava il business method concat passando come parametri due stringhe e ricevendo come risultato la loro concatenazione.

Context initial = new InitialContext();
// Localizzazione della Home interface mediante JNDI
Object objRef = initial.lookup("MyService");
// PortableRemoteObject.narrow effettua l'opportuno CAST
ConcatHome home = (ConcatHome)
    PortableRemoteObject.narrow(objRef, ConcatHome.class);
// creo l'oggetto remoto mediante il metodo create della Home interface
Concat remoteConcat = home.create();
// invocazione del business method
String res = remoteConcat.concat("Hello", " EJB World !");

Se il client viene eseguito sulla stessa macchina del server si può mandare in esecuzione il ConcatClient referenziando nel classpath il ConcatAppClient.jar:

java -classpath .;%J2EE_HOME%\lib\j2ee.jar;ConcatAppClient.jar ConcatClient

Se il client invece è eseguito da una macchina remota, si possono scegliere due strade per configurare opportunamente la macchina client:

1. Utilizzare la proprietà org.omg.CORBA.ORBInitialHost referenziandola al server. 2. Specificare il context factory, cioè il protocollo, ed il service provider, cioè il server JNDI, dal quale recuperare la Home Interface.

Nel caso dell’Application Server Reference Implementation di SUN il JNDI server risponde sulla porta TCP 1050 ed utilizza il protocollo RMI-IIOP. Questo implica settare le proprietà java.naming.factory.initial e java.naming.provider.url.

java -classpath .;%J2EE_HOME%\lib\j2ee.jar;ConcatAppClient.jar \
  -Dorg.omg.CORBA.ORBInitialHost=<SERVER> ConcatClient
java -classpath .;%J2EE_HOME%\lib\j2ee.jar;ConcatAppClient.jar \
  -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory \
  -Djava.naming.provider.url=iiop://<SERVER>:1050 ConcatClient

In entrambi i casi al posto di <SERVER> si deve specificare il nome o l’indirizzo IP della macchina server ed il comando deve essere su un’unica riga.

Figura 1: Il client stand-alone accede direttamente al Session Bean
Figura 1: Il client stand-alone accede direttamente al Session Bean

Servlet

Sviluppando il client come applicazione stand-alone bisogna distribuire il bytecode del client ed il jar su tutte le macchine degli utenti.

Tali vincoli possono essere rimossi sviluppando una Servlet il cui compito è di comunicare con l’EJB diventando lei stessa un EJB client.

In questo modo non si dovrà distribuire nessun software sulla macchina client, ponendo come unico vincolo la disponibilità di un browser Internet che comunichi con il web server.

La Servlet permette quindi al client web browser di accedere indirettamente all’EJB.

Il middletier dell’applicazione risulta essere costituito da due livelli:

  • livello di presentazione, costituito dalla Servlet, che gestisce l’interfaccia utente acquisendo i dati e visualizzando il risultato;
  • livello di business, che fornisce il servizio di concatenazione, implementato dall’EJB.
Figura 2: La Servlet come client intermedio dell’EJB
Figura 2: La Servlet come client intermedio dell’EJB

Per invocare la Servlet si crea una pagina HTML che, mediante una form, inizializza i parametri da inviare con una GET al web server.

Concat.html

<html>
<head>
  <title>Concat</title>
</head>
<body>
  <p>
  <form method=get action="ConcatServletAlias">
    Inserisci stringa :
    <input type=text name="firstString">
    <p>
    Inserisci stringa :
    <input type=text name="secondString">
    <p>
    <input type="submit" value="Inoltra">
  </form>
  <hr>
</body>
</html>

Concentrandoci sul codice della ConcatServlet si vede come all’interno del metodo init essa svolga le funzioni di EJB client ottenendo un reference alla remote interface che inizializza la proprietà remoteConcat.

All’arrivo della richiesta la servlet legge i parametri firstString e secondString ed invoca il metodo di business String concat(String, String). Il risultato della concatenazione viene formattato in HTML nel metodo generatePage.

ConcatServlet

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.rmi.PortableRemoteObject;
import javax.naming.InitialContext;
import javax.naming.Context;
import Concat;
import ConcatHome;

/**
 * ConcatServlet: Servlet EJB client
 */
public class ConcatServlet extends HttpServlet {
  private Concat remoteConcat = null;

  public void init() throws ServletException {
    addItem("ConcatServlet.init : ...");
    try {
      Context initial = new InitialContext();
      // Localizzazione della Home interface mediante JNDI
      Object objRef = initial.lookup("MyService");
      // utilizzo la classe PortableRemoteObject per effettuare l'opportuno CAST
      ConcatHome home = (ConcatHome) PortableRemoteObject.narrow(
          objRef, ConcatHome.class);
      addItem("home = " + home.getClass().getName());
      // creo l'oggetto remoto mediante il metodo create della Home interface
      remoteConcat = home.create();
      addItem("remote = " + remoteConcat.getClass().getName());
    } catch (Exception ex) {
      addItem("# Exception ! ConcatServlet.init : " + ex.getMessage());
      ex.printStackTrace();
    }
  }

  public void doGet(HttpServletRequest req, HttpServletResponse res)
      throws ServletException, IOException {
    addItem("ConcatServlet.doGet : ...");
    String firstString = req.getParameter("firstString");
    String secondString = req.getParameter("secondString");
    addItem("firstString[" + firstString + "] - secondString[" + secondString + "]");
    String result = remoteConcat.concat(firstString, secondString);
    res.setContentType("text/html");
    PrintWriter out = res.getWriter();
    generatePage(out, result);
  }

  private void generatePage(PrintWriter out, String result) {
    out.println("<html>");
    out.println("<head>");
    out.println("<title>Concat Servlet</title>");
    out.println("</head>");
    out.println("<body>");
    out.println("<h2><b><center>Concat Servlet</center></b></h2><hr>");
    out.println("<h3><b>Risultato concatenazione : " + result + "</h3></b><hr>");
    out.println("<p>");
    out.println("<form method=get action=\"ConcatServletAlias\">");
    out.println("Inserisci stringa : ");
    out.println("<input type=text name=\"firstString\">");
    out.println("<p>");
    out.println("Inserisci stringa : ");
    out.println("<input type=text name=\"secondString\">");
    out.println("<p>");
    out.println("<input type=submit value=\"Inoltra\">");
    out.println("</form>");
    out.println("<hr>");
    out.println("</body>");
    out.println("</html>");
  }

  private void addItem(String s) {
    s = new java.util.Date().toString() + "-" + s;
    System.out.println(s);
  }
}

Installazione della Servlet

Dopo aver compilato la Servlet

javac -classpath .;%J2EE_HOME%\lib\j2ee.jar;ConcatAppClient.jar ConcatServlet.java

si può procedere ad installarla nell’Application Server.

Avviato il deploytool, ad esempio d:\\j2sdkee1.2\\bin\\deploytool, si seleziona l’applicazione ConcatApp e dal menu File si sceglie New Web Component.

Figura 3: Creazione di un nuovo Web Component nel deploytool
Figura 3: Creazione di un nuovo Web Component nel deploytool

Il Web Component non è altro che un insieme di risorse Web, HTML, JSP, bean e servlet, che viene installato sull’Application Server con un file di estensione WAR, cioè un Web Archive. Le risorse contenute nel Web Component vengono gestite all’interno del Web Container del J2EE Server così come gli EJB vengono gestiti da un EJB Container.

Figura 4: Struttura del Web Component
Figura 4: Struttura del Web Component

Nella prima finestra del wizard si deve inserire il nome che si vuole assegnare al componente Web, ad esempio ConcatServletWAR, nel campo DISPLAY NAME e premere il tasto ADD per aggiungergli i file.

Si inserisce come prima risorsa, mediante il bottone ADD, il file Concat.html e si seleziona NEXT.

Figura 5: Inserimento della pagina HTML nel componente
Figura 5: Inserimento della pagina HTML nel componente

Successivamente si inserisce il ConcatServlet.class e si preme FINISH.

Figura 6: Inserimento della Servlet nel componente
Figura 6: Inserimento della Servlet nel componente

Il Web Component di nome ConcatWAR risulta essere quindi formato dal ConcatServlet.class e dal file Concat.html.

Figura 7: Risorse finali contenute nel componente
Figura 7: Risorse finali contenute nel componente

Alla successiva finestra si esplicita il tipo di componente Web che si sta creando, che nel nostro caso è una Servlet.

Figura 8: Selezione del tipo di componente
Figura 8: Selezione del tipo di componente

Bisogna poi assegnare un nome al componente Web, per esempio TheConcatServlet.

Figura 9: Assegnazione del nome alla Servlet
Figura 9: Assegnazione del nome alla Servlet

La successiva videata permette, tramite il bottone ADD, di assegnare un alias URL alla Servlet, ad esempio ConcatServletAlias. Si noti che questo è l’alias referenziato nella pagina Concat.html.

Figura 10: Associazione dell'alias URL alla Servlet
Figura 10: Associazione dell'alias URL alla Servlet

Selezionando FINISH si vede che all’applicazione Concat è stato aggiunto il Web Component ConcatWAR. Prima di procedere al deploy si deve assegnare al ConcatWAR il nome JNDI, che nell’esempio è ConcatServletContextRoot.

Figura 11: Impostazione del context root del componente
Figura 11: Impostazione del context root del componente

A questo punto si può procedere al deploy dell’applicazione senza richiedere di generare il file jar per il client.

Figura 12: Deploy dell'applicazione con il componente web
Figura 12: Deploy dell'applicazione con il componente web

Mediante NEXT si ha il riepilogo dei JNDI names sia per il Session Stateless Bean, MyService, sia per la Servlet, ConcatServletContextRoot. Schiacciando FINISH compare la finestra relativa al deploy.

Figura 13: Riepilogo finale del deploy
Figura 13: Riepilogo finale del deploy

È possibile accedere alla pagina Concat.html mediante l’URL:

http://<SERVER>:8000/ConcatServletContextRoot/Concat.html

e dopo avere inserito le due stringhe da concatenare viene invocata la ConcatServlet.

La figura 14 mostra il risultato che la Servlet fornisce in seguito alla richiesta di concatenazione tra le stringhe Hello e EJB World !.

Figura 14: Risultato della concatenazione eseguita dalla Servlet
Figura 14: Risultato della concatenazione eseguita dalla Servlet

Java Server Pages

Le Servlet presentano la scomodità di avere cablato nel codice la struttura della pagina HTML da visualizzare all’utente. In questo modo se si ha la necessità di modificare la parte HTML bisogna necessariamente modificare il codice Java e ricompilare il tutto.

La naturale evoluzione delle Servlet sono le pagine JSP, che permettono una netta distinzione tra codice HTML e codice Java. In un Web Component si può inserire anche una pagina JSP e di conseguenza sfruttarne i vantaggi intrinseci.

Nella versione JSP 1.1 non è possibile invocare un EJB direttamente da una pagina JSP mediante l’utilizzo delle action standard JSP, ma bisogna utilizzare o script o la mediazione di un worker bean. Vediamo come invocare il nostro EJB da pagina JSP mediante un bean che fondamentalmente effettua le funzioni di proxy verso l’EJB.

La pagina Concat.jsp utilizza un bean di classe ConcatProxyBean ottenendo la concatenazione delle proprietà firstString e secondString mediante l’invocazione del metodo processRequest.

Figura 15: Una JSP che usa un bean proxy per invocare l'EJB
Figura 15: Una JSP che usa un bean proxy per invocare l'EJB

Concat.jsp

<html>
<jsp:useBean id="proxyBean" scope="session" class="ConcatProxyBean" />
<jsp:setProperty name="proxyBean" property="*" />
<%! String result; %>
<% result = proxyBean.processRequest(); %>
<html>
<head>
  <title>Concat JSP</title>
</head>
<h1><b><center>Concat JSP</center></b></h1>
<hr>
<form method=POST action=Concat.jsp>
  <p>Inserisci stringa : <input type=text name="firstString" size="8"
      value="<jsp:getProperty name="proxyBean" property="firstString" />"></p>
  <p>Inserisci stringa : <input type=text name="secondString" size="8"
      value="<jsp:getProperty name="proxyBean" property="secondString" />"></p>
  <p><input type=submit name="submit" value="Submit"></p>
</form>
<hr>
<h3><b>Risultato concatenazione : <%= result %></b></h3>
<hr>
</body>
</html>

ConcatProxyBean

Il ConcatProxyBean ottiene un reference alla remote interface nel costruttore ed invoca il metodo concat dell’EJB all’interno del metodo processRequest.

import java.util.*;
import java.io.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;

public class ConcatProxyBean {
  private String firstString;
  private String secondString;
  private ConcatHome home = null;

  public ConcatProxyBean() {
    addItem("ConcatProxyBean : costruttore ...");
    try {
      Context ic = new InitialContext();
      Object objref = ic.lookup("MyService");
      home = (ConcatHome) PortableRemoteObject.narrow(objref, ConcatHome.class);
      addItem("home = " + home.getClass().getName());
    } catch (Exception e) {
      addItem("# Exception ! concatHome non localizzata : " + e.getMessage());
      e.printStackTrace();
    }
  }

  public String processRequest() {
    String result = "";
    try {
      if ((this.firstString != null) && (this.secondString != null)) {
        addItem("ConcatProxyBean.processRequest:" + this.firstString + "-" + this.secondString);
        Concat remoteConcat = home.create();
        addItem("remote = " + remoteConcat.getClass().getName());
        result = remoteConcat.concat(firstString, secondString);
        addItem("Result = " + result);
      }
    } catch (Exception e) {
      result = e.toString();
    }
    return result;
  }

  public String getFirstString() { return firstString; }
  public void setFirstString(String value) { this.firstString = value; }
  public String getSecondString() { return secondString; }
  public void setSecondString(String value) { this.secondString = value; }

  private void addItem(String s) {
    s = new java.util.Date().toString() + "-" + s;
    System.out.println(s);
  }
}
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