índice general_

1. 2. 3. 4. 5. 6.

INTRODUCCIÓN A J2EE ..............................................................1 APLICACIONES WEB .................................................................17 ENTERPRISES BEANS Y SERVICIOS DE CONTENEDOR ...............33 BEANS DE SESIÓN ....................................................................83 BEANS DE ENTIDAD................................................................109 BEANS CONTROLADOS POR MENSAJE. EMPAQUETADO Y ROLES ....................................................................................139

GLOSARIO ....................................................................................155 BIBLIOGRAFÍA..............................................................................157

1
índice_

Introducción a J2EE

1.1. 1.2.

JAVA ........................................................................................3 ¿QUÉ ES J2EE? .........................................................................3 1.2.1. El período de ejecución..................................................4 1.2.2. Los API J2EE .................................................................4

1.3. 1.4.

CONTENEDORES .......................................................................7 LA ARQUITECTURA MULTICAPA ................................................9 1.4.1. Las capas ......................................................................9 1.4.2. Las capas de J2EE........................................................11

1

1
1.1. JAVA para el desarrollo de software.

Introducción a J2EE

Hace ya varios años que el lenguaje de programación Java vio la luz. Desde entonces ha ido ganando en popularidad a pasos agigantados. Lo que en principio empezó siendo un lenguaje para la programación de electrodomésticos, es actualmente una de las mejores opciones

La que inicialmente se conoció como la plataforma Java, evolucionó con el paso del tiempo a la plataforma Java 2 (la versión 1.2) y se crearon tres ediciones distintas, cada una de ellas especializada en un conjunto de necesidades específicas y con un kit de desarrollo de software propio:

La plataforma Java 2 Edición Estándar (J2SE o Java 2 Standard Edition): Consiste en un entorno de tiempo de ejecución y un conjunto de API para crear aplicaciones y applets.

La plataforma Java 2 Edición Móvil (J2ME o Java 2 Mobile Edition): Permite la creación de aplicaciones para pequeños dispositivos y dispositivos inalámbricos, generalmente, con recursos muy limitados.

La plataforma Java 2 Edición Empresarial (J2EE o Java 2 Enterprise Edition): Contiene los API necesarios para la creación de aplicaciones para arquitecturas multicapa.

1.2. ¿QUÉ ES J2EE? J2EE es una tecnología que se centra fundamentalmente en el desarrollo de componentes para entornos distribuidos. Es un conjunto de especificaciones e indica tanto la estructura para gestionar las aplicaciones de empresa, como los servicios API para construir dichas aplicaciones. La plataforma J2EE es un entorno Java que ofrece:

− −

Una infraestructura de período de ejecución para contener y gestionar aplicaciones. Un conjunto de API para la construcción de aplicaciones.

3

1
1.2.1. El período de ejecución aplicaciones, es decir, el entorno en el que residen y se ejecutan.

Introducción a J2EE

El período de ejecución de un servidor J2EE es el contexto en el que “viven” las

La especificación J2EE no indica cómo debe o puede construirse un período de ejecución. Esto conlleva la separación entre las aplicaciones y la infraestructura del período de ejecución, la cual permite al periodo de ejecución abstraerse de los servicios de infraestructura. Desde el punto de vista del desarrollo, esto significa que los desarrolladores pueden centrarse en la lógica de negocio y despreocuparse de las cuestiones del nivel de sistemas. De este modo, la arquitectura J2EE nos proporciona un medio uniforme de acceder a los servicios a escala de la plataforma a través de su entorno de período de ejecución. Entre estos servicios podemos citar las transacciones distribuidas y la gestión de seguridad, entre otros. 1.2.2. Los API J2EE Ya sabemos que J2EE es un conjunto formado por varios API que nos permite realizar aplicaciones distribuidas. En este apartado vamos a enumerar los distintos API de los que se compone, junto con una breve descripción de cada uno de ellos.

Enterprise JavaBeans (EJB). Especifica una estructura de componentes para aplicaciones distribuidas. Además, suministra el medio para definir componentes del lado servidor y especifica la infraestructura de período de ejecución para albergar a dichos componentes. Un componente Enterprise JavaBeans es un bloque de código que implementa reglas de negocio. Puede ser autónomo o funcionar en conjunción con otros componentes para ejecutar lógica de negocio en un servidor J2EE.

Java Database Connectivity (JDBC). Permite el acceso a la información contenida en bases de datos mediante la utilización de sentencias SQL. Es una interfaz independiente del sistema de gestión de bases de datos, por lo que permite escribir código independiente del servidor de bases de datos.

4

1
Este API está formado por dos componentes: • a la base de datos. • entre el controlador JDBC y la plataforma J2EE.

Introducción a J2EE

Una interfaz a nivel de aplicación que usan los componentes para poder acceder

Una interfaz del proveedor de servicios (base de datos) que hace de puente

Java Servlet. Proporciona abstracciones para la construcción de aplicaciones web dinámicas y permite definir clases servlet específicas para el protocolo HTTP, extendiendo la capacidad de los servidores en los que las aplicaciones acceden mediante el modelo de programación solicitud-respuesta.

JavaServer Pages. Extiende las posibilidades de las aplicaciones web facilitando su desarrollo en el caso de aplicaciones dirigidas por un modelo.

Java Message Service (JMS). Es un API para colas de mensaje. Publica y suscribe tipos de servicios de software intermediarios controlados por mensajes. Además, permite a las aplicaciones la creación, envío, recepción y lectura de mensajes. Hace posible que las comunicaciones distribuidas con bajo nivel de acoplamiento sean fiables.

Java Naming and Directory Interface (JNDI). Este API pertenece realmente a la edición estándar de Java (J2SE), no obstante, lo incluimos aquí por la gran relación que tiene con el desarrollo de aplicaciones J2EE. Su finalidad es proveer funcionalidad de nombres y directorios y es independiente de cualquier implementación específica de servicio de designación de directorio. Por otra parte, provee métodos para la realización de las operaciones comunes de directorio, como la asociación de atributos con objetos y la búsqueda de objetos a partir de sus atributos. El API JNDI provee el acceso de las aplicaciones al entorno de nombres de JNDI. Este entorno permite personalizar los componentes sin tener que cambiar su código fuente.

5

1

transacciones. componentes.

Introducción a J2EE

Java Transaction API (JTA). Permite delimitar las operaciones transaccionales dentro las aplicaciones distribuidas. Es un medio para trabajar con transacciones y con transacciones distribuidas independientes de la implementación del gestor de

En la plataforma J2EE, las transacciones distribuidas están controladas por el contenedor, por lo que no debemos preocuparnos por las transacciones entre

JavaMail API. Proporciona una infraestructura independiente de la plataforma y del protocolo para el uso de mensajes (correo electrónico) desde las aplicaciones Java. Está formado por dos componentes: • • Una interfaz a nivel de aplicación que se usa para el envío de mensajes. Una interfaz de proveedor de servicios.

JavaBeans Activation Framework (JAF). Este API se incluye porque es necesario para el API JavaMail. Lo utiliza para determinar los contenidos de un mensaje y las operaciones apropiadas que pueden realizarse sobre las diferentes partes de un mensaje.

Java API for XML Processing (JAXP). Este API soporta el procesamiento de documentos XML usando DOM (Document Object Model), el API SAX (Simple API for XML Parsing) y XSLT (XML Stylesheet Language Transformation). Permite que las aplicaciones puedan analizar y transformar documentos XML con independencia de cualquier implementación específica.

Java API for XML Registries (JAXR). Permite el acceso sobre la web a los registros de empresa y de propósito general. • • Soporta los estándares ebXML Registry/Repository y las nuevas especificaciones UDDI. Con JAXR se puede aprender un único API para acceder a ambas tecnologías.

6

1

SOAP y HTTP. importar y exportar documentos WSDL.

Introducción a J2EE

Java API for XML-Based RPC (JAX-RPC). Permite que las aplicaciones puedan realizar llamadas a procedimientos remotos (RPC) sobre Internet mediante el uso de

También soporta WSDL (Web Service Description Language), por lo que se pueden

Por último decir que, mediante JAX-RPC y WSDL se puede interactuar con otros clientes y servicios.

SOAP with Attachments API for Java (SAAJ). Es un API de bajo nivel del que depende JAX-RPC. Hace posible la producción y consumo de mensajes que cumplan la especificación SOAP.

J2EE Connector Arquitecture (JCA). Se ha implementado para permitir la integración propietarios. Este API lo utilizan los desarrolladores de herramientas de J2EE y los integradores de sistemas para crear adaptadores de recursos que soporten acceso a sistemas de información corporativos que se puedan conectar con aplicaciones J2EE. Un adaptador de recursos es un componente que permite a los componentes de aplicaciones J2EE interactuar con el gestor de recursos subyacente (el sistema de información propietario). Cada adaptador de recursos es específico, ya que depende de dicho sistema de información. de componentes de aplicación J2EE de sistemas de información

Java Authentication and Authorization Service (JAAS). Proporciona mecanismos de autentificación y autorización para las aplicaciones.

1.3. CONTENEDORES Como ha hemos mencionado anteriormente, la especificación J2EE no describe la naturaleza y estructura del período de ejecución. En lugar de ello, introduce lo que se denomina contenedor y mediante los API especifica un contrato entre los contenedores y las aplicaciones, que no es más que un conjunto de normas que ambos deben cumplir. Podemos definir un contenedor J2EE como un período de ejecución para gestionar los

7

1
proporcionar acceso a los API de J2EE. Dentro de la arquitectura de J2EE, existen cuatro tipos de contenedores:

Introducción a J2EE

componentes de la aplicación desarrollados según las especificaciones del API y destinado a

− − − −

Contenedor de aplicación cliente: Alberga las aplicaciones Java estándar. Contenedor de applets: Alberga applets de Java. Contenedor web: Alberga aplicaciones web (servlets y páginas JSP). Contenedor EJB: Alberga componentes Enterprise JavaBean.

Cada de estos contenedores proporciona un entorno de período de ejecución para los componentes que aloja. Es el contenedor el que crea y gestiona dichos componentes, así como sus ciclos de vida. En esta arquitectura, los clientes empleados más frecuentemente son:

Clientes web. Se suelen ejecutar en navegadores web. La interfaz de usuario es generada dinámicamente por el servidor y mostrada por los navegadores. Se utiliza el protocolo HTTP para la comunicación entre el cliente y el servidor.

Clientes EJB. Son aplicaciones que acceden a componentes EJB. Existen tres tipos de clientes: • De aplicación. Son aplicaciones de escritorio que acceden a los EJB mediante el protocolo RMI-IIOP. • Componentes de contenedores web. Son servlets y páginas JSP que acceden a los componentes EJB utilizando el protocolo RMI-IIOP o llamadas estándar de métodos de Java mediante interfaces locales. • Componentes EJB. Se trata de EJB que acceden a otros EJB y que pueden utilizar RMI-IIOP o llamadas estándar de métodos estándar Java.

Ambos tipos de clientes acceden a los componentes de la aplicación mediante sus respectivos contenedores.

8

1
1.4. LA ARQUITECTURA MULTICAPA clientes.

Introducción a J2EE

Se entiende por capa a un grupo de tecnologías que suministran uno o más servicios a sus

La primera tecnología basada en capas que existió fue el modelo cliente/servidor y está basada en dos capas. En dicho modelo, las aplicaciones cliente son aplicaciones de escritorio y realizan peticiones a los servidores que ejecutan programas y que responden a las peticiones de los clientes. Un gran inconveniente de este tipo de arquitectura es que el mantenimiento actualizado del software de los clientes resulta difícil y costoso, sobre todo, a medida que va aumentando el número de clientes. Por el contrario, los sistemas multicapa basados en web no necesitan que se actualice el software de los clientes cuando se modifica la presentación o la funcionalidad de las aplicaciones. 1.4.1. Las capas En el apartado anterior definimos una capa como un grupo de tecnologías que suministran servicios a sus clientes. Para entender cómo se organiza una estructura de capas, podemos ver su similitud con una empresa de tamaño grande: En el nivel más bajo están los servicios de infraestructura que se componen de los recursos necesarios para mantener las instalaciones. Entre estos recursos tenemos: la electricidad, los ascensores, la telefonía y las redes informáticas. La siguiente capa contiene los servicios de soporte para la actividad principal de la empresa. Se compone de recursos como: la contabilidad, proveedores e informática. Sobre esta última se encontraría la capa de producción, que permite producir los productos y servicios que vende la empresa. Cuenta con recursos como: las compras, diseño de productos y facturación. Y por último, la capa más alta de la organización sería la de marketing, que permite determinar qué productos y servicios vender a los clientes. La siguiente figura muestra cómo se organiza en capas la estructura empresarial puesta

9

1
como ejemplo.

Introducción a J2EE

Por otro lado, hemos de entender por cliente a cualquier recurso que envía una petición de un servicio a un proveedor de servicios (o, como comúnmente se le hace referencia, servicio). Un servicio se define como cualquier recurso que recibe y atiende una petición de un cliente, y puede ser, a su vez, cliente de otro servicio. En una arquitectura multicapa, cada capa contiene servicios que incluyen objetos de software, sistemas de gestión de base de datos o conexiones con sistemas heredados. La arquitectura multicapa se utiliza porque es la forma más efectiva de construir aplicaciones flexibles y escalables. Esto se debe a que la funcionalidad de la aplicación se divide en componentes lógicos que se asocian con cada una de las capas, siendo cada componente un servicio que se construye y mantiene de forma independiente de los demás servicios. Los servicios se enlazan mediante un protocolo de comunicaciones que les permiten recibir y enviar información de y a otros servicios. De este modo, el cliente envía una petición de servicio, recibe los resultados y no debe preocuparse por la forma en que el servicio le debe proporcionar dichos resultados. Esto significa que podemos desarrollar rápidamente mediante la creación de un programa cliente que envía peticiones a los servicios que ya existen en la arquitectura multicapa. Estos servicios ya contienen la funcionalidad necesaria para atender la petición de nuestro

10

1
programa cliente.

Introducción a J2EE

Asimismo, los servicios pueden ir modificándose según va cambiando la funcionalidad y sin que afecte al programa cliente. Por ejemplo, podríamos tener un cliente que solicitara los impuestos asociados a un pedido determinado. Para ello, enviaríamos la petición al servicio que contiene la funcionalidad necesaria para calcular los impuestos (la lógica de negocio necesaria para calcular los impuestos estaría dentro del servicio) y en un futuro podría modificarse la lógica de negocio del servicio conforme a los cambios de las leyes de impuestos sin tener que modificar el programa cliente. 1.4.2. Las capas de J2EE La arquitectura J2EE está basada en cuatro capas, que son las siguientes:

Capa cliente. También es conocida como la capa de presentación o de aplicación, ya que es en la que se ubican los clientes finales (los usuarios de las aplicaciones).

− − −

Capa web.

Capa EJB o la capa de negocio. En ella se ubican las reglas de negocio.

Capa EIS. Llamada capa de los sistemas de información empresarial (Enterprise Information Systems).

Cada capa está orientada para proporcionar a una aplicación un tipo específico de funcionalidad. Es preciso diferenciar entre ubicación física y funcionalidad. A pesar de que varias capas puedan residir físicamente dentro de una misma máquina virtual (JVM), cada una proporciona a las aplicaciones J2EE distinto tipo de funcionalidad. Las aplicaciones J2EE tienen acceso únicamente a aquellas capas de las que requiere su funcionalidad.

11

1

Introducción a J2EE

En la siguiente figura podemos ver la estructura de capas de la arquitectura J2EE.

La mayoría de los API de J2EE tampoco están asociados con ninguna capa en concreto, es decir, se pueden utilizar en más de una capa. Por ejemplo, el API JDBC se puede utilizar en las capas web y EJB, mientras que el API EJB sólo es aplicable a la capa EJB. La capa cliente está compuesta por los programas que interactúan con el usuario de la aplicación. Estos programas le piden datos al usuario y convierten su respuesta en peticiones que se reenvían a un componente que procesa la petición y devuelve el resultado al programa cliente. El componente puede funcionar en cualquier capa, aunque normalmente las peticiones de clientes suelen ir dirigidas a componentes de la capa web. El programa cliente también traduce la respuesta del servidor en texto y pantallas que se muestran al usuario. Por otro lado, la capa web proporciona funcionalidad web a la aplicación J2EE. Los componentes de esta capa utilizan el protocolo HTTP para recibir peticiones de los clientes y enviar respuestas a los mismos (que pueden estar en cualquier capa). Recordemos que un cliente es cualquier componente que inicia una petición. La capa EJB (Enterprise JavaBeans) es la que contiene la lógica de negocio de las aplicaciones. Aquí se encuentran los componentes Enterprise JavaBeans a los que llaman los clientes. En esta capa, los EJB van a permitir que múltiples componentes de la aplicación tengan acceso a la lógica y datos de negocio de forma concurrente.

12

1
cada vez que se invoca a un Enterprise JavaBeans. sistemas de información empresarial (EIS).

Introducción a J2EE

Los Enterprise JavaBeans se encuentran dentro del contenedor de EJB, que es un servidor de objetos distribuidos que trabaja en la capa EJB. El contenedor gestiona las transacciones y la seguridad, y se asegura que los hilos y la persistencia se implementen de forma correcta

Aunque un EJB puede tener acceso a componentes de cualquier capa, generalmente llama a componentes y recursos como el DBMS (Database Management System) en la capa de

Por último, la capa EIS es la que conecta a la aplicación con recursos y sistemas heredados que están en la red corporativa. En esta capa, la aplicación J2EE se conecta con tecnologías como DBMS y mainframes que forman parte de los sistemas críticos de la empresa. Los componentes de esta capa se conectan a los recursos utilizando CORBA o conectores Java (JCA, Java Connector Architecture). En el apartado en el que tratamos los contenedores mencionamos un tipo de cliente consistente en una aplicación de escritorio. Se trata de una aplicación cliente/servidor que prescinde de la capa web y puede acceder directamente a la capa EJB para utilizar sus servicios. Normalmente, dichas aplicaciones acceden a los mismos componentes de la capa EJB que acceden los componentes de la capa web. Ya sabemos que la capa EJB es la que implementa la lógica de negocio y, por tanto, debe ser la capa que canalice las peticiones y les dé un trato homogéneo, con independencia del tipo de cliente que esté accediendo. En el siguiente gráfico se muestra cómo fluyen las peticiones y respuestas entre las distintas capas. Podemos ver que la aplicación cliente salta la capa web y usa directamente los servicios de la capa EJB. En dicha figura vemos también que la aplicación cliente y la capa web acceden a EJB distintos, sin embargo, no tiene que ser necesariamente así. Por ejemplo, si tenemos un componente EJB que determina las condiciones de venta de un determinado producto, lo razonable sería que cualquier cliente que necesite conocer dichas condiciones utilice el servicio que ofrece dicho componente EJB.

13

1

Introducción a J2EE

14

1
recuerde_

los servicios API para construir dichas aplicaciones.

Introducción a J2EE

J2EE es una tecnología que se centra fundamentalmente en el desarrollo de componentes para entornos distribuidos. Es un conjunto de especificaciones, e indica tanto la estructura para gestionar las aplicaciones de empresa, como

Un contenedor J2EE se define como un período de ejecución para gestionar los componentes de la aplicación desarrollados según las especificaciones del API y destinado a proporcionar acceso a los API de J2EE.

J2EE permite definir una arquitectura multicapa en la que cada una de las capas está orientada a proporcionar a una aplicación un tipo específico de funcionalidad.

15

2
índice_

Aplicaciones web

2.1. 2.2.

CONCEPTOS BÁSICOS.............................................................19 EL PROTOCOLO HTTP..............................................................20 2.2.1. La solicitud HTTP .........................................................21 2.2.1.1. El método GET ................................................21 2.2.1.2. El método POST ..............................................21 2.2.1.3. El método HEAD ..............................................22 2.2.2. La respuesta HTTP.......................................................22

2.3. 2.4. 2.5. 2.6.

CONTENEDORES WEB .............................................................23 SERVLETS...............................................................................25 PÁGINAS JSP .........................................................................27 EL DESCRIPTOR DE DESPLIEGUE ............................................29

17

2
2.1. CONCEPTOS BÁSICOS documentos HTML y XML y los ficheros de imágenes.

Aplicaciones web

Una aplicación web es un conjunto de páginas JSP, servlets, clases ayudantes, librerías de clases y recursos estáticos. Entre los recursos estáticos más comunes podemos citar los

En toda aplicación web podemos distinguir cuatro partes principales, que son:

Directorio público. Los recursos alojados en él están accesibles directamente a los clientes de la aplicación, exceptuando el directorio “WEB-INF” y su contenido.

Fichero “web.xml”. Es el fichero de despliegue de la aplicación web y está ubicado en el directorio “WEB-INF”.

Directorio “WEB-INF/classes”. Es el directorio en el que están almacenados los ficheros de clases que necesita la aplicación. Las clases deben estar organizadas en una estructura de directorios acorde a los nombres de los paquetes a los que pertenecen dichas clases.

Directorio “WEB-INF/lib”. Es el directorio en el que se almacenan los ficheros de clases empaquetadas (ficheros JAR o ZIP) que necesita la aplicación.

En el tema anterior vimos que existen principalmente dos tipos de clientes: los clientes web y los clientes de aplicación. Los clientes de aplicación tienen su origen en la arquitectura cliente-servidor. En ella, los clientes dirigen la interacción del usuario y la mayor parte de la lógica de aplicación. A los clientes de aplicación se les conoce también como clientes robustos y procesan la lógica de la aplicación de forma local. En una arquitectura multicapa, los clientes de aplicación pueden delegar parte de la lógica de aplicación y acceso a bases de datos en los componentes de la capa media (como los Enterprise JavaBeans). A pesar de esta distribución de la lógica de la aplicación en los componentes de la capa media, los clientes de aplicación requieren su instalación para cada usuario. Con la llegada de Internet, los clientes web sustituyeron a muchos clientes de aplicación autónomos. El principal motivo de este cambio radica en la propia naturaleza de los clientes web. En las arquitecturas basadas en ellos, la capa de interacción con el usuario está separada de la capa de cliente tradicional. Los navegadores web gestionan la interacción de usuario pero dejan el resto a las aplicaciones del lado servidor, incluidos la lógica para

19

2
acceso a las bases de datos. clientes web también son conocidos como clientes ligeros. Los clientes web se caracterizan por utilizar habitualmente:

Aplicaciones web

controlar la interfaz de usuario, la interacción con los componentes de la capa media y el

Para un usuario final, el navegador es el cliente para todas las aplicaciones basadas en web. Puesto que este tipo de clientes no impone ningún requisito especial en la instalación, los

− −

Un navegador web para la interacción con el usuario.

El uso de HTML, DHTML y XML para crear la interfaz de usuario. Normalmente se suele emplear también Javascript para el control dentro de dicha interfaz.

Los protocolos HTTP y/o HTTPS para el intercambio de información entre el cliente y el servidor.

La arquitectura J2EE nos ofrece un modelo de programación flexible y rico en funciones para construir aplicaciones web dinámicas. Dicha arquitectura nos proporciona contenedores web, el API Java Servlet y el API JavaServer Pages para la construcción y gestión de las aplicaciones web de forma que el contenedor web ofrece el entorno de período de ejecución y un marco para proporcionar apoyo a las aplicaciones web y los API Java Servlet y JavaServer Pages componen la base para el desarrollo de las aplicaciones web.

2.2. EL PROTOCOLO HTTP El protocolo de comunicación determina la naturaleza de los clientes y los servidores, y la relación entre ellos en el desarrollo de aplicaciones distribuidas. Lo mismo ocurre en el caso de las aplicaciones basadas en web. La complejidad de muchas de las características de nuestro navegador web y del servidor web depende del protocolo subyacente, que en este caso es HTTP (HiperText Transfer Protocol). Hemos de tener presente que HTTP es un protocolo de aplicación que suele implementarse sobre conexiones TCP/IP y que es un protocolo sin estado basado en solicitudes y respuestas. Los clientes envían solicitudes al servidor web para recibir información o para iniciar un proceso específico en el servidor.

20

2
2.2.1. La solicitud HTTP especifica cómo están estructuradas estas solicitudes y respuestas.

Aplicaciones web

El protocolo HTTP define los tipos de solicitudes que los clientes pueden enviar a los servidores y los tipos de respuestas que los servidores pueden enviar a los clientes. También

Los tipos de métodos de solicitud especificados por el protocolo HTTP han cambiado con la aparición de nuevas versiones. La versión 1.0 especifica tres tipos de métodos de solicitud: GET, POST y HEAD. La versión 1.1 añade cinco métodos nuevos: OPTIONS, PUT, TRACE, DELETE y CONNECT. De todos ellos, los métodos GET y POST cumplen la mayoría de los requisitos más comunes de desarrollo de aplicaciones. 2.2.1.1. El método GET

Es el método de solicitud más sencillo y usado con más frecuencia. Se utiliza normalmente para acceder a recursos estáticos como documentos HTML. Por otra parte, las solicitudes GET pueden utilizarse para recuperar información dinámica, incluyendo parámetros de consulta en el URL de la solicitud. Por último, el servidor web puede utilizar el valor de este parámetro para enviar contenido específico a un cliente. 2.2.1.2. El método POST

Se suele emplear para acceder a recursos dinámicos. Las solicitudes POST se utilizan habitualmente por dos motivos: para transmitir información que depende de la solicitud o cuando una gran cantidad de información compleja debe ser enviada al servidor. La solicitud POST permite encapsular los mensajes multiparte en el cuerpo de la solicitud. Como ejemplo podemos citar su uso para enviar archivos al servidor. Además, las solicitudes POST ofrecen una opción más amplia que las solicitudes GET en cuanto a los contenidos de dichas solicitudes. Por otra parte, existen ciertas diferencias entre las solicitudes GET y POST. Con las solicitudes GET, los parámetros de solicitud son transmitidos como una cadena de consulta adjunta en el URL de la solicitud. Por el contrario, en el caso de las solicitudes POST los parámetros son transmitidos en el cuerpo de la solicitud. Esto tiene dos consecuencias directas: en primer lugar, dado que la solicitud GET contiene la información completa de solicitud adjunta en el mismo URL, permite a los navegadores guardar la dirección de la página y volver a visitarla más tarde. Dependiendo del tipo y de la sensibilidad de los

21

2
información que podamos adjuntar al URL de solicitud. 2.2.1.3. El método HEAD

Aplicaciones web

parámetros de la solicitud, esto puede interesarnos o no. En segundo lugar, los servidores suelen imponer restricciones en cuanto a la longitud del URL. Esto limita la cantidad de

Un cliente enviará una solicitud de tipo HEAD cuando sólo desee ver las cabeceras de una respuesta, como “Contenido-Tipo” o “Contenido-Longitud”. Junto con el tipo de solicitud, la aplicación de cliente también especifica el recurso que necesita como parte de la cabecera de la solicitud. Vamos a ver un ejemplo: cuando introducimos “http://java.sun.com/index.jsp” en la barra de dirección de nuestro navegador, éste envía la solicitud GET al servidor web identificado por “java.sun.com”, para el recurso “index.jsp”. Para el protocolo HTTP, un identificador de recursos uniformes (URI, Uniform Resource Identifier) especifica un recurso. El URI es el URL pero excluyendo el nombre del dominio. En nuestro caso, el recurso es el archivo “index.jsp” localizado en el documento raíz del servidor web que sirve al dominio “java.sun.com”. 2.2.2. La respuesta HTTP Cuando un servidor recibe una solicitud HTTP responde con el estado de la respuesta y con información adicional que describe la respuesta. Todos estos elementos son parte de la cabecera de respuesta. Además, exceptuando el caso de las solicitudes HEAD, el servidor también enviará el contenido correspondiente al recurso que se ha especificado en la solicitud. Es decir, si en un navegador enviamos una solicitud a “http://java.sun.com/index.html” recibiremos el contenido del archivo “index.html” como parte del mensaje. Los campos de cabecera del contenido de la respuesta contienen información útil que los clientes pueden querer comprobar en determinadas circunstancias. Entre los campos habituales incluidos en la cabecera están: la fecha, el tipo de contenido y la fecha de expiración. Como ejemplo, podemos citar que el campo de fecha de expiración de una página podemos fijarlo con la misma fecha que el campo de fecha para indicar a los navegadores que no deben guardar la página en la caché. Las aplicaciones Web que suministren información dependiente del tiempo pueden necesitar establecer estos campos. Los servidores y clientes que se comunican utilizando el protocolo HTTP hacen uso de “MultiPurpose Internet Mail Extensions” (MIME) para indicar el tipo de contenido de los cuerpos de solicitud y respuesta. Los tipos MIME más comunes son: “text/html” y

22

2
extensión estándar. solicitudes para describir el tipo de datos que envían.

Aplicaciones web

“image/gif”. La primera parte de la cabecera indica el tipo de datos y la segunda indica la

Los servidores HTTP utilizan cabeceras MIME al principio de cada transmisión y los navegadores utilizan esta información para decidir cómo analizar y generar el contenido. Los navegadores también utilizan cabeceras MIME al transmitir datos en el cuerpo de las

El tipo de codificación MIME por defecto para solicitudes POST es “application/x-www-formurlencoded”. Las características principales del protocolo HTTP son:

− −

HTTP es un protocolo sin estado. Es muy simple y ligero.

Es el cliente el que inicia siempre la solicitud. El servidor no puede realizar una conexión de retrollamada al cliente.

Requiere que el cliente establezca conexiones previas a cada solicitud y que el servidor cierre la conexión después de enviar la respuesta. Esto garantiza que un cliente no pueda mantener una conexión después de recibir la respuesta. Cualquiera de los dos puede finalizar prematuramente una conexión.

2.3. CONTENEDORES WEB Las aplicaciones web son aplicaciones de lado servidor. Los requisitos fundamentales para el desarrollo de este tipo de aplicaciones son los siguientes:

− −

Un API y un modelo de programación que especifique cómo desarrollar aplicaciones.

Soporte de período de ejecución en el servidor que incluya el apoyo para los servicios de red necesarios y la ejecución de las tareas.

Soporte de implementación, es decir, de proceso de instalación y configuración de aplicaciones en el servidor.

23

2
elementos:

Aplicaciones web

Para que estos requisitos se cumplan, la especificación J2EE suministra los siguientes

Servlets y páginas JSP. Estos elementos son los bloques básicos de construcción para el desarrollo de aplicaciones web. Suelen recibir el nombre de componentes web.

− −

Aplicaciones web. Las tratamos al principio de este tema.

Contenedor web para albergar aplicaciones web.

Es un periodo de ejecución

Java que proporciona una implementación del API Java Servlet y facilidades para las páginas JSP. El contenedor web es el responsable de inicializar, invocar y gestionar el ciclo de vida de los componentes web.

Estructura de empaquetado y descriptores de implementación. La especificación J2EE define una estructura de empaquetado para las aplicaciones web y un descriptor de implementación para cada aplicación. El descriptor de implementación es un archivo XML que permite la adaptación de aplicaciones web en tiempo de despliegue.

Un contenedor web puede residir en tres ubicaciones distintas:

Integrado en un servidor de aplicaciones J2EE. La mayoría de los servidores de aplicaciones J2EE incluyen contenedores web. Como ejemplo podemos citar la implementación de referencia de Sun Microsystems.

Integrado en un servidor web. Es el caso de los servidores web basados en Java. Como ejemplo podemos citar el servidor Jakarta Tomcat.

Alojado en un período de ejecución independiente. Es el caso de servidores web ajenos a la especificación J2EE. Estos servidores requieren de un período de ejecución externo para la ejecución de los servlets y de un plugin en el propio servidor web para integrar dicho período de ejecución. Como ejemplo podemos citar el servidor Apache.

24

2
2.4. SERVLETS solicitudes y respuestas con el protocolo HTTP.

Aplicaciones web

Los servlets permiten que la lógica de la aplicación esté integrada en el proceso de

Podemos definir un servlet de Java como un programa pequeño que se ejecuta en el lado del servidor, que es independiente de la plataforma y que amplía la funcionalidad del servidor web. El API Java Servlet proporciona un marco sencillo para construir aplicaciones en estos servidores. Para que comprendamos mejor la función de la lógica de aplicación en el proceso de solicitud-respuesta, pensemos en un servidor de correo basado en web. Cuando nos registramos en dicho servidor, éste debe poder enviar una página con vínculos a nuestro correo, nuestras carpetas de correo, nuestro libro de direcciones, etc. Esta información es dinámica, es decir, cada usuario verá su propio buzón. Para poder generar este contenido, el servidor debe ejecutar una lógica de aplicación capaz de recuperar el correo y componer las páginas. Los clientes pueden enviar información de contexto o información específica propia al servidor en las solicitudes, y este último debe decidir cómo generar el contenido. El protocolo HTTP no define un medio estándar para integrar la lógica de aplicación durante la fase de generación de respuestas. Por lo tanto, no existe un modelo de programación específico para estas tareas. HTTP sólo define cómo pueden los clientes solicitar información y cómo pueden responder los servidores. Pero no especifica nada en cuanto a cómo puede o debe ser generada la respuesta. Los servlets Java no son aplicaciones que puedan invocar los usuarios. Es el contenedor web en el que está desplegada la aplicación que contiene los servlets, el que invoca a dichos servlets basándose en solicitudes HTTP entrantes. Cuando un servlet es invocado, el contenedor web le envía la información de la solicitud entrante de modo que éste pueda procesarla y generar una respuesta dinámica. El contenedor web actúa sólo como interfaz con el servidor web, aceptando solicitudes para los servlets y transmitiendo las respuestas de vuelta al servidor web. Si lo comparamos con CGI y extensiones de servidor de propiedad como NSAPI o ISAPI, el marco de servlet proporciona mejor abstracción para el paradigma solicitud-respuesta del protocolo HTTP, especificando un API de programación para encapsular solicitudes y respuestas. Por otra parte, los servlets tienen todas las ventajas del lenguaje de

25

2
del sistema operativo y de la plataforma de hardware.

Aplicaciones web

programación Java, como la independencia de la plataforma, ya que, las aplicaciones basadas en servlets pueden ser desplegadas en cualquier servidor web, con independencia

Para que podamos entender cómo un servlet interactúa con un servidor web a través de un contenedor web, vamos a tener en cuenta el proceso de invocación con el que el servidor web recibe una solicitud HTTP. Antes mencionamos que el protocolo HTTP se basa en un modelo de solicitudes y respuestas. Un cliente conecta con un servidor web y envía una solicitud HTTP en la conexión. Basado en un URL de solicitud, la secuencia de eventos que vemos a continuación tiene lugar en una secuencia típica. En la siguiente figura, las flechas que apuntan hacia la derecha representan las solicitudes, mientras que las que apuntan hacia la izquierda indican las respuestas.

Veamos algunas explicaciones sobre la figura anterior:

El servidor web tiene que descifrar si la solicitud entrante corresponde a una aplicación web del contenedor, lo que implica que debe haber un entendimiento entre el servidor y el contenedor. Los contenedores web utilizan el concepto de contexto de servlet para identificar las aplicaciones web. Este contexto debe ser especificado cuando la aplicación se despliega en el contenedor.

− −

Si el contenedor puede manejar la solicitud, el servidor la delega en él.

Cuando el contenedor ha recibido la solicitud decide qué aplicación es la que debe manejarla. En una aplicación Web de J2EE, una solicitud puede estar representada en un servlet, una página JSP o cualquier recurso estático. Esta representación está

26

2
navegador.

Aplicaciones web

basada en patrones URL. Todos los recursos indicados forman parte de la aplicación web. Cuando empaquetamos y desplegamos una aplicación, especificamos esta información de representación. El contenedor web la utiliza para representar cada solicitud entrante en un servlet, página JSP o recurso estático. Si el recurso está representado en un recurso estático, el contenedor se limita a pasar el recurso al servidor. Esto conforma el cuerpo de la respuesta que el servidor web envía al

En base a la información de representación, el contenedor web determina si la solicitud debe ser manejada por un Servlet. Y en caso de ser así, el contenedor crea o localiza una instancia de dicho servlet y delega en ella la solicitud.

Cuando el contenedor delega la solicitud en un servlet, le pasa objetos que encapsulan la solicitud y respuesta HTTP a la instancia del servlet. Para dicho servlet, estos objetos representan los flujos de solicitud y respuesta del navegador. El servlet puede leer la información de la solicitud y escribir una respuesta.

Para construir y desplegar una aplicación basada en un servlet se requieren los siguientes dos pasos:

− −

Escribir el servlet que contengan la lógica de negocio que se necesita.

Proporcionar un contexto y la información opcional de representación de patrón URL durante la fase de despliegue. Esta información es la que va a permitir identificar al servlet que debe manejar las solicitudes.

2.5. PÁGINAS JSP La generación de contenido dinámico puede conseguirse mediante generación de contenido basado en código (como los servlets) o la generación de contenido basado en una plantilla (como las páginas JSP). La tecnología JSP es una extensión de la tecnología servlets. La diferencia entre los servlets y las páginas JSP se basa en que los primeros son programas Java mientras que las páginas JSP son documentos basados en texto.

27

2
Una página JSP se compone de dos tipos de elementos:

Aplicaciones web

− −

HTML, DHTML o XML para los contenidos estáticos. Etiquetas y scriptlets escritos en Java que se utilizan para envolver la lógica que genera el contenido dinámico.

Dado que una página JSP proporciona una representación general del contenido y puede producir múltiples vistas en función del resultado de las etiquetas y scriptlets, las páginas JSP actúan como una plantilla para generar un contenido. Una plantilla es una página de anotación con marcas especiales (etiquetas y scriptlets) incrustados. Estas marcas contienen información para el procesador de la plantilla (el que genera el contenido). En una página JSP, la anotación nos permite definir su estructura estática y su contenido, y las marcas especiales nos posibilitan incluir lógica de programación para que se ejecute durante la generación de las páginas. La gran ventaja de esta tecnología es que ayuda a mantener separados el diseño del contenido y la lógica de la aplicación. Si utilizamos servlets únicamente ambos aspectos estarán estrechamente unidos, lo que conlleva que las aplicaciones sean más difíciles de mantener. En algunas otras tecnologías controladas por plantillas, éstas son evaluadas en el periodo de ejecución. Es decir, cada vez que se solicita una página el procesador de plantilla tiene que interpretar la plantilla. Por el contrario, la tecnología JSP está basada en la compilación de páginas. En lugar de interpretar la página, el contenedor web la convierte en un servlet y lo compila. Este proceso tiene lugar cuando el contenedor web invoca una página por primera vez. Algunos contenedores permiten precompilar las páginas en servlets, evitando la demora que se produce cuando se invoca por primera vez. La mayoría de los contenedores repiten el proceso de compilación cada vez que se modifica la página. En la siguiente figura podemos ver las diferentes fases de este proceso. La flecha punteada representa la compilación de la página.

28

2

Aplicaciones web

2.6. EL DESCRIPTOR DE DESPLIEGUE Los descriptores de despliegue son parte integrante de las aplicaciones web de la especificación J2EE y ayudan a gestionar la configuración de las aplicaciones una vez que se han desplegado. El descriptor de despliegue es un archivo XML llamado “web.xml” que se almacena en el directorio “WEB-INF” de la aplicación. La especificación proporciona una definición de tipo de documento (DTD) para el descriptor de despliegue. El descriptor de despliegue tiene varios propósitos:

La inicialización de los parámetros para los servlets y las aplicaciones. Esta característica nos permite modificar los valores de inicialización en nuestras aplicaciones. Un ejemplo muy común es que si nuestro servlet requiere acceso a una base de datos, el mejor lugar para especificar los detalles, como el registro y la contraseña, es el descriptor de despliegue, lo que nos va a permitir configurar nuestra aplicación sin tener que recompilar el código del servlet.

Definir los servlets y las páginas JSP. Cada servlet y página JSP precompilada que utilicemos en nuestra aplicación debe estar definida en el descriptor de despliegue. La definición incluye el nombre del elemento, su clase y una descripción.

La representación de los servlets y las páginas JSP. Los contenedores web utilizan esta información para representar solicitudes entrantes a los servlets y las páginas JSP.

Los tipos MIME. Debido a que cada aplicación web puede contener varios tipos de contenidos, podemos especificar los tipos MIME para cada tipo.

La seguridad. Podemos gestionar el control de acceso de nuestra aplicación utilizando

29

2
páginas de bienvenida, las páginas de error y la configuración de la sesión.

Aplicaciones web

el descriptor de despliegue. Por ejemplo, podemos especificar si nuestra aplicación requiere un registro, cual es la página de registro y qué rol debe tener el usuario. En el descriptor de despliegue también se indican otras características, como cuáles son las

30

2
recuerde_

ficheros de imágenes.

Aplicaciones web

Una aplicación web es un conjunto de páginas JSP, servlets, clases ayudantes, librerías de clases y recursos estáticos. Entre los recursos estáticos más comunes podemos citar los documentos HTML y XML, y los

El protocolo subyacente en el que se apoyan las aplicaciones web es HTTP (HiperText Transfer Protocol). Es un protocolo de aplicación que suele implementarse sobre conexiones TCP/IP, que es sin estado y está basado en solicitudes y respuestas.

El contenedor web alberga las aplicaciones web y es un periodo de ejecución Java que proporciona una implementación del API Java Servlet y facilidades para las páginas JSP. Es el responsable de inicializar, invocar y gestionar el ciclo de vida de los componentes web.

31

3
índice_

Enterprises Beans y servicios de contenedor

3.1. 3.2. 3.3. 3.4. 3.5. 3.6. 3.7.

¿QUÉ ES UN ENTERPRISE JAVABEAN? ....................................35 TIPOS DE EJB .........................................................................37 EL CONTENEDOR EJB ..............................................................37 EL DESCRIPTOR DE DESPLIEGUE ............................................40 UTILIZACIÓN DE BEANS.........................................................42 DESARROLLO DE BEANS .........................................................44 EJEMPLO PRÁCTICO ...............................................................46 3.7.1. El software necesario ..................................................46 3.7.1.1. Instalación de Firebird y Firebird SQL .............47 3.7.1.2. Instalación de IBAccess ..................................47 3.7.1.3. Instalación de Sun Java System Application Server ............................................................49 3.7.1.4. Instalación de NetBeans .................................52 3.7.2. El desarrollo ................................................................53 3.7.2.1. Desarrollo del componente EJB .......................53 3.7.2.2. Desarrollo del componente web ......................58 3.7.2.3. Configuración del servidor de aplicaciones ......63 3.7.2.4. Desplegando la aplicación ...............................68 3.7.3. El funcionamiento........................................................80

33

3
3.1. ¿QUÉ ES UN ENTERPRISE JAVABEANS?

Enterprises Beans y servicios de contenedor

Antes de explicar qué es un EJB, un Enterprise JavaBean o un Enterprise Bean (se les conoce por cualquiera de los tres nombres), vamos a aclarar un aspecto que ha sido fuente de confusión para muchos desarrolladores. Se trata de su nombre. A pesar de la similitud entre los términos JavaBean y Enterprise JavaBean, no tienen nada en común. Sus objetivos, implementación y usos son muy distintos. La arquitectura JavaBeans se diseñó para la especificación de componentes de propósito general, mientras que la arquitectura Enterprise JavaBeans se ha diseñado para componentes distribuidos residentes en entornos J2EE. Los componentes EJB tienen la finalidad de contener la lógica de la empresa (las reglas de negocio). Encapsulan la funcionalidad crítica y permiten que el desarrollador de aplicaciones se despreocupe de los servicios del nivel de sistemas como la concurrencia, la persistencia y las transacciones. Un Enterprise JavaBean es un conjunto de ficheros de clases Java y un fichero XML que conforman una única entidad. Las clases cumplen determinadas reglas y proporcionan métodos de retrollamada, todo ello según está definido en las especificaciones J2EE. Dado que es tecnología Java, son independientes del sistema operativo y la plataforma (siempre que no se utilice código nativo). Por ello, se pueden desarrollar en cualquier plataforma para ser usados posteriormente en cualquier otra plataforma. Actualmente sólo existe otra tecnología similar, se trata de la tecnología DCOM de Microsoft, pero tiene el inconveniente de que sólo se pueden utilizar en plataformas Windows. Como hemos mencionado con anterioridad, J2EE es una especificación. Por lo tanto, la tecnología EJB también es una especificación, y concretamente define cómo debe ser la arquitectura de componentes del lado servidor. Dicha especificación es la que deben seguir los proveedores de contenedores EJB para ser capaces de alojar componentes EJB. Pero además, dichos proveedores tienen la libertad de darle algún valor añadido a sus contenedores añadiéndole extensiones propias. Siempre que un EJB no haga uso de dichas extensiones, puede ser trasladado de un contenedor a otro en base a las necesidades. Por ejemplo, los EJB pueden desarrollarse utilizando un contenedor de bajo coste o gratis y posteriormente ponerlos en explotación en contenedores comerciales de alto rendimiento.

35

3
llamadas de clientes son los siguientes:

Enterprises Beans y servicios de contenedor

Un EJB puede utilizarse con muchos tipos de clientes. Algunos ejemplos comunes de

− − −

Desde servlets y páginas JSP para proporcionar acceso a clientes web.

Desde otros EJB.

Desde aplicaciones autónomas Java mediante la utilización del API RMI (Invocación de métodos remotos).

Mediante CORBA si el servidor en el que reside el EJB soporta RMI/IIOP.

La especificación EJB tiene la finalidad de proporcionar servicios de nivel de empresa. En otras palabras, proporcionar la funcionalidad que requiere una organización. Por lo tanto, resulta compleja desde los puntos de vista del desarrollo y la administración. La contrapartida de esta complejidad es que permite a los desarrolladores olvidarse de la complejidad del nivel de sistemas para centrarse en la lógica de negocio. En la documentación de la plataforma Java 2 Enterprise Edition, Sun Microsystems incluye un documento llamado “Designing Enterprise Applications with the Java 2 Platform Enterprise Edition” que cataloga cuatro arquitecturas para las aplicaciones web. Son las siguientes:

HTML básico: Sólo contenido estático, puesto que no existe la necesidad de contenido dinámico.

HTML con páginas JSP y servlets: Contenidos estáticos y dinámicos. Utilización de componentes java para cubrir necesidades no muy exigentes.

Páginas JSP, servlets y componentes JavaBeans: Similares a la anterior pero añadiendo las ventajas del uso de los componentes JavaBeans.

Páginas JSP, servlets, componentes JavaBeans y componentes Enterprise JavaBeans: Grandes exigencias de ejecución de lógica de negocio y utilización de componentes distribuidos.

36

3
3.2. TIPOS DE EJB controlados por mensaje.

Enterprises Beans y servicios de contenedor

La tecnología EJB se ha diseñado para proporcionar una arquitectura de componentes para la creación y uso de sistemas de empresa distribuidos. Para cubrir todas las posibilidades, la especificación EJB define tres modelos para métodos de retrollamada y ciclos de vida de período de ejecución. Los tres modelos son: beans de sesión, beans de entidad y beans

Un bean de sesión es utilizado por un único cliente a la vez y se utiliza para proporcionar lógica de empresa. Puede ser de dos tipos: con estado o sin estado: El primero puede mantener su información entre distintas llamadas a métodos. Por el contrario, un bean sin estado no puede. Es un matiz distintivo fundamental, y de hecho se utilizan para fines distintos.

Un bean de entidad representa información de una base de datos. Por ese mismo motivo, a un bean de entidad pueden acceder múltiples clientes simultáneamente. Existen dos tipos: persistencia gestionada por el contenedor y persistencia gestionada por el bean. La diferencia entre ellos radica en que sea el contenedor EJB el que interactúe con la base de datos o sea el programador quien tenga que escribir el código para interactuar con la base de datos.

Un bean controlado por mensaje es llamado de forma asíncrona y puede recibir e influir sobre mensajes JMS mediante el proveedor de servicio de mensajes Java. Los clientes enviarán mensajes a una cola y todos los beans de este tipo que estén suscritos a dicha cola recibirán el mensaje.

3.3. EL CONTENEDOR EJB Un contenedor EJB es el entorno en el que se ejecuta un componente EJB. El contenedor se encarga de proporcionarle los servicios necesarios durante su ciclo de vida. Los contenedores EJB suelen estar contenidos en servidores de aplicaciones que les suministran un entorno de ejecución, y que normalmente incluyen también otro tipo de contenedores, como pueden ser los contenedores web. El siguiente gráfico ilustra la estructura típica de un servidor de aplicaciones.

37

3

Enterprises Beans y servicios de contenedor

Los componentes EJB aprovechan los servicios que proporciona el contenedor EJB, por lo que es importante que conozcamos dichos servicios para así poder sacarles el máximo partido. A continuación, vamos a describir algunos de los más importantes:

Persistencia: Los enterprise beans proporcionan servicios de persistencia que comprenden desde reservas de conexiones hasta la gestión automática de la persistencia (evitándonos la escritura de código SQL).

Transacciones declarativas: Existen distintas API Java capaces de soportar transacciones: API JDBC, JTA (Java Transaction API) y JTS (Java Transaction Service), no obstante, ninguna de ellas es apropiada para la gestión de transacciones en las que intervienen múltiples componentes de acceso a datos o múltiples fuentes de datos, dado que dicha gestión podría volverse excesivamente compleja. Además, las transacciones complejas con EJB se pueden gestionar sin escribir ningún código, por lo que, al delegar esta tarea en el contenedor, podemos centrarnos en el desarrollo del código de la lógica de negocio.

Seguridad declarativa: El acceso a los componentes EJB también puede ser regulado sin la necesidad de escribir código.

Reajustabilidad: La especificación J2EE permite a los servidores de aplicación gestionar gran cantidad de clientes simultáneos. Los componentes están diseñados para ejecutarse en múltiples equipos virtuales Java y el servidor de la aplicación está capacitado para funcionar en un clúster (conjunto de varios equipos trabajando en colaboración).

Portabilidad: Dado que los EJB se escriben siguiendo un API estándar, pueden ser ejecutados en distintos servidores J2EE sin necesidad de modificar el código.

38

3
de conocerlas.

Enterprises Beans y servicios de contenedor

Se define como contrato a las responsabilidades definidas entre las partes de una aplicación que utiliza componentes EJB: el cliente, el contenedor y el componente. Si cada parte implicada respeta las reglas de su contrato, podrá interactuar con las demás sin necesidad

Por otro lado, el contenedor proporciona los servicios del nivel de sistemas mediante la interposición. Para ello se interpone entre la interfaz de empresa de cliente y la lógica de empresa EJB. La llamada de un cliente a un método de un EJB funciona, a grandes rasgos, de la siguiente forma:

− −

El cliente realiza la llamada mediante un stub RMI, que es la interfaz básica del bean.

El stub RMI codifica (serializa) los parámetros y envía la información a través de la red.

Un skeleton situado en el servidor decodifica los parámetros y los envía al contenedor EJB, quien los recibe mediante una clase de interposición que genera.

− −

El contenedor empezará o se unirá a las transacciones requeridas.

El contenedor desencadenará varias retrollamadas para que el componente EJB adquiera los recursos necesarios.

− −

Invocará al método de empresa correspondiente.

Envía de vuelta los datos al cliente.

Para hacernos una idea clara de la diferencia entre las interfaces básica y remota, la interfaz básica es el punto de entrada a los EJB y es la única entidad accesible desde el exterior. Una vez obtenida una instancia de la interfaz básica se le pide que cree o localice un EJB y, a continuación, se puede acceder a dicho EJB a través de la interfaz remota.

39

3

Enterprises Beans y servicios de contenedor

3.4. EL DESCRIPTOR DE DESPLIEGUE Un módulo J2EE se compone de uno o más componentes J2EE (para el mismo tipo de contenedor) y un descriptor de despliegue, siendo éste último un fichero XML que describe la configuración de despliegue del componente J2EE. La información de los descriptores de despliegue es declarativa, por lo que se puede cambiar sin modificar el código fuente. El servidor J2EE lee los descriptores de despliegue durante la ejecución y actúa acorde a sus contenidos. Según la especificación existen cuatro tipos de descriptores:

Descriptor

de

la

aplicación

J2EE.

Debe

haber

sólo

uno,

su

nombre

es

“application.xml” y se almacena en el directorio “META-INF”. Lo trataremos en el tema “Empaquetado y despliegue”.

Descriptores de módulos EJB. Existe uno por cada módulo EJB y describe la totalidad de EJB contenidos en él. Su nombre es “ejb-jar.xml” y se almacena dentro del directorio “META-INF”.

40

3

“Aplicaciones web”.

Enterprises Beans y servicios de contenedor

Descriptores de módulos web. Existe uno por cada módulo web. Su nombre es “web.xml” y se almacena dentro del directorio “WEB-INF”. Los vimos en el tema

Descriptores de adaptadores de recursos. Quedan fuera del ámbito de este manual y no vamos a tratarlos.

Los distintos servidores J2EE existentes suelen requerir descriptores de despliegue adicionales a los indicados por la especificación. Por ejemplo, en nuestro caso concreto el servidor de aplicaciones que vamos a utilizar para los ejemplos requiere que cada módulo EJB incluya un descriptor de despliegue llamado “sun-ejb-jar.xml” y se almacene en el directorio “META-INF”. El siguiente es un ejemplo de descriptor de despliegue de una aplicación J2EE. En él podemos ver que la aplicación se compone de un módulo EJB y un módulo web. Corresponde al ejemplo que veremos al final de este tema.

<?xml version="1.0" encoding="UTF-8"?> <application xmlns="http://java.sun.com/xml/ns/j2ee" version="1.4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/application_1_4.xsd"> <description xml:lang="es">Aplicación ejemplo1</description> <display-name xml:lang="es">Ejemplo1</display-name> <module> <ejb>ejb-jar-ic.jar</ejb> </module> <module> <web> <web-uri>war-ic.war</web-uri> <context-root>/ejemplo1</context-root> </web> </module> </application>

A continuación, consideramos otro ejemplo de descriptor de despliegue. En este caso se trata del módulo EJB que corresponde al ejemplo que también estudiaremos al final de este tema.

41

3
<?xml version="1.0" encoding="UTF-8"?> <ejb-jar xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd"> <enterprise-beans> <session>

Enterprises Beans y servicios de contenedor

xmlns="http://java.sun.com/xml/ns/j2ee"

version="2.1"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

<display-name xml:lang="es">moduloEJB</display-name>

<ejb-name>VentasBean</ejb-name> <home>gestion.VentasHome</home> <remote>gestion.Ventas</remote> <ejb-class>gestion.VentasBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Bean</transaction-type> </session> </enterprise-beans> </ejb-jar>

Este manual pretende ser una introducción al desarrollo de EJB. El servidor de aplicaciones que hemos elegido para los ejemplos nos va a permitir abstraernos de ciertas complejidades como, por ejemplo, los descriptores de despliegue. Por lo tanto, dado que la sintaxis y explicación de los descriptores es sumamente extensa, no vamos a detallarla aquí. La mejor información para estudiarla detalladamente podemos encontrarla en la documentación de la especificación J2EE.

3.5. UTILIZACIÓN DE BEANS Para utilizar un enterprise bean necesitamos saber cómo encontrarlo o crearlo, cómo utilizar sus métodos y como liberar sus recursos. No tenemos que preocuparnos sobre su implementación ni los servicios provistos por el contenedor. Un EJB de sesión o entidad puede tener las siguientes interfaces:

Una interfaz básica y/o una interfaz básica local. Se utilizan para operaciones de ciclo de vida (crear, encontrar y eliminar EJB). No están asociadas a una instancia de bean concreta, sólo a un tipo de bean.

42

3

asociadas a una instancia de bean concreta.

Enterprises Beans y servicios de contenedor

Una interfaz remota y/o local. Permiten el acceso a los métodos de empresa. Están

En lo que respecta a las interfaces de los EJB de sesión y de entidad, pueden tener las interfaces básica y remota, pueden tener las interfaces básica local y local, o pueden tenerlas todas. En el siguiente apartado veremos los usos y diferencias entre ellas. Los pasos para hacer uso de un componente EJB son los siguientes:

− − − −

Adquirir la interfaz básica (o básica local) a través de JNDI. Crear o encontrar una instancia de un bean que se obtendrá como interfaz remota (o local). Ejecutar los métodos de empresa necesarios. Eliminar el bean.

Veamos los pasos anteriores en un ejemplo concreto:

try { // Obtenemos una referencia al contexto de ejecución Context ctx = new InitialContext(); // Obtenemos una referencia al componente mediante JNDI Object obj = ctx.lookup("java:comp/env/ejb/Ventas"); // Obtenemos una referencia a la interfaz básica VentasHome home = (VentasHome) javax.rmi.PortableRemoteObject.narrow(obj, VentasHome.class); // Obtenemos una instancia al bean mediante la interfaz remota Ventas ventas = home.create(); // Invocamos los métodos de negocio ventas.calcularDescuentos(); ventas.actualizarDescuentos(); // Eliminamos el EJB ventas.remove(); } catch (Exception e) { errText = e.getMessage(); }

43

3
3.6. DESARROLLO DE BEANS

Enterprises Beans y servicios de contenedor

Un enterprise bean se compone, generalmente, de un conjunto de ficheros de clases Java y un descriptor de despliegue. El conjunto de clases java está formado obligatoriamente por la clase que implementa la lógica de negocio y una o las dos parejas de interfaces que permiten que los clientes puedan hacer uso del EJB. Adicionalmente, pueden incluirse clases Java adicionales de apoyo al bean y, en el caso de los beans de entidad con clave primaria compuesta, una clase que represente a dicha clave. Una de dichas parejas está formada por las interfaces básica y remota y permiten que los clientes remotos (aquellos que no están en la misma unidad de despliegue del bean) puedan hacer uso del enterprise bean. La otra pareja está formada por las interfaces básica local y local. Permiten que clientes que están en la misma unidad de despliegue puedan hacer uso del EJB, sin necesidad de utilizar las interfaces remotas. El problema del acceso remoto a un EJB reside en que es más costoso (a nivel de recursos) y lento debido a que hace uso de RMI (y todo lo que conlleva). La interfaz local no hace uso de RMI, no obstante, tiene el inconveniente de que sólo pueden usarla los clientes que formen parte de la misma unidad de despliegue en que esté el EJB. En definitiva, un enterprise bean puede incluir las interfaces para acceso local, remoto o ambas. Para las siguientes explicaciones vamos a suponer un bean llamado “VentasBean”. En base a dicho nombre indicaremos la nomenclatura que se suele emplear para nombrar las clases e interfaces relacionadas con dicho bean. La interfaz remota debe ampliar la clase “javax.ejb.EJBObject” y suele denominarse con el nombre del bean. En nuestro caso la interfaz se llamaría “Ventas”. La interfaz local debe ampliar la clase “javax.ejb.EJBLocalObject” y suele denominarse anteponiendo el texto “Local” al nombre del bean. En nuestro caso, la interfaz la denominaríamos “LocalVentas”. Tanto la interfaz remota como la local deben declarar los métodos de negocio que implementa el bean y pueden utilizar los clientes.

44

3
“VentasHome”.

Enterprises Beans y servicios de contenedor

La interfaz básica debe ampliar la clase “javax.ejb.EJBHome” y suele denominarse posponiendo el texto “Home” al nombre del bean. En nuestro caso la llamaríamos

La interfaz básica local debe ampliar la clase “javax.ejb.EJBLocalHome” y suele nombrarse anteponiendo y posponiendo los textos “Local” y “Home” respectivamente, al nombre del bean. En nuestro caso, la interfaz recibiría el nombre de “LocalVentasHome”. Tanto la interfaz básica como la interfaz básica local declararán uno o más métodos que dependerán del tipo de bean:

− −

Un bean de sesión con estado añadirá uno o más métodos “create()”.

Un bean de entidad añadirá ninguno, uno o varios métodos “create()” y uno o más métodos “finder()”.

Un bean de sesión sin estado tendrá uno y sólo un método “create()”.

Por último, la clase de implementación del bean:

− − −

Los beans de sesión derivarán de la clase “javax.ejb.SessionBean”.

Los beans de entidad derivarán de la clase “javax.ejb.EntityBean”.

Los

beans

controlados

por

mensaje

derivarán

de

la

clase

“javax.bean.ejb.MessageDriven”. La clase del bean debe implementar los métodos de retrollamada definidos en su respectiva interfaz, aunque a veces se dejen vacíos. También debe añadir los métodos de empresa declarados en las interfaces remota y básica. En los temas correspondientes a los distintos tipos de EJB entraremos en más detalles.

45

3
3.7. EJEMPLO PRÁCTICO que hemos tratado. 3.7.1. El software necesario

Enterprises Beans y servicios de contenedor

Ahora dejemos la teoría y vamos con un ejemplo que nos ayude a asimilar los conocimientos

Para los ejemplos que vamos a estudiar desde este tema en adelante, usaremos los siguientes productos:

Firebird versión 1.5. Es una base de datos gratuita (licencia GPL). Tiene su origen en la liberación del código de la base de datos Interbase de Borland, de ahí que ofrezca un rendimiento excelente. Podemos descargarla de http://www.firebirdsql.org

Firebird SQL versión 1.5.0. Contiene los controladores JDBC que vamos a usar con la base de datos Firebird. También podemos descargarlo desde la dirección anterior.

IBAccess 1.18. Herramienta de administración de bases de datos Firebird. Podemos descargarla de http://www.ibaccess.org y es gratuita.

Sun Java System Application Server Platform Edition 8.1. Es un servidor de aplicaciones J2EE de Sun Microsystems. Es gratuito. Podemos descargarlo de http://java.sun.com

NetBeans 4.1. Entorno de desarrollo integrado (IDE) para Java. Es gratuito y podemos descargarlo de http://www.netbeans.org.

La elección del software anterior se ha realizado, en primer lugar, buscando el menor coste posible. Es por eso que todos los productos mencionados son gratuitos y que la mayoría permite su uso bajo licencia GPL. El segundo factor a evaluar ha sido la calidad y simplicidad. Si estamos interesados en utilizar otro tipo de software, habremos de tener en cuenta sus diferencias con respecto a los que aquí mencionamos para hacer los cambios pertinentes de cara a que los ejemplos funcionen. Para los ejemplos crearemos un directorio llamado “cursoEJB”. Para los usuarios de Linux se asumirá el trayecto “/home/alumno/cursoEJB”, mientras que para los usuarios de Windows se asumirá el trayecto “c:\cursoEJB”. Dentro de dicho directorio vamos a crear la base de datos Firebird que utilizaremos en los ejemplos que lo necesiten.

46

3
3.7.1.1. Instalación de Firebird y Firebird SQL los detalles.

Enterprises Beans y servicios de contenedor

La instalación del servidor de bases de datos Firebird tendremos que realizarla como administrador del sistema. El proceso de instalación es muy sencillo y no vamos a entrar en

Una vez finalizada la instalación, el servidor estará en funcionamiento y a la espera de peticiones. En algunas plataformas Windows tal vez requiera reiniciar el ordenador y levantar manualmente los servicios mediante el administrador de servicios. En cualquier caso, es conveniente revisar la documentación de Firebird por si hubiera alguna consideración especial para algunas situaciones concretas. En lo que respecta a Firebird SQL, se trata de un fichero comprimido que contiene los controladores JDBC para conectar con bases de datos Firebird. De él nos interesa el fichero “firebirdsql-full.jar”. En este manual asumiremos que hemos instalado Firebird en “/opt/firebird” o en “c:\firebird”, según estemos en una plataforma Linux o Windows, respectivamente. Crearemos un directorio llamado “jdbc” dentro del directorio de instalación de Firebird (para tener organizados los ficheros) y copiaremos dentro el fichero “firebirdsql-full.jar”. 3.7.1.2. Instalación de IBAccess

Esta utilidad de administración de servidores de bases de datos Firebird tampoco reviste ninguna complejidad en su instalación y tampoco entraremos en detalles. No obstante, dado que puede resultar un proceso confuso para usuarios que no conozcan Firebird, vamos a explicar cómo configurar una conexión a una base de datos. Cuando se ejecuta IBAccess, se nos muestra la siguiente ventana:

47

3
“Configure databases”.

Enterprises Beans y servicios de contenedor

En el menú “File” seleccionaremos la opción “New database...” para crear una base de datos nueva. A continuación, se nos muestra una nueva ventana con el título “Create a new Interbase database” en la que debemos elegir la base de datos a crear. No obstante, lo primero que hemos de hacer es crear una conexión y para ello, pulsaremos el botón

Nos volverá a aparecer una nueva ventana con el título “Global Database Definition” y pulsaremos el botón “New”. Nos preguntará por el alias que queremos asignarle a la base de datos. En nuestro ejemplo usaremos el texto “cursoEJB” y pulsaremos el botón “OK”. A continuación, podremos ver que en la ventana se nos solicitan varios datos, de entre ellos debemos considerar los siguientes:

“User name”. Nombre del usuario. No vamos a crear usuarios, si no que nos limitaremos a utilizar el nombre del administrador de la base de datos. Tendremos que indicar el texto “sysdba”.

− −

“Password”. Contraseña. La contraseña del administrador es “masterkey”.

“Local connection”. La dejaremos seleccionada porque la conexión con el servidor de datos será local.

“Filename”. Nombre (y trayecto) del fichero que da soporte a la base de datos. Cada base de datos Firebird se almacena en uno o más ficheros físicos. En nuestro caso vamos a crear una base de datos de nombre “cursoEJB.gdb”. Los usuarios de Linux escribirán “/home/alumno/cursoEJB/cursoEJB.gdb”, mientras que los usuarios de Windows indicarán “c:\cursoEJB\cursoEJB.gdb”.

“Dialect”: Dialecto que se va a utilizar en la base de datos. Seleccionaremos de la lista el valor “Dialect 3 (IB 6.X)” para que la base de datos permita que los identificadores puedan ir encerrados entre comillas dobles (los nombres de tablas y de columnas).

El resto de datos son indiferentes para nuestros intereses.

48

3
de Windows verán un valor distinto en “Filename”):

Enterprises Beans y servicios de contenedor

Tras lo que hemos visto, la ventana tendrá el siguiente aspecto (recordemos que los usuarios

Seguidamente pulsaremos los botones “Save” y “OK”, en ese orden. Se cerrará la ventana y nos pedirá confirmación para guardar los cambios. Responderemos afirmativamente. Ya de vuelta a la ventana “Create a new Interbase database” seleccionaremos del control combo “Databases” el elemento “CURSOEJB” (se trata del alias que acabamos de crear) y pulsaremos el botón “Create”. Es justo en ese momento cuando se procede a la creación de la base de datos (creación del fichero físico) y se cierra la ventana. En adelante, cada vez que entremos en la utilidad IBAccess seleccionaremos la opción “Open database...” del menú “File” y en el combo “Databases” elegiremos el alias “CURSOEJB”. Una vez hecho esto, aparecerá una ventana que será donde manipularemos la base de datos (crear tablas, introducir datos, etc.) de cara a los ejemplos que se van a tratar más adelante. 3.7.1.3. Instalación de Sun Java System Application Server

La instalación la haremos siguiendo los pasos que nos va sugiriendo el asistente. Tendremos que prestar especial atención cuando se nos pregunte por el directorio del kit de desarrollo de Java 2 Edición Estándar (JDK). Si seleccionamos una versión inferior a la recomendada nos mostrará una ventana

49

3
instalación es la siguiente:

Enterprises Beans y servicios de contenedor

indicándonoslo y pidiéndonos confirmación. La versión del servidor de aplicaciones que estamos instalando aquí requiere al menos el JDK versión 1.4.2. No obstante, la ventana más importante de todas las que nos va a mostrar el proceso de

En ella definiremos los siguientes datos:

− − −

Nombre de la cuenta de administración del servidor.

Contraseña de la cuenta de administración.

Definiremos si queremos que nos pregunte el nombre y contraseña cuando nos conectemos o que los guarde para que no tengamos que indicarlo al entrar. En nuestro caso da igual lo que elijamos porque sólo vamos a hacer pruebas, pero en un servidor real sería conveniente que estos datos se preguntaran al entrar.

Los puertos de administración y de los protocolos HTTP y HTTPS. Podemos dejarlos con los valores sugeridos si no están en uso en nuestro sistema.

Una vez finalizada la instalación estaremos en disposición de iniciar el servidor y poder administrarlo. Para iniciar el servidor de aplicaciones nos iremos al directorio “bin” dentro del directorio de instalación y ejecutaremos el programa “asadmin”.

50

3
Suponiendo que estamos en Linux y “/home/alumno/SUNWappserver”, escribiremos:

Enterprises Beans y servicios de contenedor
lo hemos instalado en

alumno@mhost:~/SUNWappserver/bin$ ./asadmin start-domain domain1

Si

estuviéramos

en

Windows

y

lo

hubiéramos

instalado

en

“c:\SUNWappserver”,

escribiríamos lo siguiente:

c:\SUNWappserver> asadmin start-domain domain1

A continuación nos mostrará un mensaje que nos indicará que el servicio está iniciado. Para administrar el servidor disponemos de dos mecanismos: la línea de comando y una interfaz de gráfica de usuario basada en web. Nosotros nos vamos a decantar por la interfaz gráfica (por motivos obvios). Para entrar en la consola de administración tendremos que abrir un navegador web y navegar a la dirección “http://localhost:4848”. Si durante la instalación le cambiamos el puerto de administración que nos sugería por defecto, tendremos que indicar aquí dicho puerto. Lo siguiente que veremos será una página de registro en la que se nos solicita el nombre y clave de la cuenta de administración. Indicaremos los mismos que pusimos durante la instalación y pasaremos a la página principal de administración que tiene el siguiente aspecto:

51

3
indicándole el parámetro “stop-domain”. Sería como sigue: 3.7.1.4. Instalación de NetBeans

Enterprises Beans y servicios de contenedor

Para detener el servidor de aplicaciones usaremos también el comando “asadmin” pero

asadmin stop-domain domain1

NetBeans es un entorno de desarrollo integrado para aplicaciones Java. Es ampliamente utilizado, de una gran calidad y de coste cero. Su instalación la haremos siguiendo los pasos que nos va sugiriendo el asistente. Tendremos que prestar especial atención cuando se nos pregunte por el directorio del kit de desarrollo de Java 2 Edición Estándar (JDK). La versión del NetBeans que estamos instalando aquí requiere al menos el JDK versión 1.4.2. Podríamos prescindir de cualquier entorno de desarrollo, utilizar nuestro editor de textos favorito y compilar desde la línea de comandos pero el desarrollo dentro de un IDE tiene numerosas ventajas que van a permitirnos una mayor productividad. Empezaremos abriendo el entorno NetBeans. Dentro de él podemos ver que la zona de trabajo se divide en dos paneles. El panel de la derecha es la zona de edición de código y presenta una página de bienvenida.El de la izquierda muestra distintas ventanas. Entre las ventanas más comunes están el proyecto actual (“Projects”), la ventana de ficheros del proyecto (“Files”) y la ventana del punto de entrada de los recursos del proyecto (“Runtime”).

52

3
cerrar (“x”) de la pestaña “Welcome”. 3.7.2. El desarrollo

Enterprises Beans y servicios de contenedor

Para cerrar la página de bienvenida utilizaremos el botón izquierdo del ratón sobre el icono

Seguidamente, analizaremos un ejemplo básico de una aplicación J2EE. Se trata de una aplicación para saber el importe de una venta a partir de la cantidad y el precio unitario donde las reglas de la empresa determinan que el precio de una venta se calcula multiplicando la cantidad por el importe y añadiendo un 5% de comisión. Queremos construir una aplicación que reciba peticiones de clientes web, invoque a un componente de empresa para obtener los resultados y muestre dicho resultado al cliente que lo solicitó. Nuestra aplicación se va a componer de los siguientes módulos:

Un módulo EJB que se ejecutará en el contenedor de EJB del servidor de aplicaciones. Dicho módulo estará compuesto por un único EJB que será el que contenga la lógica de negocio que describimos anteriormente.

Un módulo web que estará compuesto por una única página que solicitará los datos y mostrará los resultados.

3.7.2.1.

Desarrollo del componente EJB

Ejecutaremos NetBeans y elegiremos la opción “Files” y subopción “New Project”. Crearemos entonces un nuevo proyecto “Java Application”.

53

3

Enterprises Beans y servicios de contenedor

A continuación, pulsaremos “Next” y llamaremos “ejemplo1” al proyecto. Seleccionaremos la dirección de nuestro directorio y no crearemos la clase principal.

Tras terminar pulsaremos el botón “Finish”. Seguidamente, se creará la estructura de carpetas del proyecto. Dentro de la subcarpeta “Source Packages” vamos a crear un nuevo paquete.

54

3
Este paquete lo vamos a llamar “gestion”.

Enterprises Beans y servicios de contenedor

Para poder desarrollar aplicaciones J2EE (concretamente para poder compilar) desde dentro de NetBeans, necesitaremos indicarle el fichero de clases “j2ee.jar”. Puesto que vamos a utilizar el servidor de aplicaciones de Sun Microsystems, lo razonable es indicar el que viene incluido en el servidor dentro del directorio “lib”. fichero de clases “j2ee.jar”. Lo próximo que haremos será crear las tres clases que necesitará nuestro EJB. Para ello, sobre el nodo “gestion” pulsamos el botón derecho del ratón y seleccionamos la opción “New” y subopción “Java Class”. Esta operación la realizaremos tres veces y los nombres de clases que emplearemos serán los siguientes: “VentasHome”, “Ventas” y “VentasBean”. Para ello, pulsaremos el botón derecho sobre el nodo “Libraries”, pincharemos sobre la opción “Add JAR/Fólder” y seleccionaremos el

55

3

Enterprises Beans y servicios de contenedor

En estos momentos, el aspecto del entorno podría ser similar al siguiente:

Habremos podido comprobar que NetBeans crea cada clase incluyendo en ella el nombre del paquete al que pertenece y añadiéndole un constructor vacío. En breve modificaremos el contenido de cada clase para que se ajuste a lo que queremos de ella. Concretamente, dos de esas clases deberían ser interfaces, por lo que las cambiaremos. Pero veamos primero cual es la finalidad de cada una de ellas:

− − −

“VentasHome”: Es la interfaz básica del EJB. A veces también recibe el nombre de interfaz inicial. “Ventas”: Es la interfaz remota del EJB. “VentasBean”: Es la clase de implementación. Contiene el código de los métodos de negocio.

56

3
package gestion; import javax.ejb.*; public interface VentasHome extends javax.ejb.EJBHome { public gestion.Ventas create()

Enterprises Beans y servicios de contenedor

Seguidamente, editaremos la clase “VentasHome” y escribiremos el siguiente código:

throws javax.ejb.CreateException, java.rmi.RemoteException; } Para la clase “Ventas”, su código será: package gestion; import javax.ejb.*; public interface Ventas extends javax.ejb.EJBObject { // Calcula el importe de la venta añadiendo el % de comisión public } float calculaImporte(int cantidad, float precio) throws java.rmi.RemoteException;

Y por último a la clase “VentasBean”, que es la que contiene el código que soporta las reglas de negocio, le escribimos el siguiente código:

package gestion; import javax.ejb.*; public class VentasBean implements javax.ejb.SessionBean { private javax.ejb.SessionContext context; private static final int comision = 5; public void setSessionContext(javax.ejb.SessionContext aContext) { context=aContext; } public void ejbActivate() { } public void ejbPassivate() { } public void ejbRemove() { } public void ejbCreate() {

57

3
} float importe = cantidad * precio; } }

Enterprises Beans y servicios de contenedor

// Calcula el importe de la venta añadiendo el % de comisión public float calculaImporte(int cantidad, float precio) { return importe + importe * this.comision / 100;

Si hemos escrito correctamente todo el código anterior, no debería haber problemas con la compilación, no obstante, lo comprobaremos compilando las clases. Un método rápido que podemos utilizar para compilar la clase y las interfases es usar el botón derecho sobre el nombre del paquete (“gestion”) y elegir del menú emergente la opción “Compile Package”. En caso de que se muestren errores, revisaremos las líneas en cuestión y los solventaremos. En este momento tenemos compilados los ficheros Java que componen el EJB. Según la especificación EJB nos faltaría el descriptor de despliegue, el fichero “ejb-jar.xml”. También nos faltaría el fichero de despliegue específico de la plataforma en la que vamos a desplegar el EJB. En nuestro caso no hemos de preocuparnos, ya que, el servidor de aplicaciones que hemos elegido incorpora una herramienta para el despliegue que será la que se va a encargar de crear ambos ficheros XML. El siguiente paso es crear el módulo EJB que debe contener a nuestro Enterprise Bean pero también nos despreocuparemos de esta labor debido a que también la realiza la herramienta de despliegue que acabamos de mencionar. 3.7.2.2. Desarrollo del componente web

Hemos decidido que se va a componer de una única página JSP. Dicha página mostrará el nombre de nuestra empresa y decidirá si los parámetros cantidad y precio que recibe son correctos. Si es así mostrará el importe de la venta. En cualquier caso, mostrará un formulario para poder realizar un nuevo cálculo. Para añadir una página JSP en NetBeans necesitaremos en primer lugar añadir un módulo web. Para evitar complejidad a este ejemplo, vamos a crear manualmente la página JSP en el directorio del ejemplo (recordemos que se trata del directorio

58

3
nuestro editor de textos favorito. El contenido de la página JSP será el siguiente: <%@page contentType="text/html"%> <%@page import="javax.naming.*"%> <%@page import="javax.sql.*"%> <%@page import="java.sql.*"%> <%@page import="gestion.*"%>

Enterprises Beans y servicios de contenedor

“/home/alumno/cursoEJB/ejemplo1” para los usuarios de Linux y de “c:\cursoEJB\ejemplo1” para los usuarios de Windows). El fichero se llamará “index.jsp” y lo podemos crear en

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta content="text/html; charset=ISO-8859-1" http-equiv="content-type"> <title>cursoEJB/ejemplo1</title> </head> <body> <% String errText = ""; String nombreEmpresa = ""; int cantidad = 0; float precio = 0; float importe = 0; try { // Obtenemos una referencia al contexto de ejecución Context ctx = new InitialContext(); // Obtenemos una referencia al pool de conexiones DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/CursoEJB"); // Obtenemos una conexión del pool Connection con = ds.getConnection(); // Leemos el nombre de la empresa Statement stmt = con.createStatement();

59

3
if (rs.next()) { nombreEmpresa = rs.getString("nombre"); }

Enterprises Beans y servicios de contenedor

ResultSet rs = stmt.executeQuery("SELECT nombre FROM empresa");

// Cerramos el conjunto de resultados y la conexión // La conexión será devuelta al pool para ser reutilizada rs.close(); con.close(); // Obtenemos los parámetros de la petición HTTP cantidad = Integer.parseInt(request.getParameter("cantidad")); precio = Float.parseFloat(request.getParameter("precio"));

// Obtenemos una referencia al componente EJB Object obj = ctx.lookup("java:comp/env/ejb/Ventas"); // Obtenemos la referencia a la interfaz básica VentasHome home = (VentasHome) javax.rmi.PortableRemoteObject.narrow(obj, VentasHome.class); // Obtenemos la referencia a la interfaz remota Ventas ventas = home.create(); // Mediante la interfaz remota invocamos al método de negocio que realiza el cálculo importe = ventas.calculaImporte(cantidad, precio); // Eliminamos el EJB ventas.remove(); } catch (NamingException e) { errText = e.getMessage(); } %> <% // Si se ha producido algún error, lo mostramos if (!errText.equals("")) { %> <%=errText%> <%

60

3
} else { %> <h2><%=nombreEmpresa%></h2> <hr> <table border="0" cellspacing="2" cellpadding="2"> <tbody> <tr>

Enterprises Beans y servicios de contenedor

<td><span style="font-weight: bold;">Cantidad:</span><br> </td> <td><span underline;"><%=cantidad%></span><br> </td> <td><span style="font-weight: bold;">Precio:</span><br> </td> <td><span underline;"><%=precio%></span><br> </td> <td><span style="font-weight: bold;">Importe:</span><br> </td> <td><span underline;"><%=importe%></span><br> </td> </tr> </tbody> </table> <hr> <br> <form name="calculos" method="post" action="index.jsp"> <table border="0" cellspacing="2" cellpadding="2"> <tbody> <tr> <td>Cantidad:</td> <td><input type="text" name="cantidad" value="0"></td> <td rowspan="2"><input type="submit" value="Calcular"></td> </tr> <tr> <td>Precio:</td> <td><input type="text" name="precio" value="0"><br> </td> </tr> </tbody> </table> </form> style="text-decoration: style="text-decoration: style="text-decoration:

61

3
<% } %> </body> </html>

Enterprises Beans y servicios de contenedor

En la página JSP hacemos uso de JNDI en dos ocasiones: la primera es para obtener una conexión del pool de conexiones del servidor y la segunda es para obtener la referencia al componente de negocio (el EJB) y poder hacer uso de él. Los nombres JNDI de ambos recursos son “java:comp/env/jdbc/cursoEJB” y “java:comp/env/ejb/Ventas”, respectivamente. La creación del primer recurso la tendremos que hacer manualmente desde la consola de administración del servidor de aplicaciones. La creación del segundo formará parte del despliegue de nuestra aplicación web, pero para que sea así tendremos que indicarlo dentro del fichero de despliegue, más concretamente, en el fichero descriptor de despliegue del componente EJB. Si observamos el código de la página JSP, veremos que mediante JDBC utilizamos una sentencia SQL para obtener información de una tabla. Esto implica que tendremos que crear dicha tabla para hacer funcionar nuestro ejemplo. La tabla en cuestión se llama “empresa” y contendrá una única columna denominada “nombre”, de tipo VARCHAR y longitud 30. Tras crear la tabla le añadiremos una fila con el nombre de nuestra empresa ficticia. Para crear y rellenar la tabla utilizaremos el programa IBAccess y una vez dentro emplearemos la opción de abrir una base de datos existente y seleccionaremos el alias “CURSOEJB”, que creamos en el apartado en el que tratábamos de la instalación de IBAccess. Una vez abierta la ventana de la base de datos, seleccionaremos el botón “Shows the exec SQL window”, que aparece resaltado en la siguiente figura.

62

3

Enterprises Beans y servicios de contenedor

A continuación, observaremos una ventana que nos va a permitir ejecutar sentencias SQL interactivamente. Ejecutaremos las líneas siguientes teniendo en cuenta que se han de ejecutar de una en una:

CREATE TABLE empresa (nombre VARCHAR(20)); INSERT INTO empresa VALUES ('Construcciones K');

Cuando cerremos esta ventana nos pedirá confirmación para guardar la transacción en curso (la que hemos generado con la sentencia INSERT), responderemos afirmativamente y podremos salir de IBAccess. No lo vamos a utilizar más por el momento. Para cerrar este apartado, mencionaremos que nos faltaría el descriptor de despliegue del módulo web (el fichero “web.xml”) y empaquetarlo todo en el correspondiente fichero WAR. Pero al igual que vimos en el apartado del componente EJB, también serán tareas que delegaremos en la herramienta de despliegue del servidor de aplicaciones. 3.7.2.3. Configuración del servidor de aplicaciones

El último uso que hicimos del servidor de aplicaciones fue entrar en la consola de administración para hacernos una idea de su estructura. Sabemos que nuestro servidor funciona, pero hasta el momento poco uso podemos darle puesto que no hemos hecho nada con él. En este apartado realizaremos dos labores de administración. Por una parte, el servidor de aplicaciones debe saber donde están las clases que le van a permitir conectarse a la base de datos, es decir, el controlador JDBC. La segunda tarea depende de la primera y consiste en

63

3
dichas conexiones.

Enterprises Beans y servicios de contenedor

definirle un recurso de tipo fuente de datos (Data Source) y asignarle un nombre JNDI. El servidor de aplicaciones puede implementar un pool de conexiones (uno o más), de donde puede suministrar conexiones a los clientes que las solicitan y con la ventaja de que reutiliza

Lo primero que vamos a hacer es indicarle al servidor donde se encuentran las clases del controlador JDBC para que pueda cargarlas cuando las necesite. Recordemos que las clases estaban almacenadas en el fichero JAR siguiente: “firebirdsql-full.jar” que estaba almacenado en “/opt/firebird/jdbc” o en “c:\firebird\jdbc”, según la plataforma fuera Linux o Windows, respectivamente. En primer lugar, nos iremos a la consola de administración utilizando un navegador web y navegar a la dirección “http://localhost:4848”. Si el servidor estuviera detenido, lo iniciaríamos mediante el comando “asadmin start-domain domain1” alojado en el directorio “bin”. Una vez identificados, seleccionaremos el nodo “Application Server” y se nos mostrará una ventana con información general del servidor. Seguidamente, seleccionaremos la pestaña “Configuración JVM” y la opción “Configuración de ruta”. Podemos verlo en la figura siguiente.

64

3

Enterprises Beans y servicios de contenedor

Dentro de esta ventana se configuran los directorios y ficheros de clases que utiliza el servidor agrupados en distintas categorías. En nuestro caso tenemos que añadir el fichero JAR del controlador JDBC, y un buen lugar para él es el apartado “Sufijo de ruta de clase”. Veamos en la siguiente figura cómo debe quedar después de que lo hayamos añadido.

Las dos primeras líneas no las hemos puesto nosotros, si no que van incluidas cuando se instala el servidor y sirven para una base de datos que lleva para usar con los ejemplos. La figura anterior corresponde a un ordenador con Linux. Los usuarios de Windows tendrán que ponerlo acorde a su plataforma. Sirva como ejemplo que la línea “/opt/firebird/jdbc/firebirdsql-full.jar” mostrada en la figura, tendrían que indicarla como “c:\firebird\jdbc\firebirdsql-full.jar”. Tras este cambio utilizaremos el botón “Guardar” que aparece en la parte superior derecha de esta misma página, reiniciaremos el servidor para que tenga en cuenta los cambios realizados y volveremos a entrar en la consola de administración. Seguidamente, expandimos el nodo “JDBC”, seleccionamos el nodo “Conjunto de conexiones” y pulsamos el botón “Nuevo” de la página de la derecha. En la siguiente figura podemos ver la relación de elementos mencionados.

65

3

“CursoEJBPool”.

Enterprises Beans y servicios de contenedor

A continuación, nos irá solicitando una serie de datos de los cuales detallamos sólo los más importantes junto con los valores que hemos de utilizar. Los campos que no estén en la siguiente lista no es necesario (ni conveniente) que los cambiemos:

“Nombre”. Nombre que queremos dar al pool de conexiones. Lo llamaremos

“Tipo de recurso”. En nuestro caso es una fuente de datos y seleccionaremos el valor “javax.sql.DataSource”.

“Nombre de clase de la fuente de datos”. Es el nombre de una de las clases definidas en el controlador JDBC que proveen la fuente de datos. Indicaremos el valor “org.firebirdsql.pool.FBSimpleDataSource”.

Propiedad “Password”. Contraseña para la conexión con la base de datos. Utilizaremos la contraseña de la cuenta del administrador, es decir, el valor “masterkey”.

Propiedad

“DatabaseName”.

Nombre

de

la

base

de

datos.

Indicaremos

“/home/alumno/cursoEJB/cursoEJB.gdb” o “c:\cursoEJB\cursoEJB.gdb” según estemos en Linux o en Windows.

Propiedad “User”. Cuenta para la conexión con la base de datos. Utilizaremos la del administrador, que es “sysdba”.

Propiedad “url”. Tendremos que añadirla utilizando el botón “Agregar propiedad”. Hace referencia a la url necesaria para conectar con la base de datos. Utilizaremos los valores “jdbc:firebirdsql:localhost/3050:/home/alumno/cursoEJB/cursoEJB.gdb” dependiendo de o que “jdbc:firebirdsql:localhost/3050:c:\cursoEJB\cursoEJB.gdb” estemos en Linux o Windows.

Según vayamos cumplimentando los datos, iremos avanzando con el botón “Siguiente”. Así hasta terminar utilizando el botón “Finalizar”, tras el cual quedará registrado el pool de conexiones que acabamos de definir. Para verificar que funciona correctamente es importante que hagamos uso del botón “Sondeo” y que no devuelva un mensaje de error. Una vez que tenemos el pool de conexiones definido, vamos a crear un recurso JDBC con un nombre JNDI para que podamos utilizarlo desde la aplicación. En nuestro ejemplo concreto lo utilizamos en la página “index.jsp” para obtener el nombre de la empresa desde la base de

66

3
botón “Nuevo”, como podemos ver en la siguiente figura.

Enterprises Beans y servicios de contenedor

datos. Seleccionamos el nodo “Recursos JDBC” que cuelga del nodo “JDBC” y pulsamos el

Los datos que nos solicita son simples. Conozcamos para qué sirve cada uno y qué valor hemos de ponerles:

“Nombre JNDI”. Nombre que queremos asignar al recurso y que será utilizado en las búsquedas JNDI. No podemos olvidar que los recursos JNDI se encuadran dentro de un subcontexto y que en nuestro caso se trata del subcontexto “jdbc”. Por lo tanto, en nuestro ejemplo vamos a llamarlo “jdbc/CursoEJB”.

“Nombre de conjunto”. Nombre del pool de conexiones del que va a obtener las conexiones. Seleccionaremos el valor correspondiente al pool que creamos anteriormente, es decir, el elemento “CursoEJBPool”.

− −

“Descripción”. Es una descripción del recurso. No vamos a escribir nada.

“Estado”. Indica si está disponible o no. Lo dejaremos seleccionado para poder hacer uso de él.

Para finalizar terminaremos pulsando el botón “Aceptar” y habremos acabado. En este

67

3
ejemplo. 3.7.2.4. Desplegando la aplicación

Enterprises Beans y servicios de contenedor

momento, nuestro servidor de aplicaciones J2EE ya es capaz de conectar con la base de datos y devolver conexiones a los clientes que las soliciten. Pero hay un problema, ya que, seguimos sin poder usarlo porque no es capaz de servir aplicaciones. No hemos desplegado ninguna aplicación dentro de él, por lo tanto prosigamos con el último paso de nuestro

Antes de ponernos manos a la obra con el proceso de despliegue de nuestra aplicación, vamos a resumir la situación actual resaltando algunos detalles que nos hará falta recordar para que el despliegue tenga éxito.

Hemos escrito las clases que componen el componente EJB y las hemos compilado. Dichas clases son “VentasHome” (interfaz básica), “Ventas” (interfaz remota) y “VentasBean” (clase de implementación de la lógica de negocio). No hemos creado el descriptor de despliegue del componente y, en consecuencia, no hemos podido crear el módulo EJB que contendrá el EJB.

Hemos escrito una página JSP para que forme parte del módulo web pero no el descriptor de despliegue del módulo web y, por lo tanto, tampoco hemos podido crear dicho módulo. En el módulo web hay elementos (la página JSP) que hacen referencia a un recurso JNDI llamado “java:comp/env/jdbc/cursoEJB” y a otro recurso JNDI llamado “java:comp/env/ejb/Ventas”. El primero no nos preocupa porque lo hemos definido a nivel del servidor, pero el segundo forma parte de la aplicación que vamos a desplegar. Por lo tanto no podemos olvidar que el módulo web hace referencia al módulo EJB. De no tenerlo en cuenta, no va a encontrar el recurso JNDI (el componente EJB) y obtendremos un error.

En lo que a descriptores de despliegue se refiere, vamos a resumir cuáles son las necesidades para nuestro ejemplo. La especificación J2EE nos requiere los siguientes descriptores:

Un descriptor de despliegue llamado “ejb-jar.xml” por cada módulo EJB. Debe ir incluido en el fichero JAR correspondiente al módulo, dentro del directorio “META-INF”.

Un descriptor de despliegue llamado “web.xml” por cada módulo web. Debe ir incluido en el fichero WAR correspondiente al módulo, dentro del directorio “WEB-INF”

68

3

INF”. descriptores:

Enterprises Beans y servicios de contenedor

Un descriptor de despliegue llamado “application.xml” único para la aplicación. Debe ir incluido en el fichero EAR correspondiente a la aplicación, dentro del directorio “META-

Por su parte, el servidor de aplicaciones que hemos elegido requiere de los siguientes

Un descriptor de despliegue llamado “sun-ejb-jar.xml” por cada módulo EJB. Debe ir incluido en el fichero JAR correspondiente al módulo, dentro del directorio “META-INF”.

Un descriptor de despliegue llamado “sun-web.xml” por cada módulo web. Debe ir incluido en el fichero WAR correspondiente al módulo, dentro del directorio “WEB-INF”.

Un descriptor de despliegue llamado “sun-application.xml” único para la aplicación. Debe ir incluido en el fichero EAR correspondiente a la aplicación, dentro del directorio “META-INF”.

Ya hemos visto qué tenemos y qué nos falta. Afortunadamente lo que nos falta nos lo va a suministrar la herramienta de despliegue. Ha llegado el momento de conocer la herramienta de despliegue. Está en el directorio “bin” del servidor de aplicaciones y se llama “deploytool”. Para utilizar esta herramienta es importante que el servidor de aplicaciones esté en ejecución. Vamos, por tanto, a ejecutarla y veamos qué aspecto tiene:

69

3
la barra de botones):

Enterprises Beans y servicios de contenedor

El área de trabajo está dividida en dos zonas principales (sin tener en cuenta el menú y

A la izquierda tenemos un panel que nos muestra una estructura de tipo árbol. En ella podremos desplazarnos por las aplicaciones que vayamos creando o abriendo con esta herramienta y por la lista de servidores que hayamos definido (por defecto viene incluido el servidor local).

En la parte derecha tenemos un panel que irá mostrando información relevante del elemento seleccionado en el árbol de la izquierda.

Lo primero que tenemos que hacer es crear una aplicación J2EE. Para ello seleccionaremos en el menú la opción “Archivo”, después la opción “Nuevo” y, por último, la opción “Application...”. Aparecerá una caja de diálogo solicitándonos el nombre del fichero y la descripción de la aplicación. Como fichero utilizaremos “/home/alumno/cursoEJB/ejemplo1/ejemplo1.ear” si estamos en Linux y “c:\cursoEJB\ejemplo1\ejemplo1.ear” si estamos en Windows. Le dejaremos la descripción que nos sugiere por defecto y pulsaremos “Aceptar” para finalizar. Ya hemos creado una aplicación, pero está vacía, ya que, no tiene ningún componente. El próximo paso será crearle un módulo EJB con las clases que hemos desarrollado para el EJB de nuestro ejemplo. A continuación, vamos a pulsar el botón izquierdo del ratón sobre el nodo “ejemplo1”, que es la aplicación recién creada, para seleccionarlo. Después, elegimos en el menú la opción “Archivo” y las subopciones “Nuevo” y “Enterprise Bean...”. Aparecerá un asistente que nos guiará a través del proceso de adición del componente EJB. Sólo vamos a detenernos en aquellas ventanas que puedan ofrecernos o solicitarnos información trascendente, el resto las ignoraremos e iremos pulsando el botón “Siguiente >”.

70

3
Prestemos atención a la siguiente ventana.

Enterprises Beans y servicios de contenedor

1

2

3

En la ventana anterior destacamos los siguientes elementos: 1. Tenemos que decidir dónde incluir el EJB y se nos ofrecen tres opciones. En nuestro caso no disponemos de ningún módulo, por lo que elegiremos que se cree uno nuevo para almacenar el EJB. 2. Nombre del fichero JAR que se creará para el módulo EJB. Puesto que sólo vamos a tener uno, lo hemos llamado “móduloEJB” para que destaque. Una aplicación J2EE real podría tener más de uno y sería conveniente que tuvieran nombres descriptivos. 3. El botón “Editar contenido...” lo usaremos para indicar qué ficheros componen el módulo. Nosotros tendremos que añadir los tres ficheros compilados que componen el enterprise bean.

71

3
1 2 3

Enterprises Beans y servicios de contenedor

4 5

La siguiente ventana sirve para que indiquemos qué papel juega cada una de las clases que componen el EJB. En ella tendremos que indicar los siguientes campos: 1. 2. 3. Nombre de la clase que implementa la lógica de negocio. Nombre del enterprise bean. Sólo sirve a título informativo. Como tipo, tendremos que elegir entre bean con estado y bean sin estado. En nuestro caso se trata de un bean sin estado (“Stateless Session”). 4. 5. Interfaz básica del EJB. Interfaz remota del bean.

En la figura anterior pudimos ver que existen dos grupos relativos a las interfaces:

“Interfaces Locales”. Las interfaces locales son aquellas que permiten comunicar con componentes EJB que estén en la misma unidad de despliegue. En nuestro ejemplo no

72

3
de la misma aplicación, no las hemos definido.

Enterprises Beans y servicios de contenedor

podemos utilizarlas porque, aunque la página JSP y el componente EJB forman parte

“Interfaces Remotas”. Las interfaces remotas permiten comunicar con componentes EJB mediante RMI.

Una vez terminado el asistente, nos aparecerá un nuevo nodo llamado “moduloEJB” colgando del nodo de la aplicación. A su vez, del módulo EJB colgarán tantos nodos como enterprise beans tengamos. En nuestro caso sólo el que acabamos de crear y que hemos llamado “VentasBean”. Recordemos que es en el descriptor de despliegue del módulo EJB donde se define el nombre JNDI que van a utilizar los enterprise beans que contiene dicho módulo. Con la creación del módulo que acabamos de realizar ya se le ha asignado un nombre JNDI por defecto al bean de nuestro ejemplo. Además, en la página JSP hacíamos uso de dicho nombre y habíamos decidido que sería “java:comp/env/ejb/Ventas”. Por lo tanto, vamos a seleccionar el nodo “VentasVean” y, a continuación, el botón “Preferencias específicas de Sun...” en la pestaña “General”. En la ventana que aparece podremos ver que el nombre JNDI asignado es “VentasBean”. Se lo cambiaremos por el de “ejb/Ventas” editando la celda correspondiente. En la figura siguiente podemos ver cómo quedaría.

Proseguiremos, a continuación, con el componente web. El proceso es parecido al anterior. En el menú “Archivo” seleccionaremos las opciones “Nuevo” y “Componente Web...”. Nos aparecerá un asistente que nos guiará a través del proceso de creación. De nuevo, nos detendremos sólo en aquellas ventanas que tengan datos trascendentes. En las demás podremos simplemente pulsar el botón “Siguiente >”. Empezamos por la siguiente ventana, muy parecida a la que ya viéramos cuando añadimos el enterprise bean.

73

3
1

Enterprises Beans y servicios de contenedor

2

3

Los datos a tener en cuenta son los siguientes: 1. De las tres opciones posibles, nos interesa crear un nuevo módulo web (hasta el momento nuestra aplicación no tiene ninguno). 2. Nombre del fichero WAR que va a contener el módulo web. Al igual que con los módulos EJB, debería tener un nombre más descriptivo, pero en nuestro caso no nos importa porque es el único que va a contener la aplicación J2EE. 3. Este botón se utiliza para indicar qué elementos forman parte del módulo web. Nosotros sólo vamos a añadirle la página “index.jsp” pero en una situación real tendríamos que añadir todos aquellos ficheros que compongan el módulo web (páginas JSP, ficheros HTML, hojas de estilo, imágenes, etc.). En la ventana en que nos solicite el tipo de componente web, elegiremos que no es ningún componente. La utilidad de esta ventana es que podamos definir características adicionales dependiendo del tipo de componente.

74

3

Enterprises Beans y servicios de contenedor

Tras la creación del módulo web nos quedan una serie de cambios por realizar. Para todos ellos tendremos que tener seleccionado el nodo “moduloWEB” en el árbol. En primer lugar, asignaremos a la aplicación web un nombre de contexto. Para ello seleccionaremos la pestaña “General” y el valor de “Raíz de contexto” lo fijaremos a “/ejemplo1”. Esto nos va a permitir ejecutar el módulo web utilizando la url “http://localhost:8080/ejemplo1”. También definiremos una página de bienvenida por defecto para que sea la que se muestre cuando se omita la página durante la navegación. A nosotros nos conviene que sea la página “index.jsp” porque además es la única que tiene nuestro módulo web. A continuación, seleccionaremos la pestaña “Referencias del archivo” y pulsaremos el botón “Agregar archivo” del apartado “Archivos de bienvenida”. Se añadirá automáticamente una fila y le indicaremos el valor “index.jsp”. Lo próximo va a ser añadir la referencia al enterprise javabean para que el módulo web pueda hacer uso de él. Seleccionaremos la pestaña “Referencias de EJB” y utilizaremos el botón “Añadir...”. La información que tenemos que completar es la siguiente:

“Nombre codificado”. Es el nombre de referencia del enterprise javabean. Tenemos que utilizar el nombre del subcontexto JNDI. Por lo tanto, el valor a poner sería “ejb/Ventas”.

“Tipo de EJB”. Tipo de bean. Podemos elegir entre los tipos “Session” y “Entity”. En nuestro caso estamos hablando de un bean de sesión.

“Interfaces”. Tendremos que decidir si utilizaremos la interfaz local o remota. Recordemos que al EJB sólo le hemos definido la interfaz remota, por lo tanto, seleccionaremos la opción “Remote”.

75

3

al que pertenece.

Enterprises Beans y servicios de contenedor

“Interfaz de inicio”. Interfaz básica del EJB. Tenemos que incluir el nombre del paquete

“Interfez local/remota”. Interfaz remota del EJB. También habremos de incluir el nombre de la clase.

“Nombre JNDI”. En el apartado “EJB de destino” tenemos que indicar cuál es el enterprise bean al que queremos hacer referencia. Nosotros vamos a optar por hacer referencia a él utilizando su nombre JNDI. Por lo tanto, será su nombre JNDI el que indicaremos aquí, es decir, el valor “ejb/Ventas”.

En la siguiente figura se muestra la información explicada anteriormente.

No obstante, nuestro módulo web no sólo hace uso del EJB. Recordemos que también utilizamos el pool de conexiones del servidor para obtener una conexión con la base de datos y realizar una consulta. No accedemos directamente al pool de conexiones, sino que hacemos referencia a un recurso JNDI que suministra una fuente de datos.

76

3
Los datos a cumplimentar son los siguientes:

Enterprises Beans y servicios de contenedor

Vamos entonces a añadirle al módulo web la referencia al recurso JNDI. Lo haremos seleccionando la pestaña “Referencias del recurso” y pulsando el botón “Agregar”.

“Nombre codificado”. Es el nombre de referencia del recurso. Tenemos que utilizar el nombre del subcontexto JNDI. Por lo tanto, el valor a poner sería “jdbc/CursoEJB”.

− −

“Tipo”. Este recurso será del tipo “javax.sql.DataSource”.

“Autenticación”. Indicaremos que la autentificación para utilizar el recurso la realiza el contenedor. Elegiremos la opción “Container”.

− −

“Compartible”. Indica si el recurso es compartible. Lo dejaremos habilitado.

“Nombre JNDI”. Éste será el nombre del recurso JNDI que queremos utilizar. Le asignaremos el valor “jdbc/CursoEJB”, que es con el que lo definimos en la consola de administración del servidor de aplicaciones.

“Nombre de usuario”. Nombre del usuario para la conexión con la base de datos. Utilizaremos la cuenta de administración por lo que el usuario es “sysdba”.

“Contraseña”. Contraseña de la cuenta de administración. Indicaremos “masterkey”.

En la siguiente figura podemos ver cómo quedarían los cambios que tenemos que realizar.

77

3

Enterprises Beans y servicios de contenedor

Con todo lo que hemos realizado, ya hemos finalizado. El proceso ha sido un poco largo y delicado y si algo no está como debiera, la aplicación no va a funcionar. Afortunadamente esta herramienta suministra un mecanismo de comprobación de errores. Concretamente se basa en comprobar que la aplicación cumple con la especificación J2EE. Por ejemplo, puede ayudarnos a resolver problemas derivados de errores al hacer referencia a recursos JNDI. Antes de desplegar la aplicación, verificaremos que cumple la especificación. Para ello, seleccionaremos el nodo de la aplicación (el llamado “ejemplo1”) en el árbol de estructura y, a continuación, elegiremos la opción “Herramientas” del menú y la subopción “Verificar la compatibilidad con J2EE...”. Nos aparecerá una ventana en la que podemos discriminar los mensajes obtenidos en base a su tipo. Elegiremos el modo “Sólo fallos y advertencias” para sólo ver los mensajes de aviso y error, pulsaremos el botón “OK” y empezará la comprobación. Cuando el proceso termine nos informará del éxito o de los errores encontrados. En la parte inferior de la ventana se nos mostrará el detalle del mensaje de error seleccionado (si lo hubiera). Acabamos de ejecutar el proceso de verificación y el resultado lo vemos en la siguiente ventana:

78

3
corresponda.

Enterprises Beans y servicios de contenedor

En caso de error tendremos que analizar su detalle y realizar la acción correctora que

Ha llegado el momento final. Hemos terminado de crear la aplicación y dentro de poco veremos el fruto de nuestro trabajo. No obstante, aún no la hemos desplegado, por lo que lo haremos ahora. Se trata de un proceso de lo más simple: teniendo seleccionado el nodo “ejemplo1”, utilizaremos el menú “Herramientas” y la opción “Implementar...”. Se nos mostrará una ventana en la que tendremos que elegir el servidor de aplicaciones e indicar el nombre y contraseña del administrador de dicho servidor. Seguidamente, pulsaremos el botón “Aceptar” y comenzará el proceso de despliegue. Iremos viendo una consola en la que se mostrarán mensajes relativos al proceso. En la figura siguiente podemos observar el resultado del despliegue de nuestra aplicación de ejemplo.

En la figura anterior tenemos la confirmación de que el despliegue ha tenido éxito y de que la aplicación está en ejecución.

79

3
3.7.3. El funcionamiento trabajo realizado y sacaremos algunas conclusiones.

Enterprises Beans y servicios de contenedor

Ahora viene la parte más esperada por todo desarrollador: ver en ejecución el código desarrollado. No esperaremos más y veamos cómo funciona. Posteriormente analizaremos el

Para ver el fruto de nuestro esfuerzo tenemos que abrir un navegador y navegar a la dirección “http://localhost:8080/ejemplo1”. Recordemos lo siguiente:

− − −

Nuestro servidor de aplicaciones atiende peticiones HTTP en el puerto 8080.

El contexto raíz que hemos definido para la aplicación es “/ejemplo1”.

En la petición no especificamos ninguna página porque le definimos al módulo web que utilizara la página “index.jsp” como página de bienvenida.

Al navegar a la dirección indicada se nos muestra el siguiente contenido:

Utilicemos los valores 3 y 17 para la cantidad y el precio, y pulsemos el botón “Calcular”. Veremos que nos muestra el resultado y nos permite volver a introducir nuevos valores. Las conclusiones que podemos extraer son variadas. Lo primero que nos puede resultar poco razonable es el volumen de trabajo que hemos tenido que realizar para obtener un producto tan simple. Utilizando otras tecnologías hubiéramos podido obtener los mismos resultados con menos esfuerzo. Por lo tanto, alguna ventaja debe tener el esfuerzo realizado.

80

3

Enterprises Beans y servicios de contenedor

Veamos algunas características de la aplicación que hemos desarrollado:

La experiencia demuestra que el esfuerzo realizado en el desarrollo de aplicaciones J2EE no es el que se percibe durante los primeros desarrollos. El problema reside en que es una tecnología muy distinta a otras que podamos conocer, por lo que aparenta gran esfuerzo y complejidad. Realmente, no hemos hecho gran cosa: escribir tres clases, compilarlas, escribir una página JSP, construir la aplicación y desplegarla en el servidor.

Supongamos

que

encontráramos

una

empresa

interesada

en

utilizar

nuestra

aplicación, pero que dispone de tres redes independientes y sus respectivos servidores son UNIX, AS/400 y Windows 2000 Server. ¿Se nos plantea algún problema? En absoluto. Nuestra aplicación es multiplataforma.

Ahora, supongamos que nuestra aplicación es utilizada en la empresa en la que trabajamos y que el volumen de usuarios ha crecido hasta el punto de que el rendimiento del servidor de aplicaciones que estamos utilizando se ha degradado demasiado. La empresa reconoce la necesidad de invertir en el mejor servidor de aplicaciones del mercado y nuestra aplicación va a ser capaz de funcionar en él.

Si decidimos cambiar la base de datos porque queremos migrar a otra más potente, bastará con cambiar el recurso JNDI del servidor para que apunte a la nueva base de datos, si hemos sido cuidadosos.

Por otro lado, si la aplicación vuelve a dar problemas porque las exigencias ha aumentado excesivamente, podemos distribuir la carga añadiendo otros servidores y equilibrando el reparto de componentes J2EE.

Esta relación es sólo una pequeña muestra de características. La documentación de la plataforma J2EE es mucho más extensa y específica al respecto.

81

3
recuerde_
− −

Enterprises Beans y servicios de contenedor

Un enterprise javabean tiene la finalidad de contener la lógica de la empresa (las reglas de negocio). Encapsula la funcionalidad crítica y permite que el desarrollador de aplicaciones se despreocupe de los servicios del nivel de sistemas, como la concurrencia, la persistencia y las transacciones

La especificación J2EE define tres tipos de enterprise javabeans, cada uno orientado a unos fines concretos. Dichos tipos son: beans de sesión, beans de entidad y beans controlados por mensaje.

El contenedor EJB es el entorno en el que se ejecuta un componente EJB y se encarga de proporcionarle los servicios necesarios durante su ciclo de vida.

82

4
índice_

Beans de sesión

4.1. 4.2. 4.3. 4.4. 4.5. 4.6.

TIPOS DE BEANS DE SESIÓN ..................................................85 LA LÓGICA DE NEGOCIO .........................................................86 LAS FACHADAS.......................................................................86 EL ESTADO CONVERSACIONAL ...............................................89 LA PERSISTENCIA ..................................................................91 UN EJEMPLO...........................................................................92 4.6.1. Un JavaBean ayudante ................................................92 4.6.2. El bean de sesión.........................................................93 4.6.3. El componente web .....................................................98 4.6.4. Desplegando la primera aplicación ............................102

83

4
4.1. TIPOS DE BEANS DE SESIÓN

Beans de sesión

Podemos distinguir dos tipos de beans de sesión: con estado y sin estado. A pesar de tener matices diferenciadores, ambos tipos tienen muchos aspectos comunes:

Implementan la interfaz “javax.ejb.SessionBean”, por lo que tienen las mismas retrollamadas de contenedor.

− − −

Se utilizan para modelar un proceso.

Representan un recurso privado para el cliente que los crea.

Pueden interactuar con datos compartidos pero no los representan como lo hacen los beans de entidad.

Tanto tienen en común, que la única forma de distinguirlos es mediante el fichero descriptor de despliegue. Mediante dicho fichero es capaz el contenedor EJB de saber de qué tipo de bean de sesión se trata. La diferencia fundamental entre ambos tipos de beans radica en la forma en la que tratan el estado. Por estado del bean se entiende el conjunto de variables miembros. De este modo, un bean de sesión con estado puede mantener los valores de sus variables entre distintas llamadas a sus métodos, mientras que un bean de sesión sin estado, no. Esta diferencia entre ambos tipos implica una gran repercusión en el diseño de una aplicación. Una regla básica a tener en cuenta es que los beans de sesión con estado sólo debemos utilizarlos en la frontera del modelo de objeto, es decir, en el extremo colindante con los clientes de la aplicación.

85

4
4.2. LA LÓGICA DE NEGOCIO

Beans de sesión

Aunque vamos a tratarlos en el siguiente tema, podemos adelantar que un bean de entidad es una entidad completa de datos. Por el contrario, los beans de sesión se utilizan para controlar la interacción entre las entidades de datos y el proceso en su conjunto. Una arquitectura muy adecuada para muchos objetivos en las aplicaciones corporativas consiste en organizar los beans en dos capas:

− −

La capa inferior proporciona servicios genéricos y se denomina capa de servicios.

La capa superior proporciona acceso controlado a estos servicios desde los clientes y se denomina capa de control de acceso.

Para que esta arquitectura sea efectiva, debemos mantener una cierta cantidad de datos, llamada estado conversacional, que representa la información creada durante un intercambio de solicitudes y respuestas. A medida que avanza el diálogo, el estado conversacional va acumulando información sobre el intercambio, y permite que las solicitudes que vayan a continuación puedan hacer uso de dicha información. El estado conversacional no debemos mantenerlo en la capa de servicios, sino que habremos de mantenerlo en la capa de control de acceso. Existe una formulación general de esta regla que prohíbe el estado en la capa de servicio basándose en criterios específicos de los EJB: Si se utilizan beans de sesión con estado, nunca deben encadenarse mediante llamadas mutuas de métodos de empresa. El contenedor EJB tiene libertad para descartar el estado conversacional después de pasado un tiempo considerable de inactividad. Es decir, puede destruir el bean de sesión con estado. A partir de ese momento, si se intentara utilizar se generaría una excepción.

4.3. LAS FACHADAS De los patrones de diseño que existen para la tecnología J2EE, uno de los más interesantes es el que utiliza un bean de sesión para proporcionar una fachada a un cliente. Se define como patrón a una solución usada comúnmente para la resolución de un problema común.

86

4
grupo de interfaces en un subsistema.

Beans de sesión

Por otro lado, una fachada es una interfaz de nivel superior que se utiliza para configurar un

En la siguiente figura podemos ver que utilizar un bean de sesión para proporcionar una fachada implica que sólo exista un punto de entrada a nuestro sistema. Desde el punto de vista del cliente sólo hay un bean de sesión con el que interactuar. Así pues, la interacción del cliente queda limitada a la fachada, que a su vez pasa las solicitudes al resto del sistema. Este patrón es conocido como el patrón de fachada porque proporciona un frontal a nuestro sistema.

Existen varias razones para utilizar el patrón de fachada. Las más obvias son que se reduce la complejidad y se minimizan las dependencias entre los subsistemas. Supongamos que un cliente necesitara acceder a la lógica de la empresa de varios beans de sesión y a la lógica de validación de varios beans de entidad. Veamos las siguientes ventajas al utilizar una fachada en lugar de acceder a los beans directamente desde el cliente:

Disminuye el tráfico de red. Éste siempre ha sido una limitación en el rendimiento de los sistemas de objetos distribuidos. La programación orientada a objetos suele implicar numerosas llamadas a métodos que cuando se realizan de forma remota, los parámetros y los valores de retorno deben ser enviados por la red. Supongamos que un cliente quiere sumar los resultados de invocar un método en un conjunto de 10 beans de entidad. Si el cliente invoca los beans de entidad directamente, cada

87

4
por la red.

Beans de sesión

invocación y cada respuesta viaja por la red. Si el cliente invoca la fachada del bean (y en él se realiza la suma), sólo es necesario que una invocación y una respuesta viajen

Control

transaccional

declarativo.

Habitualmente,

los

resultados

de

múltiples

operaciones de manipulación de datos deben aplicarse como una única unidad (una transacción). Cuando una fachada realiza todas las operaciones, el contenedor EJB puede gestionar el proceso automáticamente conforme a la información declarativa proporcionada por el desarrollador. Si es el cliente quien realiza las operaciones, debe responsabilizarse de garantizar el éxito del conjunto de dichas operaciones de forma atómica.

Se necesitan menos interposiciones. El contenedor EJB añade una capa de indirección entre el cliente y el bean para proporcionar sus servicios a los EJB. Esta capa consume recursos en el servidor (memoria y tiempo de proceso). Si un EJB llama a otro dentro del mismo contenedor, parte de su trabajo puede ser optimizado y pueden ahorrarse recursos.

La lógica de empresa estará en el nivel correcto. Cuando son necesarios varios beans para proporcionar una función de empresa, suele haber algún orden y relación en sus llamadas. Además de vincular estrechamente la capa cliente a la implementación de la capa de lógica de empresa, realizar las llamadas desde el cliente significa que cierta cantidad de flujo de trabajo se ubica en la capa cliente. Utilizando un bean de sesión como fachada, el cliente deja de estar estrechamente vinculado a la lógica de empresa y se preserva más flujo de trabajo en el servidor. Normalmente se organizan limitando los beans de entidad a representar filas en su base de datos mientras que un único método de empresa en un bean de sesión agrupa varias llamadas en uno o varios beans de entidad.

Como norma general, todos nuestros accesos a los enterprise Javabeans desde las aplicaciones cliente deberían ser a través de un número reducido de fachadas de beans de sesión. Lógicamente, esta regla no se aplica a los mismos EJB, que pueden tener beans de sesión sin fachada o de entidad como clientes; si no fuera así, la fachada necesitaría otra fachada y así sucesivamente.

88

4
4.4. EL ESTADO CONVERSACIONAL Podemos dividir el estado en dos tipos:

Beans de sesión

Transaccional. Hace referencia a los datos que almacenamos en el almacén persistente (la base de datos). Varios clientes pueden leer y modificar dichos datos simultáneamente. Si cae el servidor de aplicaciones, los datos siguen disponibles en el almacén de datos.

Conversacional. Hace referencia a los datos almacenados en las variables de la aplicación, en el cliente, en el contenedor EJB o en el servidor de aplicaciones. Son datos privados accesibles sólo para un cliente dado. Si el estado conversacional no se pasa a estado transaccional, desaparecerá cuando desaparezca el componente de la aplicación que lo mantiene.

En este apartado vamos a tratar sólo el estado conversacional. El estado transaccional es una cuestión ampliamente cubierta por las tecnologías actuales de bases de datos, que ya gozan de una dilatada experiencia en estas tareas. La mayoría de las aplicaciones tendrán estado conversacional. En función del cliente, el estado puede almacenarse de distintas formas. Los navegadores web pueden almacenar el estado en el cliente (mediante cookies o campos ocultos, por ejemplo) o en el servidor (sesiones HTTP). Los beans de sesión permiten otro espacio en el que puede almacenarse el estado (lo que puede facilitar la programación en determinadas circunstancias). El estado puede ser almacenado de forma unificada con independencia del tipo de clientes. Sin embargo, las ventajas potenciales que nos puede ofrecer en el desarrollo de la aplicación debemos equilibrarlas frente al coste de reajustabilidad y rendimiento. Para entender esto, veamos algunos detalles acerca del funcionamiento del contenedor EJB.

89

4
y lo destruye cuando invoca el método “remove ()”.

Beans de sesión

En la figura anterior podemos ver que todos los beans de sesión están asociados uno a uno con un cliente dado. El contenedor crea el EJB cuando el cliente invoca el método “create ()”,

Por ejemplo, si hubiera mil clientes web utilizando nuestra aplicación, habría mil beans de sesión en el servidor. Por el contrario, con un bean de sesión sin estado, damos al contenedor la oportunidad de optimizar los recursos utilizando la reserva de beans. Al no tener estado, no hay ningún efecto sobre el bean desde ninguna llamada de cliente, por lo que puede ser reutilizado en múltiples clientes. En la siguiente figura podemos ver un ejemplo.

Esto tiene un efecto muy importante sobre los recursos disponibles en el servidor. En lugar de tener mil beans de sesión sin estado, el contenedor puede tener una reserva de sólo cien. Claro está que la reserva debería ajustarse dinámicamente para cubrir un número indeterminado de solicitudes. Por lo que acabamos de ver, una reserva es una colección de instancias que se encuentran disponibles para ser utilizadas. El servidor podría reservar componentes, hilos, conexiones a bases de datos y otros recursos. Y una gran ventaja es que estas reservas son transparentes de cara al desarrollo de las aplicaciones. Quizás nos preguntemos que si los beans de sesión sin estado no tienen estado, por qué habrían de tener variables. La respuesta es que pueden tener estado que no esté asociado a un bean concreto (un socket, por ejemplo). Tampoco deben ser multihilo por motivos de diseño, ya que, se facilita el modelo de desarrollo para componentes EJB. A un EJB nunca accede más de un hilo a la vez, por lo que no necesitamos preocuparnos de la sincronización del acceso al estado.

90

4

Beans de sesión

Un bean de sesión sin estado pueden tener estado asociado a un cliente en una llamada de método dado, pero no puede mantener dicho estado entre distintas llamadas a métodos. Para ayudar al contenedor EJB en la gestión de un gran número de beans de sesión con estado, la especificación J2EE incluye las retrollamadas y reglas que otorgan al contenedor la capacidad de trasladar un bean de sesión con estado a almacenamiento temporal, y de restaurarlo posteriormente desde ese almacén. El algoritmo que utilice el contenedor para decidir cuándo debe almacenarlo es específico del contenedor EJB. La operación de almacenamiento de un bean se denomina pasivación y la reactivación se conoce como activación. La activación y pasivación son métodos muy efectivos para tratar los problemas de la limitación de recursos en los servidores. No obstante, si la reajustabilidad es importante para nuestra aplicación, lo mejor es mantener el estado en el cliente y pasarlo de vuelta al servidor con cada invocación.

4.5. LA PERSISTENCIA La lógica de empresa a menudo suele realizar operaciones de adición y modificación de datos del almacén persistente de nuestra empresa, es decir, de nuestra base de datos. La especificación Enterprise JavaBeans proporciona beans de entidad para representar estos datos y proveer los servicios relacionados con la persistencia. Sin embargo, podemos no hacer uso de los beans de entidad y acceder directamente a un almacén de datos desde nuestros beans de sesión. Es decir, nuestros beans de sesión pueden ser los encargados de soportar la funcionalidad de los beans de entidad. Pero como es normal, dejaremos de usar determinados servicios de persistencia del contenedor, lo que añadirá complejidad a nuestro desarrollo. En algunas ocasiones nos puede merecer la pena utilizar el acceso directo a los datos mediante JDBC desde nuestros beans de sesión en lugar de utilizar beans de entidad. En otras ocasiones, utilizar un enfoque de bean de sesión puede tener un efecto perjudicial en el rendimiento porque terminaríamos implementando muchos servicios complejos que los servidores de aplicación tienen más que optimizados. Las situaciones más comunes requerirán el uso de beans de entidad con persistencia gestionada por contenedor para operaciones sobre entidades individuales y conjuntos reducidos de valores. Los beans de sesión serán más apropiados para operaciones sobre un conjunto de datos.

91

4
4.6. UN EJEMPLO a interesar el bean de sesión.

Beans de sesión

A continuación vamos a ver un ejemplo de uso de los Enterprise JavaBeans. Se trata de un ejemplo de utilización conjunta de beans de sesión y de entidad. Por el momento sólo nos va

La funcionalidad del ejemplo se va a limitar a una página JSP que nos muestre la relación de clientes de nuestra base de datos y nos permita las operaciones de creación, modificación y borrado sobre dichos clientes. El ejemplo va a componerse de dos aplicaciones J2EE. Una de ellas va a contener los componentes EJB que van a implementar la lógica de negocio. Sus componentes serán:

Componente EJB de sesión sin estado. Va a ser la fachada de cliente. El único punto posible a través del cual los clientes de la aplicación podrán acceder a la capa EJB.

Componente EJB de entidad con persistencia gestionada por el contenedor.

Para el desarrollo y despliegue del ejemplo vamos a usar las mismas herramientas utilizadas en el tema anterior, por lo que no vamos a repetir los detalles ya descritos. Lo primero será ejecutar el entorno de desarrollo NetBeans y crear el proyecto con el nombre “ejemplo2”, creándose la siguiente estructura de directorios en los respectivos sistemas operativos:

En Linux: /home/alumno/cursoEJB/ejemplo2 En Windows: c:\cursoEJB\ejemplo2

A continuación, vamos a crear un paquete Java, llamado “gestion”, en el que meteremos todas las clases e interfaces de nuestro ejemplo. No debemos olvidar en adelante que cualquier clase que creemos tendrá que pertenecer a este paquete. 4.6.1. Un JavaBean ayudante Definiremos una clase JavaBean, a la que llamaremos “ClienteDetalle”, que va a servirnos para representar a cada uno de los clientes. Esta clase va a contener métodos “getter ()” y “setter ()” para cada uno de los atributos del cliente. Nos va a servir para utilizarla en las llamadas a métodos en lugar de usar la lista completa de propiedades del cliente. Además, si

92

4
package gestion;

Beans de sesión

en un futuro decidimos añadir o quitar propiedades del cliente, el volumen de modificaciones va a ser significativamente menor. Para crear la clase, utilizamos el botón derecho del ratón sobre el nodo “gestion” y seleccionamos la opción “New” y subopción “Java Class”. A continuación, editaremos la clase “ClienteDetalle” y escribiremos el siguiente código:

public class ClienteDetalle implements java.io.Serializable { private Integer cliente = null; private String nombre = null; public ClienteDetalle (Integer cliente, String nombre) { this.cliente = cliente; this.nombre = nombre; } public Integer getCliente() { return this.cliente; } public void setCliente(Integer cliente) { this.cliente = cliente; } public String getNombre() { return this.nombre; } public void setNombre (String nombre) { this.nombre = nombre; } }

Seguidamente compilaremos la clase. 4.6.2. El bean de sesión Anteriormente vimos que el bean de sesión que vamos a desarrollar va a formar parte de la fachada de la capa EJB. Nuestro bean estará en la frontera del modelo de componentes EJB y será el único punto de entrada para los clientes que necesiten los servicios de la capa. En dicha capa reside la lógica de negocio, y la fachada de cliente será la responsable de canalizar los accesos.

93

4
del bean de entidad.

Beans de sesión

Nuestro ejemplo es muy sencillo porque tras la fachada sólo se esconde un bean de entidad, y la relación entre los métodos del bean de sesión y del bean de entidad es de uno a uno. Es decir, cuando se invoca cualquier método del bean de sesión, éste llama en cada caso a un método concreto (y sólo a uno) del bean de entidad. Esta situación puede parecer absurda, ya que, el bean de sesión es un mero intermediario que no aporta nada (aparentemente). La página JSP podría prescindir del bean de sesión y llamar directamente al método específico

No obstante, las situaciones reales no suelen ser tan simples. Nos podemos encontrar con beans de sesión que invocan a uno o más métodos de uno o más beans (del tipo que sean) y en un orden determinado. Forma parte de la lógica de negocio que dichas llamadas se realicen, y que sea en el orden necesario. Confiar esto al cliente (la página JSP) no es lo más acertado. Estaríamos pasando la lógica de negocio a una capa que no le corresponde. Además, si en un futuro necesitamos desarrollar una página JSP adicional o un cliente de aplicación, también tendríamos que implementar en ellos la lógica de negocio, con el consiguiente riesgo de errores. Cuando decimos que el bean de sesión es el único punto de entrada a la capa donde reside la lógica de negocio, no estamos haciendo referencia a que sea aconsejable acceder a través de él. En este caso concreto se trata de que sea imposible acceder al bean de entidad puesto que sólo el bean de sesión define una interfaz remota. Aunque lo vamos a ver en el próximo tema, comentaremos aquí que el bean de entidad sólo tiene interfaz local, lo que impide que se tenga acceso a él desde fuera de la unidad de despliegue de la que forma parte. Lo próximo que vamos a hacer es crear la clase y las dos interfaces que necesitará nuestro EJB de sesión. Utilizaremos el botón derecho del ratón sobre el nodo “gestion” y seleccionamos la opción New y subopción Java Class. Esta operación la realizaremos tres veces y los nombres que emplearemos serán los siguientes: MtoClientesHome, MtoClientes y MtoClientesBean. A continuación, vamos a modificar el contenido de cada clase para que se ajuste a lo que queremos de ella. Concretamente, dos de esas clases deberían ser interfaces, por lo que las cambiaremos. Pero veamos primero cual es la finalidad de cada una de ellas:

− − −

“MtoClientesHome”. Es la interfaz básica del EJB. “MtoClientes”. Es la interfaz remota del EJB. “MtoClientesBean”. Es la clase de implementación. Contiene el código de los métodos de negocio.

94

4
package gestion; import javax.ejb.*; public gestion.MtoClientes create ()

Beans de sesión

Seguidamente, editaremos la clase MtoClientesHome y escribiremos el siguiente código:

public interface MtoClientesHome extends javax.ejb.EJBHome { throws javax.ejb.CreateException, java.rmi.RemoteException; }

Para la clase “Mtoclientes”, su código será:

package gestion; import javax.ejb.*; public interface MtoClientes extends javax.ejb.EJBObject { public java.util.Vector findAll () throws javax.naming.NamingException,

java.rmi.RemoteException,

javax.ejb.FinderException;

public void alta (java.lang.Integer cliente, java.lang.String nombre) throws java.rmi.RemoteException, javax.ejb.CreateException, public void java.sql.SQLException; baja (java.lang.Integer javax.ejb.FinderException, cliente) throws javax.naming.NamingException,

javax.naming.NamingException,

java.rmi.RemoteException, javax.ejb.RemoveException; public void modificacion (java.lang.Integer cliente, java.lang.String nombre) throws java.rmi.RemoteException, javax.ejb.FinderException; } javax.naming.NamingException,

95

4
reglas de negocio, le escribimos el siguiente código: package gestion; import javax.naming.*; import javax.ejb.*; import java.util.*; public class MtoClientesBean implements javax.ejb.SessionBean { private javax.ejb.SessionContext context;

Beans de sesión

Por último, a la clase MtoClientesBean, que es la que contiene el código que soporta las

public void setSessionContext (javax.ejb.SessionContext aContext) { context=aContext; } public void ejbActivate () { } public void ejbPassivate () { } public void ejbRemove () { } public void ejbCreate () { } public java.util.Vector findAll() throws javax.naming.NamingException, javax.ejb.FinderException { Vector clientesDetalle = new Vector(); Context ctx = new InitialContext(); Object obj = ctx.lookup ("java:comp/env/ejb/Clientes"); LocalClientesHome home = (LocalClientesHome) javax.rmi.PortableRemoteObject.narrow(obj, LocalClientesHome.class); Collection clientes = home.findAll(); if (clientes!=null) { Iterator iter = clientes.iterator(); while (iter.hasNext()) { ClienteDetalle detalle = ((LocalClientes)iter.next()).getClienteDetalle(); clientesDetalle.addElement(detalle); } } return clientesDetalle; } public void alta(java.lang.Integer cliente, java.lang.String nombre) throws javax.naming.NamingException, javax.ejb.CreateException,

96

4
java.sql.SQLException { Context ctx = new InitialContext(); LocalClientesHome home = (LocalClientesHome) javax.rmi.PortableRemoteObject.narrow(obj, LocalClientesHome.class); try {

Beans de sesión

Object obj = ctx.lookup ("java:comp/env/ejb/Clientes");

LocalClientes existe = home.findByPrimaryKey (cliente); throw new java.sql.SQLException ("Ya existe un cliente con el código " + cliente.toString ()); } catch (FinderException e) { home.create (cliente, nombre); } } public void baja (java.lang.Integer cliente) throws javax.naming.NamingException, javax.ejb.FinderException, javax.ejb.RemoveException { Context ctx = new InitialContext (); Object obj = ctx.lookup ("java:comp/env/ejb/Clientes"); LocalClientesHome home = (LocalClientesHome) javax.rmi.PortableRemoteObject.narrow(obj, LocalClientesHome.class); LocalClientes clientes = home.findByPrimaryKey (cliente); clientes.remove (); } public void modificacion (java.lang.Integer cliente, java.lang.String nombre) throws javax.naming.NamingException, javax.ejb.FinderException { Context ctx = new InitialContext (); Object obj = ctx.lookup ("java:comp/env/ejb/Clientes"); LocalClientesHome home = (LocalClientesHome) javax.rmi.PortableRemoteObject.narrow(obj, LocalClientesHome.class); LocalClientes clientes = home.findByPrimaryKey (cliente); clientes.modify (new ClienteDetalle (cliente, nombre)); } }

97

4
momento nos será suficiente con compilar las dos interfaces. 4.6.3. El componente web

Beans de sesión

Por el momento no podemos compilar la clase MtoClientesBean, ya que hace referencia a las interfaces remotas del bean de sesión y no hemos escrito su código aún. No hemos de preocuparnos por esto, ya que en el siguiente tema completaremos el ejemplo. Por el

Vamos ahora con el componente web. Hemos determinado que se va a componer de una única página JSP. Dicha página mostrará la relación de los clientes que existen y nos permitirá realizar las operaciones de creación, modificación y borrado sobre ellos. Al igual que hicimos en el capítulo anterior, vamos a crear manualmente la página en el directorio del ejemplo (recordemos que se trata del directorio “/home/alumno/cursoEJB/ejemplo2” para los usuarios de Linux, y de “c:\cursoEJB\ejemplo2” para los usuarios de Windows). El fichero se llamará “index.jsp” y lo podemos crear con nuestro editor de textos favorito. El contenido de la página JSP será el siguiente:

<%@page contentType="text/html"%> <%@page import="javax.naming.*"%> <%@page import="java.rmi.*"%> <%@page import="javax.ejb.*"%> <%@page import="java.util.Iterator"%> <%@page import="gestion.ClienteDetalle"%> <%@page import="gestion.MtoClientesHome"%> <%@page import="gestion.MtoClientes"%> <% String errorText = ""; Iterator clientes = null; try { // Obtenemos una referencia al contexto de ejecución Context ctx = new InitialContext (); // Obtenemos una referencia al componente EJB Object obj = ctx.lookup ("java: comp/env/ejb/MtoClientes");

98

4
// Obtenemos la referencia a la interfaz básica MtoClientesHome home = (MtoClientesHome) javax.rmi.PortableRemoteObject.narrow (obj, MtoClientes mtoClientes = home.create (); String operacion = request.getParameter ("operacion"); Integer cliente = null; String nombre = null; if (operacion!=null && !operacion.equals("")) {

Beans de sesión

MtoClientesHome.class);

cliente = new Integer (request.getParameter ("cliente")); nombre = request.getParameter ("nombre"); if (operacion.equals ("alta")) { mtoClientes.alta(cliente, nombre); } else if (operacion.equals("modificacion")) { mtoClientes.modificacion(cliente, nombre); } else if (operacion.equals("baja")) { mtoClientes.baja(cliente); } } clientes = mtoClientes.findAll().iterator(); mtoClientes.remove(); } catch (NamingException e) { errorText = "Error de nombre de recurso JNDI"; } catch (java.sql.SQLException e) { errorText = e.getMessage(); } catch (CreateException e) { errorText = "CreateException"; } catch (FinderException e) { errorText = "FinderException"; } catch (RemoteException e) { errorText = "RemoteException"; } catch (NumberFormatException e) { errorText = "Error de conversión numérica (" + request.getParameter("cliente") + ")"; } %>

99

4
<html> <head> <title>cursoEJB/ejemplo1</title> <SCRIPT language='javascript'> function baja(cliente) { document.datos.operacion.value = "baja"; document.datos.cliente.value = cliente; document.datos.nombre.value = ""; document.datos.submit(); } function modificacion(cliente) { document.datos.operacion.value = "modificacion"; document.datos.cliente.value = cliente;

Beans de sesión

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

document.datos.nombre.value = document.datos["nombre"+cliente].value; document.datos.submit(); } </SCRIPT> </head> <body> <% if (!errorText.equals("")) { %> <%=errorText%> <hr> <a href="index.jsp">Volver</a> <% } else { %> <FORM name="datos" method="POST" action="index.jsp"> <INPUT type="hidden" name="operacion" value="alta"> <TABLE border="0"> <TR> <TD align="right"><b>C&oacute;digo</b></TD> <TD><b>Nombre</b></TD>

100

4
<TD>&nbsp;</TD> </TR> <% while (clientes.hasNext()) { ClienteDetalle item = (ClienteDetalle)clientes.next(); %> <TR>

Beans de sesión

<TD align="right"><A href="javascript:;" title="Borrar el cliente" onclick= "javascript:baja(<%=item.getCliente()%>);"> <%=item.getCliente()%></A></TD> <TD><INPUT type="TEXT" name="nombre<%=item.getCliente()%>" value="<%=item.getNombre()%>"></TD> <TD><INPUT type="BUTTON" value="Guardar modificaci&oacute;n" onclick="javascript:modificacion(<%=item.getCliente()%>);"></TD> </TR> <% } %> </TABLE> <HR> C&oacute;digo:&nbsp; <INPUT type="text" name="cliente"><br> Nombre:&nbsp; <INPUT type="text" name="nombre"><br> <INPUT type="submit" value="Crear"> </FORM> <% } %> </body> </html>

En la página JSP hacemos uso de JNDI para obtener la referencia al componente de negocio (el EJB de sesión) y poder hacer uso de él. El nombre JNDI del recurso es “java:comp/env/ejb/MtoClientes” y su creación forma parte del despliegue de la aplicación J2EE que contiene los componentes EJB. No obstante, para que sea así tendremos que indicarlo dentro del fichero descriptor de despliegue del componente EJB. En nuestro caso lo

101

4
definiremos desde la herramienta deploytool. 4.6.4. Desplegando la primera aplicación

Beans de sesión

Nos falta crear el bean de entidad para tener todo el código fuente que necesitamos, pero vamos a dejarlo para el siguiente tema, en el que estudiaremos este tipo de EJB. En lo que respecta a la aplicación J2EE que se va a componer del módulo web, ya estamos preparados para desplegarla, no necesitamos nada más. Ha llegado el momento de que utilicemos la herramienta de despliegue. Recordemos que está en el directorio bin del servidor de aplicaciones y que se llama deploytool. Para utilizarla es importante que el servidor de aplicaciones esté en ejecución. La ejecutaremos y, una vez dentro, lo primero que tenemos que hacer es crear una aplicación J2EE. Para ello, seleccionaremos en el menú la opción Archivo, después la opción Nuevo y, por último, la opción Aplicación.... Aparecerá una caja de diálogo solicitándonos el nombre del fichero y la descripción de la aplicación. Como fichero utilizaremos “/home/alumno/cursoEJB/ejemplo2/ejemplo2.ear” si estamos en Linux, y “c:\cursoEJB\ejemplo2\ejemplo2.ear” si estamos en Windows. Le dejaremos la descripción que nos sugiere por defecto y pulsaremos Aceptar para finalizar. Ya hemos creado una aplicación, pero está vacía. No tiene ningún componente. El próximo paso será crearle un módulo web con la página JSP que hemos desarrollado. A continuación, pulsaremos el botón izquierdo del ratón sobre el nodo “ejemplo2”, que es la aplicación recién creada, para seleccionarlo. En el menú Archivo seleccionaremos las opciones Nuevo y Componente Web... Nos aparecerá un asistente que nos guiará a través del proceso de creación. Nos detendremos sólo en aquellas ventanas que tengan datos trascendentes. En las demás podremos simplemente pulsar el botón Siguiente >.

102

4
Veamos las ventanas principales:

Beans de sesión

Como vemos en la figura anterior, no podemos olvidar añadir la clase ClienteDetalle y las interfaces MtoClientes y MtoClientesHome, ya que se hace referencia a ellas en la página JSP.

103

4
“/ejemplo2”. Esto nos va a permitir ejecutar el módulo “http://localhost:8080/ejemplo2”.

Beans de sesión

Tras la creación del módulo web nos quedan una serie de cambios por realizar. Para todos ellos tendremos que tener seleccionado el nodo moduloWEB en el árbol. En primer lugar, asignaremos a la aplicación web un nombre de contexto. Para ello, seleccionaremos la pestaña General y el valor de Raíz de contexto lo fijaremos a web utilizando la url

También definiremos una página de bienvenida por defecto para que sea la que se muestre cuando se omita la página durante la navegación. A nosotros nos conviene que sea la página “index.jsp”, porque además es la única que tiene nuestro módulo web. Seleccionaremos la pestaña “Referencias de archivo” y pulsaremos el botón “Agregar Archivo” del apartado “Archivos de bienvenida”. Se añadirá automáticamente una fila y le indicaremos el valor “index.jsp”. Lo próximo va a ser añadir la referencia al enterprise javabean para que el módulo web pueda hacer uso de él. Seleccionaremos la pestaña “Referencias de EJB” y utilizaremos el botón “Agregar...”. La información que tenemos que completar es la siguiente:

“Nombre codificado”. Es el nombre de referencia del enterprise javabean. Tenemos que utilizar el nombre del subcontexto JNDI. Por lo tanto, el valor a poner sería “ejb/MtoClientes”.

“Tipo EJB”. Tipo de bean. Podemos elegir entre los tipos “Session” y “Entity”. En nuestro caso estamos hablando de un bean de sesión.

“Interfaces”. Tendremos que decidir si utilizaremos la interfaz local o remota. Recordemos que al EJB sólo le hemos definido la interfaz remota, por lo tanto seleccionaremos la opción “Remote”.

“Interfaz de inicio”. Interfaz básica del EJB. Tenemos que incluir el nombre del paquete al que pertenece.

“Interfaz local/remota”. Interfaz remota del EJB. También habremos de incluir el nombre de la clase.

“Nombre JNDI”. En el apartado “EJB de destino” tenemos que indicar cuál es el

104

4
indicaremos aquí, es decir, el valor “ejb/MtoClientes”.

Beans de sesión

enterprise bean al que queremos hacer referencia. Nosotros vamos a optar por hacer referencia a él utilizando su nombre JNDI. Por lo tanto, será su nombre JNDI el que

En la siguiente figura se muestra la información explicada anteriormente.

Hemos terminado de crear la aplicación y dentro de unos momentos veremos el fruto de nuestro trabajo. No obstante, aún no la hemos desplegado, por lo que nos tenemos que hacerlo ahora. Se trata de un proceso de lo más simple. Teniendo seleccionado el nodo “ejemplo2”, utilizaremos el menú Herramientas y la opción Implementar... Se nos mostrará una ventana en la que tendremos que elegir el servidor de aplicaciones e indicar el nombre y contraseña del administrador de dicho servidor, y seguidamente pulsaremos el botón Aceptar para comenzar el proceso de despliegue. Iremos viendo una consola en la que se mostrarán mensajes relativos al proceso. Una vez finalizado el despliegue de la aplicación habremos terminado la primera parte del ejemplo. Si queremos podemos probarla abriendo el navegador web y apuntando a la

105

4
dirección “http://localhost:8080/ejemplo2”. La aplicación aplicación web.

Beans de sesión
disponible pero

estará

obtendremos una excepción debida a que no se puede localizar el bean de sesión. En el siguiente tema terminaremos de completar este ejemplo y podremos probar la

106

4
recuerde_
− −
estado, no.

Beans de sesión

Los beans de sesión se utilizan para modelar un proceso y se clasifican en dos tipos: beans de sesión con estado y beans de sesión sin estado.

Un bean de sesión con estado puede mantener los valores de sus variables entre distintas llamadas a sus métodos, mientras que un bean de sesión sin

Uno de los patrones de diseño más interesantes que existe para la tecnología J2EE es el que utiliza un bean de sesión para proporcionar una fachada a un cliente.

Una fachada es una interfaz de nivel superior que se utiliza para configurar un grupo de interfaces en un subsistema. La utilización de fachadas aporta numerosas ventajas en el desarrollo y mantenimiento de los sistemas de software.

El estado conversacional hace referencia a los datos almacenados en las variables de la aplicación, en el cliente, en el contenedor EJB o en el servidor de aplicaciones. Son datos privados accesibles sólo para un cliente dado.

107

5
índice_

Beans de entidad

5.1. 5.2. 5.3. 5.4.

¿QUÉ ES UN BEAN DE ENTIDAD?..........................................111 LA PERSISTENCIA ................................................................112 LOS ACCESORES ABSTRACTOS..............................................114 EJB-QL .................................................................................115 5.4.1. Claúsula “SELECT” .....................................................116 5.4.2. Claúsula “FROM” .......................................................116 5.4.3. Cláusula “WHERE” .....................................................116

5.5. 5.6.

LAS CLAVES PRIMARIAS.......................................................117 LAS RETROLLAMADAS DEL CONTENEDOR .............................120 5.6.1. Creación ....................................................................120 5.6.2. Lectura......................................................................121 5.6.3. Modificación ..............................................................121 5.6.4. Borrado .....................................................................122

5.7. 5.8. 5.9.

LOS MÉTODOS BUSCADORES ................................................122 ACTIVACIÓN Y PASIVACIÓN.................................................124 SIGAMOS CON EL EJEMPLO ..................................................124 5.9.1. El bean de entidad .....................................................124 5.9.2. Desplegando la segunda aplicación............................127

109

5
5.1. ¿QUÉ ES UN BEAN DE ENTIDAD? productivo.

Beans de entidad

El concepto fundamental que debemos tener presente acerca de los Enterprises JavaBeans de entidad es que no se trata de meras clases, sino que representan entidades del modelo de análisis de una aplicación. Estas entidades pueden corresponderse con conceptos concretos, como clientes y proveedores, o con conceptos abstractos, como un proceso

Un bean de sesión puede acceder a datos, no obstante, no puede darnos una representación de objeto de dichos datos. ¿Qué significa esto? ¿Qué diferencia supone frente a la utilización de beans de sesión? En el tema anterior dijimos que el estado que mantienen los beans de sesión con estado es privado. Esto significa que sólo el cliente que lo utiliza puede manipular el estado del bean. Si varios clientes acceden a un mismo bean de sesión, cada uno de ellos accede a una instancia distinta que le suministra el contenedor EJB. En el caso de los beans de entidad, el estado es almacenado en la base de datos, por lo que varios clientes pueden acceder simultáneamente a un mismo bean. Cada bean de entidad es único y cualquier cliente que acceda a los datos tendrá que pasar por él. Además de permitirnos representar estado compartido y transaccional, los beans de entidad tienen otras ventajas adicionales. El contenedor EJB nos proporcionará una serie de servicios de nivel de sistema, motivo por el cual podremos centrarnos en la programación de lógica de empresa. Los cuatro servicios principales que suministra un contenedor EJB son:

Retrollamadas del contenedor para informar al EJB sobre el progreso de la transacción actual.

Control de accesos concurrentes. El contenedor puede emplear distintas estrategias para lograr la compatibilidad de accesos concurrentes. Una de ellas consiste en posponer el control concurrente a la base de datos.

Mantenimiento

de

una

caché

entre

transacciones,

que

puede

mejorar

significativamente el rendimiento del sistema.

Proporcionan todo el código necesario para la gestión de la persistencia. La persistencia gestionada por el contenedor no sólo nos liberará de escribir código de

111

5
contenedor. 5.2. LA PERSISTENCIA

Beans de entidad

acceso a datos, sino que también nos puede proporcionar optimizaciones propias del

El contenedor EJB puede gestionar el proceso de guardar y restaurar el estado de los beans de entidad. Esta característica recibe el nombre de persistencia gestionada por contenedor (CMP, Container Managed Persistence). No obstante, podemos desear que nuestros beans puedan gestionar la persistencia por si mismos. En este último caso hablaremos de persistencia gestionada por bean (BMP, Bean Managed Persistence). Es una decisión muy importante en cualquier aplicación que utilice la tecnología Enterprise JavaBeans, la relacionada con la forma de gestión de la persistencia que utilizarán los beans de entidad. La experiencia nos demuestra que la persistencia es uno de los servicios de nivel de sistema más tediosos cuando se desarrolla la lógica de empresa. Suele utilizarse código SQL y es un proceso que consume mucho tiempo y es muy proclive a errores. La especificación EJB ha sido desarrollada, entre otras cosas, para trasladar estos temas de nivel de sistema al contenedor EJB. Para la mayoría de los casos, lo más adecuado será aprovechar esa capacidad del contenedor para gestionar la persistencia. Sin embargo, la persistencia gestionada por bean es una elección importante en determinadas circunstancias. Tendremos que determinar si nuestro contenedor EJB tiene el nivel de compatibilidad que necesitamos para aprovechar su gestión de la persistencia. De ser así, deberíamos utilizarlo para evitarnos escribir el código necesario para la persistencia. El modelo CMP también aporta otras interesantes ventajas. Por ejemplo, si utilizamos el modelo BMP, una consulta que recupere varios beans la traduciremos normalmente en dos llamadas distintas a la base de datos: una para consultar las claves primarias y otra para recuperar los beans. Si utilizamos CMP, el contenedor puede realizar sólo una solicitud a la base de datos, cosa que es imposible con BMP. CMP tiene muchas otras ventajas, por lo que utilizar BMP lo haremos en situaciones muy concretas. En caso de dudas, será mejor que nos decidamos por CMP. Si nuestro almacén de datos fuese un sistema ERP o alguna otra aplicación existente, probablemente necesitaríamos utilizar persistencia gestionada por bean. La diferencia estaría en que, en lugar de escribir código SQL, probablemente necesitáramos utilizar protocolos específicos del almacén que no serían compatibles con el contenedor EJB.

112

5
opciones:

Beans de entidad

Por otra parte, si nuestro almacén de datos es una base de datos relacional y el contenedor EJB no es compatible con CMP para nuestra aplicación, podríamos optar entre las siguientes

Utilizar otro contenedor EJB. Esta opción no es siempre posible, no obstante, existen servidores de aplicación con sofisticadas funciones de asociación objeto/relacional en el mercado. Debemos tener en cuenta las capacidades de los distintos servidores de aplicación a la hora de decidirnos por alguno de ellos.

Utilizar alguna herramienta de asociación objeto/relacional. Podemos optar por herramientas objeto/relacional de terceros para los beans de entidad. Es una buena opción, pero tiene dos principales inconvenientes: suelen ser caras y estaremos dependiendo de un sistema de terceros.

Cambiar el diseño de la aplicación. Podemos cambiar nuestro diseño teniendo en cuenta las limitaciones de la herramienta que elijamos y utilizar persistencia gestionada por contenedor. Esta opción no es siempre posible, y presenta dos desventajas: el rendimiento puede no ser el más óptimo y el nuevo diseño podría ser más difícil de implementar, mantener y comprender.

Escribir nuestro propio código para el acceso a datos. Es un compromiso muy importante decidir si vamos a escribir el código de persistencia que necesitamos para nuestra aplicación. En caso de hacerlo, deberíamos encapsular el código de persistencia en componentes de ayuda de acceso a datos de los beans de entidad. Si observamos que estamos dedicando un tiempo considerable en su desarrollo, deberíamos volver a considerar el hecho de utilizar los servicios de persistencia del contenedor. Uno de los objetivos de la especificación EJB es la del aprovechar los servicios del contenedor para aumentar la productividad.

113

5
5.3. LOS ACCESORES ABSTRACTOS

Beans de entidad

Un bean de entidad con persistencia gestionada por contenedor se define por sus campos CMP, los cuales son los campos Java que están asociados a las tablas de la base de datos. La especificación EJB impone que estos campos se definan mediante accesores abstractos. Por ejemplo, un campo de tipo texto llamado “direccionCliente” lo declararemos como:

public abstract String getDireccionCliente(); public abstract void setDireccionCliente(String direccionCliente); Podría darse el caso de que en nuestra base de datos no tuviéramos una columna llamada “direccionCliente”, pero no importa puesto que en el descriptor de despliegue sólo tendríamos que especificar cómo asociarlo. El contenedor tiene control total sobre el acceso a los campos. Generará código para cada accesor y puede optimizar los accesos a la base de datos. Gracias a esto, hay algunas ventajas que suelen proporcionar los contenedores EJB:

Posponer la carga de los beans. Dado que el contenedor sabe qué campos son accesibles y cuándo puede acceder a ellos, no tiene que cargar el estado completo del bean inicialmente. Puede posponer la carga para cuando realmente se necesite la información.

Actualizar sólo los cambios. El contenedor sabe en todo momento qué campos han sido modificados, por lo tanto, es capaz de actualizar en la base de datos sólo las columnas correspondientes a los campos que hayan cambiado.

Carga por grupos. Algunos contenedores pueden permitirnos definir grupos de campos. Si tenemos un bean de entidad que contenga un objeto binario, además de otros de tipo básico (como números), y realizamos una consulta, el estado completo va a viajar por la red (incluyendo el objeto binario). Sería un consumo de recursos innecesario si el cliente no estuviera interesado en el objeto binario. Cuando se definen grupos de campos, el contenedor sólo manejará los campos que pertenecen al mismo grupo que el campo solicitado.

114

5
5.4. EJB-QL lenguaje de consulta que sea independiente de la base de datos.

Beans de entidad

Uno de los mayores beneficios de la persistencia gestionada por contenedor es que nos abstrae del almacén de datos. No necesitamos saber cómo se almacenan los beans o qué tipo de base de datos está utilizando. El inconveniente de esto, es que se necesita un

La especificación EJB define un lenguaje denominado EJB QL (EJB Query Language). Se trata de un lenguaje cuya sintaxis es muy similar a la de SQL. Las sentencias EJB QL se escriben en los descriptores de despliegue, y el contenedor EJB será el encargado de generar las correspondientes instrucciones para interactuar con el almacén de datos. El objetivo del lenguaje EJB QL es permitirnos la portabilidad de nuestros beans de entidad CMP, es decir, que sigan funcionando con independencia del almacén de datos y del lenguaje específico que utilice. Aunque la sintaxis de EJB QL es muy similar a la de SQL, el concepto subyacente es muy diferente. Necesitamos comprender cómo interactúan los objetos Java y las instancias de los EJB para que podamos aprovechar todas las ventajas que nos ofrece este lenguaje. EJB QL se utiliza para la implementación de los métodos buscadores y de los métodos de selección. Trataremos sobre ellos más adelante. Una consulta del lenguaje EJB QL es una cadena que se compone de las siguientes tres cláusulas:

− − −

“SELECT”. Indica el tipo de objeto o los valores que se quieren recuperar. “FROM”. Determina el origen de los datos. “WHERE”. Se emplea para restringir el conjunto de resultados. Es la única cláusula opcional, las otras dos son obligatorias.

La sintaxis del lenguaje EJB QL es muy extensa y aquí vamos a exponerla brevemente. En la documentación de la especificación J2EE podremos consultarla al completo.

115

5
5.4.1. Cláusula “SELECT”

Beans de entidad

Puede devolver diferentes valores según el tipo de método en el que se utilice:

Métodos buscadores. Sólo pueden devolver beans del mismo tipo que los creados por su interfaz inicial. Por lo tanto, el tipo de la cláusula “SELECT” debe coincidir con el nombre de esquema abstracto del EJB.

Métodos de selección. Pueden devolver cualquiera de los esquemas abstractos definidos en el descriptor de despliegue.

Podemos utilizar la palabra clave opcional “DISTINCT” para descartar valores duplicados de la consulta. 5.4.2. Cláusula “FROM” Esta cláusula se utiliza para determinar el origen de la información a obtener. Veamos un ejemplo para entender los detalles:

SELECT OBJECT(u) FROM Usuarios AS u WHERE u.login = 'juan' AND u.password = '1424'

En nuestro ejemplo, declaramos una variable de tipo “Usuarios”. No se trata del nombre del bean, en una consulta EJB QL tenemos que utilizar el nombre especificado en la etiqueta “<abstract-schema-name>” del descriptor de despliegue. Claro que, para simplificar, se suele utilizar el mismo nombre que el nombre del EJB. 5.4.3. Cláusula “WHERE” Esta cláusula es opcional y sirve para indicar una expresión que limite los resultados de la consulta. La expresión puede ser una combinación de expresiones mediante las palabras “AND” y “OR”. También podemos incluir los literales “TRUE” y “FALSE”, y operadores como “BETWEEN”, “IN” o “LIKE”. La igualdad se expresa con el símbolo “=” y la no igualdad con "<>".

116

5
selección. Si tenemos un buscador como el siguiente:

Beans de entidad

Cuando la consulta necesite parámetros, éstos se incluyen con el signo de interrogación seguido del número de orden en que aparece el parámetro en el método buscador o de

public Usuarios findByLogin(String login, String password);

La consulta a utilizar sería la siguiente:

SELECT OBJECT(u) FROM Usuarios AS u WHERE u.login = ?1 AND u.password = ?2

5.5. LAS CLAVES PRIMARIAS Todo bean de entidad debe tener una clave primaria que lo identifique de forma única que se representa mediante una clase. Dicha clase contendrá la información necesaria para encontrar su entidad en el almacén persistente y tanto el cliente como el contenedor la utilizarán cuando necesiten encontrar una determinada instancia. Esta clase tiene que cumplir determinados requisitos que veremos a continuación. En el caso de los beans de tipo BMP, los requisitos son:

La clave primaria puede ser cualquier tipo de objeto Java que se pueda codificar, es decir, que implemente la interfaz “java.io.Serializable”.

El bean debe proporcionar implementaciones de los métodos “hashCode()” y “equals()”.

La clave primaria debe ser un valor único dentro del conjunto de todos los beans.

Adicionalmente, hay algunos requisitos extra para los beans de tipo CMP. El contenedor es el responsable de manipular los beans y necesita poder crear una clave primaria. Para ello, la clase de la clave primaria debe suministrar un constructor público sin argumentos. El contenedor también necesita asociar el estado del bean con el estado de la clase de clave primaria y viceversa. Para que sea posible, la especificación proporciona dos métodos diferentes que proporcionan clases clave para beans CMP. El primero es válido para cualquier

117

5
el caso concreto de un único campo.

Beans de entidad

caso en general, con independencia del número de campos, mientras que el segundo es para

El primer método realiza la asociación utilizando una convención de nombres: los campos públicos de la clase de clave primaria se corresponden con los campos públicos equivalentes de la clase del bean. Por ejemplo, dado un bean de entidad llamado “Usuarios” y cuya clave primaria está compuesta por los campos “empresa” y “usuario”, definiremos una clase de clave primaria llamada “UsuariosPK” que necesitará los dos correspondientes campos (del mismo tipo y con el mismo nombre). La clase de la clave primaria sería como sigue:

package paquete; public class UsuariosPK implements java.io.Serializable { private String empresa; private Integer usuario; public UsuariosPK() { } public UsuariosPK(String empresa, Integer Usuario) { this.empresa = empresa; this.usuario = usuario; } public String getEmpresa() { return this.empresa; } public Integer getUsuario() { return this.usuario; } public int hashCode() { return (empresa+usuario).hashCode(); } public boolean equals(Object obj) { if (obj==null || !(obj instanceof UsuariosPK)) { return false; } UsuariosPK pk = (UsuariosPK) obj; return this.empresa.equals(pk.getEmpresa()) && this.usuario == pk.getUsuario(); } }

118

5
suministradas por Java.

Beans de entidad

Es muy importante tener en cuenta que una vez que hayamos asociado un bean de entidad a una clave primaria, no debemos reutilizar el mismo objeto de clave primaria para otro bean. Para evitarlo, no debemos definir métodos “set... ()” en las clases de clave primaria. Para el segundo método no es necesario definir una nueva clase, ya que, al tratarse de una clave primaria de un único campo, la clase para dicha clave puede ser cualquiera de las

Para los beans de entidad de tipo BMP tendremos que especificar la clase de la clave primaria en el descriptor de despliegue. Siguiendo con la clase del ejemplo anterior, la especificación de la clave primaria del descriptor sería la siguiente (tanto para beans BMP como CMP):

<prim-key-class>paquete.UsuariosPK</prim-key-class>

En el caso de que la clave estuviera formada por un único campo, supongamos que sea de tipo texto, el descriptor sería como sigue:

<prim-key-class>java.lang.String</prim-key-class>

Por último, para un bean de entidad de tipo CMP que utiliza un único campo para la clave primaria, especificaremos en el descriptor de despliegue el campo del bean que contiene la clave primaria. El tipo del campo debe ser el mismo que el tipo de clave primaria. A continuación podemos ver un ejemplo:

<primkey-field>usuario<primkey-field>

119

5
5.6. LAS RETROLLAMADAS DEL CONTENEDOR lectura, modificación y borrado. Los métodos correspondientes son:

Beans de entidad

El acceso al almacén de datos está compuesto por cuatro tipo de operaciones: creación,

Para cada una de estas operaciones existe un tipo de retrollamada en los beans de entidad.

− − − −

“ejbCreate()” y “ejbPostCreate”. Creación. “ejbLoad()”. Lectura. “ejbStore()”. Modificación. “ejbRemove()”. Borrado.

Los métodos de retrollamada se definen igualmente tanto para los beans CMP como BMP. Por el contrario, la implementación es diferente:

En los beans de tipo BMP es nuestra responsabilidad escribir el código correspondiente a la operación que debe realizarse en cada método.

En los beans de tipo CMP los métodos de retrollamada suelen dejarse vacíos (con excepción del método “ejbCreate()”), dado que es responsabilidad del contenedor implementar la funcionalidad necesaria de cada método en cuestión.

5.6.1. Creación Cuando se invoca el método “create()”, el estado se inserta en la base de datos y pasa a estar disponible para todos los clientes. El método “create()” se define en la interfaz inicial del bean y puede estar sobrecargado. Debe devolver la interfaz remota del bean para que cuando el cliente lo invoque, mediante la interfaz inicial, obtenga una referencia a dicho bean para poder utilizar sus métodos de empresa. De igual forma, este método debe lanzar la excepción “java.rmi.RemoteException”, pero sólo en el caso de los métodos remotos (recordemos que los métodos locales no usan RMI). También deben lanzar la excepción “javax.ejb.CreateException”, que se utilizará en caso de que haya algún problema en la creación. Por cada método “create()” que se defina en la interfaz inicial, deben existir dos métodos

120

5
contenedor pueda realizar la retrollamada. escribir en el método irá en función del tipo de persistencia del bean:

Beans de entidad

que coincidan, en número y tipo de argumentos, en la clase de implementación. Dichos métodos deben llamarse “ejbCreate()” y “ejbPostCreate()”, y deben ser públicos para que el

El tipo de retorno del método “ejbCreate()” debe ser la clase de la clave primaria. El código a

Para los beans CMP, los parámetros del método se utilizarán para inicializar los campos de estado.

Para los beans BMP, los parámetros se utilizarán para inicializar los campos de estado y se escribirá el código correspondiente (normalmente utilizando JDBC) para almacenar los datos en el almacén de datos.

Por otra parte, el tipo de retorno del método “ejbPostCreate()” debe ser “void”. Este método es invocado después “ejbCreate()” y, en la mayoría de los casos, suele dejarse vacío. 5.6.2. Lectura El método de retrollamada relacionado con la carga de datos desde el almacén se llama “ejbLoad()”. En el caso de los beans de tipo CMP el método se dejará vacío normalmente, a menos que queramos realizar algún tratamiento adicional, ya que, es responsabilidad del contenedor. Por el contrario, para los beans BMP tendremos que escribir el correspondiente código que realice la carga de los datos desde el almacén. 5.6.3. Modificación La actualización de la información se realiza mediante el método de retrollamada “ejbStore()”. La llamada a determinados métodos de negocio ocasionará que el contenedor invoque el método de retrollamada cuando necesite que el bean sincronice su estado con el almacén de datos. En el caso de los beans de tipo CMP este método se suele dejar vacío, mientras que para los beans BMP habrá que escribir el código correspondiente para que se guarde el estado del bean en el almacén de datos.

121

5
5.6.4. Borrado sea la de eliminar el estado del almacén de datos.

Beans de entidad

El método “remove()” es utilizado para eliminar un bean de entidad. Al contrario de los beans de sesión, la eliminación de un bean de entidad implica que éste se elimine en el almacén de datos. No debemos invocar el método “remove()” a menos que nuestra intención

El método de retrollamada correspondiente es “ejbRemove()” y en el caso de los beans de tipo CMP se suele dejar vacío. Por el contrario, en los beans BMP es necesario escribir el código necesario para interactuar con el almacén de datos.

5.7. LOS MÉTODOS BUSCADORES Ya hemos visto que los beans de entidad representan datos compartidos entre todos los clientes. Como es lógico, existe un mecanismo para que dichos clientes tengan acceso a un determinado bean de entidad. Con los beans de sesión no ocurría esto, puesto que el cliente obtiene acceso al bean cuando se crea y nadie más lo puede utilizar. Por el contrario, un bean de entidad puede ser creado por un cliente y utilizado por todos los demás, y para ello, cada uno de estos clientes debe ser capaz de encontrarlo. La especificación EJB define un mecanismo denominado método buscador y pueden definirse tantos como sean necesarios. Estos métodos se declaran en la interfaz inicial del bean de entidad y sirven para localizar un bean o una colección de ellos. Los métodos buscadores, por convención, se suelen nombrar empezando por “find, como por ejemplo “findByLogin()” o “findAll()”. Pueden utilizar parámetros para especificar los detalles de la búsqueda. Los métodos buscadores, al igual que el resto de métodos remotos, declararán que pueden lanzar la excepción “java.rmi.RemoteException”. Adicionalmente, también deben declarar la excepción “java.ejb.FinderException”. Los métodos buscadores que devuelven como máximo un único resultado, tendrán como tipo de retorno la interfaz remota del bean. El ejemplo más claro es el caso del buscador para la clave primaria; si tenemos un bean cuya clase de implementación se llama “UsuariosBean” y la clave primaria es un entero, el método “findByPrimaryKey(...)” lo definiremos en la interfaz “paquete.UsuariosHome”, recibirá un parámetro del tipo de la clase de la clave primaria y su tipo de retorno será “paquete.Usuarios”. En caso de que no se encuentre ninguna entidad, este tipo de que métodos es una lanzará subclase la de excepción la clase “javax.ejb.ObjectNotFoundException”,

122

5
“javax.ejb.FinderException”. devolverá una enumeración (o colección) vacía.

Beans de entidad

En el caso de métodos buscadores que pueden devolver cero o más resultados, el tipo de retorno será “java.util.Enumeration” o “java.util.Collection”. Un ejemplo posible sería el de un método buscador por nombre de usuario (puede haber más de uno). Si un buscador de este tipo no encuentra ninguna entidad, no se lanzará ninguna excepción, simplemente

La especificación EJB requiere que todos los beans de entidad declaren un buscador llamado “findByPrimaryKey()” con un único parámetro y que sea del mismo tipo que la clase de clave primaria. Este método debe devolver la instancia del bean de entidad con dicha clave primaria o generar una excepción “javax.ejb.ObjectNotFoundException”. El resto de métodos buscadores son opcionales y podrían no existir. En el caso de los beans de tipo CMP, la implementación de los métodos buscadores es responsabilidad del contenedor y no necesitaremos escribir ningún código. Nuestra labor como desarrolladores del bean quedará limitada a escribir la consulta en el descriptor de despliegue utilizando el lenguaje EJB QL. Por el contrario, en los beans de tipo BMP tendremos que proporcionar la implementación de los métodos buscadores en la clase de implementación del bean. Dicho método tendrá parámetros idénticos y tendrá un nombre que coincida, según la siguiente convención: si el método buscador se denomina “findXXX()”, la implementación del método se denominará “ejbFindXXX()”. El tipo de retorno para un método buscador que tiene como máximo un resultado será una instancia de la clase de clave primaria para esa entidad y el tipo de retorno para una implementación de método buscador que tiene cero o más resultados será una implementación concreta de “Collection” o “Enumeration”, según el tipo de retorno del correspondiente método buscador de la interfaz inicial. Los elementos de “Collection” o “Enumeration” serán instancias de las clases de clave primaria de las entidades encontradas.

123

5
5.8. ACTIVACIÓN Y PASIVACIÓN “ejbActivate()” y “ejbPassivate()”.

Beans de entidad

Para terminar con las retrollamadas, nos quedan por describir las dos siguientes:

El método “ejbActivate()” notifica que la instancia de bean de entidad ha sido asociada a una identidad del almacén de datos. Por el contrario, el método “ejbPassivate()” se invocará para notificar que el bean de entidad está siendo disociado de dicha entidad. La implementación de estos métodos suele dejarse vacía, sin embargo, en algunas ocasiones puede interesarnos añadirles código para realizar algún tipo de gestión.

5.9. SIGAMOS CON EL EJEMPLO En el tema anterior iniciamos un ejemplo conjunto sobre los beans de entidad y los beans de sesión. Pospusimos la parte correspondiente al bean de entidad hasta que supiéramos qué es y de qué se compone. Ya estamos listos para ponernos a trabajar. El bean de entidad que proponemos va a ser un bean con persistencia gestionada por el contenedor. No vamos a escribir código Java, no utilizaremos JDBC ni sentencias SQL, pero sí que utilizaremos el lenguaje EJB QL para uno de los métodos buscadores. Lo primero que haremos será ejecutar el entorno de desarrollo NetBeans. Una vez dentro, el proyecto “ejemplo2” debería estar creado y de no ser así procederemos a crearlo. Recordemos que en el tema anterior mencionamos que todas las clases e interfaces las crearíamos dentro del paquete “gestion”. 5.9.1. El bean de entidad En primer lugar vamos a crear la clase y las dos interfaces que necesitará nuestro EJB de entidad. Utilizaremos el botón derecho del ratón sobre el nodo “gestion” y seleccionamos la opción “New” y subopción “Java Class”. Esta operación la realizaremos tres veces y los nombres que emplearemos serán los siguientes: “LocalClientesHome”, “LocalClientes” y “ClientesBean”.

124

5
package gestion; import javax.ejb.*; throws javax.ejb.FinderException;

Beans de entidad

Seguidamente, editaremos la clase “LocalClientesHome” y escribiremos el siguiente código:

public interface LocalClientesHome extends javax.ejb.EJBLocalHome { public gestion.LocalClientes findByPrimaryKey(java.lang.Integer aKey) public LocalClientes create(java.lang.Integer cliente, java.lang.String nombre) throws javax.ejb.CreateException; public java.util.Collection findAll() throws javax.ejb.FinderException; }

Para la clase “LocalClientes”, su código será:

package gestion; import javax.ejb.*; public interface LocalClientes extends javax.ejb.EJBLocalObject { public gestion.ClienteDetalle getClienteDetalle(); public void modify(gestion.ClienteDetalle clienteDetalle); }

Por último, a la clase “ClientesBean”, que es la clase de implementación del bean, le escribimos el siguiente código:

package gestion; import javax.ejb.*; public abstract class ClientesBean implements javax.ejb.EntityBean { private javax.ejb.EntityContext context; public void setEntityContext(javax.ejb.EntityContext aContext) { context=aContext; } public void ejbActivate() { } public void ejbPassivate() { } public void ejbRemove() { }

125

5
public void unsetEntityContext() { context=null; } public void ejbLoad() { } public void ejbStore() { } public abstract java.lang.Integer getCliente(); public abstract void setCliente(java.lang.Integer cliente); public abstract java.lang.String getNombre(); public abstract void setNombre(java.lang.String nombre); public java.lang.Integer ejbCreate(java.lang.Integer

Beans de entidad

cliente,

java.lang.String

nombre) throws javax.ejb.CreateException { this.setCliente(cliente); this.setNombre(nombre); return cliente; } public void ejbPostCreate(java.lang.Integer cliente, java.lang.String nombre) throws javax.ejb.CreateException { } public gestion.ClienteDetalle getClienteDetalle() { return new ClienteDetalle(this.getCliente(), this.getNombre()); } public void modify(gestion.ClienteDetalle clienteDetalle) { this.setNombre(clienteDetalle.getNombre()); } }

Compilaremos la clase e interfaces anteriores y ya podemos compilar la clase de implementación del bean de sesión del ejemplo del tema anterior. Recordemos que dejamos sin compilar la clase “MtoClientesBean” debido a que hacía referencia a las interfaces del bean de entidad que acabamos de crear.

126

5
5.9.2. Desplegando la segunda aplicación

Beans de entidad

Ya estamos listos para crear la aplicación web que se compone del módulo EJB con los dos beans. Nos aseguraremos de que el servidor de aplicaciones se está ejecutando y, a continuación, ejecutaremos la herramienta de despliegue “deploytool”. Una vez dentro, lo primero que tenemos que hacer es crear la aplicación J2EE. Para ello, seleccionaremos en el menú la opción Archivo, después la opción Nuevo y por último la opción Aplicación... Aparecerá una caja de diálogo solicitándonos el nombre del fichero y la descripción de la aplicación. Como fichero utilizaremos “/home/alumno/cursoEJB/ejemplo2/ejemplo2b.ear” si estamos en Linux, y “c:\cursoEJB\ejemplo2\ejemplo2b.ear” si estamos en Windows. Le dejaremos la descripción que nos sugiere por defecto y pulsaremos Aceptar para finalizar. Lo primero que haremos será añadir el bean de entidad. Para ello, pulsaremos el botón izquierdo del ratón sobre el nodo “ejemplo2b”, que es la aplicación recién creada, para seleccionarlo. En el menú Archivo seleccionaremos las opciones Nuevo y Enterprise bean… Nos aparecerá un asistente que nos guiará a través del proceso de creación. Nos detendremos sólo en aquellas ventanas que tengan datos trascendentes. En las demás podremos simplemente pulsar el botón Siguiente >. Veamos las ventanas principales:

127

5
es una clase auxiliar que forma parte del bean de entidad.

Beans de entidad

En la figura podemos ver que no debemos olvidar añadir la clase “ClienteDetalle”, puesto que

En la figura anterior podemos ver que hemos de marcar los campos que nos interesa que sean persistentes, en nuestro caso son “cliente” y “nombre”. También hemos de prestar atención a seleccionar el campo “cliente” como la clase de la clave primaria. El botón

128

5
buscadores. Podemos verlo en la siguiente figura:

Beans de entidad

Buscar/seleccionar consultas... nos va a permitir escribir el código de los métodos

En nuestro caso, sólo tenemos dos métodos buscadores, que son:

“findByPrimaryKey(Integer cliente)”. La herramienta deploytool lo va a describir en el descriptor de implementación porque en la figura anterior le indicamos, a esta última, las características de la clave primaria. No necesitamos escribir código EJB QL debido a que el contenedor es capaz de generarlo por sí mismo.

“findAll()”. La herramienta “deploytool” también lo describirá en el descriptor, pero al contrario que el anterior, el contenedor no tiene forma de saber qué queremos buscar, por lo que hemos de escribir el código EJB QL adecuado a lo que nos interese que haga la consulta.

Tras los pasos anteriores, el proceso de creación del módulo EJB y de adición del bean de entidad, habrán terminado, exceptuando algunos detalles que vamos a ver seguidamente. Seleccionaremos el nodo moduloEJB que acaba de aparecer, y nos moveremos a la pestaña General. En ella veremos el botón Preferencias específicas de Sun..., lo pulsaremos y aparecerá una ventana en la que tendremos que añadir alguna información adicional relacionada con la persistencia, pero no pondremos nada de momento. En lugar de ello, pulsemos el botón Crear asignaciones en base de datos... y completemos una nueva

129

5
ventana según vemos en la siguiente figura:

Beans de entidad

Cuando pulsemos el botón Aceptar de la ventana de la figura anterior, ésta se cerrará y la información de las columnas se habrá rellenado automáticamente en la ventana que teníamos abierta previamente y que podemos ver a continuación.

130

5
elimine la aplicación.

Beans de entidad

En la lista de campos que nos muestra, hemos modificado la longitud del campo “nombre” a 50 caracteres, ya que, el valor por defecto es excesivo. También haremos uso del botón Preferencia para la generación de tablas para permitir que se cree la tabla automáticamente cuando se despliegue la aplicación, y para evitar que se pierda cuando se

Es muy importante ser extremadamente cuidadoso si se están haciendo pruebas con una base de datos en explotación y sobre tablas con información importante debido a que, por defecto, la casilla Eliminar tablas al anular implementación estará seleccionada y eso implica que se elimine la tabla cuando se elimine la aplicación del servidor. El aspecto de la ventana de la que estamos hablando es el siguiente:

Lo próximo será añadir el bean de sesión al módulo EJB. Pulsaremos el botón izquierdo del ratón sobre el nodo moduloEJB y en el menú Archivo seleccionaremos las opciones Nuevo y Enterprise bean... Nos aparecerá un asistente que nos guiará a través del proceso de creación. Al igual que en casos anteriores, sólo iremos viendo las ventanas más importantes. La primera de ellas es la que nos permite indicar el contenido y en ella podemos ver que ya están la clase ayudante “ClienteDetalle” y la clase e interfaces del bean de entidad: “ClientesBean”, “LocalClientes” y “LocalClientesHome”. Ahora tendremos que añadir la clase e interfaces del bean de sesión, que son: “MtoClientes”, “MtoClientesBean” y “MtoClientesHome”, como se muestra en la siguiente figura.

131

5

Beans de entidad

En la ventana que se muestra en la figura anterior, hemos de tener en cuenta que el bean de sesión que estamos añadiendo es sin estado (“Stateless Session”) y que sólo dispone de interfaces remotas, al contrario de lo que sucedía con el bean de entidad, que sólo ofrecía

132

5
interfaces locales.

Beans de entidad

Tras finalizar el asistente para la adición del bean a nuestro módulo EJB, tendremos que realizar aún algunas labores previas a poder desplegar la aplicación J2EE. Recordaremos que el bean de sesión que acabamos de añadir hace uso del bean de entidad, lo que significa que tenemos que indicarle a la herramienta “deploytool” la información necesaria para que ésta sea capaz de añadirla al fichero de despliegue. Seleccionaremos el nodo “MtoClientes” y a continuación nos moveremos a la pestaña “Referencias de EJB”. En ella podemos ver una lista (vacía en este momento) con las referencias a otros beans. Pulsaremos el botón Agregar... y rellenaremos los datos según se muestra en la siguiente figura:

133

5
pulsaremos el botón Preferencias específicas de Sun.... “MtoClientes”, y ponerle el valor “ejb/MtoClientes”.

Beans de entidad

Por último, seleccionaremos el nodo “moduloEJB”, nos iremos a la pestaña General y

En esta ventana tendremos que modificar el nombre JNDI, que por defecto tendrá el valor

Ya hemos terminado de crear la aplicación, ahora ha llegado el momento de desplegarla en el servidor. Para ello, seleccionaremos el nodo “ejemplo2b” y utilizaremos el menú Herramientas y la opción Implementar... Se nos mostrará una ventana en la que tendremos que elegir el servidor de aplicaciones e indicar el nombre y contraseña del administrador de dicho servidor. Seguidamente pulsaremos el botón Aceptar y comenzará el proceso de despliegue. Iremos viendo una consola en la que se mostrarán mensajes relativos al proceso. Una vez finalizado el despliegue de la aplicación habremos terminado el ejemplo por completo. Ahora podemos probarla abriendo el navegador web y apuntando a la dirección “http://localhost:8080/ejemplo2”. Recordemos que la aplicación web cuyo contexto es “ejemplo2” la desarrollamos en el tema anterior, y que esta nueva aplicación sólo se compone de beans, no tiene ningún módulo web por el que puedan acceder los usuarios.

134

5
será el siguiente:

Beans de entidad

Si abrimos el navegador y apuntamos a la dirección anterior, el aspecto que nos mostrará

Probemos a crear dos clientes; el primero con código “4” y nombre “Juan”, y el segundo con código “33” y nombre “Luis”. Para ello, colocaremos los valores en los campos correspondientes y pulsaremos el botón Crear. Tras la creación de los dos, la ventana mostrará el siguiente aspecto:

Podemos probar a modificar sus nombres editando la caja de texto correspondiente y pulsando su botón Guardar modificación. Otra funcionalidad que soporta es la de eliminar clientes utilizando el enlace del código de cliente.

135

5
aprecia diferencia en los tiempos de respuesta.

Beans de entidad

En este ejemplo podemos ver que los tiempos de respuesta de la aplicación son muy buenos, máxime si tenemos en cuenta que se trata de una aplicación web. Si el servidor de aplicaciones está instalado en nuestra máquina local y tenemos una red, sería interesante probar la aplicación desde otro ordenador distinto al nuestro para que comprobemos si se

136

5
recuerde_
− −

Beans de entidad

Los enterprises javabeans de entidad representan entidades del modelo de análisis de una aplicación y nos permiten representar estado compartido y transaccional. Como ventaja adicional tenemos que el contenedor EJB nos proporcionará una serie de servicios de nivel de sistema, motivo por el cual podremos centrarnos en la programación de lógica de empresa.

El contenedor EJB puede gestionar el proceso de guardar y restaurar el estado de los beans de entidad. Esta característica recibe el nombre de persistencia gestionada por contenedor (CMP, Container Managed Persistence). No obstante, podemos desear que nuestros beans puedan gestionar la persistencia por si mismos. En este último caso hablaremos de persistencia gestionada por bean (BMP, Bean Managed Persistence).

La especificación EJB define un lenguaje denominado EJB QL (EJB Query Language). Las sentencias EJB QL se escriben en los descriptores de despliegue, y el contenedor EJB será el encargado de generar las correspondientes instrucciones para interactuar con el almacén de datos.

Las retrollamadas son invocaciones que realiza el contenedor sobre el bean. El acceso al almacén de datos está compuesto por cuatro tipos de operaciones: creación, lectura, modificación y borrado, existiendo para cada una de las cuales un método de retrollamada, exceptuando el caso de la operación de creación, que existen dos.

La especificación EJB define un mecanismo denominado método buscador y pueden definirse tantos como sean necesarios. Estos métodos se declaran en la interfaz inicial del bean de entidad y sirven para localizar un bean o una colección de ellos.

137

6
índice_

Beans controlados por mensaje. Empaquetado y roles

6.1.

INTRODUCCIÓN A LOS MDB .................................................141 6.1.1. Transacciones ...........................................................142 6.1.2. Ejemplo .....................................................................142

6.2.

EMPAQUETADO DE APLICACIONES J2EE ...............................145 6.2.1. Contenedores ............................................................145 6.2.2. Elementos a empaquetar ...........................................146 6.2.3. Paquetes ...................................................................147 6.2.3.1. Estructura de los paquetes............................147 6.2.3.2. El descriptor de despliegue ...........................148

6.3.

ROLES ..................................................................................150 6.3.1. El proveedor de productos J2EE .................................150 6.3.2. El proveedor de herramientas....................................150 6.3.3. El proveedor de componentes....................................151 6.3.4. El ensamblador de aplicaciones .................................151 6.3.5. El implementador ......................................................151 6.3.6. El administrador del sistema .....................................151

139

6
6.1. INTRODUCCIÓN A LOS MDB

Beans controlados por mensaje. Empaquetado y roles

Para el correcto entendimiento de los beans controlados por mensaje es imprescindible tener unos conocimientos básicos del Servicio de Mensajería de Java, es decir, del API JMS (Java Messaging Service), el cual no se tratará aquí por quedar fuera del ámbito de este manual. Un bean controlado por mensaje (también llamado MDB, Message Driven Bean) es un receptor de mensajes que puede consumir los mensajes de una cola o de una suscripción (o apartado) mediante el contenedor J2EE. Cuando el contenedor recibe un mensaje, invoca al bean que corresponda. Bajo el punto de vista del cliente del bean, un bean controlado por mensaje es un consumidor que se adapta al API JMS (Java Message Service) y que implementa la lógica de negocio, pero al cual sólo se puede acceder enviándole un mensaje mediante JMS. Por su parte, un bean controlado por mensaje puede comunicar con beans de sesión y de entidad. La consecuencia lógica de esta filosofía es que un bean controlado por mensaje no tiene estado conversacional con los clientes. Por el mismo motivo, y al contrario de lo que ocurría con los beans de entidad y de sesión, no tienen interfaces iniciales ni remotas. Esto se debe a que los clientes no pueden interactuar con ellos, recordemos que es el contenedor quien se encarga de invocarlos. Por otro lado, los beans controlados por mensaje tienen una limitación importante debida a que la cola o el apartado (de la suscripción) es definido en el descriptor de despliegue, en el período de implementación en lugar del período de ejecución. Además, los selectores de mensaje también son definidos en dicho descriptor. Esta situación es una característica de JMS y, aunque la mayoría de los servidores de aplicación existentes permiten saltarse esto, corremos el riesgo de depender de algún servidor en concreto si hacemos uso de sus opciones. Un bean controlado por mensaje debe implementar las interfaces

“javax.jms.MessageListener” y “”javax.ejb.MessageListener”. La lógica debe recogerse en la implementación del método “onMessage()” de “MessageListener”, y no debe generar excepciones JMS o de aplicación, si no que debe capturarlas y tratarlas. Como mínimo, debería generarlas como excepciones “EJBException”.

141

6
siguientes métodos:

Beans controlados por mensaje. Empaquetado y roles

La clase de implementación de un bean controlado por mensaje debe proveer los

− − − −

“setMessageDrivenContext()”. Informa del contexto de ejecución para el bean. “ejbCreate()”. Método invocado por el contenedor cuando el bean se crea. “onMessage()”. Método invocado por el contenedor en el que se notifica la llegada de un mensaje. “ejbRemove()”. Método invocado por el contenedor cuando el bean se va a eliminar.

6.1.1. Transacciones Para los beans controlados por mensaje existen dos tipos de gestión de transacciones:

− −

Gestionadas por contenedor. Gestionadas por bean.

Estos tipos afectan a los atributos transaccionales del método “onMessage()” y al manejo de la entrega garantizada de los mensajes. En el caso de las transacciones gestionadas por contenedor, la entrega del mensaje está garantizada. En cuanto a los atributos transaccionales, sólo se permiten dos:”NotSupported” y “Required”. Con el primero de ellos, el bean es ejecutado fuera de ninguna transacción, mientras que con el segundo se abrirá una nueva transacción. Por último, en lo que respecta a las transacciones gestionadas por bean, los límites de la transacción deben estar dentro del método “onMessage()”. La entrega del mensaje no está garantizada a menos que se utilice “javax.transaction.UserTransaction”, y en tal caso la aplicación cliente será la que demarcará los límites de la transacción. 6.1.2. Ejemplo A continuación veremos la implementación de un bean controlado por mensaje que tiene la función de crear los pedidos de los clientes. import java.util.Date; import javax.ejb.EJBException; import javax.ejb.MessageDrivenBean;

142

6
import javax.jms.MapMessage; import javax.jms.Message; import javax.jms.MessageListener; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException;

Beans controlados por mensaje. Empaquetado y roles

public class PedidoBean implements MessageDrivenBean, MessageListener { private MessageDrivenContext mdctx; private Context ctx; public void setMessageDrivenContext(MessageDrivenContext mdctx) { this.mdctx = mdctx; try { // Necesitamos la referencia al contexto para poder // localizar posteriormente el bean de gestión de pedidos ctx = new InitialContext(); } catch (NamingException e) { throw new EJBException(e); } } public void ejbCreate() {} public void onMessage(Message msg) { try { // El mensaje debe ser del tipo MapMessage, en caso // contrario se generará una excepción MapMessage pedidoMap = (MapMessage) msg; // El mensaje contiene los valores necesarios para la // creación de un pedido Date fecha = (Date) pedidoMap.getObject("fecha"); Integer cliente = new Integer(pedidoMap.getInt("cliente")); String articulo = pedidoMap.getString("articulo"); Integer cantidad = new Integer(pedidoMap.getInt("cantidad")); // Localizamos el bean de sesión encargado de la // gestión de pedidos

143

6
} catch (Exception e) {

Beans controlados por mensaje. Empaquetado y roles

LocalPedidosHome pedidosHome = (LocalPedidosHome) ctx.lookup("java:comp/env/ejb/Pedidos"); LocalPedidos pedidos = pedidosHome.create(); // Invocamos el método de negocio que crea el pedido pedidos.crearPedido(fecha, cliente, articulo, cantidad); throw new EJBException(e); } } public void ejbRemove() throws EJBException { } }

Al igual que ocurre con los beans de sesión y de entidad, es necesario el descriptor de despliegue para que la implementación sea posible. Para la creación del fichero de despliegue, bien sea mediante alguna herramienta o bien manualmente, es necesario indicar la siguiente información:

− − − − − −

La clase de implementación del bean. El tipo de bean, que en este caso se trata de un bean controlado por mensaje. Si las transacciones están gestionadas por el contenedor o por el bean. El tipo de destino, es decir, si el mensaje se va a consumir desde una cola o un apartado, así como el nombre de dicho destino. El nombre de la factoría de conexiones a utilizar. El método de acuse de recibo.

De la relación anterior, tanto el destino (cola o apartado) como la factoría de conexiones deben ser definidos en el servidor de aplicaciones para que el contenedor sea capaz de invocar a nuestro EJB cuando dicho destino reciba mensajes.

144

6
el servidor.

Beans controlados por mensaje. Empaquetado y roles

6.2. EMPAQUETADO DE APLICACIONES J2EE A lo largo de este manual hemos visto en qué consiste la especificación J2EE, concretamente la parte relacionada con los Enterprise JavaBeans, cómo desarrollar el código y ejecutarlo en

Hasta ahora no hemos profundizado en lo relacionado con el empaquetado y despliegue de las aplicaciones y de sus componentes debido a que utilizamos la herramienta deploytool que nos ha permitido abstraernos de estas tareas. Sin embargo, incluso un conocimiento básico de la tecnología J2EE debe pasar por conocer cuál es la estructura de empaquetado de una aplicación J2EE y de los distintos componentes que la forman. La especificación J2EE dicta unas normas para la estructuración y creación de las aplicaciones, incluido el empaquetado. Sabemos que dicha especificación se compone de un conjunto de especificaciones menores y que, a su vez, también proporciona directrices para el empaquetado de los componentes individuales. Cualquier aplicación J2EE se compone de los siguientes elementos:

− −

Uno o más componentes J2EE. Un descriptor de despliegue.

Uno o más módulos J2EE se empaquetan en un único módulo de implementación, que se corresponde físicamente con un archivo EAR (fichero comprimido similar a los ficheros JAR y para el que se usa la extensión EAR). 6.2.1. Contenedores J2EE hace una clara distinción entre los recursos que se pueden empaquetar en un archivo de aplicación (EAR, Enterprise Application Archive) y los recursos que se ejecutan en un contenedor. La diferencia entre ambos estriba en que el contenedor de período de ejecución intercepta las solicitudes para proporcionar servicios del nivel del sistema, mientras que el módulo de implementación es una estructura de empaquetado para componentes que se ejecutarán, en último lugar, en un contenedor de período de ejecución.

145

6

de los contenedores EJB.

Beans controlados por mensaje. Empaquetado y roles

Recordemos que la estructura de los contenedores J2EE es la siguiente:

Contenedor web. Intercepta las solicitudes recibidas de determinados protocolos (HTTP y HTTPS generalmente) y permite a los servlets y páginas JSP acceder a los recursos

Contenedor EJB. Intercepta las solicitudes en el nivel de la lógica de negocio y permite que los Enterprise JavaBeans tengan acceso a determinados API.

Contenedor cliente de aplicación. Intercepta solicitudes para las aplicaciones Java independientes, las cuales se ejecutan remotamente en una máquina virtual distinta de donde se encuentran los contenedores web y EJB.

Contenedor de applets. Intercepta solicitudes a nivel de los programas Java que se ejecutan dentro de un navegador.

6.2.2. Elementos a empaquetar Un fichero EAR se compone de uno o varios de los siguientes tipos de componentes:

Archivo WAR de aplicación web. Cada archivo WAR sólo puede contener una única aplicación web y en caso de que el archivo EAR contenga más de una, cada una de ellas habrá de tener un nombre de contexto único.

Archivo JAR de aplicación EJB. Estará compuesto por al menos un Enterprise JavaBean.

Archivo JAR de cliente de aplicación. Contendrá una única aplicación Java destinada a ejecutarse en un contenedor cliente de aplicación.

Archivo RAR de adaptador de recursos. Contendrá clases Java y las librerías nativas necesarias para implementar un adaptador de recursos de Arquitectura de Conectores Java a un sistema de información de empresa.

Cada uno de los componentes debe ser desarrollado y empaquetado por separado, junto con su correspondiente descriptor de despliegue. El archivo EAR unifica uno o más de estos componentes en un único paquete, incluyendo su propio descriptor de implementación. Sin embargo, existen componentes que no se pueden declarar dentro de los archivos EAR, a

146

6

Beans controlados por mensaje. Empaquetado y roles

pesar de ser utilizados frecuentemente. Entre ellos podemos citar las fuentes de datos JDBC. Recordemos que en algunos ejemplos de los temas anteriores teníamos componentes que necesitaban tener acceso a la fuente de datos utilizando el nombre JNDI “jdbc/CursoEJB”. En el caso de este tipo de componentes se hace necesario configurarlos y desplegarlos manualmente mediante la consola de administración del servidor. Siguiendo con nuestros ejemplos, recordemos que la definición de la fuente de datos y la asignación del nombre JNDI las realizamos mediante la consola del servidor utilizando el navegador web en la dirección “http://localhost:4848”. 6.2.3. Paquetes La construcción de una aplicación J2EE es un proceso compuesto por las siguientes fases:

Construcción de los componentes individuales como los servlets, las páginas JSP y los Enterprise JavaBeans.

Algunos de estos componentes se empaquetan en archivos con formato JAR junto con el correspondiente descriptor de despliegue de módulo J2EE. Este último se compone de uno o más componentes J2EE del mismo tipo, por lo tanto, un módulo EJB puede estar compuesto por uno o más EJB y un módulo web puede estar compuesto por múltiples servlets y páginas JSP.

Uno o más módulos J2EE se unen en un archivo EAR junto con un descriptor de despliegue para obtener la aplicación J2EE.

La aplicación J2EE se despliega en el servidor de aplicaciones. Estructura de los paquetes

6.2.3.1.

Un paquete de aplicación J2EE está compuesto por uno o varios módulos J2EE y un descriptor de despliegue llamado “application.xml” que se ubica en el directorio “META-INF”. Los archivos se empaquetan (o comprimen) utilizando el formato JAR y se almacenan en un fichero con extensión “ear”.

147

6
siguiente contenido:

Beans controlados por mensaje. Empaquetado y roles

Por ejemplo, un archivo EAR que contenga dos módulos EJB y un módulo web podría tener el

− − − −

moduloEJB1.jar moduloEJB2.jar moduloWEB.war META-INF\application.xml

El archivo EAR de la aplicación se puede crear manualmente o utilizando las herramientas que provee el propio servidor de aplicaciones. En el primer caso se trata de utilizar la herramienta “jar” del JDK y los pasos son los siguientes:

− − −

Crear un directorio para alojar los contenidos del archivo EAR.

Copiar los módulos J2EE en dicho directorio y crear el directorio “META-INF”.

Crear

dentro

del

directorio

“META-INF”

el

descriptor

de

implementación

“application.xml”.

Utilizar la herramienta “jar”.

Siguiendo con el ejemplo anterior, para crear un fichero de aplicación llamado “MiApl, utilizaríamos la herramienta “jar” con la siguiente sintaxis: jar cvf MiApl.ear moduloEJB1.jar moduloEJB2.jar moduloWEB.war META-INF 6.2.3.2. El descriptor de despliegue

El descriptor de despliegue es un fichero XML llamado “application.xml”, por lo tanto podemos editarlo con nuestro editor favorito. A pesar de ello, la forma más cómoda de manipularlo es mediante las herramientas gráficas que nos pueda suministrar nuestro servidor de aplicaciones. No obstante, es interesante que lo conozcamos por si necesitamos editarlo manualmente. El descriptor de implementación “application.xml” es muy sencillo y sólo requiere de un conjunto reducido de etiquetas. Su declaración “DOCTYPE” debe ser la siguiente: <!DOCTYPE application PUBLIC “-//Sun Microsystems, Inc.//DTD J2EE Application 1.3//EN”

148

6
“http://java.sun.com/dtd/application_1_3.dtd”>

Beans controlados por mensaje. Empaquetado y roles

La etiqueta raíz de la estructura de nodos es “<application>” y las etiquetas más importantes que puede anidar son las siguientes:

− − − −

“<icon>”. “<display-name>”. “<description>”. “<module>”.

Las tres primeras proporcionan información sobre la aplicación, mientras que la última engloba los módulos J2EE que conforman la aplicación. La etiqueta “<module>” agrupará, a su vez, etiquetas “<ejb>”, “<web>” y “<java>”, para los módulos EJB, web y programas cliente de aplicación, respectivamente. En caso de utilizar la etiqueta “<web>”, es necesario anidarle las etiquetas “<web-uri>” y “<context-root>”, para indicar el fichero que contiene el módulo web y el nombre del contexto de ejecución de la aplicación web. A continuación, podemos ver un ejemplo de un descriptor de despliegue: 6.3. ROLES

<!DOCTYPE application PUBLIC “-//Sun Microsystems, Inc.//DTD J2EE Application 1.3//EN” “http://java.sun.com/dtd/application_1_3.dtd”> <application> <display-name>Aplicación de ejemplo</display-name> <module> <ejb>moduloEJB.jar</ejb> </module> </module> <web> <web-uri>moduloWEB.war</web-uri> <context-root>/miaplicacion</context-root> </web> </module> </application> <?xml version=”1.0” encoding=”UTF-8”?>

149

6

Beans controlados por mensaje. Empaquetado y roles

La naturaleza modular de la especificación J2EE permite dividir el desarrollo de la aplicación y el proceso de despliegue en distintos roles para que más de una persona o empresa puedan intervenir en las distintas partes del proceso. El primer rol que aparece en escena está relacionado con la instalación de los productos y herramientas J2EE. Una vez instalados, el proveedor de componentes de aplicación puede desarrollar dichos componentes, los ensambladores de aplicaciones pueden ensamblarlos, y los implementadores pueden desplegarlos. En una organización pequeña la mayoría de estos roles suelen estar desempeñados por la misma persona o equipo, sin embargo, en las organizaciones grandes suelen estar distribuidos en distintos equipos. Cada rol utiliza como entrada la salida del rol precedente, hasta llegar al final del flujo de trabajo. Por ejemplo, en la fase de desarrollo de componentes el desarrollador de Enterprise JavaBeans entregará ficheros JAR que serán utilizados en la fase de ensamblaje, en la cual otro desarrollador combinará los ficheros JAR en una aplicación J2EE para crear un fichero EAR. En los siguientes apartados vamos a ver los principales roles existentes. 6.3.1. El proveedor de productos J2EE El proveedor de productos J2EE es la organización (empresa o persona) que facilita la plataforma, los API u otras características definidas por la especificación. Habitualmente se trata de proveedores de bases de datos, servidores de aplicaciones o servidores web que implementan la plataforma J2EE conforme a la especificación. 6.3.2. El proveedor de herramientas El proveedor de herramientas es la organización que desarrolla, ensambla y empaqueta herramientas que pueden ser utilizadas por los proveedores de componentes, los ensambladores y los implementadores. Un proveedor de herramientas puede suministrar herramientas que automaticen la generación de descriptores de implementación para un archivo EAR en un servidor de aplicación. Estas utilidades pueden ser independientes de la plataforma (funcionan con todos los ficheros EAR con independencia del entorno) o dependientes de la plataforma (funcionan para un determinado entorno).

150

6
6.3.3. El proveedor de componentes

Beans controlados por mensaje. Empaquetado y roles

El proveedor de componentes es la organización que crea los componentes web, los Enterprise JavaBeans, etc., para que sean usados en las aplicaciones J2EE. También existen roles, dentro de la especificación J2EE, que pueden tener características similares a las de los proveedores de componentes. Entre estos roles se incluyen los desarrolladores de documentos, autores de JSP, desarrolladores de beans de negocio y desarrolladores de adaptadores de recursos. 6.3.4. El ensamblador de aplicaciones El ensamblador de aplicaciones es la organización que recibe los ficheros JAR con los componentes de la aplicación y los ensambla en un fichero EAR. También es responsable de crear el descriptor de despliegue de la aplicación J2EE y de identificar cualquier recurso externo del que pueda depender dicha aplicación. Entre estos recursos puede haber bibliotecas de clases, roles de seguridad y entornos de nombrado. El ensamblador de aplicaciones suele utilizar las herramientas suministradas por el proveedor de productos J2EE y por el proveedor de herramientas. 6.3.5. El implementador El implementador es el responsable de implementar las aplicaciones web y EJB en el servidor (o servidores). Entre sus labores no están las de implementar un archivo de adaptador de recursos o de cliente de aplicación, pero sí la de la configuración adicional de dichos componentes que, aunque se empaqueten como parte del archivo EAR de la aplicación, no son considerados cuando se implementa la aplicación de empresa. 6.3.6. El administrador del sistema El administrador del sistema es el responsable de la configuración del entorno de red y del entorno operativo en los que se ejecutan los servidores de aplicaciones y, por lo tanto, las aplicaciones J2EE. Así mismo, es el responsable del control y mantenimiento de dichas aplicaciones.

151

6

necesarios.

Beans controlados por mensaje. Empaquetado y roles

En todos los ejemplos de este manual nosotros hemos asumido cuatro de los seis roles expuestos. Exceptuando los roles de proveedor de productos J2EE y proveedor de herramientas, hemos desempeñado los siguientes:

Proveedor de componentes. Hemos desarrollado los componentes web y EJB

Ensamblador de aplicaciones. Hemos combinado los componentes J2EE para crear nuestra aplicación final.

Implementador. Hemos desplegado las aplicaciones en el servidor verificando que los recursos externos necesarios (las fuentes de datos) estuvieran accesibles.

Administrador del sistema. Hemos instalado y configurado el servidor de aplicaciones, así como revisado el entorno operativo para verificar que las aplicaciones están accesibles por los clientes.

152

6
recuerde_

contenedor J2EE.

Beans controlados por mensaje. Empaquetado y roles

Un bean controlado por mensaje es un receptor de mensajes que puede consumir los mensajes de una cola o de una suscripción mediante el

Un

bean

controlado

por

mensaje

debe

implementar

las

interfaces

“javax.jms.MessageListener” y “”javax.ejb.MessageListener”. La lógica debe recogerse en la implementación del método “onMessage()” de la interfaz “MessageListener”.

La especificación J2EE dicta unas normas para la estructuración y creación de las aplicaciones, incluido el empaquetado. Dicha especificación se compone de un conjunto de especificaciones menores y que, a su vez, también proporcionan individuales. directrices para el empaquetado de los componentes

Uno o más módulos J2EE se empaquetan en un único módulo de implementación, que se corresponde físicamente con un archivo EAR.

La naturaleza modular de la especificación J2EE permite dividir el desarrollo de la aplicación y el proceso de despliegue en distintos roles para que más de una persona o empresa puedan intervenir en las distintas partes del proceso.

Los principales roles existentes son: el proveedor de productos J2EE, el proveedor de herramientas, el proveedor de componentes, el ensamblador de aplicaciones, el implementador y el administrador del sistema.

153

glosario_

A API. Siglas de Application Program Interface (Interfaz para programas de aplicación). Conjunto de convenciones de programación que definen cómo se invoca un servicio desde un programa. G GUI. Siglas de Graphical User Interface (Interfaz Gráfica de Usuario). Permite a los usuarios navegar e interactuar con las informaciones en la pantalla de su ordenador utilizando un ratón para señalar, pulsar y desplazar iconos y otros datos de la pantalla, en lugar de escribir palabras y frases. H HTML. Siglas de HiperText Transfer Protocol (Protocolo de Transferencia de HiperTexto). Es un lenguaje que especifica el aspecto y estructura de las páginas web. J JDBC. Abreviatura de “Java Database Connectivity”, un API Java que permite ejecutar sentencias SQL a las aplicaciones Java sobre cualquier base de datos compatible con SQL. Debido a que la mayoría de los sistemas de gestión de bases de datos soportan SQL, y a que Java se ejecuta en casi todas las plataformas, JDBC hace posible escribir una única aplicación que se pueda ejecutar en distintas plataformas e interactúe con diferentes bases de datos. M MULTITHREADING. Técnica que permite la utilización de varios threads (hilos) que se ejecutan en paralelo. Los términos empleados en español para hacer referencia a esta característica son Multihilo y Multihebra. O OPTIMIZACIÓN. Proceso mediante el cual se detectan y aplican posibles mejoras, logrando que la ejecución resulte más eficiente.

155

glosario_

P PROTOCOLO. Conjunto de normas comunes que deben ser observadas por dos elementos que desean comunicarse para poder entender los mensajes que se reciben. En general, este término se emplea para la definición de técnicas de comunicación en una red. En el caso de Internet, un ejemplo es el protocolo IP, que define el formato de los mensajes que se envían de un nodo a otro. Sobre este protocolo básico se pueden construir otros que proporcionan mayor funcionalidad, como es el caso de HTTP, que permite transmitir la información contenida en páginas web. S SQL. Es la abreviatura de Lenguaje de Consulta Estructurado (Structured Query Language). Es un lenguaje de consulta estandarizado para interactuar con bases de datos. La versión original se llamó SEQUEL (Structured English Query Language) y fue diseñada por IBM entre 1974 y 1975. La primera base de datos comercial en la que SQL se introdujo por primera vez fue la de Oracle Corporation en 1979. U URL. Siglas de Uniform Resource Locator (Localizador Uniforme de Recursos). Permite localizar o acceder de forma sencilla cualquier recurso de la red desde el navegador de la WWW.

156

bibliografía_

Scott W. Ambler y Tyler Jewell. Mastering Enterprise JavaBeans Second Edition. Ed. The Middleware Company. 2002. Paul J. Perrone. J2EE Developer's Handbook. Ed. Sams Publishing. 2003.

157

Sign up to vote on this title
UsefulNot useful