Per vedere in azione la dependency injection realizziamo una semplice Web Application Java
con una singola servlet che faccia uso del convertitore Ejb. Seguendo le modalità
illustrate nel capitolo precedente, creiamo un progetto di tipo Dynamic Web Project al quale diamo il nome
di ProgettoWeb1. Apriamo le proprietà del progetto Web ed aggiungiamo al Java Build Path il progetto Ejb
per far in modo che il modulo Web veda le classi Ejb.
Passiamo al progetto Enteprise ed seguiamo gli stessi
step visti per il modulo Ejb per aggiungere il progetto Web al modulo Enterprise. Dopo queste operazioni,
all'interno del modulo Web creiamo il package it.html.progetto1.webtest
con la classe servlet SessionBeanTest
:
package it.html.progetto1.webtest;
import java.io.IOException;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import it.html.progetto1.ejb32.ConverterBeanLocal;
@WebServlet("/SessionBeanTest")
public class SessionBeanTest extends HttpServlet {
private static final long serialVersionUID = 1L;
@EJB
private ConverterBeanLocal converterBeanLocal;
public SessionBeanTest() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Conversion test:"+converterBeanLocal.celsiusToFahrenheit(30));
}
}
Come possiamo notare dal codice, con l'annotation javax.ejb.EJB
riusciamo ad avere un riferimento all'interfaccia dell'Ejb
attraverso dependency injection. Con la dependency injection il Container fa per noi tutto il lavoro che vedremo successivamente
con JNDI. Quando realizziamo un session bean utilizzando le interfacce l'annotation @EJB
verrà introdotta nel codice con il riferimento dell'interfaccia desiderato. Se implementiamo invece un session bean senza interfaccia,
come introdotto in Ejb 3.1 dobbiamo specificare la classe del bean:
....
@EJB
private ConverterBean converterBean;
...
Durante la fase di deploy del modulo Ejb da parte di JBoss Wildfly, possiamo notare la stampa di alcune stringhe particolari:
java:global/Progetto1Ear/ProgettoEjb1/ConverterBean!it.html.progetto1.ejb30.ConverterBeanRemote
java:app/ProgettoEjb1/ConverterBean!it.html.progetto1.ejb30.ConverterBeanRemote
java:module/ConverterBean!it.html.progetto1.ejb30.ConverterBeanRemote
java:jboss/exported/Progetto1Ear/ProgettoEjb1/ConverterBean!it.html.progetto1.ejb30.ConverterBeanRemote
java:global/Progetto1Ear/ProgettoEjb1/ConverterBean!it.html.progetto1.ejb30.ConverterBeanLocal
java:app/ProgettoEjb1/ConverterBean!it.html.progetto1.ejb30.ConverterBeanLocal
java:module/ConverterBean!it.html.progetto1.ejb30.ConverterBeanLocal
Queste stringhe rappresentano il nome JNDI con il quale possiamo ottenere il riferimento ad un Ejb, esse
seguono la struttura della sintassi JNDI portabile e si riferiscono al local JNDI di JBoss WildFly. La specifica della piattaforma JEE
definisce i seguenti contesti JNDI:
Contesto | Visibilità |
---|---|
java:module | A livello di modulo. |
java:app | A livello di applicazione. |
java:global | A livello di server. |
Il java:global JNDI namespace è la modalità portabile per recuperare riferimenti ad Ejb all'interno
dei vari EAR installati sul server. La struttura è la seguente:
java:global[/application name]/module name/enterprise bean name[/interface name]
L'application name ed il module name sono il nome del pacchetto EAR e il nome del modulo Ejb
senza le estensioni ear e jar. L'interface name è il nome completo dell'interfaccia (completo di package, es. it.html.progetto1.ejb30.ConverterBeanLocal
)
ed è richiesto soltanto se l'enterprise bean implementa più di un'interfaccia.
Il namespace java:module
è utilizzato per recuperare enterprise bean di tipo local all'interno dello stesso modulo ejb.
java:module/enterprise bean name/[interface name]
Anche in questo caso l'interface name è richiesto soltanto se l'enterprise bean implementa più di un'interfaccia.
Il namespace java:app
è utilizzato per recuperare enterprise bean impacchettati nella stessa applicazione (stesso EAR). Infatti
un file EAR può contenere molti moduli Java EE.
java:app[/module name]/enterprise bean name [/interface name]
Come nei casi precedenti l'interface name è richiesto soltanto se
l'enterprise bean implementa più di un'interfaccia. Vediamo un esempio di lookup modificando la servlet creata
precedentemente. Utilizzeremo lo scope java:app
perché vogliamo recuperare un riferiemento a session bean
da un modulo Web ad un modulo Ejb all'interno della stessa applicazione:
package it.html.progetto1.webtest;
import java.io.IOException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import it.html.progetto1.ejb32.ConverterBeanLocal;
@WebServlet("/SessionBeanTest")
public class SessionBeanTest extends HttpServlet {
private static final long serialVersionUID = 1L;
private ConverterBeanLocal converterBeanLocal;
public SessionBeanTest() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
InitialContext initialContext;
try {
initialContext = new InitialContext();
converterBeanLocal = (ConverterBeanLocal)
initialContext.lookup("java:app/ProgettoEjb1/ConverterBean32!it.html.progetto1.ejb32.ConverterBeanLocal");
System.out.println("Conversion test:"+converterBeanLocal.celsiusToFahrenheit(30));
} catch (NamingException e) {
e.printStackTrace();
}
}
}