Está en la página 1de 59

Primeros pasos usando struts e Hibernate

En esta tutorial demostraremos cmo los struts e Hibernate para persistencia de base de datos se pueden utilizar juntos. Aunque explicamos algo bsico, usted debe probar los tutoriales introductorios primero si es un prinicpiante.

General
Autor: Sebastian Hennebrder http://www.laliluna.de/tutorials.html Tutoriales para los struts, EJB, xdoclet y eclipse. Fecha: Revisado enero, 16 th 2005 Primera Edicin Diciembre, 20 2004 Cdigo fuente: http://www.laliluna.de/assets/tutorials/struts-hibernate-integration-tutorial.zip Uso del cdigo fuente. El cdigo fuente no incluye ninguna biblioteca solo los fuentes. Cree un proyecto web, agregue las bibliotecas manualmente o con la ayuda de MyEclipse y descomprima los fuentes que proporcionamos a su proyecto. Versin del pdf del tutorial : http://www.laliluna.de/assets/tutorials/struts-hibernate-integration-tutorial-es.pdf Herramientas de Desarrollo Eclipse 3.x MyEclipse 3,8 plugin (Una extensin barata y muy poderosa de eclipse para desarrollar aplicaciones web y aplicaciones de EJB (J2EE). Pienso que hay una versin de prueba disponible en MyEclipse.) Base de datos PostgreSQL 8,0 beta o MySQL Servidor de Aplicacin Jboss 3,2,5 Puede utilizar Tomcat aqu si usted quiere.

Importante:
Cuando usted est utilizando Tomcat en forma independiente y no incluido en Jboss, no puede utilizar dos proyectos separados. Esto normalmente trabaja con Jboss mientras que Jboss comparte clases por defecto.

Dos proyectos separados deben desarrollarse como proyecto EAR (MyEclipse - > new J2EE project) Un proyecto EAR puede incluir mltiples proyectos web. Si usted cambi la carga de clases de Jboss, tambin debe utilizar un proyecto EAR!

Tabla de contenidos Primeros pasos usando los struts e Hibernate General Crear un proyecto de la biblioteca Hibernate Creacin del Proyecto de Persistencia Creacin de la base de datos Reparacin del mapeo Hibernate Correccin del mapeo buleano Mejoras al session Factory Prueba de la parte de Hibernate Problema de PostgreSQL Generacin de la lgica del negocio Creacin de una clase para la lgica del negocio Creacin de los dilogos 22 1 1 2 2 6 9 10 10 11 15 16 16

Generacin del archivo de Mapeo de Hibernate y las clases 6

Configuracin de la ruta de construccin de Java 25 Creacin de una pgina de bienvenida por defecto 25 Global Action Forwards y Action Mappings (Acciones de redireccin global y Mapeo de Acciones) 27 Lista de libros 30 Action Mapping y clase Action para la lista de libros Edicin del cdigo fuente de la clase Form Action 32 Edicin del cdigo fuente de la clase Action Muestra de la lista de libros en el archivo jsp. Prueba de la aplicacin 36 Aadir, editar, pedir prestados y suprimir los libros 36 Nuevo Form Bean 36 Caso de uso: editar libro 40 Mapeo de Accin 40 Mtodos de envo de la clase accin 44 Caso de uso: la lista de clientes 47 Edicin del cdigo fuente de la clase Form Action 50 Muestra de la lista de clientes Caso de uso: aadir, editar, suprimir clientes 51 Nuevo Form Bean 53 Edicin del cdigo fuente de la clase Action Edicin del cdigo fuente del archivo jsp 57 Prueba de la aplicacin 58

32 33 33

50 56

Crear un proyecto de la biblioteca Hibernate


Comenzaremos creando y probando un proyecto de Hibernate. El segundo paso es agregar la lgica de negocio y en el ltimo integrar la parte de struts.

Creacin del Proyecto De Persistencia


Cree un nuevo proyecto web. Comencemos. Presione "Ctrl + N" para abrir el dilogo "new...". Cree un proyecto web y seleccione el nombre del proyecto como se muestra abajo.

Agregue las capacidades de Hibernate al hacer clic derecho en la vista del paquete del proyecto .

Compruebe las dos casillas de verificacin para agregar las bibliotecas al proyecto y seleccione crear un nuevo archivo de mapeo hibernate. El archivo de hibernate lleva a cabo la configuracin de sus ajustes y mappings del hibernate.

El paso siguiente es seleccionar un perfil para la conexin para la base de datos. Seleccione el botn "New profile" para crear un nuevo perfil. Cuando el controlador de Postgres falta. Clic en "New driver" para crear un nuevo controlador. Usted necesitar el archivo jar que tenga el driver de la base de datos. Llamamos nuestro perfil de libraryweb. Especifique el nombre del usuario y la contrasea.

Cercirese de que usted tenga marcado la casilla "Copy JDBC driver...". Vamos a utilizar PostgreSQL. No debera ser difcil hacer lo mismo con MySQL u otra base de datos. Cercirese de que tenga el archivo jar del controlador de la base de datos en alguna parte en su disco.

En el paso siguiente usted debe inventar un nombre descriptivo para su SessionFactory.

Qu es un SessionFactory? Hibernate espera que haya una sola instancia de la clase de sesin de Hibernate por cada conexin (thread). Tendra que tener para crear una implementacin de la clase un ThreadLocal. MyEclipse hace esto para usted. La parte difcil es inventar un nombre para l. Si usted no est utilizando MyEclipse heche un vistazo a los fuentes. Reduzca Las Bibliotecas De Hibernate Por defecto MyEclipse incluye una carga pesada de bibliotecas. Algunas de ellas sern solamente necesarias para el desarrollo local otros solamente para implementaciones especiales de cache.

Cuando desea optimizar su desarrollo despus de que aprenda los fundamentos de la transferencia directa de Hibernate bajando Hibernate del website http://www.hibernate.org/ en el directorio lib usted encontrar un README.txt donde explica qu bibliotecas son opcionales. Ahora estamos preparados para comenzar el desarrollo. Abrochese los cinturones, esto ahora ir muy rpido.

Creacin la base de datos


Cree la base de datos y las tablas siguientes. No se olvide de la clave fornea!
Script De PostgreSql CREATE TABLE customer ( id serial NOT NULL, name text, lastname text, age int4, CONSTRAINT customer_pk PRIMARY KEY (id) ) ; CREATE TABLE book ( id serial NOT NULL, title text, author text, customer_fk int4, available bool, CONSTRAINT book_pk PRIMARY KEY (id) ) ; ALTER TABLE book ADD CONSTRAINT book_customer FOREIGN KEY (customer_fk) REFERENCES customer (id) ON UPDATE RESTRICT ON DELETE RESTRICT; Script de MySQL CREATE TABLE customer ( id int( 11 ) NOT NULL AUTO_INCREMENT , name varchar( 255 ) , lastname varchar( 255 ) , age int( 11 ), CONSTRAINT customer_pk PRIMARY KEY (id) ) TYPE=INNODB; CREATE TABLE book( id int( 11 ) NOT NULL AUTO_INCREMENT , title varchar( 255 ) , author varchar( 255 ) , customer_fk int( 11 ), available TINYINT NOT NULL, CONSTRAINT book_pk PRIMARY KEY ( id ), INDEX (customer_fk) ) TYPE=INNODB; ALTER TABLE book ADD CONSTRAINT book_customer FOREIGN KEY ( customer_fk ) REFERENCES customer( id ) ON UPDATE RESTRICT ON DELETE RESTRICT ;

Genere los archivos de mapeo Hibernate y las clases


Abra la vista para examinar DB (MyEclipse). Si usted no puede encontrarlo abra "Show View" y seleccione en el escritorio de MyEclipse el browser de DB.

Abra el perfil de la conexin que usted especific antes.< >

Seleccione las dos tablas que acabamos de crear. Botn derecho y elija "Create Hibernate Mapping".

Seleccione como destino su proyecto LibraryPersistence. Cuando se est utilizando PostgreSQL seleccione la "secuence" como generador de la identificacin. Cuando usted est utilizando MySQL seleccione "native".

Clic en OK, !Ud. es realmente bueno! Acaba de crear su capa de persistencia; -) Ahora veremos ms de cerca en nuestro explorador del paquete para ver qu sucedi. Primero abra el hibernate.cfg.xml. Hay dos nuevas entradas, que especificanddonde se localizan los dos archivos de mapeo. Es una buena idea mantener los archivos de mapeo separados del hibernate.cfg.xml . (lo qu MyEclipse hace realmente para usted.)
<!-- mapping files --> <mapping resource="de/laliluna/library/Book.hbm.xml"/>

<mapping resource="de/laliluna/library/User.hbm.xml"/>

Mire en el archivo de mapeo Book.hbm.xml. En este archivo se especifica el mapeo de la clase y de sus atributos con los campos de la tabla. Incluso se ha reconocido nuestra clave fornea.
<hibernate-mapping package="de.laliluna.library"> <class name="Book" table="book"> <id name="id" column="id" type="java.lang.Integer"> <generator class="sequence"/> </id> <property name="title" column="title" type="java.lang.String" /> <property name="author" column="author" type="java.lang.String" /> <property name="available" column="available" type="java.lang.Byte" /> <many-to-one name="customer" column="customer_fk" class="Customer" /> </class> </hibernate-mapping>

Cuando usted est utilizando MySQL el mapeo es levemente diferente.


<class name="Book" table="book"> <id name="id" column="id" type="java.lang.Integer"> <generator class="native"/> </id> ...

MyEclipse cre dos archivos por clase. El primero es una clase abstracta. (AbstractBook) ser sobreescrito cada vez que usted repita el procedimiento de la importacin. En la segunda clase (libro) usted puede adaptar cualquier cambio que desee realizar. Se genera solamente una vez.

Reparacin del mapeo de Hibernate


Vamos a realizar algunos cambios. Hibernate no genera una relacin del cliente al libro. Agregaremos esto a mano. En el archivo Customer.class agregue lo siguiente.
private List books; /** * @return Returns the books. */ public List getBooks() { return books; } /** * @param books The books to set. */ public void setBooks(List books) { this.books = books; }

En el archivo Customer.hbm.xml tenemos que agregar el mapeo de la variable libros . Agregue la entrada "bag" al archivo.
<hibernate-mapping package="de.laliluna.library"> <class name="Customer" table="customer">

<id name="id" column="id" type="java.lang.Integer"> <generator class="sequence"/> </id> <bag name="books" inverse="false"> <key column="customer_fk" /> <one-to-many class="Book"/> </bag> <property name="name" column="name" type="java.lang.String" /> <property name="lastname" column="lastname" type="java.lang.String" /> <property name="age" column="age" type="java.lang.Integer" /> </class> </hibernate-mapping>

La especificamos como
inverse="false "

Esto especifica que queremos cambiar el atributo en "uno" de la relacin uno a muchos para ser reflejados en la base de datos. Pro ejemplo: customer.getbooks().add(aBook); Deberemos escribir la clave fornea en la tabla Customer. Manualmente cambiar el archivo no es muy bueno pero no hay otra forma aqu. La desventaja de esto es que ser sobreescrito cada vez qye regenere los archivos de mapeo. En nuestro caso no es importante pero en un proyecto grande esto es imposible para usar la autogeneracin de MyEclipse excepto que lo haga al principio. La funcin de importacin es realmente nueva en MyEclipse asi que seguramente habra grandes mejoras en las prximas versiones.

Corrigiendo el mapeo Boolean


La columna bool de postgreSQL es tomada como Byte y como Short cuando se usa MySql. No me pregunte por qu. Esto no es bueno, lo corregiremos. Cambie el mapeo de Hibernate en el archivo file Book.hmb.xml a
<property name="available" column="available" type="java.lang.Boolean" />

Cambie la variable, los getter y setter en el archivo AbstractBook.java a tipo Boolean. private
java.lang.Boolean available; /** * Return the value of the available column. * @return java.lang.Byte */ public java.lang.Boolean getAvailable() { return this.available; } /** * Set the value of the available column. * @param available

*/ public void setAvailable(java.lang.Boolean available) { this.available = available; }

Mejoras al session factory


El session factory generado por MyEclipse no es muy agradable porque deja errores cuando utilice el mtodo session.close(). Session factory espera que utilice el mtodo esttico closeSession() de factory, que realmente fija session a nulo si est cerrado. Pero no hay problema, aqu estn las modificaciones al metodo currentSession de factory.
public static Session currentSession() throws HibernateException { Session session = (Session) threadLocal.get(); /* * [laliluna] 20.12.2004 * we want to use the standard session.close() method and not the closeSession() from this class. * For this we need the following line of code. */ if (session != null && !session.isOpen()) session = null; if (session == null) { if (sessionFactory == null) { try { cfg.configure(CONFIG_FILE_LOCATION); sessionFactory = cfg.buildSessionFactory(); } catch (Exception e) { System.err .println("%%%% Error Creating HibernateSessionFactory %%%%"); e.printStackTrace(); } } session = sessionFactory.openSession(); threadLocal.set(session); } return session; }

Pruebas a la parte Hibernate


Cree una clase nueva.

Hagala como el siguiente ejemplo.


public class LibraryTest { private Session session; private Logger log = Logger.getLogger(this.getClass()); public static void main(String[] args) { /* * hibernate needs log4j. Either specify a log4j.properties file * * PropertyConfigurator.configure ("D:\_projekte\workspace\LibraryPersistence\src\log4j.properties"); * * or alternatively make the following to create a standard configuration * BasicConfigurator.configure(); */ BasicConfigurator.configure(); try { LibraryTest libraryTest = new LibraryTest(); libraryTest.setSession(HibernateSessionFactory.currentSession()); libraryTest.createBook(); libraryTest.createCustomer(); libraryTest.createRelation(); libraryTest.deleteCustomer();

} /** * creates a book and saves it to the db. * */ private void createBook() { System.out.println("############# create book"); try { Transaction tx = session.beginTransaction(); Book book = new Book(); book.setAuthor("Karl"); book.setTitle("Karls biography"); book.setAvailable(Boolean.TRUE); session.save(book); tx.commit(); } catch (HibernateException e) { e.printStackTrace(); } } /** * creates a user and saves it to the db * */ private void createCustomer() { System.out.println("############# create user"); try { Transaction tx = session.beginTransaction(); Customer customer = new Customer(); customer.setLastname("Fitz"); customer.setName("John"); customer.setAge(new Integer(25)); session.save(customer); tx.commit(); } catch (HibernateException e) { e.printStackTrace(); } } /** * creates a book and a user + a relation between the two * */ private void createRelation() { System.out.println("############# create relation"); try { Transaction tx = session.beginTransaction(); Customer customer = new Customer(); customer.setLastname("Schmidt"); customer.setName("Jim"); customer.setAge(new Integer(25)); /* IMPORTANT You must save the customer first, before you can assign him to the book. * Hibernate creates and reads the ID only when you save the entry. * The ID is needed as it is the foreign key */ session.save(customer); Book book = new Book(); book.setAuthor("Gerhard Petter"); book.setTitle("Gerhards biography"); book.setAvailable(Boolean.TRUE); session.save(book); Book book2 = new Book(); book2.setAuthor("Karl May");

libraryTest.listBooks(); // [laliluna] 20.12.2004 always close the session at the end libraryTest.getSession().close(); } catch (HibernateException e) { e.printStackTrace(); }

book2.setTitle("Wildes Kurdistan"); book2.setAvailable(Boolean.TRUE); session.save(book2); session.flush(); book.setCustomer(customer); book2.setCustomer(customer); tx.commit(); // [laliluna] 20.12.2004 the customer is not updated automatically, so we have to refresh him session.refresh(customer); tx = session.beginTransaction(); if (customer.getBooks() != null) { System.out.println("list books"); for (Iterator iter = customer.getBooks().iterator(); iter.hasNext();) { Book element = (Book) iter.next(); System.out.println("customer:" + element.getCustomer()); System.out.println("customer is now:" + element.getCustomer()); } } tx.commit(); } catch (HibernateException e) { e.printStackTrace(); } } private void deleteCustomer() { System.out.println("############# delete customer"); try { Transaction tx = session.beginTransaction(); Customer customer = new Customer(); customer.setLastname("Wumski"); customer.setName("Gerhard"); customer.setAge(new Integer(25)); /* IMPORTANT You must save the customer first, before you can assign him to the book. * Hibernate creates and reads the ID only when you save the entry. * The ID is needed as it is the foreign key */ session.save(customer); Book book = new Book(); book.setAuthor("Tim Tom"); book.setTitle("My new biography"); book.setAvailable(Boolean.TRUE); session.save(book); book.setCustomer(customer); tx.commit(); // [laliluna] 20.12.2004 and now we are going to delete the customer which will set the foreign key in the book table to null tx = session.beginTransaction(); // [laliluna] 20.12.2004 the customer is not updated automatically, so we have to refresh him session.refresh(customer); session.delete(customer); tx.commit(); } catch (HibernateException e) { e.printStackTrace(); } } /** * lists all books in the db * */ private void listBooks() { System.out.println("####### list customers"); Query query; Transaction tx; try {

tx = session.beginTransaction(); query = session.createQuery("select c from Customer as c"); for (Iterator iter = query.iterate(); iter.hasNext();) { Customer element = (Customer) iter.next(); List list = element.getBooks(); System.out.println(element.getName()); if (list == null) System.out.println("list = null"); else { for (Iterator iterator = list.iterator(); iterator.hasNext();) { Book book = (Book) iterator.next(); System.out.println(book.getAuthor()); } } System.out.println(element); } tx.commit(); } catch (HibernateException e1) { e1.printStackTrace(); } System.out.println("####### list books"); try { tx = session.beginTransaction(); query = session.createQuery("select b from Book as b"); for (Iterator iter = query.iterate(); iter.hasNext();) { System.out.println((Book) iter.next()); } tx.commit(); } catch (HibernateException e) { e.printStackTrace(); } } /** * @return Returns the session. */ public Session getSession() { return session; } /** * @param session The session to set. */ public void setSession(Session session) { this.session = session; } }

Botn derecho sobre la clase y seleccione Run -> Java Application.

Y al menos cuando se usa PostgreSQL, obtendremos unos cuantos errores. ;-) java.sql.SQLException: ERROR: relation "hibernate_sequence" does not exist

Problema con PostgreSQL


Esto es porque hay un pequeo bug en la rutina de importacin. Asume que la secuencia es llamada por hibernate_sequence. Esta secuencia se crea automticamente cuando estamos usando una columna serial, es llamada table_column_seq, ej: book_id_seq. El tarea ms fcil con respecto a esto es esperar hasta que MyEclipse mejore la rutina. La ms rpida es crear una secuencia llamada hibernate_sequence. Una desventaja es que todas las tablas compartidas tiene la misma secuencia. Tendr una tabla con una sobrecarga.
CREATE SEQUENCE hibernate_sequence INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1;

La forma ms agradable, pero solo es posible cuando est seguro de no generar sus archivos de mapeo (Debera sobreescribir sus cambios) es cambiar el mapeo de
<generator class="sequence"/>

a lo siguiente para book. Los cambios sobre Customer son semejantes.


<generator class="sequence"> <param name="sequence">book_id_seq</param> </generator>

Eso es para la capa de persistencia de nuestra aplcacin.

Generacin de la Lgica de Negocio


Creacin de una clase de lgica de negocio
Pondremos toda la lgica de negocio en una sola clase. Nuestro struts utilizar ms adelante solamente esta clase. No habr acceso directa a la capa de la persistencia. Usted podra incluso pensar de substituir su capa de la persistencia por otra.

Este clase mantendr todos los mtodos necesarios como lgica de negocio

crear, modificar y borrar libros crear, modificar y borrar clientes pedir prestado y devolver libros leer todos los clientes o libros de la db para una lista

Excepciones en Hibernate Cuando una excepcin ocurre se recomienda hacer roll back a la transaccin e inmediatamente cerrar la sesin. Eso es lo que hemos hecho con try catch {} finally{} Usamos Diseo Hibernate Una consulta hibernate devuelve una interface lista a una implementacin especial de Lista de Hibernate. Esta implementacin es directamente conectada con la sesin. No se puede cerrar la sesin cuando usa estas listas Hibernate. Usted tiene que desconectar la sesin de la base de datos y volverla a conectar, utilizar una de las soluciones de cache o hacerlo de la manera ms fcil pero no

hay mejor forma de trabajar con los Value Objects. Tomemos la manera ms fcil: La consecuencia es que tenemos una copia de todos los elementos de una lista hibernate en una lista normal java.util.List.
public class LibraryManager { /** * get all books from the database * @return Array of BookValue */ public Book[] getAllBooks() { /* will hold the books we are going to return later */ List books = new ArrayList(); /* a Hibernate session */ Session session = null; /* we always need a transaction */ Transaction tx = null; try { /* get session of the current thread */ session = HibernateSessionFactory.currentSession(); tx = session.beginTransaction(); Query query = session .createQuery("select b from Book as b order by b.author, b.title"); for (Iterator iter = query.iterate(); iter.hasNext();) { books.add((Book) iter.next()); } tx.commit(); } catch (HibernateException e) { e.printStackTrace(); // [laliluna] 17.12.2004 it is recommended to roll back the transaction after an error occured if (tx != null) try { tx.rollback(); } catch (HibernateException e1) { e1.printStackTrace(); } } finally { try { if (session != null) session.close(); } catch (HibernateException e1) { e1.printStackTrace(); } } return (Book[]) books.toArray(new Book[0]); } /** * get book by primary key * @param primaryKey * @return a Book or null */ public Book getBookByPrimaryKey(Integer primaryKey) { /* holds our return value */ Book book = null; /* a Hibernate session */ Session session = null; /* we always need a transaction */ Transaction tx = null; try { /* get session of the current thread */ session = HibernateSessionFactory.currentSession(); tx = session.beginTransaction(); book = (Book) session.get(Book.class, primaryKey); tx.commit(); } catch (HibernateException e) {

e.printStackTrace(); // [laliluna] 17.12.2004 it is recommended to roll back the transaction after an error occured if (tx != null) try { tx.rollback(); } catch (HibernateException e1) { e1.printStackTrace(); } } finally { try { if (session != null) session.close(); } catch (HibernateException e1) { e1.printStackTrace(); } } return book; } /** * sets the book as borrowed to the user specified in the database * @param primaryKey * @param userPrimaryKey */ public void borrowBook(Integer primaryKey, Integer customerPrimaryKey) { /* a Hibernate session */ Session session = null; /* we always need a transaction */ Transaction tx = null; try { /* get session of the current thread */ session = HibernateSessionFactory.currentSession(); tx = session.beginTransaction(); Book book = (Book) session.get(Book.class, primaryKey); Customer customer = (Customer) session.get(Customer.class, customerPrimaryKey); if (book != null && customer != null) book.setCustomer(customer); tx.commit(); } catch (HibernateException e) { e.printStackTrace(); // [laliluna] 17.12.2004 it is recommended to roll back the transaction after an error occured if (tx != null) try { tx.rollback(); } catch (HibernateException e1) { e1.printStackTrace(); } } finally { try { if (session != null) session.close(); } catch (HibernateException e1) { e1.printStackTrace(); } } } /** * customer returns a book, relation in the db between customer and book is deleted * @param primaryKey */ public void returnBook(Integer primaryKey) { /* a Hibernate session */ Session session = null; /* we always need a transaction */ Transaction tx = null; try { /* get session of the current thread */ session = HibernateSessionFactory.currentSession(); tx = session.beginTransaction();

found

Book book = (Book) session.get(Book.class, primaryKey); if (book != null) // session.get returns null when no entry is

book.setCustomer(null); tx.commit(); } catch (HibernateException e) { e.printStackTrace(); // [laliluna] 17.12.2004 it is recommended to roll back the transaction after an error occured if (tx != null) try { tx.rollback(); } catch (HibernateException e1) { e1.printStackTrace(); } } finally { try { if (session != null) session.close(); } catch (HibernateException e1) { e1.printStackTrace(); } } } /** * updates/creates a book * @param bookValue */ public void saveBook(Book bookValue) { /* a Hibernate session */ Session session = null; /* we always need a transaction */ Transaction tx = null; try { /* get session of the current thread */ session = HibernateSessionFactory.currentSession(); tx = session.beginTransaction(); Book book; if (bookValue.getId() != null && bookValue.getId().intValue() != 0) { // [laliluna] 04.12.2004 load book from DB book = (Book) session.get(Book.class, bookValue.getId()); if (book != null) { book.setAuthor(bookValue.getAuthor()); book.setTitle(bookValue.getTitle()); book.setAvailable(bookValue.getAvailable()); session.update(book); } } else // [laliluna] 04.12.2004 create new book { book = new Book(); book.setAuthor(bookValue.getAuthor()); book.setTitle(bookValue.getTitle()); book.setAvailable(bookValue.getAvailable()); session.save(book); } tx.commit(); } catch (HibernateException e) { e.printStackTrace(); // [laliluna] 17.12.2004 it is recommended to roll back the transaction after an error occured if (tx != null) try { tx.rollback(); } catch (HibernateException e1) { e1.printStackTrace(); } } finally { try { if (session != null) session.close(); } catch (HibernateException e1) {

} } /** * deletes a book * @param primaryKey */ public void removeBookByPrimaryKey(Integer primaryKey) { /* a Hibernate session */ Session session = null; /* we always need a transaction */ Transaction tx = null; try { /* get session of the current thread */ session = HibernateSessionFactory.currentSession(); tx = session.beginTransaction(); Book book = (Book) session.get(Book.class, primaryKey); if (book != null) session.delete(book); tx.commit(); } catch (HibernateException e) { e.printStackTrace(); // [laliluna] 17.12.2004 it is recommended to roll back the transaction after an error occured if (tx != null) try { tx.rollback(); } catch (HibernateException e1) { e1.printStackTrace(); } } finally { try { if (session != null) session.close(); } catch (HibernateException e1) { e1.printStackTrace(); } } } /** * returns all customers from the db * @return */ public Customer[] getAllCustomers() { /* will hold the books we are going to return later */ List customers = new ArrayList(); /* a Hibernate session */ Session session = null; /* we always need a transaction */ Transaction tx = null; try { /* get session of the current thread */ session = HibernateSessionFactory.currentSession(); tx = session.beginTransaction(); Query query = session .createQuery("select c from Customer as c order by c.name"); for (Iterator iter = query.iterate(); iter.hasNext();) { customers.add((Customer) iter.next()); } tx.commit(); } catch (HibernateException e) { e.printStackTrace(); // [laliluna] 17.12.2004 it is recommended to roll back the transaction after an error occured if (tx != null) try { tx.rollback(); } catch (HibernateException e1) { e1.printStackTrace(); } } finally { try {

e1.printStackTrace();

} /** * gets a customer from the db * @param primaryKey * @return the customer class or null, when no customer is found */ public Customer getCustomerByPrimaryKey(Integer primaryKey) { /* holds our return value */ Customer customer = null; /* a Hibernate session */ Session session = null; /* we always need a transaction */ Transaction tx = null; try { /* get session of the current thread */ session = HibernateSessionFactory.currentSession(); tx = session.beginTransaction(); customer = (Customer) session.get(Customer.class, primaryKey); tx.commit(); } catch (HibernateException e) { e.printStackTrace(); // [laliluna] 17.12.2004 it is recommended to roll back the transaction after an error occured if (tx != null) try { tx.rollback(); } catch (HibernateException e1) { e1.printStackTrace(); } } finally { try { if (session != null) session.close(); } catch (HibernateException e1) { e1.printStackTrace(); } } return customer; } /** * saves the customers to the db * @param customer */ public void saveCustomer(Customer customer) { /* a Hibernate session */ Session session = null; /* we always need a transaction */ Transaction tx = null; try { /* get session of the current thread */ session = HibernateSessionFactory.currentSession(); tx = session.beginTransaction(); if (customer.getId() == null || customer.getId().intValue() == 0) // [laliluna] 06.12.2004 create customer session.save(customer); else { Customer toBeUpdated = (Customer) session.get(Customer.class, customer .getId()); toBeUpdated.setAge(customer.getAge()); toBeUpdated.setLastname(customer.getLastname()); toBeUpdated.setName(customer.getName()); session.update(toBeUpdated); } tx.commit();

} return (Customer[]) customers.toArray(new Customer[0]);

if (session != null) session.close(); } catch (HibernateException e1) { e1.printStackTrace(); }

} catch (HibernateException e) { e.printStackTrace(); // [laliluna] 17.12.2004 it is recommended to roll back the transaction after an error occured if (tx != null) try { tx.rollback(); } catch (HibernateException e1) { e1.printStackTrace(); } } finally { try { if (session != null) session.close(); } catch (HibernateException e1) { e1.printStackTrace(); } } } /** * deletes a customer from the database * @param primaryKey */ public void removeCustomerByPrimaryKey(Integer primaryKey) { /* a Hibernate session */ Session session = null; /* we always need a transaction */ Transaction tx = null; try { /* get session of the current thread */ session = HibernateSessionFactory.currentSession(); tx = session.beginTransaction(); Customer customer = (Customer) session.get(Customer.class, primaryKey); if (customer != null) session.delete(customer); tx.commit(); } catch (HibernateException e) { e.printStackTrace(); // [laliluna] 17.12.2004 it is recommended to roll back the transaction after an error occured if (tx != null) try { tx.rollback(); } catch (HibernateException e1) { e1.printStackTrace(); } } finally { try { if (session != null) session.close(); } catch (HibernateException e1) { e1.printStackTrace(); } } } }

Bueno, ya hemos creado nuestra lgica de negocio. Y ahora la ltima parte: los dilogos

Creacin de dilogos
Cree un nuevo proyecto struts con File > New > Project o use el atajo Ctrl + n. Elija el Wizard de proyectos Web J2EE.

Pongale un buen nombre a su proyecto.

Por ahora su proyecto es como un proyecto Web comn, lo que necesitamos es agregar las capacidades struts. Botn derecho en el proyecto y agregue estas capacidades con Add Struts Capabilities.

Cambie Base package for new classes y Default application resource

Configuracin de la ruta de construccin java


Abra las propiedades del proyecto Web and seleccione LibraryPersistence del proyecto Hibernate.

Creacin de una pgina de bienvenida


Ok, ahora queremos crear una pgina por defecto. Botn derecho (s de nuevo) en la carpeta Folder WebRoot del proyecto y elija New > JSP.

Ponga el nombre index.jsp y seleccione en Template to use > Standard JSP using Struts 1.1 MyEcplise usar el esquema para crear el archivo JSP.

Encontrar el archivo index.jsp en la carpeta WebRoot del proyecto. Al principio del archivo encontrar la declaracin de la biblioteca de marcas de struts. Esto ser usado para acceder a las marcas de struts. En este caso solo necesitamos la biblioteca de marcas lgicas.

Inserte la siguiente linea que incluye la marca logic.


<logic:forward name="welcome" />

Esta lnea le dice a struts que busque una redireccin (forward) con el nombre welcome. Si la aplicacin no encuentra este forward, devolver un error, en la seccin siguiente explicar brevemente la accin forward. Cree un segundo archivo index.jsp en la carpeta /WebRoot/jsp Cambie el body del archivo por lo siguiente:
<body> Welcome! <br> <html:link action="bookList">Show the book list</html:link> <br> <html:link action="customerList">Show the customer list</html:link> </body

Global Action Forwards y Action Mappings


Qu es una accin de redireccin (Action Forward)? Una accin forward puede ser usada para remitir a un jsp o a un mapeo de accin. Existen dos acciones de redireccin distintos. La accin global y la local. Puede acceder a una accin global en cada jsp o action class. Una accin local solo puede ser accedida por la action class asignada. Qu es un action mapping? Qu es un mapa de accin (action mapping)? El mapa de accin es el corazn de struts. Maneja todas las acciones entre la aplicacin y el usuario. Usted puede definir qu accin ser ejecutada creando un mapa de accin (Action Mapping). El diagrama le muestra, cmo el servidor de aplicacin maneja la peticin del index.jsp o una accin no mapeada.

En el primer paso creamos una nueva accin mapeada. Abra el archivo struts-config.xml de la configuracin de struts, que est situado en WebRoot/WEB-INF. Botn derecho en la vista outline del action-mapping.

MyEclipse provee algunas buenas caractersticas para crear archivos struts. Abra struts-config.xml y la vista Outline. Clic con el botn derecho del mouse en action-mappings para crear una nueva accin con el asistente.

Seleccione Use Case default y Action Type Forward. El Forward Path es la pgina de bienvenida / jsp/index.jsp

Para atrapar todas las solicitudes de las acciones que no esten mapeadas, tenemos que agregar manualmente un parmetro unknow="true" en action forward.
<action-mappings > <action forward="/jsp/index.jsp" path="/default" unknown="true"/> </action-mappings>

Cree el jsp especifciado arriba y cambie el cdigo a lo siguiente:


<%@ page language="java"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html:html locale="true"> <head> <html:base /> <title>index.jsp</title> </head> <body> Welcome! <br> <html:link action="bookList">Show the book list</html:link> <br> <html:link action="customerList">Show the customer list</html:link> </body> </html:html>

En el segundo paso va a crear un accin de redireccin global. Vuelva a la ventana Outline de MyEclipse y seleccione Global Forward

Elija Forward Scope Global Forward. Use el mismo nombre que puso en la pgina por defecto. Global Forward se refiere a su action mapping.

Ver lo siguiente en su editor.


<global-forwards > <forward name="welcome" path="/default.do" redirect="true" /> </global-forwards> <action-mappings > <action forward="/jsp/index.jsp" path="/default" /> </action-mappings>

Lista de Libros
Este caso de uso lista todo los libros disponibles. Seleccione el asistente para crear un nuevo Formulario, accin y JSP.

El caso de uso es bookList, Superclass org.apache.struts.ActionForm. Elija public void reset.. para crear este mtodo. Vaya a la lengeta jsp y ponga el nombre del jsp a crear.

Action mapping und action class of the book list


Haga los siguientes cambios para la action class. Superclass org.apache.struts.Action En Optional Details seleccione el formulario Bean bookListForm. El cdigo de ingreso est en /jsp/bookList.jsp

Ahora agregue un forward showList al mapeo de accin.

Eso es. Los archivos estn generados.

Edicin del cdigo fuente de la action form class


Abra el archivo BookListForm.java y agregue las siguientes lneas.
public class BookListForm extends ActionForm { private Book[] book = new Book[0]; /** * @return Returns the book. */ public Book[] getBooks() { return book; } /** * @param book The book to set. */ public void setBooks(Book[] bookValues) { this.book = bookValues; } /** * Method reset * @param mapping * @param request */ public void reset(ActionMapping mapping, HttpServletRequest request) { book = new Book[0]; } }

No necesita tipear los mtodos getter y setter. Clic con el botn derecho sobre el proyecto -> select Source -> Generate Getters/Setters.

Edicin del cdigo de la action class


Encontrar la clase bookListAction en su paquete de.laliluna.tutorial.library.action. Abra la clase bookListAction y edite el mtodo execute. Guarde el array de libros devuelto por el mtodo en el formulario bean. El comando mapping.findForward(showList) buscar un forward local con el nombre showList.
public class BookListAction extends Action { /** * Method loads book from DB * @param mapping * @param form * @param request * @param response * @return ActionForward */ public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { BookListForm bookListForm = (BookListForm) form; // [laliluna] 27.11.2004 get busines logic LibraryManager libraryManager = new LibraryManager(); // [laliluna] 29.11.2004 update the form bean, from which the jsp will read the data later. bookListForm.setBooks(libraryManager.getAllBooks()); return mapping.findForward("showList"); }

Mostrar la lista de libros en el archivo jsp.


Abra bookList.jsp y agregue el siguiente cdigo.
<%@ <%@ <%@ <%@ page language="java"%> taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%> taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%> taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %>

<html> <head> <title>Show book list</title> </head> <body> <table border="1"> <tbody> <%-- set the header --%> <tr> <td>Author</td> <td>Book name</td> <td>Available</td> <td>Borrow by</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <%-- start with an iterate over the collection books --%> <logic:iterate name="bookListForm" property="books" id="book"> <tr> <%-- book informations --%> <td><bean:write name="book" property="author" /></td> <td><bean:write name="book" property="title" /></td> <td><html:checkbox disabled="true" name="book" property="available"/> </td> <td> <%-- check if a customer borrowed a book, when its true display his name otherwise display nothing --%> <logic:notEmpty name="book" property="customer"> <bean:write name="book" property="customer.name" />, <bean:write name="book" property="customer.lastname" /> </logic:notEmpty> <logic:empty name="book" property="customer"> </logic:empty> </td> <%-- borrow, edit and delete link for each book --%> <td> <%-- check if a user borrowed a book, when its true display the return link otherwise display the borrow link --%> <logic:notEmpty name="book" property="customer"> <html:link action="bookEdit.do?do=returnBook" paramName="book" paramProperty="id" paramId="id">Return book</html:link> </logic:notEmpty> <logic:empty name="book" property="customer"> <html:link action="bookEdit.do?do=borrowBook" paramName="book" paramProperty="id" paramId="id">Borrow book</html:link>

</logic:empty> </td> <td><html:link action="bookEdit.do?do=editBook" paramName="book" paramProperty="id" paramId="id">Edit</html:link> </td> <td><html:link action="bookEdit.do?do=deleteBook" paramName="book" paramProperty="id" paramId="id">Delete</html:link> </td> </tr> </logic:iterate> <%-- end interate --%> <%-- if books cannot be found display a text --%> <logic:notPresent name="book"> <tr> <td colspan="5">No books found.</td> </tr> </logic:notPresent> </tbody> </table> <br> <%-- add and back to menu button --%> <html:button property="add" onclick="location.href='bookEdit.do?do=addBook'">Add a new book </html:button> &nbsp; <html:button property="back" onclick="location.href='default.do'">Back to menu </html:button> </body> </html>

La marca <logic:iterate> recorre el array de libros. Con la marca Ud. tiene acceso a las propiedades de los libros con el nombre book. La marca <bean:write> imprime una propiedad de un libro, por ejemplo el ttulo (title). Con la marca <logic:notEmpty> y <logic:empty> vcerificamos, si un usuario a ha pedido prestado un libro o no. S eso es todo, ha creado su formulario bean con un action form class, un action mapping con un action class y el jsp que muestra algo.

Prueba de la aplicacin
Arranque el jboss y despliegue el proyecto (LibraryPersistenceLibs, LibraryPersistence y LibraryWeb) como archivos adjuntos

Llame al proyecto con su navegador favorito http://localhost:8080/LibraryWeb/ Problema de distribucin de Jboss Cuando redistribuye un proyecto Jboss a menudo bloquea las bibliotecas. El resultado es que obtiene el siguiente mensaje: Undeployment failure on Jboss. File ....jar Unable to be deleted. Un solucin sencilla es crear dos proyectos, uno que incluya las bibliotecas que no tiene que distribuir y el otro que incluya su proyecto Hibernate. Tenemos un tutorial expolicando esto. Si comienza a molestarle cuando redistribuya, pruebe este tutorial.

Agregar, editar, prestar y eliminar libros


En el prximo paso tenemos que agregar los siguientes casos de uso:

Agregar libros Editar libros Prestar / devolver libros Eliminar libros

Nuevo formulario bean


Cree un nuevo formulario bean y una clase action form. Ponga como Use case a bookEdit y elmine todos los mtodos en Optional details Methods. MyEcplise crea un archivo jsp por nosotros. Abra la clase BookEditForm.java en de.laliluna.tutorial.library.form . Cree los atributos book y customerId.
public class BookEditForm extends ActionForm {

private Book book = new Book(); /** * we will need this field to save the customer id in the dialogs where a customer borrows a book */ private Integer customerId;

Genere los getters y setters para los atributos. Luego genere todos los mtodos delegados por el atributo book.

El cdigo ser como el siguiente:


public class BookEditForm extends ActionForm { private Book book = new Book(); /** * we will need this field to save the customer id in the dialogs where a customer borrows a book */ private Integer customerId; /** * @return Returns the book. */ public Book getBook() { return book; } /** * @param book The book to set. */ public void setBook(Book book) { this.book = book; } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object arg0) { return book.equals(arg0); } /** * @return */

public String getAuthor() { return book.getAuthor(); } /** * @return */ public Boolean getAvailable() { return book.getAvailable(); } /** * @return */ public Customer getCustomer() { return book.getCustomer(); } /** * @return */ public Integer getId() { return book.getId(); } /** * @return */ public String getTitle() { return book.getTitle(); } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ public int hashCode() { return book.hashCode(); } /** * @param author */ public void setAuthor(String author) { book.setAuthor(author); } /** * @param available */ public void setAvailable(Boolean available) { book.setAvailable(available); } /** * @param customer */ public void setCustomer(Customer customer) { book.setCustomer(customer); } /** * @param id */ public void setId(Integer id) { book.setId(id); } /** * @param title */ public void setTitle(String title) { book.setTitle(title); } /* (non-Javadoc) * @see java.lang.Object#toString() */ public String toString() { return book.toString(); }

/** * @return Returns the customerId. */ public Integer getCustomerId() { return customerId; } /** * @param customerId The customerId to set. */ public void setCustomerId(Integer customerId) { this.customerId = customerId; }

Caso de uso editar libro


El prximo paso es crear lo necesario para editar los libros.

Action Mapping
Cree un nuevo action mapping. Hay una diferencia con nuestra primer first action class. La nueva action class extender la superclase org.apache.struts.DispatchAction. Una Dispatch action no llama al mtodo execute pero si a otros mtodos especificados por un parmetro. Cuando el usuario haga clic en un enlace de edicin (Edit Link) la dispatch action llamar al mtodo Edit, cuando l haga clic en un enlace para Agregar, la dispatch action llama al mtodo create.

En Parameter agregamos el parmetro do. Este parmetro lo necesita la dispatch action class.

Agregue cuatro nuevos forwards. Uno para la pgina de edicin, el segundo para la pgina que agrega, donde se podr agregar libros, el tercer forward para la pgina de prstamo y la cuarta para redireccionar al usuaio al listado de libros.

El ltimo forward es distinto a los otros. Se refiere a una action mapping existente y redirecciona al usuario. Cree los archivos jsp faltantes con New > JSP. bookAdd.jsp bookEdit.jsp bookBorrow.jsp Edite el cdigo de los archivos jsp. Abra el archivo bookAdd.jsp y agregue el siguiente cdigo.
<%@ <%@ <%@ <%@ page language="java"%> taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%> taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%> taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %>

<html> <head> <title>Add a book</title> </head> <body> <%-- create a html form --%> <html:form action="bookEdit"> <%-- print out the form data --%> <table border="1"> <tbody> <tr> <td>Author:</td> <td><html:text property="author" /></td> </tr> <tr> <td>Title:</td> <td><html:text property="title" /></td> </tr> <tr> <td>Available:</td> <td><html:checkbox property="available" /></td> </tr> </tbody> </table> <%-- set the parameter for the dispatch action --%> <html:hidden property="do" value="saveBook" /> <br> <%-- submit and back button --%> <html:button property="back" onclick="history.back();"> </html:button>

Back

&nbsp; <html:submit>Save</html:submit> </html:form> </body> </html>

La marca <html:form> crea un nuevo formulario HTML y se enlaza con el parmetro action=bookEdit al action mapping. La marca <html:text> crea un campo de texto con la propiedad del autor del libro. <html:hidden> es un campo oculto con el nombre do. Necesitamos este campo oculto porque llama a la the dispatch action class con el mtodo que querramos. Abra el archivo bookEdit.jsp. Ouede usar el cdigo del archivo bookAdd.jsp y cambiar las siguientes lneas.
<title>Edit a book</title>

Agegue la siguiente lnea arriba <html:hidden property="do" value="saveBook" />


<%-- hidden fields for id and userId --%> <html:hidden property="id" />

Abra el archivo bookBorrow.jsp y agregue


<%@ <%@ <%@ <%@ <%@ page language="java"%> page isELIgnored="false"%> taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%> taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%> taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %>

<html> <head> <title>Show customers</title> </head> <body> <html:form action="bookEdit"> <table border="1"> <tbody> <%-- set the header --%> <tr> <td>Last name</td> <td>Name</td> <td>Borrow</td> </tr> <%-- start with an iterate over the collection users --%> <logic:present name="customers"> <logic:iterate name="customers" id="customer"> <tr> <%-- book informations --%> <td><bean:write name="customer" property="lastname" /></td> <td><bean:write name="customer" property="name" /></td> <td><html:radio property="customerId" value="${customer.id}" /></td> </tr> </logic:iterate> </logic:present> <%-- end interate --%> <%-- if customers cannot be found display a text --%> <logic:notPresent name="customers"> <tr> <td colspan="5">No customers found.</td>

</tr> </logic:notPresent> </tbody> </table> <%-- set the book id to lent --%> <html:hidden property="id" /> <%-- set the parameter for the dispatch action --%> <html:hidden property="do" value="saveBorrow" /> <%-- submit and back button --%> <html:button property="back" onclick="history.back();"> </html:button> &nbsp; <html:submit>Save</html:submit> </html:form> </body> </html>

Back

Mtodos de la dispatch action class


Abra el archivo bookEditAction.java agregue los siguientes mtodos.
public class BookEditAction extends DispatchAction { /** * loads the book specified by the id from the database and forwards to the edit form * @param mapping * @param form * @param request * @param response * @return ActionForward */ public ActionForward editBook( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { System.out.println("editBook"); BookEditForm bookEditForm = (BookEditForm) form; /* lalinuna.de 04.11.2004 * get id of the book from request */ Integer id = Integer.valueOf(request.getParameter("id")); // [laliluna] 28.11.2004 get business logic LibraryManager libraryManager = new LibraryManager(); bookEditForm.setBook(libraryManager.getBookByPrimaryKey(id)); return mapping.findForward("showEdit");

/** * loads a book from the db and forwards to the borrow book form * @param mapping * @param form * @param request * @param response * @return ActionForward */ public ActionForward borrowBook( ActionMapping mapping, ActionForm form,

HttpServletRequest request, HttpServletResponse response) { System.out.println("borrowBook"); BookEditForm bookEditForm = (BookEditForm) form; /* lalinuna.de 04.11.2004 * get id of the book from request */ Integer id = Integer.valueOf(request.getParameter("id")); /* lalinuna.de 16.11.2004 * load the session facade for book and user * get the book information and get all users */ LibraryManager libraryManager = new LibraryManager(); // [laliluna] 28.11.2004 save book in the form bookEditForm.setBook(libraryManager.getBookByPrimaryKey(id)); // [laliluna] 28.11.2004 save customers in the reqest request.setAttribute("customers", libraryManager.getAllCustomers return mapping.findForward("showBorrow");

()); }

/** * return a book from a customer * @param mapping * @param form * @param request * @param response * @return ActionForward */ public ActionForward returnBook( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { System.out.println("returnBook"); BookEditForm bookEditForm = (BookEditForm) form; /* lalinuna.de 04.11.2004 * get id of the book from request */ Integer id = Integer.valueOf(request.getParameter("id")); // [laliluna] 28.11.2004 get business logic LibraryManager libraryManager = new LibraryManager(); libraryManager.returnBook(id); } return mapping.findForward("showList");

/** * deletes a book from the database * @param mapping * @param form * @param request * @param response * @return ActionForward */ public ActionForward deleteBook( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) {

System.out.println("deleteBook"); BookEditForm bookEditForm = (BookEditForm) form; /* lalinuna.de 04.11.2004 * get id of the book from request */ Integer id = Integer.valueOf(request.getParameter("id")); // [laliluna] 28.11.2004 get business logic LibraryManager libraryManager = new LibraryManager(); libraryManager.removeBookByPrimaryKey(id); return mapping.findForward("showList"); } /** * forwards to the add book form * @param mapping * @param form * @param request * @param response * @return ActionForward */ public ActionForward addBook( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { System.out.println("addBook"); BookEditForm bookEditForm = (BookEditForm) form; return mapping.findForward("showAdd"); } /** * saves the borrow assigned in the form in the database * @param mapping * @param form * @param request * @param response * @return ActionForward */ public ActionForward saveBorrow( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { BookEditForm bookEditForm = (BookEditForm) form; // [laliluna] 28.11.2004 get business logc LibraryManager libraryManager = new LibraryManager(); libraryManager.borrowBook(bookEditForm.getId(), bookEditForm.getCustomerId()); } return mapping.findForward("showList");

/** * updates or creates the book in the database * @param mapping * @param form * @param request * @param response * @return ActionForward */ public ActionForward saveBook(

ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { BookEditForm bookEditForm = (BookEditForm) form; // [laliluna] 28.11.2004 get business logic LibraryManager libraryManager = new LibraryManager(); libraryManager.saveBook(bookEditForm.getBook()); return mapping.findForward("showList");

Caso de uso listado de clientes


Creamos esta lista de la misma forma que la de los libros. Abra struts-config.xml. Elija el asistente para crear una accin, un formulario y los forwards a la vez. Nuestro caso de uso es customer list. Edite el dilogo como ya lo vi:

No se olvide los cambios en las lengetas de mtodos. En la lengeta JSP cree el siguiente JSP.

El prximo paso es poner la accin que ser llamada antes que su JSP se muestre. Haga los cambios como se muestra debajo.

El ltimo paso es crear el forwards la accin que redireccionar al JSP que muestra la lista de clientes.

Por ahora, emos creado todos los archivos necesarios para nuestros casos de uso. El paso siguiente es rellenarlos con contenido.

Edicin del cdigo de la action form class


Abra el archivo CustomerListForm.java y agregue el cdigo siguiente.
public class CustomerListForm extends ActionForm { private Customer[] customers = new Customer[0]; /** * @return Returns the customers. */ public Customer[] getCustomers() { return customers; } /** * @param customers The customers to set. */ public void setCustomers(Customer[] customers) { this.customers = customers; } }

No necesitamos un mtodo reset aqu, como el bean es usado solamente para pasar los datos de la accin al JSP. Edite la action class.
public class CustomerListAction extends Action { /** * loads customers from the db and saves them in the request * @param mapping * @param form * @param request * @param response * @return ActionForward */ public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { CustomerListForm customerListForm = (CustomerListForm) form; // [laliluna] 29.11.2004 get business logic LibraryManager libraryManager = new LibraryManager(); customerListForm.setCustomers(libraryManager.getAllCustomers()); return mapping.findForward("showCustomerList");

Mostrar la lista de clientes


Abra el archivo jsp customerList.jsp y cambie el contenido del archivo por esto.
<%@ page language="java"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic"%> <html> <head> <title>JSP for customerListForm form</title>

</head> <body> <table border="1"> <tbody> <%-- set the header --%> <logic:present name="customerListForm" property="customers"> <tr> <td>Name</td> <td>Last name</td> <td>Age</td> <td></td> <td></td> </tr> <%-- start with an iterate over the collection books --%> <logic:iterate name="customerListForm" property="customers" id="customer"> <tr> <%-- book informations --%> <td><bean:write name="customer" property="name" /></td> <td><bean:write name="customer" property="lastname" /></td> <td><bean:write name="customer" property="age" /></td> <%-- edit and delete link for each customer --%> <td><html:link action="customerEdit.do?do=editCustomer" paramName="customer" paramProperty="id" paramId="id">Edit</html:link> </td> <td><html:link action="customerEdit.do?do=deleteCustomer" paramName="customer" paramProperty="id" paramId="id">Delete</html:link> </td> </tr> </logic:iterate> <%-- end interate --%> </logic:present> <%-- if customers cannot be found display a text --%> <logic:notPresent name="customerListForm" property="customers"> <tr> <td colspan="5">No customers found.</td> </tr> </logic:notPresent> </tbody> </table> <br> <%-- add and back to menu button --%> <html:button property="add" onclick="location.href='customerEdit.do?do=addCustomer'">Add a new customer </html:button> &nbsp; <html:button property="back" onclick="location.href='default.do'">Back to menu </html:button> </body> </html>

Eso es. Hemos terminado el caso de uso, ahora debemos probarlo.

Casos de uso Agegar, editar y borrar clientes


En el siguiente paso queremos agregar los siguientes procesos.

Agregar un cliente

Editar un cliente Borrar un cliente

Seleccione New Form, Action and JSP.

Seleccione para crear un archivo JSP.

Siga hasta la pgina de accin. Seleccione DispatchAction como la Super Clase.

Luego seleccione para crear un parmetro:

Cree tres forwards como se muestra debajo.

Formulario bean para Cliente


Agregue un nuevo atributo del tipo Customer
private Customer customer;

Genere los mtodos getter y setter y herede todos los mtodos de la clase, al igual que hizo con el form bean de libros.

El cdigo de la clase es como el siguiente


public class CustomerEditForm extends ActionForm { private Customer customer; /** * @return Returns the customer. */ public Customer getCustomer() { return customer; } /** * @param customer The customer to set. */ public void setCustomer(Customer customer) { this.customer = customer; } /** * Method reset * @param mapping * @param request */ public void reset(ActionMapping mapping, HttpServletRequest request) { customer=new Customer(); } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object arg0) { return customer.equals(arg0); } /**

* @return */ public Integer getAge() { return customer.getAge(); } /** * @return */ public Integer getId() { return customer.getId(); } /** * @return */ public String getLastname() { return customer.getLastname(); } /** * @return */ public String getName() { return customer.getName(); } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ public int hashCode() { return customer.hashCode(); } /** * @param age */ public void setAge(Integer age) { customer.setAge(age); } /** * @param id */ public void setId(Integer id) { customer.setId(id); } /** * @param lastname */ public void setLastname(String lastname) { customer.setLastname(lastname); } /** * @param name */ public void setName(String name) { customer.setName(name); } /* (non-Javadoc) * @see java.lang.Object#toString() */ public String toString() { return customer.toString(); }

Edicin del cdigo de la action class


Abra el archivo CustomerEditAction.class en el paquete de.laliluna.library.struts.action y agregue los mtodos siguientes. Lo primero es el paso antes de editar un cliente. Cargar los datos del cliente desde la base de datos y guardarlos en el formulario bean.
/** * loads customer from the db and forwards to the edit form * @param mapping * @param form * @param request * @param response * @return */ public ActionForward prepareEdit(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { CustomerEditForm customerEditForm = (CustomerEditForm) form; Integer id = Integer.valueOf(request.getParameter("id")); LibraryManager libraryManager = new LibraryManager(); customerEditForm.setCustomer(libraryManager.getCustomerByPrimaryKey(id)); return mapping.findForward("editCustomer"); }

El prximo mtodo es el anterior a agregar un cliente. Realmente solo es un forrward al JSP.


/** * prepares the add form (actually only forwards to it) * @param mapping * @param form * @param request * @param response * @return */ public ActionForward prepareAdd(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { return mapping.findForward("addCustomer"); }

La actualizacin y creacin de clientes est hecho por el siguiente mtodo.


/** * saves the customers and forwards to the list * @param mapping * @param form * @param request * @param response * @return */ public ActionForward saveCustomer(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { CustomerEditForm customerEditForm = (CustomerEditForm) form; LibraryManager libraryManager = new LibraryManager(); libraryManager.saveCustomer(customerEditForm.getCustomer()); return mapping.findForward("customerList"); }

Y finalmente cuando hace clic en eliminar, el siguiente mtodo es llamado.


/** * deletes the customers and forwards to the list * @param mapping * @param form * @param request * @param response * @return */ public ActionForward deleteCustomer(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { CustomerEditForm customerEditForm = (CustomerEditForm) form; LibraryManager libraryManager = new LibraryManager(); libraryManager.removeCustomerByPrimaryKey(customerEditForm.getCustomer(). getId()); } return mapping.findForward("customerList");

Cuando la lgica del negocio se mantiene separada, el cdigo de accin es siempre mucho ms corto y fcil de leer.

Edit the source code of the jsp file


Create a new file named editcustomer.jsp in the folder WebRoot/jsp/. Open the file editcustomer.jsp and change the content of the file.
<%@ page language="java"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%> <html> <head> <title>JSP for customerEditForm form</title> </head> <body> <html:form action="/customerEdit"> <html:hidden property="id"/> <html:hidden property="do" value="saveCustomer"/> Name: <html:text property="name"/><br/> Last name <html:text property="lastname"/><br/> Age <html:text property="age"/><br/> <html:submit/><html:cancel/> </html:form> </body> </html>

Test the applications


Start the jboss and deploy the project as package archiv.

Call the project in your favorite web browser. http://localhost:8080/LibraryWeb/ Nice, that's all. I hope you enjoyed the tutorial. If you have any feedback to us, feel free to contact us.

También podría gustarte