Está en la página 1de 16

Patrones de Diseño J2EE

Introducción a los Patrones

¿Qué es un Patrón?
Algunas personas definen un patrón como una solución recurrente para un problema en un contexto.
Estos términos -- contexto, problema y solución -- merecen una pequeña explicación. Primero, ¿qué es un
contexto? Un contexto es el entorno, situación, o condiciones interrelacionadas dentro de las cuales existe
algo. Segúndo, ¿qué es un problema? Un problema es una cuestión insatisfecha, algo que se necesita
investigar y resolver. Un problema se puede especificar mediante un conjunto de causas y efectos.
Normalmenete un problema está restringido al contexto en el que ocurre. Finalmente, la solución se
refiere a la respuesta al problema dentro de un contexto que ayuda a resolver las dificultades.

Entonces, si tenemos una solución a un problema en un contexto, ¿es un patrón? No necesariamente.


También necesitamos asociar la característica de recurrencia con la definición de un patrón. ¿Eso es
todo? Quizás no. Los patrones deberían comunicar soluciones de diseño a los desarrolladores y
arquitectos que los leen y los utilizan. Como puedes ver, aunque el concepto de patrón es bastante
simple, definir realmente el término es muy complejo.

Hemos señalado sólo las referencias para que puedas indagar en más profundidad en la historia de los
patrones y aprender sobre ellos en otras áreas. Sin embargo, deberías tener en mente que la definición
de patrón que hemos adoptado funciona. En nuestro catálogo, se describe un patrón de acuerdo a sus
principales características: contexto, problema y solucion, junto con otros aspectos importantes, como
causas y consecuencias. La página que describe la plantilla de patrones explica estas características en
más detalle.

Abstracción de Patrones
Un patrón describe, con algún nivel de abtrascción, una solución experta a un problema. Normalmente, un
patrón está documentado en forma de una plantilla. Aunque es una práctica estándar documentar los
patrones en un formato de plantilla especializado, esto no significa que sea la única forma de hacerlo.
Además, hay tantos formatos de plantillas como autores de patrones, esto permite la creatividad en la
documentación de patrones.

Los patrones solucionan problemas que existen en muchos niveles de abstracción. Hay patrones que
describen soluciones para todo, desde el análisis hasta el diseño y desde la arquitectura hasta la
implementación. Además, los patrones existen en diversaa áreas de interés y tecnologías. Por ejemplo,
hay un patrón que describe como trabajar con un lenguaje de programación específico o un segmento de
la industria específico, como la sanidad.

Identificar un Patrón
Se han manejado muchos proyectos J2EE en Sun Java Center, y, con el tiempo, se ha notado que
ocurren problemas similares en todos estos proyectos. También se ha visto que han emergido soluciones
similares para todos estos problemas. Aunque las estrategias de implementación variaran, las soluciones
generales eran bastante similares.
Cuando se ha visto un problema y una solución recurrentes, se ha intentado identificar y documentar sus
características usando la plantilla de patrón. Los candidatos a patrones no se han añadido al catálogo de
patrones hasta que no se ha podido observar y documentar su utilización varias veces en diferentes
proyectos. También se emprendió el procesamiento de significado de los patrones buscando patrones en
soluciones ya implementadas.
Luego, hay una "Regla de Tres", como se la conoce en la comunidad de los patrones. Esta regla es una
guiá para ascender un patrón candidato al catálogo de patrones. De acuerdo a esta regla, una solución
permanece como un patrón candidato hasta que se ha verificado en al menos tres sistemas diferentes.
Ciertamente que hay mucho espacio para la interpretación en reglas como ésta, pero ayudan a
proporcionar un contexto para la identificación de patrones.
Muchas veces, soluciones similares podrían representar un sólo patrón. Cuando se decide cómo formar
un patrón, es importante considerar cual es la mejor forma de comunicar la solución. Algunas veces, un
nombre indenpendiente mejora la comunicación entre los desarrolladores. Si es así, es mejor considerar
la documentación de dos soluciones similares como dos patrones diferentes. Por otro lado, podría ser
mejor comunicar la solución destilando las ideas similares en una combinación de patrón/estrategia.
Patrones contra Estrategias
Cuando se empezó a documentar los patrones J2EE, se tomó la decisión de documentarlos con un nivel
de abstracción relativamente alto. Al mismo tiempo, cada patrón incluye varias estrategias que
proporcionan detalles de su implementación a bajo nivel. A través de las estrategias, cada patrón
documenta una solución con varios niveles de abstracción. Se ha reconocido que se podría haber
documentado algunas de estas estrategias como patrones por sí mismas. Sin embargo, se ha creído que
la estructura de plantilla actual comunica más claramente la relación de las estrategias con la estructura
de patrón de alto nivel en que se ha incluido.

Se han anotado algunos de los problemas con respecto a la relación entre las estrategias y los patrones:
• Los patrones existen a un nivel de abstracción más alto que las estrategias.
• Los patrones incluyen implementaciones más comunes o más recomendadas que las
estrategias.
• Las estrategias proporcionan un punto de extensibilidad para cada patrón. Los desarrolladores
descubren e inventan nuevas formas de implementar patrones, produciendo nuevas estrategias
para patrones bien-conocidos.
• Las estrategias promueven una mejor comunicación, proporcionando nombres para aspectos de
bajo nivel de una solución particular.
El Catálogo de Patrones J2EE (Core J2EE Patterns)
Abajo puedes ver una representación gráfica del Catálogo de Patrones Principales de J2EE (Core J2EE
Patterns):

Catálogo de patrones J2EE

Capa de Presentación

Decorating Filter Un objeto que está entre el cliente y los componentes Web. Este procesa las
/ Intercepting peticiones y las respuestas.
Filter
Un objeto que acepta todos los requerimientos de un cliente y los direcciona a
manejadores apropiados. El patrón Front Controller podría dividir la
Front Controller/
funcionalidad en 2 diferentes objetos: el Front Controller y el Dispatcher. En
Front
ese caso, El Front Controller acepta todos los requerimientos de un cliente y
Component
realiza la autenticación, y el Dispatcher direcciona los requerimientos a
manejadores apropiados.
Un objeto helper que encapsula la lógica de acceso a datos en beneficio de
View Helper los componentes de la presentación. Por ejemplo, los JavaBeans pueden ser
usados como patrón View Helper para las páginas JSP.
Un objeto vista que está compuesto de otros objetos vista. Por ejemplo, una
Composite view página JSP que incluye otras páginas JSP y HTML usando la directiva include
o el action include es un patrón Composite View.
Es como el patrón de diseño MVC con el Controlador actuando como Front
Service To Controller pero con una cosa importante: aquí el Dispatcher (el cual es parte
Worker del Front Controller) usa View Helpers a gran escala y ayuda en el manejo de
la vista.
Es como el patrón de diseño MVC con el controlador actuando como Front
Controller pero con un asunto importante: aquí el Dispatcher (el cual es parte
Dispatcher View del Front Controller) no usa View Helpers y realiza muy poco trabajo en el
manejo de la vista. El manejo de la vista es manejado por los mismos
componentes de la Vista.

Capa de Negocio

Un objeto que reside en la capa de presentación y en beneficio de los otros


Business
componentes de la capa de presentación llama a métodos remotos de los
Delegate
objetos de la capa de negocios.
Value Object/
Data Transfer
Un objeto serializable para la transferencia de datos sobre la red.
Object/
Replicate Object
Session Façade/
El uso de un bean de sesion como una fachada (facade) para encapsular la
Session Entity
complejidad de las interacciones entre los objetos de negocio y participantes
Façade/
en un flujo de trabajo. El Session Façade maneja los objetos de negocio y
Distributed
proporciona un servicio de acceso uniforme a los clientes.
Façade
Aggregate Entity Un bean entidad que es construido o es agregado a otros beans de entidad.
Value Object Un objeto que reside en la capa de negocios y crea Value Objets cuando es
Assembler requerido.
Value List
Es un objeto que maneja la ejecución de consultas SQL, caché y
Handler/ Page-
procesamiento del resultado. Usualmente implementado como beans de
by-Page Iterator/
sesión.
Paged List
Consiste en utilizar un objeto Service Locutor para abstraer toda la utilización
JNDI y para ocultar las complejidades de la creación del contexto inicial, de
Service Locator búsqueda de objetos home EJB y recreación de objetos EJB. Varios clientes
pueden reutilizar el objeto Service Locutor para reducir la complejidad del
código, proporcionando un punto de control.
Capa de Integración

Data Access Consiste en utilizar un objeto de acceso a datos para abstraer y encapsular
Object Service todos los accesos a la fuente de datos. El DAO maneja la conexión con la
Activator fuente de datos para obtener y almacenar datos.
Se utiliza para recibir peticiones y mensajes asíncronos de los clientes.
Cuando se recibe un mensaje, el Service Activator localiza e invoca a los
Service Activator
métodos de los componentes de negocio necesarios para cumplir la petición
de forma asíncrona.

Plantilla de Patrón
Los patrones J2EE se han estructurado de acuerdo a una plantilla de patrón definida. Cada sección de la
plantilla de patrón contribuye a entender el patrón particular. También observarás que se ha intentado dar
un nombre de patrón descriptivo a cada patrón J2EE. Aunque es dificil acompasar un patrón singular con
su nombre, se ha intentado que los nombres de patrón proporcionen suficiente información sobre la
función del patrón.

Se ha adoptado una plantilla de patrón que consta de las siguientes secciones:

• Contexto:
Conjunto de entornos bajo los cuales existe el patrón.

• Problema:
Describe los problemas de diseño que se ha encontrado el desarrollador.

• Causas:
Lista los razones y motivos que afectan al problema y la solución. La lista de causas ilumina las
razones por las que uno podría haber elegido utilizar el patrón y proporciona una justificación de
su uso.

• Solución:
Describe brevemente la solución y sus elementos en más detalle. La sección de la solución
contiene dos sub-secciones:

o Estructura:
Utiliza diagramas de clases UML para mostrar la estructura básica de la solución. Los
diagramas de secuencias UML de esta sección presentan los mecanismos dinámicos
de la solución. Hay una explicación detalladas de los participantes y las colaboraciones.

o Estrategias:
Describe diferentes formas en las que se podría implementar el patrón.

• Consecuencias:
Aquí se describen las compensaciones del patrón, esta sección se enfoca en los resultados de la
utilización de un patrón en particular o de su estrategia, y anota los pros y los contras que
podrían resultar de la aplicación del patrón.

• Patrones Relacionados:
Esta sección lista otros patrones relevantes en el catálogo de patrones J2EE u otros recursos
externos, como los patrones de diseño GoF. Por cada patrón relacionado, hay una breve
descripción de su relación con el patrón que se está describiendo.

Service Activator

Contexto
Los beans enterprise y otros servicios de negocio necesitan una forma de activarse asíncronamente.

Problema
Cuando un cliente necesita acceder a un bean enteprise, primero busca el objeto home del bean. Luego el
cliente le pide a ese objeto home que le proporcione una referencia remota al bean enterprise requerido.
Entonces el cliente invoca a los métodos de negocio sobre la referencia remota para acceder a los
servicios del bean enterpise. Estas llamadas a métodos, así como las búsquedas y las llamdas a métodos
remotos, son síncronos. El cliente tiene que esperar hasta que esos metodos retornan.

Otro factor a considerar es el ciclo de vida de un bean enterprise. La especificación EJB permite que el
contenedor pasivice un bean enterprise a un almacenamiento intermedio. Como resultado, el contenedor
EJB no tiene un mecanismo mediante el cual poder proporcionar un servicio estilo-proceso para mantener
un bean enterprise constantemente activado y en estado listo. Como el cliente debe interactúar con el
bean enterprise utilizando su interface remoto, incluso si el bean está en estado activado en el
contenedor, el cliente áun necesita obtener su interface remoto mediante un proceso de búsqueda y
todavía actúa con el bean de forma síncrona.

Si una aplicación necesita procesamiento síncrono para sus componentes de negocio del lado del
servidor, entonces los beans enterprise son una opción apropiada. Algunas aplicaciones cliente podrían
requerir este tipo de procesamiento porque los clientes no necesitan esperar o no tienen tiempo para
esperar a que se complete el procesamiento. En caso donde la aplicación necesita una forma de
procesamiento asíncrono, los beans enterpise no ofrecen esta capacidad en implementaciones anteriores
a la especificación EJB 2.0.

La especificación EJB 2.0 proporciona integración introduciendo el bean dirigido-a-mensaje, que es un


tipo especial de bean de sesión sin estado que ofrece capacidades de invocación asíncrona. Sin
embargo, la nueva especificación no ofrece invocación asíncrona para otros tipos de beans enterprise,
como los beans con estado o de entidad.

En general, un servicio de negocio como un bean de sesión o de entidad sólo proporciona procesamiento
síncrono y esto representa un reto para implemenetar procesamiento asíncrono.

Causas

• Los beans enterprise se exponen a sus clientes mediante sus interfaces remotos, que sólo
permiten acceso síncrono.

• El contenedor maneja los beans enterprise, permitiendo interacciones sólo mediante referencias
remotas. El contenedor EJB no permite acceso directo a la implementación del bean y sus
métodos. Así, implementar el oyente de mensajes JMS no es factible en un bean enterprise, ya
que esto viola la especificación EJB al permitir el acceso directo a la implementación del bean.

• Una aplicación necesita proporcionar un marco de mensajería publicar/suscribir o punto-a-punto


donde los clientes puedan publicar peticiones a beans enterprise para procesamiento asíncrono.

• Los clientes necesitan capacidades de procesamiento asíncrono en los beans entreprise y otros
componentes de negocio que sólo pueden ofrecer acceso síncrono, para que el cliente pueda
enviar una petición para su procesamiento sin esperar los resultados.

• Los clientes quieren utilizar interfaces de la capa media orientados a mesnajes (MOM) ofrecidos
por el API Java Messaging Service (JMS). Estos interfaces no están integrados en los productos
servidores EJB que están basados en especificaciones anteriores a la la EJB 2.0.

• Una aplicación necesita proporcionar un servicio estilo "criado(daemon)" para que un bean
enterprise pueda estar en modo callado hasta que un evento (o un mensaje) dispare su
actividad.

• Los beans enterprise están sujetos al control de su ciclo de vida por parte del contenedor, lo que
incluye la pasivización debido a periodos de inactividad y control de recursos. El cliente tendrá
que invocar a un bean enteprise para activarlo de nuevo.

• La especificación EJB 2.0 introdujo un bean dirigio-a-mensaje como un bean de sesión sin
estado, pero no es posible invocar otros tipos diferentes de beans enteprise de forma asíncrona.

Solución
Utilizar un Service Activator para recibir peticiones y mensajes asíncronos de los clientes. Cuando
se recibe un mensaje, el Service Activator localiza e invoca a los métodos de de los componentes
de negocio necesarios para cumplir la petición de forma asíncrona.

El ServiceActivator es un oyente JMS y un servicio de delegación que requiere la implementación de


un oyente de mensajes JMS. Se puede implementar como un servicio independiente. Los clientes actúan
como generadores de mensajes, generando eventos basándose en su actividad.

Cualquier cliente que necesite invocar asíncronamente un servicio de negocio, como un bean enteprise,
podría crear y enviar un mensaje al Service Activator. Éste recibe el mensaje y lo analiza para interpretar
la petición del cliente. Una vez que se ha analizado y desempaquetado la petición del cliente, el Service
Activator identifica y localiza los componentes de servicio de negocio necesarios e invoca a sus métodos
de negocio para completar el procesamiento de la petición del cliente de forma asíncrona.

Service Activator opcionalmente podría enviar un reconocimiento al cliente después de que haya
completado el procesamiento de la petición. También podría notificar al cliente o a otros servicios si
ocurre un fallo durante el procesamiento de la petición.

El Service Activator podría utilizar los servicios de un Service Locator.

Estructura

La siguiente figura representa las relaciones entre clases para el patrón Service Activator:

Participantes y Responsabilidades

La siguiente figura muestra las interacciones entre los distintos participantes en el patrón Service
Activator:
Ejemplo
ServiceActivatorBean.java
package drivenbeans;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.EJB;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import sessionbeans.Service1Local;
import sessionbeans.Service2Local;

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


@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue
= "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue
= "javax.jms.Queue")
})
public class ServiceActivatorBean implements MessageListener {

@EJB
private Service2Local service2Bean;
@EJB
private Service1Local service1Bean;

public ServiceActivatorBean() {
}

public void onMessage(Message message) {

TextMessage msg = (TextMessage) message;


try {
String servicio = msg.getText();
if (servicio.equalsIgnoreCase("service1"))
service1Bean.metodoDeServicio();
if (servicio.equalsIgnoreCase("service2"))
service2Bean.metodoDeServicio();

} catch (JMSException ex) {

}
}

Service1Bean.java
package sessionbeans;

import javax.ejb.Stateless;

@Stateless
public class Service1Bean implements Service1Local {

public void metodoDeServicio() {


System.out.println("Se ha invocado el servicio 1");
}

Service1Local.java
package sessionbeans;

import javax.ejb.Local;

@Local
public interface Service1Local {

public void metodoDeServicio();


}

Service2Bean.java
package sessionbeans;

import javax.ejb.Stateless;

@Stateless
public class Service2Bean implements Service2Local {

public void metodoDeServicio() {


System.out.println("Se ha invocado el servicio 2");
}

Service2Local.java
package sessionbeans;

import javax.ejb.Local;

@Local
public interface Service2Local {
public void metodoDeServicio();
}
Formulario.jsp
<html>
<body>
<form name="formulario" action="Controlador">
Escriba el nombre del servicio<br/>
(service1, service2)<input type="text" name="servicio">
<input type="submit" value="Ejecutar servicio">
</form>

</body>
</html>

Controlador.java
package servlets;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Controlador extends HttpServlet {

@Resource(name = "jms/server")
private Queue server;
@Resource(name = "jms/serverFactory")
private ConnectionFactory serverFactory;

protected void processRequest(HttpServletRequest request,


HttpServletResponse response)
throws ServletException, IOException {
try {
String servicio = request.getParameter("servicio").toString();
sendJMSMessageToServer(servicio);
} catch (JMSException ex) {
}

private Message createJMSMessageForjmsServer(Session session, Object


messageData) throws JMSException {
// TODO create and populate message to send
TextMessage tm = session.createTextMessage();
tm.setText(messageData.toString());
return tm;
}

private void sendJMSMessageToServer(Object messageData) throws


JMSException {
Connection connection = null;
Session session = null;
try {
connection = serverFactory.createConnection();
session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(server);
messageProducer.send(createJMSMessageForjmsServer(session,
messageData));
} finally {
if (session != null) {
try {
session.close();
} catch (JMSException e) {
Logger.getLogger(this.getClass().getName()).log(Level.WARN
ING, "Cannot close session", e);
}
}
if (connection != null) {
connection.close();
}
}
}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
processRequest(request, response);
}

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
processRequest(request, response);
}
}

Data Access Object

Contexto

El acceso a los datos varía dependiendo de la fuente de los datos. El acceso al almacenamiento
persistente, como una base de datos, varía en gran medida dependiendo del tipo de almacenamiento
(bases de datos relacionales, bases de datos orientadas a objetos, ficheros planos, etc.) y de la
implementación del vendedor.

Problema

Muchas aplicaciones de la plataforma J2EE en el mundo real necesitan utilizar datos persistentes en
algún momento. Para muchas de ellas, este almacenamiento persistente se implementa utilizando
diferentes mecanismos, y hay marcadas diferencias en los APIS utilizados para acceder a esos
mecanismos de almacenamiento diferentes. Otras aplicaciones podrían necesitar acceder a datos que
residen en sistemas diferentes. Por ejemplo, los datos podrían residir en sitemas mainframe, repositorios
LDAP, etc. Otro ejemplo es donde los datos los proporcionan servicios a través de sistemas externos
como los sistemas de integración negocio-a-negocio (B2B), servicios de tarjetas de crédito, etc.

Normalmente, las aplicaciones utilizan componentes distribuidos y compartidos como los beans de
entidad para representar los datos persistentes. Se considera que una aplicación emplea consistencia
manejada por el bean (BMP) cuando sus beans de entidad acceden explícitamente al almacenamiento
persistente -- el bean de entidad incluye código para hacer esto. Una aplicación con requerimientos
sencillos podría por lo tanto utilizar beans de entidad en lugar de beans de sesión o servlets para acceder
al almacenamiento persistente y recuperar o modificar los datos. O, la aplicación podría usar beans de
entidad con persistencia manejada por el contenedor, y así dejar que el contenedor maneje los detalles de
las transaciones y de la persistencia.

Las aplicaciones pueden utilizar el API JDBC para acceder a los datos en un sistema de control de bases
de datos relacionales (RDBMS). Este API permite una forma estándar de acceder y manipular datos en un
almacenamineto persistente, como una base de datos ralacional. El API JDBC permite a las aplicaciones
J2EE utilizar sentencias SQL, que son el método estándar para acceder a tablas RDBMS. Sin embargo,
incluso dentro de un entorno RDBMS, la síntaxis y formatos actuales de las sentencias SQL podrían
variar dependiendo de la propia base de datos en particular.
Incluso hay una mayor variación con diferentes tipos de almacenamientos persistentes. Los mecanimos
de acceso, los APIs soportados, y sus características varian entre los diferentes tipos de
almacenamientos persistentes, como bases de datos relacionales, bases de datos orientadas a objetos,
ficheros planos, etc. Las aplicaciones que necesitan acceder a datos de un sistema legal o un sistema
dispar (como un mainframe o un servicio B2B) se ven obligados a utilizar APIs que podrían ser
propietarios. Dichas fuentes de datos dispares ofrecen retos a la aplicación y potencialmente pueden
crear una dependencia directa entre el código de la aplicación y el código de acceso a los datos. Cuando
los componentes de negocio -- beans de entidad, beans de sesión e incluso componentes de
presentación como servlets y beans de apoyo para páginas JSP -- necesitan acceder a una fuente de
datos, pueden utilizar el API apropiado para conseguir la conectividad y manipular la fuente de datos.
Pero introducir el código de conectividad y de acceso a datos dentro de estos componentes genera un
fuerte acoplamiento entre los componentes y la implementación de la fuente de datos. Dichas
dependencias de código en los componentes hace difícil y tedioso migrar la aplicación de un tipo de
fuente de datos a otro. Cuando cambia la fuente de datos, también deben cambiar los componentes para
manejar el nuevo tipo de fuente de datos.

Causas

• Los componentes como los beans de entidad controlados por el bean, los beans de sesión, los
servlets, y otros objetos como beans de apoyo para páginas JSP necesitan recuperar y
almacenar información desde almacenamientos persistentes y otras fuentes de datos como
sistemas legales, B2B, LDAP, etc.

• Los APIs para almacenamiento persistente varían dependiendo del vendedor del producto. Otras
fuentes de datos podrían tener APIS que no son estándar y/o propietarios. Estos APIs y sus
capacidades también varían dependiendo del tipo de almacenamiento -- bases de datos
relacionales, bases de datos orientadas a objetos, documentos XML, ficheros planos, etc. Hay
una falta de APIs uniformes para corregir los requrimientos de acceso a sistemas tan dispares.

• Los componentes normalmente utilizan APIs propietarios para acceder a sistemas externos y/o
legales para recuperar y almacenar datos.

• La portabilidad de los componentes se ve afectada directamente cuando se incluyen APIs y


mecanismos de acceso específicos.

• Los componentes necesitan ser transparentes al almacenamiento persistente real o la


implementación de la fuente de datos para proporcionar una migración sencilla a diferentes
productos, diferentes tipos de almacenamiento y diferentes tipos de fuentes de datos.

Solución

Utilizar un Data Access Object (DAO) para abstraer y encapsular todos los accesos a la fuente de
datos. El DAO maneja la conexión con la fuente de datos para obtener y almacenar datos.

El DAO implementa el mecanismo de acceso requerido para trabajar con la fuente de datos. Esta fuente
de datos puede ser un almacenamiento persistente como una RDMBS, un servicio externo como un
intercambio B2B, un repositorio LDAP, o un servicio de negocios al que se accede mediante CORBA
Internet Inter-ORB Protocol (IIOP) o sockets de bajo nivel. Los componentes de negocio que tratan con el
DAO utilizan un interface simple expuesto por el DAO para sus clientes. El DAO oculta completamente los
detalles de implementación de la fuente de datos a sus clientes. Como el interface expuesto por el DAO
no cambia cuando cambia la implementación de la fuente de datos subyacente, este patrón permite al
DAO adaptarse a diferentes esquemas de almacenamiento sin que esto afecte a sus clientes o
componentes de engocio. Esencialmente, el DAO actúa como un adaptador entre el componente y la
fuente de datos.

Estructura

La siguiente figura muestra el diagrama de clases que representa las relaciones para el patrón DAO:
Participantes y Responsabilidades

La siguiente figura muestra el diagrama de secuecnia de la interacción entre los distintos participantes en
este patrón:
Ejemplo

Cliente.java
package beans;

public class Cliente {

private String nombre;


private String apellidos;
private String dni;

public String getNombre() {


return nombre;
}

public void setNombre(String nombre) {


this.nombre = nombre;
}

public String getApellidos() {


return apellidos;
}

public void setApellidos(String apellidos) {


this.apellidos = apellidos;
}

public String getDni() {


return dni;
}

public void setDni(String dni) {


this.dni = dni;
}
}

ClienteDAO.java
package dao;
import beans.Cliente;

public interface ClienteDAO {


public void salvar(Cliente c);
}

DBClienteDAO.java
package negocio;

import dao.ClienteDAO;
import beans.Cliente;
public class DBClienteDAO implements ClienteDAO{

public void salvar(Cliente c) {


System.out.println("Registro Salvado a Base de Datos");
//Este método invoca a JDBC nativo para lanzar el insert
//contra la base de datos
}

FileClienteDAO.java
package negocio;

import beans.Cliente;
import dao.ClienteDAO;

public class FileClienteDAO implements ClienteDAO{

public void salvar(Cliente c) {


System.out.println("Registro salvado a fichero");
}

Controlador.java
package servlets;

import beans.Cliente;
import dao.ClienteDAO;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import negocio.DBClienteDAO;
import negocio.FileClienteDAO;

public class Controlador extends HttpServlet {

protected void processRequest(HttpServletRequest request,


HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
String nombre = request.getParameter("nombre");
String apellidos = request.getParameter("apellidos");
String dni = request.getParameter("dni");
Cliente c = new Cliente();
c.setNombre(nombre);
c.setApellidos(apellidos);
c.setDni(dni);
ClienteDAO clienteDAO = new FileClienteDAO();
clienteDAO.salvar(c);
} finally {
out.close();
}
}

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
processRequest(request, response);
}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
processRequest(request, response);
}

@Override
public String getServletInfo() {
return "Short description";
}

Formulario.jsp
<html>
<body>
<form name="formulario" action="Controlador">
Nombre:<input type="text" name="nombre"/><br/>
Apellidos:<input type="text" name="apellidos"/><br/>
dni:<input type="dni" name="dni"/><br/>
<input type="submit" value="Guardar Datos"/>
</form>
</body>
</html>