Nella lezione precedente abbiamo visto come testare il funzionamento del bean ShoppingCart come singola unità. È evidente che un progetto di web application in ambiente Java enterprise implichi l'utilizzo di interfacce grafiche da mostrare all'utente finale. A partire da questo semplice stateful session bean vogliamo creeremo in questa lezione una web application per mostrare l'integrazione tra la logica di presentazione e la logica di business.
Il componente di base già ce l'abbiamo e supponiamo sia pure installato sull'application server. Ipotizziamo quindi una serie di semplici funzioni di ecommerce per l'inserimento di prodotti nel carrello della spesa e la visualizzazione delle informazioni (come peraltro sottolineato dalle funzioni di business del componente).
In un contesto Java, utilizzeremo le JSP per la rappresentazione e le servlet come componenti di controllo. Partiamo dalla figura che illustra il design del semplice progetto.
Le funzioni di controllo sono definite nella servlet "Controller" che ha il compito di gestire il flusso di operazioni. I metodi che qui dovremo implementare corrispondono alle funzioni predefinite:
- Visualizzazione del carrello (showCart)
- Visualizzazione della lista prodotti (showList)
- Aggiunta di un prodotto al carrello (addCart)
- Creazione del carrello ed associazione alla sessione utente (createCart)
A partire dall'interfaccia Home.jsp, l'utente può richiedere due operazioni: visualizzazione prodotti (showList) e visualizzazione carrello (showCart). Nel primo caso, la servlet recupera dall'oggetto ProductMaker
una collezione di prodotti e la inoltra alla vista AllProds.jsp che si occupa di mostrare la rappresentazione dei prodotti con un link che rimanda all'operazione addCart
per ognuno di essi (cioè aggiunge il prodotto al carrello).
La vista Cart.jsp è inoltrata dalla servlet che si preoccupa di recuperare dalla sessione il carrello utente. La vista recupererà il contenuto del carrello mostrandone i prodotti presenti ed il relativo totale: queste operazioni sono già state viste nell'interfaccia ShoppingCart.
Il codice sorgente della servlet (Controller.java) mostra come è organizzato il flusso di informazioni: ogni metodo effettua una particolare funzione. Sottolineo come l'inizializzazione di oggetti utili durante tutto il ciclo di vita della servlet venga effettuato nel metodo init()
. È inoltre evidente come attraverso la gestione della sessione sia possibile associare un carrello ad ogni utente, riutilizzando la stessa istanza durante tutta la sessione.
Listato 1. Il controller definisce il flusso di operazioni per la gestione del carrello della spesa (Guarda il codice completo)
..//
public class Controller extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
..//
public void init(){
..//
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
..//
//Mostra la lista di prodotti
private void showAllProducts(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
..//
//Crea un carrello anonimo
private void createNewCart(HttpServletRequest request) throws RemoteException, CreateException{
..//
//Aggiungi un prodotto al carrello
private void addProduct(HttpServletRequest request, HttpServletResponse response) throws CreateException, IOException{
..//
//Mostra il carrello della spesa
private void showCart(HttpServletRequest request, HttpServletResponse response) throws CreateException, IOException, ServletException{
..//
}
La classe ProductMaker (ProductMaker.java) simula la presenza di una sorgente dati che si occupa della gestione degli oggetti Product.
Listato 2. Simula la presenza di un gestore di prodotti
package it.html.ejb.session.stateful.data;
import it.html.shop.Product;
import java.util.Collection;
import java.util.Hashtable;
public class ProductMaker {
private Hashtable ht;
public ProductMaker(){
ht=new Hashtable();
Product p1=new Product("P01","Lettore MP4",50);
Product p2=new Product("P02","Radio Stereo",20);
Product p3=new Product("P03","Notebook Ultra 2",780);
Product p4=new Product("P04","Eppol AIFon",399);
ht.put(p1.getId(), p1);
ht.put(p2.getId(), p2);
ht.put(p3.getId(), p3);
ht.put(p4.getId(), p4);
}
//Restituisce il prodotto ID
public Product getProductById(String id){
return (Product) ht.get(id);
}
//Restituisce l'intera lista di prodotti
public Collection getList(){
return ht.values();
}
}
La pagina home.jsp non fa altro che mostrare le funzioni menzionate in maniera statica.
Listato 3. Pagina JSP di introduzione
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Index - Pagina di welcome</title>
</head>
<body>
<h1>Home page</h1>
<p>Benvenuto utente, sono disponibili le seguenti opzioni</p>
<p><a href="Controller?op=showAll">Mostra lista prodotti disponibili</a></p>
<p><a href="Controller?op=showCart">Mostra carrello della spesa</a></p>
</body>
</html>
Le interfacce cart.jsp e allProds.jsp, invece sono costruite dinamicamente, sulla base degli oggetti che vengono loro inoltrati dalla servlet.
Ecco il risultato con l'esecuzione di due sessioni utente.
Il deploy di un componente web può essere fatto in maniera analoga a quanto viene fatto con un web server (Tomcat, ad esempio), quindi copiando la cartella e definendo opportunamente il descrittore web.xml. Alcuni application server però necessitano di un componente compattato e nominato con estensione .war (web archive, vedi appendice D). Gli strumenti di sviluppo lo faranno automaticamente ed è una procedura analoga a quanto viene fatto con i pacchetti jar degli ejb.