Академический Документы
Профессиональный Документы
Культура Документы
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
Temario
1. Descripcin de la Arquitectura J2EE 1.1 Describir los principales elementos de la arquitectura J2EE. 1.2 Arquitectura para aplicaciones J2EE (definicin del contexto) 1.3 Modelo MVA 2. Descripcin del Componente EJB 2.1 SessionBean Aplicacin Cliente Multi-Capa Software J2EE y Configuracin Componentes de Aplicacin J2EE Crear la Pgina HTML Crear y Compilar el Bean de Sesin y el Servlet Ciclo de vida de SessionBean Arrancar el Servidor de Aplicaciones J2EE Aplicacin J2EE Crear la aplicacin J2EE Crear Componentes Web Especificar el Nombre JNDI y el Contexto Raz Verificar, Desplegar y Ejecutar la Aplicacin Actualizar el Cdigo de Componentes 2.2. EntityBean (EJB de tipo Entidad Ciclo de vida de EntityBean Crear el Bean de Entidad Cambiar el Servlet Compilar el Bean de Entidad y el Servlet Arrancar la Plataforma y las Herramientas Verificar, Desplegar y Ejecutar la Aplicacin 3. Comunicaciones entre Beans Enterprise 3.1 Cambiar el Bean de Sesin y el Servlet 3.2 Compilar el Bean de Sesin y el Servlet 3.2.1 Arrancar la Plataforma y las Herramientas 3.2.2 Ensamblar la Aplicacin J2EE 3.2.3 Verificar, Desplegar y Ejecutar la Aplicacin J2EE 4. Construccin de una sencilla aplicacin de J2EE 4.1 Como configurar el software para la ejecucin de una aplicacin J2EE 4.2 Construccin de un SessionBean 4.3 Construccin de un EntityBean 4.4 Construccin del Cliente
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
4.4.1 Servlets 4.4.2 JSPs Tecnologa JavaServer Pages (JSP) Crear la Pgina JSP Modificar bonus.html Eliminar el Fichero WAR Verificar, Desplegar y Ejecutar la Aplicacin J2EE Tecnologa JavaBeans Crear bonus.jsp Crear la Clase JavaBean Arrancar la Plataforma y las Herramientas Eliminar el Fichero WAR Crear el Nuevo Fichero WAR eXtensible Markup Language XML Marcar y manejar texto Modificar la clase JavaBean Los APIs SAX y DOM J2EE JDBC Ciclo de Vida del Bean Modificar cdigos Crear la tabla de la base de datos Eliminar el Fichero JAR Verificar, Desplegar y Ejecutar la aplicacin
Requisitos: Conocimientos de Modelamiento UML, Lenguaje Java Avanzado (haber realizado los cursos anteriores del programa), conocimientos de Arquitectura Cliente/Servidor, RMI, JSP, y Servlets. Dirigido a: Responsables de equipos tcnicos y de planificacin estratgica, expertos en arquitectura de sistemas y asesores tecnolgicos de departamentos de informtica y empresas independientes proveedoras de software. Duracin:40 horas cronolgicas
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
Un Sencillo Bean de Sesin Ejemplo de Aplicacin Cliente Multi-Capa Software J2EE y Configuracin Configuracin del Path y ClassPath Componentes de Aplicacin J2EE Crear la Pgina HTML Cdigo HTML Crear el Servlet Sentencias Import Mtodo init() Mtodo doGet Cdigo del Servlet Crear el Bean de Session CalcHome Calc CalcBean Compilar el Bean de Sesin y el Servlet Compilar el Bean de Session Compilar el Servlet Arrancar el Servidor de Aplicaciones J2EE Arrancar la Herramienta DeployTool DeployTool Ensamblar la Aplicacin J2EE Crear la aplicacin J2EE Crear el Bean de Sesin Crear Componentes Web Especificar el Nombre JNDI y el Contexto Raz Verificar y Desplegar la Aplicacin J2EE Ejecutar la Aplicacin J2EE Actualizar el Cdigo de Componentes Un Bean de Entidad Crear el Bean de Entidad BonusHome Bonus BonusBean Cambiar el Servlet Compilar Compilar el Bean de Entidad Compilar el Servlet Arrancar la Plataforma y las Herramientas Ensamblar y Desplegar Actualizar el Fichero de Aplicacin Crear el Bean de Entidad Verificar y Desplegar la aplicacin J2EE Ejecutar la Aplicacin J2EE
5 6 6 7 7 8 8 9 9 10 10 11 12 13 13 14 14 14 15 15 16 16 17 17 17 19 22 23 24 24 25 25 26 27 29 30 30 31 31 31 31 32 36 36
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
Comunicaciones entre Beans Cambiar el Bean de Sesin CalcHome Calc CalcBean Cambiar el Servlet Compilar Compilar el Bean de Sesin Compilar el Servlet Arrancar la Plataforma y las Herramientas Ensamblar la Aplicacin Crear una Nueva aplicacin J2EE Crear un nuevo componente Web. Empaquetar los Beans de Sesin y de Entidad en un Fichero JAR Verificar y Desplegar la Aplicacin J2EE Ejecutar la Aplicacin J2EE Tecnologa JavaServer Pages (JSP) Crear la Pgina JSP Comentarios Directivas Declaraciones Scriptlets Variables Predefinidas Expresiones Etiquetas Especificas de JSP Modificar bonus.html Arrancar la Plataforma y las Herramientas Eliminar el Fichero WAR Verificar y Desplegar la Aplicacin J2EE Ejecutar la Aplicacin J2EE Tecnologa JavaBeans Sobre el Ejemplo Crear bonus.jsp Especificar el JavaBean Obtener los Datos Pasar los Datos al JavaBean Recuperar los Datos desde el JavaBean Crear la Clase JavaBean Propiedades del Bean Constructor Mtodos Set Mtodos Get Arrancar la Plataforma y las Herramientas Eliminar el Fichero WAR Crear el Nuevo Fichero WAR Verificar y Desplegar la Aplicacin J2EE
38 38 38 39 39 40 42 42 42 43 43 43 44 45 48 49 51 51 52 53 53 53 54 54 54 55 55 56 57 58 59 59 61 62 62 62 63 63 64 65 65 66 67 68 68 69 5
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
70
71 71 72 72 72 74 74 74 76 77 77 77 78 78 79 79 80 80 80 85 86 87 87 87 88 89 91
XML - eXtensible Markup Language Marcar y Manejar Texto Modificar la Clase JavaBean Prlogo XML Documento Raz Nodos Hijos Otras Etiquetas XML Cdigo del JavaBean Los APIs SAX y DOM J2EE Actualizar y Ejecutar la Aplicacin JDBC Ciclo de Vida del Bean Modificar el cdigo de BonusBean Sentencias Import Variables de Ejemplar Mtodos de Negocio Mtodos de Ciclo de Vida Modificar el Cdigo de CalcBean y JBonusBean Crear la Tabla de la Base de Datos createTable.sql cloudTable.bat cloudTable.sh Eliminar el Fichero JAR Verificar y Desplegar la Aplicacin Ejecutar la Aplicacin
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
Capitulo I - Introduccin
Este manual presenta los APIs, las herramientas y los servicios que proporciona la Implementacin de Referencia de Java 2 Enterprise Edition (J2EE). EJB, es la adaptacin de un modelo de componente Java para servidores de bases de datos, Transacciones y aplicaciones. Cada uno de estos funciona como un contenedor para componentes EJB, los cuales se intenta que sean porttiles entre servidores y sistemas operativos. A excepcin del aspecto de la portabilidad, la idea tras el EJB es similar a aquella que Microsoft promovi con el Microsoft Transaction Server y tecnologas relacionadas para aislar a los desarrolladores de negocios de la complejidad de crear aplicaciones demasiado complicadas. Los desarrolladores escribirn componentes que requieran de servicios del contenedor EJB, y el servidor secundario descifrar que servicio puede proporcionar y cual deber ser enviado a otro servidor. "La idea es que escribir aplicaciones interrelacionadas es difcil, y EJB lo facilita".
El SDK J2EE es una definicin y especificacin operacional no comercial de la plataforma J2EE que Sun Microsystem a liberado para demostraciones, prototipos y usos educacionales. Viene con el servidor de aplicaciones J2EE, servidor Web, base de datos, los APIs J2EE, y un completo conjunto de herramientas de desarrollo. Nos iremos encontrando con estas caractersticas y herramientas segn vayamos avanzando en este tutorial.
capas extiende el modelo de tres capas reemplazando la aplicacin cliente con un navegador Web y una pgina HTML potenciada con las tecnologas servlet/JavaServer Pages.
Mientras que esta leccin usa slo tres o cuatro capas, la siguiente leccin extiende este mismo ejemplo para acceder al servidor de base de datos en la cuarta capa. Lecciones posteriores adaptan el ejemplo para usar las tecnologas JavaServer Pages y Extensible Markup Language (XML).
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
En esta leccin, crearemos una aplicacin y dos componentes J2EE: un servlet y un Bean de sesin. El servlet est empaquetado con su fichero HTML en un fichero Web Archive (WAR), y las clases e interfaces del Bean de sesin estn empaquetadas en un fichero JAR. Los ficheros WAR y JAR se aaden a la aplicacin J2EE y se empaquetan dentro de un fichero Enterprise Archive (EAR) para probar, verificar y desplegar el entorno de produccin. Mientras estemos haciendo todos estos pasos para esta leccin, realmente estaremos realizando varias funciones diferentes. Escribir el cdigo del servlet y del Bean de sesin es una funcin de desarrollo, mientras que crear la aplicacin J2EE y aadir los componentes J2EE a una aplicacin es una funcin de ensamblaje. En realidad, estas funciones podran ser realizadas por diferentes personas de diferentes compaas. Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile 9
La siguiente Figura muestra el flujo de los datos entre el navegador y el Bean de sesin. El Bean de sesin se ejecuta en el servidor de aplicaciones J2EE.
Cdigo HTML
Lo ms interesante sobre el cdigo del formulario HTML es el alias usado para invocar a BonusServlet . Cuando el usuario pulsa el botn Submit sobre el formulario HTML, se llama a BonusServlet porque se ha mapeado a BonusAlias durante el ensamblaje de la aplicacin descrito en Ensamblar la Aplicacin J2EE. El ejemplo asume que bonus.html est en el directorio /home/monicap/J2EE/ClientCode en UNIX. Aqu y desde ahora los usuarios de Windows pueden invertir las barras inclinadas para obtener los paths correctos para su plataforma: <HTML> <BODY BGCOLOR = "WHITE"> <BLOCKQUOTE>
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
10
<H3>Bonus Calculation</H3> <FORM METHOD="GET" ACTION="BonusAlias"> <P> Enter social security Number: <P> <INPUT TYPE="TEXT" NAME="SOCSEC"></INPUT> <P> Enter Multiplier: <P> <INPUT TYPE="TEXT" NAME="MULTIPLIER"></INPUT> <P> <INPUT TYPE="SUBMIT" VALUE="Submit"> <INPUT TYPE="RESET"> </FORM> </BLOCKQUOTE> </BODY> </HTML>
Crear el Servlet
El ejemplo asume que el fichero BonusServlet.java est en el directorio /home/monicap/J2EE/ClientCode en UNIX. Durante la ejecucin, el cdigo del servlet hace lo siguiente: Recupera los datos del usuario Busca el bean de sesin Le pasa los datos al bean de sesin Despus de recibir un valor de vuelta desde el bean de sesin, crea una pgina HTML para mostrar el valor devuelto al usuario.
La siguiente seccin describe las diferentes partes del cdigo del servlet
Sentencias Import
El cdigo del servlet empieza con sentencias import para los siguientes paquetes: javax.servlet, que contiene clases servlets genricas (independientes del protocolo). La clase HTTPServlet usa la clase ServletException de este paquete para indicar un problema en el servlet. javax.servlet.http, que contiene clases servelts HTTP. La clase HttpServlet est en este paquete. java.io para entrada y salida del sistema. La clase HttpServlet usa la clase IOException de este paquete para sealar que se ha producido una excepcin de algn tipo de entrada o salida. javax.naming para poder usar los APIs Java Naming and Directory Interface (JNDI) para buscar el interface home del bean de sesin. javax.rmi para buscar el interface home del bean de sesin y poner su objeto servidor remoto listo para las omunicaciones.
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
11
Mtodo init()
El mtodo BonusServlet.init busca el interface home del bean de sesin y crea su ejemplar. El mtodo usa el nombre JNDI especificado durante el ensamblado de componentes ( calcs) para obtener una referencia al interface home por su nombre. La siguiente lnea pasa la referencia y la clase del interface home al mtodo PortableRemoteObject.narrow para asegurarse de que la referencia puede forzarse al tipo CalcHome. InitialContext ctx = new InitialContext(); Object objref = ctx.lookup("calcs"); homecalc = (CalcHome)PortableRemoteObject.narrow(obj ref, CalcHome.class);
Mtodo doGet
La lista de parmetros de doGet toma un objeto request y un response. El navegador enva una peticin (request) al servlet y el servlet enva una respuesta (response) de vuelta al navegador. La implementacin del mtodo accede a informacin del objeto request para encontrar quin ha hecho la peticin, en qu formulario estn los datos de la peticin, y que cabeceras HTTP se enviarn, y usa el objeto response para crear una pgina HTML en respuesta a la peticin del navegador. El mtodo doGet lanza una IOException si hay algn problema con los datos de entrada o salida cuando maneja la peticin, y una ServletException si la peticin no se puede manejar. Para calcular el valor del bonus, el mtodo doGet crea el interface home y llama al mtodo calcBonus. public void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String socsec = null; int multiplier = 0; double calc = 0.0; PrintWriter out; response.setContentType("text/html"); String title = "EJB Example"; out = response.getWriter(); out.println("<HTML><HEAD><TITLE>") out.println(title); out.println("</TITLE></HEAD><BODY>"); try{ //Retrieve Bonus and Social Security Information String strMult = request.getParameter( "MULTIPLIER"); Integer integerMult = new Integer(strMult); multiplier = integerMult.intValue(); socsec = request.getParameter("SOCSEC"); //Calculate bonus double bonus = 100.00; theCalculation = homecalc.create(); calc = theCalculation.calcBonus( multiplier, bonus); }catch(Exception CreateException){
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
12
CreateException.printStackTrace(); } //Display Data out.println("<H1>Bonus Calculation</H1>"); out.println("<P>Soc Sec: " + socsec + "<P>"); out.println("<P>Multiplier: " + multiplier + "<P>"); out.println("<P>Bonus Amount: " + calc + "<P>"); out.println("</BODY></HTML>"); out.close(); }
13
try{ Calc theCalculation; //Get Multiplier and Social Security Information String strMult = request.getParameter("MULTIPLIER"); Integer integerMult = new Integer(strMult); multiplier = integerMult.intValue(); socsec = request.getParameter("SOCSEC"); //Calculate bonus double bonus = 100.00; theCalculation = homecalc.create(); calc = theCalculation.calcBonus(multiplier, bonus); } catch(Exception CreateException){ CreateException.printStackTrace(); } //Display Data out.println("<H1>Bonus Calculation</H1>"); out.println("<P>Soc Sec: " + socsec + "<P>"); out.println("<P>Multiplier: " + multiplier + "<P>"); out.println("<P>Bonus Amount: " + calc + "<P>"); out.println("</BODY></HTML>"); out.close(); } public void destroy() { System.out.println("Destroy"); } }
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
14
La siguiente seccin muestra el cdigo del bean de sesin. El ejemplo asume que los ficheros /cursos/j2ee/L1/Beans/CalcBean.javaCalcBean.java , /cursos/j2ee/L1/Beans/Calc.java Calc.java, y /cursos/j2ee/L1/Beans/CalcHome.java CalcHome.java estn situados en el directorio /home/monicap La sentencia package Beans en la parte superior del interface CalcBean y los ficheros de clases es el mismo nombre que el nombre de este directorio. Cuando se compilen estos ficheros, se hara desde el directorio superior Beans y el nombre del paquete Beans (o directorio) se pretende que apunte al interface y los ficheros class compilados. Compilar el Bean de Sesin. Nota: Este ejemplo muestra cmo escribir un bean de sesin, pero tambin es posible comprar beans enterprise a un proveedor y ensamblarlos dentro de una aplicacin J2EE.
CalcHome
BonusServlet no trabaja directamente con el bean de sesin, sino que crea un ejemplar de su interface home. El interface home extiende EJBHome y tiene un mtodo create para crear el bean de sesin en su contendor. Se lanzar una CreateException si no se puede crear el bean de sesin y una RemoteException si ocurre una excepcin relacionada con las comunicaciones durante la ejecucin del mtodo remoto. package Beans; import java.rmi.RemoteException; import javax.ejb.CreateException; import javax.ejb.EJBHome; public interface CalcHome extends EJBHome { Calc create() throws CreateException, RemoteException; }
Calc
Cuando se crea el interface home, el servidor de aplicaciones J2EE crea el interface remoto y el bean de sesin. El interface remoto extiende EJBObject declara el mtodo calcBonus para el clculo del valor del bonos. Este mtodo requiere que se lance una javax.rmi.RemoteException, y est implementado por la clase CalcBean. package Beans; import javax.ejb.EJBObject; import java.rmi.RemoteException; public interface Calc extends EJBObject { public double calcBonus(int multiplier, double bonus) throws RemoteException; }
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
15
CalcBean
La clase del bean de sesin implementa el interface SessionBean y proporciona el comportamiento para el mtodo calcBonus. Los mtodos setSessionContext y ejbCreate son llamados en este orden por el contendor despus de que BonusServlet llame al mtodo create CalcHome. Los mtodos vacos son del inteface SessionBean. Estos mtodos los llama el contenedor del bean. No tenemos que proporcionar comportamiento para estos mtodos a menos que necesitemos funcionalidades adicionales, por ejemplo cuando el bean es aadido o eliminado de su contenedor. package Beans; import java.rmi.RemoteException; import javax.ejb.SessionBean; import javax.ejb.SessionContext; public class CalcBean implements SessionBean { public double calcBonus(int multiplier, double bonus) { double calc = (multiplier*bonus); return calc; } //These methods are described in more //detail in Lesson 2 public void ejbCreate() { } public void setSessionContext( SessionContext ctx) { } public void ejbRemove() { } public void ejbActivate() { } public void ejbPassivate() { } public void ejbLoad() { } public void ejbStore() { } }
16
Windows cd \home\monicap\J2EE set J2EE_HOME=\home\monicap\J2EE\j2sdkee1.2.1 set CPATH=.;%J2EE_HOME%\lib\j2ee.jar javac -d . -classpath %CPATH% Beans/CalcBean.java Beans/CalcHome.java Beans/Calc.java
Compilar el Servlet
Unix #!/bin/sh cd /home/monicap/J2EE/ClientCode J2EE_HOME=/home/monicap/J2EE/j2sdkee1.2.1 CPATH=.:$J2EE_HOME/lib/j2ee.jar: /home/monicap/J2EE javac -d . -classpath "$CPATH" BonusServlet.java Windows cd \home\monicap\J2EE\ClientCode set J2EE_HOME=\home\monicap\J2EE\j2sdkee1.2 set CPATH=.;%J2EE_HOME%\lib\j2ee.jar; \home\monicap\J2EE javac -d . -classpath %CPATH% BonusServlet.java
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
17
DeployTool
El herramienta DeployTool mostrada en la siguiente figura tiene cuatro ventanas principales. La ventana "Local Aplications" muestra las aplicaciones J2EE y sus componentes. La ventana "Inspecting" muestra informacin sobre la aplicacin o componentes seleccionados. La ventana "Servers" nos dice si el servidor de aplicaciones se est ejecutando en un host local. Y la ventana "Server Aplications" nos dice qu aplicaciones tenemos instaladas. Cuando sigamos los pasos para ensamblar la aplicacin de ejemplo J2EE, veremos que todas estas ventanas nos muestran informacin.
Nota:
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
18
A la derecha de la ventana Server Applications hay un botn gris Uninstall. Despus de desplegar la aplicacin, veremos la aplicacin listada en esta ventana. Podemos pulsar sobre Uninstall para desinstalarla, hacerle cambios, y reinstalarla sin tener que parar y rearrancar el servidor de aplicaciones.
Selector de Ficheros New Application: Localizamos el directorio donde queremos situar el fichero EAR de la aplicacin. En este ejemplo, este directorio es /home/monicap/J2EE . En el campo File name, tecleamos BonusApp.ear. Pulsamos sobre New Application . Pulsamos sobre OK.
En la ventana de Local Applications ahora aparecer " Bonusapp.ear", y en la ventana Inspector a la derecha muestyra el nombre, la localizacin y la informacin de contenidos para BonusApp . La meta informacin mostrada en la ventrana contents describe el fichero JAR y la aplicacin J2EE, y prorporciona informacin de tiempo de ejecucin sobre la aplicacin.
19
Caja de Dilogo Add Files to .JAR: vamos al directorio J2EE. Podemos teclear el nombre del path o usar el navegador para obetenerlo. Una vez en el directorio J2EE, hacemos doble click sobre beans para mostrar el contenido del directorio beans. Selecionamos Calc.class . Pulsamos sobre Add . Seleccionamos CalcHome.class . Pulsamos sobre Add . Seleccionamos CalcBean.class . Pulsamos sobre Add .
Nota Importante: La caja de dilogo Add Contents to .JAR se debera parecer a la de la figura siguiente. Las clases Enterprise Bean JAR se deberan mostrar con el prefijo del nombre de directorio Beans. Pulsamos OK. Ahora deberamos estar de nuevo en la caja de dilogo EJB JAR. Beans/Calc.class , Beans/CalcHome.class, y Beans/CalcBean.class deberan aparecer en la ventana Contents. Pulsamos Next.
Caja de dilogo General : Seleccionamos la siguiente informacin: classname: Beans.CalcBean Home interface: Beans.CalcHome Remote interface: Beans.Calc Bean type: Session y Stateless Especificamos el nombre (el nombre que aparece cuando el fichero JAR se aade a BonusApp en la ventana de "Local Applications"), y proporcionamos una descripcin para los contenidos del ficheros JAR. Display Name: CalcBean Description: Este fichero JAR contiene el bean de sesin CalcBean. Pulsamos sobre Next .
Caja de Dilogo Environment Entries: Este ejemplo no hace uso de las propiedades (entradas de entorno) pero nosotros si podramos: Pulsamos sobre Finish . Verificar que el fichero JAR se aadido realmente a la aplicacin J2EE: Vamos a la ventana "Local Applications" Pulsamos el grfico gris en frente de BonusApp . Veremos el fichero JAR CalcJar. Pulsamos el grfico gris en frente de CalcJar para ver el bean de sesin CalcBean.
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
20
WAR file: BonusApp Display name: BonusWar Description: Este fichero war contiene un servlet y una pgina HTML Pulsamos Add .
Caja de Dilogo Add Contents to WAR: Vamos el directorio ClientCode tecleando ClientCode despus de J2EE en el campo Root Directory. Seleccioamos bonus.html. Debemos asegurarnos de que WAR contents muestra el listado como bonus.html sin el directorio ClientCode precediendo al nombre. Pulsamos sobre Add .
Pulsamos sobre Next . Elegimos de nuevo el directorio ClientCode. Seleccionamos BonusServlet.class. Debemos asegurarnos de que WAR contents muestra el nombre de BonusServlet.class sin el directorio precediendo el nombre. Pulsamos sobre Add . Caja de Digolo Contents to WAR: La pantalla se debera parecer a la de la siguiente figura
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
21
Pulsamos Finish . Caja de digolo WAR File General Properties : Pulsamos Next . Caja de dilogo Choose Component Type: Selecccionamos Servlet (si no est ya seleccionado) Puslamos Next . Caja de Dilogo Component General Properties : Nos aseguramos de que BonusServlet est seleccionado para la clase Servlet. Introducimos un nombre ( BonusServlet ) y una descripcin. Podemos ignornar las selecciones de Startup y load sequence aqu porque este ejemplo slo usa un servlet. Caja de dilogo Component Initialization Parameters : Pulsamos Next . BonusServlet no usa ningn parmetro de inicializacin. Caja de dilogo Component Aliases:
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
22
Pulsamos Add . Tecleamos BonusAlias y pulsamos Return . Este es el mismo nombre de alias que pusimos en el campo ACTION del formulario HTML embebido en el fichero bonus.html. Pulsamos Finish .
En el panel de contenido, podemos ver que el fichero WAR contiene un fichero XML con informacin estructural y de atributos sobre la aplicacin web. el fichero bonus.html, y el fichero class BonusServlet. El formato del fichero WAR es donde van todas las clases servlet en un punto de entrada con Web-INF/classes. Sin embargo, cuando se despliega el fichero WAR, la clase BonusServlet se sita en un directorio raz de contexto bajo public_html. Esta situacin es la convencin parra servidores web compatibles con Servlet 2.2. Para cambiar el nombre o la descripcin: Ponemos el cursor en el campo apropiado en la ventana Lo cambiamos segn nuestros deseos Pulsamos la tecla Return para que las ediciones tengan efecto.
Contexto Raz: Pulsamos la pestaa Web Context en la parte superior de la ventana Inspecting. Veremos BonusWar en la columna de la izquierda. Tecleamos BonusRoot en la columna de la derecha Pulsamos la tecla Return. Durante el despliegue se crea el directorio BonusRoot bajo el directorio public_html en nuestra instalacin J2sdkee1.2 , y los ficheros bonus.html y BonusServlet se copian como muestra en la siguiente figura:
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
23
Alias:
En la ventana LocalApp, pulsamos BonusWar y luego BonusServlet Pulsamos la pestaa Aliases de la parte superior de la ventana Inspecting. Deberamos ver BonusAlias en el campo. Si BonusAlias no est ah, lo tecleamos y pulsamos Return.
Nota: En la versin 1.2 podramos obtener un error tests app.WebURI. Esto significa que la herramienta de desarrollo no puso una extensin .war al fichero WAR durante su creacin. Este es un bug menor y la apliacin J2EE se despliega bien sin notarlo. Desplegar: Desde el men Tools, elegimos Deploy Application . Se mostrar una caja de dilogo Deploy BonusApp. Debemos verificar que la seleccin Target Server es o localhost o el nombre del servidor donde se est ejecutando el J2EE.
Nota: No debemos seleccionar el check box Return Client Jar. La nica vez que necesitamos seleccionar este check box es cuando despleguemos una aplicacin solitaria para el programa cliente. Este ejemplo usa un servlet y una pgina HTML por eso no debemos seleccionarlo. Seleccionar este check box crea un fichero Jar con la informacin de despliegue necesaria para una aplicacin solitaria. Pulsamos Next. Nos aseguramos de que el nombre JNDI muestra calcs. Si no lo hace, lo tecleamos nosotros mismos y pulsamos la tecla Return. Pulsamos Next. Nos aseguramos de que el nombre Context Root muestra BonusRoot. Si no lo hace, lo tecleamos nosotros y pulsamos la tecla Return. Pulsamos Next . Pulsamos Finish para empezar el despliegue. Aparecer una caja de dilogo que mostrar el estado de la operacin de despliegue.
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
24
Cuando est completa, las tres barras de la izquierda estrn completamente sombreadas, como se ve en la siguiente figura. Cuando esto suceda, pulsamos OK.
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
25
BonusHome
La principal diferencia entre el bean de sesin CalcHome de la leccin anterior y el bean de entidad BonusHome de esta leccin es el mtodo findByPrimaryKey. Este mtodo de bsqueda toma la clave primaria como un parmetro. En este ejemplo, la clave primara es el nmero de la seguridad social, que se usa para recuperar la fila con el valor de la clave primaria que corresponde con el nmero de la seguridad social pasado a este mtodo. El mtodo create toma el valor del bono y de la clave primaria como parmetros. Cuando BonusServlet ejemplariza el interface home y llama a su mtodo create, el contenedor crea un ejemplar de BonusBean y llama a su mtodo ejbCreate. Los mtodos BonusHome.create y BonusBean.ejbCreate deben tener la misma firma , para que los valores del bono y la clave primaria puedan ser pasados desde el interface home al bean de entidad mediante el contenedor del bean de entidad. Si una fila para una clave primada dada (nmero de seguridad social) ya existe, se lanza una java.rmi.RemoteException que es manejada por el cdigo cliente BonusServlet. package Beans; import java.rmi.RemoteException; import javax.ejb.CreateException;
26
public interface BonusHome extends EJBHome { public Bonus create(double bonus, String socsec) throws CreateException, RemoteException; public Bonus findByPrimaryKey(String socsec) throws FinderException, RemoteException; }
Bonus
Despus de crear el interface home, el contenedor crea el interface remoto y el bean de entidad. El interface Bonus declara los mtodos getBonus y getSocSec para que el servlet pueda recuperar los datos desde el bean de entidad package Beans; import javax.ejb.EJBObject; import java.rmi.RemoteException; public interface Bonus extends EJBObject { public double getBonus() throws RemoteException; public String getSocSec() throws RemoteException; }
BonusBean
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
27
BonusBean es un bean de entidad controlado por contenedor. Esto significa que el contenedor maneja la persistencia de los datos y el control de las transaciones sin tener que escribir cdigo para transferir datos entre el bean de entidad y la base de datos o definir paquetes de transacciones. Si por alguna razn queremos que el bean de entidad maneje su propia persistencia o las transacciones, podramos proporcionar implementaciones para algunos de los mtodos vacos mostrados en el cdigo de BonusBean de abajo. Cuando BonusServlet llama a BonusHome.create, el contenedor llama al mtodo BonusBean.setEntityContext. El ejemplar de EntityContext pasado al mtodo setEntityContext tiene mtodos que permiten al bean devolver una referencia a s mismo o para obtener su clave primaria. Luego, el contenedor, llama al mtodo ejbCreate. Este mtodo asigna datos a las variables de ejemplar del bean, y luego el contenedor escribe los datos en la base de datos. Se llama al mtodo ejbPostCreate despus de ejbCreate y realiza cualquier proceso necesario despus de que se cree el bean. Este sencillo ejemplo no hace procesamiento postcreacin. Los otros mtodos vacos son mtodos de retrollamada usados por el contenedor para notificar al bean algn evento que va a ocurrir. Podramos proporcionar comportamiento para algunos de estos mtodos si estmos usando persistencia controlada por el bean, y otros si necesitamos proporcionar limpieza especfica del bean u operaciones de limpieza. Estas operaciones de limpieza e inicializacin tienen lugar en momentos especficos durante el ciclo de vida del bean, y el contenedor se lo notifica al bean y llama al mtodo aplicable en el momento apropiado. Aqu tenemos una breve descripcin de los mtodos vacos: Los mtodos ejbPassivate y ejbActivate los llama el contenedor antes de que el contenedor mueva el bean de su almacenamiento. Este proceso es similar al concepto de intercambio de una pgina de memoria virtual entre la memoria y el disco. El contenedor llama al mtodo ejbRemove si el interface home tiene el correspondiente mtodo remove que es llamado por el cliente. Los mtodos ejbLoad y ejbStore los llama el contenedor antes de que se sincronize el estado del bean con la base de datos subyacente.
Los mtodos getBonus y getSocSec son llamados por los clientes para recuperar datos almacenados en variables de ejemplar. Este ejemplo no tiene mtodos del tipo set< type >, pero si los tuviera, el cliente podra llamarlos para modificar los datos de las variables de ejemplar del bean. Cualquier cambio hecho en una variable de ejemplar resulta en una actualizacin de la fila de la tabla de la base de datos subyacente. package Beans; import import import import java.rmi.RemoteException; javax.ejb.CreateException; javax.ejb.EntityBean; javax.ejb.EntityContext;
public class BonusBean implements EntityBean { public double bonus; public String socsec; private EntityContext ctx; public double getBonus() { return this.bonus; } public String getSocSec() { return this.socsec; }
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
28
public String ejbCreate(double bonus, String socsec) throws CreateException{ //Called by container after setEntityContext this.socsec=socsec; this.bonus=bonus; return null; } public void ejbPostCreate(double bonus, String socsec) { //Called by container after ejbCreate } //These next methods are callback methods that //are called by the container to notify the //Bean some event is about to occur public void ejbActivate() { //Called by container before Bean //swapped into memory } public void ejbPassivate() { //Called by container before //Bean swapped into storage } public void ejbRemove() throws RemoteException { //Called by container before //data removed from database } public void ejbLoad() { //Called by container to //refresh entity Bean's state } public void ejbStore() { //Called by container to save //Bean's state to database } public void setEntityContext(EntityContext ctx){ //Called by container to set Bean context } public void unsetEntityContext(){ //Called by container to unset Bean context } }
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
29
Cambiar el Servlet
El cdigo de esta leccin es muy similar al de la pgina anterior con cambios en los mtodos init y doGet. El mtodo init de esta leccin busca el bean de sesin CalcBean, y el bean de entidad BonusBean. public class BonusServlet extends HttpServlet { CalcHome homecalc; BonusHome homebonus; Bonus theBonus, record; public void init(ServletConfig config) throws ServletException{ try { InitialContext ctx = new InitialContext(); Object objref = ctx.lookup("bonus"); Object objref2 = ctx.lookup("calcs"); homebonus=( BonusHome)PortableRemoteObject.narrow( objref, BonusHome.class); homecalc=(CalcHome) PortableRemoteObject.narrow( objref2, CalcHome.class); } catch (Exception NamingException) { NamingException.printStackTrace(); } } La sentencia try en el mtodo doGet crea los interfaces home de CalcBean y BonusBean. Despus de llamar a calcBonus para calcular el bono, se llama al mtodo BonusHome.create para crear un ejemplar del bean de entidad y la correspondiente fila en la tabla de la base de datos subyacente. Despus de crear la tabla, se llama al mtodo BonusHome.findByPrimaryKey para recuperar el mismo registro por su clave primaria (nmero de la seguridad social). Luego, se devuelve una pgina HTML al navegador mostrado los datos pasados originalmente, el bono calculado, y los datos recuperados desde la fila de tabla de la base de datos. La sentencia catch captura y maneja los valores de claves primaria duplicados (nmeros de seguridad social. La tabla de la base de datos subyacente no puede tener dos filas con la misma clave primaria, por eso si pasamos el mismo nmero de la seguridad social, el servlet captura el error antes de intentar crear el bean de entidad. En el evento de una clave duplicada, el servlet devuelve una pgina HTML con los datos pasados originalmente, el bono calculado, y un mensaje de error de clave duplicada: try { Calc theCalculation; //Retrieve Bonus and Social Security Information String strMult = request.getParameter( "MULTIPLIER");//Calculate bonus Integer integerMult = new Integer(strMult); multiplier = integerMult.intValue(); socsec = request.getParameter("SOCSEC"); //Calculate bonus double bonus = 100.00; theCalculation = homecalc.create(); calc = theCalculation.calcBonus( multiplier, bonus); //Create row in table
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
30
theBonus = homebonus.create(calc, socsec); record = homebonus.findByPrimaryKey(socsec); //Display data out.println("<H1>Bonus Calculation</H1>"); out.println("<P>Soc Sec passed in: " + theBonus.getSocSec() + "<P>"); out.println("<P>Multiplier passed in: " + multiplier + "<P>"); out.println("<P>Bonus Amount calculated: " + theBonus.getBonus() + "<P>"); out.println("<P>Soc Sec retrieved: " + record.getSocSec() + "<P>"); out.println("<P>Bonus Amount retrieved: " + record.getBonus() + "<P>"); out.println("</BODY></HTML>"); //Catch duplicate key error } catch (javax.ejb.DuplicateKeyException e) { String message = e.getMessage(); //Display data out.println("<H1>Bonus Calculation</H1>"); out.println("<P>Soc Sec passed in: " + socsec + "<P>"); out.println("<P>Multiplier passed in: " + multiplier + "<P>"); out.println("<P>Bonus Amount calculated: " + calc + "<P>"); out.println("<P>" + message + "<P>"); out.println("</BODY></HTML>"); } catch (Exception CreateException) { CreateException.printStackTrace(); } }
Compilar
Primero, compilamos el Bean de entidad y el servlet. Puedes volver a la leccin anterior para ver la configuracin del path, classpath y dnde situar los ficheros fuentes.
31
Compilar el Servlet
Unix: cd /home/monicap/J2EE/ClientCode J2EE_HOME=/home/monicap/J2EE/j2sdkee1.2.1 CPATH=.:$J2EE_HOME/lib/j2ee.jar:/home/monicap/J2EE javac -d . -classpath "$CPATH" BonusServlet.java Windows: cd \home\monicap\J2EE\ClientCode set J2EE_HOME=\home\monicap\J2EE\j2sdkee1.2.1 set CPATH=.;%J2EE_HOME%\lib\j2ee.jar; \home\monicap\J2EE javac -d . -classpath %CPATH% BonusServlet.java
Ensamblar y Desplegar
Los pasos de esta seccin son: Actualizar el Fichero de Aplicacin Crear el Bean de Entidad
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
32
El archivo web (WAR) contiene BonusServlet y bonus.html. Como hemos modificado BonusServlet, tenemos que actualizar la aplicacin J2EE con el nuevo cdigo del servlet. Ventana Local Applicatons: Iluminamos la aplicacin BonusApp. Men Tools Menu: Seleccionamos Update Application Files .
EJB JAR : Nos aseguramos de que BonusApp se ve en Enterprise Bean will go in field . Especificamos BonusJar como nombre. Pulsamos Add (el ms cercano a la ventana Contents).
Aadir Componentes al JAR: Cambiamos el directorio para que el directorio de beans muestre su contenido. Seleccionamos Bonus.class Pulsamos Add. Selecionamos BonusBean.class Pulsamos Add. Seleccionamos BonusHome.class Pulsamos Add. Pulsamos OK.
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
33
General : Beans.BonusBean es el nombre de la clase. Beans.BonusHome es el interface Home. Beans.Bonus es el interface Remoto. Introducimos BonusBean como nombre a mostrar. Pulsamos Entity . Pulsamos Next .
Configuracin Entity: Seleccionamos Container-Managed persistence . En la ventana inferior, marcamos bonus y socsec . Especificamos java.lang.String para la clase de la clave primaria. Observa que la clave primaria tiene que ser un tipo de clase. Los tipos primitivos no pueden ser claves primaria. Especificamos socsec para el nombre de campo de la clave primaria. Pulsamos Next .
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
34
Entradas de Entorno: Pulsamos Next. Este sencillo bean de entidad no usa propiedades (entradas de entorno). Referencias a Beans Enterprise: Pulsamos Next. Este sencillo bean de entidad no referencia otros beans enterprise. Referencias a Recursos: Pulsamos Next. Este sencillo bean de entidad no busca un objeto database o JavaMail session. Seguridad: Pulsamos Next. Este sencillo bean de entidad no usa roles de seguridad. Control de Transaccin : Seleccionamos Container-managed transactions (si no est ya seleccionado). En la lista hacemos que sean requeridos create, findByPrimaryKey, getBonus y getSocSec. Esto significa que el contenedor empieza una nueva transaccin antes de ejecutar estos mtodos. Las transacciones se envan justo antes de que los mtodos terminen.
Aplicaciones Locales: Seleccionamos BonusApp . En la ventana Inspecting, seleccionamos JNDI names La damos a BonusBean el nombre JNDI de bonus Pulsamos la tecla Return
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
35
Antes de poder desplegar la aplicacin J2EE, necesitamos especificar las condiciones de despliegue para el bean de entidad y generar el SQL. Aqu est cmo hacerlo: Ventana Local Applications: Seleccionamos BonusBean . Ventana Inspecting: Seleccionamos Entity Pulsamos el botn Deployment Settings de la parte inferior izquierda. Configuracin de Despliegue: Especificamos jdbc/Cloudscape (con una C mauscula en Cloudscape) para el nombre JNDI de la base de datos. Pulsamos Return. Nos aseguramos de que las cajas Create table on deploy y Delete table on Deploy estn marcadas. Ahora pulsamos Generate SQL .
Nota: Si obtenemos un error de que la conexin fue rechazada, arrancamos la base de datos como se describe en Arrancar la Plataforma y las Herramientas
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
36
Cuando se complete la generacin de SQL, seleccionamos el mtodo findByPrimaryKey en la caja EJB method. Aparecer una secuencia SQL a la derecha. Debera leerse SELECT "socsec" FROM "BonusBeanTable" WHERE "socsec"=?. El interrogante representa el parmetro pasado por el mtodo findByPrimaryKey. Pulsamos OK.
Nota: En la versin 1.2 del software podra obtener un error tests app.WebURI. La Aplicacin J2EE se desplegar de todas formas. Despliegue: En el Men Tools: Seleccionamos Tools.Deploy Application.
Nota: No marcamos la caja "Return Client Jar". El nico momento en que debemos chequear esta caja es cuando usamos persistencia controlada por el bean o desplegamos una aplicacin solitaria para el programa cliente. Este ejemplo usa un servlet y una pgina HTML por lo que no debe estr marcada. Esta caja crea un fichero JAR con toda la informacin de despliegue necesaria para una aplicacin solitaria. Pulsamos Next. Nos aseguramos de que JNDI names muestra calcs para CalcBean y bonus para BonusBean . Tecleamos cualquier nombre JNDI que no est y pulsamos la tecla Return. Pulsamos Next. Nos aseguramos que el nombre Context Root muestra BonusRoot. Si no lo hace, lo tecleamos nosotros mismos y pulsamos la tecla Return. Pulsamos Next. Pulsamos Finish para empezar el despliegue. Cuando se haya completado el despliegue, pulsamos OK.
37
Si volvemos al cdigo de bonus.html y cambiamos el multiplicador por 2, pero usamos el mismo nmero de la seguridad social, veremos esto: Bonus Calculation Soc Sec passed in: 777777777 Multiplier passed in: 2 Bonus Amount calculated: 200.0 Duplicate primary key.
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
38
CalcHome
El interface CalcHome no se modifica. Tiene el mismo mtodo create que devuelve un ejemplar del interface remoto. package Beans; import java.rmi.RemoteException; import javax.ejb.CreateException; import javax.ejb.EJBHome; public interface CalcHome extends EJBHome { public Calc create() throws CreateException, RemoteException; }
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
39
Calc
El mtodo calcBonus del interface Calc se ha modificado para tomar el nmero de la seguridad social como parmetro. Por eso CalcBean puede pasar el bono y el nmero de la seguridad social al bean de entidad despus de calcular el valor del bono. Se aade un nuevo mtodo getRecord para que CalcBean peuda encontrar el bean de entidad por sus clave primaria (el nmero de la seguridad social). Tambin, la firma del mtodo calcBonus lanza DuplicateKeyException y CreateException. Esto es por lo que BonusServlet puede capturar y manejar cualquiera de estas condiciones de excepcin. DuplicateKeyException desciende de CreateException. Si diseamos el mtodo calcBonus para lanzar DuplicateKeyException , pero capturamos CreateException, DuplicateKeyException no se lanzar. El atajo es hacer que calcBonus lance DuplicateKeyException y CreateException . package Beans; import javax.ejb.EJBObject; import java.rmi.RemoteException; import javax.ejb.DuplicateKeyException; import javax.ejb.CreateException; public interface Calc extends EJBObject { public Bonus calcBonus(int multiplier, double bonus, String socsec) throws RemoteException, DuplicateKeyException, CreateException; public Bonus getRecord(String socsec) throws RemoteException; }
CalcBean
El cdigo para crear el bean de entidad se ha movido desde BonusServlet hasta calcBonus para que el bono y el nmero de la seguridad social puedan escribirse en el bean de entidad despus de haber calculado el bono. La variable homebonus es una variable de ejemplar para que pueda ser usada en el mtodo calcBonus para buscar el bean de entidad y en el mtodo getRecord para localizar el bean de entidad correspondiente al nmero de la seguridad social. package Beans; import import import import import import import java.rmi.RemoteException; javax.ejb.SessionBean; javax.ejb.SessionContext; javax.naming.InitialContext; javax.rmi.PortableRemoteObject; javax.ejb.DuplicateKeyException; javax.ejb.CreateException;
public class CalcBean implements SessionBean { BonusHome homebonus; //Throw DuplicateKeyException and CreateException //so BonusServlet can catch and handle these //exception conditions.
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
40
public Bonus calcBonus(int multiplier, double bonus, String socsec) throws DuplicateKeyException, CreateException { Bonus theBonus = null; double calc = (multiplier*bonus); try { InitialContext ctx = new InitialContext(); Object objref = ctx.lookup("bonus"); homebonus = (BonusHome) PortableRemoteObject.narrow( objref, BonusHome.class); } catch (Exception NamingException) { NamingException.printStackTrace(); } //Store data in entity bean try { theBonus = homebonus.create(calc, socsec); } catch (java.rmi.RemoteException e) { String message = e.getMessage(); e.printStackTrace(); } return theBonus; } public Bonus getRecord(String socsec) { Bonus record = null; //Use primary key to retrieve data from entity bean try { record = homebonus.findByPrimaryKey(socsec); } catch (java.rmi.RemoteException e) { String message = e.getMessage(); } catch (javax.ejb.FinderException e) { e.printStackTrace(); } return record; } public void ejbCreate() { } public void setSessionContext( SessionContext context){ } public void ejbRemove() { } public void ejbActivate() { } public void ejbPassivate() { } public void ejbLoad() { } public void ejbStore() { } }
Cambiar el Servlet
El programa BonusServlet es muy similar a la versin de la Leccin anterior con algunos cambios en los mtodos init y doGet. El mtodo init para esta seccin slo busca el bean de sesin.
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
41
public class BonusServlet extends HttpServlet { CalcHome homecalc; //Need Bonus variables because CalcBean methods //called in the doGet method return instances //of type Bonus Bonus theBonus, record; public void init(ServletConfig config) throws ServletException{ try { InitialContext ctx = new InitialContext(); Object objref = ctx.lookup("calcs"); homecalc = (CalcHome) PortableRemoteObject.narrow( objref, CalcHome.class); } catch (Exception NamingException) { NamingException.printStackTrace(); } } La sentencia try del mtodo doGet calcula el bono, crea el interface home del bean de sesin y llama a los mtodos calcBonus y getRecord. Si el mtodo se completa con xito, se devuelve una pgina HTML que muestra los datos recuperados desde el bean de entidad. Si el mtodo calcBonus lanza una DuplicateKeyException, se devuelve una pgina HTML mostrando el nmero de la seguridad social y el multiplicador pasados, y un mensaje de excepcin, Duplicate primary key. Como en la leccin anterior, la sentencia catch captura y maneja valores de claves primarias duplicadas (nmeros de la seguridad social). try { Calc theCalculation; //Retrieve Bonus and Social Security Information String strMult = request.getParameter( "MULTIPLIER");//Calculate bonus Integer integerMult = new Integer(strMult); multiplier = integerMult.intValue(); socsec = request.getParameter("SOCSEC"); //Calculate bonus double bonus = 100.00; theCalculation = homecalc.create(); //Call session bean //Pass 3 parameters:multiplier, bonus, and socsec theBonus = theCalculation.calcBonus( multiplier, bonus, socsec); record = theCalculation.getRecord(socsec); //Display data returned by session bean out.println("<H1>Bonus Calculation</H1>"); out.println("<P>Soc Sec retrieved: " + record.getSocSec() + "<P>"); out.println("<P>Bonus Amount retrieved: " + record.getBonus() + "<P>"); out.println("</BODY></HTML>"); } catch (javax.ejb.DuplicateKeyException e) { String message = e.getMessage();
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
42
out.println("<H1>Bonus Calculation</H1>"); out.println("<P>Soc Sec passed in: " + socsec + "<P>"); out.println("<P>Multiplier passed in: " + multiplier + "<P>"); out.println("</BODY></HTML>"); } catch (Exception CreateException) { CreateException.printStackTrace(); }
Compilar
Primero compilamos el bean de sesin y el servlet. Puedes referirte a la primera leccin para ver la configuracin del path y del classpath y ms informacin sobre dnde situar los ficheros fuente.
Compilar el Servlet
Unix: cd /home/monicap/J2EE/ClientCode J2EE_HOME=/home/monicap/J2EE/j2sdkee1.2 CPATH=.:$J2EE_HOME/lib/j2ee.jar: /home/monicap/J2EE javac -d . -classpath "$CPATH" BonusServlet.java Windows: cd \home\monicap\J2EE\ClientCode set J2EE_HOME=\home\monicap\J2EE\j2sdkee1.2 set CPATH=.;%J2EE_HOME%\lib\j2ee.jar:\home\monicap\J2EE javac -d . -classpath %CPATH% BonusServlet.java
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
43
Ensamblar la Aplicacin
Los pasos de esta seccin incluyen: Crear una nueva aplicacin J2EE. Crear un nuevo componente Web. Empaquetar los Beans de Sesin y de Entidad en un fichero JAR.
Crear 2BeansApp : Desde el men File, seleccionamos New Application . Pulsamos con el botn derecho del ratn en el campo Application Display Name. Aparecer 2BeansApp como nombre. Pulsamos el botn Browse para abrir el selector de ficheros y seleccionar la localizacin donde queremos grabar el fichero EAR de la aplicacin.
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
44
Selector de ficheros New Application : Localizamos el directorio donde queremos situar el fichero de aplicacin EAR. En este ejemplo, el directorio es /export/home/monicap/J2EE. En el campo File name, tecleamos 2BeansApp.ear. Pulsamos New Application. Pulsamos OK.
War File General Properties : Especificamos BonusWar para el nombre. Pulsamos Add Vamos al directorio ClientCode y aadimos bonus.html Pulsamos Next Vamos al directorio ClientCode y aadimos BonusServlet.class Pulsamos Finish. War File General Properties : Pulsamos Next. Choose Component Type: . Nos aseguramos de seleccionar Describe a servlet. Pulsamos Next. Component General Properties : Hacemos la clase de servlet BonusServlet. Hacemos el nombre de display BonusServlet . Pulsamos Next. Component Initialization Parameters . Pulsamos Next. Component Aliases : Especificamos BonusAlias Pulsamos Finish. Ventana Inspecting:
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
45
46
Referencias a Recursos: Pulsamos Next. Este sencillo bean de sesin no busca ningn objeto de base de datos o sesin JavaMail. Seguridad: Pulsamos Next. Este sencillo bean de sesin no usa roles de seguridad. Control de Transaciones : Seleccionamos Container-managed transactions (si no lo est ya). En la lista de abajo hacemos necesarios calcBonus, y getRecord. Esto significa que el contenedor arranca una nueva transacin antes de ejecutar estos mtodos. La transacin se enva justo antes de que los mtodos terminen. Pulsamos Next. Revisar configuraciones: Pulsamos Finish . Local Applications: Seleccionamos 2BeansApp . En la ventana Inspecting seleccionamos JNDI names, le damos el nombre CalcBean JNDI de calcs, y pulsamos la tecla Return. Aadir el Bean de Entidad Con 2BeansApp seleccionado, File Menu: Seleccionamos New Enterprise Bean Introduction : Leemos y pulsamos Next. EJB JAR : Nos aseguramos de que 2BeansJar se muestra en el campo Enterprise Bean will go in . Esta seleccin aadir el nuevo bean al fichero JAR existente en lugar de ponerlo en un nuevo fichero JAR. Pulsamos Add (el ms cercano a la ventana Contents). Cambiamos el directorio para que el directorio Beans muestre su contenido. Seleccionamos Bonus.class Pulsamos Add . Seleccionamos BonusBean.class Pulsamos Add . Seleccionamos BonusHome.class Pulsamos Add. Enterprise Bean JAR classes : Nos aseguramos de ver Beans/Bonus.class , Beans/BonusHome.class, y Beans/BonusBean.class en el display. Pulsamos OK. EJB JAR : Pulsamos Next . General :
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
47
Nos aseguramos de que Beans.BonusBean es el nombre de la clase, Beans.BonusHome es el interface Home, y Beans.Bonus es el interface remoto. Introducimos BonusBean como nombre de pantalla. Pulsamos Entity . Pulsamos Next .
Entity Settings: Seleccionamos Container managed persistence . En la ventana inferior, marcamos bonus y socsec. la clase de clave primaria es java.lang.String, y el nombre del campo de la clave primaria es socsec. Observa que la clave primara tiene que ser un tipo de clase. Los tipos primitivos no son vlidos para claves primarias. Pulsamos Next . Environment Entries: Pulsamos Next . Este sencillo bean no usa propiedades (entradas de entorno). Enterprise Bean References: Pulsamos Next. Este sencillo bean no referencia otros beans enterprise. Resource References: Pulsamos Next. Este sencillo bean no busca objetos de base de datos ni sesiones JavaMail. Seguridad: Pulsamos Next. Este sencillo Bean no usa roles de seguridad. Control de Transaciones : Seleccionamos Container-managed transactions (si no lo est ya) En la lista de abajo hacemos necesarios create , findByPrimaryKey, getBonus y getSocSec. Esto significa que el contenedor arrancar una nueva transacin antes de ejecutar estos mtodos. La transacin se enva justo antes de que los mtodos terminen. Pulsamos Next . Review Settings: Pulsamos Finish . Local Applications: Seleccionamos 2BeansApp . En la ventana Inspecting, seleccionamos JNDI names, dando a BonusBean el nombre JNDI de bonus y a CalcBean el nombre JNDI de calcs Pulsamos la tecla Return despus de cada entrada. Antes de poder desplegar la aplicacin J2EE, necesitamos especificar las configuraciones de despliegue para el bean de entidad y generar el SQL: Ventana Local Applications: Seleccionamos BonusBean. Ventana Inspecting: Seleccionamos Entity Pulsamos el botn Deployment Settings inferior derecha.
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
48
Ventana Deployment Settings: Especificar jdbc/Cloudscape (con una C maysculas en Cloudscape) para el nombre JNDI de la base de datos. Pulsamos Return Nos aseguramos de que las cajas Create table on deploy y Delete table on Deploy estn marcadas. Ahora pulsamos Generate SQL . Nota: Si obtenemos un error de que la conexin fue rechazada, arrancamos de nuevo la base de datos como se describe en Arrancar la Plataforma y las Herramientas. Cuando se complete la generacin del SQL, Seleccionamos el mtodo findByPrimaryKey en la caja EJB method. Aparecer una sentencia SQL a la derecha. Debera ser SELECT "socsec" FROM "BonusBeanTable" WHERE "socsec"=?. El interrogante representa el parmetro pasado para el mtodo findByPrimaryKey. Pulsamos OK.
Nota: En la versin 1.2.1 del software podramos obtener un error tests app.WebURI. Esto significa que la herramienta DeployTool no puso la extensin .war al fichero WAR durante su creaccin. Es un error menor y la aplicacin J2EE se despliega sin problemas. Desplegar: Desde el men Tools, elegimos Deploy Application. Se mostrar una caja de dilogo Deploy BonusApp. Verificar que la seleccin de Target Server es un host local o el nombre de un host donde se est ejecutando el servidor J2EE. Nota: No marcamos la caja "Return Client Jar". El nico momento en que debemos chequear esta caja es cuando usamos persistencia controlada por el bean o desplegamos una aplicacin solitaria para el programa cliente. Este ejemplo usa un servlet y una pgina HTML por lo que no debe estr marcada. Esta caja crea un fichero JAR con toda la informacin de despliegue necesaria para una aplicacin solitaria. Pulsamos Next .
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
49
Nos aseguramos de que los nombres JNDI muestran calcs para CalcBean y bonus para BonusBean. Si no es as, tecleamos los nombres JNDI nosotros mismos, y pulsamos la tecla Return. Pulsamos Next. Nos aseguramos de que el nombre Context Root muestra BonusRoot. Si no es as, lo tecleamos nosotros mismos y pulsamos la tecla Return. Pulsamos Next . Pulsamos Finish para empezar el despliegue. Se mostrar una caja de dilogo que mostrar el estado de la operacin de despliegue. Cuando se haya completado, las tres barras de la izquierda se habrn sombreado completamente, como se ve en la siguiente figura. Cuando esto suceda pulsamos OK
50
51
Object objref = ctx.lookup("calcs"); CalcHome homecalc = (CalcHome) PortableRemoteObject.narrow( objref, CalcHome.class); %> <%-- Comment Scriptlet to create session Bean, call calcBonus method, and retrieve a database record by the social security number (primary key) --%> <% try { Calc theCalculation = homecalc.create(); Bonus theBonus = theCalculation.calcBonus( multiplier, bonus, socsec); Bonus record = theCalculation.getRecord(socsec); %> <%-- Comment HTML code to display retrieved data on returned HTML page. --%> <H1>Bonus Calculation</H1> Social security number retrieved: <%= record.getSocSec() %> <P> Bonus Amount retrieved: <%= record.getBonus() %> <P> <%-- Comment Scriptlet to catch DuplicateKeyException --%> <% } catch (javax.ejb.DuplicateKeyException e) { String message = e.getMessage(); %> <%-- Comment HTML code to display original data passed to JSP on returned HTML page --%> Social security number passed in: <%= socsec %> <P> Multiplier passed in: <%= strMult %> <P> Error: <%= message %> <%-- Comment Scriptlet to close try and catch block --%> <% } %> <%-- Comment HTML code to close HTML body and page --%> </BODY> </HTML>
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
52
Comentarios
Las primeras siete lneas de Bonus.jsp muestran un HTML normal seguido por un comentario JSP. Los comentarios JSP son similares a los comentarios HTML excepto en que empiezan con <%-- en lugar de <!--, que es como empiezan en HTML. Podemos usar comentarios JSP o HTML en una pgina HTML. Los comentarios HTML se envan al navegador web del cliente donde aparezcan como parte de la pgina HTML, y los comentarios JSP son eliminados y no aparecen en el HTML generado. Nota: Hemos visto que poner dos puntos (:) en un comentario JSP como en <%-- Comment: Scriptlet for import statements . . . creaba un error en tiempo de ejecucin que desapareca cuando eliminamos los dos puntos. <HTML> <HEAD> <TITLE>Bonus Calculation</TITLE> </HEAD> <%-- Comment Scriptlet for import statements <%@ indicates a jsp directive --%>
Directivas
Las directivas JSP son instrucciones procesadas por el motor JSP cuando la pgina JSP se traduce a un servlet. Las directivas usadas en este ejemplo le dicen al motor JSP que incluya ciertos paquetes y clases. Las directivas estn encerradas entre etiquetas de directiva <%@ y %>. <%@ page import="javax.naming.*" %> <%@ page import="javax.rmi.PortableRemoteObject" %> <%@ page import="Beans.*" %>
Declaraciones
Las declaraciones JSP nos permiten configurar variables para su uso posterior en expresiones o scriptlets. Tambin podemos declarar variables dentro de expresiones o scriptlets en el momento de usarlas. El mbito es toda la pgina JSP, no hay concepto de variables de ejemplar. Es decir, no tenemos que declarar variables de ejemplar para usar en ms de una expresin o scriptlet. Las declaraciones van encerradas entre etiquetas de declaracin <%! y %>. Podemos tener varias declaraciones. Por ejemplo, <%! double bonus; String text; %> . <%! String strMult, socsec; %> <%! Integer integerMult; %> <%! int multiplier; %> <%! double bonus; %>
Scriptlets
Los scriptlets JSP nos permiten embeber segmentos de cdigo java dentro de una pgina JSP. El codigo embebido se inserta directamente en el servlet generado que se ejecuta cuando se pide la pgina. Este scriptlet usa las variables declaradas en las directivas descritas arriba. Los Scriptlets van encerradas entre etiquetas <% y %>. <% strMult = request.getParameter("MULTIPLIER"); socsec = request.getParameter("SOCSEC"); integerMult = new Integer(strMult); multiplier = integerMult.intValue(); Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile 53
Variables Predefinidas
Un scriptlet puede usar las siguientes variables predefinidas: session, request, response, out , e in. Este ejemplo usa la variable predefinida request, que es un objeto HttpServletRequest. De igual forma, response es un objeto HttpServletResponse, out es un objeto PrintWriter, e in es un objeto BufferedReader. Las variables predefinidas se usan en los scriptlets de la misma forma que se usan en los servelts, excepto que no las declaramos. <% strMult = request.getParameter("MULTIPLIER"); socsec = request.getParameter("SOCSEC"); integerMult = new Integer(strMult); multiplier = integerMult.intValue(); bonus = 100.00; %>
Expresiones
La expresiones JSP nos permiten recuperar dinmicamente o calcular valores a insertar directamente en la pgina JSP. En este ejemplo, una expresin recupera el nmero de la seguridad social desde el bean de entidad Bonus y lo pone en la pgina JSP. <H1>Bonus Calculation</H1> Social security number retrieved: <%= record.getSocSec() %> <P> Bonus Amount retrieved: <%= record.getBonus() %> <P>
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
54
Modificar bonus.html
El nico cambio que necesitamos hacer a bonus.html es hacer que el parametro ACTION del formulario HTML invoque a Bonus.jsp en lugar de a BonusServlet . <HTML> <BODY BGCOLOR = "WHITE"> <BLOCKQUOTE> <H3>Bonus Calculation</H3> <FORM METHOD="GET" ACTION="Bonus.jsp"> <P> Enter social security Number: <P> <INPUT TYPE="TEXT" NAME="SOCSEC"></INPUT> <P> Enter Multiplier: <P> <INPUT TYPE="TEXT" NAME="MULTIPLIER"></INPUT> <P> <INPUT TYPE="SUBMIT" VALUE="Submit"> <INPUT TYPE="RESET"> </FORM> </FORM> </BLOCKQUOTE> </BODY> </HTML>
55
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
56
Nota: En la versin 1.2.1 del software podramos obtener un error tests app.WebURI. Esto significa que la herramienta DeployTool no puso la extensin .war al fichero WAR durante su creaccin. Es un error menor y la aplicacin J2EE se despliega sin problemas. Desplegar: Desde el men Tools, elegimos Deploy Application. Se mostrar una caja de dilogo Deploy BonusApp. Verificar que la seleccin de Target Server es un host local o el nombre de un host donde se est ejecutando el servidor J2EE
Nota: No marcamos la caja "Return Client Jar". El nico momento en que debemos chequear esta caja es cuando usamos persistencia controlada por el bean o desplegamos una aplicacin solitaria para el programa cliente. Este ejemplo usa un servlet y una pgina HTML por lo que no debe estr marcada. Esta caja crea un fichero JAR con toda la informacin de despliegue necesaria para una aplicacin solitaria. Pulsamos Next . Nos aseguramos de que los nombres JNDI muestran calcs para CalcBean y bonus para BonusBean. Si no es as, tecleamos los nombres JNDI nosotros mismos, y pulsamos la tecla Return. Pulsamos Next. Nos aseguramos de que el nombre Context Root muestra JSPRoot. Si no es as, lo tecleamos nosotros mismos y pulsamos la tecla Return. Pulsamos Next . Pulsamos Finish para empezar el despliegue. Se mostrar una caja de dilogo que mostrar el estado de la operacin de despliegue. Cuando se haya completado, las tres barras de la izquierda se habrn sombreado completamente, como se ve en la siguiente figura. Cuando esto suceda pulsamos OK.
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
57
58
de objetos. El Modelo proporciona la lgica de negocio de la aplicacn, la Vista es la presentacin en pantalla, y el Controlador es un objeto que maneja lo que sucede cuando el usuario interacta con la Vista. Un patrn de diseo describe un problema recurrente y sus soluciones cuando la solucin no es siempre exactamente la misma para cada recurrencia. La leccin sobre Tecnologa JSP se configur para que las pginas HTML y JSP proporcionaran la presentacin en pantalla (Vista) y manejar lo que sucedia cuando el usuario interacta con los datos (Controlador). Los beans de entidad y de sesin ( BonusBean y CalcBean ) son los objetos de la aplicacin o Modelo. Esta leccin usa una pgina JSP para la presentacin en pantalla (View), un JavaBean para manejar lo que sucede cuando el usuario interacta con la vista (Controlador), y los beans de entidad y de sesin para los objetos de aplicacin (Modelo). Separando el Controlador de la Vista permite al JavaBean servir como una envoltura para el bean de sesin y ofrece un ejemplo mucho ms claro de la separacin MVC. Una aplicacin que usa patrones de diseo es mucho ms sencilla de actualizar, mantener y manejar.
Sobre el Ejemplo
En la Leccin anterior, el interface de usuario de la aplicacin consiste en una pgina HTML con un formulario HTML. El formulario llama a la pgina JSP cuando el usuario pulsa el botn Submit de la pgina HTML. Otra forma de crear el interface de usuario es con una pgina JSP que incluya el formulario HTML, scriptlets JSP, y etiquetas especficas JSP para interactar con el JavaBean. Cuando se carga la pgina JSP, se muestra el formulario HTML y se ejecutan los escriptlets y las etiquetas especificas JSP para interactuar con el JavaBean. Como todava no se han suministrado datos, la pantalla se parecer a la de la siguiente figura
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
59
Cuando el usuario introduce algn dato y pulsa el botn Submit, se vuelve a mostrar el formulario HTML, y se ejecutan de
nuevo los scriptlets y las etiquetas especificas JSP con los datos suministrados. La pantalla se parecera algo a la de la siguiente figura. Esto es porque el parmetro ACTION del formulario HTML de bonus.jsp se llama a s mismo de forma recursiva. Si el usuario introduce el mismo nmero de la seguridad social, se devuelve un error de clave duplicada y se muestra sobre la pgina JSP como se muestra en la siguiente figura:
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
60
Crear bonus.jsp
El cdigo de bonus.jsp es bastante sencillo poque el cdigo que busca el bean de sesin y calcula el bono est ahora en el JavaBean. La primera parte del fichero contiene el cdigo HTML para crear el formulario. El cdigo para pasar los datos del formulario HTML al JavaBean est en la segunda parte del fichero. Abajo podemos ver el fichero bonus.jsp completo: <HTML> <BODY BGCOLOR = "WHITE"> <HEAD> <TITLE>Bonus Calculation</TITLE> </HEAD> <BLOCKQUOTE> <H3>Bonus Calculation</H3> <!--ACTION parameter calls this page--> <FORM METHOD="GET" ACTION="bonus.jsp"> <P> Enter social security Number: <P> <INPUT TYPE="TEXT" NAME="SOCSEC"></INPUT> <P> Enter Multiplier: <P> <INPUT TYPE="TEXT" NAME="MULTIPLIER"></INPUT> <P> <INPUT TYPE="SUBMIT" VALUE="Submit"> <INPUT TYPE="RESET"> </FORM> <!--Scriptlet and JavaBeans Tags start here --> <jsp:useBean id = "jbonus" class = "JBonusBean"/> <%! String sMult, ssec; %> <% sMult = request.getParameter("MULTIPLIER"); ssec = request.getParameter("SOCSEC"); %> <jsp:setProperty name = "jbonus" property="strMult" value="<%=sMult%>"/> <jsp:setProperty name = "jbonus" property="socsec" value="<%=ssec%>"/> Social security number retrieved: <jsp:getProperty name="jbonus" property="socsec"/>
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
61
<P> Bonus Amount retrieved: <jsp:getProperty name="jbonus" property="bonusAmt"/> <P> Error messages: <jsp:getProperty name = "jbonus" property="message"/> </BLOCKQUOTE> </BODY> </HTML>
Especificar el JavaBean
La siguiente etiqueta HTML especifica el JavaBean que se esta utilizando en este ejemplo. El parmetro id define un alias para usarlo como referencia al JavaBean, y el parmetro class especifica la clase JavaBean. En este ejemplo el id es jbonus y el class es JBonusBean. <jsp:useBean id = "jbonus" class = "JBonusBean"/>
Social security number retrieved: <jsp:getProperty name="jbonus" property="socsec"/> Las siguientes etiquetas realizan operaciones similares para los campos bonusAmt y message de la clase JBonusBean. <P> Bonus Amount retrieved: <jsp:getProperty name="jbonus" property="bonusAmt"/> <P> Error messages: <jsp:getProperty name = "jbonus" property="message"/>
63
int multiplier = integerMult.intValue(); try { double bonus = 100.00; Calc theCalculation = homecalc.create(); Bonus theBonus = theCalculation.calcBonus( multiplier, bonus, socsec); Bonus record = theCalculation.getRecord( socsec); bonusAmt = record.getBonus(); socsec = record.getSocSec(); } catch (javax.ejb.DuplicateKeyException e) { message = e.getMessage(); } catch (javax.ejb.CreateException e) { e.printStackTrace(); } catch (java.rmi.RemoteException e) { e.printStackTrace(); } return this.bonusAmt; } else { this.bonusAmt = 0; this.message = "None."; return this.bonusAmt; } } public String getMessage(){ return this.message; } public String getSocsec(){ return this.socsec; } public String getStrMult(){ return this.strMult; } public void setSocsec(String socsec) { this.socsec = socsec; } public void setStrMult(String strMult) { this.strMult = strMult; } }
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
64
El siguiente segmento de cdigo muestra las propiedades privadas de la clase JBonusBean. Esta clase tiene un correspondiente mtodo get<property> para cada campo y sus correspondientes mtodos set<property> para los campos strMult y socsec. public class JBonusBean { private String strMult, socsec, message; private double bonusAmt;
Constructor
El constructor JBonusBean busca el bean de sesin. public JBonusBean() { try{ InitialContext ctx = new InitialContext(); Object objref = ctx.lookup("calcs"); homecalc = (CalcHome) PortableRemoteObject.narrow( objref, CalcHome.class); } catch (javax.naming.NamingException e) { e.printStackTrace(); } }
Mtodos Set
JBonusBean tiene dos mtodos set (mtodos precedidos por la palabra set). Estos mtodos seleccionan propiedades (campos privados) con valores especificados. Los dos mtodos set son setSocsec y setStrMult para seleccionar los campos privados socsec y strMult (propiedades JavaBean) . En este ejemplo, los valores usados para las propiedades socsec y strMult vienen de las etiquetas setProperty name de la pgina JSP. El servidor J2EE usa la informacin suministrada en la siguiente etiqueta setProperty name para localizar el correspondiente mtodo set en JBonusBean (con el alias jbonus id ): <jsp:setProperty name = "jbonus" property="strMult" value="<%=sMult%>"/> <jsp:setProperty name = "jbonus" property="socsec" value="<%=ssec%>"/> En la clase JBonusBean, los mtodos set<property> siguen las convenciones de nombrado para que el servidor J2EE pueda mapear las etiquetas setProperty name del fichero JSP a los mtodos set<property> correctos para pasar los datos desde la pgina JSP al JavaBean. Con los mtodos set, el nombre de mtodo consiste en la palabra set y el nombre de la propiedad. El nombre de la propiedad es el nombre de uno de los campos privados de JBonusBean. Mientras que los nombres de campos por convencin empiezan siempre con una letra minscula, la segunda palabra de un nombre de mtodo siempre empieza con una myuscula. Por eso, para seleccionar el campo privado socsec, el nombre del mtodo es setSocsec. El servidor J2EE mapea la mayscula de Socsec en el nombre del mtodo a la minscula socsec del campo. Los mtodos set no tienen valor de retorno y tienen un argumento del tipo apropiado. public void setSocsec(String socsec) { this.socsec = socsec;
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
65
Mtodos Get
JBonusBean tiene cuatro mtodos get (mtodos precedidos por la palabra get ). Los mtodos Get obtienen y devuelven un valor de propiedad (valores de campos privados). Los cuatro mtodos get son getBonusAmt, getMessage, getSocsec, y getStrMult para devolver datos desde los campos privados bonusAmt, message , socsec , y strMult (propiedades JavaBean). En este ejemplo, los valores usados para seleccionar los campos bonusAmt y message vienen desde el mtodo getBonusAmt. La pgina JSP recupera los datos de las propiedades de JBonusBean usando las siguientes etiquetas getProperty name. La pgina JSP slo recupera los valores que le interesan, por eso podramos observar que aunque hay una propiedad en JBonusBean para el multiplicador (el campo strMult), este valor no es recuperado por la pgina JSP. Social security number retrieved: <jsp:getProperty name="jbonus" property="socsec"/> <P> Bonus Amount retrieved: <jsp:getProperty name="jbonus" property="bonusAmt"/> <P> Error messages: <jsp:getProperty name = "jbonus" property="message"/> Los mtodos Get siguen las mismas convenciones de nombres que los mtodos Set por eso la pgina JSP puede recuperar los datos del JBonusBean. Los mtodos Get siempre tienen un valor de retorno y no tienen argumentos. Podramos observar que aunque el mtodo getBonusAmt seleccciona valores de propiedades, realmente no necesita devolver ningn valor en este ejemplo, devuelve this.bonusAmt para evitar un error en tiempo de ejecucin del servidor J2EE. El mtodo getBonusAmt usa una sentencia if-else para manejar el caso cuando no se suministra ningn valor strMult. Cuando la pgina JSP se carga por primera vez, el usuario final no ha suministrado ningn dato, pero todas las etiquetas y scriptlets de la pgina son ejecutados de cualquier forma. En este caso, el valor de la propiedad strMult pasada a JBonusBean es null, lo que resulta en un multiplicador nulo y un valor nulo de bonusAmt. Ocurre un error de servidor cuando la pgina JSP obtiene e intenta mostrar el valor null de bonusAmt. Para evitar este error, bonusAmt se selecciona a cero en el caso de que se reciba un valor null desde la pgina JSP. public double getBonusAmt() { if(strMult != null){ Integer integerMult = new Integer(strMult); int multiplier = integerMult.intValue(); try { double bonus = 100.00; Calc theCalculation = homecalc.create(); Bonus theBonus = theCalculation.calcBonus( multiplier, bonus, socsec); Bonus record = theCalculation.getRecord(
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
66
socsec); bonusAmt = record.getBonus(); socsec = record.getSocSec(); } catch (javax.ejb.DuplicateKeyException e) { message = e.getMessage(); } catch (javax.ejb.CreateException e) { e.printStackTrace(); } catch (java.rmi.RemoteException e) { e.printStackTrace(); } return this.bonusAmt; } else { this.bonusAmt = 0; this.message = "None."; return this.bonusAmt; } } public String getMessage(){ return this.message; } public String getSocsec(){ return this.socsec; } public String getStrMult(){ return this.strMult; } public void setSocsec(String socsec) { this.socsec = socsec; } public void setStrMult(String strMult) { this.strMult = strMult; }
67
j2sdkee1.2.1\bin\cloudscape -start
Verificar: Con 2BeansApp seleccionado, elegimos Verifier desde el men Tools. En el dilogo que aparece, pulsamos OK. La ventana debera decir que no hay ningn fallo. Cerramos la ventana del verificador porque ahora estamos listos para desplegar la aplicacin.
Nota: En la versin 1.2.1 del software podramos obtener un error tests app.WebURI. Esto significa que la herramienta DeployTool no puso la extensin .war al fichero WAR durante su creaccin. Es un error menor y la aplicacin J2EE se despliega sin problemas. Desplegar: Desde el men Tools, elegimos Deploy Application. Se mostrar una caja de dilogo Deploy BonusApp. Verificar que la seleccin de Target Server es un host local o el nombre de un host donde se est ejecutando el servidor J2EE.
Nota: No marcamos la caja "Return Client Jar". El nico momento en que debemos chequear esta caja es cuando usamos persistencia controlada por el bean o desplegamos una aplicacin solitaria para el programa cliente. Este ejemplo usa un servlet y una pgina HTML por lo que no debe estr marcada. Esta caja crea un fichero JAR con toda la informacin de despliegue necesaria para una aplicacin solitaria. Pulsamos Next . Nos aseguramos de que los nombres JNDI muestran calcs para CalcBean y bonus para BonusBean. Si no es as, tecleamos los nombres JNDI nosotros mismos, y pulsamos la tecla Return. Pulsamos Next. Nos aseguramos de que el nombre Context Root muestra JSPRoot. Si no es as, lo tecleamos nosotros mismos y pulsamos la tecla Return. Pulsamos Next . Pulsamos Finish para empezar el despliegue. Se mostrar una caja de dilogo que mostrar el estado de la operacin de despliegue. Cuando se haya completado, las tres barras de la izquierda se habrn sombreado completamente, como se ve en la siguiente figura. Cuando esto suceda pulsamos OK.
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
69
Bonus Calculation Social Security number retrieved: 777777777 Bonus Amount Retrieved: 200.0 Si hemos suministrado dos veces el mismo nmero de la seguridad social, veremos algo similar a esto: Bonus Calculation Soc Sec passed in: 777777777 Multiplier passed in: 2 Error: Duplicate primary key
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
70
Cualquier programa capaz de analizar XML puede chequear etiquetas XML bien-formadas, y cualquier programa capaz de aplicar estilos XLS o especificaciones DTD a datos XML puede manejar datos que fueron etiquetados de forma inteligente. Por ejemplo, si un artculo titne dos etiquetas de ttulo, pero el DTD permite slo una, el programa devuelve un error. Chequear un documento XML contra un DTD es lo que se conoce como verificacin. Lo ms bonito sobre XML es que el etiquetado est separado de las hojas de estilos y DTD. Esto significa que podemos tener un documento XML y desde a muchas hojas de estilo o DTDs. Diferentes hojas de estilo nos permiten tener
diferentes presentaciones dependiendo de cmo se utilice el documento. Por ejemplo, un artculo en XML puede tener una hoja de estilo para diferentes web sites donde se va a publicar para que corresponda con el aspecto y comportamietno de cada site. Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile 71
La versin actual de J2EE no tiene un motor de "eXtensible Style sheet Language Transformation (XSLT)" por eso no es posible actualmente usar una hoja de estilo para hacer cosas como transformar un documento XML en HTML para mostrarlo.
Prlogo XML
La lnea <?xml version="1.0"?> es el prlogo XML. Un fichero XML siempre debe empezar con un prologo que lo identifique como un fichero XML. El prlo no es necesario si slo va a ser ledo por humanos, pero es buena idea incluirlo. Junto con la informacin de versin, el prlogo tambin puede incluir informacin de codificacin e informacin "standalone . Informacin de Codificacin: indica el conjunto de caracteres usado en los datos del documento. Unicode descomprimido se representa como <?xml version="1.0" encoding="UTF-8"?>. El conjunto de caracteres Western European y lenguaje Ingls se indica como: <?xml version="1.0" encoding="ISO8859-1"?>. Informacin Standalone: idnica si este documento usa informacin de otros ficheros. Por ejemplo, un documento XML podra relacionarse con una hoja de estilo para infomacin sobre cmo crear un interface de usuario e HTML, o un DTD para especificaciones de etiquetas vlidas.
Documento Raz
La etiqueta <report> es la primera etiqueta XML de este fichero. Es la etiqueta XML de ms alto nivel y marca el inicio de los datos del documento. Otro nombre para este nivel de etiqueta es root. Las etiquetas XML tienen su correspondiente etiqueta final, por eso el final de este documento tiene su correspondiente etiqueta </report> para cerrar la pareja. Podemos darle a una etiqueta XML cualquier nombre que queramos. Este ejemplo usa report porque el fichero XML es un informe de bonos. Podra haberse llamado <root> o <begin> o cualquier otra cosa. el nombre tiene significado en la hoja de estilo y en el DTD porque es donde asignamos especificaciones para las etiquetas por sus nombres.
Nodos Hijos
La etiqueta <bonusCalc> representa el informe de bonos. Esta etiqueta es un nodo hijo que se aade al raz. Usa atributos para especificar el nmero de la seguridad social y el valor del bono ( ssnum y bonusAmt ). Podemos definir un DTD para chequear que las etiquetas bonusCalc tienen los atributos ssnum y bonusAmt, y poder hacer que nuestro programa corriga un error si ha desaparecido algn atributo o si los atributos presentes no deberian estar ah. <bonusCalc ssnum="777777777" bonusAmt="300.0" />
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
72
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
import com.sun.xml.tree.XmlDocument; Esta versin de la clase JBonusBean tiene una variable ms de ejemplar. El interface remoto del bean de sesin, theCalculation, necesita ser accedido desde los mtodos getBonusAmt y genXML. Esto es porque genXML lee la base de datos para generar XML para todos los registros almacenados ene lla y tiene que poder acceder al mtodo getRecord del bean de sesin. Calc theCalculation; El mtodo JBonusBean.genXML es llamado desde el mtodo getBonusAmt despus de que el proceso se complete en el evento strMult y no sea null . Lo prmero que este mtodo hace es crear un objeto XMLDocument y el nodo raz, y aade la raz al documento. El nodo raz represetna el punto de ms alto nivel en el rbol del documento y es el punto donde empieza el procesamiento. private void genXML(){ Bonus records = null; //Create XML document XmlDocument doc = new XmlDocument(); //Create node ElementNode root = (ElementNode) doc.createElement("report"); //Add node to XML document doc.appendChild(root); Los bloques try y catch que vienen luego, obtienen el registro de la base de datos, recuperar el valor del bono y el nmero de la seguridad social desde el registro, convierte el valor del bono a un string, crea un nodo hijo ( bonusCalc ), y aade el nmero de la seguridad social y el bono al nodo hijo bonusCalc como atributos. El nodo hijo epresenta la herencia o rbol, y los atributos representan el tercer nivel. try{ //Get database record records = theCalculation.getRecord(socsec); //Retrieve the social security number from record String ssRetrieved = records.getSocSec(); //Retrieve bonus amount from record double bRetrieved = records.getBonus(); //Convert double to string Double bonusObj = new Double(bRetrieved); String bString = bonusObj.toString(); //Create child node ElementNode bonusCalc = (ElementNode) doc.createElement("bonusCalc"); //Add attributes to child node bonusCalc.setAttribute("ssnum", ssRetrieved); bonusCalc.setAttribute("bonusAmt", bString);
74
La ltima parte del mtodo genXML crea un objeto StringWriter, escribe la herencia del documento o rbol al objeto StringWriter, y escribe el objeto StringWriter al terminal. try{ StringWriter out = new StringWriter(); doc.write(out); System.out.println(out); } catch (java.io.FileNotFoundException fe) { System.out.println("Cannot write XML"); } catch (IOException ioe) { System.out.println("cannot write XML"); } El rbol o estructura del documento XML se llama Document Object Model (DOM). La siguiente figura muestra una representacin simplificada del DOM del ejemplo de esta leccin. Las llamadas al API en el mtodo genXML crea el DOM y podemos aplicar las llamadas al API para acceder al DOM paa hacer cosas como aadir, borrar y editar nodos hijos, o validar el DOM contra un DTD. Podemos crear un DOM desde un fichero XML.
Los APIs
El fichero j2ee.jar que viene con nuestra instalacin J2EE proporciona APIs para analizar y manipular datos XML. El fichero JAR realmente prporciona APIs XML para SAX, DOM y J2EE. Podemos usar cuaquier API que necesitamos como se muestra en la siguiente figura, el texto XML es independiente de la plataforma y el lenguaje de creaccin...
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
75
SAX y DOM
El API SAX es un mecanismo de acceso serial dirigido por eventos que hace un proceso elemento por elemento. El API DOM proporciona una estructura de objetos del tipo rbol relativamente familiar. Podemos usar el API DOM para manipular la herencia de los objetos que encapsula. El API DOM es ideal para aplicaciones interactivas porque el modelo completo del objeto est presente en la memoria, donde el usuario puede acceder a l y modificarlo. Construir el DOM requiere la lectura de la estructura XML completa y mantener el rbol de objetos en memoria, lo que significa mucho consumo de CPU y de memoria. Por esta razn, se tiende a preferir el API SAX para aplicaciones clienteservidor y para filtros de datos que no requieren una representacin de los datos en memoria.
J2EE
El API XML J2EE independiente de la plataforma usa un rbol DOM y proporciona muchos mtodos para manipularlo. los APIs XML J2EE estn en el paquete com.sun y se han utilizado en el ejemplo de esta leccin. No olvidemos que estos APIs estn sujetos a modificaciones.
Nota: La aplicacin BonusApp de la leccin anterior se desinstala automticamente. El servidor web se ejecuta por defecto en el puerto 8000. Para abrir la pgina bonus.jsp apuntamos el navegador a http://localhost:8000/JSPRoot/bonus.jsp, que es donde la herramietna Deploy puso la pgina JSP. Rellenamos un nmero de la seguridad social y un multiplicador. Pulsamos el botn Submit. Bonus.jsp procesa nuestros datos y devuelve una pgina HTML con el bono calculado.
76
La persistencia controlada por el bean es cuando nosotros escribimos mtodos de los beans de entidad o de sesin para usar los comandos SQL que le proporcionamos. La peristencia controlada por el bean puede ser util si necesitamos mejorar el rendimiento o mapear datos de varios beans en un fila de una tabla de base de datos. Esta leccin modifica el bean de entidad de la aplicacin de ejemplo J2EE para usar persistencia controlada por el bean.
77
el contenedor llama al mtodo ejbStore para envar el objeto a la base de datos y llama a ejbLoad para leerlo de nuevo. Cuando un cliente llama a un mtodo find, el contenedor llama a ejbLoad para inicializar el bean con los datos desde la base de datos subyacente. ejbActivate y ejbPassivate: El contenedor llama a estos mtodos para activar o desactivar el estado del bean. La activacin o desactivacin se refieren al intercambio del bean dentro y fuera del almacenamiento temporal para liberar memoria, que podra ocurrir si un bean dado no ha sido llamado por un cliente desde hace mucho tiempo. Las implementaciones de ejbPassivate podran incluir cosas como el cierre de conexiones o ficheros usados por el bean, y para ejbActivate podra incluir cosas como la reapertura de las mismas conexiones o ficheros.
Sentencias Import
Las interfaces InitialContext, DataSource, y Connection se importan para establecer conexiones con la base de datos. La interface PreparedStatement se importa para usarlo como plantilla para crear una peticin SQL. La interface ResultSet se importa para manejar accesos a filas de datos devueltas por una consulta. Las clases FinderException y SQLException se importan para manejar excepciones de bsqueda y accesos a bases de datos. package Beans; import java.rmi.RemoteException; import javax.ejb.CreateException; import javax.ejb.EntityBean; import javax.ejb.EntityContext; import javax.naming.InitialContext; import javax.sql.DataSource; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import javax.ejb.FinderException; import java.sql.SQLException;
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
78
Variables de Ejemplar
Las variables de ejemplar aadidas en esta leccin nos permiten establecer y cerrar conexiones con bases de datos. El string java:comp/env/jdbc/BonusDB indica el nombre de referencia para el recurso, que tambin deberamos especificar cuando aadamos el bean de entidad a la aplicacin J2EE usando la herramienta Deploy. En este ejemplo, la referencia de recursos es un alias a la base de datos Cloudscape ( CloudscapeDB) donde est almacenada la tabla de datos. Despus crearemos la tabla BONUS en CloudscapeDB, y durante el despliegue mapearemos jdbc/BonusDB a jdbc/CloudscapeDB . public class BonusBean implements EntityBean { private EntityContext context; private Connection con; private String dbName = "java:comp/env/jdbc/BonusDB"; private InitialContext ic = null; private PreparedStatement ps = null; private double bonus; private String socsec;
Mtodos de Negocio
Los mtodos de negocio no han cambiado para esta leccin excepto en las llamadas a System.out.println, que nos permiten ver el orden en que se llaman los mtodos de negocio y ciclo de vida durante la ejecucin. public double getBonus() { System.out.println("getBonus"); return this.bonus; } public String getSocSec() { System.out.println("getSocSec"); return this.socsec; }
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
79
Una cosa a observar de esta clase es que devuelve un valor String que es la clave primaria, pero la declaracin para este mtodo en el interface home espera recibir un ejemplar de la clase Bonus. El contenedor usa la clave primaria devuelta por este mtodo para crear un ejemplar de Bonus. public String ejbCreate(double bonus, String socsec) throws RemoteException, CreateException, SQLException { this.socsec=socsec; this.bonus=bonus; System.out.println("Create Method"); try { //Establish database connection ic = new InitialContext(); DataSource ds = (DataSource) ic.lookup(dbName); con = ds.getConnection(); //Use PreparedStatement to form SQL INSERT statement //to insert into BONUS table ps = con.prepareStatement( "INSERT INTO BONUS VALUES (? , ?)"); //Set 1st PreparedStatement value marked by ? , with //socsec and the 2nd value marked by ?) with bonus ps.setString(1, socsec); ps.setDouble(2, bonus); ps.executeUpdate(); } catch (javax.naming.NamingException ex) { ex.printStackTrace(); } finally { //Close database connection ps.close(); con.close(); } //Return primary key return socsec; } ejbPostCreate Este mtodo tiene la misma firma que ejbCreate, pero no tiene implementacin porque nuestro ejemplo no realiza procesamientos o inicializaciones posteriores a la creaccin. public void ejbPostCreate(double bonus, String socsec) throws RemoteException, CreateException, SQLException { System.out.println("Post Create"); } ejbFindByPrimaryKey La versin controlada por el contenedor de BonusBean no incluia una implementacin de ejbFindByPrimaryKey porque el contenedor podra localizar los registros de la base de datos por su clave primaria si especificamos persistencia
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
80
controlada por el contenedor y proporcionamos un campo de clave primaria durante el despliegue. En esta leccin, BonusBean se despliega con persistencia controlada por el bean por eso debemos proporcionar una implementacin para este mtodo y lanzar una SQLException. La versin controlada por contenedor slo lanzaba RemoteException y FinderException. Si la operacin find localiza un registro con la clave primaria pasada a ejbFindByPrimaryKey, se devuelve el valor de la clave primaria para que el contenedor pueda llamar al mtodo ejbLoad para inicializar BonusBean con los datos bonus y socsec recuperados. Una cosa a observar sobre esta clase es que devuelve un valor String que es la clave primaria, pero la declaracin para este mtodo en el interface home espera recibir un ejemplar de la clase Bonus. El contenedor usa la clave primaria devuelta por este mtodo para crear un ejemplar de Bonus. public String ejbFindByPrimaryKey(String primaryKey) throws RemoteException,FinderException, SQLException { System.out.println("Find by primary key"); try { //Establish database connection ic = new InitialContext(); DataSource ds = (DataSource) ic.lookup(dbName); con = ds.getConnection(); //Use PreparedStatement to form SQL SELECT statement //to select from BONUS table ps = con.prepareStatement( "SELECT socsec FROM BONUS WHERE socsec = ? "); ps.setString(1, primaryKey); //Use ResultSet to capture SELECT statement results ResultSet rs = ps.executeQuery(); //If ResultSet has a value, the find was successful, //and so initialize and return key if(rs.next()) { key = primaryKey; } else { System.out.println("Find Error"); } } catch (javax.naming.NamingException ex) { ex.printStackTrace(); } finally { //Close database connection ps.close(); con.close(); } //Return primary key return key; } ejbLoad Este mtodo se llama despus de una llamada exitosa a ejbFindByPrimaryKey para cargar y recuperar datos y sincronizar los datos del bean con los de la base de datos. public void ejbLoad() { System.out.println("Load method"); try {
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
81
//Establish database connection ic = new InitialContext(); DataSource ds = (DataSource) ic.lookup(dbName); con = ds.getConnection(); //Use PreparedStatement to form SQL SELECT statement //to select from BONUS table ps = con.prepareStatement( "SELECT * FROM BONUS WHERE SOCSEC = ?"); ps.setString(1, this.socsec); //Use ResultSet to capture SELECT statement results ResultSet rs = ps.executeQuery(); //If ResultSet has a value, the find was successful if(rs.next()){ this.bonus = rs.getDouble(2); } else { System.out.println("Load Error"); } } catch (java.sql.SQLException ex) { ex.printStackTrace(); } catch (javax.naming.NamingException ex) { ex.printStackTrace(); } finally { try { //Close database connection ps.close(); con.close(); } catch (java.sql.SQLException ex) { ex.printStackTrace(); } } } ejbStore Se llama a este mtodo cuando un cliente selecciona u obtiene datos en el bean para envar el objeto a la base de datos y mantener el bean y la base de datos sincronizados. public void ejbStore() { System.out.println("Store method"); try { //Establish database connection DataSource ds = (DataSource)ic.lookup(dbName); con = ds.getConnection(); //Use PreparedStatement to form SQL UPDATE statement //to update BONUS table ps = con.prepareStatement( "UPDATE BONUS SET BONUS = ? WHERE SOCSEC = ?"); //Set 1st PreparedStatement value marked by ? with //bonus and the 2nd value marked by ?) with socsec ps.setDouble(1, bonus); ps.setString(2, socsec); int rowCount = ps.executeUpdate(); } catch (javax.naming.NamingException ex) { ex.printStackTrace();
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
82
} catch (java.sql.SQLException ex) { ex.printStackTrace(); } finally { try { //Close database connection ps.close(); con.close(); } catch (java.sql.SQLException ex) { ex.printStackTrace(); } } } ejbRemove Se llama a este mtodo cuando un cliente llama al mtodo remove del interface home del bean. El cliente JavaBean de este ejemplo no proporciona un mtodo remove que el cliente pueda llamar para eliminar BonusBean desde su contenedor. De todas formas, aqu podemos ver la implementacin de un mtodo ejbRemove. cuando el contenedor llama a ejbRemove, ste obtiene la clave primaria (socsec) de la variable de ejemplar socsec, elimina el bean de su contenedor, y borra la correspondiente fila de la base de datos. public void ejbRemove() throws RemoteException { System.out.println("Remove method"); try { DataSource ds = (DataSource)ic.lookup(dbName); con = ds.getConnection(); ps = con.prepareStatement( "DELETE FROM BONUS WHERE SOCSEC = ?"); ps.setString(1, socsec); ps.executeUpdate(); } catch (java.sql.SQLException ex) { ex.printStackTrace(); } catch (Exception ex) { ex.printStackTrace(); try { ps.close(); con.close(); } catch (java.sql.SQLException ex) { ex.printStackTrace(); } } ejbActivate Cuando un bean no se ha utilizado durante mucho tiempo, el contenedor lo desactiva o lo mueve a un almacenamiento temporal donde el contenedor puede rpidamente reactivar el bean en el caso de que algn cliente llame a un mtodo de negocio del bean. Este mtodo llama al mtodo getPrimaryKey en el contexto de entidad para que la clave primaria est disponible para los clientes del bean. Cuando se hace una peticin, el contenedor usa la clave primaria para cargar los datos del bean. public void ejbActivate() { System.out.println("Activate method"); socsec = (String)context.getPrimaryKey(); } ejbPassivate
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
83
Cuando un bean no se ha utilizado durante mucho tiempo, el contenedor lo desactiva o lo mueve a un almacenamiento temporal donde el contenedor puede rpidamente reactivar el bean en el caso de que algn cliente llame a un mtodo de negocio del bean. Este mtodo selecciona la clave primaria a null para liberar memoria mientras el bean est desactivado. public void ejbPassivate() { System.out.println("Passivate method"); socsec = null; } setEntityContext El contenedor llama a este mtodo para inicializar la variable de ejemplar context del bean. Es necesario porque el mtodo ejbActivate llama al mtodo getPrimarykey sobre la variable de ejemplar context para pasar el bean del estado desactivado al de activado. public void setEntityContext( javax.ejb.EntityContext ctx){ System.out.println("setEntityContext method"); this.context = ctx; } unsetEntityContext El contenedor llama a este mtodo para poner a null la variable de ejemplar context despus de que se haya llamado al mtodo ejbRemove para eliminar el bean. Slo los beans de entidad tienen un mtodo unsetEntityContext. public void unsetEntityContext(){ System.out.println("unsetEntityContext method"); ctx = null; } }
84
objref, BonusHome.class); } catch (Exception NamingException) { NamingException.printStackTrace(); } //Store data in entity Bean theBonus=homebonus.create(calc, socsec); return theBonus; }
La clase JBonusBean tiene que modificarse para capturar la SQLException lanzada por CalcBean. DuplicateKeyExcpetion es una subclase de CreateException, por eso ser capturada por la sentencia catch (javax.ejb.CreateExceptione). public double getBonusAmt() { if(strMult != null){ Integer integerMult = new Integer(strMult); int multiplier = integerMult.intValue(); try { double bonus = 100.00; theCalculation = homecalc.create(); Bonus theBonus = theCalculation.calcBonus( multiplier, bonus, socsec); Bonus record = theCalculation.getRecord( socsec); bonusAmt = record.getBonus(); socsec = record.getSocSec(); } catch (java.sql.SQLException e) { this.bonusAmt = 0.0; this.socsec = "000"; this.message = e.getMessage(); } catch (javax.ejb.CreateException e) { this.bonusAmt = 0.0; this.socsec = "000"; this.message = e.getMessage(); } catch (java.rmi.RemoteException e) { this.bonusAmt = 0.0; this.socsec = "000"; this.message = e.getMessage(); } genXML(); return this.bonusAmt; } else { this.bonusAmt = 0; this.message = "None."; return this.bonusAmt; } }
85
Como este ejemplo usa persistencia controlada por el bean, tenemos que crear la tabla BONUS en la base de datos CloudscapeDB. Con persistencia controladda por el contenedor, la tabla se creaba automticamente. Para mantener las cosas sencillas, la tabla de la base de datos se crea con dos scripts: createTable.sql y cloudTable.sh (Unix) o cloudTable.bat (Windows/NT). Para este ejemplo, el escript createTable.sql va en nuestro directorio ~/J2EE/Beans, y el script cloudTable.sh (Unix) o cloudTable.bat (Windows/NT) va en nuestro directorio ~/J2EE. Para ejecutar estos scripts, vamos al directorio Beans y tecleamos los siguiente: Unix: ../cloudTable.sh Windows/NT: ..\cloudTable.bat
createTable.sql
Este fichero se proporciona con los ficheros fuentes de esta lecccin. drop table bonus; create table bonus (socsec varchar(9) constraint pk_bonus primary key, bonus decimal(10,2)); exit;
cloudTable.bat
Este fichero se proporciona con los ficheros fuentes de esta lecccin. rem cloudTable.bat rem Creates BONUS table in CloudscapeDB. rem rem Place this script in ~\J2EE rem To run: cd ~\J2EE\cloudTable.sh rem rem Change this next line to point to *your* rem j2sdkee1.2.1 installation rem set J2EE_HOME=\home\monicap\J2EE\j2sdkee1.2.1 rem rem Everything below goes on one line java -Dij.connection.CloudscapeDB= jdbc:rmi://localhost:1099/jdbc:cloudscape: CloudscapeDB\;create=true -Dcloudscape.system.home= %J2EE_HOME%\cloudscape -classpath %J2EE_HOME%iib\cloudscape\client.jar; %J2EE_HOME%iib\cloudscape\ tools.jar; %J2EE_HOME%iib\cloudscape\cloudscape.jar; %J2EE_HOME%iib\cloudscape\RmiJdbc.jar; %J2EE_HOME%iib\cloudscapeiicense.jar; %CLASSPATH% -ms16m -mx32m COM.cloudscape.tools.ij createTable.sql
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
86
cloudTable.sh
Este fichero se proporciona con los ficheros fuentes de esta lecccin. #!/bin/sh J2EE_HOME=/home/monicap/J2EE/j2sdkee1.2 java -Dij.connection.CloudscapeDB=jdbc:rmi: //localhost:1099/jdbc:cloudscape:CloudscapeDB\; create=true -Dcloudscape.system.home= $J2EE_HOME/cloudscape -classpath $J2EE_HOME/lib/cloudscape/client.jar: $J2EE_HOME/lib/cloudscape/tools.jar: $J2EE_HOME/lib/cloudscape/cloudscape.jar: $J2EE_HOME/lib/cloudscape/RmiJdbc.jar: $J2EE_HOME/lib/cloudscape/license.jar: ${CLASSPATH} -ms16m -mx32m COM.cloudscape.tools.ij createTable.sql
Clases Enterprise Bean JAR : Nos aseguramos de ver Beans/Bonus.class, Beans/BonusHome.class, y Beans/BonusBean.class en el display. Pulsamos OK.
EJB JAR :
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
87
Pulsamos Next .
General : Nos aseguramos de que Beans.BonusBean es el nombre de clase, Beans.BonusHome es el interface Home, y Beans.Bonus es el interface Remoto. Introducimos BonusBean como nombre de display. Pulsamos Entity . Pulsamos Next . Selecciones de Entidad: Seleccionamos Bean-managed persistence . La clase de clave primaria es java.lang.String, Observa que la clave primaria tiene que ser un tipo de clase, los tipos primitivos no son vlidos como claves primarias. Pulsamos Next
. Entradas de Entornio: Pulsamos Next. Este sencillo bean no usa propiedades (entradas de entorno). Referencias a Beans Enterprise: Pulsamos Next .
Referencias a Recursos: Pulsamos Add Tecleamos jdbc/BonusDB en la primera columna, debajo de Coded Name. Nos aseguramos de que Type es javax.sql.DataSource, y Authentication es Container . Pulsamos Next. Seguridad: Pulsamos Next. Este sencillo bean no usa roles de seguridad. Control de Transaccin : Seleccionamos Container-managed transactions (si no lo est ya). En la lista de abajo , marcamos como necesarios create , findByPrimaryKey, getBonus y getSocSec. Esto significa que el contenedor arranca una nueva transacin antes de ejecutar estos mtodos. La transacin se enva justo antes de que los mtodos terminen. Pulsamos Next . Revisin de Selecciones: Pulsamos Finish . Ventana Inspecting: Con 2BeansApp seleccionado pulsamos JNDI names. Asignamos calcs a CalcBean , bonus a BonusBean , y jdbc/Cloudscape a jdbc/BonusDB.
88
En el dilogo que aparece, pulsamos OK. La ventana debera decir que no hay ningn fallo. Cerramos la ventana del verificador porque ahora estamos listos para desplegar la aplicacin. Nota: En la versin 1.2.1 del software podramos obtener un error tests app.WebURI. Esto significa que la herramienta DeployTool no puso la extensin .war al fichero WAR durante su creaccin. Es un error menor y la aplicacin J2EE se despliega sin problemas. Desplegar: Desde el men Tools, elegimos Deploy Application. Se mostrar una caja de dilogo Deploy BonusApp. Verificar que la seleccin de Target Server es un host local o el nombre de un host donde se est ejecutando el servidor J2EE. Marcar la caja Return Client Jar. Al marcar esta caja se crea un ficher JAR con la informacin de despliegue necesaria por el bean de entidad. Pulsamos Next . Nos aseguramos de que los nombres JNDI muestran calcs para CalcBean, bonus para BonusBean y jdbc/Cloudscape para BonusDB. Si no es as, tecleamos los nombres JNDI nosotros mismos, y pulsamos la tecla Return. Pulsamos Next. Nos aseguramos de que el nombre Context Root muestra JSPRoot. Si no es as, lo tecleamos nosotros mismos y pulsamos la tecla Return. Pulsamos Next . Pulsamos Finish para empezar el despliegue. Se mostrar una caja de dilogo que mostrar el estado de la operacin de despliegue. Cuando se haya completado,pulsamos OK.
Ejecutar la Aplicacin
El servidor web se ejecuta por defecto en el puerto 8000. Para abrir la pgina bonus.html apuntamos nuestro navegador a http://localhost:8000/JSPRoot/bonus.html, que es dnde la herramienta de despliegue puso el fichero HTML. Rellenamos un nmero de la seguridad social y un multiplicador. Pulsamos el botn Submit. Bonus.jsp procesa nuestros datos y devuelve una pgina HTML con el bono calculado.
La salida del servidor J2EE podra mostrar los siguientes mensajes cada vez que se intente un acceso a la base de datos.
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
89
Estos mensajes significan que no se suministraron nombres de usuarios ni passwords para acceder a la base de datos. Podemos ignorar estos mensajes porque los nombres de usuario y las passwords no son necesarios para acceder a la base de datos Cloudscape, y este ejemplo funciona bien sin importarle estos mensajes
Cannot find principal mapping information for data source with JNDI name jdbc/Cloudscape Aqu tenemos una versin ms limpia de la salida del servidor J2EE (el mensaje de arriba fue editado) setEntityContext method Create Method Post Create setEntityContext method Find by primary key Load method getBonus Store method Load method getSocSec Store method Find by primary key Load method getSocSec Store method Load method getBonus Store method <?xml version="1.0"?> <report> <bonusCalc ssnum="777777777" bonusAmt="300.0" /> </report>
Hurfanos 835 piso 20 oficina 2003, Fonos: * 6322497- *6322102, Fax: 6322529 - www.ciisa.cl - Santiago Chile
90