Você está na página 1de 101

INTRODUCCIÓN A J2EE

Autor: Sun
Traductor: Juan Antonio Palos
Compilación en PDF: Javier Galdames
Indice
INTRODUCCIÓN............................................................................................. 5

1. UN SENCILLO BEAN DE SESIÓN ....................................................................... 7

1.1. EJEMPLO DE APLICACIÓN CLIENTE MULTI-CAPA........................................................................ 7


1.2. SOFTWARE J2EE Y CONFIGURACIÓN ................................................................................... 8
CONFIGURACIÓN DEL PATH Y CLASSPATH .................................................................................................... 9
1.3. COMPONENTES DE APLICACIÓN J2EE .................................................................................. 9
1.4. CREAR LA PÁGINA HTML ............................................................................................. 10
CÓDIGO HTML ............................................................................................................................. 12
1.5. CREAR EL SERVLET.................................................................................................... 13
SENTENCIAS IMPORT ........................................................................................................................ 13
MÉTODO INIT() ............................................................................................................................. 14
MÉTODO DOGET ............................................................................................................................ 14
CÓDIGO DEL SERVLET ....................................................................................................................... 15
1.6. CREAR EL BEAN DE SESSION ........................................................................................... 16
CALCHOME ................................................................................................................................. 17
CALC ....................................................................................................................................... 17
CALCBEAN .................................................................................................................................. 18
1.7. COMPILAR EL BEAN DE SESIÓN Y EL SERVLET .......................................................................... 18
COMPILAR EL BEAN DE SESSION ............................................................................................................. 19
COMPILAR EL SERVLET ...................................................................................................................... 19
1.8. ARRANCAR EL SERVIDOR DE APLICACIONES J2EE ..................................................................... 20
1.9. ARRANCAR LA HERRAMIENTA DEPLOYTOOL ........................................................................... 20
1.10. DEPLOYTOOL ....................................................................................................... 21
1.11. ENSAMBLAR LA APLICACIÓN J2EE................................................................................... 22
CREAR LA APLICACIÓN J2EE ................................................................................................................ 22
CREAR EL BEAN DE SESIÓN .................................................................................................................. 22
CREAR COMPONENTES WEB ................................................................................................................. 24
ESPECIFICAR EL NOMBRE JNDI Y EL CONTEXTO RAÍZ ........................................................................................ 27
1.12. VERIFICAR Y DESPLEGAR LA APLICACIÓN J2EE...................................................................... 28
1.13. EJECUTAR LA APLICACIÓN J2EE .................................................................................... 29
1.14. ACTUALIZAR EL CÓDIGO DE COMPONENTES .......................................................................... 30

2. AÑADIR UN BEAN DE ENTIDAD ..................................................................... 31

2.1. CREAR EL BEAN DE ENTIDAD .......................................................................................... 31


BONUSHOME ................................................................................................................................ 31
BONUS ...................................................................................................................................... 32
BONUSBEAN ................................................................................................................................ 33
2.2. CAMBIAR EL SERVLET ................................................................................................. 35
2.3. COMPILAR............................................................................................................. 36
COMPILAR EL BEAN DE ENTIDAD ............................................................................................................. 36
COMPILAR EL SERVLET ...................................................................................................................... 37
2.4. ARRANCAR LA PLATAFORMA Y LAS HERRAMIENTAS .................................................................... 37
2.5. ENSAMBLAR Y DESPLEGAR............................................................................................. 37
ACTUALIZAR EL FICHERO DE APLICACIÓN .................................................................................................... 38
CREAR EL BEAN DE ENTIDAD ................................................................................................................ 38
VERIFICAR Y DESPLEGAR LA APLICACIÓN J2EE .............................................................................................. 42
2.6. EJECUTAR LA APLICACIÓN J2EE ..................................................................................... 43

3. COMUNICACIONES ENTRE BEANS .................................................................. 45

3.1. CAMBIAR EL BEAN DE SESIÓN.......................................................................................... 45


CALCHOME ................................................................................................................................. 45
CALC ....................................................................................................................................... 46
CALCBEAN .................................................................................................................................. 46
3.2. CAMBIAR EL SERVLET ................................................................................................. 47
3.3. COMPILAR............................................................................................................. 48
COMPILAR EL BEAN DE SESIÓN .............................................................................................................. 48
COMPILAR EL SERVLET ...................................................................................................................... 49
3.4. ARRANCAR LA PLATAFORMA Y LAS HERRAMIENTAS .................................................................... 49
3.5. ENSAMBLAR LA APLICACIÓN ........................................................................................... 50
CREAR UNA NUEVA APLICACIÓN J2EE....................................................................................................... 50
CREAR UN NUEVO COMPONENTE WEB. ...................................................................................................... 50
EMPAQUETAR LOS BEANS DE SESIÓN Y DE ENTIDAD EN UN FICHERO JAR..................................................................... 51
3.6. VERIFICAR Y DESPLEGAR LA APLICACIÓN J2EE ....................................................................... 56
3.7. EJECUTAR LA APLICACIÓN J2EE...................................................................................... 57

4. TECNOLOGÍA JAVASERVER PAGES™ (JSP)........................................................ 59

4.1. CREAR LA PÁGINA JSP ............................................................................................... 59


COMENTARIOS .............................................................................................................................. 60
DIRECTIVAS ................................................................................................................................. 61
DECLARACIONES ............................................................................................................................ 61
SCRIPTLETS ................................................................................................................................. 61
VARIABLES PREDEFINIDAS ................................................................................................................... 61
EXPRESIONES ............................................................................................................................... 62
ETIQUETAS ESPECIFICAS DE JSP ............................................................................................................ 62
4.2. MODIFICAR BONUS.HTML .............................................................................................. 62
4.3. ARRANCAR LA PLATAFORMA Y LAS HERRAMIENTAS .................................................................... 63
4.4. ELIMINAR EL FICHERO WAR .......................................................................................... 63
4.5. VERIFICAR Y DESPLEGAR LA APLICACIÓN J2EE ....................................................................... 65
4.6. EJECUTAR LA APLICACIÓN J2EE...................................................................................... 66

5. TECNOLOGÍA JAVABEANS ........................................................................... 67

5.1. SOBRE EL EJEMPLO ................................................................................................... 67


5.2. CREAR BONUS.JSP .................................................................................................... 69
ESPECIFICAR EL JAVABEAN .................................................................................................................. 70
OBTENER LOS DATOS ....................................................................................................................... 70
PASAR LOS DATOS AL JAVABEAN ............................................................................................................ 70
RECUPERAR LOS DATOS DESDE EL JAVABEAN ................................................................................................ 71
5.3. CREAR LA CLASE JAVABEAN .......................................................................................... 71
PROPIEDADES DEL BEAN..................................................................................................................... 72
CONSTRUCTOR .............................................................................................................................. 73
MÉTODOS SET .............................................................................................................................. 73
MÉTODOS GET .............................................................................................................................. 74
5.4. ARRANCAR LA PLATAFORMA Y LAS HERRAMIENTAS .................................................................... 75
5.5. ELIMINAR EL FICHERO WAR .......................................................................................... 76
5.6. CREAR EL NUEVO FICHERO WAR ..................................................................................... 76
5.7. VERIFICAR Y DESPLEGAR LA APLICACIÓN J2EE ....................................................................... 77
5.8. EJECUTAR LA APLICACIÓN J2EE...................................................................................... 78

6. AÑADIR EXTENSIBLE MARKUP LANGUAGE (XML)................................................ 79

6.1. MARCAR Y MANEJAR TEXTO .......................................................................................... 79


6.2. MODIFICAR LA CLASE JAVABEAN ...................................................................................... 80
PRÓLOGO XML ............................................................................................................................. 80
DOCUMENTO RAÍZ .......................................................................................................................... 81
NODOS HIJOS ............................................................................................................................... 81
OTRAS ETIQUETAS XML..................................................................................................................... 81
CÓDIGO DEL JAVABEAN ..................................................................................................................... 82
6.3. LOS APIS ............................................................................................................. 84
SAX Y DOM ................................................................................................................................ 84
J2EE ....................................................................................................................................... 85
6.4. ACTUALIZAR Y EJECUTAR LA APLICACIÓN ............................................................................. 85

7. AÑADIR JDBC.......................................................................................... 87

7.1. CICLO DE VIDA DEL BEAN ............................................................................................. 87


7.2. MODIFICAR EL CÓDIGO DE BONUSBEAN ................................................................................ 88
SENTENCIAS IMPORT ........................................................................................................................ 89
VARIABLES DE EJEMPLAR .................................................................................................................... 89
MÉTODOS DE NEGOCIO...................................................................................................................... 89
MÉTODOS DE CICLO DE VIDA ................................................................................................................ 90
7.3. MODIFICAR EL CÓDIGO DE CALCBEAN Y JBONUSBEAN ................................................................ 95
7.4. CREAR LA TABLA DE LA BASE DE DATOS .............................................................................. 96
CREATETABLE.SQL .......................................................................................................................... 96
CLOUDTABLE.BAT........................................................................................................................... 96
CLOUDTABLE.SH ............................................................................................................................ 97
7.5. ELIMINAR EL FICHERO JAR ........................................................................................... 97
7.6. VERIFICAR Y DESPLEGAR LA APLICACIÓN .............................................................................. 99
7.7. EJECUTAR LA APLICACIÓN .......................................................................................... 100
Introducción
Este tutorial presenta los APIs, las herramientas y los servicios que
proporciona la Implementación de Referencia de Java 2 Enterprise Edition
(J2EE).

Podemos obtener la implementación de referencia J2EE para


demostraciones, prototipos y uso educacional en
http://java.sun.com/j2ee/download.html.

Para soportar estos usos, la Implementación de Referencia viene con


herramientas de desarrollo y despliegue J2EE, Java WebServer, base de datos
Cloudscape, servidor de aplicaciones Java Software, soporte de Extensible
Markup Language (XML), y los APIs J2EE.
Capítulo 1.Un Sencillo Bean de Sesión 7

1. Un Sencillo Bean de Sesión


Esta lección nos presenta la programación de aplicaciones J2EE, y el SDK J2EE
mostrándonos como escribir una sencilla y pequeña aplicación Enterprise
multi-capa que consiste en una página HTML, un servlet y un Bean de sesión.

El SDK J2EE es una definición y especificación 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 características
y herramientas según vayamos avanzando en este tutorial.

1.1. Ejemplo de Aplicación Cliente Multi-Capa

La pequeña aplicación cliente de ejemplo de esta lección acepta entrada de


usuario a través de un formulario HTML que invoca un servlet. El servlet usa el
API JNDI (Java Naming and Directory Interface™) para buscar un Bean de
sesión que realice los cálculos por él.

Este ejemplo es una aplicación pequeña porque el servlet no ejecuta ninguna


lógica de negocio. El sencillo cálculo lo realiza un Bean de sesión que se
ejecuta en el servidor de aplicaciones J2EE. Por eso el cliente es pequeño,
porque no maneja el proceso; lo hace el Bean de sesión.

Las aplicaciones multi-capa pueden consistir en 3 ó 4 capas. Como se ve en la


, el ejemplo multi-capa para este tutorial tiene cuatro capas. La arquitectura
de tres capas extiende al cliente estándar de dos capas y el modelo del
servidor situando un servidor de aplicaciones multi-capa entre la aplicación
cliente no-basada-en-web y la base de datos final. La arquitectura de cuatro
capas extiende el modelo de tres capas reemplazando la aplicación cliente
con un navegador Web y una página HTML potenciada con las tecnologías
servlet/JavaServer Pages™.
8 Introducción a J2EE

Mientras que esta lección usa sólo tres o cuatro capas, la siguiente lección
extiende este mismo ejemplo para acceder al servidor de base de datos en la
cuarta capa. Lecciones posteriores adaptan el ejemplo para usar las
tecnologías JavaServer™ Pages y Extensible Markup Language (XML).

1.2. Software J2EE y Configuración

Para ejecutar los ejemplos del tutorial, necesitas descargar e instalar el SDK
Java 2 Enterprise Edition (J2EE), Versión 1.2.1
(http://java.sun.com/j2ee/download.html), y SDK Java 2, Standard Edition
(J2SE), Versión 1.2 o posterior (http://java.sun.com/jdk/index.html).

Las instrucciones de este tutorial asumen que J2EE y J2SE están instalados en
el directorio J2EE debajo del directorio home del usuario.

Nota:
Siempre que se utilice monicap en un nombre de path, tendrás que cambiarlo
por tu nombre de usuario.

Unix:

/home/monicap/J2EE/j2sdkee1.2.1
/home/monicap/J2EE/jdk1.2.2

Windows:

\home\monicap\J2EE\j2sdkee1.2.1
\home\monicap\J2EE\jdk1.2.2
Capítulo 1.Un Sencillo Bean de Sesión 9

Configuración del Path y ClassPath

La descarga contiene el servidor de aplicaciones J2EE, la base de datos


Cloudscape, un servidor Web que usa capas de socket seguras (SSL) también
conocido como HTTP sobre HTTPS, herramientas de desarrollo y despliegue, y
los APIs Java para Enterprise. Para usar estar características, debemos
configurar las variables de entorno path y classpath como se describe aquí:

Configuración del Path

La configuración del Path hace accesibles las herramientas de desarrollo y


despliegue desde cualquier lugar de nuestro sistema. Debemos asegurarnos de
seleccionar estos path antes de cualquier otro path que pudiéramos tener de
viejas instalaciones del JDK.

Unix:

/home/monicap/J2EE/jdk1.2.2/bin
/home/monicap/J2EE/j2sdkee1.2.1/bin

Windows:

\home\monicap\J2EE\jdk1.2.2\bin
\home\monicap\J2EE\j2sdkee1.2.1\bin
Configuración del ClassPath

La configuración del ClassPath le dice a las herramientas de desarrollo y


despliegue de Java 2 dónde encontrar las distintas librerías de clases que usa:

Unix:

/home/monicap/J2EE/j2sdkee1.2.1/lib/j2ee.jar

Windows:

\home\monicap\J2EE\j2sdkee1.2.1\lib\j2ee.jar

1.3. Componentes de Aplicación J2EE

Los programadores de aplicaciones J2EE escriben componentes de aplicación


J2EE. Un componente J2EE es una unidad de software funcional auto-
contenida que se ensambla dentro de una aplicación J2EE y que se comunica
con otros componentes de aplicación. La especificación J2EE define los
siguientes componentes de aplicación:

• Componentes de Aplicación Cliente


• Componentes JavaBeans Enterprise
• Componentes Servlets y JavaServer Pages (también llamados
componentes Web)
10 Introducción a J2EE

• Applets

En esta lección, crearemos una aplicación y dos componentes J2EE: un servlet


y un Bean de sesión. El servlet está empaquetado con su fichero HTML en un
fichero Web Archive (WAR), y las clases e interfaces del Bean de sesión están
empaquetadas en un fichero JAR. Los ficheros WAR y JAR se añaden a la
aplicación J2EE y se empaquetan dentro de un fichero Enterprise Archive
(EAR) para probar, verificar y desplegar el entorno de producción.

Mientras estemos haciendo todos estos pasos para esta lección, realmente
estaremos realizando varias funciones diferentes. Escribir el código del servlet
y del Bean de sesión es una función de desarrollo, mientras que crear la
aplicación J2EE y añadir los componentes J2EE a una aplicación es una función
de ensamblaje. En realidad, estas funciones podrían ser realizadas por
diferentes personas de diferentes compañías.

1.4. Crear la Página HTML


bonus.html

<HTML>
<BODY BGCOLOR = "WHITE">

<BLOCKQUOTE>

<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>
Capítulo 1.Un Sencillo Bean de Sesión 11

BonusServlet.java

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import javax.naming.*;
import javax.rmi.PortableRemoteObject;
import Beans.*;

public class BonusServlet extends HttpServlet {


CalcHome homecalc;

public void init(ServletConfig config) throws ServletException{

//Look up home interface


try {
InitialContext ctx = new InitialContext();
Object objref = ctx.lookup("calcs");
homecalc = (CalcHome)PortableRemoteObject.narrow(objref, CalcHome.class);
} catch (Exception NamingException) {
NamingException.printStackTrace();
}
}

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{
Calc theCalculation;

//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){
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");
}
}
12 Introducción a J2EE

El fichero bonus.html tiene dos campos de datos en los que usuario puede
introducir un número de seguridad social y un multiplicador. Cuando el
usuario pulsa el botón Submit, BonusServlet.java recupera el dato del usuario,
busca el Bean de sesión, y le pasa el dato del usuario al Bean de sesión. el
Bean de sesión calcula un valor "bonus" y lo devuelve al servlet. El servlet
devuelve otra página HTML con el valor del "bonus" para que lo vea el usuario.

La siguiente Figura muestra el flujo de los datos entre el navegador y el Bean


de sesión. El Bean de sesión se ejecuta en el servidor de aplicaciones J2EE.

Código HTML

Lo más interesante sobre el código del formulario HTML es el alias usado para
invocar a BonusServlet. Cuando el usuario pulsa el botón Submit sobre el
formulario HTML, se llama a BonusServlet porque se ha mapeado a BonusAlias
durante el ensamblaje de la aplicación descrito en Ensamblar la Aplicación
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:
Capítulo 1.Un Sencillo Bean de Sesión 13

<HTML>
<BODY BGCOLOR = "WHITE">
<BLOCKQUOTE>
<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>

1.5. Crear el Servlet

El ejemplo asume que el fichero BonusServlet.java está en el directorio


/home/monicap/J2EE/ClientCode en UNIX. Durante la ejecución, el código
del servlet hace lo siguiente:

• Recupera los datos del usuario


• Busca el bean de sesión
• Le pasa los datos al bean de sesión
• Después de recibir un valor de vuelta desde el bean de sesión, crea una
página HTML para mostrar el valor devuelto al usuario.

La siguiente sección describe las diferentes partes del código del servlet.

Sentencias Import

El código del servlet empieza con sentencias import para los siguientes
paquetes:

• javax.servlet, que contiene clases servlets genéricas (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 señalar que se ha producido
una excepción de algún 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 sesión.
• javax.rmi para buscar el interface home del bean de sesión y poner su
objeto servidor remoto listo para las comunicaciones.
14 Introducción a J2EE

Método init()

El método BonusServlet.init busca el interface home del bean de sesión y crea


su ejemplar. El método usa el nombre JNDI especificado durante el
ensamblado de componentes (calcs) para obtener una referencia al interface
home por su nombre. La siguiente línea pasa la referencia y la clase del
interface home al método 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);

Método doGet

La lista de parámetros de doGet toma un objeto request y un response. El


navegador envía una petición (request) al servlet y el servlet envía una
respuesta (response) de vuelta al navegador. La implementación del método
accede a información del objeto request para encontrar quién ha hecho la
petición, en qué formulario están los datos de la petición, y que cabeceras
HTTP se enviarón, y usa el objeto response para crear una página HTML en
respuesta a la petición del navegador.

El método doGet lanza una IOException si hay algún problema con los datos
de entrada o salida cuando maneja la petición, y una ServletException si la
petición no se puede manejar. Para calcular el valor del bonus, el método
doGet crea el interface home y llama al método 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){
CreateException.printStackTrace();
}

//Display Data
out.println("<H1>Bonus Calculation</H1>");
out.println("<P>Soc Sec: " + socsec + "<P>");
Capítulo 1.Un Sencillo Bean de Sesión 15

out.println("<P>Multiplier: " +
multiplier + "<P>");
out.println("<P>Bonus Amount: " + calc + "<P>");
out.println("</BODY></HTML>");
out.close();
}

Código del Servlet

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import javax.naming.*;
import javax.rmi.PortableRemoteObject;
import Beans.*;

public class BonusServlet extends HttpServlet {


CalcHome homecalc;

public void init(ServletConfig config)


throws ServletException{

//Look up home interface


try{
InitialContext ctx = new InitialContext();
Object objref = ctx.lookup("calcs");
homecalc =
(CalcHome)PortableRemoteObject.narrow(
objref,
CalcHome.class);
} catch (Exception NamingException) {
NamingException.printStackTrace();
}
}
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{
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() {
16 Introducción a J2EE

System.out.println("Destroy");
}
}

1.6. Crear el Bean de Session

Un bean de sesión representa una conversación temporal con un cliente. Si el


servidor o el cliente, se cuelgan, el bean de sesión y sus datos se van. En
contraste, los beans de entidad son persistentes y representan datos en una
base de datos. Si el servidor o el cliente se bloquean, los servicios
relacionados aseguran que los datos del bean de entidad se graban.

La siguiente Figura muestra como funcionan el servlet y el bean de sesión


como una aplicación J2EE completa una vez que se han ensamblado y
desplegado. El contenedor, mostrado en la caja sombreada, es el interface
entre el bean de sesión y las funcionalidades especificas de la plataforma de
bajo-nivel que soporta el bean de sesión. El contenedor se crea durante el
despliegue.

La siguiente sección muestra el código del bean de sesión. El ejemplo asume


que los ficheros CalcBean.java , Calc.java, y CalcHome.java están situados en
el directorio /home/monicap/J2EE/Beans.
CalcBean.java

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;
}

public void ejbCreate() { }


public void setSessionContext(
SessionContext ctx) { }
public void ejbRemove() { }
public void ejbActivate() { }
public void ejbPassivate() { }
public void ejbLoad() { }
public void ejbStore() { }
}
Capítulo 1.Un Sencillo Bean de Sesión 17

Calc.java

package Beans;

import javax.ejb.EJBObject;
import java.rmi.RemoteException;

public interface Calc extends EJBObject {


public double calcBonus(int multiplier, double bonus) throws RemoteException;
}

CalcHome.java

package Beans;

import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;

public interface CalcHome extends EJBHome {


Calc create() throws CreateException, RemoteException;
}

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 Sesión.

Nota:
Este ejemplo muestra cómo escribir un bean de sesión, pero también es
posible comprar beans enterprise a un proveedor y ensamblarlos dentro de
una aplicación J2EE.

CalcHome

BonusServlet no trabaja directamente con el bean de sesión, sino que crea un


ejemplar de su interface home. El interface home extiende EJBHome y tiene
un método create para crear el bean de sesión en su contendor. Se lanzará
una CreateException si no se puede crear el bean de sesión y una
RemoteException si ocurre una excepción relacionada con las comunicaciones
durante la ejecución del método 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 sesión. El interface remoto extiende EJBObject
declara el método calcBonus para el cálculo del valor del bonos. Este método
18 Introducción a J2EE

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;
}

CalcBean

La clase del bean de sesión implementa el interface SessionBean y


proporciona el comportamiento para el método calcBonus. Los métodos
setSessionContext y ejbCreate son llamados en este orden por el contendor
después de que BonusServlet llame al método create CalcHome.

Los métodos vacíos son del inteface SessionBean. Estos métodos los llama el
contenedor del bean. No tenemos que proporcionar comportamiento para
estos métodos a menos que necesitemos funcionalidades adicionales, por
ejemplo cuando el bean es añadido 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() { }
}

1.7. Compilar el Bean de Sesión y el Servlet

Para ahorrarnos tecleado, la forma más sencilla para compilar el bean de


sesión y el servlet es con un script (en Unix) o un fichero batch (en Windows).
Capítulo 1.Un Sencillo Bean de Sesión 19

Compilar el Bean de Session

Unix

#!/bin/sh
cd /home/monicap/J2EE
J2EE_HOME=/home/monicap/J2EE/j2sdkee1.2.1
CPATH=.:$J2EE_HOME/lib/j2ee.jar
javac -d . -classpath "$CPATH" Beans/CalcBean.java
Beans/CalcHome.java Beans/Calc.java

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
20 Introducción a J2EE

1.8. Arrancar el Servidor de Aplicaciones J2EE

Necesitamos arrancar el servidor de aplicaciones J2EE para desplegar y


ejecutar el ejemplo. El comando para arrancar el servidor está en el
directorio bin debajo de nuestra instalación J2EE. Si tenemos el path
configurado para que lea el directorio bin, vamos directamente al directorio
J2EE (entonces nuestra versión real corresponde con lo que veremos en el
texto) y tecleamos:

j2ee –verbose

Nota:
Algunas veces el servidor J2EE no arranca si estámos ejecutando Outlook

Si esto no funciona, tecleamos lo siguiente desde el directorio J2EE:

Unix:

j2sdkee1.2.1/bin/j2ee -verbose

Windows:

j2sdkee1.2.1\bin\j2ee -verbose

La opción verbose imprime mensajes de información en la línea de comandos


cuando el servidor arranca. Cuando veamos J2EE server startup complete ,
podemos arrancar la herramienta de despliegue. Por ahora, podemos ignorar
los otros mensajes que aparecen.

1.9. Arrancar la Herramienta DeployTool

Para ensamblar y desplegar la aplicación J2EE, tenemos que arrancar la


herramienta deploytool. Si tenemos el path configurado para que lea el
directorio bin, vamos directamente al directorio J2EE (entonces nuestra
versión real corresponde con lo que veremos en el texto) y tecleamos:

deploytool

Si esto no funciona, hacemos lo siguiente desde el directorio J2EE:

Unix:

j2sdkee1.2.1/bin/deploytool

Windows:

j2sdkee1.2.1\bin\deploytool
Capítulo 1.Un Sencillo Bean de Sesión 21

Notas:
Si ocurre un error de acceso a memoria mientras arrancamos deploytool ,
añadimos una variable de entorno llamada JAVA_FONTS y seleccionamos el
path a c: \<font directory> . Por ejemplo c:\winnt\fonts. También, si se
encuentra una NullPointerException para BasicFileChooserUI cuando se
arranca deploytool, debemos asegurarnos de no arrancar la herramienta
desde el directorio raíz (es decir c:\ ). Si la ejecutamos desde cualquier otro
lugar, como el directorio bin de nuestra instalación j2sdkee1.2, no
encontraremos este problema.

1.10. 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 información sobre la
aplicación 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 aplicación de ejemplo J2EE, veremos que
todas estas ventanas nos muestran información.

Nota:
A la derecha de la ventana Server Applications hay un botón gris Uninstall.
Después de desplegar la aplicación, veremos la aplicación listada en esta
ventana. Podemos pulsar sobre Uninstall para desinstalarla, hacerle cambios,
y reinstalarla sin tener que parar y rearrancar el servidor de aplicaciones.
22 Introducción a J2EE

1.11. Ensamblar la Aplicación J2EE

Ensamblar una aplicación J2EE implica crear una nueva aplicación, y añadirle
los componentes de aplicación. Aquí tenemos un sumario de los pasos para
ensamblar, que se describen abajo con más detalle.

1. Crear una nueva aplicación J2EE (BonusApp.ear).


2. Crear un nuevo bean enterprise (CalcBean.jar).
3. Crear un nuevo componente web (Bonus.war).
4. Especificar un nombre JNDI para el bean enterprise (calcs).
5. Especificar el contexto raíz para la aplicación J2EE (BonusRoot ).

Crear la aplicación J2EE

Los componentes J2EE se ensamblan dentro de ficheros (EAR) "Enterprise


Archive".

Menu File : Seleccionamos New Application .

Caja de diálogo New Application:

• Tecleamos BonusApp.ear para el Application File Name.


• Pulsamos el botón derecho del ratón en el campo Application Display
Name. BonusApp aparece en el nombre.
• Pulsamos el botón Browse para abrir el selector de ficheros para
seleccionar la localización donde queremos grabar el fichero EAR

Selector de Ficheros New Application:

• Localizamos el directorio donde queremos situar el fichero EAR de la


aplicación.
• 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 localización y la
información de contenidos para BonusApp . La meta información mostrada en
la ventrana contents describe el fichero JAR y la aplicación J2EE, y
prorporciona información de tiempo de ejecución sobre la aplicación.

Crear el Bean de Sesión

Los beans Enterprise (tanto de entidad como de sesión) se empaquetan en un


fichero JAR.

Menú File: Seleccionamos New Enterprise Bean. Arrancará el New


Enterprise Bean Wizard y mostrará un diágolo de introducción que sumariza
los pasos que vamos a tomar. Después de leerlos, pulsamos sobre Next .
Capítulo 1.Un Sencillo Bean de Sesión 23

Caja de Diálogo EJB JAR: Especificamos la siguiente información:

• Enterprise Bean will go in : BonusApp


Display name: CalcJar
Description: Un sencillo Bean de sesión que calcula un bonus y tiene un
método.
• Pulsamos sobre Add. Hay dos botones en esta pantalla. No aseguramos
de pulsar el segundo que está cerca de la ventana Contents.

Caja de Diálogo 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 diálogo Add Contents to .JAR se debería parecer a la de la figura
siguiente. Las clases Enterprise Bean JAR se deberían mostrar con el prefijo
del nombre de directorio Beans.

• Pulsamos OK. Ahora deberíamos estar de nuevo en la caja de diálogo


EJB JAR. Beans/Calc.class , Beans/CalcHome.class, y
Beans/CalcBean.class deberían aparecer en la ventana Contents.
24 Introducción a J2EE

• Pulsamos Next.

Caja de diálogo General: Seleccionamos la siguiente información:

• 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 añade a BonusApp en la ventana de "Local Applications"), y
proporcionamos una descripción para los contenidos del ficheros JAR.
• Display Name: CalcBean
• Description: Este fichero JAR contiene el bean de sesión CalcBean.
• Pulsamos sobre Next .

Caja de Diálogo Environment Entries: Este ejemplo no hace uso de las


propiedades (entradas de entorno) pero nosotros si podríamos:

• Pulsamos sobre Finish .

Verificar que el fichero JAR se añadido realmente a la aplicación J2EE:

• Vamos a la ventana "Local Applications"


• Pulsamos el gráfico gris en frente de BonusApp . Veremos el fichero JAR
CalcJar.
• Pulsamos el gráfico gris en frente de CalcJar para ver el bean de sesión
CalcBean.

Crear Componentes Web

Los componentes Web (servlets, o JavaServer Pages™) se empaquetan dentro


de un fichero Web Archive (WAR).

Menú File : Seleccionamos New Web Component . Se arrancará el New Web


Component Wizard y mostrará una ventana que sumariza los pasos que vamos
a tomar. Después de leerlos, pulsamos sobre Next .

Caja de diálogo WAR File General Properties : Proporcionamos la siguiente


información:

• WAR file: BonusApp


Display name: BonusWar
Description: Este fichero war contiene un servlet y una página HTML
• Pulsamos Add .

Caja de Diálogo Add Contents to WAR:

• Vamos el directorio ClientCode tecleando ClientCode después de J2EE


en el campo Root Directory.
Capítulo 1.Un Sencillo Bean de Sesión 25

• Seleccionamos bonus.html. Debemos asegurarnos de que WAR contents


muestra el listado como bonus.html sin el directorio ClientCode
precediendo al nombre.
• Pulsamos sobre Add .

Nota:
Debemos asegurarnos de añadir bonus.html antes de añadir
BonusServlet.class

• 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 .
26 Introducción a J2EE

Caja de Diágolo Contents to WAR: La pantalla se debería parecer a la de la


siguiente figura:

• Pulsamos Finish .

Caja de diágolo WAR File General Properties :

• Pulsamos Next .

Caja de diálogo Choose Component Type:

• Selecccionamos Servlet (si no está ya seleccionado)


• Puslamos Next .

Caja de Diálogo Component General Properties:

• Nos aseguramos de que BonusServlet está seleccionado para la clase


Servlet.
• Introducimos un nombre ( BonusServlet ) y una descripción.
• Podemos ignornar las selecciones de Startup y load sequence aquí
porque este ejemplo sólo usa un servlet.

Caja de diálogo Component Initialization Parameters:

• Pulsamos Next . BonusServlet no usa ningún parámetro de


inicialización.

Caja de diálogo Component Aliases:


Capítulo 1.Un Sencillo Bean de Sesión 27

• 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 información estructural y de atributos sobre la aplicación
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 sitúa en un directorio raíz de contexto bajo public_html. Esta
situación es la convención parra servidores web compatibles con Servlet 2.2.

Para cambiar el nombre o la descripción:

• Ponemos el cursor en el campo apropiado en la ventana


• Lo cambiamos según nuestros deseos
• Pulsamos la tecla Return para que las ediciones tengan efecto.

Especificar el Nombre JNDI y el Contexto Raíz

Antes de poder desplegar la aplicación BonusApp y sus componentes, tenemos


que especificar el nombre JNDI que BonusServlet usa para buscar el bean de
sesión CalcBean, y especificar un directorio de contexto raíz donde el
desplegador pondrá los componentes web.

Nombre JNDI:

• Seleccionamos el fichero BonusApp en la ventana "Local Applications".


La ventana "Inspecting" muestra pestañas en la parte superior, y una de
esas pestañas es JNDI Names.
• Seleccionamos Select JNDI. La ventana "Inspecting" muestra una
pantalla con tres columnas y una fila. CalcBean se ve en la columna
central.
• En la columna más a la derecha bajo el nombre JNDI, tecleamos calc.
Este nombre JNDI es el mismo nombre JNDI pasado al método
BonusServlet.lookup.
• Pulsamos la tecla Return.

Contexto Raíz:

• Pulsamos la pestaña 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 instalación
J2sdkee1.2, y los ficheros bonus.html y BonusServlet se copian como
muestra en la siguiente figura:
28 Introducción a J2EE

Alias:

• En la ventana LocalApp, pulsamos BonusWar y luego BonusServlet


• Pulsamos la pestaña Aliases de la parte superior de la ventana
Inspecting. Deberíamos ver BonusAlias en el campo.
• Si BonusAlias no está ahí, lo tecleamos y pulsamos Return.

1.12. Verificar y Desplegar la Aplicación J2EE

Antes de desplegar la aplicación, es una buena idea ejecutar el verificador. El


verificador nos mostrará errores en los componentes de la aplicación como un
método no existente en el bean que el compilador no captura.

Verificar:

• Con BonusApp seleccionado, elegimos Verifier desde el menú Tools.


• En el diálogo que aparece, pulsamos OK. La ventana nos debería decir
si no han fallado los tests.
• Cerramos la ventana del verificador porque ya estamos listos para
desplegar la aplicación.

Nota:
En la versión 1.2 podríamos obtener un error tests app.WebURI. Esto significa
que la herramienta de desarrollo no puso una extensión .war al fichero WAR
durante su creación. Este es un bug menor y la apliación J2EE se despliega
bien sin notarlo.

Desplegar:

• Desde el menú Tools, elegimos Deploy Application . Se mostrará una


caja de diálogo Deploy BonusApp. Debemos verificar que la selección
Target Server es o localhost o el nombre del servidor donde se está
ejecutando el J2EE.
Capítulo 1.Un Sencillo Bean de Sesión 29

Nota:
No debemos seleccionar el check box Return Client Jar. La única vez que
necesitamos seleccionar este check box es cuando despleguemos una
aplicación solitaria para el programa cliente. Este ejemplo usa un servlet y
una página HTML por eso no debemos seleccionarlo. Seleccionar este check
box crea un fichero Jar con la información de despliegue necesaria para una
aplicación 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
diálogo que mostrará el estado de la operación de despliegue.
• Cuando esté completa, las tres barras de la izquierda estárán
completamente sombreadas, como se ve en la siguiente figura. Cuando
esto suceda, pulsamos OK.

1.13. Ejecutar la Aplicación J2EE

El servidor web se ejecuta por defecto en el puerto 8000. Para abrir la página
bonus.html apuntamos nuestro navegador a
http://localhost:8000/BonusRoot/bonus.html, que es donde DeployTool puso
el fichero HMTL.

Nota:
Si necesitamos usar un puerto diferente porque el puerto 8000 está siendo
utilizado por otra cosa, editamos el fichero web.properties en el directorio
~/J2EE/j2sdkee1.2/config y arrancamos de nuevo el servidor J2EE.

• Rellenamos un número de seguridad social.


• Rellenamos un multiplicador.
• Pulsamos el botón Submit. BonusServlet procesa nuestros datos y
devuelve una página HTML con el cálculo del bono.

Bonus Calculation

Soc Sec: 777777777


Multiplier: 25

Bonus Amount 2500.0


30 Introducción a J2EE

1.14. Actualizar el Código de Componentes

El menú Tools tiene dos opciones de interés. Son Update Application Files y
Update and Redeploy Application. Estas opciones nos permiten cambiar el
código y redesplegar nuestra aplicación con facilidad. Simplemente hacemos
los cambios en el código, lo recompilamos, y elegimos una de estas opciones
del menú.

• Update Application Files actualiza los ficheros de la aplicación con


nuestro nuevo código. En este punto podemos verificar la aplicación o
desplegarla.
• Update and Redeploy Application actualiza los ficheros de la
aplicación con nuestro nuevo código y redespliega la aplicación sin
ejecutar el verificador.
Capítulo 2.Añadir un Bean de Entidad 31

2. Añadir un Bean de Entidad


Esta lección amplía el ejemplo de la lección anterior para usar un bean de
entidad. BonusServlet llama al bean de entidad para grabar información sobre
el número de la seguridad social y el bono y recuperarlo desde una tabla de la
base de datos. Este funcionalidad de acceso a la base de datos añade la
cuarta capa y la capa final al pequeño cliente empezado en la lección
anterior.

El SDK J2EE viene con una base de datos Cloudscape, y no necesitamos


configuración adicional en nuestro entorno para el bean de entidad. De echo
en este jemplo, no escribimos ningún código SQL o JDBC™ para crear las
operaciones de acceso a la base de datos. La tabla y el código SQL se generan
con la herramienta de Despliegue durante en el ensamble y el despliegue. La
lección sobre Tecnología JDBC y Persistencia Manejada por el Bean nos
enseñará como escribir código SQL para un bean de entidad.

2.1. Crear el Bean de Entidad

Un bean de entidad representa datos persistentes almacenados en una fila de


una tabla de una base de datos. Cuando se crea un bean de entidad, los datos
se escriben en la fila apropiada de la tabla, y si se actualizan los datos de un
bean de entidad, los datos de la fila apropiada de la tabla también se
actualizan. La creación de la tabla de la base de datos y la actualización de
las filas ocurre sin escribir nada de código SQL o JDBC.

Los datos de un bean de entidad son persistentes porque sobreviven a los


crashs.

• Si ocurre un crash mientras se están actualizando los datos de un bean


de entidad, estos datos son restaurados autmáticamente al estado de la
última transación enviada a la base de datos.
• si ocurre un crash en medio de una transación a la base de datos, la
transación se "deshace" para evitar que un envío parcial corrompa los
datos.

BonusHome

La principal diferencia entre el bean de sesión CalcHome de la lección


anterior y el bean de entidad BonusHome de esta lección es el método
findByPrimaryKey. Este método de búsqueda toma la clave primaria como un
parámetro. En este ejemplo, la clave primara es el número de la seguridad
social, que se usa para recuperar la fila con el valor de la clave primaria que
corresponde con el número de la seguridad social pasado a este método.

El método create toma el valor del bono y de la clave primaria como


parámetros. Cuando BonusServlet ejemplariza el interface home y llama a su
método create, el contenedor crea un ejemplar de BonusBean y llama a su
método ejbCreate. Los métodos BonusHome.create y BonusBean.ejbCreate
32 Introducción a J2EE

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
(número de seguridad social) ya existe, se lanza una
java.rmi.RemoteException que es manejada por el código cliente
BonusServlet.
package Beans;

import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.FinderException;
import javax.ejb.EJBHome;

public interface BonusHome extends EJBHome {


public Bonus create(double bonus, String socsec)
throws CreateException, RemoteException;
public Bonus findByPrimaryKey(String socsec)
throws FinderException, RemoteException;
}

Bonus

Después de crear el interface home, el contenedor crea el interface remoto y


el bean de entidad. El interface Bonus declara los métodos 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;
}
Capítulo 2.Añadir un Bean de Entidad 33

BonusBean

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 código para transferir datos entre el bean
de entidad y la base de datos o definir paquetes de transaciones.

Si por alguna razón queremos que el bean de entidad maneje su propia


persistencia o las transaciones, podríamos proporcionar implementaciones
para algunos de los métodos vacíos mostrados en el código de BonusBean de
abajo.

Cuando BonusServlet llama a BonusHome.create, el contenedor llama al


método BonusBean.setEntityContext. El ejemplar de EntityContext pasado al
método setEntityContext tiene métodos que permiten al bean devolver una
referencia a sí mismo o para obtener su clave primaria.

Luego, el contenedor, llama al método ejbCreate. Este método asigna datos a


las variables de ejemplar del bean, y luego el contenedor escribe los datos en
la base de datos. Se llama al método ejbPostCreate después de ejbCreate y
realiza cualquier proceso necesario después de que se cree el bean. Este
sencillo ejemplo no hace procesamiento post-creacción.

Los otros métodos vacíos son métodos de retrollamada usados por el


contenedor para notificar al bean algún evento que va a ocurrir. Podríamos
proporcionar comportamiento para algunos de estos métodos si estámos
usando persistencia controlada por el bean, y otros si necesitamos
proporcionar limpieza específica del bean u operaciones de limpieza. Estas
operaciones de limpieza e inicialización tienen lugar en momentos específicos
durante el ciclo de vida del bean, y el contenedor se lo notifica al bean y
llama al método aplicable en el momento apropiado. Aquí tenemos una breve
descripción de los métodos vacíos:

• Los métodos 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 página de
memoria virtual entre la memoria y el disco.
• El contenedor llama al método ejbRemove si el interface home tiene el
correspondiente método remove que es llamado por el cliente.
• Los métodos ejbLoad y ejbStore los llama el contenedor antes de que
se sincronize el estado del bean con la base de datos subyacente.

Los métodos getBonus y getSocSec son llamados por los clientes para
recuperar datos almacenados en variables de ejemplar. Este ejemplo no tiene
métodos del tipo set< type >, pero si los tuviera, el cliente podría llamarlos
para modificar los datos de las variables de ejemplar del bean. Cualquier
cambio hecho en una variable de ejemplar resulta en una actualización de la
fila de la tabla de la base de datos subyacente.
34 Introducción a J2EE

package Beans;

import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EntityBean;
import 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;
}

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
}
}
Capítulo 2.Añadir un Bean de Entidad 35

2.2. Cambiar el Servlet

El código de esta lección es muy similar al de la página anterior con cambios


en los métodos init y doGet. El método init de esta lección busca el bean de
sesión 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 método doGet crea los interfaces home de CalcBean y


BonusBean. Después de llamar a calcBonus para calcular el bono, se llama al
método BonusHome.create para crear un ejemplar del bean de entidad y la
correspondiente fila en la tabla de la base de datos subyacente. Después de
crear la tabla, se llama al método BonusHome.findByPrimaryKey para
recuperar el mismo registro por su clave primaria (número de la seguridad
social). Luego, se devuelve una página 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


(números 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 número 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 página 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
theBonus = homebonus.create(calc, socsec);
record = homebonus.findByPrimaryKey(socsec);
36 Introducción a J2EE

//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();
}
}

2.3. Compilar

Primero, compilamos el Bean de entidad y el servlet. Puedes volver a la


lección anterior para ver la configuración del path, classpath y dónde situar
los ficheros fuentes.

Compilar el Bean de Entidad

Unix

#!/bin/sh
cd /home/monicap/J2EE
J2EE_HOME=/home/monicap/J2EE/j2sdkee1.2.1
CPATH=.:$J2EE_HOME/lib/j2ee.jar
javac -d . -classpath "$CPATH" Beans/BonusBean.java
Beans/BonusHome.java Beans/Bonus.java

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/BonusBean.java
Bean s/BonusHome.java Beans/Bonus.java
Capítulo 2.Añadir un Bean de Entidad 37

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

2.4. Arrancar la Plataforma y las Herramientas

Para ejecutar este ejemplo, necesitamos arrancar el servidor J2EE, la


herramienta Deploy y la base de datos Cloudscape. En diferentes ventanas,
tecleamos los siguientes comandos.

j2ee -verbose
deploytool
cloudscape -start

Si esto no funciona, tecleamos esto desde el directorio J2EE:

Unix

j2sdkee1.2.1/bin/j2ee -verbose
j2sdkee1.2.1/bin/deploytool
j2sdkee1.2.1/bin/cloudscape -start

Windows

j2sdkee1.2.1\bin\j2ee -verbose
j2sdkee1.2.1\bin\deploytool
j2sdkee1.2.1\bin\cloudscape -start

2.5. Ensamblar y Desplegar

Los pasos de esta sección son:

• Actualizar el Fichero de Aplicación


• Crear el Bean de Entidad
38 Introducción a J2EE

Actualizar el Fichero de Aplicación

El archivo web (WAR) contiene BonusServlet y bonus.html. Como hemos


modificado BonusServlet, tenemos que actualizar la aplicación J2EE con el
nuevo código del servlet.

• Ventana Local Applicatons: Iluminamos la aplicación BonusApp.


• Menú Tools Menu: Seleccionamos Update Application Files .

Nota:
Se desinstalará automáticamente la aplicación BonusApp de la lección
anterior.

Crear el Bean de Entidad

Los pasos para crear el EJB JAR para el bean de entidad son muy similares a
los pasos del bean de sesión cubiertos en la lección anterior. Sin embargo, hay
algunas diferencias, y se explican aquí:

Nota:
En esta lección, el bean de entidad va en un ficjero JAR separado del bean de
sesión para continuar el ejemplo de la lección anterior con el menor número
de cambios. Sin embargo, como estos beans tienen funcionalidades
relacionadas podríamos empaquetarlos y desplegarlos en el mismo fichero
JAR. Vermos como hacer esto en la siguiente lección.

Menu File:

• Seleccionamos New Enterprise Bean.

Introducción :

• Leer y Pulsar Next

EJB JAR :

• Nos aseguramos de que BonusApp se ve en Enterprise Bean will go in


field.
• Especificamos BonusJar como nombre.
• Pulsamos Add (el más cercano a la ventana Contents).

Añadir 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.
Capítulo 2.Añadir un Bean de Entidad 39

• Seleccionamos BonusHome.class
• Pulsamos Add.
• Pulsamos OK.

EJB JAR:

• Pulsamos Next .

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 .

Configuración 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 .
40 Introducción a J2EE

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 Transación :

• 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 transación antes de ejecutar estos métodos. Las transaciones se
envían justo antes de que los métodos terminen.

• Pulsamos Next .
• Pulsamos Finish .
Capítulo 2.Añadir un Bean de Entidad 41

Aplicaciones Locales:

• Seleccionamos BonusApp .
• En la ventana Inspecting, seleccionamos JNDI names
• La damos a BonusBean el nombre JNDI de bonus
• Pulsamos la tecla Return

Antes de poder desplegar la aplicación J2EE, necesitamos especificar las


condiciones de despliegue para el bean de entidad y generar el SQL. Aquí está
cómo hacerlo:

Ventana Local Applications:

• Seleccionamos BonusBean .

Ventana Inspecting:

• Seleccionamos Entity
• Pulsamos el botón Deployment Settings de la parte inferior izquierda.

Configuración de Despliegue:

• Especificamos jdbc/Cloudscape (con una C maýuscula 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 están marcadas.
• Ahora pulsamos Generate SQL.

Nota:
Si obtenemos un error de que la conexión fue rechazada, arrancamos la base
de datos como se describe en Arrancar la Plataforma y las Herramientas.
42 Introducción a J2EE

• Cuando se complete la generación de SQL, seleccionamos el método


findByPrimaryKey en la caja EJB method. Aparecerá una secuencia SQL
a la derecha. Debería leerse SELECT "socsec" FROM "BonusBeanTable"
WHERE "socsec"=?. El interrogante representa el parámetro pasado por
el método findByPrimaryKey.
• Pulsamos OK.

Verificar y Desplegar la aplicación J2EE

Verificar:

• Con BonusApp seleccionado, elegimos Verifier desde el menú Tools.


• En el diálogo que aparece, pulsamos OK. La ventana debería decirnos
que no ha fallado ningún test.
• Cerramos la ventana del verificador porque ya estamos listos para
desplegar la apliación.

Nota:
En la versión 1.2 del software podría obtener un error tests app.WebURI. La
Aplicación J2EE se desplegará de todas formas.

Despliegue:

• En el Menú Tools: Seleccionamos Tools.Deploy Application.


Capítulo 2.Añadir un Bean de Entidad 43

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 aplicación solitaria para el programa cliente. Este ejemplo
usa un servlet y una página HTML por lo que no debe estár marcada. Esta caja
crea un fichero JAR con toda la información de despliegue necesaria para una
aplicación 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.

2.6. Ejecutar la Aplicación J2EE

El servidor web se ejecuta por defecto en el puerto 8000. Para abrir la página
bonus.html apuntamos nuestros navegador a
http://localhost:8000/BonusRoot/bonus.html, que es donde DeployTool puso
el fichero HMTL.

Rellenamos un número de la seguridad social y un múltiplicador, y pulsamos el


botón Submit. BonusServlet procesa nuestros datos y devuelve una página
HTML con el bono calculado.

Bonus Calculation

Soc Sec passed in: 777777777


Multiplier passed in: 25
Bonus Amount calculated: 2500.0
Soc Sec retrieved: 7777777777
Bonus Amount retrieved: 2500.0

Si volvemos al código de bonus.html y cambiamos el multiplicador por 2, pero


usamos el mismo número 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.
Capítulo 3. Comunicaciones entre Beans 45

3. Comunicaciones entre Beans


En la lección anterior, el servlet buscaba y creaba un bean de sesión para
realizar el cálculo de un bono, y luego buscaba y creaba un bean de entidad
para almacenar el valor del bono y el número de la seuridad social asociado.
Esta lección modifica el ejemplo para que el bean de sesión busque y cree el
bean de entidad. Como el bean de sesión y el de entidad trabajan juntos,
están empaquetados en un sólo fichero JAR para su despliegue.

Nota:
Algunas personas tienen problemas con esta lección al trabajar 2 beans en un fichero JAR. Si
sucede esto, podemos borrar el fichero JAR con los dos beans y poner cada bean en su propio
fichero JAR. Podríamos necesitar parar y rearrancar el servidor y las herramientas antes de
poder generar el SQL y desplegar.

3.1. Cambiar el Bean de Sesión

En esta lección y como se ve en la siguiente figura el bean de entidad es un


cliente del bean de sesión. Esto significa que el bean de entidad obtiene sus
datos del bean del sesión en vez de BonusServlet como lo hizo en la . Por eso,
se modifica el método calcBonus del bean de sesión para tomar el número de
la seguridad social como un parámetro y crear el bean de entidad.

CalcHome

El interface CalcHome no se modifica. Tiene el mismo método 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;
}
46 Introducción a J2EE

Calc

El método calcBonus del interface Calc se ha modificado para tomar el


número de la seguridad social como parámetro. Por eso CalcBean puede pasar
el bono y el número de la seguridad social al bean de entidad después de
calcular el valor del bono. Se añade un nuevo método getRecord para que
CalcBean peuda encontrar el bean de entidad por sus clave primaria (el
número de la seguridad social).

También, la firma del método calcBonus lanza DuplicateKeyException y


CreateException. Esto es por lo que BonusServlet puede capturar y manejar
cualquiera de estas condiciones de excepción. DuplicateKeyException
desciende de CreateException. Si diseñamos el método 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 código para crear el bean de entidad se ha movido desde BonusServlet


hasta calcBonus para que el bono y el número de la seguridad social puedan
escribirse en el bean de entidad después de haber calculado el bono. La
variable homebonus es una variable de ejemplar para que pueda ser usada en
el método calcBonus para buscar el bean de entidad y en el método getRecord
para localizar el bean de entidad correspondiente al número de la seguridad
social.

package Beans;

import java.rmi.RemoteException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import javax.ejb.DuplicateKeyException;
import javax.ejb.CreateException;

public class CalcBean implements SessionBean {


BonusHome homebonus;
//Throw DuplicateKeyException and CreateException
//so BonusServlet can catch and handle these
//exception conditions.
Capítulo 3. Comunicaciones entre Beans 47

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() { }
}

3.2. Cambiar el Servlet

El programa BonusServlet es muy similar a la versión de la Lección anterior


con algunos cambios en los métodos init y doGet. El método init para esta
sección sólo busca el bean de sesión.
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();
}
48 Introducción a J2EE

La sentencia try del método doGet calcula el bono, crea el interface home del
bean de sesión y llama a los métodos calcBonus y getRecord. Si el método se
completa con éxito, se devuelve una página HTML que muestra los datos
recuperados desde el bean de entidad. Si el método calcBonus lanza una
DuplicateKeyException, se devuelve una página HTML mostrando el número de
la seguridad social y el multiplicador pasados, y un mensaje de excepción,
Duplicate primary key.

Como en la lección anterior, la sentencia catch captura y maneja valores de


claves primarias duplicadas (números 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();
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();
}

3.3. Compilar

Primero compilamos el bean de sesión y el servlet. Puedes referirte a la


primera lección para ver la configuración del path y del classpath y más
información sobre dónde situar los ficheros fuente.

Compilar el Bean de Sesión

Unix

#!/bin/sh
cd /home/monicap/J2EE
J2EE_HOME=/home/monicap/J2EE/j2sdkee1.2.1
Capítulo 3. Comunicaciones entre Beans 49

CPATH=.:$J2EE_HOME/lib/j2ee.jar
javac -d . -classpath "$CPATH" Beans/CalcBean.java
Beans/CalcHome.java Beans/Calc.java

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:

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

3.4. Arrancar la Plataforma y las Herramientas

Para ejecutar este ejemplo, necesitamos arrancar el servidor J2EE, la


herramienta Deploy y la base de datos Cloudscape. En diferentes ventanas,
tecleamos los siguientes comandos.

j2ee -verbose
deploytool
cloudscape -start

Si esto no funciona, tecleamos esto desde el directorior J2EE:

Unix

j2sdkee1.2.1/bin/j2ee -verbose
j2sdkee1.2.1/bin/deploytool
j2sdkee1.2.1/bin/cloudscape -start

Windows

j2sdkee1.2.1\bin\j2ee -verbose
50 Introducción a J2EE

j2sdkee1.2.1\bin\deploytool
j2sdkee1.2.1\bin\cloudscape -start

3.5. Ensamblar la Aplicación

Los pasos de esta sección incluyen:

• Crear una nueva aplicación J2EE.


• Crear un nuevo componente Web.
• Empaquetar los Beans de Sesión y de Entidad en un fichero JAR.

Crear una Nueva aplicación J2EE

En vez de actualizar la aplicación J2EE de las lecciones anteriores, estos pasos


crean una nueva aplicación J2EE.

Borrar BonusApp:

• Pulsamos BonusApp para que se ilumine


• Seleccionamos Delete desde el menú Edit

Crear 2BeansApp :

• Desde el menú File, seleccionamos New Application .


• Pulsamos con el botón derecho del ratón en el campo Application
Display Name. Aparecerá 2BeansApp como nombre.
• Pulsamos el botón Browse para abrir el selector de ficheros y
seleccionar la localización donde queremos grabar el fichero EAR de la
aplicación.

Selector de ficheros New Application :

• Localizamos el directorio donde queremos situar el fichero de


aplicación EAR.
• En este ejemplo, el directorio es /export/home/monicap/J2EE.
• En el campo File name, tecleamos 2BeansApp.ear.
• Pulsamos New Application.
• Pulsamos OK.

Crear un nuevo componente Web.

Ahora, veremos los pasos para crear el fichero WAR. Estos pasos que se
presentaron en la primera lección se sumarizan abajo.

Con 2BeansApp seleccionado:

File Menu:

• Seleccionamos New Web Component.


Capítulo 3. Comunicaciones entre Beans 51

Introducción :

• Leemos y Pulsamos Next

War File General Properties :

• Especificamos BonusWar para el nombre.


• Pulsamos Add
• Vamos al directorio ClientCode y añadimos bonus.html
• Pulsamos Next
• Vamos al directorio ClientCode y añadimos 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:

• Seleccionamos Web Context


• Especificamos BonusRoot.

Empaquetar los Beans de Sesión y de Entidad en un Fichero JAR

En esta lección, pondremos los beans de sesión y de entidad en el mismo


fichero JAR. Para hacer esto, primero creamos el fichero JAR con sólo el bean
de sesión, y luego le añadimos el bean de entidad.
52 Introducción a J2EE

Crear JAR con el Bean de Sesión

Con 2BeansApp seleccionado,

Menú File:

• Seleccionamos New Enterprise Bean.

Introducción :

• Leemos y pulsamos Next .

EJB JAR :

• Nos aseguramos de que 2BeansApp se muestra en el campo Enterprise


Bean will go in .
• Especificamos 2BeansJar como nombre.
• Pulsamos Add (el más cercano a la ventana Contents).
• Cambiamos el directorio para que el directorio Beans muestre su
contenido.
• Seleccionamos Calc.class
• Pulsamos Add .
• Seleccionamos CalcBean.class
• Pulsamos Add .
• Seleccionamos CalcHome.class
• Pulsamos Add.

Clases Enterprise Bean JAR :

• Nos aseguramos de que vemos Beans/Calc.class ,


Beans/CalcHome.class, y Beans/CalcBean.class en la pantalla.
• Pulsamos OK.

EJB JAR :

• Pulsamos Next.

General :

• CalcBean es el nombre de la clase, Beans.CalcHome es el interface


Home, y Beans.Calc es el interface remoto.
• Introducimos CalcBean como nomre de display.
• Pulsamos session and stateless.
• Pulsamos Next.

Entradas de Entorno:

• Pulsamos Next. Este sencillo bean de sesión no usa propiedades


(entradas de entorno)
Capítulo 3. Comunicaciones entre Beans 53

Referencias a Beans Enterprise:

• Pulsamos Next. Las referencias se manejarán durante el despliegue


mejor que aquí.

Referencias a Recursos:

• Pulsamos Next. Este sencillo bean de sesión no busca ningún objeto de


base de datos o sesión JavaMail™.

Seguridad:

• Pulsamos Next. Este sencillo bean de sesión 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 transación antes de
ejecutar estos métodos. La transación se envía justo antes de que los
métodos 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.

Añadir 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 selección añadirá el nuevo bean al fichero JAR
existente en lugar de ponerlo en un nuevo fichero JAR.
54 Introducción a J2EE

• Pulsamos Add (el más 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 :

• 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 válidos 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.


Capítulo 3. Comunicaciones entre Beans 55

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 transación antes de ejecutar estos métodos. La transación se
envía justo antes de que los métodos 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 después de cada entrada.

Antes de poder desplegar la aplicación 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 botón Deployment Settings inferior derecha.

Ventana Deployment Settings:

• Especificar jdbc/Cloudscape (con una C mayúsculas 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 están marcadas.
• Ahora pulsamos Generate SQL.
56 Introducción a J2EE

Nota:
Si obtenemos un error de que la conexión fue rechazada, arrancamos de
nuevo la base de datos como se describe en Arrancar la Plataforma y las
Herramientas.

Cuando se complete la generación del SQL,

• Seleccionamos el método findByPrimaryKey en la caja EJB method.


• Aparecerá una sentencia SQL a la derecha. Debería ser SELECT "socsec"
FROM "BonusBeanTable" WHERE "socsec"=?.
El interrogante representa el parámetro pasado para el método
findByPrimaryKey.
• Pulsamos OK.

3.6. Verificar y Desplegar la Aplicación J2EE

Antes de desplegar la aplicación, es una buena idea ejecutar el verificador. El


verificador mostrará los errores en los componentes de la aplicación como
métodos inexistentes que el compilador no captura.

Nota:
Si obtenemos un error Save cuando verificamos o desplegamos, debemos parar todo y
rearrancar el servidor y las herramientas.

Verificar:

• Con 2BeansApp seleccionado, elegimos Verifier desde el menú Tools.


• En el diálogo que aparece, pulsamos OK. La ventana debería decir que
no hay ningún fallo.
• Cerramos la ventana del verificador porque ahora estamos listos para
desplegar la aplicación.

Nota:
En la versión 1.2.1 del software podríamos obtener un error tests app.WebURI. Esto significa
que la herramienta DeployTool no puso la extensión .war al fichero WAR durante su
creacción. Es un error menor y la aplicación J2EE se despliega sin problemas.

Desplegar:

• Desde el menú Tools, elegimos Deploy Application. Se mostrará una


caja de diálogo Deploy BonusApp.
• Verificar que la selección 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 aplicación
solitaria para el programa cliente. Este ejemplo usa un servlet y una página HTML por lo que
no debe estár marcada. Esta caja crea un fichero JAR con toda la información de despliegue
necesaria para una aplicación solitaria.
Capítulo 3. Comunicaciones entre Beans 57

• 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 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
diálogo que mostrará el estado de la operación de despliegue.
• Cuando se haya completado, las tres barras de la izquierda se habrán
sombreado completamente, como se ve en la siguiente figura. Cuando
esto suceda pulsamos OK.

3.7. Ejecutar la Aplicación J2EE

El servidor web se ejecuta por defecto en el puerto 8000. Para abrir la página
bonus.html apuntamos nuestros navegador a
http://localhost:8000/BonusRoot/bonus.html, que es donde DeployTool puso
el fichero HMTL.

Rellenamos un número de la seguridad social y un múltiplicador, y pulsamos el


botón Submit. BonusServlet procesa nuestros datos y devuelve una página
HTML con el bono calculado

Bonus Calculation
Soc Sec retrieved: 777777777
Bonus Amount Retrieved: 200.0

Si volvemos al código de bonus.html y cambiamos el multiplicador por 2, pero


usamos el mismo número de la seguridad social, veremos esto:
58 Introducción a J2EE

Bonus Calculation
Soc Sec passed in: 777777777
Multiplier passed in: 2
Duplicate primary key
Capítulo 4.Tecnología JavaServer Pages (JSP) 59

4. Tecnología JavaServer Pages™ (JSP)


La tecnología JavaServer Pages™ (JSP) nos permite poner segmentos de código
servlet directamente dentro de una página HTML estática. Cuando el
navegador carga una página JSP, se ejecuta el código del servlet y el servidor
de aplicaciones crea, compila, carga y ejecuta un servlet en segundo plano
para ejecutar los segmentos de código servlet y devolver una página HTML o
imprimir un informe XML.

Esta lección modifica el fichero WAR de la Lección anterior para usar una
página JSP en lugar de BonusServlet.

4.1. Crear la Página JSP

Una página JSP se parece a una página HTML con segmentos de código servlet
embebidos entre varias etiquetas de apertura ( <% ) y cierre (%> ) JSP. No hay
métodos HttpServlet como init , doGet, o doPost. En su lugar, el código que
normalmente iría en estos métodos está directamente embebido en la página
JSP usando etiequetas JSP.

La siguiente página JAP ( Bonus.jsp ) es equivalente al BonusServlet de la


lección anterior. Después del código podremos ver una descripción detallada
de las etiquetas JSP. Observa que las etiquetas JSP no pueden estar anidadas.
Por ejemplo, no podemos anidar una etiqueta de comentario JSP con una
etiqueta scriptlet JSP.
<HTML>
<HEAD>
<TITLE>Bonus Calculation</TITLE>
</HEAD>
<%-- Comment
Scriptlet for import statements
<%@ indicates a jsp directive --%>
<%@ page import="javax.naming.*" %>
<%@ page import="javax.rmi.PortableRemoteObject" %>
<%@ page import="Beans.*" %>
<%-- Comment
Scriptlet to get the parameters,
convert string to Integer to int for bonus
calculation, and declare/initialize bonus
variable. <% indicates a jsp scriptlet --%>
<%! String strMult, socsec; %>
<%! Integer integerMult; %>
<%! int multiplier; %>
<%! double bonus; %>
<%
strMult = request.getParameter("MULTIPLIER");
socsec = request.getParameter("SOCSEC");
integerMult = new Integer(strMult);
multiplier = integerMult.intValue();
bonus = 100.00;
%>
<%-- Comment
Scriptlet to look up session Bean --%>
<%
InitialContext ctx = new InitialContext();
Object objref = ctx.lookup("calcs");
CalcHome homecalc = (CalcHome)
60 Introducción a J2EE

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>

Comentarios

Las primeras siete líneas 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 página HTML. Los
comentarios HTML se envían al navegador web del cliente donde aparezcan
como parte de la página 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
ejecución que desaparecía cuando eliminamos los dos puntos.
Capítulo 4.Tecnología JavaServer Pages (JSP) 61

<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
página 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 están
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. También podemos declarar variables dentro de
expresiones o scriptlets en el momento de usarlas. El ámbito es toda la página
JSP, no hay concepto de variables de ejemplar. Es decir, no tenemos que
declarar variables de ejemplar para usar en más de una expresión o scriptlet.
Las declaraciones van encerradas entre etiquetas de declaración <%! 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 código java dentro de
una página JSP. El codigo embebido se inserta directamente en el servlet
generado que se ejecuta cuando se pide la página. 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();
bonus = 100.00;
%>

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
62 Introducción a J2EE

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 dinámicamente o calcular valores


a insertar directamente en la página JSP. En este ejemplo, una expresión
recupera el número de la seguridad social desde el bean de entidad Bonus y lo
pone en la página JSP.
<H1>Bonus Calculation</H1>
Social security number retrieved:
<%= record.getSocSec() %>
<P>
Bonus Amount retrieved: <%= record.getBonus() %>
<P>

Etiquetas Especificas de JSP

La especificación JavaServer Pages 1.1 define etiquetas específicas de JSP


que nos permiten extender la implementación JSP con nuevas características
y ocultar mucha complejidad a los diseñadores visuales que necesitan buscar
la página JSP y modificarla. El ejemplo JSP de esta lección no usa ninguna de
estas etiquetas específicas, pero las veremos en la siguiente lección. Las
etiquetas específicas JSP definidas en la especificación 1.1 son las siguientes:

jsp:forward y jsp:include para instruir al motor JSP que pase de la página


actual a otra página JSP.

jsp:useBean, jsp:setProperty, jsp:getProperty nos permiten embeber y utilizar


tecnología JavaBeans en páginas JSP.

jsp:plugin descarga automáticamente el Plug-In Java al cliente para ejecutar


applet en la plataforma Java adecuada.

4.2. 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 .
Capítulo 4.Tecnología JavaServer Pages (JSP) 63

<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>

4.3. Arrancar la Plataforma y las Herramientas

Para ejecutar este ejemplo, necesitamos arrancar el servidor J2EE, la


herramienta Deploy, y la base de datos Cloudscape. En diferentes ventanas,
tecleamos los siguientes comandos:

j2ee -verbose
deploytool
cloudscape -start

Si esto no funciona, tecleamos esto desde el directorio J2EE:

Unix

j2sdkee1.2.1/bin/j2ee -verbose
j2sdkee1.2.1/bin/deploytool
j2sdkee1.2.1/bin/cloudscape -start

Windows

j2sdkee1.2.1\bin\j2ee -verbose
j2sdkee1.2.1\bin\deploytool
j2sdkee1.2.1\bin\cloudscape -start

4.4. Eliminar el Fichero WAR

Como se ha añadido una página JSP al componente Web, tenemos que borrar
el fichero WAR de las lecciones anteriores y crear uno nuevo con la página
JSP.

Local Applications:

• Pulsar el icono 2BeansApp para poder ver los componentes de nuestra


aplicación.
64 Introducción a J2EE

• Seleccionamos BonusWar para que se ilumine.


• Seleccionamos Delete desde el menú Edit.

Crear el Nuevo Fichero WAR

Menú File:

• Seleccionamos New Web Component

Introduction:

• Leemos y pulsamos Next .

War File General Properties :

Nota:
Parece que hay un bug en la herramienta Deploy. Debemos asegurarnos de
añadir primero Bonus.jsp seguido de bonus.html. Si añadimos primero
bonus.html, la herramienta Deploy pone bonus.html donde debería ir
Bonus.jsp y Bonus.jsp donde debería ir bonus.html. Si esto sucede, podemos
corregirlo manualmente copiándolos en las localizaciones correctas. Así es
como deben estar después del despliegue:
~/j2sdkee1.2/public_html/JSPRoot/bonus.html
~/j2sdkee1.2/public_html/JSPRoot/WEB-INF/classes/Bonus.jsp

• Especificamos BonusWar para el nombre de display.


• Pulsamos Add
• Vamos al directorio ClientCode y añadimos Bonus.jsp,
• Pulsamos Next
• Vamos al directorio ClientCode y añadimos bonus.html
• Pulsamos Finish .

Propiedades Generales del Fichero War:

• Pulsamos Next.

Elegir el tipo de Componente: .

• Seleccionamos Describe a JSP.


• Pulsamos Next.

Propiedades generales del Componente:

• Ponemos Bonus.jsp como nombre de fichero JSP.


• Ponemos BonusJSP como nombre de display.
• Pulsamos Finish .
Capítulo 4.Tecnología JavaServer Pages (JSP) 65

Ventana Inspecting:

• Seleccionamos Web Context


• Especificamos JSPRoot.

4.5. Verificar y Desplegar la Aplicación J2EE

Antes de desplegar la aplicación, es una buena idea ejecutar el verificador. El


verificador mostrará los errores en los componentes de la aplicación como
métodos inexistentes que el compilador no captura.

Verificar:

• Con 2BeansApp seleccionado, elegimos Verifier desde el menú Tools.


• En el diálogo que aparece, pulsamos OK. La ventana debería decir que
no hay ningún fallo.
• Cerramos la ventana del verificador porque ahora estamos listos para
desplegar la aplicación.

Nota:
En la versión 1.2.1 del software podríamos obtener un error tests
app.WebURI. Esto significa que la herramienta DeployTool no puso la
extensión .war al fichero WAR durante su creacción. Es un error menor y la
aplicación J2EE se despliega sin problemas.

Desplegar:

• Desde el menú Tools, elegimos Deploy Application. Se mostrará una


caja de diálogo Deploy BonusApp.
• Verificar que la selección 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 aplicación solitaria para el programa cliente. Este ejemplo
usa un servlet y una página HTML por lo que no debe estár marcada. Esta caja
crea un fichero JAR con toda la información de despliegue necesaria para una
aplicación 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 .
66 Introducción a J2EE

• Pulsamos Finish para empezar el despliegue. Se mostrará una caja de


diálogo que mostrará el estado de la operación de despliegue.
• Cuando se haya completado, las tres barras de la izquierda se habrán
sombreado completamente, como se ve en la siguiente figura. Cuando
esto suceda pulsamos OK.

4.6. Ejecutar la Aplicación J2EE

El servidor web se ejecuta por defecto en el puerto 8000. Para abrir la página
bonus.html apuntamos nuestro navegador a
http://localhost:8000/JSPRoot/bonus.html, que es dónde la herramienta de
despliegue puso el fichero HTML.

Nota:
La Herramienta Deploy pone Bonus.jsp bajo public_html/JSPRoot , y bonus.html bajo
public_html/JSPRoot/WEB-INF/classes, que es lo opuesto a donde realmente pertenecen.
Manualmente los copiamos en sus localizaciones correctas como sigue
public_html/JSPRoot/bonus.html y public_html/JSPRoot/WEB-INF/classes/Bonus.jsp.

• Rellenamos un número de la seguridad social y un multiplicador.


• Pulsamos el botón Submit. Bonus.jsp procesa nuestros datos y devuelve
una página HTML con el bono calculado.

Bonus Calculation

Social Security number retrieved: 777777777


Bonus Amount Retrieved: 200.0

Si hemos suministrado dos veces el mismo número de la seguridad social,


veremos algo similar a esto:

Bonus Calculation

Soc Sec passed in: 777777777


Multiplier passed in: 2
Error: Duplicate primary key
Capítulo 5.Tecnología JavaBeans 67

5. Tecnología JavaBeans
Podemos usar la tecnología JavaBeans™ para poner un JavaBean entre una
página JSP y el bean de sesión CalcBean para obtener una mejor separación
"Model, View, Controller (MVC)". MVC es un patrón de diseño que consiste en
tres tipos de objetos. El Modelo proporciona la lógica de negocio de la
aplicacón, la Vista es la presentación en pantalla, y el Controlador es un
objeto que maneja lo que sucede cuando el usuario interactúa con la Vista.
Un patrón de diseño describe un problema recurrente y sus soluciones cuando
la solución no es siempre exactamente la misma para cada recurrencia.

La lección sobre Tecnología JSP se configuró para que las páginas HTML y JSP
proporcionaran la presentación en pantalla (Vista) y manejar lo que sucedia
cuando el usuario interactúa con los datos (Controlador). Los beans de entidad
y de sesión ( BonusBean y CalcBean) son los objetos de la aplicación o
Modelo.

Esta lección usa una página JSP para la presentación en pantalla (View), un
JavaBean para manejar lo que sucede cuando el usuario interactúa con la
vista (Controlador), y los beans de entidad y de sesión para los objetos de
aplicación (Modelo). Separando el Controlador de la Vista permite al JavaBean
servir como una envoltura para el bean de sesión y ofrece un ejemplo mucho
más claro de la separación MVC. Una aplicación que usa patrones de diseño es
mucho más sencilla de actualizar, mantener y manejar.

5.1. Sobre el Ejemplo

En la Lección anterior, el interface de usuario de la aplicación consiste en una


página HTML con un formulario HTML. El formulario llama a la página JSP
cuando el usuario pulsa el botón Submit de la página HTML.

Otra forma de crear el interface de usuario es con una página JSP que incluya
el formulario HTML, scriptlets JSP, y etiquetas específicas JSP para
interactúar con el JavaBean. Cuando se carga la página JSP, se muestra el
formulario HTML y se ejecutan los escriptlets y las etiquetas especificas JSP
para interactuar con el JavaBean. Como todavía no se han suministrado datos,
la pantalla se parecerá a la de la siguiente figura:
68 Introducción a J2EE

Cuando el usuario introduce algún dato y pulsa el botón 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 parecería
algo a la de la siguiente figura. Esto es porque el parámetro ACTION del
formulario HTML de bonus.jsp se llama a sí mismo de forma recursiva.

Si el usuario introduce el mismo número de la seguridad social, se devuelve un


error de clave duplicada y se muestra sobre la página JSP como se muestra en
la siguiente figura:
Capítulo 5.Tecnología JavaBeans 69

5.2. Crear bonus.jsp

El código de bonus.jsp es bastante sencillo poque el código que busca el bean


de sesión y calcula el bono está ahora en el JavaBean. La primera parte del
fichero contiene el código HTML para crear el formulario. El código 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"
70 Introducción a J2EE

value="<%=ssec%>"/>

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"/>

</BLOCKQUOTE>
</BODY>
</HTML>

Especificar el JavaBean

La siguiente etiqueta HTML especifica el JavaBean que se esta utilizando en


este ejemplo. El parámetro id define un alias para usarlo como referencia al
JavaBean, y el parámetro class especifica la clase JavaBean. En este ejemplo
el id es jbonus y el class es JBonusBean.
<jsp:useBean id = "jbonus" class = "JBonusBean"/>

Obtener los Datos

Los siguientes scriptlets JSP recuperan los datos suministrados por el usuario
desde los campos del formulario HTML. El multiplicador se almacena en la
variable sMult String, y el número de la seguridad social en la variable ssec
String.
<%! String sMult, ssec; %>
<%
sMult = request.getParameter("MULTIPLIER");
ssec = request.getParameter("SOCSEC");
%>

Pasar los Datos al JavaBean

Las siguientes etiquetas HTML configuran dos propiedades del JavaBean. Una
propiedad es un campo privado de la clase JavaBean. La primera línea usa la
etiqueta jsp:setProperty para configurar el campo strMult en la clase
JBonusBean (con el alias jbonus id) al valor almacenado en la variable sMult.
La segunda línea realiza una operación similar para el campo socsec de la
clase JBonusBean.
<jsp:setProperty name = "jbonus" property="strMult" value="<%=sMult%>"/>
<jsp:setProperty name = "jbonus" property="socsec" value="<%=ssec%>"/>

La expresión value="<%=ssec%>" envía el dato contenido en la variable ssec al


campo socsec del JavaBean.
Capítulo 5.Tecnología JavaBeans 71

Recuperar los Datos desde el JavaBean

Recuperar los datos desde el JavaBean es similar a enviárselos. Usamos la


etiqueta jsp:getProperty e indicamos la propiedad (campo privado) cuyo dato
queremos obtener. La siguiente etiqueta getProperty obtiene el dato
almacenado en el campo privado socsec de la clase JBonusBean (con el alias
jbonus id ).
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"/>

5.3. Crear la Clase JavaBean

Una clase JavaBeans™ (o bean para acortar) se parece a cualquier clase


normal del lenguaje Java™. Pero para ser un bean, una clase JavaBean debe
seguir un conjunto de sencillas convenciones de nombres y diseño explicados
en la especificación JavaBeans. Como los Beans cumplen la especifiación
JavaBean, pueden ser accedidos y manejados por otros programas y
herramientas que cumplan las mismas convenciones.

En la sección Crear bonus.jsp, se utilizarón etiquetas HTML y scriptlets JSP


para obtener y seleccionar los datos privados de la clase JBonusBean. Esto es
posible porque la clase JBonusBean sigue las convenciones de nombrado y
diseño de JavaBeans.

Esta sección describe el código de JBonusBean y nos ofrece una sencilla


presentación de la tecnología JavaBeans cuando se usa con páginas JSP.

Aquí tenemos la clase JBonusBean completa.


import javax.naming.*;
import javax.rmi.PortableRemoteObject;
import Beans.*;

public class JBonusBean {


private String strMult, socsec, message;
private double bonusAmt;
CalcHome homecalc;

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();
72 Introducción a J2EE

}
}
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(
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;
}
}

Propiedades del Bean

Las propiedades definen los datos que un JavaBean pone a disposición de


otros programas o herramientas a través de métodos get o set. Los datos
podrían hacer cosas como definir la apariencia o el comportamiento del
JavaBean, o utilizarse para algún cálculo, etc. Las propiedades realmente son
campos privados de la clase que siempre deberían ser privados y sólo
accesibles a través de métodos set y get.

El siguiente segmento de código muestra las propiedades privadas de la clase


JBonusBean. Esta clase tiene un correspondiente método get<property> para
cada campo y sus correspondientes métodos set<property> para los campos
strMult y socsec.
public class JBonusBean {
private String strMult, socsec, message;
private double bonusAmt;
Capítulo 5.Tecnología JavaBeans 73

Constructor

El constructor JBonusBean busca el bean de sesión.


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();
}
}

Métodos Set

JBonusBean tiene dos métodos set (métodos precedidos por la palabra set).
Estos métodos seleccionan propiedades (campos privados) con valores
especificados. Los dos métodos 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 página JSP. El servidor J2EE
usa la información suministrada en la siguiente etiqueta setProperty name
para localizar el correspondiente método 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 métodos set<property> siguen las convenciones de


nombrado para que el servidor J2EE pueda mapear las etiquetas setProperty
name del fichero JSP a los métodos set<property> correctos para pasar los
datos desde la página JSP al JavaBean.

Con los métodos set, el nombre de método 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
convención empiezan siempre con una letra minúscula, la segunda palabra de
un nombre de método siempre empieza con una máyuscula. Por eso, para
seleccionar el campo privado socsec, el nombre del método es setSocsec. El
servidor J2EE mapea la mayúscula de Socsec en el nombre del método a la
minúscula socsec del campo. Los métodos set no tienen valor de retorno y
tienen un argumento del tipo apropiado.
public void setSocsec(String socsec) {
this.socsec = socsec;
}
public void setStrMult(String strMult) {
this.strMult = strMult;
}
74 Introducción a J2EE

Métodos Get

JBonusBean tiene cuatro métodos get (métodos precedidos por la palabra get
). Los métodos Get obtienen y devuelven un valor de propiedad (valores de
campos privados). Los cuatro métodos 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 método getBonusAmt. La página JSP recupera los
datos de las propiedades de JBonusBean usando las siguientes etiquetas
getProperty name. La página JSP sólo recupera los valores que le interesan,
por eso podríamos observar que aunque hay una propiedad en JBonusBean
para el multiplicador (el campo strMult), este valor no es recuperado por la
página 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 métodos Get siguen las mismas convenciones de nombres que los métodos
Set por eso la página JSP puede recuperar los datos del JBonusBean. Los
métodos Get siempre tienen un valor de retorno y no tienen argumentos.
Podríamos observar que aunque el método getBonusAmt seleccciona valores
de propiedades, realmente no necesita devolver ningún valor en este
ejemplo, devuelve this.bonusAmt para evitar un error en tiempo de ejecución
del servidor J2EE.

El método getBonusAmt usa una sentencia if-else para manejar el caso cuando
no se suministra ningún valor strMult. Cuando la página JSP se carga por
primera vez, el usuario final no ha suministrado ningún dato, pero todas las
etiquetas y scriptlets de la página 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 página 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 página 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(
Capítulo 5.Tecnología JavaBeans 75

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;
}

5.4. Arrancar la Plataforma y las Herramientas

Para ejecutar este ejemplo, necesitamos arrancar el servidor J2EE, la


herramienta Deploy, y la base de datos Cloudscape. En diferentes ventanas,
tecleamos los siguientes comandos:

j2ee -verbose
deploytool
cloudscape -start

Si esto no funciona, tecleamos esto desde el directorio J2EE:

Unix

j2sdkee1.2.1/bin/j2ee -verbose
j2sdkee1.2.1/bin/deploytool
j2sdkee1.2.1/bin/cloudscape -start

Windows

j2sdkee1.2.1\bin\j2ee -verbose
j2sdkee1.2.1\bin\deploytool
j2sdkee1.2.1\bin\cloudscape -start
76 Introducción a J2EE

5.5. Eliminar el Fichero WAR

Como se ha añadido una página JSP al componente Web, tenemos que borrar
el fichero WAR de las lecciones anteriores y crear uno nuevo con la página
JSP.

Local Applications:

• Pulsar el icono 2BeansApp para poder ver los componentes de nuestra


aplicación.
• Seleccionamos BonusWar para que se ilumine.
• Seleccionamos Delete desde el menú Edit.

5.6. Crear el Nuevo Fichero WAR

Menú File:

• Seleccionamos New Web Component

Introduction:

• Leemos y pulsamos Next .

War File General Properties :

• Especificamos BonusWar para el nombre de display.


• Pulsamos Add
• Vamos al directorio ClientCode y añadimos Bonus.jsp,
• Pulsamos Next
• Vamos al directorio ClientCode y añadimos JBonusBean.class
• Pulsamos Finish .

Propiedades Generales del Fichero War:

• Pulsamos Next.

Elegir el tipo de Componente: .

• Seleccionamos Describe a JSP.


• Pulsamos Next.

Propiedades generales del Componente:

• Ponemos Bonus.jsp como nombre de fichero JSP.


• Ponemos BonusJSP como nombre de display.
• Pulsamos Finish .
Capítulo 5.Tecnología JavaBeans 77

Ventana Inspecting:

• Seleccionamos Web Context


• Especificamos JSPRoot.

5.7. Verificar y Desplegar la Aplicación J2EE

Antes de desplegar la aplicación, es una buena idea ejecutar el verificador. El


verificador mostrará los errores en los componentes de la aplicación como
métodos inexistentes que el compilador no captura.

Verificar:

• Con 2BeansApp seleccionado, elegimos Verifier desde el menú Tools.


• En el diálogo que aparece, pulsamos OK. La ventana debería decir que
no hay ningún fallo.
• Cerramos la ventana del verificador porque ahora estamos listos para
desplegar la aplicación.

Nota:
En la versión 1.2.1 del software podríamos obtener un error tests
app.WebURI. Esto significa que la herramienta DeployTool no puso la
extensión .war al fichero WAR durante su creacción. Es un error menor y la
aplicación J2EE se despliega sin problemas.

Desplegar:

• Desde el menú Tools, elegimos Deploy Application. Se mostrará una


caja de diálogo Deploy BonusApp.
• Verificar que la selección 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 aplicación solitaria para el programa cliente. Este ejemplo
usa un servlet y una página HTML por lo que no debe estár marcada. Esta caja
crea un fichero JAR con toda la información de despliegue necesaria para una
aplicación 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 .
78 Introducción a J2EE

• Pulsamos Finish para empezar el despliegue. Se mostrará una caja de


diálogo que mostrará el estado de la operación de despliegue.
• Cuando se haya completado, las tres barras de la izquierda se habrán
sombreado completamente, como se ve en la siguiente figura. Cuando
esto suceda pulsamos OK.

5.8. Ejecutar la Aplicación J2EE

El servidor web se ejecuta por defecto en el puerto 8000. Para abrir la página
bonus.html apuntamos nuestro navegador a
http://localhost:8000/JSPRoot/bonus.html, que es dónde la herramienta de
despliegue puso el fichero HTML.

• Rellenamos un número de la seguridad social y un multiplicador.


• Pulsamos el botón Submit. Bonus.jsp procesa nuestros datos y devuelve
una página HTML con el bono calculado.

Bonus Calculation

Social Security number retrieved: 777777777


Bonus Amount Retrieved: 200.0

Si hemos suministrado dos veces el mismo número de la seguridad social,


veremos algo similar a esto:

Bonus Calculation

Soc Sec passed in: 777777777


Multiplier passed in: 2
Error: Duplicate primary key
Capítulo 6.Añadir eXtensible Markup Languaje (XML) 79

6. Añadir eXtensible Markup


Language (XML)
eXtensible Markup Language (XML) es un lenguaje para representar y
describir datos basados en texto para que los datos puedan ser leídos y
manejados por cualquier progrma o herramienta que usa los APIs XML. Los
programas y herramientas pueden generar ficheros XML que otros programas y
herramientas pueden leer y manejar.

Por ejemplo, una compañía puede usar XML para producir informes para que
las diferentes partes que reciban los informes puedan manejar los datos de
una forma apropiada a sus necesidades. Una parte podría pasar los datos XML
a través de un programa para traducirlos a HTML y poder ponerlos en la Web,
otra parte podría pasar los datos por una herramienta para producir un inform
de stocks, y otra tercera parte podría pasar los datos XML a través de una
herramienta para crear una presentación de marketing. Mismos datos,
diferentes necesidades, y un grupo de programas y herramientas
independientes de la plataforma para usar los mismos datos en varis formas
distintas. Estas capaciades tan flexibles y baratas están disponibles a través
de etiquetas XML, Definiciones de Tipos de Documentos (DTDs) también
conocidos com esquemas XML, y los APIs XML.

Esta lección adapta el ejemplo de la Lección anterior para que la clase


JavaBeans use los APIs XML para impriir un sencillo informe donde los datos
están marcados con etiquetas XML.

6.1. Marcar y Manejar Texto

Con XML definimos etiquetas de marcas para representar diferentes


elementos de datos en un fichero de texto. Por ejemplo, si tenemos un
fichero de texto que consiste en un pequeño artículo, definimos etiquets que
represente el título, el autor, las cabeceras de primer nivel, las cabeceras de
segundo nivel, las listas bulleteadas, el texto del artículo, etc. Una vez que
los datos están representados por etiquetas XML, podemos crear una
Definición de Tipo de Documento (DTD) y/o un fichero "eXtensible Style sheet
Language (XSL)" para describir cómo queremos que se manejen los datos.

• Los estilos XSL nos pemiten hacer cosas como el mapeo de XML a HTML.
Por ejemplo, podemos definir una etiqueta de título XML para que
represente el título de un artículo, y crear un fichero XSL que mapee la
etiqueta de título CML a una etiqueta H1 de HTML para mostrarselo al
usuario final.
• Un DTD (también conocido como esquema XML) contiene
especificaciones que permiten a otros programa validad la estructura
de un fichero XML para asegurarse que los datos están etiquetados de
la forma correcta. Por ejemplo, un DTD para un artículo podría
permitir una etiqueta de título, pero cero o más primeros y segundos
niveles de cabeceras.
80 Introducción a J2EE

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 artículo titne dos
etiquetas de título, pero el DTD permite sólo una, el programa devuelve un
error. Chequear un documento XML contra un DTD es lo que se conoce como
verificación.

Lo más 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 cómo se utilice el documento. Por
ejemplo, un artículo 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.

La versión 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.

6.2. Modificar la Clase JavaBean

En esta lección, se añade un método genXML a la clase JBonusBean para


generar el documento XML mostrado abajo. Después de ver las etiquetas y
estructura de un documento XML vermos el código que genera este
documento XML.
<?xml version="1.0"?>
<report>
<bonusCalc ssnum="777777777" bonusAmt="300.0" />
</report>

Prólogo XML

La línea <?xml version="1.0"?> es el prólogo XML. Un fichero XML siempre debe


empezar con un prologo que lo identifique como un fichero XML. El prólo no
es necesario si sólo va a ser leído por humanos, pero es buena idea incluirlo.
Junto con la información de versión, el prólogo también puede incluir
información de codificación e información "standalone.

• Información de Codificación: 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 Inglés se indica como:<?xml
version="1.0" encoding="ISO-8859-1"?>.
• Información Standalone: idnica si este documento usa información de
otros ficheros. Por ejemplo, un documento XML podría relacionarse con
una hoja de estilo para infomación sobre cómo crear un interface de
usuario e HTML, o un DTD para especificaciones de etiquetas válidas.
Capítulo 6.Añadir eXtensible Markup Languaje (XML) 81

Documento Raíz

La etiqueta <report> es la primera etiqueta XML de este fichero. Es la


etiqueta XML de más 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. Podría
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 añade al raíz. Usa atributos para especificar el número 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 algún atributo o si los atributos presentes no deberian estar ahí.
<bonusCalc ssnum="777777777" bonusAmt="300.0" />

Otras Etiquetas XML

Hay varias formas de etiquetar datos XML. Este ejemplo usa etiquetas vacías,
que son etiquetas que no encierran datos, usan atributos para especificar
datos, y se cierran con una barra inclinada. La siguiente etiqueta vacía de
este ejemplo, podría crearse para que los datos se encerraran entre etiquetas
XML. El analizador XML chequea todos los datos encerrados por datos que
llamados etiquetas bien-formadas. Las etiquetas bien-formadas consisten en
una etiqueta de apertura y una de cierre como es muestra en el ejemplo de
abajo:

Etiqueta Vacía:
<bonusCalc ssnum="777777777" bonusAmt="300.0" />
Etiquetas bien-formadas:
<bonusCalc>
<ssnum>"777777777"</ssnum>
<bonusAmt>300.0</bonusAmt>
</bonusCalc>

Los comentarios XML son como las etiquetas de comentario HTML.

<!-- Bonus Report -->


<bonusCalc ssnum="777777777" bonusAmt="300.0" />

Las instrucciones de procesamiento le dan comandos o información a una


aplicación que está procesando los datos XML. Las instrucciones de
procesamiento tienen el formado <? target instructions?> donde target es el
82 Introducción a J2EE

nombre de la aplicación que está haciendo el procesamient, e instructions


encierra la información o comandos para que los procese la aplicación. El
prólogo es un ejemplo de una instrucción de procesamiento, donde xml es la
fuente y version="1.0" encierra las instrucciones. Debemos observar que el
nombre de fuente xml esta reservado para estándar XML.
<?xml version="1.0"?>

También podemos usar instrucciones de procesamiento par ahacer cosas como


distinguir entre diferentes versiones de una representación como la versión de
alto nivel ejecutivo y la versión de nivel técnico.

Código del JavaBean

La clase JBonusBean para esta lección tiene sentencias import para crear el
documento XML, manejar errores, y escribir el documento en el terminal. Esta
lección escribe la salida del XML en el terminal para mantener las cosas
sencillas. También podría escribirse en un fichero, pero necesitaríamos
configutrar nuestro navegador para usar el Java Plug-In e incluir un fichero de
policía de seguridad que concediera permiso para escribir un fichero.

Para generar el fichero XML para esta lección, necesitamos importar las clases
ElementNode y XmlDocument. También necesitamos las clases StringWriter e
IOException para escribir datos XML en el terminal.
import javax.naming.*;
import javax.rmi.PortableRemoteObject;
import Beans.*;
import java.io.StringWriter;
import java.io.IOException;
import com.sun.xml.tree.ElementNode;
import com.sun.xml.tree.XmlDocument;

Esta versión de la clase JBonusBean tiene una variable más de ejemplar. El


interface remoto del bean de sesión, theCalculation, necesita ser accedido
desde los métodos 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 método getRecord del bean de sesión.
Calc theCalculation;

El método JBonusBean.genXML es llamado desde el método getBonusAmt


después de que el proceso se complete en el evento strMult y no sea null . Lo
prmero que este método hace es crear un objeto XMLDocument y el nodo raíz,
y añade la raíz al documento. El nodo raíz represetna el punto de más 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
Capítulo 6.Añadir eXtensible Markup Languaje (XML) 83

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 número de la seguridad social desde el
registro, convierte el valor del bono a un string, crea un nodo hijo (bonusCalc
), y añade el número 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);
//Add child node to root
root.appendChild(bonusCalc);
} catch (java.rmi.RemoteException e) {
e.printStackTrace();
}

La última parte del método 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 representación simplificada del DOM
del ejemplo de esta lección. Las llamadas al API en el método genXML crea el
DOM y podemos aplicar las llamadas al API para acceder al DOM paa hacer
cosas como añadir, borrar y editar nodos hijos, o validar el DOM contra un
DTD. Podemos crear un DOM desde un fichero XML.
84 Introducción a J2EE

6.3. Los APIs

El fichero j2ee.jar que viene con nuestra instalación 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 creacción...

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 razón, se tiende a preferir el API SAX para
aplicaciones cliente-servidor y para filtros de datos que no requieren una
representación de los datos en memoria.
Capítulo 6.Añadir eXtensible Markup Languaje (XML) 85

J2EE

El API XML J2EE independiente de la plataforma usa un árbol DOM y


proporciona muchos métodos para manipularlo. los APIs XML J2EE están en el
paquete com.sun y se han utilizado en el ejemplo de esta lección. No
olvidemos que estos APIs están sujetos a modificaciones.

6.4. Actualizar y Ejecutar la Aplicación

Como todo lo que hemos hecho en esta lección ha sido modificar la clase
JBonusBean, simplementen podemos actualizar y redesplegar la aplicación.

• Ventana Local Applicatons: Seleccionamos la aplicación 2BeansApp.


• Menú Tools: Seleccionamos Update and Redeploy Application.

Nota:
La aplicación BonusApp de la lección anterior se desinstala automáticamente.

El servidor web se ejecuta por defecto en el puerto 8000. Para abrir la página
bonus.jsp apuntamos el navegador a
http://localhost:8000/JSPRoot/bonus.jsp, que es donde la herramietna
Deploy puso la página JSP.

• Rellenamos un número de la seguridad social y un multiplicador.


• Pulsamos el botón Submit. Bonus.jsp procesa nuestros datos y devuelve
una página HTML con el bono calculado.
Capítulo 7.Añadir JDBC 87

7. Añadir JDBC
Hasta ahora, la aplicación de ejemplo J2EE ha escrito y leído los datos desde
una base de datos Cloudscape subyancente sin que hayamos escrito código
SQL. Esto es porque el contenedor ha estado manejando el almacenamiento y
recuperación de los datos a través del bean de entidad. La persistencia
controlada por el contenedor es el termino usado para describir la situación
donde el contenedor maneja el almacenamiento y la recuperación. Esta
lección nos muestra como sobreescribir la persistencia controlada por el
contenedor por defecto e implementar la persistencia controlada por el bean.

La persistencia controlada por el bean es cuando nosotros escribimos métodos


de los beans de entidad o de sesión 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 lección modifica el bean de entidad de la aplicación de ejemplo J2EE


para usar persistencia controlada por el bean.

7.1. Ciclo de Vida del Bean

La Lección 3 mostraba la clase BonusBean manejada por el contenedor. Los


únicos métodos con implementaciones eran getBonus para devolver el valor
del bono, getSocSec para devolver el número de la seguridad social, y
ejbCreate para crear un bean de entidad y pasarle los valores bonus y socsec.
El contenedor tenía en cuenta cosas como la creacción de la fila en la tabla
de la base de datos, y asegurarse de que los datos en memoria era
consistentes con los datos de la fila de la tabla. Con la persistencia controlada
por el bean nosotros tenemos que implementar todos estos comportamientos,
lo que significa añadir codigo JDBC™ y SQL, e implementar los métodos vacíos
del ejemplo controlado por el contenedor.

Un bean de sesión o de entidad consiste en métodos de negocio y métodos de


ciclo de vida. en el ejemplo, CalcBean tiene dos métodos de negocio,
calcBean y getRecord , y BonusBean tiene dos métodos de negocio getBonus y
getSocsec. Tanto CalcBean como BonusBean tienen los siguientes métodos de
ciclo de vida. A los métodos de negocio los llama el cliente y a los métodos
del ciclo de vida los llama el contenedor del bean.

• setEntityContext: El contenedor llama primero a este método para


pasar un objeto contexto al bean de entidad. El contexto de entidad lo
actualiza dinamicamente el contenedor incluso si muchos clientes
llaman al bean de entidad a la vez, el contexto contiene datos actuales
para cada llamada. Un bean de sesión tiene un método
setSessionContext correspondiente que realiza una función similar a la
del método setEntityContext.
• ejbCreate: El contenedor llama a este método cuando un cliente llama
al método create del interface home del bean. Por cada método create
88 Introducción a J2EE

en el interface home, el bean tiene un método ejbCreate


correspondiente con la misma firma (parámetros y valor de retorno).
• ejbPostCreate: El contenedor llama a este método después de que se
complete el método ejbCreate. Hay un método ejbPostCreate por cada
método ejbCreate que toma los mismos argumentos que su método
create. Sin embargo, ejbPostCreate no tiene valor de retorno. Usamos
ejbPostCreate para implementar cualquier procesamiento especial que
necesitemos hacer después de crear el bean y antes de que esté
disponible para el cliente. Lo podemos dejar en blanco si no
necesitamos procesamiento especial.
• ejbRemove: El contenedor llama a este método cuando un cliente
llama al método remove del interface home del bean. La aplicación de
ejemplo J2EE para este tutorial no incluye ningún método remove en el
interface home.
• unsetEntityContext: El contenedor llama a este método después de que
se haya llamado a ejbRemove para eliminar el bean de entidad. Sólo los
beans de entidad tienen un método unsetEntityContext. Un bean de
sesión no tiene el correspondiente método unsetSessionContext.
• ejbFindByPrimaryKey: El contenedor llama a este método cuando un
cliente llama al método findByPrimaryKey del interface home del bean.
Por cada método find del interface home del bean, tiene su
correspondiente método ejbFind< type > con la misma firma
(parámetros y valor de retorno).
• ejbLoad y ejbStore : El contenedor llama a estos métodos para
sincronizar el estado del bean con la base de datos subyacente. Cuando
un cliente selecciona u obtiene los datos de un bean como en el caso
de un método get, el contenedor llama al método ejbStore para envíar
el objeto a la base de datos y llama a ejbLoad para leerlo de nuevo.
Cuando un cliente llama a un método 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 métodos para
activar o desactivar el estado del bean. La activación o desactivación
se refieren al intercambio del bean dentro y fuera del almacenamiento
temporal para liberar memoria, que podría ocurrir si un bean dado no
ha sido llamado por un cliente desde hace mucho tiempo. Las
implementaciones de ejbPassivate podrían incluir cosas como el cierre
de conexiones o ficheros usados por el bean, y para ejbActivate podría
incluir cosas como la reapertura de las mismas conexiones o ficheros.

7.2. Modificar el código de BonusBean

Esta sección nos lleva a través del código de BonusBean con persistencia
controlada por el bean. Lo primero que observaremos es que hay mucho más
código que en la versión con persistencia controlada por el contenedor.
Capítulo 7.Añadir JDBC 89

Sentencias Import

Los interfaces InitialContext, DataSource, y Connection se importan para


establecer conexiones con la base de datos. El interface PreparedStatement
se importa para usarlo como plantilla para crear una petición SQL. El
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 búsqueda 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;

Variables de Ejemplar

Las variables de ejemplar añadidas en esta lección 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 también deberíamos
especificar cuando añadamos el bean de entidad a la aplicación 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.

Después 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;

Métodos de Negocio

Los métodos de negocio no han cambiado para esta lección excepto en las
llamadas a System.out.println, que nos permiten ver el orden en que se
llaman los métodos de negocio y ciclo de vida durante la ejecución.
public double getBonus() {
System.out.println("getBonus");
return this.bonus;
}
public String getSocSec() {
System.out.println("getSocSec");
return this.socsec;
}
90 Introducción a J2EE

Métodos de Ciclo de Vida

Estos métodos incluyen llamadas a System.out.println para que podamos ver


en que orden se llaman durante la ejecución.

ejbCreate

La firma del método ejbCreate para esta lección lanza RemoteException y


SQLException además de CreateException. SQLException es necesaria porque
el método ejbCreate proporciona su propio código SQL, y RemoteException es
necesaria porque ese método realiza acceso remoto

Una cosa a observar de esta clase es que devuelve un valor String que es la
clave primaria, pero la declaración para este método en el interface home
espera recibir un ejemplar de la clase Bonus. El contenedor usa la clave
primaria devuelta por este método 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;
}
Capítulo 7.Añadir JDBC 91

ejbPostCreate

Este método tiene la misma firma que ejbCreate, pero no tiene


implementación porque nuestro ejemplo no realiza procesamientos o
inicializaciones posteriores a la creacción.
public void ejbPostCreate(double bonus,
String socsec)
throws RemoteException,
CreateException,
SQLException {
System.out.println("Post Create");
}

ejbFindByPrimaryKey

La versión controlada por el contenedor de BonusBean no incluia una


implementación de ejbFindByPrimaryKey porque el contenedor podría
localizar los registros de la base de datos por su clave primaria si
especificamos persistencia controlada por el contenedor y proporcionamos un
campo de clave primaria durante el despliegue. En esta lección, BonusBean se
despliega con persistencia controlada por el bean por eso debemos
proporcionar una implementación para este método y lanzar una
SQLException. La versión controlada por contenedor sólo lanzaba
RemoteException y FinderException.

Si la operación 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 método 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 declaración para este método en el interface home
espera recibir un ejemplar de la clase Bonus. El contenedor usa la clave
primaria devuelta por este método 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");
}
92 Introducción a J2EE

} catch (javax.naming.NamingException ex) {


ex.printStackTrace();
} finally {
//Close database connection
ps.close();
con.close();
}
//Return primary key
return key;
}

ejbLoad

Este método se llama después 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 {
//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 método cuando un cliente selecciona u obtiene datos en el


bean para envíar 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(
Capítulo 7.Añadir JDBC 93

"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();
} 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 método cuando un cliente llama al método remove del


interface home del bean. El cliente JavaBean de este ejemplo no proporciona
un método remove que el cliente pueda llamar para eliminar BonusBean desde
su contenedor. De todas formas, aquí podemos ver la implementación de un
método 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 rápidamente reactivar el bean en el caso de que algún cliente llame a
un método de negocio del bean. Este método llama al método getPrimaryKey
en el contexto de entidad para que la clave primaria esté disponible para los
clientes del bean. Cuando se hace una petición, el contenedor usa la clave
primaria para cargar los datos del bean.
94 Introducción a J2EE

public void ejbActivate() {


System.out.println("Activate method");
socsec = (String)context.getPrimaryKey();
}

ejbPassivate

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 rápidamente reactivar el bean en el caso de que algún cliente llame a
un método de negocio del bean. Este método 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 método para inicializar la variable de ejemplar


context del bean. Es necesario porque el método ejbActivate llama al método
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 método para poner a null la variable de ejemplar


context después de que se haya llamado al método ejbRemove para eliminar
el bean. Sólo los beans de entidad tienen un método unsetEntityContext.
public void unsetEntityContext(){
System.out.println("unsetEntityContext method");
ctx = null;
}
}
Capítulo 7.Añadir JDBC 95

7.3. Modificar el Código de CalcBean y JBonusBean

Como BonusBean proporciona su propio código SQL, el método


CalcBean.calcbonus, que crea ejemplares de BonusBean, tiene que
modificarse para lanzar la excepción java.sql.SQLException. Aquí tenemos la
forma de hacer este cambio:
public class CalcBean implements SessionBean {
BonusHome homebonus;

public Bonus calcBonus(int multiplier,


double bonus, String socsec)
throws RemoteException,
SQLException,
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


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;
96 Introducción a J2EE

} else {
this.bonusAmt = 0;
this.message = "None.";
return this.bonusAmt;
}
}

7.4. Crear la Tabla de la Base de Datos

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 automáticamente.

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 leccción.


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 leccción.


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
Capítulo 7.Añadir JDBC 97

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

cloudTable.sh

Este fichero se proporciona con los ficheros fuentes de esta leccción.


#!/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

7.5. Eliminar el Fichero JAR

Tenemos que actualizar el fichero JAR con el nuevo código del Bean. Si
tenemos los dos beans en un sólo fichero JAR, tenemos que borrar 2BeansJar y
crear uno nuevo. Los pasos para añadir CalcBean son los mismos que los de la
lección Comunicaciones entre Beans. Los pasos para añadir BonusBean son
ligeramente diferentes como se describe aquí.

Si tenemos los beans en ficheros JAR separados, tenemos que borrar el fichero
JAR con BonusBean y crear uno nuevo como se describe aquí.

Estas instrucciones empiezan en el momento de añadir los interfaces y las


clases de BonusBean al fichero JAR.

EJB JAR :

• Pulsamos Add (el más cercano a la ventana Contents).


• Cambiamos de directorio para que el directorio Beans muestre su
contenido.
• Seleccionamos Bonus.class
• Pulsamos Add .
• Seleccionamos BonusBean.class
• Pulsamos Add .
• Seleccionamos BonusHome.class
• Pulsamos Add .
98 Introducción a J2EE

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 :

• 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
válidos 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.


Capítulo 7.Añadir JDBC 99

Control de Transación :

• 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 transación antes de ejecutar estos
métodos. La transación se envía justo antes de que los métodos
terminen.
• Pulsamos Next .

Revisión 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.

7.6. Verificar y Desplegar la Aplicación

Antes de desplegar la aplicación, es una buena idea ejecutar el verificador. El


verificador mostrará los errores en los componentes de la aplicación como
métodos inexistentes que el compilador no captura.

Verificar:

• Con 2BeansApp seleccionado, elegimos Verifier desde el menú Tools.


• En el diálogo que aparece, pulsamos OK. La ventana debería decir que
no hay ningún fallo.
• Cerramos la ventana del verificador porque ahora estamos listos para
desplegar la aplicación.

Nota:
En la versión 1.2.1 del software podríamos obtener un error tests
app.WebURI. Esto significa que la herramienta DeployTool no puso la
extensión .war al fichero WAR durante su creacción. Es un error menor y la
aplicación J2EE se despliega sin problemas.

Desplegar:

• Desde el menú Tools, elegimos Deploy Application. Se mostrará una


caja de diálogo Deploy BonusApp.
• Verificar que la selección 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 información de despliegue necesaria por el bean de entidad.
• Pulsamos Next .
100 Introducción a J2EE

• 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
diálogo que mostrará el estado de la operación de despliegue.
• Cuando se haya completado,pulsamos OK.

7.7. Ejecutar la Aplicación

El servidor web se ejecuta por defecto en el puerto 8000. Para abrir la página
bonus.html apuntamos nuestro navegador a
http://localhost:8000/JSPRoot/bonus.html, que es dónde la herramienta de
despliegue puso el fichero HTML.

• Rellenamos un número de la seguridad social y un multiplicador.


• Pulsamos el botón Submit. Bonus.jsp procesa nuestros datos y devuelve
una página HTML con el bono calculado.

La salida del servidor J2EE podría mostrar los siguientes mensajes cada vez
que se intente un acceso a la base de datos. 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 versión más 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
Capítulo 7.Añadir JDBC 101

getBonus
Store method

<?xml version="1.0"?>
<report>
<bonusCalc ssnum="777777777" bonusAmt="300.0" />
</report>

Você também pode gostar