MokaByte 55 - 7mbre  2001
Foto dell'autore non disponibile
di
Stefano
Rossini
JSP come client di EJB
 
Nell'articolo [CEJB] sono state presentate varie tipologie di client EJB al fine di utilizzare l'EJB session stateless Concat [SEJB].
In particolare sono stati portati come esempi un’applicazione client stand-alone, un Servlet ed una pagina JSP utilizzante una Java Bean.
In [CEJB] si è ricordato che nella versione JSP1.1 non è possibile invocare un’Ejb direttamente da una pagina JSP mediante l'utilizzo delle action standard JSP ma si deve  utilizzare  scriptlet o la mediazione di un worker Java bean.
L'invocazione mediante scriptlet avviene includendo il codice Java tra i tag <% ed %> come riportato in seguito :

<%@ page import="java.util.*,javax.naming.*,javax.rmi.*,Concat,ConcatHome"%>

<html>
<head>
<title>EJB Scriptlet test</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>

<h2 align="center">Prova EJB</h2>

<%
 try {

   Context ctx = new InitialContext();
   Object objRef = ctx.lookup("MyService");
   ConcatHome home = (ConcatHome)PortableRemoteObject.narrow(
                               objRef,ConcatHome.class); 
   Concat remoteConcat = home.create();
   String res = remoteConcat.concat("Hello", " EJB World !");
   out.println("<hr><h3>Result : " + res + "</h3><hr>");
 } 
 catch (Exception ex) {
    out.println("<hr><h3> !!! Exception : " + ex.getMessage());
    out.println("</h3><hr>");
    ex.printStackTrace();
 }
%>

</body>
</html>

L'utilizzo dello scriptlet  è però  sconsigliato perché non permette una netta divisione tra la logica di programmazione e quella di visualizzazione ed inoltre non favorisce il riutilizzo del codice.
E' possibile tuttavia creare custom tag mediante i quali si possono definire nuove action da usare all'interno delle pagine JSP estendendo il set dei tag di default dei tag JSP.
Scopo dell'articolo è realizzare un tag proprietario al fine di localizzare la home interface di un EJB per ridurre l'utilizzo di scriptlet all'interno della pagina JSP.
 
 
 

Cos’è un custom tag ?
Il tag extension è un meccanismo, introdotto nella versione JSP 1.1, che permette di definire dei tag personalizzati estendendo il set dei tag di default JSP.
In questo modo è possibile costruire tag i cui compiti sono decisi dal programmatore in base alle sue specifiche esigenze: questi tag personalizzati prendono il nome di custom tag.
Un insieme di custom tag viene chiamato tag library.
 
 
 

Il custom tag  myEjbTag
Iniziamo con il definire le caratteristiche del custom tag myEjbTag che si intende costruire. 
Al fine di localizzare la home interface dell'EJB, il tag myEjbTag richiede la presenza di tre attributi : jndiName, homeInterface e homeVar che identificano rispettivamente il nome JNDI dell’EJB, il nome della Home interface  ed il nome del reference dell'interfaccia home.
Una volta specificati i valori degli attributi è possibile, mediante scriptlet ,reperire un riferimento alla Remote  interface di un’EJB mediante l'invocazione del metodo create sulla variabile homeVar. Questa operazione viene effettuata all’interno del tag e prende il nome di body (corpo del tag).In questo modo si può procedere ad invocare direttamente i metodi di business dell’EJB direttamente da scriplet JSP utilizzando la variabile concatRemote.
Il risultato che si ottiene è una pagina JSP che utilizza elementi di script in congiunzione con il custom tag myEjbTag.

<% Concat concatRemote = null; %>

<myJ2ee:myEjbTag
   jndiName="java:comp/env/ejb/MyConcat" 
   homeInterface="ConcatHome"
   homeVar="concatHome">
   <% concatRemote = concatHome.create(); %>
</myJ2ee:myEjbTag>
<%= concatRemote.concat("Hello EJB World ","from my JSP tag lib!") %> 
 
 
 

Come si definisce un custom tag ?
Si definisce ora il custom tag myEjbTag con i suoi attributi, il body e la gestione dell'interazione con la variabile di script  concatRemote.
Bisogna quindi creare una classe tag handler che gestisca il tag,  una classe di informazione sul contenuto del tag ed un descrittore del tag library (Tag Library Descriptor).
 
 
 

La classe tag handler
La classe tag handler è la classe che permette la gestione del custom tag da parte del JSP container.
Le classi di supporto per l’implementazione dei tag proprietari sono contenute nel package javax.servlet.jsp.tagext.
Per implementare un custom tag si deve definire una classe tag  che implementi o l'interfaccia Tag o BodyTag. Queste interfacce rappresentano il meccanismo di comunicazione con il JSPContainer e sono implementate rispettivamente dalle classi concrete TagSupport e BodyTagSupport(quest'ultima  deriva da TagSupport).
 
 


Figura 1

La scelta dell'utilizzo di una o dell'altra classe/interfaccia dipende dalla tipologia del custom tag che si vuole realizzare (vedere [MJSP] e [JTAG]).
Dato che il tag myEjbtag possiede un body, la sua classe tag handler deve implementare l’interfaccia BodyTag.

Piuttosto che implementare l'interfaccia BodyTag è più comodo ereditare dalla classe BodyTagSupport in modo da non dover implementare tutti i metodi dell'interfaccia ma solamente effettuare l'overiding dei metodi di interesse.
Rispetto alla classe TagSupport, la classe BodyTagSupport aggiunge tre metodi per la gestione del body del tag : setBodyContent, doInitBody e doAfterBody.

Per interagire con il body (<% concatRemote = concatHome.create(); %>) nel nostro caso  basta implementare il metodo doInitBody utilizzando per gli altri metodi le implementazioni di default della classe BodyTagSupport.
Nel metodo doInitBody inseriamo le operazioni tipiche di un client EJB  e cioè la localizzazione ed il narrow della home interface. 

  Object homeRef = ic.lookup(jndiName); 
 homeRef = PortableRemoteObject.narrow(homeRef,
                                Class.forName(homeInterface));

L'oggetto homeRef viene  memorizzato come attributo (avente il nome specificato dalla proprietà homeVar, che nel nostro caso specifico è conconcatHome)  nel contesto della pagina JSP mediante il metodo setAttribute(name, Object)  invocato sulla variabile pageContext.
La variabile pageContext è utilizzabile all’interno della classe tag handler essendo ereditata dalla classe TagSupport con modalità d’accesso protected.

 pageContext.setAttribute(homeVar, homeRef);

In questo modo si rende visibile con scope di pagina la variabile di script concatHome mediante la quale è possibile invocare i metodi create dell’EJB direttamente all’interno del body del myEjbTag.
Per ogni attributo del myEjbTag si deve definire una proprietà in stile Java Bean nella classe tag handler associando un metodo get ed uno set per rendere accessibile la proprietà dal JSP container.

MyEjbTag.java : la classe tag handler del tag myEjbTag

import javax.rmi.PortableRemoteObject;
import javax.naming.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;

public class MyEjbTag extends BodyTagSupport {

   /** Proprietà Tag */
   private String jndiName = null; 
   private String homeVar = null;
   private String homeInterface = null; 

   public MyEjbTag() {
      super();
      addItem("Constructore MyEjbTag : ...");
   }

   public String getJndiName() {
      addItem("MyEjbTag.getJndiName : return " + this.jndiName);
      return this.jndiName;
   }

   public void setJndiName(String jndiName) {
      addItem("MyEjbTag.setJndiName : " + jndiName);
      this.jndiName = jndiName;
   }

   public String getHomeVar() {
      addItem("MyEjbTag.getHomeVar : return " + this.homeVar);
      return this.homeVar;
   }

   public void setHomeVar(String homeVar) {
      addItem("MyEjbTag.setHomeVar : " + homeVar);
      this.homeVar = homeVar;
   }

   public String getHomeInterface() {
      addItem("MyEjbTag.getHomeInterface : return " + 
              this.homeInterface);
      return this.homeInterface;
   }
 

   public void setHomeInterface(String homeInterface) {
      addItem("MyEjbTag.setHomeInterface : " + homeInterface );
      this.homeInterface = homeInterface;
   }

   // doInitBody
   public void doInitBody() throws JspException {
       try {
           addItem("MyEjbTag.doInitBody : ...");
           InitialContext ic = new InitialContext();
           addItem("MyEjbTag.doInitBody : BEFORE lookup 
                   ["+jndiName+"]...");
           Object homeRef = ic.lookup(jndiName); 
           homeRef = PortableRemoteObject.narrow(homeRef,
                               Class.forName(homeInterface));
           addItem("MyEjbTag.doInitBody :"+
                   "setAttribute homeVar["+homeVar+
                   "] homeRef["+homeRef+"]...");
           // Memorizzazione nel Page context 
           // dell’oggetto homeRef con il nome 
           // specificato dalla proprietà homeVar
           pageContext.setAttribute(homeVar, homeRef);
       } 
       catch (NamingException ex) {
           addItem("MyEjbTag.doInitBody : "+
                   "Unable to lookup home["+jndiName+
                   "]: "+ex);

           throw new JspTagException("MyEjbTag.doInitBody"+
                   ": Unable to lookup home["+jndiName+ "] :
                   "+ex);
       }
       catch (ClassNotFoundException ex) {
           addItem("Class ["+homeInterface+
                   "] not found !" + ex);

           throw new JspTagException("Class ["+
                   homeInterface+"] not found !" + ex);
       }
   }

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

La classe tag info
La variabile concatHome è una variabile di scripting disponibile all'interno del body ed è valorizzata nel metodo doInitBody della classe tag handler MyEjbTag. Questa variabile (detta variabile di scripting) deve essere descritta da un'apposita classe detta Tag Extra Info (TEI). Mediante la TEI è possibile oltre che descrivere la variabile di scripting anche effettuare un controllo sulla sua valorizzazione in fase di traduzione da parte del JSP container.
Il motore JSP invoca il metodo getVariableInfo per scoprire la presenza di variabili di scripting associate al tag che sta interpretando, ed il metodo isValid per verificare la validità del valore in fase di compilazione della pagina JSP.
Il metodo getVariableInfo viene invocato dal JSP Container sole se il metodo isValid ritorna true e cioè il valore dell’attributo del custom tag è valido.

MyEjbExtraInfo.java

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.util.Date;

public class MyEjbExtraInfo extends TagExtraInfo {

   public VariableInfo[] getVariableInfo(TagData data){
      return new VariableInfo[]{
                 new VariableInfo(
                (String)data.getAttribute("homeVar"),
                (String)data.getAttribute("homeInterface"),
                 true,
                 VariableInfo.NESTED)
      };
   }

  public boolean isValid(TagData data){
    return true;
  } 
}

La sequenza delle chiamate (life cycle) da parte del JSP container ai metodi della classe MyEjbExtraInfo e MyEjbTag  può essere così schematizzata : 

MyEjbExtraInfo info = new MyEjbExtraInfo();
info.isValid(…);
info.getVariableInfo(…);
MyEjbTag t = new MyEjbTag();
t.setPageContext(...);
t.setParent(...);
t.setJndiName(…);
t.setHomeInterface(…);
t.setHomeVar(…);
t.doStartTag();
t.setBodyContent(...);
t.doInitBody();
t.doAfterBody();
t.doEndTag();
t.release();
 
 

Tag Library Descriptor
Prima di potere utilizzare il tag myEjbtag all’interno di una pagina JSP, bisogna costruire il relativo tag library descriptor (TLD).
Il TLD è un file XML che descrive i custom tag (sintassi,attributi,classi Java correlate, …) di un tag library e viene utilizzato dal JSP container per interpretarli.
Tra  i  tag <taglib> bisogna specificare la versione della taglib <tlibversion>, la versione JSP <jspversion> e l’URI.
Mediante il tag <info> è possibile inserire un testo arbitrario contenente informazioni sulla libreria.
Per ogni tag bisogna dichiarare una sezione (contenuta tra  <tag> e </tag>) per descriverne le proprietà :

  • <name> : nome del custom tag (myEjbTag)
  • <tagClass> : nome della classe Java tag handler (MyEjbTag)
  • <teiClass> :  nome della classe TEI (MyEjbExtraInfo)
  • <bodycontent> : indica il tipo di contenuto del body (nel nostro caso è scriptlet JSP)
  • <info> : descrizione informativa del tag
Per ogni attributo (quindi sia per jndiName, homeInterface che homeVar) attraverso il tag <attribute> bisogna specificare :
  • <name> : nome dell’attributo 
  • <required> indica se l’attributo è obbligatorio 
  • <rtexprvalue> indica se l’attributo può essere valorizzato dinamicamente mediante scriptlet
  • <type> indica il tipo di ritorno dell’espressione JSP (è presente solo in concomitanza del tag <rtexprvalue>)
Ecco il file myejbtaglib.tld

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib
        PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
 "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">

<taglib>
  <tlibversion>1.0</tlibversion>
  <jspversion>1.1</jspversion>
  <uri></uri>
  <info>
 Tag library for EJB support
  </info>

  <tag>
    <name>myEjbTag</name>
    <tagclass>MyEjbTag</tagclass>
    <teiclass>MyEjbExtraInfo</teiclass>
    <bodycontent>JSP</bodycontent>
    <info>
      Tag JSP per lookup di un EJB
    </info>

    <attribute>
      <name>jndiName</name>
      <required>true</required>
      <rtexprvalue>true</rtexprvalue>
      <type>String</type>
    </attribute>
    <attribute>
      <name>homeInterface</name>
      <required>true</required>
    </attribute>
    <attribute>
      <name>homeVar</name>
      <required>true</required>
    </attribute>
  </tag>
</taglib>
 
 

Utilizzo del tag myEjbTag all’interno di una pagina JSP
Dopo avere sviluppato le classi per la gestione del tag ed il TLD, è finalmente possibile inserire il tag myEjbTag nelle pagine JSP.
Per prima cosa bisogna specificare l’identificatore del TLD sotto forma di URI (Universal Resource Identificator), cioè indicare dove il JSP engine deve reperire il file TLD.

<%@ taglib uri="myejbtaglib.tld" prefix="myJ2ee" %>

L’attributo prefix assegna una label al tag permettendo di distinguere eventuali tag anonimi presenti in altre librerie (namespace).

Mediante il tag <myJ2ee:ejb> si provvede ad inizializzare le tre proprietà del custom tag specificando il JNDI name del Session Stateless bean Concat([SEJB]), la sua interfaccia di Home e definendo il nome per la variabile di script.

<myJ2ee:myEjbTag
   jndiName="java:comp/env/ejb/MyConcat" 
   homeInterface="ConcatHome"
   homeVar="concatHome">
   <% concatRemote = concatHome.create(); %>
</myJ2ee:myEjbTag>

Nella pagina JSP si dichiara un reference alla Remote Interface dell’EJB

<% Concat concatRemote = null; %>

si crea l’ EJB concat

<% concatRemote = concatHome.create(); %>

ed infine si invoca il business method concat

<%= concatRemote.concat("Hello EJB World ","from my JSP tag lib!") %> 
 

Il file ConcatWithMyTagLib.jsp

<html>
<%@ taglib uri="myejbtaglib.tld" prefix="myJ2ee" %>

<head>
    <title>Concat JSP</title>
</head>

<h1><b><center>Concat JSP with tag library</center></b></h1>
<hr>

<%
  System.setProperty("java.naming.factory.initial",
                     "com.sun.jndi.cosnaming.CNCtxFactory");
  System.setProperty("java.naming.provider.url",
                     "iiop://localhost:1050");
%>

<% Concat concatRemote = null; %>

<myJ2ee:myEjbTag
   jndiName="java:comp/env/ejb/MyConcat" 
   homeInterface="ConcatHome"
   homeVar="concatHome">
   <% concatRemote = concatHome.create(); %>
</myJ2ee:myEjbTag>

<p>
Result : <b>
  <%= concatRemote.concat("Hello EJB World ",
                          "from my JSP tag lib!")%>
</b> 

</html>
 
 


Figura 2





Installazione della pagina JSP e del tag library myEjbTag
Dopo aver compilato le classi del custom tag : 

javac  -classpath .;%J2EE_HOME%\lib\j2ee.jar MyEjbTag.java
javac  -classpath .;%J2EE_HOME%\lib\j2ee.jar MyEjbExtraInfo.java

si può procedere all’installazione sull’application server, che nel nostro è Tomcat 3.2. 
Come primo si crea una WebApplication (WA) di nome mywebapp  : <tomcat home>/webapps/mywebapp (per dettagli fare riferimento alle specifiche delle Servlet 2.2).
Bisogna quindi posizionare in modo opportuno i file CustomWithMyTagLib.jsp, MyEjbTag.class,MyEjbExtraInfo.class e myejbtaglib.tld.
La pagina JSP la si copia nella root della WA (<tomcat home>/mywebapp), i file .class nella directory classes di WEB-INF (mywebapp/WEB-INF/classes) mentre il file TLD nella WEB-INF stessa.
Inoltre bisogna portare il Jar contenente gli stub dell’EJB concat nella directory lib della WA (mywebapp/WEB-INF/lib) insieme al j2ee.jar.
L’ultimo passo da effettuare riguarda il Deployment Descriptor  (<tomcat home>/mywebapp/WEB-INF/web.xml) della WA all’interno del quale  bisogna referenziare la tag library mediante il tag <taglib> :

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
    "http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">

<web-app>
 <taglib>
  <taglib-uri>
   http://www.mokabyte.it/myejbtaglib
  </taglib-uri>
  <taglib-location>
   /WEB-INF/myejbtaglib.tld
  </taglib-location>
 </taglib> 
</web-app>
 
 


Figura 3






Una volta avviato l’application server Sun RI (<j2ee home>/bin/j2ee) e successivamente tomcat (<tomcat home>/bin/startup>), è possibile accedere alla pagina JSP mediante l’URL :

http://<SERVER>:8080/mywebapp/ConcatWithMyTagLib.jsp

dove al  posto di <SERVER> bisogna inserire il nome o l’indirizzo IP della macchina server (localhost per testare in locale).
In figura 4 viene mostrato il risultato dell’invocazione.


Figura 4





Conclusioni
Con questo articolo si conclude la breve rassegna di esempi di client EJB.
Si è visto come invocare un EJB mediante servlet, scriptlet, proxy bean ed infine custom tag, cercando di mettere in risalto pro e contro di ogni soluzione.
Il custom myejbtag è un semplice esempio di tag per invocare EJB, adatto laddove non si richieda il mantenimento di stato tra un’invocazione della pagina JSP e la successiva.
 

Bibliografia
[CEJB]    S.Rossini - "Client EJB ", Mokabyte N53, Giugno 2001
[SEJB]   S.Rossini - "Session EJB  : un esempio applicativo", Mokabyte N46, Novembre 2000
[MJSP]   P. Aiello -  MokaBook : Java Server Pages
[JTAG]    M.Carli - "Java Server Pages", Computer Programming N.101, Aprile 2001
[TJSP]    JSP Tutorial - http://java.sun.com/products/jsp/tutorial/TagLibrariesTOC.html 
[JEED]   J2SDKEE1.2 documentation : Accessing Enterprise Beans Through JSP Tag Libraries
[JAPI]   J2SDKEE1.2 documentation : API Documentation 
[WDJ]   G. Puliti - "Web dinamico con JSP", Mokabyte N.29, Aprile 1999 

 

Vai alla Home Page di MokaByte
Vai alla prima pagina di questo mese


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