Download Seminario Spring Remoting 9 de Octubre de 2008 9 de Octubre de

Document related concepts
no text concepts found
Transcript
Seminario Spring Remoting
9 de Octubre de 2008
Spring Remoting
1
¿Qué es Spring Framework?
Nace con el objeto de reducir la complejidad en el desarrollo de aplicaciones
empresariales.
Spring es definido como un framework que se comporta a la vez como un contenedor
orientado a aspectos y con una base de inyección de dependencias ligero.
Ligero: Es ligero tanto en términos de tamaño como de sencillez en el desarrollo.
Dependency Injection. Los objetos declaran las dependencias con el resto de
componentes del sistema/arquitectura y es el contenedor el encargado de resolver éstas.
Orientación a aspectos: Permite separar la lógica de negocio de los servicios de
middleware: transaccionalidad, seguridad, logging, etc…
Contenedor: Contiene y gestiona el ciclo de vida de los objetos que contiene.
Framework: Es posible configurar y componer componentes complejos a partir de
componentes más simples. Spring incorpora mucha funcionalidad de infraestructura,
permitiendo que el desarrollador se centre en la lógica de negocio.
NO PRETENDE REINVENTAR LA RUEDA. Asume que hay buenas soluciones para la capa
de persistencia (Hibernate, Ibatis, etc..) y para la capa Web (Struts, JSF, etc…). Se integra
hasta con la tecnología motivo de su génesis (EJB’s).
Spring Remoting
2
Módulos Spring Framework
Spring MVC:
Implementación alternativa a Struts. Nace como alternativa menos intrusiva facilitando la reutilización de
componentes y la independencia tecnológica
Integración con Hibernate(ORM):
Implementa el patrón DAO y aisla al desarrollador de la obtención de la conexión con la BBDD y simplifica la etapa de
configuración.
Los componentes DAO únicamente presentan el código de persistencia mínimo (no es responsable de la obtención y el
cierre de la conexión).
La transaccionalidad es gestionada mediante aspectos de un modo standalone. No hay necesidad de disponer de un
contenedor que de los servicios de infraestructura de un modo intrusivo. (Módulo AOP).
Remoting:
Los componentes pueden ser invocados remotamente mediante la incorporación de
componentes “Exporter”. Es decir, cualquier componente desarrollado de la capa de servicio
puede ser expuesto como un servicio remoto sin que fuese desarrollado para tal fin.
Posibilidad de invocación mediante HTTP/RMI/SOAP/REST (XML + HTTP)/Hessian and Burlap
(RMI binario y optimizado).
Aíslas al desarrollador de la complejidad tecnológica subyacente.
Posibilidad de ejecutarse todo el código fuera de contenedores específicos para la capa de
negocio. En caso de aplicación web, únicamente es necesario un contenedor de servlets.
Spring Remoting
3
Módulos Spring Framework (II)
Spring Remoting
4
Spring Framework – Servicios enterprise
Presenta API’s que facilita de servicios enterprise:
JavaMail. Permite de una manera sencilla el envío de un correo, con todas las alternativas de
configuración: SMTP seguro/no seguro.
Quartz Scheduler. Permite la planificación de tareas con la potencia de las expresiones Cron.
Infraestructura de monitorización y gestión JMX (equivalente a SNMP). Permite disponer de
una infraestructura para la monitorización y gestión de los servicios/sistemas de las aplicaciones
desarrolladas.
Todos los fabricantes de contenedores J2EE, se han visto en la tesitura de publicar que son
compatibles con Spring, incluso elaborar herramientas de apoyo al desarrollo. Ejemplos:
BEA: http://e-docs.bea.com/platform/suppconfigs/configs/spring/
Oracle:
http://www.oracle.com/corporate/press/2007_may/SpringDevKit.html
IBM:
http://www.ibm.com/developerworks/websphere/library/techarticles/0706_johnsonbuck/0706_johnsonbuck.html
Spring Remoting
5
Dependency Injection
En un principio es conocido como el patrón Inversion Of Control (IoC).
¿Qué es lo que se está invirtiendo?. Martin Fowler 2004. Concluyó que lo que se estaba invirtiendo era la
obtención de dependencias. A partir de ese momento, el patrón paso a conocerse como “Dependency
Injection”.
Tradicionalmente, cada objeto es responsable de obtener las referencias de los objetos con los que
trabaja. Esto puede conducir a un fuerte acoplo entre componentes, así como un código difícil de probar.
Con DI las dependencias son inyectadas a los objetos por una entidad externa, con lo que los componentes
únicamente “declaran” su dependencia con otros objetos, sin ser responsables de obtener las referencias
de los mismos.
La principal ventaja de DI es el desacoplo de componentes.
Se aconseja el uso de interfaces con el objeto de ocultar la implementación de los componentes asociados,
mejorando aún más el desacoplo.
Dentro de Spring existe un componente llamado BeanFactory (contenedor) encargado de contener e
instanciar los objetos de la aplicación, así como resolver las dependencias entre los mismos.
XmlBeanFactory es una implementación que define los mismos, en un fichero XML.
El proceso de ir definiendo las asociaciones entre componentes siguiendo el patrón DI, es conocido como
wiring.
Spring Remoting
6
Exposición de servicios remotos basados en POJOS
7
Spring Remoting
7
Introducción
Gracias al poder de DI y al desacoplo de componentes, es posible exponer declarativamente
lógica de negocio como un servicio con invocación remota. El desarrollador no tiene por qué
conocer las particularidades del protocolo subyacente.
Los distintos protocolos soportados son:
Servicios RMI
Servicios Hessian and Burlap (Caucho)
Innovaciones HTTP de servicios Spring
Spring Web Services (Xfire)
Spring Remoting
8
Exposición servicio mediante RMI. Parte cliente
Desde el punto de vista del cliente, la programación tradicional de un consumidor de servicios RMI
presentaba dos potenciales problemas:
Excepciones que deben ser capturadas o relanzadas: RemoteException, NotBoundException,
MalformedURLException. Ejemplo: En el caso que se indique mal la localización del servicio, la única
manera de resolverlo es recompilando el código involucrado en definir la URL (o reconfigurando las
propiedades del servicio). ¿Por qué tratar este tipo de excepciones?.
EL método de localización de un servicio RMI, normalmente incumple el principio fundamental de DI,
con lo que el objeto cliente es responsable de obtener la referencia del servicio RMI.
Con Spring, el cliente se va a comunicar con el servicio remoto mediante el uso de un proxy.
El proxy se encarga de ocultar al cliente de las particularidades del protocolo. Asimismo las
excepciones propias del protocolo las convierte en excepciones de Runtime (el cliente no trata
excepciones propias del protocolo)
Spring Remoting
9
Exposición de servicio mediante RMI. Parte servidora
Pasos a realizar en una implementación clásica:
La implementación de los métodos del servicio deben lanzar java.rmi.RemoteException
EL interfaz del servicio debe extender de java.rmi.Remote
Compilar los fuentes con el compilador de RMI (rmic) para producir los stubs y skeleton.
Arrancar un registro RMI
Registrar los servicios en el registro RMI
Spring te simplifica todos estos pasos de la siguiente manera:
El interfaz no es necesario que extienda de java.rmi.Remote
La implementación del servicio es un POJO sin necesidad de lanzar excepciones java.rmi.RemoteException. Por tanto, el
componente no tiene ningún código asociado que le haga “comportarse” como un servicio RMI.
Una vez definida la implementación e interfaz del servicio, Spring proporciona un componente RMIServiceExporter con
todo lo necesario para exponer la lógica como servicio RMI. Por defecto se intenta conectar con el registro RMI en el
puerto 1099 de la máquina local. En el caso que se quiera redefinir hay que establecer valor para las propiedades
registryHost y registryPort.
RMI presenta dos inconvenientes fundamentales:
No trabaja bien con firewalls (existe la posibilidad de tunelar el tráfico RMI).
El cliente y el servidor deben ser código Java
Spring Remoting
10
Exposición mediante Hessian and Burlap
Ambos protocolos usan HTTP como protocolo de capa de aplicación (modelo OSI)
Hessian lleva asociado un protocolo binario propio y con API’s para ser manejado por clientes
que no sean Java: PHP, Python, C++, C#.
Burlap, sin embargo, es un protocolo basado en tramas XML con lo que el abanico de clientes
se aumenta.
Por tanto, en el caso que haya restricciones de ancho de banda Hessian sería la solución más
óptima. Sin embargo, si se quiere que la comunicación sea legible se aconseja el uso de
Burlap.
Spring Remoting
11
Configuración Hessian/Burlap
Desde el punto de vista del cliente la configuración es exactamente igual. Para el caso de Hessian se genera
el proxy mediante la clase HessianProxyFactoryBean y en el caso de Burlap con la clase
BurlapProxyFactoryBean.
Exposición de servicio Hessian
La implementación del servicio debe extender de HessianServlet. Los métodos deben ser públicos.
Sin embargo, con Spring no es necesario este paso, puesto que tiene un componente que aisla de todas las
particularidades del servicio: HessianServiceExporter.
Es necesario configurar el controlador de Hessian encargado de definir los endpoints donde los servicios
escucharan (URL HTTP).
HessianServiceExporter es configurado como un controlador Spring MVC. Por tanto es necesario definir el
DispatcherServlet, así como el manejador de URL’s.
De la misma manera es posible exponer lógica de negocio como WebService mediante el uso de Xfire
Spring Remoting
12
Exposición de servicios mediante XFire
XFire permitirá el exportar los métodos de la lógica de negocio implementada en POJOS como un web
services. XFire permitirá por tanto traducir los mensajes de entrada SOAP en invocaciones a métodos
Java.
XFire presenta una aproximación bottom-up donde se expone directamente como Servicio Web la API
interna de nuestra aplicación.
Como ventaja presenta la posibilidad de abstraer al programador de los detalles de la tecnología
subyacente.
A continuación se ve el diagrama donde se explica el comportamiento del componente XFireExporter:
Spring Remoting
13
Declaración de servicios Web usando anotaciones JSR- 181
El problema principal que presenta la solución con XFireExporter es que es necesario definir el
bean de exportación por cada bean que quieras exportar como servicio web.
Para poder usar las anotaciones con XFire es necesario incluir el soporte JAX-WS para Xfire
(dependencia de Maven).
Las anotaciones se realizan sobre la clase y el interfaz.
Por defecto, se publican todos los métodos públicos de la clase. Cuidado, por tanto, con
exponer métodos de la API interna de la aplicación.
Dentro de Spring es necesario configurar un mapeador de direcciones específico para que el
DispatcherServlet interprete las anotaciones JSR-181 de los beans: JSR181HandlerMapping.
Finalmente todos aquellos beans que estén anotados responderán a la dirección:
http://<host>:<port>/<contextApp>/services/<serviceName>?wsdl
Spring Remoting
14
Consumiendo web services
Aunque es posible realizar la llamada al web service mediante la API de XFire:
ObjectServiceFactory y XFireProxyFactory, lo lógico es aprovechar las ventajas del patrón DI,
evitando al cliente tener que conocer las particularidades de la API.
Siguiendo la misma filosofía que en los casos anteriores, haremos uso de una factoría de
Proxies que serán los encargados de implementar toda la lógica específica del protocolo.
Existen dos proxies para poder realizar esta labor:
JaxRpcPortProxyFactoryBean. Esta implementación es propia de Spring
XFireClientFactoryBean: Esta factoría es provista dentro de Xfire.
Elegiremos XFire por la gestión implícita que hace de los tipos complejos, así como la sencillez
a la hora de definirlo: no es necesario definir el nombre del servicio, nombre del puerto,
namespace, puesto que él automáticamente lo descubre a partir del WSDL.
Al igual que en los casos anteriores el proxy es el que se inyecta al bean cliente, con el objeto
de proporcionar una referencia al servicio de invocación remoto.
Spring Remoting
15
XFireClientFactoryBean
Spring Remoting
16
Conclusiones
La exposición de lógica de negocio como servicio mediante el uso de componentes
exportadores (aplicación del patrón DI y uso de AOP), permite una solución sencilla, donde no
es necesario conocer las particularidades de las tecnologías y protocolos subyacentes.
Presenta la ventaja de poder probar la lógica de negocio, puesto que se trata de un POJO.
Posibilidad de disponer de mecanismos más ligeros que SOAP, con lo que el rendimiento
aumenta.
Posibilidad de cambio en el método de exposición, sin que se vean afectadas la parte cliente y
la parte servidora.
Se desarrollan más rápidos que con Spring-WS
Tener cuidado con no exponer la API interna de la aplicación. Quizás será necesario el generar
componentes de la capa de servicio de más alto nivel.
Cambios en las API’s afectan al entorno cliente (suponen un cambio en el contrato/interfaz). La
aproximación no tiene en cuenta el contrato con el cliente.
Spring Remoting
17
Implementando Web Services con Spring
Aproximación top-down (contract first)
18
Spring Remoting
18
Introducción – Spring WS
Como se ha comentado anteriormente los mecanismos de exposición de JavaBeans como
servicio remoto, presenta la desventaja de ofrecer la API interna de la aplicación.
Como contraposición a este modelo se presenta un modelo de trabajo top-down, donde se
enfatiza en qué ofrece el servicio (contrato) del cómo es implementado el mismo.
Esto permite que podamos evolucionar el interfaz entre el cliente y el servidor, permitiendo
compatibilidad hacia atrás. En el modelo anterior, cambios en la API conducen a cambios en el
contrato.
Por tanto, en esta aproximación los pasos a realizar son los siguientes:
Definir el contrato de servicio: Se definen los mensajes de entrada y salida del servicio, se
generan los esquemas XML , los cuales serán usados posteriormente en el WSDL.
Implementación del service endpoint. Básicamente este componente se encarga de gestionar
los mensajes de entrada y salida del servicio.
Configuración del endpoint y de la infraestructura Spring-WS. En este paso, se generará el WSDL
usando los componentes que ofrece el framework
Spring Remoting
19
Definición del contrato
Para la defínición del contrato es necesario modelar los mensajes XML de entrada y de salida.
A partir de éstos se infiere el esquema XML. Este paso evita el tener que conocer con gran
detalle las particularidades de la tecnología Schema XML. En el ejemplo del seminario se ha
usado la herramienta Trang.
El contrato de servicio se divide en dos partes:
El contrato a nivel de datos: Se definen los mensajes de entrada y de salida del servicio.
Contrato operacional: Define las operaciones de servicio. Una operación de servicio no tiene
por qué coincidir con un método en la API de servicio.
Por tanto, el WSDL se divide en dos partes diferenciadas:
Contrato de datos: Donde se incluyen los esquemas de los mensajes de entrada y de salida:
elementos <wsdl:types> y <wsdl:message>.
Contrato de servicio: Elementos <wsdl:portType> y <wsdl:binding>.
Spring Remoting
20
Manejando los mensajes con Service Endpoints
Básicamente estos componentes se encargan de gestionar los mensajes XML de entrada y de salida.
Los tipos de endpoints que Spring-WS ofrecen son muy variados.
Existe la posibilidad de trabajar con cualquier parseador XML: SAX, DOM, StAX.
Se integra con las API’s DOM4j, JDOM.
Con el objeto de abstraer al programador del tratamiento a bajo nivel del mensaje se ofrece una API: OXM (
Object-XML-Mapping) que realiza procesos de marshalling y unmarshalling de los mensajes.
OXM tiene soporte para Castor XML, JAXB v1, JAXB v2, JIBX, XmlStream (limitaciones con namespaces),
XMLBeans.
Es importante que el MessageEndpoint no se encargue de realizar directamente la lógica de negocio, sino
que se inyecte un componente encargado de realizar ésta. Permite la separación del contrato de datos del
contrato operacional.
Spring Remoting
21
Configuración de Spring WS
En la configuración de Spring es necesario definir los siguientes tipos de beans:
Mapeador de entrada (PayloadMapping). Encargado de redirigir los mensajes XML de entrada al
correspondiente endpoint (Se realiza a partir del nombre cualificado del XML (namespace +
elemento raíz).
MessageEndpoint. Componente encargado de procesar los ficheros XML del servicio
(entrada/salida).
Bean lógica de negocio. Se encarga de a partir de los datos de entrada (objetos Java) invocar a la
logica de negocio y generar los datos de salida. Este objeto se inyecta al MessageEndpoint.
Marshaller. Encargado de realizar los procesos de marshalling y unmarshalling. En nuestro caso
se realiza usando Castor XML y apoyándose en el fichero de mapeo.
ExceptionResolver: Encargado de generar una SOAP fault a partir de las excepciones Java
producidas en la cadena de proceso.
Generador dinámico de WSDL. A partir de los esquemas XML y en función de una serie de
convenciones (Request y Response) genera los ficheros descriptores del servicio Web. Es
posible proporcionar WSDL de manera estática
Spring Remoting
22
ExceptionResolver & Generador dinámica WSDL
Spring Remoting
23
DispatcherServlet
Finalmente es necesario configurar un DispatcherServlet específico para poder permitir que la invocación
de los servicios web se realice mediante el protocolo HTTP.
Spring Remoting
24
Consumición de servicios web con Spring-WS. WebServiceTemplate
Trabajar con WebServiceTemplate. El cliente trabaja directamente con mensajes XML y es el template el encargado de
realizar las traducciones necesarias para uso del protocolo SOAP. Básicamente este tipo de templates necesita un
componente para poder enviar el mensaje via HTTP (MessageSender) y una factoría de mensajes(MessageFactory)
encargada de generar el mensaje SOAP. Existen los siguientes tipos de MessageFactory:
AxiomSOAPMessageFactory: Genera los mensajes SOAP usando la API de Axiom (Axis Object Model). Está basado en la API de
StAX y se recomienda cuando los mensajes del servicio se prevean sean de un volumen considerable
DomPoxMessageFactory: Produce XML plano y es usado para cuando no se prevea el uso de SOAP. En la versión 2 de Spring-WS
se prevee soporte para interfaces REST (☺).
SaajSOAPMessageFactory: Usa la API SAAJ (Soap With Attachment API). Internamente usa DOM. Cuidado con mensajes largos Rendimiento bajo.
Igualmente existen dos tipos de MessageSender: Uno que trabaja directamente con el soporte de gestión HTTP de la JDK:
HttpURLConnectiony otro que trabaja con la librería commons-http. Éste último se considera más idóneo para
autenticación HTTP y pool de conexiones HTTP.
Es posible usar las capacidades de marshalling y unmarshalling para que el cliente componga el mensaje. En este caso el
serviceTemplate mantiene una referencia al objeto marshaller y unmarshaller.
Spring Remoting
25
WebServiceTemplate con soporte para marshalling
Spring Remoting
26
Consumición de servicios web con Spring-WS. Soporte gateway
Es posible en Spring-WS evitar que el template sea inyectado. Para ello se ofrece una clase de
soporte que automáticamente genera el WebServiceTemplate.
Logicamente es necesario proveer un bean definiendo el gateway con la configuración
necesaria para que éste pueda crear el WebServiceTemplate (MessageSender, marshaller y
unmarshaller).
Spring Remoting
27
Conclusiones finales. Contract-first vs contract-last
Fragilidad. Cada vez que se cambia el interfaz Java se cambia el contrato de servicio generado.
Por tanto, es necesario mantener el contrato con el cliente aunque cambie la API.
Rendimiento: Cuando se renderiza automáticamente el objeto Java en XML, puede tener una
penalización en el rendimiento (referencias cruzadas). En el caso de contract-first se explicita
el mensaje XML que va por el interfaz.
Reusabilidad. El esquema XML es un fichero que puede ser reusado para generar el WSDL, o
en otros esquemas.
Versionado. Al mantener desacoplado el contrato de la implementación es posible mantener
el contrato cambiando la implementación del servicio. Además es posible mantener
compatibilidad hacia atrás, por ejemplo realizando transformaciones de mensajes antiguos en
el nuevo.
Soporte de protocolos HTTP/JMS e Email.
Los procesos de logging y auditoría de mensajes está integrados con Log4j:
log4j.logger.org.springframework.ws.client.MessageTracing.sent=TRACE
log4j.logger.org.springframework.ws.client.MessageTracing.received=DEBUG
Incluye interceptores de validación de los mensajes de entrada y salida.
Spring Remoting
28
Impedancia entre XML y objetos
Similar a la impedancia que existe en las soluciones ORM con respecto al modelo
entidad/relación, existe problemas al convertir objetos en XML.
Extensiones XSD. Las extensiones XSD permiten restricciones en los tipos de datos. Ejemplo:
permitir tres letras mayusculas. Este tipo de extensiones no las presenta Java (únicamente
extensión de comportamiento y no de restricción).
Tipos no soportados. Uno de los principios básicos de la plataforma web service es la
interoperabilidad: Java, .NET, Python, … Por ejemplo si desde Java se usa el tipo TreeMap,
seguramente en .NET se use el tipo System.collections.Hashtable. Por tanto, la semántica del
tipo de dato es diferente.
Referencias ciclicas. La forma de representar en XML referencias ciclicas es mediante
referencias. El problema es que no se puede usar validadores XML para validar esta estructura.
Hay que tener en cuenta estas consideraciones a la hora de implementar web services.
Spring Remoting
29
Introducción a WS-Security
WS-Security se centra en tres grandes aspectos:
Autenticación: Determinar el principal y comprobar qué es quien dice ser.
Firma digital: Pieza de información que es basada en el documento y la clave privada de
firmante. Internamente se compone de una función hash y una función de firma con la clave
privada del firmante.
Encriptación y desencriptación.
Consideraciones:
El uso de WS-Security lleva consigo una penalización importante del rendimiento con lo que se
aconseja en algunos casos el uso de mecanismos de seguridad más sencillos como puede ser la
los mecanismos de seguridad básicos HTTP.
La implementación de WS-Security para Spring dispone de soporte para Acegi Security. Es
posible reusar la configuración existente para el soporte de WebServices.
Spring Remoting
30