Sei sulla pagina 1di 158

ENTERPRISE JAVA BEANS

AUTOR: Juan Carlos Rubio Pineda


CREATIVE - COMMONS
Creative Commons License Deed: Reconocimiento-No comercial-Compartir bajo la misma licencia 2.5
España: Usted es libre de:
• copiar, distribuir y comunicar públicamente la obra
• hacer obras derivadas bajo las condiciones siguientes:
• Reconocimiento. Debe reconocer los créditos de la obra de la manera especificada por el autor o el
licenciador (pero no de una manera que sugiera que tiene su apoyo o apoyan el uso que hace de su
obra).
• No comercial. No puede utilizar esta obra para fines comerciales.
• Compartir bajo la misma licencia. Si altera o transforma esta obra, o genera una obra derivada,
sólo puede distribuir la obra generada bajo una licencia idéntica a ésta.
• Al reutilizar o distribuir la obra, tiene que dejar bien claro los términos de la licencia de esta obra.
• Alguna de estas condiciones puede no aplicarse si se obtiene el permiso del titular de los derechos de
autor
• Nada en esta licencia menoscaba o restringe los derechos morales del autor.
• Este resumen no es una licencia. Es simplemente una referencia práctica para entender el Texto
Legal (la licencia completa) — es un redactado inteligible por cualquiera de algunos de los términos
clave de la licencia. Se trata de una interficie amigable del Texto Legal que hay debajo. Este resumen
por si mismo no tiene valor legal, y su contenido no aparece en la auténtica licencia. Creative
Commons no es un bufete de abogados y no ofrece servicios legales. La distribución, la muestra, o el
enlace de este Resumen no crea ningun vínculo abogado-cliente. Los derechos derivados de usos
legítimos u otras limitaciones reconocidas por ley no se ven afectados por lo anterior. Esto es
un resumen legible por humanos del texto legal
• Para más información: http://creativecommons.org/licenses/by-nc-sa/2.5/es/
ÍNDICE

• Bloque I: Introducción a JEE


− Visión General
− Definiciones
• Componentes de JEE
− Aplicaciones clientes y applets
− Java Servlets, JavaServer Pages y JavaServer Faces
− Enterprise Java Beans

• Bloque II: EJB3


• Desarrollo fácil de Enterprise Applications (EA)
• Empaquetado de aplicaciones JEE5
• Líneas de desarrollo de software EJB
− Stateless Session Beans
− Stateful Session Beans
− Message Driven Beans
• EJB2.1 vs EJB3
• Java Persistence API (entities)

• Bloque III: PRÁCTICAS


BLOQUE I
Introducción a J2EE: Visión General
Visión general

• Java ha sufrido una evolución que prácticamente ha


tomado vida propia.
• Diseñado originalmente para controlar dispositivos
electrónicos, hoy es el lenguaje preferido para
aplicaciones empresariales basadas en la web
• Tres ediciones de Java
» J2SE (Java 2 Standard Edition): Contiene las API's para construir una
aplicación Java o un applet.
» J2ME (Java 2 Mobile Edition): API's para aplicaciones inalámbricas o
dispositivos pequeños (teléfonos móviles, PDA's, etc. con prestaciones
reducidas)
» J2EE (Java 2 Enterprise Edition): API's para crear aplicaciones para
arquitecturas multicapa.
Visión general

• JEE simplifica la creación de aplicaciones


empresariales, ya que la funcionalidad se encapsula en
los componentes de JEE
• JEE es una tecnología versátil, ya que los componentes
se comunican entre sí mediante métodos estándar
como HTTP, SSL, XML, RMI e IIOP.
• El diseño multicapa JEE frente a otras alternativas,
garantiza que si se efectúan cambios en la lógica de
negocio, no es necesario reconstruir TODA la
aplicación, y reinstalarla en todos los clientes.
Visión general
Visión general

• Modelo: encapsula la lógica o funcionalidad de negocio.


− Ejemplo: en una aplicación bancaria, el modelo es el conjunto de clases que nos
permiten crear y destruir cuentas, hacer transferencias, etc. El modelo debería ser
reusable con otras GUI

• Problema
− Un cambio en la implementación del modelo implica recompilación de toda la
aplicación y reinstalación en los clientes.
» Cambios de drivers de acceso a BD

− Cambio en la lógica del modelo


− Cambio de fabricante de BD

• Solución:
− Modelo en servidor intermedio
» Un cambio en la implementación del modelo sólo afecta al servidor.

− Clientes standalone
» Sólo disponen de la interfaz gráfica

» Acceden al servidor que implementa el modelo.


Visión general
BLOQUE I: Definiciones
Definiciones

• JEE: es una especificación para implementar aplicaciones de


arquitectura multicapa de tipo empresarial y aplicaciones
basadas en la Web.

• Componente JEE: Es una unidad de software funcional


autocontenida que se ensambla dentro de una aplicación JEE
con sus clases de ayuda y ficheros y que se comunica con otros
componentes. La especificación JEE define los siguientes
componentes:
− Las aplicaciones clientes y los applets son componentes que se
ejecutan en el lado del cliente.
− Los componentes java servlet y los JSP's son componentes web que se
ejecutan en el lado del servidor
− Los Enterprise Java Beans (EJB) son componentes de negocio que
se ejecutan en el servidor de aplicación, destinados al desarrollo y
despliegue de aplicaciones empresariales.
Definiciones
• Componente Web: Pueden ser servlets o páginas creadas con la
tecnología JSP y/o JavaServer Faces. JavaServerFaces se
construye sobre servlets y páginas JSP y proporciona un
framework de interfaz de usuario para aplicaciones web.

• Aplicación cliente: Se ejecuta en una máquina cliente y


proporciona un medio para que los usuarios lleven a cabo un GUI
más rico que el que puede proporcionarse por un lenguaje de
marcas (HTML, etc).

• Cliente JEE: Puede ser un cliente web (navegador) o una


aplicación cliente..

• Cliente web: Consiste de dos partes:


− Páginas dinámicas generadas por componentes web de la capa web
− Navegador web, que presenta las páginas recibidas del servidor.
Definiciones

• Contenedor: es un interfaz entre un componente y la


funcionalidad específica de bajo nivel que da soporte al
componente. Antes de que se ejecute un componente
web, enterprise bean, o componente cliente de
aplicación, debe ensamblarse en un módulo JEE y
disponerse dentro de un contenedor.
CONTENEDOR = SERVIDOR
− Contenedor web = contenedor servlet + contenedor JSP
• Servidor de aplicaciones: Servidor en red que facilita o
proporciona a los clientes aplicaciones software.
− Serv. aplicaciones = contenedor web + contenedor EJB
Definiciones

• Servlet: Es un programa Java capaz de procesar datos,


y generar una respuesta utilizando HTTP, y que es
ejecutado a través de un navegador.
• JSP (Java Server Pages): Es una página en formato
HTML que contiene código Java encerrado entre
etiquetas especiales, y que se convierte en servlet la
primera vez que se ejecuta.
• Applet: Es una pequeña aplicación cliente escrita en
Java que se ejecuta la la JVM del navegador.
Definiciones

• ¿Qué es un Java Bean?


− componente software que pueden encapsular una
funcionalidad por sí mismo y ofrecerla allí donde sea
necesario independientemente del tipo de aplicación
que se esté programando.
− Por ejemplo, un Java Bean puede ser una clase Java
que agrupe funcionalidades y propiedades utilizadas
en una aplicación WEB y poder utilizarse desde una
página JSP
• Conseguiríamos así separar:
− LÓGICA DE APLICACIÓN
− ASPECTO
Definiciones

• Diferencia entre JavaBean y EJB:


− Basados en los paquetes JavaBeans y javax.ejb
respectivamente.
− Los primeros interactúan entre ellos SÓLO dentro del mismo
espacio de nombres, mientras que los segundos interactúan
con otros componentes que pueden pertenecer a otro espacio
de nombres como objetos distribuidos.
− JavaBeans es una interfaz de SUN para construir aplicaciones
reutilizables; permite construir bloques que pueden usarse de
forma separada o en conjunción con otros, y se pueden utilizar
en la capa de cliente, mientras que los componentes EJB sólo
se utilizan en la capa de negocio, y pueden servir para
comunicación entre los componentes del servidor y una base
de datos.
Definiciones
• Componentes de negocio (Business Components): El código de negocio, que es la
lógica que resuelve o cumple las necesidades de un negocio particular, como la banca,
la venta, o la financiación, se maneja mediante enterprise beans que se ejecutan en la
capa de negocio (business tier). Representa el medio de comunicarnos con lo que
conocemos como el modelo de datos.

• Tipos de EJB:
− Beans de sesión: representa una conversación temporal con un cliente. Cuando el cliente
finaliza su ejecución, el bean de sesión y sus datos desaparecen.
− Java Persistence API / Beans de entidad: representa datos persistentes almacenados en una
fila de una tabla/relación de una base de datos. Si el cliente termina o si se apaga el servidor,
los servicios subyacentes de aseguran de grabar el bean.
• La nueva Java Persistence API ha simplificado la persistencia de los entity beans. Los nuevos entity
objects son POJOs que proporcionan una vista orientada a objetos de los datos almacenados en una
base de datos.
− Beans dirigidos por mensajes: combina las características de un bean de sesión y de un
oyente de Java Message Service (JMS), permitiendo que un componente de negocio reciba
asíncronamente mensajes JMS.

• Capa del sistema de información empresarial (EIS): La capa del sistema de información
empresarial maneja el software del sistema de información empresarial como ERP's,
BD, etc. Las aplicaciones J2EE pueden necesitar acceder a estas aplicaciones, pEj.
para acceder a sus BD.
Definiciones
• Empaquetado: Para desplegar una aplicación JEE, se empaquetan los
componentes en ficheros especiales que contienen los ficheros de las clases
relevantes y los descriptores de despliegue XML
− Estos descriptores de despliegue contienen información específica de componentes
empaquetados y son un mecanismo para configurar el comportamiento de la aplica-
ción en el momento del ensamble o del despliegue.

• Estos se empaquetan en diferentes tipos de


archivos según los distintos componentes.
− Los componentes Web se empaquetan en un archivo Web (.war) que contiene los
servlets, las páginas JSP y los componentes estáticos como las páginas HTML y
las imágenes.
• El fichero .war contiene clases y ficheros utilizados en la capa Web junto con un
descriptor de despliegue (no siempre).
− Los componentes de negocio se empaquetan en un archio Java (.jar) que contiene
los descriptores de despliegue EJB (no siempre), los ficheros de interfaz remoto
junto con los ficheros de ayuda requeridos por el componente EJB.
− Los ficheros de clases del lado del cliente se empaquetan en un fichero Java (.jar).
− Una aplicación JEE se empaqueta en un archivo enterprise (.ear) que contiene toda
la aplicación junto con el descriptor de despliegue (no siempre) que proporciona
información sobre la aplicación y todos sus componentes.
Definiciones

• Ejemplo de arquitectura JEE


Capa de Interfaz de Usuario Capa de Lógica Capa de Datos

Contenedor
Cliente EJBs
(HTML, (Sun App Serv,
JavaScrip Glassfish,
t, Petición HTTP
Contenedor JBoss, …)
Applets, Servidor Servlets /JSP
PDF, etc) Web
(MSIE, Respuesta HTTP
(Sun App. Serv,
(HTML+ JavaScript Base de Datos
NSN, (Apache) Glassfish,
PDF, ZIP, etc.) (Oracle)
Java Tomcat…) Clases,
PlugIn JavaBeans,
Acrobat SQLJs sobre
Reader) una JVM
(Sun App. S.,
Glassfish…)
BLOQUE II
Contenido
Desarrollo fácil de Enterprise Applications (EA)
Empaquetado de aplicaciones JEE5
Líneas de desarrollo de software EJB
Stateless Session Beans
Stateful Session Beans
Message Driven Beans
EJB2.1 vs EJB3
Java Persistence API (entities)
Desarrollo fácil de EAs

• JEE5 elimina gran parte de tareas engorrosas


necesarias en modelos Java anteriores.
• Con JEE5, los descriptores de despliegue XML son
ahora opcionales.
• En lugar de ello, empleamos Annotations
(anotaciones, también llamados metadatos)
directamente en un POJO, dentro del código fuente en
el que estemos trabajando.
• Se reconocen porque empiezan por @
Desarrollo fácil de EAs

• Las anotaciones se usan para incrustar datos en un


programa que de otra forma tendrían que ser
proporcionados en un fichero por separado.
• JEE5 proporciona anotaciones para estas tareas:
− Definir y usar Web Services
− Desarrollar aplicaciones EJB
− Mapeo de clases Java a XML
− Mapeo de clases Java a Bases de Datos
− Mapeo de métodos a operaciones
− Especificación de dependencias externas
− Especificación de información de despliegue, incluyendo
seguridad.
Desarrollo fácil de EAs

• Algunos beneficios inmediatos de JEE5


− Ya no son necesarios los marcadores:
• extends java.rmi.Remote
• throws java.rmi.RemoteException
− Ya no es necesario que exista un fichero application.xml en un
paquete que contenga una aplicación JEE5; el servidor
determina el tipo de cada módulo examinando el contenido del
paquete.
− Ya no es necesario incluir un fichero de MANIFEST en los
paquetes de librerías .JAR
Empaquetado en JEE5

• Empaquetado de aplicaciones JEE5


− Las aplicaciones web usan: .WAR
− Los ficheros .RAR son Resource Adapters
− El directorio lib contiene ficheros compartidos .JAR
− Un fichero .JAR con Main-Class se considera una aplicación
cliente
− Un fichero .JAR con la anotación @stateless es considerada
una aplicación EJB
Empaquetado en JEE5

• Aplicaciones que ya no requieren descriptores de


despliegue:
− Aplicaciones EJB (.JAR)
− Aplicaciones web exclusivamente JSP
− Aplicaciones clientes (.JAR)
− Enterprise Applications (.EAR)
Líneas de desarrollo EJB

• ¿Qué es un Enterprise Bean?


− Es un componente del extremo del servidor que encapsula la
lógica de negocio de una aplicación. La Lógica de negocio es
el código que cumplimenta el propósito de la aplicación.
− Ejemplo: en una aplicación de control de inventario, el
enterprise bean podría implementar la lógica de negocio de
métodos que se llamasen compruebaNivelInventario o por
ejemplo solicitaProducto. Invocando a estos métodos, los
clientes remotos podrían acceder a los servicios de inventario
proporcionados por la aplicación.
Líneas de desarrollo EJB

• Beneficios de EJB
− Simplifican el desarrollo de aplicaciones grandes y/o
distribuídas. Razones:
• El contenedor proporciona servicios a nivel de sistema a los enterpise
beans, por lo que el desarrollador puede dedicarse a resolver
problemas de negocio. Ejemplo de esos servicios: la gestión de
transacciones y las autorizaciones de seguridad.
• Como los EJBs (y no los clientes) contienen la lógica de negocio de la
aplicación, el programador de la capa cliente, puede dedicarse a
mejorar la presentación hacia el cliente. Esto permite construir clientes
ligeros, lo cual es especialmente interesante para dispositivos móviles.
• Al ser los EJBs componentes portables, pueden construirse nuevas
aplicaciones ensamblando Beans existentes.
Líneas de desarrollo EJB

• ¿Cuándo debemos usar EJBs?


− Cuando la aplicación deba ser escalable.- Si el número de
usuarios de la aplicación puede ser elevado, cabe la
posibilidad de tener que distribuir los componentes de la
aplicación entre múltiples máquinas. No sólo pueden
ejecutarse EJBs en diferentes máquinas, sino que además, su
localización es transparente a los clientes.
− Cuando las transacciones deban asegurar integridad de
datos: Los enterprise beans soportan transacciones, que son
los mecanismos que administran los accesos concurrentes de
objetos compartidos.
− Cuando la aplicación tenga clientes de tipos variados: Con
pocas líneas de código, cualquier cliente remoto puede
localizar enterprise beans.
Líneas de desarrollo EJB

• La API EJB 3.0 se ha simplificado muchísimo;


Beneficios de la nueva API EJB 3.0
− Se requieren menos clases e interfaces: El EJB Home ya no se necesita
y ya no hay que implementar el interfaz javax.ejb.SessionBean para
codificar un bean de sesión.
− Descriptores de despliegue opcionales: Uso de anotaciones.
− Búsquedas simples: Ya no se necesitan las APIs JNDI (Java Naming and
Directoy Interface) ni en el servidor ni en el cliente. Se ha añadido un
método de búsqueda en el interfaz EJBContext, permitiendo buscar un
objeto dinámicamente dentro del espacio de nombres JNDI.
− Persistencia ligera y simplificada para el mapeo de objetos
relacionales: la nueva Java Persistence API ha simplificado la
persistencia de los entity beans. Los nuevos entity objects son POJOs que
proporcionan una vista orientada a objetos de los datos almacenados en
una base de datos.
− Interceptors: Son objetos que se usan para interceptar una llamada a un
business method.
Líneas de desarrollo EJB
• Algunas annotations que pueden usarse en desarrollo de software EJB:
− @Stateless, @Stateful. Para indicar si es un componente bean de sesión stateless o stateful
− @PostConstruct, @PreDestroy, @PostActivate, @PrePassivate. Indicación un método como de
event callback *
− @EJB. Usado en un cliente JEE para referenciar instancias de Enterprise Beans.
− @PersistenceUnit. Se usa para expresar una dependencia de un EntityManagerFactory.
− @PersistenceContext. Se usa para expresar una dependencia de un EntityManager.
− @WebServiceRef. Se usa en un cliente para referenciar web services.
− @Resource. Para todos los demás recursos no cubiertos por @EJB o @WebServiceRef
− @Timeout. Especifica un método timeout sobre un componente que use servicios de temporizador
(container-managed timer services).
− @MessageDriven. Especifica un bean message-driven. Un bean message-driven es un consumidor
de mensajes que puede ser llamado por su contenedor.
− @TransactionAttribute. Aplica un atributo transaction a todos los métodos de un interfaz de negocio
o a métodos de negocio individuales de un bean
− @TransactionManagement. Declara si un bean tendrá transacciones container-managed o
bean-managed (controladas por contenedor o por bean).
− @RolesAllowed, @PermitAll, and @DenyAll. Permisos de métodos.
− @RolesReferenced. Declara roles de seguridad referenciados en el código del bean
− @RunAs. Usa un rol de seguridad especificado para ejecutar un método.
*
Listeners o callback methods son métodos destinados a recibir invocaciones de proveedores de persistencia a varios niveles del ciclo de vida de la
entidad (@Prepersist, @Postload, @Postpersist).
Líneas de desarrollo EJB :
EJB 2.1 Vs EJB 3.0

• Características EJB 2.1


− Muy potente, pero complejo de usar
− Demasiadas clases e interfaces.
− Java Naming an Directory Interface (JNDI) para búsquedas.
− Interfaces Javax.ejb
− Descriptores de despliegue
− Modelo de programación complicado y pesado
− Incremento de costes
…..
…..
Líneas de desarrollo EJB :
EJB 2.1 Vs EJB 3.0

• Desarrollo simplificado con EJB 3.0


− La tecnología EJB es ahora más sencilla de aprender y usar.
− Menor número de clases e interfaces
− Inyección de dependencias (dependency injection)
− Búsquedas simples
− No se requieren interfaces de contenedor
− No se requieren descriptores de despliegue
− Persistencia simplificada
− Mapeo objeto/relacional
− Incremento de la productividad del programador.
Líneas de desarrollo EJB :
EJB 2.1 Vs EJB 3.0

• La mejor forma de comprobar los beneficios de JEE5


respecto de J2EE en la línea de desarrollo EJB puede
ser mediante ejemplos. Sigamos con más ejemplos
incrementando el nivel de detalle.
• El ejemplo 1, muestra el código fuente de una
aplicación que use un hipotético session bean usando
la API EJB 2.1.
• El ejemplo 2, muestra el código equivalente usando la
API EJB 3.0, resaltando en negrita las nuevas
características.
Líneas de desarrollo EJB :
EJB 2.1 Vs EJB 3.0

• Ejemplo EJB 2.1


public class PayrollBean implements javax.ejb.SessionBean {
SessionContext ctx;
DataSource empDB;
public void setSessionContext(SessionContext ctx) {
this.ctx = ctx;
}
public void ejbCreate() {
Context initialContext = new InitialContext();
empDB = (DataSource)initialContext.lookup(“java:comp/env/jdbc/empDB”);
}

public void ejbActivate() {}


public void ejbPassivate() {}
public void ejbRemove() {}
public void setBenefitsDeduction (int empId, double deduction) {
...
Connection conn = empDB.getConnection();
}
...
} // **** * Y ADEMÁS, ES NECESARIO UN DESCRIPTOR DE DESPLIEGUE * ***
Líneas de desarrollo EJB :
EJB 2.1 Vs EJB 3.0

• Ejemplo EJB 2.1: Descriptor ejb-jar.xml necesario:


<session>
<ejb-name>PayrollBean</ejb-name>
<local-home>PayrollHome</local-home>
<local>Payroll</local>
<ejb-class>com.example.PayrollBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<resource-ref>
<res-ref-name>jdbc/empDB</res-ref-name>
<res-ref-type>javax.sql.DataSource</res-ref-type>
<res-auth>Container</res-auth>
</resource-ref>
</session>
...
<assembly-descriptor>
...
</assembly-descriptor>
Líneas de desarrollo EJB :EJB 2.1 Vs EJB 3.0

• Ejemplo con EJB 3.0


// El mismo ejemplo, con EJB 3.0
@Stateless public class PayrollBean implements Payroll {
@Resource DataSource empDB;
public void setBenefitsDeduction (int empId, double deduction) {
...
Connection conn = empDB.getConnection();
...
}
...
}
// Y no hacen falta descriptores de despliegue.
Líneas de desarrollo EJB :EJB 2.1 Vs EJB 3.0

• Mejoras de la versión EJB 3.0 respecto EJB 2.1


− Hemos eliminado del código los métodos no usados del ciclo
de vida del EJB.
− Ya no se necesita la declaración: implements javax.ejb.SessionBean
En lugar de ello, la Bean Class PayrollBean implementa el
interfaz Payroll.
− La anotation @Resource permite que las dependencias se
inyecten directamente al componente cunado el contenedor la
instancie, eliminando la necesidad de búsquedas JNDI
(véase el lookup del ejemplo 1).
Líneas de desarrollo EJB :EJB 2.1 Vs EJB 3.0

• Búsquedas dinámicas en JNDI


− Las búsquedas dinámicas también se han simplificado
Algunas aplicaciones siguen teniendo la necesidad de hacer búsquedas
dinámicas en JNDI. Estas búsquedas pueden llevarse a cabo ahora mucho
más fácilmente con un método lookup añadido a SessionContext.
− Las APIS JNDI se han eliminado de la visión del desarrollador
− Las dependencias se expresan a nivel de la clase Bean
− El método: EJBContext.lookup se usa en tiempo de ejecución.
Líneas de desarrollo EJB :EJB 2.1 Vs EJB 3.0

• Ejemplo:
@Resource(name=”myDB”, type=javax.sql.DataSource)
@Stateful public class ShoppingCartBean implements ShoppingCart {
@Resource SessionContext ctx;
public Collection startToShop (String productName) {
...
DataSource productDB =(DataSource)ctx.lookup(“myDB”);
Connection conn = myDB.getConnection();
...
}
...
}
El recurso MyDB es buscado en
tiempo de ejecución, lo que permite
a una aplicación decidir a qué
recursos acceder dependiendo de la
disponibilidad o por ejemplo, de
parámetros de QoS
Líneas de desarrollo EJB: Compatibilidad y migración

• Todas las aplicaciones existentes en la actualidad


siguen funcionando en este modelo.
• Facilidad de integración entre componentes y
aplicaciones preexistentes.
• Permite que se actualicen o reemplacen componentes
(usando APIS EJB 3.0) sin afectar a los clientes
existentes.
• La migración incremental facilita la adopción de la
tecnología EJB 3.0
Líneas de desarrollo EJB: EJB3

• Tácticas de EJB 3.0 (I)


− Simplificación de las APIS EJB
• Se elimina la necesidad de EJBHomes y EJBObjects
• Se eliminan las APIS JNDI del punto de vista del desarrollador y el
cliente.
• Eliminamos la necesidad de los descriptores de despliegue
− Utilizar las ventajas de los metadatos Java (annotations)
• Beneficiarnos de las configuraciones por defecto para los casos típicos
• Los metadatos han sido diseñados de modo que los casos más
frecuentes o comunes son más fáciles de expresar.
Líneas de desarrollo EJB: EJB3

• Tácticas de EJB 3.0 (II)


− El contenedor realiza más cantidad de trabajo tedioso, y el
desarrollador menos, de modo que puede centrarse en tareas
más importantes.
− El Bean especifica lo que necesita usando metadatos, de
modo que ya no tenemos que escribir interfaces de
contenedor innecesarios.
− El contenedor actúa de intermediario para proporcionar los
servicios que sean requeridos.
Líneas de desarrollo EJB: EJB3

• EJB3: Conceptos básicos


− Beans de sesión (session beans)
• Stateless session bean
• Stateful session beans
− Beans dirigidos por mensaje (Message Driven Bean)

NOTA: Los beans de entidad (entity beans) han sido sustituidos


por entidades de la Java Persistence API.
Líneas de desarrollo EJB3

• Stateless Session Bean (Bean de sesión sin estado)


− Es aquél que no dispone de variables de instancia en las
cuales se guarden datos que puedan ser compartidos entre
los distintos métodos del bean.
− Se trata de un bean que por lo general contará con una serie
de métodos que realizarán un trabajo determinado e
independiente y que el resultado de las operaciones
realizadas dentro de cada uno de los métodos no dependerá
de ningún “estado” relativo a la conversación que mantiene el
cliente con el bean.
Líneas de desarrollo EJB3

• Ejemplo de stateless session bean


− Tomemos como ejemplo un bean que se encarga de gestionar las
operaciones básicas que podemos realizar con un cliente, como son
consultar un cliente, guardar un cliente y borrarlo.
− En primer lugar tendríamos que crear una interface :
public interface CustomerServiceLocal {
public void saveCustomer( Customer customer );
public Customer getCustomer( Long id );
public Collection getAllCustomers();
public void deleteCustomer( Long id );
}
− Todo bean de sesión sin estado es necesario que disponga de una
interface.
− Si no la hubiéramos creado y hubiéramos definido directamente el bean sin
la creación de la interface, hubiera sido el propio contenedor quién la
hubiera creado por nosotros.
Líneas de desarrollo EJB3

• La interfaz debiera de tener una anotación, que le


indicara si se trata de una interface Local o Remote.
• Si el bean va a ser utilizado por una clase que se
ejecute dentro de la misma JVM en la que se ejecuta el
bean de sesión entonces la interface podría ser Local, y
si el bean va a ser llamado por una clase que se ejecuta
en una JVM distinta entonces la interface tendría que
ser Remote.
• Por defecto, si no se indica nada, será tratada como
una interface Local.
Líneas de desarrollo EJB3
• Ejemplo de una interface local:
@Local
public interface CustomerServiceLocal {
public void saveCustomer( Customer customer );
public Customer getCustomer( Long id );
public Collection getAllCustomers();
public void deleteCustomer( Customer customer );
}

• Ejemplo de una interfaz remota:


@Remote
public interface CustomerServiceRemote{
public void saveCustomer( Customer customer );
public Customer getCustomer( Long id );
public Collection getAllCustomers();
public void deleteCustomer( Customer customer );
}
Líneas de desarrollo EJB3

• El bean completo sería:


@Stateless
public class CustomerService implements CustomerServiceLocal {
@PersistenceContext()
private EntityManager em;
// Persistencia de tipo: container-managed entity manager.
public void saveCustomer( Customer customer ) {
em.persist( customer );
}
public Customer getCustomer( Long id ) {
Query q=em.createQuery( "SELECT c FROM Quiz c WHERE c.id = :id" ).setParameter("id", id );
return (Customer) q.getSingleResult();
}
public Collection getAllCustomers() {
return em.createQuery( "SELECT c from Customer c" ).getResultList();
}
public void deleteCustomer( Customer customer ) {
em.remove( customer );
}
}
Líneas de desarrollo EJB3

• Stateful session bean


− Al contrario que en los beans de sesión sin estado, los stateful session
bean, como su nombre indica, sí tienen estado.
− Lo que esto significa es que dentro de la sesión del usuario estos beans
van a almacenar datos en variables de instancia, y esos datos van a tener
un significado concreto durante toda la conversación mantenida entre el
cliente y el bean.
− Un ejemplo típico de bean de sesión con estado es un carro de la compra,
en el cual, durante la sesión de usuario, éste va agregando productos en el
carro a través de una lista.
− Tras ir agregando productos llegará un momento en el que el usuario
quiera efectuar la compra, para lo cuál tendrá que realizar previamente un
registro de sus datos, especificar la dirección de entrega, indicar el número
de su tarjeta de crédito, etcétera, y finalmente confirmará la compra de los
productos seleccionados.
Líneas de desarrollo EJB3

• Todos estos datos hay que almacenarlos en unas


variables, que son las que conforman el estado del
bean.
• Al igual que los Stateless Session Bean, los Stateful
también deben de implementar una interface que puede
ser Local o Remote :
@Local
public interface CartServiceLocal {
public void addProduct( Product product );
public void removeProduct( Product product );
public Collection getProducts();
}
Líneas de desarrollo EJB3
• Y la implementación de esta interface sería el Stateful Session
Bean :
@Stateful
public class CartService implements CartServiceLocal {
private List products;
public void addProduct( Product product ) {
products.add( product );
}
public void removeProduct( Product product ){
products.remove( product );
}
public Collection getProducts() {
return products;
}
}
Líneas de desarrollo EJB3

• Message Driven Beans (beans Dirigidos por mensaje)


− Este tipo de beans ( MDB ) permite a las aplicaciones
procesar mensajes de forma asíncrona a través del servicio
JMS ( Java Messaging Service ).
− JMS funciona a través de colas de mensajes, donde los
clientes envían sus peticiones, y estas colas son controladas
por los Message Driven Beans, los cuales procesan los
mensajes que hay en ellas y ejecutan ciertos servicios
dependiendo del mensaje procesado.
− Este tipo de beans se aproximan más a la forma conceptual
de los Stateless Session Bean en el sentido que son beans
que no deben almacenar estado alguno.
Líneas de desarrollo EJB3

• Cuando un mensaje llega a la cola el contenedor hace una


llamada al método onMessage del Message Driven Bean y en
este método el bean debería invocar a métodos de otros sesión
bean o realizar la lógica de negocio de debiera ejecutar ( es más
conveniente no tener aquí lógica de negocio, sino hacer
invocaciones a métodos de otras clases que sí se encarguen de
realizar lógica de negocio ).

• Para declarar un MDB sólo hemos de establecer la anotación


@MessageDriven a una clase que implemente la interface
MessageListener, e indicar el nombre de la cola del contenedor
( la cuál es accesible vía JNDI) que va a controlar el MDB
Líneas de desarrollo EJB3

• Veamos un ejemplo de MDB:


@MessageDriven( mappedName = "jms/Queue" )
public class AsynchronousService implements MessageListener
{
public void onMessage( Message message ) {
TextMessage textMessage = (TextMessage)message;
System.out.println( textMessage.getText() );
}
}
Dependency Injection

• Dependency Injection es un patrón según el cual, las


dependencias de un objeto se proporcionan
automáticamente por una entidad externa a ese objeto,
y no es necesario que ese objeto pida el recurso
explícitamente.
• Para solicitar la inyección de un recurso, el componente
usa la anotación @Resource. En algunos recursos
especializados, también las anotaciones @EJB y
@WebServiceRef.
Dependency Injection
Java Persistence API

• La Java Persistence API trata lo siguiente:


− Cómo los datos relacionales se mapean en Objetos Java
(Persistent Entities)
− Cómo esos objetos se almacenan en una base de datos
relacional para que puedan ser accedidos con posterioridad
− Conseguir la existencia continuada de un estado de entidad
incluso después de que finalice la aplicación que la usa.
− Estandariza el mapeo objeto/relacional
• Una entidad (entity) es un objeto de persistencia.
Normalmente una entidad representa una tabla en una
BD relacional, y cada instancia de entidad es una fila
de la tabla.
Java Persistence API

• Características clave de la Java Persistence API (I)


− Las entidades son POJOs: al contrario que los componentes EJB que
usan container-managed persistence (CMP). Los objetos entidad usando
la nueva API ya no son componentes
− Mapeo estandarizado objeto/relacional: podemos mapear información
objeto/relacional bien usando annotations o bien descriptores XML
− Soporte de herencia y polimorfismo: Obviamente al ser los objetos de
entidad POJOs.
− Soporte a consultas nativas (native query): Además del Java
Persistence Query Language, ahora también podemos expresar nuestras
consultas en el lenguaje nativo de la BD subyacente.
− Named Query: Es una consulta estática expresada en metadatos. La
consulta puede ser o bien una Java Persistence query o bien una native
query, lo cual mejora la reutilización de consultas.
Java Persistence API

• Características clave de la Java Persistence API (II)


− Reglas de empaquetado simplificadas: Ya que las entity beans son
clases java (POJO), pueden ser empaquetadas en cualquier lugar de una
aplicación JEE5. Por ejemplo, pueden formar parte de un .JAR EJB o en
un .JAR que forme parte de librerías de un .EAR.
− Soporte para bloqueo optimista (optimist locking): Es una técnica
que evita el bloqueo por razones de rendimiento pero teniendo en
consideración que la transacción puede fallar debido a colisión con otro
usuario.
− Entidades separadas (Detached Entities): Como las entidades son
POJOs, pueden ser serializadas (implements Serializable) y enviadas a a
través de la red a distintas direcciones. Ya no son necesarios los Data
Transfer Objects (DTOs).
− EntityManager API: En operaciones CRUD (Create Read Update
Delete) que impliquen entidades.
− Conectividad de proveedores de persistencia de terceros: Es un
interfaz entre un contenedor Java EE y un proveedor de persistencia.
Java Persistence API

• Entity Beans (beans de entidad)


− Un Entity Bean es una clase ( POJO ) que representa una
tabla de una base de datos, y cada instancia de esta clase
representa un registro de la tabla, es decir, con los entity
beans lo que conseguimos es crear un mapeo entre las
propiedades de una clase y los campos de una tabla.
− Además de este mapeo también vamos a poder especificar
las relaciones que tienen las clases entre sí ( uno a uno, uno a
muchos, muchos a uno y muchos a muchos ).
− Todo Entity Bean debe de tener una clave primaria que
identifica a ese registro de forma única dentro de la tabla.
Todas estas configuraciones las vamos a realizar a través de
anotaciones, y el API que se encarga de gestionar todos
los aspectos relativos a la persistencia es JPA ( Java
Persistent API ).
Java Persistence API

• Como ejemplo, vamos a crear una entidad llamada


Team, para lo cual veremos que lo único que vamos a
tener en cuenta es:
− Establecer una anotación @Entity al principio de la clase,
− Una anotación @Id para indicar cuál es la propiedad que
representa la clave primaria,
− Y por último una anotación @OneToMany para indicar que un
equipo puede estar compuesto por muchos jugadores y que
éstos sólo pueden pertenecer a un equipo :
Java Persistence API
@Entity
public class Team {
private int id;
private String name;
private Date foundationDate;
private Collection players;
@Id
public int getId() {
}
return id; Un Team (equipo) puede tener
public void setId( int value ) {
id = value;
muchos jugadores
}
public String getName() {
return name;
}
public void setName( String value ) {
name = value;
}
public Date getFoundationDate() {
return foundationDate;
}
public void setFoundationDate( Date value ) {
foundationDate = value;
}
@OneToMany
public Collection getPlayers() {
return players;
}
public void setPlayers( Collection value ) {
players = value;
}
}
Java Persistence API

• A continuación vamos a crear la Entidad Player, que al


igual que la entidad anterior va a tener:
− una anotación @Entity,
− otra anotación @Id,
− y por último una anotación @ManyToOne para establecer una
relación bidireccional entre las dos entidades :
Java Persistence API
public class Player {
private int id; Muchos player
private String name;
private Team team; (jugadores)
@Id
public int getId() { pertenecen a un
return id; mismo equipo
}
public void setId( int value ) {
id = value;
}
public String getName() {
return name;
}
public void setName( String value ) {
name = value;
}
@ManyToOne
public Team getTeam() {
return team;
}
public void setTeam( Team value ) {

team = value;
}
}
Java Persistence API

− Creando entidades que utilizan en nuevo modelo de persistencia


package demo; @ManyToOne
import javax.persistence.*; public Department getDepartment() {
import java.util.*; return department;
import java.io.Serializable; }
public void setDepartment(Department department) {
@Entity this.department = department;
public class Employee implements Serializable { }
}
private String id;
private String name; @Entity
private Department department; public class Department implements Serializable {
private String name;
// Every entity must have a no-arg private Set<Employee> employees = new HashSet<Employee>();
public/protected constructor. public Department() { }
public Employee(){ }
public Employee(String name, Department dept) { @Id
this.name = name; public String getName() {
this.department = dept; return name;
} }

@Id // Every entity must have an identity. public void setName(String name) {
public String getId() { this.name = name;
return id; }
}
public void setId(String id) { @OneToMany(mappedBy="department")
this.id = id; public Set<Employee> getEmployees() {
} return employees;
}
public String getName() {
return name; public void setEmployees(Set<Employee> employees) {
} this.employees = employees;
}
public void setName(String name) { }
this.name = name;
}
Java Persistence API

• Este stateless bean demuestra cómo usar las anteriores


entidades:
@Stateless
public class HRMSBean implements HRMS {

@PersistenceContext private EntityManager em;

public Employee createEmployee(String empName, String departmentName) {


Department dept = em.find(Department.class, empName);
Employee emp = new Employee(empName, dept);

// User is responsible for managing bidirectional relationships


dept.getEmployees().add(emp);
em.persist(emp);
return emp;
}
}

@Remote
public interface HRMS {
Employee createEmployee(String empName, String departmentName);
}
BLOQUE III: PRÁCTICAS DEL CURSO
Práctica 1

• Práctica número 1:
− Descripción: Creación de un JavaBean
− Objetivos:
• Primera toma de contacto con Netbeans como IDE
• Primera toma de contacto con Sun Application Server 9 como Servidor
de Aplicaciones
• Primera toma de contacto con Colinux modificado como entorno virtual
avanzado del curso.
− Entorno gráfico con NX
• Conocer las características principales de un JavaBean, para entender
a diferenciar los casos en los que es conveniente usar JavaBeans, y
cuándo usar EJB’s.
Práctica 1

• Arrancamos Netbeans.

• Creamos un nuevo proyecto: ejb01-javabean:


Práctica 1

• En el asistente, elegimos una aplicación Web:


Práctica 1

• Elegimos el nombre ejb01-javabean

Luego NEXT y FINISH


Práctica 1
• Modificamos el archivo:index.jsp
<jsp:useBean id="libro" class="cursoEjb.LibroListenerBean" scope="session" />
<%=session.getAttribute("libro") + "<br>" %>
<html>
<head>
<title>JavaBeans - Curso EJB</title>
</head>

<body>
<b>Guardamos los datos...</b><p>
<jsp:setProperty name="libro" property="titulo" value="Avanced JavaServer Pages" />
<jsp:setProperty name="libro" property="autor" value="David M. Geary" />
<b>Recuperamos los datos...</b><br>
<jsp:getProperty name="libro" property="titulo" /><br>
<jsp:getProperty name="libro" property="autor" /><br>
</body>
</html>
Práctica 1
• Creamos una nueva clase Java: cursoEjb.LibroListenerBean

package cursoEjb;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
*
* @author jcarlos
*/
public class LibroListenerBean implements
HttpSessionListener {
public String getTitulo() {
private String titulo;
return titulo;
private String autor;
public void setTitulo(String titulo) { }
this.titulo = titulo; public String getAutor() {
} return autor;
public void setAutor(String autor) { }
this.autor = autor;
}
public void sessionCreated(HttpSessionEvent
se) {
}

public void sessionDestroyed(HttpSessionEvent


se) {
}
Práctica 1

• Resultados esperados tras un deploy + Run:


Práctica 2

• Práctica número 2:
− Descripción: Creación de un Stateless EJB
• Primera toma de contacto con los EJBs
• Primera toma de contacto con las anotaciones.
• Construcción de un EJB simple, que realice las funciones de una
calculadora.
• Será una aplicación que tenga un Servlet que haga la llamada al EJB
Práctica 2

• Primero: Creamos un proyecto de tipo Enterprise:


Práctica 2

• Le pedimos al asistente que cree el módulo WAR y el


EJB:
Práctica 2

• Ahora, en el cuadro de proyectos, pulsamos click derecho sobre


“ejb02-calculadora-ejb”, y elegimos New=>Session Bean
Práctica 2

• El asistente debe • El EJB propiamente


haber dejado lo dicho, es la clase
siguiente: “CalculadoraBean”
• CalculadoraRemote, es
un interfaz, ya que los
clientes nunca se
comunican directamente
contra el Bean
Práctica 2

• Una vez hecho esto, • Con esa etiqueta, el


nos fijamos en la contenedor se encargará
annotation que de crear un EJB sin
estado.
tenemos justo en la
• No tenemos tampoco
cabecera de la clase:
que crear el archivo
ejb-jar.xml
• No necesitamos el
interfaz home.
Práctica 2

• Empezamos a codificar los métodos de la calculadora, y


observamos que Netbeans ya nos empieza a mostrar
un asistente de ayuda que solicita incorporar esos
métodos al interfaz:

(Prestar atención al icono de la bombilla)


Práctica 2

• El resultado final de CalculadoraBean debe ser el que


package ejb02;
sigue: import javax.ejb.Stateless;

@Stateless
public class CalculadoraBean implements ejb02.CalculadoraRemote {

/** Creates a new instance of CalculadoraBean */


public CalculadoraBean() {
}

public int suma(int a, int b) {


return a+b;
}

public int resta(int a, int b) {


return a-b;
}

public int divide(int a, int b) {


if (b == 0) {
throw new IllegalArgumentException("No puedo dividir por 0");
}
return a / b;
}

public int multiplica(int a, int b) {


return a*b;
}

}
Práctica 2

• El resultado final de CalculadoraRemote debe ser el


que sigue:
package ejb02;

import javax.ejb.Remote;

@Remote
public interface CalculadoraRemote {
int multiplica(int a, int b);

int divide(int a, int b);

int resta(int a, int b);

int suma(int a, int b);

}
Práctica 2

• Ahora vamos a crear un servlet. Más adelante crearemos un


formulario en el index.jsp que enviará el submit a este servlet,
que a su vez, usará al EJB para operar con las operaciones de la
calculadora:
Práctica 2

• Seguimos el asistente, tecleando lo siguiente:


Práctica 2

• El código del servlet donde hay cambios es:


package war02;
import java.io.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;

import javax.ejb.EJB;
import ejb02.CalculadoraRemote;
public class Resultados extends HttpServlet {
@EJB
private CalculadoraRemote calcu;

protected void processRequest(HttpServletRequest request, HttpServletResponse response)


throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
Integer arg0 = Integer.parseInt(request.getParameter("arg0"));
Integer arg1 = Integer.parseInt(request.getParameter("arg1"));

out.println("<html>");
out.println("<head>");
out.println("<title>Servlet que suma dos argumentos</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Servlet que suma dos argumentos</h1>");
out.println("</body>");
out.println("La suma de: "+arg0+" Y: "+arg1+" es: "+calcu.suma(arg0,arg1));
out.println("</html>");
out.close();
}
Práctica 2

• Ahora retocamos el index.jsp del .WAR para que incluya un


formulario que envíe dos argumentos numéricos al servlet, que a
su vez usar al EJB para los cálculos:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Práctica 2</title>
</head>
<body>

<h1>Practica 2 - Curso EJB</h1>


<form name="formulario" action="Resultados" method="POST">
Introduce dos argumentos numericos, y haremos calculos:<BR>
<input type="text" name="arg0" value="1" />
<input type="text" name="arg1" value="2" />
<input type="submit" value="Enviar" name="enviar" />
</form>

</body>
</html>
Práctica 2

• Para acabar, sólo nos queda testearlo. Para ello, le decimos a


Netbeans que ejecute un Run, que es lo mismo que
build+deploy+Run.
Práctica 2

• Una vez visto los resultados, cambiar el código


necesario para que el proyecto reste y multiplique.
• Objetivo: repetir conceptos y fijar el conocimiento del
entorno Netbeans para la generación de proyectos
Enterprise Edition.
Práctica 3

• Práctica número 3:
− Descripción: Creación de un Stateful EJB
• Primera toma de contacto con los EJBs de tipo statefull
• Construcción de un EJB simple, que realice las funciones de una mini-
carrito de la compra (en este caso, de libros).
• Será una aplicación que tenga una aplicación de consola que haga la
llamada al EJB
Práctica 3

• Primero: creamos una aplicación de tipo Enterprise:


Práctica 3

• En el asistente, comprobamos que los parámetros


queden EXACTAMENTE como en la figura:
Práctica 3

• Una vez de
pulsemos Finish,
desplegamos el
árbol de proyectos y
pulsamos click
derecho sobre
ejb03-carro-ejb tal
como en la figura:
Práctica 3

• Continuamos con el asistente, con estos parámetros:


Práctica 3

• Una vez finalizado, navegamos por el árbol de directorios.


Netbeans nos ha creado automáticamente la plantilla del Bean y
el Interfaz. La renombraremos y ejecutaremos un Refactoring:
<= Teniendo esta selección activa,
pulsamos F2, o bien botón
derecho, menú, y rename.
Práctica 3

• Ahora observamos que Netbeans nos muestra una nueva


subventana, en la que espera confirmación para ejecutar el
proceso de refactoring:
Práctica 3

• Cremos ahora una nueva clase tal como en la figura:


Práctica 3

• En el asistente, • Y este código:


proporcionamos estos datos:
package util;

public class LibroException


extends Exception {
public LibroException() {
}

public LibroException(String
msg) {
super(msg);
}
}
Práctica 3
• Volvemos a crear una • Y este código:
package util;

nueva clase, esta vez /**


*
con estos datos: * @author jcarlos
*/
public class IdVerificador {

public IdVerificador() {
}

public boolean validar(String id) {


boolean result = true;

for (int i = 0; i < id.length(); i++) {


if (Character.isDigit(id.charAt(i))
== false) {
result = false;
}
}

return result;
}

}
Práctica 3

• El código del @Stateful


public class CarroBean implements ejb03.Carro {
Bean es el /** Creates a new instance of CarroBean */
List<String> contenidos;
siguiente String IdCliente;
String nombreCliente;
(1/2): public CarroBean() {
}

public void inicializar(String persona) throws LibroException {


if (persona == null) {
throw new LibroException("No se permite persona con
valor Null");
} else {
nombreCliente = persona;
}

IdCliente = "0";
contenidos = new ArrayList<String>();
}

// ---> Continua en la siguiente pagina


Práctica 3

• Código del bean (2/3)


public void inicializar(String persona,String id) throws LibroException {
if (persona == null) {
throw new LibroException("No esta permitida persona con valor Null");
} else {
nombreCliente = persona;
}

IdVerificador compruebaId = new IdVerificador();

if (compruebaId.validar(id)) {
IdCliente = id;
} else {
throw new LibroException("Codigo de ID invalido: " + id);
}

contenidos = new ArrayList<String>();


}

// ---> Continua en la siguiente pagina


Práctica 3

• Código del bean (3/3)


public void anadirLibro(String titulo) {
contenidos.add(titulo);
}

public void borrarLibro(String titulo) throws LibroException {


boolean result = contenidos.remove(titulo);

if (result == false) {
throw new LibroException("\"" + titulo + "\" no esta en el carro.");
}
}

public List<String> getcontenidos() {


return contenidos;
}

@Remove()
public void borrado() {
contenidos = null;
}
}
Práctica 3

• Se pide lo siguiente en este punto:


− Solucionar los problemas de referencias no satisfechas
usando la ayuda de Netbeans (presentará un icono de
bombilla para elegir los imports que el entorno crea que
necesitamos)
• import java.rmi.RemoteException;
• import java.util.ArrayList;
• import java.util.List;
• import javax.ejb.Remove;
• import javax.ejb.Stateful;
• import util.IdVerificador;
• import util.LibroException;
− Usar el asistente Netbeans para definir los métodos en el
interfaz del Bean de forma automática.
Práctica 3
• Nos movemos por el menú de proyectos hasta el cliente
del EJB que hemos creado (1/2):
public class ClienteCarro {
@EJB
private static Carro carro;

public ClienteCarro(String[] args) {


}

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
ClienteCarro client = new ClienteCarro(args);
client.doTest();
}

public void doTest() {


try {
carro.inicializar("Mi carro de la compra", "123");
carro.anadirLibro("El nombre de la Rosa");

carro.anadirLibro("La ciudad de la algegria");


carro.anadirLibro("La metamorfosis de Kafka");

List<String> bookList = carro.getcontenidos();

// ---> Continua en la pagina siguiente


Práctica 3

• El código continúa así:


bookList = carro.getcontenidos();

Iterator<String> iterator = bookList.iterator();

while (iterator.hasNext()) {
String titulo = iterator.next();
System.out.println("Obteniendo titulo del libro del carro: " + titulo);
}
System.out.println("Borrando \"El nombre de la Rosa\" from carro.");
carro.borrarLibro("El nombre de la Rosa");

System.out.println("Borrando \"El resplandor\" del carro.");


carro.borrarLibro("El nombre de la Rosa");

System.exit(0);
} catch (LibroException ex) {
System.err.println("Se elevo una LibroException: " + ex.getMessage());
System.exit(1);
} catch (Exception ex) {
System.err.println("Se elevo una excepcion inesperada");
ex.printStackTrace();
System.exit(1);
}
}
}
Práctica 3

• Se pide, en este caso:


− Resolver las referencias no satisfechas, usando el asistente
de Netbeans, y comprobar que no existe ningún aviso de
error en el código y ejecutar la aplicación:
Hemos provocado una excepción de manera
intencional al borrar un libro inexistente en el
carro.
Práctica 4

• Práctica número 4:
− Descripción: Creación de un Message Driven Bean y conocer
usando el sistema pb-project (Java Blue Prints Project).
− Objetivos:
• Primera toma de contacto con los MDB
• Primera toma de contacto con el sistema pb-project
• Conocer las características principales de un MDB, para entender
cuándo puede compensarnos el usarlo.
Práctica 4

• Los proyectos que usan el sistema Java Blue Prints


Project (bp-project) tienen las siguientes ventajas:
− Pueden crear proyectos Java basados en la herramienta ANT
− Pueden cargarse y usarse como proyectos nativos en IDE’s
como Netbeans
− Pueden ser ejecutados (y desplegados) desde la línea de
comandos
− Permiten que un conjunto de proyectos compartan una misma
configuración.
Práctica 4
• Instrucciones de uso de bp-project de un proyecto con código
fuente existente
− Descargar bp-project y descomprirlo ejecutando el fichero JAR. Este proceso,
genera una nueva carpeta llamada “bp-project-vXX” (llamaremos a este directorio
bp-project.home). Nos dirigimos al directorio bp-project.home/bp-project.
− Nos aseguramos de tener ANT instalado. Si no lo tenemos, lo descargamos.
− Creamos el proyecto Netbeans si aún no está creado.
− Abrimos el fichero build.xml generado por NetBeans y reemplazamos la línea:
    <import file="nbproject/build-impl.xml"/>
Por:
<property name="bp-project.home" value=“poner el path <bp-project.home>"/> 
    <import file="${bp-project.home}/main.xml" />
− Observar que podemos compartir un único directorio bp-project/ entre muchas
aplicaciones simplemente copiándolo a un lugar común, y ajustando la línea de
import a la carpeta o ubicación que corresponda.
− También será necesario definir una nueva propiedad en el fichero build.xml que
defina el tipo de proyecto. Por ejemplo, si es un proyecto Web, tendremos que
añadir la siguiente línea a build.xml:
Justo antes del import de ${bp-project.home}/main.xml Ponemos:
    <property name="is.war.module" value="true"/>
Práctica 4

• Ejemplo de un caso concreto:


− Abrimos build.xml y reemplazamos:
<import file="nbproject/build-impl.xml"/>

− Por:
<property name="is.war.module" value="true"/>
<property name="bp-project.home" value="path de <bp-project.home>"/>
<import file="${bp-project.home}/main.xml" />

− Nosotros copiaremos la carpeta bp-project al path del proyecto, de modo


que esas tres líneas quedarán en dos:
<property name="is.war.module" value="true"/>
<import file="./bp-project.home/main.xml" />

• En el directorio <bp-project.home> copiamos el fichero


build.properties.sample a build.properties y corregimos los valores de
las propiedades javaee.home, y javaee.server.passwordfile.
Práctica 4

• Instrucciones para proyectos nuevos


− Crear la estructura de directories del proyecto siguiendo las
Reglas de proyecto Java BluePrints. Si estamos creando el
proyecto con Netbeans, no hay problema, ya que NB sigue
esas reglas.
− Copiamos el directorio bp-project/ en el home del directorio del
proyecto.
− Creamos un fichero build.xml adecuado para un war, ear o
ejb-jar siguiendo los ejemplos que se describen en las
siguientes diapositivas.
Práctica 4

• Proyecto EAR (enterprise archive)


<?xml version="1.0"?>
<project name="bp-web-project" default="default" basedir=".">
    <property name="is.ear.module" value="true"/> 
    <import file="bp-project/main.xml"/>   
</project>

• Proyecto Web
<?xml version="1.0"?>
<project name="bp-web-project" default="default" basedir=".">
    <property name="is.war.module" value="true"/> 
    <import file="bp-project/main.xml"/>   
</project>

• Proyecto EJB Jar


<?xml version="1.0" encoding="UTF-8"?>
<project name="hello-ejb" default="default" basedir="."
xmlns:ejbjarproject="http://www.netbeans.org/ns/j2ee-ejbjarproject/2">
    <property name="is.ejb-jar.module" value="true"/>
    <import file="bp-project/main.xml"/>
</project>
Práctica 4
• Proyecto Java Persistente Unit.
<?xml version="1.0" encoding="UTF-8"?>
<project name="hello-pu" default="default" basedir=".">
    <description>Builds, tests, and runs the project hello-pu.</description>
    <property name="is.jar.module" value="true"/>
    <property name="is.persistence-unit.module" value="true"/>
    <import file="bp-project/main.xml"/>
</project>

• Proyecto Web que depende la la JPU declarada encima de estas líneas


<?xml version="1.0" encoding="UTF-8"?>
<project name="hello-servlet" default="default" basedir=".">
    <property name="is.war.module" value="true"/>
    <!-- This project is dependent on the hello-pu project so it is declaring a dependency -->
    <property name="hello-pu.home" value="${home.dir}/../hello-pu"/>
    <!-- extra.classpath property adds to the classpath used for compilation -->
    <property name="extra.classpath" value="${hello-pu.home}/dist/hello-pu.jar"/>
    <!-- include the persistence unit in the Web-app -->
    <target name="-post-compile" depends="init">
        <copy file="${hello-pu.home}/dist/hello-pu.jar" todir="${build.dir}/web/WEB-INF/lib"/>
    </target>
    <!-- Note that this project is sharing the build system with other projects -->
    <import file="bp-project/main.xml"/>
</project>
Práctica 4

• Proyecto Web que depende de una librería de


componentes JSF
<?xml version="1.0"?>
<project name="bp-slider-navigator" default="default" basedir=".">

  <property name="is.war.module" value="true"/>


  <import file="bp-project/main.xml"/>

  <property name="project.ui" value="../../../components/ui"/>


  <property name="reference.ui.jar" value="${project.ui}/dist/ui.jar"/>

 <target name="-pre-compile" depends="init">


      <copy file="${reference.ui.jar}" todir="${build.web.dir}/WEB-INF/lib"/>
  </target>     
</project>
Práctica 4

• TARGETs típicos de compilación: Estos son algunos


target’s típicos de compilación (build) que está
disponibles automáticamente cuando usamos
bp-project:
− all: Compila, empaqueta el archive, despliega la aplicación y
ejecuta.
− compile: Compila a aplicación.
− package-module: Empaqueta el archivo.
− default: Compila y empaqueta el archivo.
− run: Ejecuta la aplicación
− undeploy: repliega la aplicación.
− clean: Borra los directories generados, como build y dist
Práctica 4

• Valores de variables en el fichero build.properties (1/3)


Práctica 4

• Valores de variables en el fichero build.properties (1/3)


Práctica 4

• Valores de variables en el fichero build.properties (1/3)


Práctica 4

• Comenzamos la construcción de nuestro proyecto.

• Será un proyecto de tipo Enterprise Application, con un


módulo EJB y con un módulo de aplicación que actuará
como cliente del Message Driven Bean.
• Posteriormente a la ejecución del cliente,
chequearemos el fichero de log el Application Server,
que se encuentra en el path:

C:\Sun\AppServer\domains\domain1\logs
/opt/SUNWApp/domains/domain1/logs
Práctica 4

• Creamos nuestro proyecto


Enterprise, llamado
ejb04-mensajesimple.
• El path de ese proyecto,
debería ser uno de estos:

C:\CursoEJB\proyectos\ejb04-mensajesimple
/opt/cursoejb/proyectos/ejb04-mensajesimple
Práctica 4

• Copiamos la carpeta bp-project ya preparada, y la


pegamos en el directorio de nuestro proyecto.
• En el fichero build.xml de nuestro proyecto, abrimos
build.xml y reemplazamos:
<import file="nbproject/build-impl.xml"/>

− Por:
<property name="is.ear.module" value="true"/>
<import file=“./bp-project/main.xml" />

• Lo podemos hacer desde el propio Netbeans o desde


fuera.
Práctica 4

• Creamos un nuevo MDB tal como en la figura:


Práctica 4

• Elegimos estos datos en el asistente:

NOTA: en los MDB, Netbeans no añade el sufijo Bean a


• El código del MDB debe ser el siguiente: Práctica 4

@MessageDriven(mappedName = "jms/MensajeSimpleBean", activationConfig = {


@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue
= "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue
= "javax.jms.Queue") public void onMessage(Message mensajeEntrante)
{
}) TextMessage msg = null;
public class MensajeSimpleBean implements MessageListener
try { {
static final Logger logger = if (mensajeEntrante instanceof
Logger.getLogger("SimpleMessageBean"); TextMessage) {
msg = (TextMessage) mensajeEntrante;
@Resource
logger.info("BEAN DE MENSAJE: Mensaje
private MessageDrivenContext mdc; recibido: " + msg.getText());
public MensajeSimpleBean() { } else {
} logger.warning("Mensaje de tipo
erroneo: “ +
mensajeEntrante.getClass().getName());
}
} catch (JMSException e) {
e.printStackTrace();
mdc.setRollbackOnly();
} catch (Throwable te) {
te.printStackTrace();
}
}
}
Práctica 4
•El código del cliente, debe ser el siguiente:
public class ClienteMensajeSimple { System.out.println("Para ver si el bean recibío
@Resource(mappedName = "jms/ConnectionFactory") mensajes,");
private static ConnectionFactory connectionFactory; System.out.println(“ mirar en el fichero: “+
@Resource(mappedName = "jms/MensajeSimpleBean") <install>/domains/domain1/logs/server.log.");
private static Queue queue; } catch (JMSException e) {
public static void main(String[] args) { System.out.println("Se elevo una excepcion: “+
Connection connection = null; e.toString());
Session session = null; } finally {
MessageProducer messageProducer = null; if (connection != null) {
TextMessage message = null; try {
final int NUM_MSGS = 3; connection.close();
try { } catch (JMSException e) {
connection = connectionFactory.createConnection(); }
session = connection.createSession(false, } // if
Session.AUTO_ACKNOWLEDGE);
messageProducer = session.createProducer(queue); System.exit(0);
message = session.createTextMessage(); } // finally
} // main
for (int i = 0; i < NUM_MSGS; i++) {
message.setText("Este es el mensaje numero: " + public void onMessage(Message message) {
(i + 1));
}
System.out.println("Enviando mensaje: " +
message.getText()); } // class
messageProducer.send(message);
}
Práctica 4

• Ahora que ya tenemos el código de nuestra aplicación, vamos a


preparar el entorno antes de lanzarla.

• Este proyecto, requiere lo siguiente:


− Un recurso JMS destination (la cola o ‘queue’)
• Usado en el MDB en la línea:
@MessageDriven(mappedName = "jms/MensajeSimpleBean", […]
• Referenciado por el cliente en la línea:
@Resource(mappedName = "jms/MensajeSimpleBean")
− Un recurso JMS Connection Factory
• Usado en el cliente, en la línea:
@Resource(mappedName = "jms/ConnectionFactory")

• Para crear estos recursos, usaremos al herramienta ANT.


Práctica 4
Una vez más, editaremos nuestro fichero build.xml, para añadir lo siguiente:
<target name="create-queue" description="create JMS queue">
<antcall target="create-jms-resource">
<param name="jms.restype" value="javax.jms.Queue" />
<param name="jms.resource.property" value="Name=PhysicalQueue" />
<param name="jms.resource.name" value="jms/MensajeSimpleBean" />
</antcall>
</target>

<target name="create-cf" description="create JMS connection factory">


<antcall target="create-jms-connection-factory">
<param name="jms.restype" value="javax.jms.ConnectionFactory" />
<param name="jms.resource.name" value="jms/ConnectionFactory" />
</antcall>
</target>
<target name="delete-queue"
description="delete JMS queue">
<antcall target="delete-jms-resource">
<param name="jms.resource.name" value="jms/MensajeSimpleBean" />
</antcall>
</target>

<target name="delete-cf"
description="delete JMS connection factory">
<antcall target="delete-jms-resource">
<param name="jms.resource.name" value="jms/ConnectionFactory" />
</antcall>
</target>
Práctica 4
• Abrimos una shell, y desde la
carpeta de nuestro proyecto,
ejecutamos:
– ant create-cf
– ant create-queue
• Debemos obtener
lo siguiente:
Práctica 4

• Ahora ya estamos listos para lanzar nuestro proyecto


(Run):
Práctica 4

• Una vez finalizada la ejecución de la práctica, borramos


los recursos connection factory y queue.
− ant delete-cf
− ant delete-queue
Práctica 5

• Práctica número 5:
− Descripción: Creación de un bean de entidad, y primer
acercamiento a la base de datos derby para la función de
almacén de datos.
− Objetivos:
• Primera toma de contacto con los entity beans.
• Primera toma de contacto con derby
• Conocer las características principales de un entity bean.
Práctica 5

• Creamos un nuevo proyecto, de tipo Web Application, y


lo llamamos ejb05-jpa
Práctica 5

• Arrancamos la base de datos DERBY:


Práctica 5

• Creamos una nueva unidad de persistencia (I)


Práctica 5

• Creamos una nueva unidad de persistencia (II)


Práctica 5

• Creamos ahora una nueva Entity Class:


Práctica 5

• Damos a esa esa entity class los siguientes valores:


Práctica 5
@Entity • El código fuente de CredencialUsuario es:
public class CredencialUsuario implements Serializable {
@Id // nombre es la PK de esta entity.
private String nombre;
private String password;

protected CredencialUsuario() {
}

public CredencialUsuario(String nombre, String password) {


if ( (nombre == null || nombre.length() == 0) ||
(password == null || password.length() == 0)) {
throw new IllegalArgumentException("El nombre o la password esta en blanco");
}
this.nombre = nombre;
this.password = password;
}

public boolean esMismaPassword(String password) {


return this.password.equals(password);
}
}
Práctica 5

• Creamos ahora el servlet login:


Práctica 5
• El servlet login debe tener este código
public class login extends HttpServlet {
@PersistenceUnit
private EntityManagerFactory emf;

public void service ( HttpServletRequest req , HttpServletResponse resp)


throws ServletException, IOException {
EntityManager em = emf.createEntityManager();
try {
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
out.println("<HTML> <HEAD> <TITLE> Login correcto " +
"</TITLE> </HEAD> <BODY BGCOLOR=white>");
String nombre = req.getParameter("nombre");
String password = req.getParameter("password");
CredencialUsuario credencial = em.find(CredencialUsuario.class, nombre);

// em.find devuevle null si no encuentra el usuario.


if (credencial != null && credencial.esMismaPassword(password)) {
out.println("Bienvenido " + nombre);
} else {
out.println("Nombre o password erronea.");
}
Práctica 5

out.println("</BODY> </HTML> ");


} finally {
em.close();
}
}

public void init( ServletConfig config) throws ServletException {


super.init(config);
}

}
Práctica 5

• Creamos un nuevo servlet, esta vez, registro:


Práctica 5
• El servlet registro debe tener este código:
public class registro extends HttpServlet {
@PersistenceUnit
private EntityManagerFactory emf;

// Inyecta un objeto transacción de usuario.


@Resource
private UserTransaction utx;

public void service (HttpServletRequest req , HttpServletResponse resp)


throws ServletException, IOException {

try {
// Comenzamos una transaccion porque usamos un Entity Manager JTA.
utx.begin();
} catch (Exception e) {
throw new ServletException(e);
}

EntityManager em = emf.createEntityManager();
try {
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
out.println("<HTML> <HEAD> <TITLE>Registro de nuevo usuario " +
"</TITLE> </HEAD> <BODY BGCOLOR=white>");
Práctica 5
String nombre = req.getParameter("nombre");
String password = req.getParameter("password");
CredencialUsuario credencial = new CredencialUsuario(nombre, password);
// em.persist hace que el objeto se vuelva persistente.
em.persist(credencial);
out.println("Se ha creado correctamente el nuevo usuario. " +
"Haz click <A HREF=\"login.html\"> aqui </A> para logarte.");
out.println("</BODY> </HTML> ");
utx.commit();
} catch (Exception e) {
try {
utx.rollback();
} catch (Exception ee) {
// Excepcion
}
throw new ServletException(e);
} finally {
em.close();
}
}

public void init( ServletConfig config) throws ServletException {


super.init(config);
}
}
Práctica 5

• Creamos ahora el documento HTML login.html:


Práctica 5

• Login.html debe tener este código:


<html>
<head>
<title>Pagina de Login</title>
</head>

<body>
<form method="post" action="login">
<p>Nombre de Usuario: <input type="text" name="nombre" size="10"> </p>
<p>Password: <input type="password" name="password" size="10"> </p>
<br>
<p>
<input type="submit" value="login"/>
<A href="registro.html"> Nuevo usuario? </A>
</form>
</body>
Práctica 5

• Creamos ahora el documento html registro.html:


Práctica 5

• Registro.html debe tener el siguiente código:


<html>
<head>
<title>Pagina de alta de nuevo usuario</title>
</head>

<body>
<form method="post" action="registro">
<p>Nombre de Usuario: <input type="text" name="nombre" size="10">
</p>
<p>Password: <input type="password" name="password" size="10"> </p>
<br>
<p>
<input type="submit" value="registro"/>
<input type="reset" value="cancelar"/>
</form>
</body>
Práctica 5

• Por último, sólo nos queda hacer un cambio en el


archivo index.jsp que tenemos por defecto. Cambiamos
el código a este:

<%

String URLRedireccion = "/ejb05-jpa/login.html";

response.sendRedirect(URLRedireccion);

%>

• Por último, hacemos un Run de la aplicación:


Práctica 5
• Debemos obtener lo siguiente:
Práctica 5

• Ahora probamos que no acepta credenciales erróneas;


sólo podemos entrar con usuario “paquito” y password
“chocolatero”.
Práctica 5

• Probamos también que nos permite acceder con el


usuario “paquito” y la password “chocolatero”.
Práctica 5

• ¿Qué esta ocurriendo aquí? SI recordamos los checks


en la creación de la unidad de persitencia:
Práctica 5

• Existe una característica en Sun Application Server y en


Glassfish llamada: Java2DB
− Esta característica es permite que el esquema de la base de
datos se cree automáticamente en Derby.
− El nombre de la tabla es en este caso, el mismo que el de la
clase entidad, en MAYÚSCULAS: “CREDENCIALUSUARIO”.
− El nombre de las columnas es el nombre de los atributos de la
clase, en MAYÚSCULAS:
• “NOMBRE”
• “PASSWORD”
− Si recordamos el
código fuente de
la clase:
Práctica 5

• ¿Cómo podríamos nosotros consultar esa base de datos?

• ¿Disponemos de un entorno amigable para hacerlo?

• Sí, dicha funcionalidad está INTEGRADA en Netbeans.


Práctica 5

• Abrimos el árbol hasta encontrarnos con la situación


descrita en la imagen siguiente (usuario “app” password
“app”):
Práctica 5

• Ahora abrimos nuevamente el árbol hasta encontrarnos


en esta situación:
Fin

Potrebbero piacerti anche