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
|