Open Source Frameworks

Transcript

Open Source Frameworks
Open Source
Frameworks
Ingegneria del software (parte II)
Andrea Bei
1
Framework
„
Un framework è un insieme di classi e interfacce che cooperano
e generalizzano task e workflow comuni di uno specifico dominio
applicativo (funzionale o tecnologico)
„
Un framework ha le seguenti caratteristiche
…
…
…
Accelera la costruzione di applicazioni del dominio a cui si rivolge
grazie al riuso della soluzione architetturale che ne costituisce la
struttura
I componenti del framework sono riusabili
Utilizzo diffuso di classi astratte e interfacce
„
…
…
Considerate come "template" per le sottoclassi o classi delle specifiche
applicazioni.
Adozione di un modello collaborativo
Inversione del flusso di controllo (IOC)
„
Lo sviluppatore non scrive codice per coordinare le componenti. Lo
sviluppatore implementa le componenti che aderendo alla logica
collaborativa del framework verranno coordinate da quest'ultimo. I
framework assumono il controllo della applicazione e non il contrario! cfr
ad esempio: pattern template method)
2
Framework Open Source
„
Sono stati tra i principali elementi di innovazione nelle architetture web
negli ultimi anni
„
Hanno rappresentato il principale veicolo dell’esperienza “collettiva”
degli sviluppatori in termini di design & architectural pattern, idioms,
best practices
„
Rispetto ai framework in-house (realizzati ad hoc) hanno una
contribuzione di sviluppo più ampia e quindi una maggiore velocità di
convergenza alla soluzione “migliore” per il dominio specifico
„
Aumentano la produttività nello sviluppo
„
Supportano la standardizzazione delle soluzioni
„
Supportano un approccio allo sviluppo architettura-centrico
„
Per uno sviluppatore/architetto Java EE la competenza su framework e
librerie Open Source è fondamentale
3
Web Application Framework
„
Un Web Application Framework è:
…
un sistema software che fornisce struttura e comportamento generalizzati di task e
workflow tipici delle applicazioni web. Es: gestione della navigazione (MVC), gestione
dell’accesso ai dati (DAO), …
„
Il framework di riferimento di IS/LIS (eUniversity) è un Web
Application Framework didattico completo (nel senso che include
tutti i task tipici di una applicazione web dalla presentazione
all’accesso ai dati basandosi dai design pattern fondamentali)
„
Nella “vita reale” per la realizzazione di web application è tipico
l’utilizzo congiunto di diversi framework open source
specializzati in aspetti specifici
„
Ci concentreremo su alcuni di quelli più diffusi
…
…
…
Struts / Struts 2
Spring
Hibernate
4
Struts
„
Struts
…
…
…
„
E’ un insieme di classi ed interfacce che costituiscono l'infrastruttura per costruire web
application Java EE conformi al design pattern Model 2 (MVC)
Il suo ideatore è Craig McClanahan ed è stato donato alla Apache Software Foundation
nel maggio del 2000 da parte di IBM.
E’ uno dei web application framework più diffusi al mondo
Struts 2
…
…
Nonostante il nome, Struts 2 non è una nuova release di Struts ma un framework
completamente nuovo basato su WebWork
Sono state introdotte caratteristiche non presenti in Struts grazie ai feedback di
migliaia di sviluppatori
5
Spring
„
Spring è un “lightweight” container che fornisce una soluzione per sviluppare
applicazioni costruite su POJO. Si basa su:
…
…
…
Inversion of Control/Dependency Injection (configurazione data-driven di POJO)
AOP (Aspect Oriented Programming) (
Diverse componenti di utilità (tra cui una propria implementazione di MVC
„
La prima versione venne scritta da Rod Johnson e rilasciata con la pubblicazione
del proprio libro "Expert One-on-One Java EE Design and Development" (Wrox
Press, Ottobre 2002).
„
Spring è stato largamente riconosciuto all'interno della comunità Java quale
valida alternativa al modello basato su Enterprise JavaBeans (EJB). Rispetto a
quest'ultimo, il framework Spring lascia una maggiore libertà al programmatore
fornendo allo stesso tempo un'ampia e ben documentata gamma di soluzioni
6
semplici adatte alle problematiche più comuni.
Hibernate
„
„
Hibernate (H8) è un middleware ORM (Object-relational mapping) open source.
Consente la rappresentazione e la gestione su database relazionale di un
sistema di oggetti Java.
E’ stato originariamente sviluppato da un team internazionale di programmatori
volontari coordinati da Gavin King; in seguito il progetto è stato proseguito sotto
l'egida di JBoss, che ne ha curato la standardizzazione rispetto alle specifiche
Java EE.
7
Mapping dei FW OS con eUniversity
Struts (2)
Hibernate
Spring
8
Struts – class diagram
9
Struts – componenti principali
„
Struts-config.xml fornisce alla ActionServlet, in base ai
parametri della URL
…
…
„
„
La Action da invocare
La pagina JSP a cui inoltrare la richiesta
ActionServlet: il controller di Model 2
Action: il Model di Model 2 (Classe base per le classi “action” )
…
Le classi action sono responsabili di
„
„
„
Interfacciarsi con il layer sottostante (es: EJB, DAO, …)
Recuperare i dati da presentare alla View e inserirli in sessione
JSP: la View di Model 2
…
Le pagine JSP sono responsabili di
„
„
Recuperare i dati da visualizzare dalla sessione
Visualizzare i dati
10
Struts- esempio di struts-config
<struts-config>
<form-beans>
<form-bean name=”projectForm” type=”it.uniroma2.app.form.ProjectListForm”/>
</form-beans>
<action-mappings>
<action path=”/tasklist” type=” it.uniroma2.app.action.ProduceTaskListAction”
name=”projectForm” scope=”request” validate=”true” input=”/jsp/Project.jsp”>
<forward name=”success” path=”/jsp/TaskList.jsp”/>
<forward name=”failure” path=”/jsp/ServerErrors.jsp”/>
</action>
</action-mappings>
</struts-config>
11
Bibliografia
„
Programming Jakarta Struts - Chuck Cavaness
12
Spring - Caratteristiche
„
Spring è un lightweight container framework che supporta tecniche di
IoC (inversion of control) e AoP (aspect-oriented programming)
„
Lightweight (“leggero”)
“leggero” per dimensione e overhead di elaborazione. (file JAR circa 1MB)
„
Inversion of control
„
„
„
„
Permette di sostenere “low coupling” (basso accoppiamento).
Gli oggetti ricevono passivamente dall’esterno le loro dipendenze (es: il riferimento
ad altri oggetti) , invece di crearle (new di oggeti) o cercarle in file esterni (es:
classloading dinamico). Approccio “push” invece di “pull”.
E’ il container che fornisce le dipendenze all’oggetto all’atto della istanziazione di
quest’ultimo (Dependency Iniection)
Aspect-oriented programming
„
Permetta la SoC (separation of concern). Ovvero la separazione di responsabilità tra
business logic e system services (come logging, autenticazione, gestione delle
transazioni)
13
Spring - Caratteristiche
Container
„
Contiene e gestisce il ciclo di vita e la configurazione delle dipendenze degli
oggetti. E’ possibile configurare come ogni singolo bean (POJO) deve essere creato (ad
esempio in modalità “singleton”, pool, classica) e quali sono le sue dipendenze con gli
altri bean.
Framework
„
„
„
Permette di configurare e comporre applicazioni complesse a partire da
componenti più semplici in maniera dichiarativa (XML)
Fornisce funzionalità infrastrutturali riusabili (transaction management,
persistence framework integration, etc.), lasciando al developer solo lo sviluppo
della logica di business
14
Spring Architettura
15
Spring Architettura
„
Core container
Contiene le funzionalità di base del framework. Contiene il BeanFactory, il “cuore” di ogni
applicazione Spring-based, che che consiste in una implementazione del pattern factory che
utilizza la tecnica IoC
„
Modulo Application Context
Contiene il supporto per l’internazionalizzazione (I18N messages), gestione degli
eventi del ciclo di vita della applicazione, meccanismi di validazione, servizi come
come e-mail, JNDI access, EJB integration, scheduling, integrazione con “templating
framework” come Velocity e FreeMarker
„
Modulo AOP
E’ il componente base per lo sviluppo di aspects (le API sono conformi a quelle definite
in AOP Alliance(*) . Permette la meta-programmazione. (è possibile aggiungere annotations
per istruire Spring su dove e quando aggiungere aspetti)
16
Spring Architettura
„
Modulo JDBC e DAO
Aiuta a evitare il codice “boilerplate” proprio di JSBC (connessioni, resultset, …).
Fornisce una astrazione del codice boilerplate e permette di semplificare il codice di
accesso a db. Fornisce un layer di exception relative all’accesso al db “on top” rispetto
a quelle native dei db.
„
Modulo Web Context and Utility
Si basa sul modulo Application Context e lo specializza per applicazioni. Fornisce il
supporto a task web-oriented (es: file upload) e all’integrazione con Jakarta Struts
.
MVC framework
Fornisce un framework Model/View/Controller (MVC) per la costruzione di web
application. Spring’s MVC framework usa IoC per separare la logica di business e la
logica di controllo e collegare in modo dichiarativo i parametri della request ai relativi
oggetti di business (i.e. actions)
„
„
Modulo O/R Mapping
Punto di integrazione per Hibernate, JDO, OJB, iBATIS
17
Spring “hello world”
public interface GreetingService {
public void sayGreeting();
}
public class GreetingServiceImpl implements GreetingService {
private String greeting;
public GreetingServiceImpl() {}
public GreetingServiceImpl(String greeting) {
this.greeting = greeting;
}
public void sayGreeting() {
System.out.println(greeting);
}
public void setGreeting(String greeting) {
this.greeting = greeting;
}
}
GreetingServiceImpl
GreetingServiceImplha
haun
unsolo
soloattributo
attributo(o
(oproperty):
property):greeting.
greeting.
La
dellaclasse
classepuò
puòessere
essereimpostata
impostatatramite
tramiteilil
Laproperty
propertyèèl’unica
l’unicadipendenza
dipendenzadella
costruttore
costruttoreootramite
tramiteililmetodo
metodosetter
setter
SPRING
SPRINGIMPOSTA
IMPOSTAIL
ILVALORE
VALOREDELLA
DELLAPROPERTY
PROPERTY
Æ
Æ
18
Spring “hello world”
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id=“greetingService” class="com.springinaction.chapter01.hello.GreetingServiceImpl">
<property name="greeting">
<value>Buenos Dias!</value>
</property>
</bean>
</beans>
TRAMITE
TRAMITESETTER
SETTER--EQUIVALE
EQUIVALEAA
GreetingServiceImpl
GreetingServiceImplgreetingService
greetingService==new
newGreetingServiceImpl();
GreetingServiceImpl();
greetingService.setGreeting("Buenos
Dias!");
greetingService.setGreeting("Buenos Dias!");
19
Spring “hello world”
<bean id="greetingService"
class="com.springinaction.chapter01.hello.GreetingServiceImpl">
<constructor-arg>
<value>Buenos Dias!</value>
</constructor-arg>
</bean>
TRAMITE
TRAMITECOSTRUTTORE
COSTRUTTORE--EQUIVALE
EQUIVALEAA
GreetingServiceImpl
GreetingServiceImplgreetingService
greetingService==new
newGreetingServiceImpl(“Buenos
GreetingServiceImpl(“BuenosDias”);
Dias”);
20
Spring “hello world”
package com.springinaction.chapter01.hello;
import java.io.FileInputStream;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
public class HelloApp {
public static void main(String[] args) throws Exception {
BeanFactory factory = new XmlBeanFactory(new FileInputStream("hello.xml"));
GreetingService greetingService = (GreetingService) factory.getBean("greetingService");
greetingService.sayGreeting();
}
}
Risultato
Risultato“Hello
“HelloWorld”:
World”:Come
Comeconfigurare
configurareun
unbean
beanmediante
mediantel’injection
l’injectiondidiuna
una
specifica
stringa
in
una
property.
specifica stringa in una property.
La
Lareale
realepotenzialià
potenzialiàdidiSpring
Springconsiste
consistenel
nelpoter
poterfare
farel’injection
l’injectiondidiun
unbean
beanininun
unaltro
altro
bean
usando
IoC
Æ
bean usando IoC Æ
21
IoC (Inversion of control)
„
Hollywood Principle “Don’t call me, I’ll
call you”.
Lo sviluppatore implementa dei metodi che
verranno chiamati dal framework
„
E’ una tecnica usata nella progettazione
dei framework
Uno dei pattern per realizzarla è il Template
Method (fig. a destra)
„
Esempio: Servlet container
Gestisce il ciclo di vita le request delle Servlet
Invocando i metodi callback “Init”,
“Destroy”, “doGet”, “doPost”
abstract class AbstractClass {
public void templateMethod() {
// qui c’è l’algoritmo
...
framework
method1();
while (...) method2();
...
method3();
}
abstract void method1();
abstract void method2();
abstract void method3();
}
class ConcreteClass extends AbstractClass {
void method1() {...}
applicazione
void method2() {...}
void method3() {...}
}
22
Dependency Iniection
„
E’ un tipo particolare di inversione del controllo
„
Tradizionalmente nell’ OOP ogni oggetto è responsabile di ottenere i riferimenti agli
oggetti con cui collabora (le sue dipendenze)
„
Applicando IoC, agli oggetti le dipendenze vengono fornite all’atto della creazione da un
entità esterna che coordina ogni oggetto nel sistema. In altre parole le dipendenze
vengono “iniettate” nell’oggetto
„
In pratica in Spring il container inietta le dipendenze nell’oggetto tramite i suoi metodi
Java usati come metodi callback (setter o costruttori). Le dipendenze possono essere
oggetti, primitive (es: String) o tipi semplici (es: int, float)
.
„
DI è anche conosciuta come “push configuration”. Le dipendenze sono “spinte dentro”
(push) l’oggetto dal container piuttosto che “prelevate” (pull) dall’oggetto stesso
PULL
PUSH
Dependency
DependencyInjection
InjectionPattern
Pattern
23
DI Esempio
public
public class
class KnightOfTheRoundTable
KnightOfTheRoundTable {{
private
private String
String name;
name;
private
HolyGrailQuest
private HolyGrailQuest quest;
quest;
public
public KnightOfTheRoundTable(String
KnightOfTheRoundTable(String name)
name) {{
this.name
this.name == name;
name;
quest
=
new
HolyGrailQuest();
quest = new HolyGrailQuest();-> L’oggetto recupera la propria dipendenza
}}
public
public HolyGrail
HolyGrail embarkOnQuest()
embarkOnQuest() throws
throws GrailNotFoundException
GrailNotFoundException {{
return
return quest.embark();
quest.embark();
}}
}}
public
public class
class HolyGrailQuest
HolyGrailQuest {{
public
public HolyGrailQuest()
HolyGrailQuest() {}
{}
public
public HolyGrail
HolyGrail embark()
embark() throws
throws GrailNotFoundException
GrailNotFoundException {{
HolyGrail
HolyGrail grail
grail == null;
null;
//
// Look
Look for
for grail
grail
……
return
return grail;
grail;
}}
}}
24
DI Esempio
import
import junit.framework.TestCase;
junit.framework.TestCase;
public
class
public class KnightOfTheRoundTableTest
KnightOfTheRoundTableTest extends
extends TestCase
TestCase {{
public
public void
void testEmbarkOnQuest()
testEmbarkOnQuest() {{
KnightOfTheRoundTable
KnightOfTheRoundTable knight
knight == new
new KnightOfTheRoundTable("Bedivere");
KnightOfTheRoundTable("Bedivere");
try
try {{
HolyGrail
HolyGrail grail
grail == knight.embarkOnQuest();
knight.embarkOnQuest();
assertNotNull(grail);
assertNotNull(grail);
assertTrue(grail.isHoly());
assertTrue(grail.isHoly());
}} catch
catch (GrailNotFoundException
(GrailNotFoundException e)
e) {{
fail();
fail();
}}}
}}}
„
„
„
„
„
„
Se
Sesisiesegue
esegueililtest
testsu
suKnightOfTheRoundTable,
KnightOfTheRoundTable,indirettamente
indirettamentesisieffettua
effettuaililtest
test
anche
su
HolyGrailQuest
anche su HolyGrailQuest
Inoltre
Inoltreèèimpossibile
impossibileavere
avereun
uncomportamento
comportamentodiverso
diversoHolyGrailQuest
HolyGrailQuest(e.g.,
(e.g.,return
return
null
o
throw
GrailNotFoundException)
per
diversi
test
null o throw GrailNotFoundException) per diversi test
Se
Sesisista
stautilizzando
utilizzandoper
perHolyGrailQuest
HolyGrailQuestun
unmock
mockobject
objectper
persimulare
simulareun
unoggetto
oggettoreale
reale
ininambiente
di
test
si
deve
modificare
il
codice
per
farlo
funzionare
in
ambiente
di
ambiente di test si deve modificare il codice per farlo funzionare in ambiente di
produzione
produzione
25
DI Esempio
„
„
„
„
Il problema è l’accoppiamento. KnightOfTheRoundTable è staticamente accoppiato con
HolyGrailQuest (non si può avere un KnightOfTheRoundTable senza avere anche un HolyGrailQuest)
L’accoppiamento è necessario ma va minimizzato
Necessario: Due oggetti sono accoppiati quando uno dipende dall’altro, ma un programma OO
in esecuzione è proprio un insieme di oggetti che dipendono l’uno dall’altro (eseguono dei
compiti o delegano l’esecuzione ad altri oggetti dipendenti)
Minimizzato: Va reso più basso possibile perchè riduce la leggibilità, manutenibilità, testabilità
(pattern GRASP “low coupling”). Un modo per ridurre l’accoppiamento diretto è introdurre un
livello di indirezione mediante interfacce
public
public interface
interface Quest
Quest {{
public
public abstract
abstract Object
Object embark()
embark() throws
throws QuestException;
QuestException;
}}
public
public class
class HolyGrailQuest
HolyGrailQuest implements
implements Quest
Quest {{
public
public HolyGrailQuest()
HolyGrailQuest() {}
{}
public
public Object
Object embark()
embark() throws
throws QuestException
QuestException {{
//
// Do
Do whatever
whatever it
it means
means to
to embark
embark on
on aa quest
quest
return
new
HolyGrail();
return new HolyGrail();
}}
}}
private
private Quest
Quest quest;
quest;
……
public
public Object
Object embarkOnQuest()
embarkOnQuest() throws
throws
QuestException
{
QuestException {
return
return quest.embark();
quest.embark();
}}
Nella classe
KnightOfTheRoundTable uso
il tipo interfaccia
26
DI Esempio
public
public interface
interface Knight
Knight {{
public
public Object
Object embarkOnQuest()
embarkOnQuest() throws
throws QuestException;
QuestException;
}}
public
public class
class KnightOfTheRoundTable
KnightOfTheRoundTable implements
implements Knight
Knight {{
private
private Quest
Quest quest;
quest;
……
public
public KnightOfTheRoundTable(String
KnightOfTheRoundTable(String name)
name) {{
quest
quest == new
new HolyGrailQuest();
HolyGrailQuest();
…… }}
public
public Object
Object embarkOnQuest()
embarkOnQuest() throws
throws QuestException
QuestException {{
return
return quest.embark();
quest.embark();
}}
}}
„
„
Anche
Anchecon
conleleinterfacce
interfaccenon
nonrisolvo
risolvoililproblema
problemaperchè
perchèun
unKnightOfTheRoundTable
KnightOfTheRoundTableisisvincolato
vincolato
solo
ad
un
tipo
di
ricerca
per
“Holy
Grail”
e
nessun
altro
tipo
di
ricerca
solo ad un tipo di ricerca per “Holy Grail” e nessun altro tipo di ricerca
27
DI Esempio
„
„
E’E’giusto
giustoche
cheililcavaliere
cavalierescelga
scelgada
dasolo
sololalapropria
propriaricerca
ricerca(missione)
(missione)ooèèpiù
più
conveniente/utile
che
gli
venga
assegnata
?
conveniente/utile che gli venga assegnata ?
public
public class
class KnightOfTheRoundTable
KnightOfTheRoundTable implements
implements Knight
Knight {{
private
private Quest
Quest quest;
quest;
……
public
public KnightOfTheRoundTable(String
KnightOfTheRoundTable(String name)
name) {{
……
}}
public
public HolyGrail
HolyGrail embarkOnQuest()
embarkOnQuest() throws
throws QuestException
QuestException {{
……
return
return quest.embark();
quest.embark();
}}
public
public void
void setQuest(Quest
setQuest(Quest quest)
quest) {{
this.quest
this.quest == quest;
quest;
}}
}}
„
„
„
„
„
„
Ora
OraKnightOfTheRoundTable
KnightOfTheRoundTablenon
nonèèpiù
piùresponsabile
responsabiledidirecuperare
recuperareleleproprie
propriemissioni.
missioni.
Inoltre
poiché
KnightOfTheRoundTable
è
dipendente
solo
dall’interfaccia
Quest
Inoltre poiché KnightOfTheRoundTable è dipendente solo dall’interfaccia Questèèpossibile
possibile
passargli
qualsiasi
implementazione
di
tale
interfaccia.
passargli qualsiasi implementazione di tale interfaccia.
La
Laresponsabilità
responsabilitàdidicoordinare
coordinarelalacollaborazione
collaborazionetra
traoggetti
oggettidipendenti
dipendentièèscorporata
scorporatadagli
dagli
oggetti
stessi.
oggetti stessi.
„ es: In ambiente di produzione potremmo aver bisogno di un tipo di HolyGrailQuest,
28ma
„ es: In ambiente di produzione potremmo aver bisogno di un tipo di HolyGrailQuest,
ma
ininambiente
di
test
potremmo
avere
una
implementazione
mock
(mock
object)
ambiente di test potremmo avere una implementazione mock (mock object)
DI Esempio
„
„
„
„
Ora
Orache
chel’oggetto
l’oggettoèèpronto
prontoaaricevere
riceveredall’”esterno”
dall’”esterno”una
una
dipendenza
chi
la
passa
?
QUI
ENTRA
IN
GIOCO
SPRING
dipendenza chi la passa ? QUI ENTRA IN GIOCO SPRING
L’azione
L’azionedidicreare
creareassociazioni
associazionitra
tracomponenti
componentiapplicativi
applicativi
èèdetta
wiring
(cablare/collegare
fili
elettrici).
In
detta wiring (cablare/collegare fili elettrici). InSpring,
Spring,
cicisono
molti
modi
di
collegare
tra
loro
componenti
sono molti modi di collegare tra loro componenti ma
ma
ililpiù
comune
è
tramite
XML
(“knight.xml”)
più comune è tramite XML (“knight.xml”)
<?xml
<?xml version="1.0"
version="1.0" encoding="UTF-8"?>
encoding="UTF-8"?>
<!DOCTYPE
beans
PUBLIC
<!DOCTYPE beans PUBLIC "-//SPRING//DTD
"-//SPRING//DTD BEAN//EN"
BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<beans>
<bean
<bean id="quest“
id="quest“ class="com.springinaction.chapter01.knight.HolyGrailQuest"/>
class="com.springinaction.chapter01.knight.HolyGrailQuest"/>
<bean
id="knight“
<bean id="knight“ class="com.springinaction.chapter01.knight.KnightOfTheRoundTable">
class="com.springinaction.chapter01.knight.KnightOfTheRoundTable">
<constructor-arg>
<constructor-arg>
<value>Bedivere</value>
<value>Bedivere</value>
</constructor-arg>
</constructor-arg>
<property
<property name="quest">
name="quest">
<ref
<ref bean="quest"/>
bean="quest"/>
</property>
</property>
</bean>
</bean>
</beans>
</beans>
29
DI Esempio
import
import org.springframework.beans.factory.BeanFactory;
org.springframework.beans.factory.BeanFactory;
import
org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
public
public class
class KnightApp
KnightApp {{
public
public static
static void
void main(String[]
main(String[] args)
args) throws
throws Exception
Exception {{
BeanFactory
BeanFactory factory
factory == new
new XmlBeanFactory(new
XmlBeanFactory(new FileInputStream("knight.xml"));
FileInputStream("knight.xml"));
KnightOfTheRoundTable
knight
=
(KnightOfTheRoundTable)factory.getBean("knight");
KnightOfTheRoundTable knight = (KnightOfTheRoundTable)factory.getBean("knight");
knight.embarkOnQuest();
knight.embarkOnQuest();
}}
}}
30
Aspect Oriented Programming (AOP)
E’ un paradigma per incapsulare il codice “crosscutting”
Il codice che altrimenti sarebbe disperso (sparso) tra oggetti e metodi (es:
„
„
)può essere raggruppato in un solo punto
logging, security, transaction
Codice “disperso”
„
„
Layers
Per
Perintuire
intuireililfunzionamento
funzionamentosisipensi
pensialalconcetti
concettididiInterceptor
Interceptor(e.g.
(e.g.interceptor
interceptordidi
Struts2)
Struts2)
„ Il client invoca un proxy
„ Il client invoca un proxy
„ Una catena di interceptors (layer) decora le successive chiamate fino al metodo
„ Una catena di interceptors (layer) decora le successive chiamate fino al metodo
target
target
„ Gli interceptor forniscono servizi come transaction management, logging, security
„ Gli interceptor forniscono servizi come transaction management, logging, security
„ I servizi sono specificati dichiarativamente
„ I servizi sono specificati dichiarativamente
31
Esempio di AOP
package com.springinaction.chapter01.knight;
import org.apache.log4j.Logger;
public class Minstrel {
Logger song = Logger.getLogger(KnightOfTheRoundTable.class);
public Minstrel() {}
public void compose(String name, String message) {
song.debug("Fa la la! Brave " + name + " did " + message + "!");
}}
public class KnightOfTheRoundTable {
…
private Minstrel minstrel;
public void setMinstrel(Minstrel minstrel) {
this.minstrel = minstrel;
}
…
public HolyGrail embarkOnQuest() throws QuestException {
minstrel.compose(name, "embark on a quest");
return quest.embark();
„
Ideally a minstrel (metafora di un logger)
would automatically compose songs
}
without being explicitly told to do so
}
32
Esempio di AOP
package com.springinaction.chapter01.knight;
import java.lang.reflect.Method;
import org.apache.log4j.Logger;
import org.springframework.aop.MethodBeforeAdvice;
public class MinstrelAdvice
implements MethodBeforeAdvice {
public MinstrelAdvice() {}
public void before(Method method, Object[] args,Object target) throws Throwable {
Knight knight = (Knight) target;
Logger song = Logger.getLogger(target.getClass());
song.debug("Brave " + knight.getName() +" did " + method.getName());
}
}
„
Applying advice to an object is known as weaving
33
Bibliografia
„
Spring in action - Craig Walls Ryan Breidenbach – Manning
34
Hibernate - Caratteristiche
Hibernate è un middleware ORM (Object Relational
Mapping).
La funzione principale di un ORM è l’automatica e
trasparente persistenza di oggetti nelle tabelle di un DB
relazionale tramite metadata che descrivono il mapping
tra oggetti e entità del DB. Lo strato ORM trasforma dati
da una rappresentazione e l’altra in entrambi i versi
„
„
Ogni middleware ORM comprende i seguenti elementi:
„
„
„
„
„
API per eseguire operazioni CRUD (Create Read Update Delete) su
oggetti di classi persistenti
Un linguaggio o API per specificare delle Query su classi e proprietà
di classi
Una “facility” per specificare i mapping metadata
Una tecnica per gestire oggetti transazionali per eseguire dirty
checking, lazy association fetching, ed altre funzioni di ottimizzazione
35
Hibernate “Hello World”
package
package hello;
hello;
public
class
Message {
public class Message {
private
private Long
Long id;
id;
private
String
private String text;
text;
private
Message
private Message nextMessage;
nextMessage;
private
Message()
private Message() {}
{}
public
Message(String
public Message(String text)
text) {{
this.text
this.text == text;
text;
}}
public
public Long
Long getId()
getId() {{
return
return id;
id;
}}
private
private void
void setId(Long
setId(Long id)
id) {{
this.id
this.id == id;
id;
}}
public
public String
String getText()
getText() {{
return
return text;
text;
}}„
Applying advice to an object is known as weaving
public
public void
void setText(String
setText(String text)
text) {{
this.text
this.text == text;
text;
}}
public
public Message
Message getNextMessage()
getNextMessage() {{
return
return nextMessage;
nextMessage;
}}
public
public void
void setNextMessage(Message
setNextMessage(Message nextMessage)
nextMessage) {{
this.nextMessage
this.nextMessage == nextMessage;
nextMessage;
}}
}}
36
Hibernate “Hello World”
Session
Session session
session == getSessionFactory().openSession();
getSessionFactory().openSession();
Transaction
tx
=
session.beginTransaction();
Transaction tx = session.beginTransaction();
Message
Message message
message == new
new Message("Hello
Message("Hello World");
World");
session.save(message);
session.save(message);
tx.commit();
tx.commit();
session.close();
session.close();
equivale a
insert
insert into
into MESSAGES
MESSAGES (MESSAGE_ID,
(MESSAGE_ID, MESSAGE_TEXT,
MESSAGE_TEXT, NEXT_MESSAGE_ID)
NEXT_MESSAGE_ID)
values
(1,
'Hello
World',
null)
values (1, 'Hello World', null)
37
Hibernate “Hello World”
Session
Session newSession
newSession == getSessionFactory().openSession();
getSessionFactory().openSession();
Transaction
newTransaction
Transaction newTransaction == newSession.beginTransaction();
newSession.beginTransaction();
List
from
List messages
messages == newSession.find("
newSession.find("
from Message
Message as
as mm order
order
System.out.println(
messages.size()
+
"
message(s)
found:"
System.out.println( messages.size() + " message(s) found:" );
);
for
(
Iterator
iter
=
messages.iterator();
iter.hasNext();
)
for ( Iterator iter = messages.iterator(); iter.hasNext(); ) {{
Message
Message message
message == (Message)
(Message) iter.next();
iter.next();
System.out.println(
message.getText()
System.out.println( message.getText() );
);
}}
newTransaction.commit();
newTransaction.commit();
newSession.close();
newSession.close();
by
by m.text
m.text asc
asc");
");
Hibernate Query
Language
(HQL)
equivale a
select
select m.MESSAGE_ID,
m.MESSAGE_ID, m.MESSAGE_TEXT,
m.MESSAGE_TEXT, m.NEXT_MESSAGE_ID
m.NEXT_MESSAGE_ID
from
MESSAGES
m
from MESSAGES m
order
order by
by m.MESSAGE_TEXT
m.MESSAGE_TEXT asc
asc
38
Hibernate “Hello World”
XML Mapping
<?xml
<?xml version="1.0"?>
version="1.0"?>
<!DOCTYPE
<!DOCTYPE hibernate-mapping
hibernate-mapping PUBLIC
PUBLIC
"-//Hibernate/Hibernate
Mapping
"-//Hibernate/Hibernate Mapping DTD//EN"
DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<hibernate-mapping>
<class
<class name="hello.Message“
name="hello.Message“ table="MESSAGES">
table="MESSAGES">
<id
name="id“
column="MESSAGE_ID">
<id name="id“ column="MESSAGE_ID">
<generator
<generator class="increment"/>
class="increment"/>
</id>
</id>
<property
<property name="text“
name="text“ column="MESSAGE_TEXT"/>
column="MESSAGE_TEXT"/>
<many-to-one
name="nextMessage“
<many-to-one name="nextMessage“ cascade="all“
cascade="all“ column="NEXT_MESSAGE_ID"/>
column="NEXT_MESSAGE_ID"/>
</class>
</class>
</hibernate-mapping>
</hibernate-mapping>
39
Hibernate “Hello World”
Session
Session session
session == getSessionFactory().openSession();
getSessionFactory().openSession();
Transaction
tx
=
session.beginTransaction();
Transaction tx = session.beginTransaction();
//
// 11 is
is the
the generated
generated id
id of
of the
the first
first message
message
Message
message
=
(Message)
session.load(
Message message = (Message) session.load( Message.class,
Message.class, new
new Long(1)
Long(1) );
);
message.setText("Greetings
Earthling");
message.setText("Greetings Earthling");
Message
Message nextMessage
nextMessage == new
new Message("Take
Message("Take me
me to
to your
your leader
leader (please)");
(please)");
message.setNextMessage(
nextMessage
);
message.setNextMessage( nextMessage );
tx.commit();
tx.commit();
session.close();
session.close();
equivale a
select
select m.MESSAGE_ID,
m.MESSAGE_ID, m.MESSAGE_TEXT,
m.MESSAGE_TEXT, m.NEXT_MESSAGE_ID
m.NEXT_MESSAGE_ID
from
MESSAGES
m
from MESSAGES m
where
where m.MESSAGE_ID
m.MESSAGE_ID == 11
insert
insert into
into MESSAGES
MESSAGES (MESSAGE_ID,
(MESSAGE_ID, MESSAGE_TEXT,
MESSAGE_TEXT, NEXT_MESSAGE_ID)
NEXT_MESSAGE_ID)
values
(2,
'Take
me
to
your
leader
(please)',
null)
values (2, 'Take me to your leader (please)', null)
update
MESSAGES
update MESSAGES
set
set MESSAGE_TEXT
MESSAGE_TEXT == 'Greetings
'Greetings Earthling',
Earthling', NEXT_MESSAGE_ID
NEXT_MESSAGE_ID == 22
where
where MESSAGE_ID
MESSAGE_ID == 11
40
Hibernate Architettura
4 Tipi di API
„
„
„
„
Interfacce chiamate dall’applicazione per eseguire operazioni CRUD e
Query (Session, Transaction, and Query)
Interfacce chiamate per configurare hibernate (la principale è Hibernate) la
principale è la classe Configuration
Interfacce Callback che permettono alla applicazione di reagire
automaticamente ad eventi interni ad Hibernate (Interceptor, Lifecycle,
Validatable=
Interfacce che permettono l’estensione delle funzionalità di mapping di
41
Hibernate ( UserType, CompositeUserType, IdentifierGenerator)
Hibernate Architettura
Interfaccia Session
„
Il concetto di Session Hibernate si pone tra
quello di connection e transaction.
„
Una session è una “cache” di oggetti
caricati relativamente ad una unità di lavoro
Interfaccia SessionFactory
„
L’applicazione ottiene una istanza di
Session da un SessionFactory.
„
Esiste una SessionFactory per ogni database
„
La SessionFactory esegue il caching di
istruzioni SQL e metadati
Interfaccia Configuration
„
L’oggetto Configuration è usato per configurare Hibernate.
„
L’applicazione usa una istanza di Configuration per recuperare la posizione dei
documenti di mapping e delle proprietà e successivamente crea la SessionFactory
Interfaccia Transaction
„
E’ opzionale: si può decidere di gestire le transazioni ad hoc nel proprio codice.
„
Una interfaccia Transaction astrae l’applicazione dal particolare tipo di tecnologia
usata per le transazioni: JDBC, JTA UserTransaction, o CORBA transaction
Interfacce Query e Criteria
„
L’interfaccia Query permette di eseguire query. Le query possono essere scritte in
HQL o nel dialetto SQL del DB di riferimento.
„
L’oggetto Query è usato per effettuare il bind dei parametri della query, limitare il
numero dei risultati ritornati dalla query ed eseguire la query.
„
L’interfaccia Criteria è simile; permette di creare ed eseguire query objectoriented
42
Managed Env VS Non Managed Env
Managed Environment
„
Resource Pool (es: db connection), Transazionalità e Sicurezza
sono gestiti in modo dichiarativo
„
Application Server come Jboss; Glassfish; WebSphere; WebLogic
forniscono un managed environment
Non Managed Environment
„
Fornisce semplicemente la gestione delle richieste concorrenti
(Servlet Container come TomCat)
„
Per le connessioni si utilizza JDBC e Transazionalità e Sicurezza
sono sviluppati nell’applicazione
Hibernate può essere usato in entrambi gli ambienti
Nel seguito ci si riferisce al Non Managed Environment
43
Hibernate Startup
Startup di Hibernate
„
Localizzare il file di mapping tramite l’oggetto Configuration
„
Creare un SessionFactory
Regole
1.
Il file di mapping (Message.hbm.xml) deve essere visibile nel CLASSPATH
2.
Per convenzione 1 map file per classe (è possibile invocare più volte il metodo
addResource per caricarli tutti)
3.
Per impostare le configurazioni 3 alternativa
„
java -Dproperty=value.
„
file hibernate.properties nel classpath.
„
Tag <property> in hibernate.cfg.xml nel classpath.
Equivalente
Equivalentecon
conililmethod
methodchaining
chaining
Configuration
Configuration cfg
cfg == new
new Configuration();
Configuration();
cfg.addResource("hello/Message.hbm.xml");
cfg.addResource("hello/Message.hbm.xml");
cfg.setProperties(
cfg.setProperties( System.getProperties()
System.getProperties() );
);
SessionFactory
sessions
=
cfg.buildSessionFactory();
SessionFactory sessions = cfg.buildSessionFactory();
Configuration
Configuration cfg
cfg == new
new
Configuration()
Configuration()
.addResource("hello/Message.hbm.xml")
.addResource("hello/Message.hbm.xml")
.setProperties(System.getProperties())
.setProperties(System.getProperties())
.buildSessionFactory();
.buildSessionFactory();
44
Connection Pool
„
Supporto al connection pool open source C3P0 (altri supportati sono Apache DBCP e
Proxool)
Senza
SenzaHibernate
Hibernate
Con
ConHibernate
Hibernate
File
File
hibernate.properties
hibernate.properties
hibernate.connection.driver_class
hibernate.connection.driver_class == org.postgresql.Driver
org.postgresql.Driver
hibernate.connection.url
=
jdbc:postgresql://localhost/auctiondb
hibernate.connection.url = jdbc:postgresql://localhost/auctiondb
hibernate.connection.username
hibernate.connection.username == auctionuser
auctionuser
hibernate.connection.password
=
secret
hibernate.connection.password = secret
hibernate.dialect
hibernate.dialect == net.sf.hibernate.dialect.PostgreSQLDialect
net.sf.hibernate.dialect.PostgreSQLDialect
hibernate.c3p0.min_size=5
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.max_size=20
hibernate.c3p0.timeout=300
hibernate.c3p0.timeout=300
hibernate.c3p0.max_statements=50
hibernate.c3p0.max_statements=50
hibernate.c3p0.idle_test_period=3000
hibernate.c3p0.idle_test_period=3000
45
Caso di Studio: Modello di Dominio-Aste Online
1°
1°Passo:
Passo: Disegnare
DisegnareililModello
ModellodidiDominio
Dominio
46
Caso di Studio: Modello di Dominio-Aste Online
2°
2°Passo:
Passo: Progettare
Progettarei iPOJO
POJO(o(oJavaBean)
JavaBean)
public
public class
class User
User implements
implements Serializable
Serializable {{
private
private String
String username;
username;
private
Address
private Address address;
address;
public
User()
{}
public User() {}
public
public String
String getUsername()
getUsername() {{
return
return username;
username;
}}
public
public void
void setUsername(String
setUsername(String username)
username) {{
this.username
this.username == username;
username;
}}
public
public Address
Address getAddress()
getAddress() {{
return
return address;
address;
}}
public
public void
void setAddress(Address
setAddress(Address address)
address) {{
this.address
this.address == address;
address;
}}
public
public MonetaryAmount
MonetaryAmount calcShippingCosts(Address
calcShippingCosts(Address
fromLocation)
{
fromLocation) {
...
...
}}
}}
Impl.
Impl.Serializable
Serializable
Setter/Getter
Setter/Getter
Business
BusinessMethod
Method
47
Caso di Studio: Modello di Dominio-Aste Online
3°
3°Passo:
Passo: Progettare
Progettareleleassociazioni
associazioni
public
public class
class Category
Category implements
implements Serializable
Serializable {{
private
private String
String name;
name;
private
Category
private Category parentCategory;
parentCategory;
private
Set
childCategories
private Set childCategories == new
new HashSet();
HashSet();
public
Category()
{
}
public Category() { }
...
...
public
public void
void setName(String
setName(String name)
name) {{
this.name
this.name == name;
name;
}}
public
public Set
Set getChildCategories()
getChildCategories() {{
Codice
return
Codice“Scaffolding”
“Scaffolding”
return childCategories;
childCategories;
}}
public
public void
void setChildCategories(Set
setChildCategories(Set childCategories)
childCategories) {{
this.childCategories
this.childCategories == childCategories;
childCategories;
}}
public
public Category
Category getParentCategory()
getParentCategory() {{
return
return parentCategory;
parentCategory;
}}
public
public void
void setParentCategory(Category
setParentCategory(Category parentCategory)
parentCategory)
{{
this.parentCategory
this.parentCategory == parentCategory;
parentCategory;
}}
}}
48
Caso di Studio: Modello di Dominio-Aste Online
3°
3°Passo:
Passo: Progettare
Progettareleleassociazioni
associazioni(…aggiungere
(…aggiungereelementi)
elementi)
Category
Category aParent
aParent == new
new Category();
Category();
Category
aChild
=
new
Category();
Category aChild = new Category();
aChild.setParentCategory(aParent);
aChild.setParentCategory(aParent);
aParent.getChildCategories().add(aChild);
aParent.getChildCategories().add(aChild);
Codice
Codice“Scaffolding”
“Scaffolding”
3°
3°Passo:
Passo: Progettare
Progettareassociazioni
associazioni
public
public class
class Category
Category {{
...
...
private
private Set
Set items
items == new
new HashSet();
HashSet();
...
...
public
public Set
Set getItems()
getItems() {{
return
return items;
items;
}}
public
public void
void setItems(Set
setItems(Set items)
items) {{
this.items
this.items == items;
items;
}}
}}
Codice
Codice“Scaffolding”
“Scaffolding”
Categoria
Categoria>>Item
Item
49
Caso di Studio: Modello di Dominio-Aste Online
3°
3°Passo:
Passo: Progettare
Progettareleleassociazioni
associazioni
public
public class
class Item
Item {{
private
private String
String name;
name;
private
String
description;
private String description;
...
...
private
private Set
Set categories
categories == new
new HashSet();
HashSet();
...
...
public
public Set
Set getCategories()
getCategories() {{
Codice
Codice“Scaffolding”
“Scaffolding”
return
categories;
return categories;
Item
>
Categoria
Item > Categoria
}}
private
private void
void setCategories(Set
setCategories(Set categories)
categories) {{
this.categories
this.categories == categories;
categories;
}}
public
public void
void addCategory(Category
addCategory(Category category)
category) {{
if
if (category
(category ==
== null)
null)
throw
new
IllegalArgumentException("Null
throw new IllegalArgumentException("Null category");
category");
category.getItems().add(this);
category.getItems().add(this);
categories.add(category);}}
categories.add(category);}}
50
Caso di Studio: Modello di Dominio-Aste Online
4°
4°Passo:
Passo: Definire
Definirei imetadata
metadata
<?xml
<?xml version="1.0"?>
version="1.0"?>
<!DOCTYPE
<!DOCTYPE hibernate-mapping
hibernate-mapping
PUBLIC
"-//Hibernate/Hibernate
PUBLIC "-//Hibernate/Hibernate Mapping
Mapping DTD//EN"
DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<hibernate-mapping>
<class
<class name="org.hibernate.auction.model.Category“
name="org.hibernate.auction.model.Category“ table="CATEGORY">
table="CATEGORY">
<id
name="id“
column="CATEGORY_ID“
type="long">
<id name="id“ column="CATEGORY_ID“ type="long">
<generator
<generator class="native"/>
class="native"/>
</id>
</id>
<property
<property name="name“
name="name“ column="NAME“
column="NAME“ type="string"/>
type="string"/>
</class>
</class>
</hibernate-mapping>
</hibernate-mapping>
51
Bibliografia
„
Hibernate in Action - CHRISTIAN BAUER-GAVIN KING Manning
52