Programmazione Java Avanzata

Transcript

Programmazione Java Avanzata
Programmazione Java Avanzata
Struts 2 (Parte 4)
Ing. Giuseppe D'Aquì
Testi Consigliati
●
http://struts.apache.org/2.x/docs/tag-reference.
●
Struts 2 In Action (Manning)
●
●
Practical Apache Struts 2 Web 2.0 Projects
(Apress)
Validator reference:
●
http://struts.apache.org/2.0.11/docs/validation.html
2
Interceptor Validation
●
●
Abbiamo visto come effettuare una validazione
logica con l'interceptor Workflow
Questo ulteriore interceptor permette di
validare l'input utente attraverso la
configurazione, tramite XML o annotazioni
3
Interceptor Validation
●
●
●
●
L'interceptor Validation è il punto d'accesso al
Validation Framework presente in Struts2
Il Validation Framework consente di combinare
una serie di “test” sui nostri input
I test sono predefiniti e se ne possono creare
di nuovi
L'interceptor Validation viene eseguito subito
prima di Workflow, e si possono utilizzare
contemporaneamente
4
Interceptor Validation
●
L'interceptor ha bisogno di file di
configurazione scritti in XML
●
È anche possibile usare l'equivalente
configurazione tramite annotations
Vedi:
http://struts.apache.org/2.0.14/docs/validat
Il file XML ha il seguente nome:
–
●
●
NomeAction-validation.xml
–
Es. Register-validation.xml
5
Tipi di validator predefiniti
●
Field Validators
●
●
Effettuano controlli su singoli campi della form
HTML
Non-field Validators
●
Effettuano controlli su combinazioni di campi
6
Validazione XML
●
La radice è il tag <validators>
●
All'interno possono esserci
●
tag <field>, per i field validator
●
Tag <validator>, per i non-field validator
7
Validazione XML
●
<field name="username">
●
<field-validator type="requiredstring">
<message >Username is
required.</message>
</field-validator>
–
●
●
</field>
8
Validazione XML
●
●
●
Il tag <field> prevede un attributo “name” che
corrisponde al nome del campo
All'interno del tag ci possono essere uno o più
tag <field-validator>
<field-validator> ha un attributo “type”: il suo
valore può essere uno dei validator di struts
●
●
Es.: requiredstring, stringlenght
Dentro <field-validator> troviamo uno o più
tag <param> (per configurare il validator)
9
Validazione XML
●
●
Dentro <field-validator> troviamo anche un tag
<message> usato per contenere il messaggio
che verrà visualizzato all'utente
Il testo di <message> può contenere anche
espressioni OGNL, scritte nella forma:
●
${ espressione }
–
●
Attenzione: in questo caso si usa ${ } e non %{ } come si
faceva nel JSP
Se vogliamo usare una stringa di un Resource
Bundle basta usare l'attributo “key”, come per
10
i campi di testo
Validazione XML
●
●
Per i non-field validator abbiamo il tipo
“expression”
Questo validator prende un parametro
“expression” che contiene una qualunque
espressione OGNL booleana
11
Esempio 12: validazione via XML
●
Vedi
12
Validazione XML: Short Circuit
●
●
●
Se per un dato campo ci sono più validator
attivi, ogni fallimento corrisponde ad un
messaggio utente
Ci sono casi in cui non ha senso far comparire
molti errori e vorremmo visualizzare solo il
primo (o i primi n)
In questo caso si può usare l'attributo “shortcircuit” nel <field-validator> che interrompe
l'esecuzione dei prossimi validator
●
<field-validator type=... short-circuit=”true”>
13
I18n degli errori di conversione
●
In caso di errori di conversione prima della
validazione, Struts2 mostra dei messaggi di
errore predefiniti
●
●
È possibile modificarli inserendo nei nostri
resource bundle alcune stringhe con chiave:
●
●
Es. conversione da stringa a Date
invalid.fieldvalue.nomecampo
Esempio:
●
invalid.fieldvalue.dataDiNascita=La data di nascita
14
non ha un formato valido
Struts UI Tags
15
UI tag: attributi comuni
●
Tutti i tag UI (User Interface) hanno un insieme
di attributi in comune, che cioè possono essere
usati in ogni tag
●
●
●
name: è riportato nell'attributo name HTML, ed è
usato come riferimento ad un oggetto sul
ValueStack
Key: serve per riferirsi a stringhe di un Resource
Bundle
Label: crea una label HTML per il campo; se è
specificato l'attributo key non è necessario
16
UI tag: attributi comuni (2)
●
●
●
●
required: se posto a “true”, comparirà un
asterisco accanto al nome del campo
disabled: booleano, imposta l'attributo
disabled in HTML
labelPosition: può essere pari a “left” o “top”,
definisce la posizione della label rispetto al
campo
cssClass: viene tradotto con l'attributo HTML
class, usato per impostare la classe CSS del
campo
17
UI tag: head
●
●
●
Il tag <s:head /> si usa senza parametri
In sé non fa alcuna azione, ma è usato da
Struts per aggiungere in automatico fogli di
stile CSS oppure Javascript esterni
Infatti alcuni tag prevedono l'uso di librerie
javascript e fogli di stile che, senza il tag
<s:head /> dovremmo aggiungere
manualmente
18
UI tag: form
●
●
<s:form> è probabilmente il tag più
importante, perché sta alla base di tutti gli
inserimenti di input dell'utente
I suoi attributi principali sono:
●
●
action: può essere il nome di una Action oppure
una URL; se è riconosciuto come nome di una
Action allora genera la url corrispondente
namespace: è riferito all'attributo action, indica il
namespace di riferimento della Action
19
UI tag: form
●
Altri attributi:
●
●
●
method: si comporta come l'equivalente HTML, di
default è pari a POST
target: come in HTML; permette di aprire una
nuova finestra con il risultato della form
enctype: usato nel caso uno dei campi serva per
fare l'upload di file; in questo caso è impostato a
“multipart/form-data”
20
UI tag: textfield
●
Abbiamo già visto <s:textfield> in molti esempi
●
I suoi attributi:
●
●
●
maxlenght: la dimensione massima per il
contenuto del campo
readonly: se posto a true, il campo non è
modificabile
size: la dimensione visibile del campo
21
UI tag: password
●
●
●
Il tag <s:password> è essenzialmente una
textfield con i caratteri sostituiti da un
asterisco
Come tale, ha gli stessi attributi di
<s:textfield>
Ulteriore attributo:
●
showPassword: se impostato a true, il valore del
campo verrà preso dal ValueStack. Infatti per
default se il campo è password si ha un valore
vuoto; la password rimane in ogni caso nascosta
dagli asterischi
22
UI tag: textarea
●
●
<s:textarea> ha un uso molto simile a
<s:textfield>, solo che si usa per contenuti di
testo molto lunghi
Attributi:
●
cols: numero di colonne da visualizzare
●
rows: numero di righe
●
readonly: se true, il contenuto non è modificabile
●
wrap: imposta la funzione di “a capo automatico”;
può essere “off”, “physical” (a capo automatico) e
“virtual” (come physical ma elimina tutti gli “a
23
capo quando la form viene inviata”)
UI tag: checkbox
●
●
<s:checkbox> serve per impostare proprietà
booleane
Attributi:
●
●
fieldValue: può essere “true” o “false”; è il valore
che verrà inviato se la spunta è impostata
value: booleano, indica se la spunta deve essere
già impostata oppure no
24
UI tag: select
●
Permette all'utente di selezione un valore da
una lista
●
<s:select> funziona con tutte le Collection
●
Attributi:
●
●
list: è un'espressione OGNL che si riferisce ad un
oggetto di tipo Collection che contiene i valori per
il campo
listKey: la proprietà (variabile membro)
dell'oggetto Collection che verrà usata come
chiave
25
UI tag: select
●
Altri attributi:
●
●
●
listValue: la proprietà (variabile membro)
dell'oggetto Collection che sarà effettivamente
vista dall'utente
multiple: booleano, serve ad impostare se l'utente
può scegliere più valori
size: il numero di righe mostrate alla volta
26
UI tag: radio
●
●
<s:radio> è molto simile a <s:select> ma
presenta la scelta in un altro modo
Le scelte possibili sono elencate ed è possibile
sceglierne una sola alla volta
●
●
I pulsanti ricordano il funzionamento delle vecchie radio, dove quando
si premeva un pulsante si sbloccavano tutti gli altri
Gli attributi sono gli stessi di <s:select> :
●
list
●
listKey
●
listValue
27
UI tag: checkboxlist
●
●
●
<s:checkboxlist> è molto simile a <s:select>
impostato per scelta multipla
Visualizza le varie scelte con accanto una
checkbox, e possono essere spuntate in modo
indipendente
Gli attributi sono gli stessi di <s:select> :
●
list
●
listKey
●
listValue
28
Preselezione
●
I tag UI hanno normalmente il riempimento
automatico da parte di Struts
●
●
Es. se un <s:textfield> si riferisce ad un oggetto sul
ValueStack, il suo valore sarà automaticamente
impostato
I tag di selezione hanno invece bisogno di
alcune impostazioni per essere
“preselezionati”
29
Preselezione (2)
●
●
Il cuore della preselezione è l'attributo
“value”
value permette di impostare un'espressione
OGNL con il valore predefinito del campo
●
●
●
Value è comune a tutti i tag, ma per i campi
stringa è automaticamente impostato da Struts
Quando trattiamo con campi Collection
dovremmo riempirlo a mano con i valori della
preselezione
value deve essere riempito in modo da riferirsi
30
a una delle chiavi della Collection
UI tag: label
●
●
●
<s:label> è diverso dall'attributo “label” dei
campi
È un textfield a sola lettura
Invece di mostrare una casella per scrivere il
testo, mostra solo il testo
●
Utile per mostrare campi immodificabili
●
Attributi come <s:textfield>: name, label, key
31
UI tag: hidden
●
●
●
<s:hidden> serve ad inserire parametri
invisibili in una form
Infatti spesso ci sono dei parametri (come l'id)
che non ha senso mostrare all'utente ma che
vogliamo vengano passati alla Action quando la
form viene inviata
Attributi:
●
name
32
Esempio 13: uso dei tag UI
●
Vedi
33
Result Types
●
I Result possono essere di tipi differenti, che si
impostano con l'attributo “type” nel tag
<result> di struts.xml:
●
●
●
dispatcher: default, serve per impostare una url
che corrisponde ad un file JSP da renderizzare
redirect: dopo l'esecuzione della Action comunica
al browser di cambiare URL (redirezionamento)
[l'abbiamo visto nel caso di fallita autenticazione]
redirectAction: come redirect, ma redirige verso
un'altra Action
34
RedirectAction
●
Nel caso il result type sia redirectAction
dobbiamo impostare alcuni parametri
●
●
actionName: il nome della Action da richiamare
namespace: il namespace che contiene la action
da richiamare
●
L'uso è:
●
<result type=”redirectAction”>
●
●
<param name=”actionName”>MiaAction</param>
●
<param name=”namespace”>/esempio1</param>
</result>
35
Creare un convertitore di tipo
●
●
●
●
Struts permette di creare propri convertitori di
tipo, in aggiunta a quelli di default
Possono essere utili per acquisire in
automatico oggetti rappresentati da stringhe
complesse
Esempio: potremmo voler trasformare un
campo di testo “indirizzo” direttamente in un
oggetto Indirizzo
L'utente scrive “Via Garibaldi, 30” e
automaticamente Struts crea un oggetto
corrispondente
36
Creare un convertitore di tipo (2)
●
●
●
Un convertitore di tipo è una qualunque classe
che estende StrutsTypeConverter
E implementa le funzioni convertFromString()
e convertToString()
Struts chiamerà l'una o l'altra funzione a
seconda della “direzione” di conversione
37
Creare un convertitore di tipo (3)
●
Per utilizzare il nostro convertitore, è
necessario creare un file chiamato
●
●
●
Il file serve per definire, per ogni campo, un
corrispondente convertitore
Basta impostare ad es.
●
●
NomeAction-conversion.properties
indirizzo=it.unirc.pja.conv.ConvertitoreIndirizzo
E il campo “indirizzo” della nostra form
utilizzerà il convertitore prescelto invece di
quello di default
38
List e Map in OGNL
●
●
●
Spesso può essere necessario creare in OGNL
degli oggetti Collection dinamici
Ad esempio quando abbiamo campi di
selezione <s:select> (vedi)
Per esempio, volendo impostare in un campo
la lista contenente i numeri 1, 2 e 3,
dovremmo creare un oggetto List sul
ValueStack e poi riferirci a quello via OGNL
39
List e Map in OGNL (2)
●
Per fortuna c'è un metodo più rapido:
●
{1, 2, 3}
–
●
Restituisce un oggetto List il cui contenuto è 1, 2 e 3
#{ “mrossi”: “Mario Rossi”, “dbianchi”: “Davide
Bianchi” }
–
Restituisce un oggetto Map con due elementi: “Mario
Rossi” (con chiave “mrossi”) e “Davide Bianchi” (con
chiave “dbianchi”)
40
Creare un proprio Validator
●
●
Un proprio validator può venire in aiuto se
vogliamo separare la logica di validazione in
una classe specializzata, ai fini di riuso dello
stesso codice di validazione in più Action
Se creiamo un nostro validator potremo
richiamarlo tramite validazione XML
41
Creare un proprio Validator (2)
●
●
●
La nostra classe deve estendere
FieldValidatorSupport (se è un field validator)
oppure ValidatorSupport
Il cuore della classe è una funzione validate()
che si scrive in modo identico a come la
scriveremmo all'interno di una Action
In particolare, avremo a disposizione i metodi
getFieldName() e getFieldValue() che ci
restituiscono, rispettivamente, il nome del
campo e il valore che dovremo testare
42
Esempio 14: validator fatto in casa
●
Vedi
43
Programmazione Java Avanzata
Hibernate e JPA
Ing. Giuseppe D'Aquì
Testi Consigliati
●
Beginning Hibernate 2nd edition (Apress)
●
●
Sul sito è possibile scaricare, tra gli “extra”, il
codice sorgente e il capitolo 3
Hibernate Getting Started
●
http://docs.jboss.org/hibernate/core/3.6/quickstart/e
45
Persistenza
●
●
●
La persistenza è quella caratteristica delle
applicazioni orientate agli oggetti che
permette agli oggetti (o alle reti di oggetti) di
“sopravvivere” al processo che li ha creati.
Gli oggetti che non possiedono tale proprietà
si dicono transitori (transient).
L’obiettivo della persistenza è raggiunto
principalmente mediante l’uso di DBMS
relazionali.
JPA
●
●
●
Java Persistence API è uno standard per
l'implementazione di framework che
forniscono servizi di persistenza
Se un framework per la persistenza
implementa JPA, allora i suoi oggetti
estenderanno e implementeranno le classi e le
interface di JPA
Si standardizza l'utilizzo della persistenza
JPA (2)
●
JPA è composto da due parti:
●
●
●
●
Le Application Programming Interfaces vere e
proprie, definite nel package javax.persistence
Un query language semplificato chiamato JPQL
JPA è stato definito prendendo come
riferimento Hibernate, un famoso middleware
di persistenza e il suo linguaggio di query HQL
Hibernate a sua volta, nelle ultime versioni,
implementa JPA e quindi il cerchio si chiude
ORM
●
●
L' Object-Relational Mapping (ORM) è un
paradigma di programmazione che permette
l'integrazione fra applicazioni Object-Oriented
e sistemi RDBMS.
Un applicazione ORM fornisce, mediante
un'interfaccia orientata agli oggetti:
●
●
I servizi inerenti la persistenza dei dati
Un’astrazione rispetto alle caratteristiche
implementative dello specifico RDBMS utilizzato.
ORM: Vantaggi
●
●
Superamento del disadattamento
dell'impedenza tra paradigma relazionale e
ad-oggetti (object/relational impedance
mismatch).
Riduzione della quantità di codice da scrivere.
l'ORM presenta una semplice interfaccia per
realizzare operazioni di tipo CRUD, che sono
per loro natura molto ripetitive e favoriscono
la possibilità che vengano commessi errori
durante la stesura del codice che le
implementa
ORM: Vantaggi (2)
●
●
Approccio stratificato, che isola in un solo
livello la logica di persistenza dei dati, a
vantaggio della modularità complessiva del
sistema.
Elevata portabilità rispetto alla tecnologia
DBMS utilizzata.
ORM: Vantaggi (3)
●
●
●
Caricamento automatico del grafo degli
oggetti secondo i legami di associazione
definiti a livello del linguaggio di modellazione
del dominio
Lazy-loading, cioè caricamento dei dati
collegati on-demand.
Rilevamento automatico delle modifiche sui
dati e aggiornamento implicito
ORM: Vantaggi (4)
●
●
Gestione della concorrenza nell'accesso ai dati
durante sessioni. Conflitti durante la modifica
di un dato, da parte di più utenti in
contemporanea, possono essere
automaticamente rilevati dal sistema ORM.
Meccanismi di caching dei dati per migliorare
le prestazioni di accesso al RDBMS utilizzato.
Hibernate
●
●
●
●
Hibernate è un middleware che permette di
automatizzare la persistenza degli oggetti
negli RDBMS
I mapping fra Java e Tabelle del DB sono fissati
dall’utente attraverso file XML o annotazioni
sul codice
Hibernate è detto “lightweight” perché lavora
con oggetti Plain Old Java Object (POJO)
Un POJO è un oggetto semplice, che non deve
rispondere alle specifiche di alcn altro
framework
Hibernate
●
●
●
●
Hibernate permette di scrivere codice che si
riferisce agli oggetti Java, automatizzando le
operazioni CRUD, tramite la generazione
automatica del codice SQL che lega gli oggetti
alle tabelle del DB.
Esiste un linguaggio di querying (HQL) che fa
riferimento ai POJO
E’ possibile creare il codice Java
automaticamente a partire dai mapping
E’ possibile partire dal DB per creare le classi
(reverse engineering)
Hibernate: Struttura
Hibernate: concetti base
●
Due sono i concetti da capire per comprendere
bene il funzionamento di Hibernate
●
●
Entity
– Un oggetto che corrisponde ad una entità
del modello Entità/Relazione
Session
– Una session in Hibernate è una Unit of
Work (pattern), ovvero un
raggruppamento di operazioni da svolgere
assieme
Hibernate Tools
●
Sul sito di Hibernate è possibile scaricare un
plugin per Eclipse che semplifica molte delle
operazioni di configurazione
●
Per esempio consente di creare in maniera
visuale i file di configurazione, definire le
classi che possiedono mapping eccetera
Passi per l'integrazione
1) Identificare i POJO che hanno una
rappresentazione su database
2) Identificare le proprietà di questi POJO che
devono essere rese persistenti
3) Aggiungere le Java Annotations a ciascun
POJO, per mappare le proprietà sulle colonne
corrette
4) Creare lo schema del database
Passi per l'integrazione (2)
5) Aggiungere le librerie di Hibernate
all'applicazione
6) Creare la configurazione di Hibernate in XML
7) Creare un oggetto Configuration con
riferimento al file XML
8) Creare una SessionFactory inizializzata con
l'oggetto Configuration
9) Ottenere l'oggetto Session, che ci permetterà
di accedere ai dati
Includere Hibernate nel progetto
●
Dal pacchetto scaricato dal sito, bisogna
aggiungere al progetto:
Il file hibernate3.jar
●
I file jar contenuti in lib/required
●
I file jar contenuti in lib/jpa
Nota bene: Hibernate può essere utilizzato in
qualsiasi tipo di progetto, non è necessario che
sia web-based o J2EE
●
●
Naming Strategy
●
Se il nostro POJO deve essere reso persistente
(è cioè una Entity) dovremo definire un
mapping per stabilire:
Su quale tabella va salvato
●
A quali campi della tabella corrispondono le
variabili membro dell'oggetto
Il mapping dovrà essere definito per ogni
classe e per ogni proprietà della classe
●
●
Naming Strategy (2)
●
Hibernate infatti definisce due convenzioni per
i nomi:
●
Default: i nomi delle classi corrispondono a
nomi di tabella, e i nomi delle proprietà
corrispondono a nomi dei campi
– Es: un oggetto di tipo User verrà salvato
sulla tabella User, e la sua variabile
firstName su un campo firstName
Naming Strategy (3)
●
Seconda convenzione:
●
Improved: i nomi delle classi e delle
proprietà vengono riportati in minuscolo, e
se si usa lo standard CamelCase le due
parole vengono separate con underscore
– Es: un oggetto di tipo User verrà salvato
sulla tabella “user”, e la sua variabile
firstName su un campo “first_name”
Esempio15: Hibernate base
●
Vedi
Mapping con Annotations
●
●
Definiremo i nostri mapping object/relational
tramite Java Annotation “immerse” nel codice
dei nostri oggetti
In questo caso le annotation sono comode,
perché abbiamo oggetti che rappresentano
elementi del dominio applicativo che sono
POJO e quindi non contengono logica estranea
all'oggetto stesso
Mapping con Annotations (2)
●
@Entity
Posto prima di una classe, specifica che la
stessa è una Entità (come da modello E/R)
@Table
●
●
●
Posto prima di una classe, permette di
specificare il nome della tabella che salverà
gli oggetti di quella classe, evitando di
utilizzare una Naming Strategy
Mapping con Annotations (3)
●
@Id
Posto prima di una variabile o di un getter,
specifica che quella proprietà è la chiave
primaria della tabella
@GeneratedValue
●
●
●
Posto subito dopo @Id, specifica che quel
campo è una chiave con valore incrementale
che deve essere definita da Hibernate
Mapping con Annotations (4)
●
@Transient
●
Posto prima di una variabile o un getter,
specifica che quel valore non deve essere
considerato persistente e pertanto non va
salvato nel database
Mapping con Annotations (5)
●
@Column
●
●
Posto prima di una variabile o un getter,
specifica le caratteristiche che avrà la
colonna corrispondente nella tabella del
database
Attributi:
– Name: il nome della colonna
– lenght: la lunghezza
– Nullable: se può essere NULL o meno
– Unique