04 SessionBeansEMDB
04 SessionBeansEMDB
© 2008 - CEFRIEL
The present original document was produced by CEFRIEL and the Teacher for the benefit and internal use of this
course, and nobody else may claim any right or paternity on it. No right to use the document for any purpose other than
the Intended purpose and no right to distribute, disclose, release, furnish or disseminate it or a part of it in any way or
form to anyone without the prior express written consent of CEFRIEL and the Teacher.
© copyright Cefriel and the Teacher-Milan-Italy-23/06/2008. All rights reserved in accordance with rule of law and
international agreements.
© 2008 - CEFRIEL
Sommario
SLIDE CONTENUTO
© 2008 - CEFRIEL
Applicazioni EE
Cosa sono?
– Applicazioni distribuite multiutente e multipiattaforma;
– applicazioni three-tiered:
• EIS tier,
• business tier,
• web/client tier;
– strumenti potenti ma computazionalmente onerosi;
onerosi
• da usare solo se servono;
servono
• esigono progettazione “per sopravvivere”.
Cosa offrono?
– Gestione trasparente e ottimale delle risorse:
• distribuzione, balancing, pooling, caching, …
– gestione (trasparente) di problematiche comuni come:
• persistence (JPA), security (JAAS), transaction
(JTA), naming (JNDI), RPC (RMI, JAX-RPC),
timing, distribution, …
– UNO STANDARD,
STANDARD non una tecnologia!
© 2008 - CEFRIEL
Applicazioni EE: quando
Quando si:
– Scalabilità:
• se il sistema potrà crescere a dismisura… richiedendo
adattività delle risorse sfruttate:
– numero di server, cluster, componenti parallele, componenti distribuite, …
– Distribuzione sicura:
• se il sistema richiede transazioni e sicurezza distribuiti:
– ad esempio un servizio di trading on-line:
» con più filiali;
» che sfrutta servizi esterni per il pagamento, ad esempio server di
pagamento on-line via carta di credito.
Quando no:
– Applicazione web:
• non strumento per applicazioni web (li supportano);
• usare invece Servlet e JSP.
– Mancata distribuzione:
• tutto è gestibile localmente;
• Inutile, essendo lo scopo;
• oneroso, esistendo comunque l’overhead.
© 2008 - CEFRIEL
Applicazioni EE: risorse e moduli
Applicazione (ear): risorsa
– insieme di moduli EE (ejb-jar): EEApp
risorsa
• EJB:
– stateless; risorsa
– stateful;
• MDB; MDB
– applicazioni web (war):
• servlet, JSP, JSF, …;
EJB
Clients: stateless
– WebApps (interne o esterne);
– Applicazioni Java (o altro):
• in grado di usufruire dei servizi; EJB
stateful
• conformi agli standard.
web
Localizzazione:
– distribuzione trasparente dei bean:
• DOVE sono in esecuzione i beans;
• QUALI bean rispondono; web
• QUANTI bean sono presenti; Client
– distribuzione trasparente delle risorse:
• DOVE, QUALI e QUANTE Client
© 2008 - CEFRIEL
Applicazioni EE: mettere assieme i pezzi
Application
Moduli:
server
– jar (condivisi) per la persistenza;
Moduli
• ejb-jar.xml, … Deploy:
persistence, ejb
– war con servlet, JSP, JSF, … war
Applicazioni: JavaBeans
(internamente); Applicazioni
Librerie in
Tipo e parametri
© 2008 - CEFRIEL
Applicazioni EE: il deploy
Deploy di un’applicazione =
– mettere in opera l’applicazione:
• le risorse che usa vengono linkate/create;
• le classi vengono rese disponibili;
• EJB istanziati/distribuiti/“cacheati”/“poolati”;
• database creati/preparati per l’ORM;
• JNDI ENC popolato;
Application server
• …
– utilizzo di metadati: risorsa
• annotazioni su classi o metodi; risorsa
Applicazione
• descrittori di deploy; risorsa
Modalità (in GlassFish v2): risorsa
– tramite Admin Console:
• applicazione web di amministrazione dell’AP;
– tramite asadmin;
• comando di amministrazione dell’AS;
– tramite la directory di autodeploy:
• una directory monitorata dall’AS per il deploy di nuovi archivi.
© 2008 - CEFRIEL
SJSAS 9.1: GlassFish v2
Installazione:
– a pacchetti:
• JDK J2SE 1.5>
• SDK J2EE
• Opzionali:
– NetBeans, NetBeans enterprise pack;
– Javadoc, blueprints, SJSAS docs and guides;
– all in one:
• J2SE, J2EE, NetBeans+pacchetti, blueprints, doc,
ecc ecc.
Profili di esecuzione:
– developer (predefinito):
• una istanza, no clusters, varie restrizioni;
– cluster (da Admin Console):
• possibilità di creazione ed inserimento in clusters;
– enterprise (scaricando plugins aggiuntivi):
• Svariate funzionalità aggiunte per la distribuibilità.
© 2008 - CEFRIEL
Stateless EJB: scopo
Fornire servizi:
– sicuri, efficienti, distribuiti, con tansazioni;
– senza stato, auto-contenuti in un metodo;
– remoti o locali, eventualmente web (SOAP);
Efficienza:
– pooling di istanze multiple, in numero adattivo;
Remoti/distribuiti:
– chiamate tramite RMI/JAX-RPC;
Sicuri e con transazioni:
– JAAS e JTA trasparenti (gestite dal container);
Interfacce:
– Locali, remote, endpoint.
© 2008 - CEFRIEL
Stateless EJB: caching e pooling
Il container:
– istanzia un certo numero di beans;
– li cacha in attesa di richieste; Container
– li utilizza per le richieste;
– adatta la dimensione del pool; EJB pool
Lo sviluppatore/amministratore: bean bean bean
– definisce i parametri; bean bean bean
– li utilizza da altri EJB o da client;
– hooka cambiamenti di stato bean
Bean
object
(creato/distrutto);
Strumenti:
Enterprise Bean come
– risorse locali o remote; estensione del client…
– parametri: aggiornabile senza
• del bean; intaccarne alcunché.
• delle richieste;
– attributi di istanza:
• senza poter contare
sull’assegnamento bean/client; Client
– NIENTE STATO CONVERSAZIONALE!
© 2008 - CEFRIEL
Stateless EJB: interfacce
Dichiarate come:
– normali interfacce Java;
– contrassegnate da @Loca o @Remote;
– possibile costruirne una gerarchia.
package com.gab.tests.j2ee.contacts.usersmanager; package com.gab.tests.j2ee.contacts.util;
import javax.ejb.EJBException; public interface BeanTraker {
import java.util.Collection;
public int getAccessNumber(); }
import com.gab.tests.j2ee.contacts.util.*;
import com.gab.tests.j2ee.contacts.entities.*; package com.gab.tests.j2ee.contacts.usersmanager;
public interface UsersManagerInterface import javax.ejb.Local;
extends BeanTraker { @Local public interface UsersManagerLocal
public AppUser registerNewUser(AppUser u) extends UsersManagerInterface {}
throws EJBException;
package com.gab.tests.j2ee.contacts.usersmanager;
public Collection<AppUser> getUsers()
import javax.ejb.Remote;
throws EJBException;
@Remote public interface UsersManagerRemote
public void removeUser(int UID)
throws EJBException; } extends UsersManagerInterface {}
© 2008 - CEFRIEL
Stateless EJB: injection di risorse
Risorse create esternamente:
– tramite Admin console, asadmin, …
Risorse accessibili tramite naming/directory:
– JNDI: nomi logici a risorse fisiche;
– JNDI ENC: lookup esplicito o implicito con injection.
© 2008 - CEFRIEL
JNDI e JNDI ENC: due parole in più
JNDI dell’AS: JNDI
Come ci si accede?
– esempio: Globali nell’AS
(e oltre)
© 2008 - CEFRIEL
Stateless EJB: deploy
ejb-jar.xml
– non utilizzato, annotazioni al suo posto;
– utilizzabile come alternativa… overrides.
sun-ejb-jar.xml
– specifico di configurazione di SJSAS.
persistence.xml
– persistenza… QUASI come già visto.
@PersistenceContext(unitName="contactsPU",type=PersistenceContextType.TRANSACTION)
private EntityManager em;
Transazioni separate per ogni metodo
@PersistenceContext(unitName="contactsPU",type=PersistenceContextType.EXTENDED)
private EntityManager em;
Transazione estesa a tutta la conversazione
© 2008 - CEFRIEL
Stateful EJB: sviluppo
// Attributi locali conversazionali:
AppUser user = null;
Contact contact = null;
Collection<Phone> phones = new Vector<Phone>();
Collection<WebAddress> webs = new Vector<WebAddress>();
// Attributi locali transienti:
transient int accessNumber = 0;
// Definizione dell'utente che conosce il contatto:
public AppUser setUser(int uid) throws InconsistentStateException {
user = em.find(AppUser.class,uid);
if (user==null) throw new InconsistentStateException("User cannot be found!");
return user; }
…
public void saveContact() throws InconsistentStateException {
user.addContact(contact); // Assegnamento del contatto all'utente e persist sull'entity manager:
em.merge(user); // Non serve se si usa EXTENDED in @PersistenceContext:
}
coda
può ricevere messaggi inviati ad
essa (consumer);
– ogni “inviatore di messaggi”
(producer) invia messaggi ad una
precisa destinazione (coda); consumer consumer consumer
– un messaggio inviato arriva ad uno
ed un solo consumer.
Pub/sub: producer
– ogni destinazione è dichiarata
come topic; topic
– ogni producer invia a un topic;
– ogni consumer si iscrive ai topic di
coda
coda
coda
suo interesse (quanti vuole);
– ogni consumer iscritto al topic del
messaggio ne riceve una copia.
consumer consumer consumer
© 2008 - CEFRIEL
JMS: code (P2P)
Caratteristiche:
– container può garantire la consegna;
– container può garantire la non replicazione;
– un solo consumer riceve il messaggio:
• utile per svolgere azioni non idempotenti.
Quando:
– quando i messaggi sono azioni;
– quando è importante che l’azione avvenga;
– quando l’azione deve avvenire una sola volta.
Problemi:
– gestione pending requests;
– oneroso e scomodo se:
• più consumer devono ricevere il messaggio;
• replicazione di destinazioni e invii (pacchetti).
© 2008 - CEFRIEL
JMS: topics (pub/sub)
Caratteristiche:
– consumer può collezionare una-tantum;
• messagge storing condiviso;
– tutti i consumer possono ricevere il messaggio:
• utile per diffusione di informazioni:
– auditing, logging, publishing.
Quando:
– quando i messaggi sono informazioni:
– quando non è un problema perdere messaggi;
– quando non è richiesta l’esecuzione singola.
Problemi:
– gestione message storing;
– oneroso e scomodo se:
• si vuole inviare un messaggio a un solo consumer;
• replicazione topics fittizi.
© 2008 - CEFRIEL
JMS: injection
ConnectionFactory:
– permette di generare connessioni a JMS;
– da creare tramite Admin Console (o asadmin, …);
– ottenibile tramite JNDI:
@Resource(mappedName="jms/ActivityFactory")
private ConnectionFactory factory;
Destinazioni:
– rappresenta la coda di destinazione…
– …oppure il topic di destinazione;
– da creare tramite Admin Console (o asadmin, …);
– ottenibile tramite JNDI:
@Resource(mappedName="jms/Activity")
private Queue loggerQueue;
– oppure:
@Resource(mappedName="jms/Activity")
private Topic loggerTopic;
© 2008 - CEFRIEL
JMS: inviare messaggi
Connessione con JMS;
sessione di comunicazione con JMS;
creazione del messaggio;
producer verso uno specifico topic (o coda);
invio messaggio (o messaggi);
fine conversazione con JMS.
Connection connection = factory.createConnection();
Session session = connection.createSession(true,0);
TextMessage message = session.createTextMessage(
"[Access "+accessNumber+"] "+msg);
MessageProducer producer = session.createProducer(loggerTopic);
producer.send(message);
connection.close();
© 2008 - CEFRIEL
MDB: scopo, caching e pooling
Scopo:
– eseguire azioni…
• …in sicurezza, con transazioni, ecc ecc…
• …come per gli stateless EJB;
– niente return/conferma;
– esecuzione asincrona.
Caching e pooling:
– come per stateless EJB;
– code di messaggi:
• sia per P2P che per pub/sub;
– maggiore efficienza lato client:
• niente chiamate bloccanti;
– efficiente lato server:
• come stateless EJB.
© 2008 - CEFRIEL
MDB: realizzazione
@MessageDriven(mappedName = "jms/Activity", activationConfig = {
@ActivationConfigProperty( propertyName = "acknowledgeMode",
propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty( propertyName = "destinationType",
propertyValue = "javax.jms.Topic"),
@ActivationConfigProperty( propertyName = "subscriptionDurability",
propertyValue = "Durable"),
@ActivationConfigProperty( propertyName = "clientId",
propertyValue = "Activity"),
@ActivationConfigProperty( propertyName = "subscriptionName",
propertyValue = "Activity") })
public class Activity implements MessageListener {
@PersistenceContext(unitName="loggerPU")
private EntityManager em;
public void onMessage(Message message) {
try {
LogInfo info = new LogInfo(((TextMessage)message).getText());
em.persist(info); }
catch (Exception e) {throw new EJBException(e);} } }
© 2008 - CEFRIEL
Pausa riflessiva: i class loaders
Gerarchia di delegazione…
– …non di ereditarietà;
– eccezione: web class loader;
universi dei class loader;
– application;
– modules;
librerie condivise:
– library-directory in
application.xml…
– …o dipende dall’AS;
• in GlassFish v2:
– <domain>/lib/classes/
– <domain>/lib/<jars>
© 2008 - CEFRIEL
Pausa riflessiva: i class loaders
Usiamoli:
– assemblando applicazioni coese:
• ejb, persistence, mdb, client, web, ecc.;
– non serve includere classi esterne in ogni modulo:
• ad esempio gli Entity beans;
• niente replicazione del codice eseguibile:
– problemi di versioning;
– problemi di dimensione;
Se si usano moduli separati?
– gli universi sono separati;
– solo a livello di dominio è possibile condividere classi:
• <domain>/lib/…
• classpath, classpath-prefix o classpath-suffix;
– di solito:
• replicazione di bytecode (solo il necessario).
© 2008 - CEFRIEL
I context
Scopo:
– fornire informazioni riguardo al Container EJB
contesto di esecuzione dell’EJB:
SessionContext
• JNDI ENC;
• JAAS: Session bean
– Principal (utente); context
– ruolo del Principal;
• transazione attuale;
• riferimenti: «interfaccia»
– interfaccia self (@Local o @Remote); EJBContext
+lookup()
– interfaccia utilizzata dal client; +getCallerPrincipal()
– il tutto in maniera semplice e +isCallerInRole()
+getUserTransaction()
trasparente: +getRollbackOnly ()
+setRollbackOnly ()
• usando l’injection; «extends»
© 2008 - CEFRIEL
I context
Reperiti tramite injection:
– @Resource SessionContext context;
@Resource MessageDrivenContext context;
@Resource EJBContext context;
contengono metodi deprecati:
– generano a runtime una eccezione;
• i metodi mostrati nella slide precedente sono utilizzabili;
permettono di accedere all’EJB ENC:
– esempio di accesso a parametro:
• int maxCalls = context.lookup(“MCalls”);
– dichiarazione:
<ejb-jar>
<enterprise-beans>
<session>
@Resource(name="MCalls") int maxCalls; <ejb-name>UsersManagerBean</ejb-name>
@Resource SessionContext context; <env-entry>
<env-entry-name>MCalls</env-entry-name>
message = session.createTextMessage( <env-entry-type>Integer</env-entry-type>
"Max calls reset! MCalls=" + <env-entry-value>3</env-entry-value>
context.lookup("MCalls")); </env-entry>
</session>
</enterprise-beans>
</ejb-jar>
© 2008 - CEFRIEL
Ciclo di vita
Non esiste
Ciclo di vita di un:
Class.newInstance()
@PreDestroy injections • Stateless Session Bean
@PostConstruct
Method • Message Driven Bean
ready pool
call
Non esiste
timeout
timeout Ciclo di vita di un
Class.newInstance()
Stateful Session Bean
injections
@PostConstruct
@PreDestroy
@PrePassivate
Passive
Method
ready pool
@PostActivate
call
© 2008 - CEFRIEL
Ciclo di vita: rispondere agli eventi
Come:
– annotando dei metodi all’interno del bean:
– un metodo solo per evento;
– nessun parametro, restituito “void”;
– pubblico e di istanza;
utilità:
– inizializzazione e rilascio di risorse;
– audit e monitoring;
– risparmio di spazio occupato nello stato passivato:
• compressione;
• eliminazione di dati facilmente reperibili;
•…
@PostConstruct // EJB creato:
public void inizializza() {
// Posso già utilizzare tutte le features:
logInfo("UsersManagerBean inizializzato",0); }
© 2008 - CEFRIEL
Interceptors: cosa e perché?
Intercettazione:
– di chiamate a metodi di EJB;
– sullo stesso stack call;
– nella stessa transazione/contesto/…;
– anche degli stessi eventi di lifecycle;
Applicati a cosa:
– singoli metodi;
– classi intere;
– tutti gli EJB (da descrittore di deploy con wildcards);
Perché?
– per fare auditing/logging/profiling;
– per modificare l’esecuzione;
• es.: controllo eccezioni;
– per inventare nuove annotazioni (es.: injection di nuovi tipi);
– a fantasia dello sviluppatore!
© 2008 - CEFRIEL
Interceptors: dichiarazione
Una classe come tante…
– … ma con un metodo annotato @AroundInvoke:
• @AroundInvoke
public Object <nome>(
InvocationContext invocation) {…}
– in cui si accede alle info. di chiamata dell’EJB:
• invocation.getTarget()
invocation.getMethod()
invocation.getParameters()
invocation.getContextData()
– in cui si esegue esplicitamente il metodo dell’EJB:
• return invocation.proceed();
• se si vuole;
• quante volte si vuole;
– annotando i metodi di risposta agli eventi di lifecycle:
• @<evento>
public void <nome>(
InvocationContext invocation) {…}
Si può usufruire di:
– injection, transazioni, persistence, …
– …tutto ciò che si può usare nell’EJB.
© 2008 - CEFRIEL
Interceptors: applicazione
Tramite annotazione:
– @Interceptors({sequenza ordinata classi})
– su classe EJB;
– su singolo metodo;
Tramite deploy descriptor:
– bean intero:
• <ejb-jar>
<assembly-descriptor>
<interceptor-
interceptor-binding>
binding>
<ejb- name>ejbName</ejb
ejb-name> </ejb-
ejb-name>
name>
<interceptor- class>interClassName</interceptor
interceptor-class> </interceptor-
interceptor-class>
class>
</interceptor
</interceptor-
interceptor-binding>
binding>
</assembly-descriptor>
</ejb-jar>
– singolo metodo:
• …
<interceptor-class>interClassName</interceptor-class>
<method- name>methodName</method
method-name> </method-
method-name>
name>
<method-
method-params>
params>
<method- param>paramType</method
method-param> </method-
method-param>
param>…
</method
</method-
method-params>
params>
– wildcard:
• …
<interceptor-binding>
<ejb-name>**</ejb-name>
<interceptor-class>interClassName</interceptor-class>
</interceptor-binding>
© 2008 - CEFRIEL
Interceptors: la catena
Gli interceptors vengono organizzati:
– in una struttura dati a catena;
– ogni interceptor usa invocation.proceed():
• per chiamare l’elemento successivo;
• potrebbe essere:
– un altro interceptor;
– il metodo del bean;
Container EJB
Chiamata
esterna interceptor
interceptor
stub
interceptor EJB
metodo
proceed proceed proceed
© 2008 - CEFRIEL
Utilizzo interceptors: auditing
…
@AroundInvoke public Object salvaInfoMetodo(
InvocationContext invocation) throws Exception {
String msg = ""; // Message with infos:
msg += "Class:" + invocation.getTarget().getClass().getName() + "<br/>";
© 2008 - CEFRIEL
Utilizzo interceptors: eccezioni
@AroundInvoke public Object salvaInfoMetodo(
InvocationContext invocation)
throws Exception {
// Trying:
int tryes = 1;
boolean done = false;
Object res = null;
// The tryals:
while (!done && tryes<=3) {
try {
logInfo(invocation.getTarget().getClass().getName() + " -> " +
invocation.getMethod().getName() +
": try number " + tryes,0);
res = invocation.proceed();
done = true;
}
catch(Exception e) {tryes++;}
}
// Returning:
return res;
}
© 2008 - CEFRIEL
Utilizzo interceptors: nuove annotazioni
import java.lang.annotation.*;
import java.lang.reflect.*;
import javax.interceptor.*; @Target(ElementType.FIELD)
import javax.ejb.*; @Retention(RetentionPolicy.RUNTIME)
import javax.naming.*; public @interface JndiInject {
import javax.annotation.*;
String value();
public class JndiInjector { }
@PostConstruct public void inietta(InvocationContext invocation) {
Object target = invocation.getTarget();
Field[] fields = target.getClass().getDeclaredFields();
try { // Locating the @JndiInject annotations:
@JndiInject("jdbc/logger")
InitialContext jndi = new InitialContext();
for (Field field: fields) { DataSource loggerDS;
// Getting the annotation:
JndiInject inject = field.getAnnotation(JndiInject.class);
if (inject!=null) { // Injecting:
Object o = jndi.lookup(inject.value()); @PostConstruct
field.setAccessible(true); public void inizializza() {
field.set(target,o); logInfo(loggerDS!=null?
} "loggerDS correttamente iniettato":
} "problemi nella injection di loggerDS",0);
invocation.proceed(); }
}
catch (Exception e) {throw new EJBException(e);}
}
}
© 2008 - CEFRIEL
Utilizzo interceptors: nuove annotazioni
Dichiarato come interceptor;
Come al solito…
– …manca una caterva di interessanti argomenti…
– …che non avremo il tempo di trattare.
Però non possono mancare:
– scheduling di eventi nel futuro… ripetuti… ecc;
– gestione delle transazioni con JTA;
– gestione della sicurezza con JAAS;
– cenni sulla creazione di web-services.
Questo ed altro ancora…
– …nelle prossime “entusiasmanti” puntate!
© 2008 - CEFRIEL