Note - Sviluppo e collaudo di una webapp mediante

perchmysteriousData Management

Dec 1, 2012 (4 years and 9 months ago)

522 views

Sviluppo e collaudo di un'applicazione
web mediante IoC e AOP

1

Introduzione

Il progetto si propone lo sviluppo di un'applicazione Java enterprise mediante l'impiego di Spring, un
framework non
-
invasivo per il supporto alla programmazione di componenti software in grado di
eseguire stand
-
alone o all'interno di piattaforme quali web

server e application server.

L'impiego delle funzionalità di Spring abilita lo sviluppo di applicazioni modulari, facilmente testabili
ed in grado di gestire logica di presentazione e modellazione dei dati, logica di business ed aspetti
ortogonali a ques
t'ultima quali ad esempio la gestione di contesti transazionali.

Le specifiche J2EE tradizionali, pur abilitando lo sviluppo di applicazioni enterprise mediante
strumenti quali Enterprise JavaBeans di tipo Session ed Entity, si rivelano troppo spesso comp
licate
da usare e portano alla stesura di codice difficile da testare al di fuori dell'ambiente di esecuzione
dell'Application Server.

Inoltre, il paradigma di programmazione degli EJB costringe spesso ad abdicare a numerosi principi
dell'object
-
oriented
programming a causa delle numerose limitazioni in termini di ereditarietà ed
uso di interfacce che essi comportano.

L'utilizzo di pattern di programmazione quali l'inversione del controllo (IoC, Inversion of Control) e la
programmazione orientata agli asp
etti (AOP, Aspect
-
Oriented Programming) permette, al contrario,
di sviluppare codice che non necessariamente dipende dal container o dal framework all'interno del
quale dovrà eseguire, dalle facility che esso espone, o dagli altri componenti software acces
sibili
attraverso di esso o da esso affiancati alla sua esecuzione.


Mediante inversione del controllo, ad esempio, è possibile evitare il lookup esplicito di altri
componenti software all'interno del codice relativo alla logica di business che si vuole re
alizzare,
lasciando che i parametri e i riferimenti necessari alle operazioni da eseguire siano valorizzati per
iniziativa del container ospitante.

Analogamente, è possibile gestire aspetti concettualmente ortogonali alla logic
a

di business di un
componen
te, associando tali operazioni alla definizione di variabili, all'invocazione di metodi o alla
restituzione dei loro risultati, ecc... piuttosto che sporcandone il codice vero e proprio con
funzionalità che nulla hanno a che vedere con i suoi specifici obi
ettivi.

La verifica di pre
-

e post
-

condizioni, l'apertura e chiusura di connessioni al database, il rollback o il
commit di transazioni sono tutti esempi di funzionalità ortogonali alla business logic di un
componente software e che possono essere effica
cemente gestiti sotto forma di aspetti.

Spring, oggi giunto alla versione 2.5, è stato uno dei primi framework a sostenere e ad abilitare
questo tipo di metodologia di programmazione ed il suo contributo ha notevolmente influenzato i
recenti sviluppi dell
e specifiche J2EE quali l'introduzione, negli EJB3, della '
Dependency

Injection
' e di
nuove modalità di indicazione dei contesti di transazionalità.


Si vuole realizzare, mediante il framework Spring, una tradizionale applicazione web per la gestione
di un
o shop on
-
line. Tale applicazione dovrà presentare funzionalità per:



l'inserimento di uno o più articoli contemporaneamente;



la ricerca di articoli mediante una o più parole chiave;



l'acquisto di uno o più articoli mediante 'carrello della spesa' virtuale.

Pur condividendo un comune modello dei dati, i componenti software che presiedono alle tre
funzionalità principali potranno essere sviluppati in parallelo dai componenti del gruppo.

Per ciascuno di essi, inoltre, dovranno essere preventivamente sviluppat
e adeguate interfacce Java e
corrispondenti suite di test, in grado di valorizzare con mock objects i parametri necessari
all'esecuzione, allo stesso modo in cui il framework Spring avrebbe provveduto alla loro
valorizzazione con parametri reali (es: conte
sto di esecuzione, riferimento ad altri componenti
deployati, ecc..).

Analogamente, si richiede di testare in isolamento (i.e., al di fuori del normale deploy su web server
o application server) anche dei singoli componenti interessati alla logica di pers
istenza (query SQL o
mapping OR, in funzione del tipo di implementazione scelta).

Infine, si richiede di gestite mediante l'impiego di Spring per la definizione di aspetti, anche il
contesto di transazionalità delle diverse funzionalità di business (es: a
cidità delle operazioni di
inserimento/ricerca/acquisto multiple) ed il caso di un loro insuccesso logico (es: inserimento di
articoli duplicati, ricerca priva di risultati, acquisto di quantità non disponibili).

2

Nuove tecniche per lo sviluppo di applicazi
oni Enterprise

Un’applicazione

è generalmente composta

di oggetti che collab
o
rano tra loro e che quindi
dipendono gli uni dagli altri. Il linguaggio Java fornisce svariate funzionalità per progettare e
implementare applicazioni, dai tipi primitivi alle cla
ssi, ma non
sono supportati
modi di prendere
questi blocchi

di base

e comporli in un tutto coerente; quest’area è sempre stata lasciata agli
sviluppatori. In realtà sono stati sviluppati molti
Design Patterns

dedicati alla composizione di classi e
istanze
di oggetti

ma sono comunque delle best practice
su cui uno sviluppatore deve riflettere e poi
implementare nell’applicazione.

Con l’introduzione dei JavaBeans, Sun ha definito un modello di componente software per Java. Le
specifiche
definiscono

un insieme

di
politiche

di sviluppo che permettono di rendere riutilizzabili
semplici oggetti Java e di comporli facilmente per costituire applicazioni più complesse. Tuttavia
sembravano

troppo semplici per poter creare qualsiasi applicazione reale, gli sviluppatori

Enterprise
volevano qualcosa di più e per questo JavaBeans sono stati principalmente usati per costruire widget
per interfacce grafiche.

Infatti applicazioni complesse spesso richiedono servizi come supporto alle transazioni, sicurezza,
distributed comput
ing
, caratteristiche non supportate da JavaBeans. Per questo motivo Sun ha
pubblicato le specifiche degli Enterprise JavaBeans (EJB) che estendono le nozioni di componenti
Java al lato server, ma che allo stesso tempo falliscono nel mantenere la semplicità

dei JavaBeans
originali e così EJB non hanno mai raggiunto il loro scopo preposto cioè semplificare lo sviluppo di
applicazioni Enterprise.

Oggi lo sviluppo di componenti Java è supportato da nuove tecniche come Aspect
-
Oriented
Programming (AOP) e Depende
ncy Injection (DI) che consentono di realizzare con JavaBeans,
applicazioni prima possibili solo utilizzando EJB. Queste tecniche supportano plain
-
old Java objects
(POJO) con un modello di programmazione dichiarativa simile a quello degli EJB ma senza la l
oro
complessità.

The fundamental construct that makes this possible is Spring's use of
Plain Old Java Objects (POJOs).
POJOs are essentially plain old Java classes free from any contract usually enforced by a framework
or component architecture through
subclassing

or the implementation of interfaces. POJOs are plain
old objects that are free from such constraints, making object
-
oriented programming possible once
again. When you are working with Spring, the domain objects and services you implement will b
e
POJOs. In fact, almost everything you implement should be a POJO. If it's not, you should be sure to
ask yourself why that is.


2.1

Dependency

Injection

Generalmente quando due o più
oggetti

devono collaborare per eseguire qualche

logica di business,
ciascun
o di essi è responsabile del reperimento dei propri riferimenti agli oggetti con cui deve
dialogare. Questo comporta un codice
highly coupled

e difficile da testare.

Con la Dependency Injection (DI)
(originariamente nota come Inversione del Controllo)

al c
ontrario è
il container ad essere responsabile di “iniettare” negli oggetti le
dipendenze di cui hanno bisogno,
quindi la configurazione e la specifica delle dipendenze è disaccoppiata dalla logica del programma.

Questo consente di ottenere
loose coupling

tra le entità che costituiscono l’applicazione: se un
oggetto conosce le proprie dipendenze solo attraverso la loro interfaccia, allora l’
effettiva
implementazione dell
e

dipendenz
e

non è importante per l’oggetto
.

Loose coupling

consente
migliore testabil
it
à e facilità di manutenzione

del codice.

Ad esempio
supponiamo di implementare una classe CartService che
gestisce uno S
hopping Cart;
tale classe avrà bisogno di
due riferimenti: uno oggetto ShoppingCart e un ProductService per
aggiornare il database al mo
mento della conferma dell’ordine. Senza DI, CartService
dovrebbe
creare

nuove istanze oppure
ottenerle

attraverso JNDI,
ma

in ogni caso sarebbe responsabile di
recuperare

le sue stesse dipendenze. Se ora definiamo uno Unit Test di CartService,
ci accorgiamo
che non siamo in grado di testare questa classe in isolamento, perché ogni volta che eseguiamo un
test, testiamo indirettamente anche ProductService. Inoltre non c’è modo di modificare il
comportamento di ProductService (es. restituire un cer
to valore o lanciare un’eccezione) per
eseguire
diversi tipi di
test; potremmo utilizzare implementazioni mock, ma anche in questo caso,
Cart
Service recupera comunque le sue dipendenze
e non possiamo passargli il nostro mock object,
quindi dovremmo modific
are CartService per recuperare le implementazioni mock solo per eseguire
i test, e poi modificarlo nuovamente.

Il problema è l’accoppiamento: CartService è staticamente accoppiato ai suoi riferimenti, non
possiamo avere un CartService senza avere anche uno

ShoppingCart e un ProductService. Codice
tight coupled

è difficile da testare, da capire e da riutilizzare e
spesso il fix di un bug causa la
creazione di altri
bug.

D’altra parte codice completamente disaccoppiato non può fare niente, le
classi devono co
noscersi in qualche modo, solo che il modo deve essere gestito con attenzione.

Una tecnica comune utilizzata per ridurre l’accoppiamento è quella di nascondere i dettagli
dell’implem
entazione dietro le interfacce; tuttavia non è sufficiente

perché ancora è

CartService a
dover recuperare le proprie dipendenze. Occorre quindi
trasferire la responsabilità di coordinare la
collaborazione tra oggetti dipendenti al di fuori degli oggetti stessi e questo è possibile grazie alla
Dependency Injection:
definiamo per

ogni riferimento getter e setter

all’interno della classe
CartService

(es. getProductService, setProductService).
Poiché CartService conosce le proprie
dipendenze solo attraverso la loro interfaccia,
possiamo

dall’esterno “iniettare” una qualsiasi
impleme
ntazione

di quelle interfacce
,
come ad esempio un SimpleProductService o
un’implementazione mock per eseguire i

test

senza cambiare nessuna riga del codice
.

Non c’è codice di lookup delle dipendenze, la classe si occupa solo delle proprie responsabilità
co
nfidando che i suoi riferimenti gli saranno forniti quando necessario.

2.2

A
spect Oriented Programming

Cross Cutting Concerns are functions you need throughout your application. This can be

for example
transactions, logging or functions you need only for a lim
ited time like

measuring of process time to
benchmark your application.

Very often you implement this code in each method of your business
logic.

AOP fornisce un diverso tipo di disaccoppiamento rispetto alla DI, separando funzionalità ortogonali
all’appli
cazione dalla business logic. Consente di catturare funzionalità che sono
utilizzate

in
più parti
di
un’applicazione in componenti riutilizzabili.

E’ spesso definita come una tecnica di programmazione che promuove la separazione dei
compiti /
responsabilità / concerns

all’interno di un sistema software. Sistemi software sono composti da vari
componenti, ciascuno responsabile di una certa funzionalità; spesso tuttavia questi componenti
sono costretti ad accollarsi anche responsabilità
che esulano dalla loro funzione principale. In questo
modo servizi come logging, gestione delle transazioni, sicurezza, sono
inglobati

nei componenti
stessi
, aumentando la complessità del codice a vari livelli:



codice che implementa servizi che riguardano
tutto il sistema software, è duplic
ato in più
componenti: per modificare il comportamento di n servizio, è necessario modificare tutti i
componenti



i componenti contengono codice che niente ha a che vedere con la loro funzionalità: non
solo ogni oggetto sa

di essere loggato o di essere in un contesto transazionale, ma
addirittura sono gli oggetti stessi ad essere responsabili dell’esecuzione di tali servizi

AOP consente di modulare questi servizi per poi applicarli dichiarativamente ai componenti. Questo
pe
rmette di avere componenti meno complessi e più concentrati sui loro compiti specifici e che
ignorano qualsiasi servizio di sistema in cui sono coinvolti.

Utilizzando l’AOP, i servizi possono essere applicati come dei layer di funzionalità che coprono la
c
ore application.

2.3

Spring Framework

Tra i tool di sviluppo basati su POJO si è imposto negli ultimi anni Spring Framework.
Spring
affronta
questo problema fornendo dei metodi per prendere classi, oggetti e servizi diversi e comporli in
un’applicazione funzio
nante. Per fare questo prende quei pattern che con il tempo si sono affermati
e sono stati formalizzati, e li codifica in oggetti base che possono essere integrati nelle applicazioni.

Spring è un
framework

nel senso che consente di configurare e comporre a
pplicazioni complesse a
partire da componenti semplici. Ma è anche un
container

perché contiene e gestisce il lifecycle e la
configurazione degli oggetti. È leggero, sia in termini di overhead che di dimensioni e tramite DI e
AOP, consente di ottenere loos
e coupling e separazione tra servizi di sistema e la logica
dell’applicazione. È stato creato per affrontare la complessità dello sviluppo di applicazioni
enterprise, consente di utilizzare
plain
-
vanilla

JavaBeans e ottenere cose prima possibili solo con
EJB.
Tuttavia l’utilità di Spring non è solo nello sviluppo lato server, ogni applicazione Java può
beneficiarne in termini di semplicità, testabilità e loose coupling.

Il framework Spring ha molte funzionalità organizzate in 6 moduli:

[
spring
-
overview.png
]

Ciascuno di essi fornisce dei framework aggiuntivi con cui possiamo costruire i servizi della nostra
applicazione, come ad esempio il supporto ad AOP, integrazione con framework di object
-
relational
mapping (es.
Hibernate),
pattern
MVC ecc.

Allo stesso t
empo Spring ci permette di scegliere i moduli
di cui abbiamo bisogno e di affidarsi ad altre opzioni quando Spring non è adatto al nostro scopo,
offrendo il supporto anche ad altri framework.


Spring provides functionality to implement a well designed
business layer for your application. It
helps you implementing standard design patterns like DAO or designing to interfaces and provides
features you need in all standard application and which allow you

to integrate different services.


2.3.1

Core module

Il core

module contiene le funzionalità di base di Spring e definisce come sono creati, configurati e
gestiti i bean. Contiene il container
BeanFactory
, implementazione del pattern Factory, il quale
rappresenta la base della Dependency Injection di Spring.

Sulle
basi fornite dal Core Module è stato costruito il package Context che fornisce un modo per
accedere agli oggetti in una modalità simile ad un
registro JNDI
. Eredita tutte le funzionalità del Core
e aggiunge il supporto all’internazionalizzazione (I18N),
alla propagazione degli eventi e alla
creazione trasparente di contesti attraverso, ad esempio, un servlet container.

2.3.2

AOP module

Il modulo AOP fornisce un’implementazione di Aspect
-
Oriented Programming conforme alle
specifiche dell’AOP Alliance (progetto
che mira a standardizzare l’utilizzo dell’AOP e garantire
l’interoperabilità delle diverse implementazioni).

Permette di definire method
-
interceptors e pointcuts

per disaccoppiare il codice che implementa
funzionalità logicamente separate.
È possibile anch
e definire il comportamento di un oggetto
direttamente nel codice usando metadati.

Tramite Spring AOP possiamo trasformare un semplice POJO in un aspect dichiarativamente nel
context di Spring, ma la classe rimane comunque un POJO, non c’è niente che indic
hi che debba
essere utilizzato come aspect

2.3.3

DAO module

The DAO package provides a JDBC
-
abstraction layer that removes the need to do tedious JDBC
coding and parsing of database
-
vendor specific error codes. Also, the JDBC package provides a way
to do program
matic as well as declarative transaction management, not only for classes
implementing special interfaces, but for all your POJOs (plain old Java objects).

2.3.4

ORM module

The ORM package provides integration layers for popular object
-
relational mapping APIs, i
ncluding
JPA, JDO, Hibernate, and iBatis. Using the ORM package you can use all those O/R
-
mappers in
combination with all the other features Spring offers, such as the simple declarative transaction
management feature mentioned previously.

2.3.5

Web module

Sprin
g's Web package provides basic web
-
oriented integration features, such as multipart file
-
upload
functionality, the initialization of the IoC container using servlet listeners and a web
-
oriented
application context. When using Spring together with WebWork o
r Struts, this is the package to
integrate with.

Spring's MVC package provides a Model
-
View
-
Controller (MVC) implementation for web
-
applications. Spring's MVC framework is not just any old implementation; it provides a clean
separation between domain model

code and web forms, and allows you to use all the other features
of the Spring Framework.

[SCHEMA FUNZIONAMENTO SPRING MVC e WEB FLOW]

[Vedi
5
-
SpringMVCandSecurity.pdf

per lo schema di Spring MVC]

2.3.6

Spring Security

Bla e bla e bla

(provare Spring Security v
2.0?)

[SCHEMA FUNZIONAMENTO

ACEGI SECURITY
]


2.3.7

Spring Web Flow

Ci sono due tipi di interazione nelle applicazioni web. Molti siti sono basati su una navigazione libera
da flussi cioè all'utente è dato un array di collegamenti e bottoni con cui hanno il
completo controllo
del flusso dell'applicazione. Ci sono invece applicazioni che guidano l'utente da una pagina all'altra,
come fosse una conversazione, ma l'applicazione segue comunque un flusso predefinito. Si può
pensare di utilizzare Spring MVC anche p
er questo secondo tipo di applicazioni creando:

una pagina j
sp che contiene un collegamento “Aggiungi prodotto al carrello”

un controller che aggiunge il prodotto all'
carrello

e
restituisce una View in cui viene mostrato
l’elenco dei prodotti acquistati

In

questo modo però il flusso dell'applicazione è distribuito all'interno di jsp (nel link) e di Controller
(nel ModelAndView) e quindi è difficile da seguire; inoltre cambiare il flusso significherebbe
modificare più file sorgenti. Spri
ng Web Flow elimina q
uesto acco
ppiamento stretto tra il codice e il
flusso dell'applicazione definendo il flusso in un file di configurazione separato e autonomo.


2.3.8

Vantaggi di Spring

2.3.8.1

Integration of JDBC, Hibernate, JDO, EJB to access databases

Spring allows to integrate any of

this solutions to access your database.
The interface is well
designed and lets you easily replace a JDBC database access with a Hibernate based database access.

Hibernate, JDO and EJB are solutions to map database data to classes, e.g. Reading a line of
the table
book and writing it to a object of class type book. This allows you to use classes instead of result sets
in your application and is considered as good design,

because your application keeps being object
oriented.

If you use JDBC access, Spring p
rovides an abstract exception layer.
If you change your database
from PostgreSQL to Oracle you do not have to change the exception handling

from
OracleDataAcception to PostgresDataException. Spring catches the application server specific
Exception and thro
ws a Spring dataexception.

2.3.8.2

Gestione delle transazioni

You can use a wide choice of transaction management solutions including Hibernate, database
transactions or the Transaction Management from your Websphere or JBoss application server (JTA).
The selectio
n of a transaction management solution is not very invasive, i.e. you can easily change
the transaction management without changing much

of your code.

2.3.8.3

Integration of resource files

A complete library to read your resource and configuration files.

2.3.8.4

Integration of messaging

A complete library to create Emails or messages using a Java Messaging System. JMS is

included in
most J2EE application servers like JBoss, Websphere etc. A JMS allows you for

example to send
messages including objects (classes) be
tween applications. For example

your Internet shop
applications sends a message including the order class. The message

is read later by your enterprise
resource planning application.

2.3.8.5

JMX (Java Management Extension)

JMX allows you to remote access other app
lication from within your application. Imagine

a local Java
application calling a remote server to start jobs, getting information or do

what ever you like. JMX
allows you to connect your application between multiple servers

across the Internet or a LAN.

2.3.8.6

W
eb application development

Spring provides his own web framework but also allows to use Struts, Velocity,

FreeMarker, Struts
Tiles or Libraries to create XML, Excel, PDF documents or reports. You

can even develop an adapter
for your own web framework to us
e Spring for your

business logic.

2.3.8.7

Little invasive

Spring is little invasive compared to other solutions. Using EJB version 2.1 will force you

to extend
EJBObject classes and other when you want to create your business logic or

your entity objects. Your
cod
e is closely coupled to to the technology you choose. This is

improved in EJB 3 but EJB 3 is at the
time (December 2005) still not not integrated in all

J2EE application servers.

Spring allows you to use so
-

called POJO (Plain Old Java Objects) for your do
main classes

(domain
class = e.g. a class Book representing a entity book) or your business logic. This

will keep your code
clean and easily to understand.

2.3.8.8

Good Design

Spring is very well designed even if I question the usefulness of the runtime exception
for

example,
the usefulness of all the adapters to EJB access, transaction management etc.

are enormous. They
allow to replace technology A with technology B when your

application growths and needs a more
powerful solution or if you change the

environment
or because of other reasons.


3

Hibernate

Hibernate is a solution for object relational mapping and a persistence management

solution or
persistent layer. This is probably not understandable for anybody learning

Hibernate.

What you can imagine is probably th
at you have your application with some functions

(business
logic) and you want to save data in a database. When you use Java all the

business logic normally
works with objects of different class types. Your database tables

are not at all objects.

Hibernate

provides a solution to map database tables to a class. It copies
one row of
the database

data to a class. In the other direction it supports to save objects to the database. In this

process the
object is transformed to one or more tables.

Saving data to a

storage is called persistence. And the copying of tables to objects and

vice versa is
called object relational mapping.

3.1

Perché

usare

Object Relational Mapping?

3.1.1

Migliore

architettura

del
sistema

When you include all functionality of your application and th
e access to the database

within your
dialogs, you will have some severe disadvantages.

It is really difficult to reuse code. You will repeat code at many places. If you change

anything it is
quite hard to find out all places where you have to add changes.

When you separate your dialogs from your logic and the logic from the persistence

mechanism you
can more easily apply changes to one part without influencing the other

parts.

3.1.2

Riduce il tempo necessario per azion
i

DB standar
d

Most queries in database develo
pment are simple “insert, update, delete” statements.

There is no
need to develop all these tedious statements. Hibernate helps you save time.

3.1.3

Advanced features difficult to develop yourself

Caching solutions, transactions and other features Hibernate prov
ides are not so easy to

implement.
It is actually non sense to develop something which allready exist.

Using Hibernate everything is
there. You just have to use it.

3.2

How Hibernate works

What is nice and in my opinion an advantage over entity beans, hibernat
e starts from simple java

classes (Pojo = Plain Old Java Objects).

You just need to create a mapping file.
The mapping file explains Hibernate which field in the class is

mapped to which field in the database.

A session factory is important for Hibernate.
It implements a design pattern, that ensures that only

one instance of the session is used per thread. You should only get your Hibernate session from

this
factory.

Even Hibernate needs a database driver to access a database.


3.3

Databases

3.3.1

Why use PostreSQL?

It provides features like Triggers, Stored Procedures, Views for quite a long time compared to MySql,
it has a better
license

model, a wide choice of languages to create stored procedures including
pg/psql, c and others. I have heard ;
-

) that it is better

scalable when you are not having a simple
web application reading data but a large scale application using transactions, triggers, stored
procedures and a lot of complex queries.

4

Struttura dell’applicazione web

The application we will be building from scr
atch over the course of this tutorial is a
very basic
inventory

management system. This inventory management system is severely constrained in terms
of scope; find below

a use case diagram illustrating the simple use cases that we will be
implementing.


Th
e solution should be portable between different database server, so we need to

encapsulate the
access to the database. A good way to make your application not aware

of a special implementation,
is to use an interface.

[SCHEMA BookDAO <<interface>>


HibernateBookDao]


In our inventory management system, we have the concept of a product and a service for handling
them. In

particular, the business has requested the ability to increase prices across all products. Any
decrease will be

done on an individua
l product basis, but this feature is outside the scope of our
application. The validation rules

for price increase are:

• The maximum increase is limited to 50%.

• The minimum increase must be greater than 0%.

Find below a class diagram of our inventory ma
nagement system.

[SCHEMA
?
UML? DEL SERVICE LAYER]

In order to separate the web dependent logic from the business logic, we will

place classes related to
the web tier in the
'web'
package and create two new packages: one for service objects

called
'service'

and another for domain objects called
'domain'
.

First we implement the
Product
class as a POJO with a default constructor (automatically provided if
we don't

specify any constructors) and getters and setters for its properties
'description'
and
'price'
.
L
et's also make

it
Serializable
, not necessary for our application, but could come in handy later on
when we persist and store

its state.

This is the service res
ponsible for handling products.
It contains two

methods: a business method
increasePrice()
that
increases prices for all products and a getter method

getProducts()
for retrieving
all products. We have chosen to make it an interface instead of a concrete class

for an number of
reasons. First of all, it makes writing unit tests for
Controllers
easier (
as we'll see in the next

chapter). Secondly, the use of interfaces means JDK proxying (a Java language feature) can be used
to make

the service transactional instead of CGLIB (a code generation library).


This next class (PriceIncrease) is a very simple Ja
vaBean class, and in our case there is a single
property with a getter and setter.
This is the object that
the form will populate and that our business
logic will extract the price increase percentage from.

The following validator class gets control after
the user presses submit. The values entered in the
form will be set on the command object by the framework. The
validate(..)
method is called
and the
command object (
PriceIncrease
) and a contextual object to hold any errors are passed in.




Un’applicazion
e web per

la gestione di uno shop online richiede l’accesso ad un database; tale
accesso avviene attraverso un Service Layer tramite cui i Controller (?) interagiscono con il database
per aggiungere, modificare o ottenere prodotti dal database.

Il Service
Layer si appoggia al Data Layer (?) che un’interfaccia DAO (Data Access Object) (?) per
accedere direttamente al database. Grazie all’uso delle interfacce e grazie alla DI, L’implementazione
effettiva del DAO non è importante: Spring inietta nel Service La
yer un riferimento ad un qualsiasi
DAO purché rispetti il contratto stabilito dall’interfaccia che il Service Layer si aspetta. In questo
modo possiamo successivamente scegliere di cambiare DAO, ad esempio utilizzando Hibernate
piuttosto che JDBC, senza ch
e il Service Layer se ne accorga e senza modificarne il codice.


We create a new interface called
ProductDao
. This will be the interface that defines the functionality
that the DAO implementation classes will provide


we could choose to have more than one

implementation some day.

We'll follow this with a class called
JdbcProductDao
that will be the JDBC implementation of this
interface. Spring provides a JDBC abstraction framework that we will make use of. The biggest
difference between using straight JDBC

and Spring's JDBC framework is that you don't have to worry
about opening and closing the connection or any statements.
It is all handled for you.
Another
advantage is that you won't have to catch any exceptions, unless you want to. Spring wraps all
SQLEx
ceptions in it's own unchecked exception hierarchy inheriting from DataAccessException. If
you want to, you can catch this exception, but since most database exceptions are impossible to
recover from anyway, you might as well just let the exception propaga
te up to a higher level. The
class
SimpleJdbcDaoSupport
provides convenient access to an already configured
SimpleJdbcTemplate
, so we extend this class. All we will have to provide in the application context is
a configured
DataSource
.

Let's go over the

tw
o DAO methods in this class.
Since we are extending
SimpleJdbcSupport
we get
a

SimpleJdbcTemplate
prepared and ready to use.
This is accessed by calling the
getSimpleJdbcTemplate()
method.

A differenza di JDBC, in cui si deve fornire una classe RowMapper p
er eseguire il mapping tra I campi
del domain object e le tabelle del database, …

The first method,
getProductList()
executes a query using the
SimpleJdbcTemplate
. We simply
provide the SQL statement and a class that can handle the mapping between the
Resu
ltSet
and the
Product
class. In our case the row mapper is a class named
ProductMapper
that we define as an
inner class of the DAO. This class will so far not be used outside of the DAO so making it an inner
class works well.

The second method saveProduct is also using the
SimplJdbcTemplate
. This time we are calling the
update
method passing in an SQL statement together with the parameter values in the form of a

MapSqlParameterSource
.
Using a
MapSqlParameterSource
allows us to
use named parameters
instead of the typical "?" place holders that you are used to from writing plain JDBC. The named
parameters makes your code more explicit and you avoid problems caused by parameters being set
out of order etc. The update method

returns

the count of rows affected.




We will
use a Spring template to access
the database.
A spring template keeps us away from dealing
with JDBC/Hibernate datasources
,

connections

and sessions
.

The
hibernate

template provides a convenient method to encapsulate

all the handling with the

datasource and the connection

(vale anche per Hibernate o solo per JDBC?)
. We will configure the
datasource later

in the Spring context
. Each query
is executed only by a save/update/insert…


Now that we implemented the
Persistence Layer, i
f we structured our application properly, we
should only have to change the service layer classes to take

advantage of the database persistence.
The view and controller classes should not have to be modified, since

they should be unawar
e of any
implementation details of the service layer. So let's add the persistence to the

ProductManager
implementation. We modify the
SimpleProductManager
and add a reference to a
ProductDao

interface plus a setter method for this reference. Which impleme
ntation we actually use here should
be

irrelevant to the ProductManager class, and we will set this through a configuration option. We
also change the

setProducts
method to a
setProductDao
method so we can inject an instance of
the DAO class. The

getProduc
ts
method will now use the DAO to retrieve a list of products. Finally,
the
increasePrices
method

will now get the list of products and then after the price have been
increased the product will be stored in the

database using the
saveProduct
method on the
DAO.


We also need to define a connection pool.
We are using the DBCP
connection pool from the Apache
Jakarta project.




The Spring Web MVC framework uses an implementation class of the interface called
HandlerMapping

to define the mapping between a request URL and the object that is going to
handle that request (the handler). Unlike the
DispatcherServlet
, the
HelloController

is
responsible for handling a request for a particular page of the website and is also known as

a

Page
Controller”.
The default
HandlerMapping

that the
DispatcherServlet

uses is the
BeanNameUrlHandlerMapping
; this class will use the bean name to map to the URL in the
request so that the
DispatcherServlet

knows which controller must be invoked for h
andling
different URLs.

In Spring Web MVC, the
Controller

handles

the

request and returns a
ModelAndView

-

in
this case, one named
'hello.jsp'

which is also the name of the JSP

file we will create next. The
model that this class returns is actually resolved via a
ViewResolver
. Since we

have not explicitly
defined a
ViewResolver
, we are going to be given a default one by Spring that simply

forwards to
a URL matching the name of th
e view specified.

We're also going to put all JSPs in a directory named
'jsp'
under the
'WEB
-
INF'
directory. This will
ensure that views can only be accessed via the controller since it will not be not possible to access
these pages directly via a URL.

4.1

Dis
accoppiare

la View
dal

Controller

Right now the controller specifies the full path of the view, which creates an unnecessary
dependency between the controller and the view. Ideally we would like to map to the view using a
logical name, allowing us to switc
h the view without having to change the controller. You can set this
mapping in a properties file if you like using a
ResourceBundleViewResolver
and a
SimpleUrlHandlerMapping
class. For the basic mapping of a view to a location, simply set a prefix
and a s
uffix on the
InternalResourceViewResolver
. This second approach is the one that we will
implement now, so we modify the
'springapp
-
servlet.xml'
and declare a

'viewResolver'
entry. By
choosing the
JstlView
, it will enable us to use JSTL in combination with
message resource bundles as
well as provide us with the support for internationalization.



The class book is a normal Java bean with private attributes and public getter/setter and constructor
method.



4.2

Web Layer

Questo strato dell’applicazione comprende
View, Model, Controller e Flow di Spring MVC e Spring
Web

Flow.


4.3

Service Layer

Il compito del service layer è quello della gestione dei domain objects.


4.4

Persistence
Layer

Il compito del Persistence Layer è quello della gestione della persistenza su databas
e.




Lo shopping cart deve essere un oggetto che sopravvive tra una richiesta e l’altra in modo che anche
se l’utente naviga all’interno del sito, i prodotti aggiunti al carrello siano mantenuti. Per ottenere un
comportamento di questo tipo occorre defini
re lo Shopping Cart come
bean scoped
-
proxy

(ma siamo
sicuri che serva?)

[
Being able to define a bean scoped to a HTTP request or Session (or indeed a custom scope of your
own devising) is all very well, but one of the main value
-
adds of the Spring IoC cont
ainer is that it
manages not only the instantiation of your objects (beans), but also the wiring up of collaborators
(or dependencies). If you want to inject a (for example) HTTP request scoped bean into another
bean, you will need to inject an AOP proxy i
n place of the scoped bean. That is, you need to inject a
proxy object that exposes the same public interface as the scoped object, but that is smart enough
to be able to retrieve the real, target object from the relevant scope (for example a HTTP request)

and delegate method calls onto the real object.

Note

You do not need to use the <aop:scoped
-
proxy/> in conjunction with beans that are scoped as
singletons or prototypes. It is an error to try to create a scoped proxy for a singleton bean (and the
resulti
ng BeanCreationException will certainly set you straight in this regard)
.]


Il processo di iniezione delle dipendenze è chiamato

wiring”
.

Anche se Spring utilizza la parola

“bean” per riferirsi ai componenti dell’applicazione, questo non
significa che un componente Spring debba seguire le specifiche JavaBean, al contrario può essere un
qualsiasi tipo di POJO; assumiamo dunque nel seguito che JavaBean, bean o POJO siano sinon
imi.

In un’applicazione Spring
-
based, gli oggetti che la costituiscono vivono all’interno del container
Spring: il container ha il compito di crearli, collegarli (wiring) configurarli e gestire
tutto
il loro
lifecycle.

Tale container è il cuore di Spring F
ramework; utilizza la DI per gestire i componenti che formano
l’applicazione e questo include la creazione delle associazioni tra componenti che collaborano,
rendendo il loro codice più pulito, semplice da capire, facilmente riutilizzabile e facile da test
are.

Ci sono due tipi di container:



Bean Factor
y
:

più semplic
e
, con supporto di base alla DI



Application Context
:
estend
e

Bean Factory, supportando la risoluzione di messaggi testuali
da file properties
, inclusa l’internazionalizzazione,

e
la notifica di a
pplication events ai
listener registrati.

Bean Factory è
un’implementazione general
-
purpose del pattern Factory, che può creare e
dispensare bean di tipi diversi; essendo una factory, conosce tutti gli oggetti all’interno
dell’applicazione quindi è in grad
o di creare le associazioni necessarie tra gli oggetti che devono
collaborare tra loro; gli oggetti creati dalla factory sono quindi già configurati, conoscono tutte le
loro dipendenze e sono pronti all’uso. Inoltre il container prende parte attivamente ne
l ciclo di vita
dei bean, eseguendo chiamate a metodi di inizializzazione o di distruzione se definiti.

L’implementazione più utilizzata di BeanFactory è
XmlBeanFactory

che carica i bean basandosi
sulle definizioni contenute in un file xml;

i bean vengono
caricati in modo lazy cioè

la factory non
istanzia immediatamente i bean ma carica la loro definizione (descrizione e proprietà) per poi
instanziarli solo quando sono necessari.

Questo tipo di container è utile per applicazioni semplici o nel caso di mobil
e device dove le risorse
hardware sono scarse; per applicazioni più complesse è meglio caricare i bean dell’applicazione
util
izzando un Application Context.

In Application Context è simile a BeanFactory, entrambi caricano le definizioni dei bean,
eseguono
il
wiring

e restituiscono i bean quando richiesto; tuttavia questo container aggiunge alcune
funzionalità
necessarie per applicazioni enterprise
:



Risoluzione di messaggi di testo da message resource bundle per supporto
all’internazionalizzazione



Supporto g
enerico per caricare risorse (es. immagini…)



Notifica di eventi ai bean registrati come listener



A differenza della BeanFactory, pre
-
carica tutti i bean singleton allo startup del context
, in
modo che siano già pronti quando saranno richiesti.

Le due princ
ipali implementazioni sono:



FileSystemXmlApplicationContext



carica
la definizione del context da un file
XML presente nel file system



XmlWebApplicationContext



come il precedente ma il file xml è contenuto in una
web application

[Bean Lifecycle p 37 cap
.2 ?]

[
Wiring injection: by con
s
tr
u
ctor or by setter

p42
]

[Aurowiring]

[Bean scoping]




5

Test con Spring

Test Driven Development…

Testing is a vital part of software development. It is also a core practice in Agile development.
We
have found that the best
time to write tests is during development, not after, so even though our
controller doesn't contain complex logic, we're going to write a test. This will allow us to make
changes to it in the future with confidence.

Another of the best practices of Agile d
evelopment is Continuous Integration. It's a good idea to
ensure your tests are run with every build (ideally as automated project builds) so that you know
your application logic is behaving as expected as the code evolves.


Some developers don't bother
writing tests for getters and setters or so
-
called 'auto
-
generated'
code. It usually takes much longer to engage in the debate (as this paragraph demonstrates) on
whether or not getters and setters need to be unit tested as they're so 'trivial'. We write t
hem
because: a) they are trivial to write; b) having the tests pays dividends in terms of the time saved for

the one time out of a hundred you may be caught out by a dodgy getter or setter; and c) they
improve test coverage. We create a
Product
stub and te
st each getter and setter as a pair in a single
test. Usually, you will write one or more test methods per class method, with each test method
testing a particular condition in a class

method such as checking for a
null
value of an argument
passed into the

method.


Before we implement the methods in
SimpleProductManager
, we're going to define some tests first.
The strictest definition of
Test Driven Development
(TDD) is to always write the tests first, then the
code. A looser interpretation of it is more ak
in to
Test Oriented Development
(TOD), where we
alternate between

writing code and tests as part of the development process. The most important
thing is for a codebase to have as complete a set of unit tests as possible, so how you achieve it
becomes somew
hat academic. Most TDD developers, however, do agree that the quality of tests is
always higher when they are written at around the

same time as the code that is being developed,
so that's the approach we're going to take.



Ci interessano due tipi di test
:

Unit Test: test di un'unità logica di lavoro isolata (classe, metodo...)

Integration Test: test di due o più unità di un'applicazione insieme

Spring in genere non è direttamente coinvolto nei test perché le applicazione che sfruttano la
Dependency Inject
ion di Spring, sono costituite da oggetti loosely coupled, che sono per loro natura
più semplici da testare. Tuttavia ci sono punti in cui Spring può partecipare direttamente nei test:



Unit Testing di Spring MVC Controllers
: Spring fornisce un'estensione d
i JUnit TestCase con
metodi di assert specifici per verificare i valori ritornati in un oggetto ModelAndView. Inoltre
fornisce delle utilissime implementazioni Mock di HttpServl
etRequest e HttpServletResponse



Integration Testing di flussi definiti con Spri
ng Web Flow
:

anche in questo caso viene fornita
un’estensione TestCase con assert specifici per verificare lo stato corrente di un flusso e per
verificare la presenza e i valori di oggetti contenuti nel flowscope. Per fare questo è messa a
disposizione un’
implementazioni Mock del contesto del flusso che possiamo modificare
come vogliamo



Integration Testing di applicazioni Spring
: fornisce un'estensione di TestCase che carica
automaticamente il context di Spring



Transactional Testing
: un'altra estensione che

inizia una transazione prima di ogni metodo di
test ed esegue il rollback al completamento.


We get dependency injection of any public setter from an application context. This application
context is loaded by the test framework. All we need to do is speci
fy the name for it in the
getConfigLocations
method. We also get an opportunity to prepare our database with the
appropriate test data in the
onSetUpInTransaction
method. This is important, since we don't know
the state of the database when we run our tests.
As long as the table exists we will clear it and load
what we need for our tests.
Since we are extending a "Transactional" test, any changes we make will
be aut
omatically rolled back once the test finishes.


6

Gestione servizi tramite Spring AOP

6.1.1

Transazioni

Once we add business methods dealing with multiple queries in the same business process, we will
have to use transactions.

Spring provides an extensive range of options for how to provide transaction management. The
reference manual covers this in depth. Here we will make use of one way of providing this using AOP
(Aspect Oriented Programming) in the form of a transaction advi
ce and an ApectJ pointcut to define
where the transactions should be applied.

The pointcut applies to any method called on the ProductManager interface. The advice is a
transaction advice that applies to methods with a name starting with 'save'. The defaul
t transaction
attributes of REQUIRED applies since no other attribute was specified. The advice also applies "read
-
only" transactions on any other methods that are
advised

via the pointcut.


6.1.2

Sicurezza


7

Conclusioni

7.1

Replacing the datasource with a connection

pool

The use of a simple datasource is not adequate for larger applications.
Spring provides apdapters to
connection pools like dbcp or pools coming from JNDI contexts. The latter

is provided by Tomcat,
JBoss, Websphere etc.


8

Bibliografia