Programação de Servlets

Aplicação de Compras On-line

O Problema: Aplicação de Compras On-line

A Demo

A Teoria necessária sobre Servlets e Java para Resolver o Problema

Mais informação sobre o ServletContext

      contexto.log(String memnsagem);
  // num Servlet qualquer
  contexto = getServletContext();

  // num ContextListener que recebeu um evento
  contexto = event.getServletContext();

  // num filtro (ver adiante)
  contexto = filterConfig.getServletContext();

Definição de páginas de erro

wpe2.jpg (114416 bytes)

Incluindo o conteúdo de outro recurso na resposta

  // Obtém o dispatcher; ele vai mandar o banner para o usuário
  RequestDispatcher dispatcher =
      getServletContext().getRequestDispatcher("/banner");
  if (dispatcher != null) {
    dispatcher.include(request, response);
  }
import java.io.*;
import java.util.*;
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;

import database.*;
import cart.*;

public class BannerServlet extends HttpServlet { 

  public void service (HttpServletRequest request,
                     HttpServletResponse response)
                     throws ServletException, IOException {
    PrintWriter out = response.getWriter();
    out.println("<body  bgcolor=\"#ffffff\">" +
                "<center>" +
                "<hr> <br> &nbsp;" +
                "<h1>" +
                "<font size=\"+3\" color=\"#CC0066\">Duke's </font> <img src=\"" + request.getContextPath() + "/duke.books.gif\">" + 
                "<font size=\"+3\" color=\"black\">Bookstore</font>" +
                "</h1>" +
                "</center>" +
                "<br> &nbsp; <hr> <br> ");
  }
}
  request.getContextPath() + "/duke.books.gif"

Internacionalização

Locales

Resource Bundles

package messages;

import java.util.*;

public class BookstoreMessages extends ListResourceBundle {
  public Object[][] getContents() {
    return contents;
  }

  static final Object[][] contents = {

  {"ServerError", "Your request cannot be completed.  The server got the following error: "},
  {"TitleServerError", "Server Error"},
  {"TitleShoppingCart", "Shopping Cart"},
  {"What", "What We\'re Reading"},
  // ...
  {"Submit", "Submit Information"},
  {"Catalog", "Back to the Catalog"},
  {"ThankYou", "Thank you for purchasing your books from us "},
  };
}

package messages;

import java.util.*;

public class BookstoreMessages_pt extends ListResourceBundle {
  public Object[][] getContents() {
    return contents;
  }

  static final Object[][] contents = {

  {"ServerError", "Seu pedido não pode ser completado.  O servidor recebeu o seguinte erro: "},
  {"TitleServerError", "Erro de Servidor"},
  {"TitleShoppingCart", "Cesta de Compras"},
  {"What", "O que Estamos Lendo"},
  // ...
  {"Submit", "Submeter Informação"},
  {"Catalog", "Voltar ao Catálogo"},
  {"ThankYou", "Obrigado por comprar seus livros conosco "},
  };
}

public class BookStoreServlet extends HttpServlet {
  // ...
   public void doGet (HttpServletRequest request,
                         HttpServletResponse response)
        throws ServletException, IOException {        
     // ...
     HttpSession session = request.getSession();
     ResourceBundle messages = (ResourceBundle)session.getAttribute("messages");
     if (messages == null) {
       Locale locale=request.getLocale();
       messages = ResourceBundle.getBundle("messages.BookstoreMessages", locale); 
       session.setAttribute("messages", messages);
     }
     // ...
     out.println("<b>" + messages.getString("What") + "</b>");  

Formatação de Números

package util;

import java.text.NumberFormat;
import java.util.*;

public class Currency {

  private Locale locale;
  private double amount;
  public Currency() {
    locale = null;
    amount = 0.0;
  }

  public synchronized void setLocale(Locale l) {
    locale = l;
  }

  public synchronized void setAmount(double a) {
    amount = a;
  }

  public synchronized String getFormat() {
    NumberFormat nf = NumberFormat.getCurrencyInstance(locale);
    return nf.format(amount);
  }
}
public class BookDetailsServlet extends HttpServlet {
    // ...
    // na inicialização
    Currency c = (Currency)session.getAttribute("currency");
    if (c == null) {
      c = new Currency();
      c.setLocale(request.getLocale());
      session.setAttribute("currency", c);
    }
    // ...
    // quando se deseja imprimir o valor de um livro a partir do banco de dados
    c.setAmount(bd.getPrice());
    out.println(... + c.getFormat() + ...);

Filtros de Pedidos e Respostas

filtro1.gif (6213 bytes)

package filters;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class CharResponseWrapper extends HttpServletResponseWrapper {
  private CharArrayWriter output;

  public String toString() {
    return output.toString();
  }
      
  public CharResponseWrapper(HttpServletResponse response) {
    super(response);
    output = new CharArrayWriter();
  }

  public PrintWriter getWriter() {
    return new PrintWriter(output);
  }
}
package filters;

import java.io.*;
import java.sql.Timestamp;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import util.Counter;

public final class HitCounterFilter implements Filter {
  private FilterConfig filterConfig = null;

  public void init(FilterConfig filterConfig) throws ServletException {
    this.filterConfig = filterConfig;
  }
  
  public void destroy() {
    this.filterConfig = null;
  }

  public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain chain) throws IOException, ServletException {

    if (filterConfig == null)
      return;

    HttpServletRequest hr = (HttpServletRequest)request;
    HttpSession session = hr.getSession();
    ResourceBundle messages = (ResourceBundle)session.getAttribute("messages");
    if (messages == null) {
      Locale locale=request.getLocale();
      messages = ResourceBundle.getBundle("messages.BookstoreMessages", locale); 
      session.setAttribute("messages", messages);
    }
    StringWriter sw = new StringWriter();
    PrintWriter writer = new PrintWriter(sw);

    Counter counter = (Counter)filterConfig.getServletContext().getAttribute("hitCounter");
    writer.println();
    writer.println("=======================================================");
    writer.println("The number of hits is: " + counter.incCounter());
    writer.println("=======================================================");

    // Log the resulting string
    writer.flush();
    filterConfig.getServletContext().log(sw.getBuffer().toString());

    PrintWriter out = response.getWriter();
    CharResponseWrapper wrapper = new CharResponseWrapper((HttpServletResponse)response); 
    chain.doFilter(request, wrapper);
    CharArrayWriter caw = new CharArrayWriter();
    caw.write(wrapper.toString().substring(0, wrapper.toString().indexOf("</body>")-1));
    caw.write("<p>\n<center><center>" + messages.getString("Visitor") + "<font color='red'>" + counter.getCounter() + "</font><center>");
    caw.write("\n</body></html>");
    response.setContentLength(caw.toString().length());
    out.write(caw.toString());        
    out.close();
  }

  public String toString() {
    if (filterConfig == null)  
      return ("HitCounterFilter()");
    StringBuffer sb = new StringBuffer("HitCounterFilter(");
    sb.append(filterConfig);
    sb.append(")");
    return (sb.toString());
  }
}

Manutenção do estado do cliente: o conceito de Sessão

Acesso à sessão

Associação de atributos à sessão

public class CashierServlet extends HttpServlet { 
  public void doGet (HttpServletRequest request,
                     HttpServletResponse response)
                     throws ServletException, IOException {

    // Get the user's session and shopping cart
    HttpSession session = request.getSession();
    ResourceBundle messages = (ResourceBundle)session.getAttribute("messages");

    ShoppingCart cart = (ShoppingCart)session.getAttribute("cart");
    if (cart == null) {
      cart = new ShoppingCart();
      session.setAttribute("cart", cart);
    }
    // ...
    double total = cart.getTotal();
    // ...

Gerência de sessão

public class ReceiptServlet extends HttpServlet { 
  public void doPost(HttpServletRequest request,
                     HttpServletResponse response)
                     throws ServletException, IOException {

    // Get the user's session and shopping cart
    HttpSession session = request.getSession(true);
    ResourceBundle messages = (ResourceBundle)session.getAttribute("messages");

    // Payment received -- invalidate the session
    session.invalidate();
    // ...

Implementação do rastreamento de uma sessão

      // Where to go and what to do next
      out.println("<p> &nbsp; <p><strong><a href=\"" +
          response.encodeURL(request.getContextPath() + "/catalog") +
          "\">" + messages.getString("ContinueShopping") + "</a> &nbsp; &nbsp; &nbsp;" +
                        
          "<a href=\"" +
          response.encodeURL(request.getContextPath() + "/cashier") +
          "\">" + messages.getString("Checkout") + "</a> &nbsp; &nbsp; &nbsp;" +
                        
          "<a href=\"" + 
          response.encodeURL(request.getContextPath() + "/showcart?Clear=clear") +
          "\">" + messages.getString("ClearCart") + "</a></strong>");

A Solução

Requisito Solução
  • A aplicação é de compra de livros on-line
  • Solução J2EE com Web Components e browser como cliente
  • O servlet principal de entrada é BookStoreServlet que exibe a primeira página
  • Deve-se exibir o catálogo
  • Servlet chamado CatalogServlet com o catálogo num BD acessado via JDBC
  • O catálogo deve poder fornecer detalhes sobre um livro
  • Servlet chamado BookDetailsServlet acessando o BD. O servlet é chamado com URL especial /bookdetails?bookId=<bookId>
  • Deve-se permitir colocar itens numa cesta de compras
  • A cesta de compras é armazenada na sessão
  • Deve ser possível comprar mais de uma cópia de um livro
  • A cesta de compras sabe diferenciar entre um novo item sendo adicionado e incrementar a quantidade de um item já presente
  • Deve haver uma forma de verificar o conteúdo da cesta de compras
  • Servlet chamado ShowCartServlet
  • Deve-se permitir remover itens da cesta de compras
  • Servlet chamado ShowCartServlet com URL especial /showcart?Remove=<bookId>
  • Para esvaziar a cesta, a URL é /showcart?Clear=clear
  • Deve-se permitir que o usuário se encaminhe para o caixa para pagar os livros
  • Servlet chamado CashierServlet
  • Para efetuar a compra, o usuário deve fornecer seu nome e número de cartão de crédito
  • Servlet chamado CashierServlet produz uma página com formulário para recolher a informação
  • A aplicação não precisa contactar um site de aprovação de crédito mas deve manter um log de cada compra
  • O servlet ReceiptServlet estará sujeito a uma cadeia de filtro (filter chain) e um filtro tratará de logar a informação com contexto.log(...)
  • A primeira página deve fornecer o link de um livro que o staff da livraria está lendo
  • Hardcoded no servlet BookStoreServlet
  • A informação mantida para cada livro é:
    • Identificação única
    • Sobrenome do autor
    • Primeiro nome do autor
    • Título do livro
    • O preço do livro
    • O ano de publicação do livro
    • Uma descrição do livro
  • Isso afeta a definição do Banco de Dados (BookDB) mantido no Cloudscape
  • A aplicação deve exibir páginas em inglês ou português ou espanhol, dependendo das preferências do browser do usuário
  • Uso de ResourceBundles com escolha baseada na Locale
    • BookstoreMessages (inglês)
    • BookstoreMessages_pt (português)
    • BookstoreMessages_es (espanhol)
  • Os preços dos livros devem ser exibidos na moeda local, isto é dependendo das preferências do browser do usuário
  • Uso de NumberFormat.getCurrencyInstance(locale)
  • Todas as páginas exibidas deve iniciar com um banner comum
  • Cada servlet chama (inclui) o BannerServlet
  • A primeira página deve fornecer um contador de hits de visitas
  • O BookStoreServlet faz parte de um filter chain com um filtro tratando de inserir o contador depois que o servlet gerou sua informação
  • Deve haver um log das visitas
  • O mesmo filtro acima (que insere um contador de visitas) também as loga usando contexto.log(...)
  • Uma página de erro adequada deve ser exibida na ocorrência de problemas
  • Uma página errorpage.html dizendo que a aplicação não está disponível será usada e associada aos Web Components durante a composição da aplicação

O package util

Classe Currency

import java.text.NumberFormat;
import java.util.*;

public class Currency {

  private Locale locale;
  private double amount;
  public Currency() {
    locale = null;
    amount = 0.0;
  }

  public synchronized void setLocale(Locale l) {
    locale = l;
  }

  public synchronized void setAmount(double a) {
    amount = a;
  }

  public synchronized String getFormat() {
    NumberFormat nf = NumberFormat.getCurrencyInstance(locale);
    return nf.format(amount);
  }
}

Classe Counter

package util;

public class Counter {
  private int counter;
  public Counter() {
    counter = 0;
  }
  public synchronized int getCounter() {
    return counter;
  }
  public synchronized int setCounter(int c) {
    counter = c;
    return counter;
  }
  public synchronized int incCounter() {
    return(++counter);
  }
}

O package messages

O package listeners

package listeners;

import database.BookDB;
import javax.servlet.*;
import util.Counter;

public final class ContextListener
  implements ServletContextListener {
  private ServletContext context = null;

  public void contextInitialized(ServletContextEvent event) {
    context = event.getServletContext();
    
    try {
      BookDB bookDB = new BookDB();
      context.setAttribute("bookDB", bookDB);
    } catch (Exception ex) {
      context.log("Couldn't create bookstore database bean: " + ex.getMessage());
    }

    context.setAttribute("hitCounter", new Counter());
    context.setAttribute("orderCounter", new Counter());
  }
    
  public void contextDestroyed(ServletContextEvent event) {
    context = event.getServletContext();
    BookDB bookDB = (BookDB)context.getAttribute("bookDB");
    bookDB.remove();
    context.removeAttribute("bookDB");
    context.removeAttribute("hitCounter");
    context.removeAttribute("orderCounter");
  }
}

O package database

package database;

import java.sql.*;
import javax.sql.*;
import javax.naming.*;
import java.util.*;
import exception.*;

public class BookDB {

  private ArrayList books;
  Connection con;
  private String dbName = "java:comp/env/jdbc/BookDB";

  public BookDB () throws Exception {
    try  {               
      InitialContext ic = new InitialContext();
      DataSource ds = (DataSource) ic.lookup(dbName);
      con =  ds.getConnection();     
    } catch (Exception ex) {
      throw new Exception("Couldn't open connection to database: " + ex.getMessage());
    }	 	
  }
    
  public void remove () {
    try {
      con.close();
    } catch (SQLException ex) {
      System.out.println(ex.getMessage());
    }
  }
    
  public int getNumberOfBooks() throws BooksNotFoundException {
    return getBooks().size();
  }

  public Collection getBooks() throws BooksNotFoundException {
 		books = new ArrayList();
    try {
      String selectStatement = "select * from books";
      PreparedStatement prepStmt = con.prepareStatement(selectStatement);
      ResultSet rs = prepStmt.executeQuery();
      while (rs.next()) {
        BookDetails bd = new BookDetails(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), 
                                         rs.getFloat(5), rs.getInt(6), rs.getString(7));
        books.add(bd);
      }
      prepStmt.close();
    } catch (SQLException ex) {
      throw new BooksNotFoundException(ex.getMessage());
    }

    Collections.sort(books);
    return books;
  }

  public BookDetails getBookDetails(String bookId) throws BookNotFoundException {
    try {
      String selectStatement = "select * from books where id = ? ";
      PreparedStatement prepStmt = con.prepareStatement(selectStatement);
      prepStmt.setString(1, bookId);
      ResultSet rs = prepStmt.executeQuery();
      if (rs.next()) {
        BookDetails bd = new BookDetails(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), 
                                         rs.getFloat(5), rs.getInt(6), rs.getString(7));
        prepStmt.close();
        return bd;
      } else {					
        prepStmt.close();
        throw new BookNotFoundException("Couldn't find book: " + bookId);
      }
    } catch (SQLException ex) {
      throw new BookNotFoundException("Couldn't find book: " + bookId + ex.getMessage());
    }
  }
}

package database;

public class BookDetails implements Comparable {
  private String bookId = null;
  private String title = null;
  private String firstName = null;
  private String surname = null;
  private float price = 0.0F;
  private int year = 0;
  private String description = null;
  
  public BookDetails(String bookId, String surname, String firstName, String title, 
                     float price, int year, String description) {
    this.bookId = bookId;
    this.title = title;
    this.firstName =  firstName;
    this.surname = surname;
    this.price = price;
    this.year = year;
    this.description = description;
  }

  public String getTitle() {
    return title;
  }
  
  public float getPrice() {
    return price;
  }

  public int getYear() {
    return year;
  }

  public String getDescription() {
    return description;
  }

  public String getBookId() {
    return this.bookId;
  }

  public String getFirstName() {
    return this.firstName;
  }

  public String getSurname() {
    return this.surname;
  }
  public int compareTo(Object o) {
     BookDetails n = (BookDetails)o;
     int lastCmp = title.compareTo(n.title);
     return (lastCmp);
  }		
}

O package cart

package cart;

import java.util.*;
import database.BookDetails;
 
public class ShoppingCart {
  HashMap items = null;
  int numberOfItems = 0;

  public ShoppingCart() {
    items = new HashMap();
  }

  public synchronized void add(String bookId, BookDetails book) {
    if(items.containsKey(bookId)) {
      ShoppingCartItem scitem = (ShoppingCartItem) items.get(bookId);
      scitem.incrementQuantity();
    } else {
      ShoppingCartItem newItem = new ShoppingCartItem(book);
      items.put(bookId, newItem);
    }

    numberOfItems++;
  }

  public synchronized void remove(String bookId) {
    if(items.containsKey(bookId)) {
      ShoppingCartItem scitem = (ShoppingCartItem) items.get(bookId);
      scitem.decrementQuantity();

      if(scitem.getQuantity() <= 0)
        items.remove(bookId);

      numberOfItems--;
    }
  }

  public synchronized Collection getItems() {
    return items.values();
  }

  protected void finalize() throws Throwable {
    items.clear();
  }

  public synchronized int getNumberOfItems() {
    return numberOfItems;
  }
  public synchronized double getTotal() {
    double amount = 0.0;

    for(Iterator i = getItems().iterator(); i.hasNext(); ) {
      ShoppingCartItem item = (ShoppingCartItem) i.next();
      BookDetails bookDetails = (BookDetails) item.getItem();

      amount += item.getQuantity() * bookDetails.getPrice();
    }
    return roundOff(amount);
  }

  private double roundOff(double x) {
    long val = Math.round(x*100); // cents
    return val/100.0;
  }

  public synchronized void clear() {
    items.clear();
    numberOfItems = 0;
  }
}

package cart;

public class ShoppingCartItem {
  Object item;
  int quantity;

  public ShoppingCartItem(Object anItem) {
    item = anItem;
    quantity = 1;
  }

  public void incrementQuantity() {
    quantity++;
  }

  public void decrementQuantity() {
    quantity--;
  }

  public Object getItem() {
    return item;
  }

  public int getQuantity() {
    return quantity;
  }
}

O package filters

package filters;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class CharResponseWrapper extends HttpServletResponseWrapper {
  private CharArrayWriter output;

  public String toString() {
    return output.toString();
  }
    
  public CharResponseWrapper(HttpServletResponse response) {
    super(response);
    output = new CharArrayWriter();
  }

  public PrintWriter getWriter() {
    return new PrintWriter(output);
  }
}
package filters;

import java.io.*;
import java.sql.Timestamp;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import util.Counter;

public final class HitCounterFilter implements Filter {
  private FilterConfig filterConfig = null;

  public void init(FilterConfig filterConfig) throws ServletException {
    this.filterConfig = filterConfig;
  }
  
  public void destroy() {
    this.filterConfig = null;
  }

  public void doFilter(ServletRequest request, ServletResponse response,
                       FilterChain chain)
                       throws IOException, ServletException {

    if (filterConfig == null)
      return;

    HttpServletRequest hr = (HttpServletRequest)request;
    HttpSession session = hr.getSession();
    ResourceBundle messages = (ResourceBundle)session.getAttribute("messages");
    if (messages == null) {
      Locale locale=request.getLocale();
      messages = ResourceBundle.getBundle("messages.BookstoreMessages", locale); 
      session.setAttribute("messages", messages);
    }
    StringWriter sw = new StringWriter();
    PrintWriter writer = new PrintWriter(sw);

    Counter counter = (Counter)filterConfig.getServletContext().getAttribute("hitCounter");
    writer.println();
    writer.println("=======================================================");
    writer.println("The number of hits is: " + counter.incCounter());
    writer.println("=======================================================");

    // Log the resulting string
    writer.flush();
    filterConfig.getServletContext().log(sw.getBuffer().toString());

    PrintWriter out = response.getWriter();
    CharResponseWrapper wrapper = new CharResponseWrapper((HttpServletResponse)response); 
    chain.doFilter(request, wrapper);
    CharArrayWriter caw = new CharArrayWriter();
    caw.write(wrapper.toString().substring(0, wrapper.toString().indexOf("</body>")-1));
    caw.write("<p>\n<center><center>" + messages.getString("Visitor") + "<font color='red'>" + counter.getCounter() + "</font><center>");
    caw.write("\n</body></html>");
    response.setContentLength(caw.toString().length());
    out.write(caw.toString());        
    out.close();
  }

  public String toString() {
    if (filterConfig == null)  
      return ("HitCounterFilter()");
    StringBuffer sb = new StringBuffer("HitCounterFilter(");
    sb.append(filterConfig);
    sb.append(")");
    return (sb.toString());
  }
}
package filters;

import java.io.*;
import java.sql.Timestamp;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import database.BookDetails;
import cart.*;
import util.*;

public final class OrderFilter implements Filter {

  private FilterConfig filterConfig = null;

  public void init(FilterConfig filterConfig) throws ServletException {
      this.filterConfig = filterConfig;
  }

  public void destroy() {
    this.filterConfig = null;
  }
  public void doFilter(ServletRequest request, ServletResponse response,
                       FilterChain chain)
                       throws IOException, ServletException {

    if (filterConfig == null)
        return;
  
    // Render the generic servlet request properties
    StringWriter sw = new StringWriter();
    PrintWriter writer = new PrintWriter(sw);
    ServletContext context = filterConfig.getServletContext();
    Counter counter = (Counter)context.getAttribute("orderCounter");
    HttpServletRequest hsr = (HttpServletRequest)request;
    HttpSession session = hsr.getSession();
    ShoppingCart cart = (ShoppingCart)session.getAttribute("cart");
    Currency c = (Currency)session.getAttribute("currency");
    c.setAmount(cart.getTotal());
    writer.println();
    writer.println("=======================================================");
    writer.println("The total number of orders is: " + counter.incCounter());
    writer.println("This order Received at " +
        (new Timestamp(System.currentTimeMillis())));
    writer.println();
    writer.print("Purchased by: " + request.getParameter("cardname"));
    writer.println();
    writer.print("Total: "  + c.getFormat());
    writer.println();
          
    int num = cart.getNumberOfItems();
    if (num > 0) {
      Iterator i = cart.getItems().iterator();
      while (i.hasNext()) {
        ShoppingCartItem item = (ShoppingCartItem) i.next();
        BookDetails bookDetails = (BookDetails) item.getItem();
        writer.print("ISBN: "  + bookDetails.getBookId());
        writer.print("   Title: "  + bookDetails.getTitle());
        writer.print("   Quantity: " + item.getQuantity());
        writer.println();       
      }
    }
  
  
    writer.println("=======================================================");
  
    // Log the resulting string
    writer.flush();
    context.log(sw.getBuffer().toString());
    chain.doFilter(request, response);
  }

  public String toString() {
    if (filterConfig == null)
      return ("OrderFilter()");
    StringBuffer sb = new StringBuffer("OrderFilter(");
    sb.append(filterConfig);
    sb.append(")");
    return (sb.toString());
  }
}
...
BookStoreServlet: init

=======================================================
The number of hits is: 1
=======================================================

BannerServlet: init
CatalogServlet: init
BookDetailsServlet: init
ShowCartServlet: init
CashierServlet: init
ReceiptServlet: init

=======================================================
The total number of orders is: 1
This order Received at 2001-10-20 14:53:20.695

Purchased by: Gwen Canigetit
Total: R$ 32,25
ISBN: 208   Title: Duke: A Biography of the Java Evangelist   Quantity: 2
ISBN: 205   Title: From Oak to Java: The Revolution of a Language   Quantity: 1
=======================================================


=======================================================
The number of hits is: 2
=======================================================


=======================================================
The total number of orders is: 2
This order Received at 2001-10-20 14:55:00.669

Purchased by: Gwen Canigetit
Total: R$ 10,75
ISBN: 208   Title: Duke: A Biography of the Java Evangelist   Quantity: 1
=======================================================


=======================================================
The number of hits is: 3
=======================================================


=======================================================
The total number of orders is: 3
This order Received at 2001-10-20 18:51:10.704

Purchased by: papi
Total: R$ 82,25
ISBN: 201   Title: My Early Years: Growing up on *7   Quantity: 1
ISBN: 208   Title: Duke: A Biography of the Java Evangelist   Quantity: 1
ISBN: 207   Title: The Green Project: Programming for Consumer Devices   Quantity: 1
ISBN: 206   Title: Java Intermediate Bytecodes   Quantity: 1
ISBN: 205   Title: From Oak to Java: The Revolution of a Language   Quantity: 1
ISBN: 203   Title: Web Components for Web Developers   Quantity: 1
ISBN: 202   Title: Web Servers for Fun and Profit   Quantity: 1
=======================================================


=======================================================
The number of hits is: 4
=======================================================

Os servlets

Servlet Alias
BookStoreServlet /enter
BannerServlet /banner
CatalogServlet /catalog
BookDetailsServlet /bookdetails
ShowCartServlet /showcart
CashierServlet /cashier
ReceiptServlet /receipt

O servlet BookStoreServlet

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import database.*;
import exception.*;
/**
 * An HTTP Servlet that overrides the service method to return a
 * simple web page.
 */
public class BookStoreServlet extends HttpServlet {

  private BookDB bookDB;

  public void init() throws ServletException {
    bookDB = (BookDB)getServletContext().getAttribute("bookDB");
    if (bookDB == null)
      throw new UnavailableException("Couldn't get database.");
    }

  public void destroy() {
    bookDB.remove();
    bookDB = null;
  }

      
  public void doGet (HttpServletRequest request,
                     HttpServletResponse response)
                     throws ServletException, IOException {        
            
    HttpSession session = request.getSession();
    ResourceBundle messages = (ResourceBundle)session.getAttribute("messages");
    if (messages == null) {
      Locale locale=request.getLocale();
      messages = ResourceBundle.getBundle("messages.BookstoreMessages", locale); 
      session.setAttribute("messages", messages);
    }
    
    
    // set content-type header before accessing the Writer
    response.setContentType("text/html");
    response.setBufferSize(8192);
    PrintWriter out = response.getWriter();
      
    // then write the data of the response
    out.println("<html>" +
                "<head><title>Duke's Bookstore</title></head>");

    // Get the dispatcher; it gets the banner to the user
    RequestDispatcher dispatcher =
        getServletContext().getRequestDispatcher("/banner");
                                     
    if (dispatcher != null)
      dispatcher.include(request, response);
                                   
    try {      
      BookDetails bd = bookDB.getBookDetails("203");      
       
      //Left cell -- the "book of choice"
      out.println("<b>" + messages.getString("What") + "</b>" +
                  "<p>" + "<blockquote>" + 
                         "<em><a href=\"" +
                  response.encodeURL(request.getContextPath() + "/bookdetails?bookId=203") +
                  "\">" + bd.getTitle() + "</a></em>" + messages.getString("Talk") + "</blockquote>");
      
      //Right cell -- various navigation options
      out.println("<p><a href=\"" +
                  response.encodeURL(request.getContextPath() + "/catalog") +
                  "\"><b>" + messages.getString("Start") + "</b></a></font><br>" +
                  "<br> &nbsp;" +
                  "<br> &nbsp;" +
                  "<br> &nbsp;" +
                  "</body>" +
                  "</html>");
    } catch (BookNotFoundException ex) {
      response.resetBuffer();
      throw new ServletException(ex);
    }
    out.close();
  }

  public String getServletInfo() {
    return "The BookStore servlet returns the main web page " +
           "for Duke's Bookstore.";
  }
}

O servlet BannerServlet

import java.io.*;
import java.util.*;
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;

import database.*;
import cart.*;

/**
 * This is a simple example of an HTTP Servlet.  It responds to the GET
 * method of the HTTP protocol.
 */

public class BannerServlet extends HttpServlet { 

  public void doGet (HttpServletRequest request,
                     HttpServletResponse response)
                     throws ServletException, IOException {
    writeBanner(request, response);
  }

  public void doPost (HttpServletRequest request,
                      HttpServletResponse response)
                      throws ServletException, IOException {
    writeBanner(request, response);
  }

  private void writeBanner (HttpServletRequest request,
                            HttpServletResponse response)
                            throws IOException {
    PrintWriter out = response.getWriter();
    out.println("<body  bgcolor=\"#ffffff\">" +
                "<center>" +
                "<hr> <br> &nbsp;" +
                "<h1>" +
                "<font size=\"+3\" color=\"#CC0066\">Duke's </font> <img src=\"" + request.getContextPath() + "/duke.books.gif\">" + 
                "<font size=\"+3\" color=\"black\">Bookstore</font>" +
                "</h1>" +
                "</center>" +
                "<br> &nbsp; <hr> <br> ");
  }
}

O servlet CatalogServlet

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

import database.*;
import cart.*;
import util.Currency;
import exception.*;

/**
 * This is a simple example of an HTTP Servlet.  It responds to the GET
 * method of the HTTP protocol.
 */
public class CatalogServlet extends HttpServlet { 
  private BookDB bookDB;

  public void init() throws ServletException {
    bookDB = (BookDB)getServletContext().getAttribute("bookDB");
    if (bookDB == null)
      throw new UnavailableException("Couldn't get database.");
  }

  public void destroy() {
    bookDB.remove();
    bookDB = null;
  }
     
  public void doGet (HttpServletRequest request,
                     HttpServletResponse response)
                     throws ServletException, IOException {

    // Get the user's session and shopping cart
    HttpSession session = request.getSession(true);
    ResourceBundle messages = (ResourceBundle)session.getAttribute("messages");

    ShoppingCart cart = (ShoppingCart)session.getAttribute("cart");

    // If the user has no cart, create a new one
    if (cart == null) {
      cart = new ShoppingCart();
      session.setAttribute("cart", cart);
    }
    // set content-type header before accessing the Writer
    response.setContentType("text/html");
    response.setBufferSize(8192);
    PrintWriter out = response.getWriter();

    // then write the data of the response
    out.println("<html>" +
                "<head><title>" + messages.getString("TitleBookCatalog") + "</title></head>");

    // Get the dispatcher; it gets the banner to the user
    RequestDispatcher dispatcher =
        getServletContext().getRequestDispatcher("/banner");
                                   
    if (dispatcher != null)
      dispatcher.include(request, response);
           

    //Information on the books is from the database through its front end

    // Additions to the shopping cart
    String bookId = request.getParameter("bookId");
    if (bookId != null) {
      try {
        BookDetails book = bookDB.getBookDetails(bookId);
        cart.add(bookId, book);
        out.println("<p><h3>" + "<font color=\"#ff0000\">" + messages.getString("CartAdded1") + 
         						"<i>" + book.getTitle() + "</i> " + 
                    messages.getString("CartAdded2") + "</font></h3>");
      } catch (BookNotFoundException ex) {
        response.reset();
        throw new ServletException(ex);
      }
    }

    //Give the option of checking cart or checking out if cart not empty
    if (cart.getNumberOfItems() > 0) {
      out.println("<p><strong><a href=\"" +
                  response.encodeURL(request.getContextPath() + "/showcart") +
                  "\">" + messages.getString("CartCheck") + "</a>&nbsp;&nbsp;&nbsp;" +
                  "<a href=\"" +
                  response.encodeURL(request.getContextPath() + "/cashier") +
                  "\">" + messages.getString("Buy") + "</a>" +
                  "</p></strong>");
    }

    // Always prompt the user to buy more -- get and show the catalog
    out.println("<br> &nbsp;" +
                "<h3>" + messages.getString("Choose") + "</h3>" +
                "<center> <table>");
    
    try {
      Collection coll = bookDB.getBooks();
      Iterator i = coll.iterator();
      Currency c = (Currency)session.getAttribute("currency");
      if (c == null) {
        c = new Currency();
        c.setLocale(request.getLocale());
        session.setAttribute("currency", c);
      }
      while (i.hasNext()) {
        BookDetails book = (BookDetails)i.next();
        bookId = book.getBookId();
        c.setAmount(book.getPrice());
    
        //Print out info on each book in its own two rows
        out.println("<tr>" +

                    "<td bgcolor=\"#ffffaa\">" +
                    "<a href=\"" +
                    response.encodeURL(request.getContextPath() + "/bookdetails?bookId=" + bookId) +
                    "\"> <strong>" + book.getTitle() +
                    "&nbsp; </strong></a></td>" +

                    "<td bgcolor=\"#ffffaa\" rowspan=2>" +
                    c.getFormat() +
                    "&nbsp; </td>" +

                    "<td bgcolor=\"#ffffaa\" rowspan=2>" +
                    "<a href=\"" +
                    response.encodeURL(request.getContextPath() + "/catalog?bookId=" + bookId)
                    + "\"> &nbsp;" + messages.getString("CartAdd") + "&nbsp;</a></td></tr>" +

                    "<tr>" +
                    "<td bgcolor=\"#ffffff\">" +
                    "&nbsp; &nbsp;" + messages.getString("By") + "<em> " + book.getFirstName() +
                    " " + book.getSurname() + "</em></td></tr>");
      }

    } catch (BooksNotFoundException ex) {
       response.reset();
       throw new ServletException(ex);
    }
    out.println("</table></center></body></html>");
    out.close();
  }

  public String getServletInfo() {
    return "The Catalog servlet adds books to the user's " +
           "shopping cart and prints the catalog.";
  }
}

O servlet BookDetailsServlet

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import database.*;
import cart.*;
import util.Currency;
import exception.*;

/**
 * This is a simple example of an HTTP Servlet.  It responds to the GET
 * method of the HTTP protocol. 
 */
public class BookDetailsServlet extends HttpServlet {

  private BookDB bookDB;

  public void init() throws ServletException {
    bookDB = (BookDB)getServletContext().getAttribute("bookDB");
    if (bookDB == null)
      throw new UnavailableException("Couldn't get database.");
  }

  public void destroy() {
    bookDB = null;
  }

      
  public void doGet (HttpServletRequest request,
                     HttpServletResponse response)
                     throws ServletException, IOException {

    HttpSession session = request.getSession(true);
    ResourceBundle messages = (ResourceBundle)session.getAttribute("messages");

    // set headers and buffer size before accessing the Writer
    response.setContentType("text/html");
    response.setBufferSize(8192);
    PrintWriter out = response.getWriter();

    // then write the response
    out.println("<html>" +
                "<head><title>" + messages.getString("TitleBookDescription") + "</title></head>");

    // Get the dispatcher; it gets the banner to the user
    RequestDispatcher dispatcher =
        getServletContext().getRequestDispatcher("/banner");
                                   
    if (dispatcher != null)
      dispatcher.include(request, response);
           
    //Get the identifier of the book to display
    String bookId = request.getParameter("bookId");
    if (bookId != null) {

      // and the information about the book
      try {
        BookDetails bd = bookDB.getBookDetails(bookId);
        Currency c = (Currency)session.getAttribute("currency");
        if (c == null) {
          c = new Currency();
          c.setLocale(request.getLocale());
          session.setAttribute("currency", c);
        }
        c.setAmount(bd.getPrice());
       
       
        //Print out the information obtained
        out.println("<h2>" + bd.getTitle() + "</h2>" +
                    "&nbsp;" + messages.getString("By") + " <em>" + bd.getFirstName() + " " +
                    bd.getSurname() + "</em> &nbsp; &nbsp; " +
                    "(" + bd.getYear() + ")<br> &nbsp; <br>" +
                    "<h4>" + messages.getString("Critics")+ "</h4>" +
                    "<blockquote>" + bd.getDescription() +
                    "</blockquote>" +
                    "<h4>" + messages.getString("Price") + c.getFormat() + "</h4>" +
                    "<p><strong><a href=\"" +
                    response.encodeURL(request.getContextPath() + "/catalog?bookId=" + bookId) +
                    "\">" + messages.getString("CartAdd") + "</a>&nbsp;&nbsp;&nbsp;" +
                    "<a href=\"" + 
                    response.encodeURL(request.getContextPath() + "/catalog") + "\">" + messages.getString("ContinueShopping") + "</a></p></strong>");
      } catch (BookNotFoundException ex) {
        response.resetBuffer();
        throw new ServletException(ex);
      }
    }
    out.println("</body></html>");
    out.close();
  }

  public String getServletInfo() {
    return "The BookDetail servlet returns information about" +
           "any book that is available from the bookstore.";
  }
}

O servlet ShowCartServlet

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import database.*;
import cart.*;
import util.Currency;
import exception.*;

/**
 * An HTTP servlet that displays the contents of a customer's shopping
 * cart at Duke's Bookstore.  It responds to the GET and HEAD methods of
 * the HTTP protocol.  This servlet calls other servlets.
 */
public class ShowCartServlet extends HttpServlet { 

  private BookDB bookDB;

  public void init() throws ServletException {
    bookDB = (BookDB)getServletContext().getAttribute("bookDB");
    if (bookDB == null)
      throw new UnavailableException("Couldn't get database.");
  }

  public void destroy() {
    bookDB.remove();
    bookDB = null;
  }

      
  public void doGet (HttpServletRequest request,
                     HttpServletResponse response)
                     throws ServletException, IOException {

    // Get the user's session and shopping cart
    HttpSession session = request.getSession(true);
    ResourceBundle messages = (ResourceBundle)session.getAttribute("messages");

    ShoppingCart cart = (ShoppingCart)session.getAttribute("cart");

    // If the user has no cart, create a new one
    if (cart == null) {
      cart = new ShoppingCart();
      session.setAttribute("cart", cart);
    }

    // set content type header before accessing the Writer
    response.setContentType("text/html");
    response.setBufferSize(8192);
    PrintWriter out = response.getWriter();

    //Print out the response
    out.println("<html>" +
                "<head><title>" + messages.getString("TitleShoppingCart") + "</title></head>" );

    // Get the dispatcher; it gets the banner to the user
    RequestDispatcher dispatcher =
        getServletContext().getRequestDispatcher("/banner");
                                   
    if (dispatcher != null)
      dispatcher.include(request, response);
           
    /* Handle any pending deletes from the shopping cart and
       indicate the outcome as part of the response */
    String bookId = request.getParameter("Remove");
    BookDetails bd;
    if (bookId != null) {
      try {
        bd = bookDB.getBookDetails(bookId);
        cart.remove(bookId);
        out.println("<font color=\"#ff00000\" size=\"+2\">" +
                    messages.getString("CartRemoved") + "<strong>" + bd.getTitle() +
                    "</strong> <br> &nbsp; <br>" +
                    "</font>");
      } catch (BookNotFoundException ex) {
        response.reset();
        throw new ServletException(ex);
      }           
    } else if (request.getParameter("Clear") != null) {
      cart.clear();
      out.println("<font color=\"#ff0000\" size=\"+2\"><strong>" +
                  messages.getString("CartCleared") +
                  "</strong> <br>&nbsp; <br> </font>");
    }

    // Print a summary of the shopping cart
    int num = cart.getNumberOfItems();
    if (num > 0) {
      out.println("<font size=\"+2\">" +
                  messages.getString("CartContents") + num + (num==1 ? messages.getString("CartItem") : messages.getString("CartItems")) +
                  "</font><br>&nbsp;");

        // Return the Shopping Cart 
      out.println("<table>" +
                  "<tr>" +
                  "<th align=left>" + messages.getString("ItemQuantity") + "</TH>" +
                  "<th align=left>" + messages.getString("ItemTitle") + "</TH>" +
                  "<th align=left>" + messages.getString("ItemPrice") + "</TH>" +
                  "</tr>");
      
      Iterator i = cart.getItems().iterator();
      Currency c = (Currency)session.getAttribute("currency");
      if (c == null) {
         c = new Currency();
         c.setLocale(request.getLocale());
         session.setAttribute("currency", c);
      }
      while (i.hasNext()) {
        ShoppingCartItem item = (ShoppingCartItem) i.next();
        bd = (BookDetails) item.getItem();
        c.setAmount(bd.getPrice());
        
        out.println("<tr>" +
                    "<td align=\"right\" bgcolor=\"#ffffff\">" +
                    item.getQuantity() +
                    "</td>" +

                    "<td bgcolor=\"#ffffaa\">" +
                    "<strong><a href=\"" + 
                    response.encodeURL(request.getContextPath() + "/bookdetails?bookId=" + bd.getBookId()) +
                    "\">" + bd.getTitle() + "</a></strong>" +
                    "</td>" +

                    "<td bgcolor=\"#ffffaa\" align=\"right\">" +
                    c.getFormat() +
                    "</td>" +

                    "<td bgcolor=\"#ffffaa\">" +
                    "<strong>" +
                    "<a href=\"" + 
                    response.encodeURL(request.getContextPath() + "/showcart?Remove=" + bd.getBookId()) +
                    "\">" + messages.getString("RemoveItem") + "</a></strong>" +
                    "</td></tr>");
      }

      c.setAmount(cart.getTotal());
      // Print the total at the bottom of the table
      out.println("<tr><td colspan=\"5\" bgcolor=\"#ffffff\">" +
                  "<br></td></tr>" +
                  "<tr>" +
                  "<td colspan=\"2\" align=\"right\"" +
                  "bgcolor=\"#ffffff\">" +
                  messages.getString("Subtotal") + "</td>" +
                  "<td bgcolor=\"#ffffaa\" align=\"right\">" +
                  c.getFormat() + "</td>" +
                  "</td><td><br></td></tr></table>");

      // Where to go and what to do next
      out.println("<p> &nbsp; <p><strong><a href=\"" +
                  response.encodeURL(request.getContextPath() + "/catalog") +
                  "\">" + messages.getString("ContinueShopping") + "</a> &nbsp; &nbsp; &nbsp;" +
                  
                  "<a href=\"" +
                  response.encodeURL(request.getContextPath() + "/cashier") +
                  "\">" + messages.getString("Checkout") + "</a> &nbsp; &nbsp; &nbsp;" +
                  
                  "<a href=\"" + 
                  response.encodeURL(request.getContextPath() + "/showcart?Clear=clear") +
                  "\">" + messages.getString("ClearCart") + "</a></strong>");
    } else {

      // Shopping cart is empty!
      out.println("<font size=\"+2\">" +
                  messages.getString("CartEmpty") + "</font>" +
                  "<br> &nbsp; <br>" +
                  "<center><a href=\"" +
                  response.encodeURL(request.getContextPath() + "/catalog") +
                  "\">" + messages.getString("Catalog") + "</a> </center>");
    }

    out.println("</body> </html>");
    out.close();
  }

  public String getServletInfo() {
    return "The ShowCart servlet returns information about" +
           "the books that the user is in the process of ordering.";
  }
}

O servlet CashierServlet

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import cart.*;
import util.Currency;

/**
 * An HTTP Servlet that responds to the GET method of the
 * HTTP protocol.  It returns a form to the user that gathers data.
 * The form POSTs to another servlet.
 */
public class CashierServlet extends HttpServlet { 

  public void doGet (HttpServletRequest request,
                     HttpServletResponse response)
                     throws ServletException, IOException {
    // Get the user's session and shopping cart
    HttpSession session = request.getSession();
  	ResourceBundle messages = (ResourceBundle)session.getAttribute("messages");

    ShoppingCart cart =
        (ShoppingCart)session.getAttribute("cart");
    if (cart == null) {
      cart = new ShoppingCart();
      session.setAttribute("cart", cart);
    }
    
    // set content-type header before accessing Writer
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    Currency c = (Currency)session.getAttribute("currency");
    if (c == null) {
      c = new Currency();
      c.setLocale(request.getLocale());
      session.setAttribute("currency", c);
    }
    c.setAmount(cart.getTotal());

    // then write the data of the response
    out.println("<html>" +
                "<head><title>" + messages.getString("TitleCashier") + "</title></head>");

    // Get the dispatcher; it gets the banner to the user
    RequestDispatcher dispatcher =
           getServletContext().getRequestDispatcher("/banner");
                                   
    if (dispatcher != null)
      dispatcher.include(request, response);
           
    // Print out the total and the form for the user
    out.println("<p>" + messages.getString("Amount") +
                "<strong>" + c.getFormat() + "</strong>" +
                "<p>" + messages.getString("Purchase") +
                "<form action=\"" +
                response.encodeURL(request.getContextPath() + "/receipt") +
                "\" method=\"post\">" +
                "<table>" +
                "<tr>" +
                "<td><strong>" + messages.getString("Name")+ "</strong></td>" +
                "<td><input type=\"text\" name=\"cardname\"" +
                "value=\"Gwen Canigetit\" size=\"19\"></td>" +
                "</tr>" +
                "<tr>" +
                "<td><strong>" + messages.getString("CCNumber") + "</strong></td>" +
                "<td>" +
                "<input type=\"text\" name=\"cardnum\" " +
                "value=\"xxxx xxxx xxxx xxxx\" size=\"19\"></td>" +
                "</tr>" +
                "<tr>" +
                "<td></td>" +
                "<td><input type=\"submit\"" +
                "value=\"" + messages.getString("Submit") + "\"></td>" +
                "</tr>" +
                "</table>" +
                "</form>" +
                "</body>" +
                "</html>");
    out.close();
  }

  public String getServletInfo() {
    return "The Cashier servlet takes the user's name and " +
           "credit card number so that the user can buy the books.";
  }
}

A página errorpage.html

<html>
<head>
  <title>Server Error</title>
</head>

<body bgcolor="white">
  <h2>The application is unavailable. Please try later.</h2>
</body>
</html>

A Composição da Aplicação

C:\...\src>ant livros
Buildfile: build.xml

init:

livros:
    [mkdir] Created dir: C:\...\build\livros
     [copy] Copying 2 files to C:\...\build\livros
    [javac] Compiling 22 source files to C:\...\build\livros

BUILD SUCCESSFUL

Total time: 7 seconds

O Deployment da Aplicação

Na máquina de deployment

No servidor de banco de dados

DROP TABLE books;

CREATE TABLE books
   (id VARCHAR(8) 
       CONSTRAINT pk_books PRIMARY KEY,
		surname VARCHAR(24),
		first_name VARCHAR(24),
    title VARCHAR(96),
		price FLOAT,
		yr INT,
    description VARCHAR(30));

DELETE FROM books;

INSERT INTO books VALUES('201', 'Duke', '',
 'My Early Years: Growing up on *7',
 10.75, 1995, 'What a cool book.');

INSERT INTO books VALUES('202', 'Jeeves', '',
 'Web Servers for Fun and Profit', 10.75,
 2000, 'What a cool book.');

INSERT INTO books VALUES('203', 'Masterson', 'Webster',
 'Web Components for Web Developers',
 17.75, 2000, 'What a cool book.');

INSERT INTO books VALUES('205', 'Novation', 'Kevin',
 'From Oak to Java: The Revolution of a Language',
 10.75, 1998, 'What a cool book.');

INSERT INTO books VALUES('206', 'Gosling', 'James',
 'Java Intermediate Bytecodes', 10.75,
 2000, 'What a cool book.');

INSERT INTO books VALUES('207', 'Thrilled', 'Ben',
 'The Green Project: Programming for Consumer Devices',
 10.75, 1998, 'What a cool book');

INSERT INTO books VALUES('208', 'Tru', 'Itzal',
 'Duke: A Biography of the Java Evangelist',
 10.75, 2001, 'What a cool book.');

No servidor J2EE

j2ee -stop
j2eeadmin -addJdbcDatasource jdbc/BookDB jdbc:cloudscape:rmi:BookDB;create=true
j2ee -verbose
Binding DataSource, name = jdbc/BookDB, url = jdbc:cloudscape:rmi:BookDB;create=true

Ainda na máquina de deployment

livros programa