Autenticación con AgilePoint y el uso de Surrogate (2ª Parte)

En un artí­culo anterior hablábamos de la autenticación con AgilePoint y la surrogación. Echaba en falta algíºn gráfico que dejara algo más clara la forma de trabajar, así­ que lo adjunto en esta segunda parte.

Esquema Surrogate
Esquema Surrogate

Como véis, se aprecian las tres combinaciones de las que se habla en la primera parte.

  • Opción A: Usuario a través de un navegador web, el servidor web tiene que impersonar al usuario llamante.
  • Opción B: Usuario a través de aplicación de escritorio que trabaja contra una capa de servicios, el servidor de negocio tiene que impersonar al usuario llamante.
  • Opción C: Usuario a trvés de aplicación de escritorio que trabaja directamente con servicios de AgilePont, no hace falta impersonación, el propio usuario pertenece al dominio y se autentica directamente con sus credenciales de red.

Pocos artí­culos íºltimamente. Mucho trabajo.
Saludos!
Miguel.

Autenticación con AgilePoint y el uso de Surrogate

Una de las principales capacidades que ofrece AgilePoint como producto, es la orientación a servicios que han dado a la solución de software. Para ello, en la versión 4.0 de la herramienta ofrecen en concreto dos servicios que agrupan todos los métodos que permiten acceder a la funcionalidad del motor.
workflow.asmx
Servicio que encapsula todos los métodos asociados a la manipulación de los flujos (incluyendo por ejemplo servicios para instanciar plantillas, obtener información de un proceso, establecer el valor de una de las propiedades de un proceso…).
admin.asmx
Servicio que encapsula todos los métodos asociados a la administración del propio motor (incluyendo por ejemplo servicios especí­ficos para la creación de usuarios, permisos, roles…).
A priori, con estas dos piezas, y desde cualquier tipo de tecnologí­a cliente, podrí­amos manipular el BPM desde una aplicación cliente creada por nosotros mismos.
La pieza que aquí­ nos falta es conocer cómo se protege AgilePoint para que no todos los usuarios que tengan acceso a dichos asmx puedan utilizarlos para acceder al motor y manipularlo a su gusto. Como comprenderéis, si no existiera dicha autenticación estarí­amos hablado de un fallo de seguridad como la copa de un pino.
El requerimiento indispensable para poder acceder a los servicios, es que el mismo objeto que está realizando la conexión al servicio cuente con las credenciales de red del usuario que está haciendo la llamada. Esto ya en principio garantiza que la persona que está llamando al servicio está autenticada en el dominio, que quieras que no, supone una primera barrera de seguridad. Pero esto, no es suficiente, ya que necesitaremos que el usuario que esté haciendo la llamada también esté dado de alta en la propia base de datos de usuarios de Agilepoint. Como curiosidad, remarcar que la propia herramienta de gestión de usuarios de AgilePoint provee de facilidades para sincronizarse con el directorio activo e importar la información de los usuarios de dicho directorio a la base de datos de usuario de AgilePoint.
Resumiendo, si disponemos de nuestras credenciales de red validadas, se las pasamos a AgilePoint y nuestro usuario está también incluido en el repositorio de usuarios de AgilePoint, olé, ya podemos usar los servicios sin problemas.
Pongamos por ejemplo que estamos trabajando con una aplicación de escritorio que referencia los servicios web de AgilePoint directamente. Siguiendo este procedimiento, conseguiremos autenticarnos sin problema.
La casuí­stica complicada viene cuando por ejemplo trabajando en web, o en el caso de que no conectemos directamente con nuestra aplicación al servicio, si no que tengamos otra aplicación que haga la conexión en nuestro nombre. Estarí­amos hablando de una tí­pica aplicación web, donde el usuario que la está ejecutando es del del pool del servidor de aplicaciones y no la persona que ha abierto el navegador en su casa… o en el caso de que nuestra aplicación de servicios no ataque directamente a los servicios de AgilePoint si no que llame a una capa de negocio con orientación a servicios que sea la que se encargue después de llamar a Agilepoint. En ambos casos tenemos “algo”por enmedio que tiene sus propias credenciales que no son precisamente las nuestras.
Ante este problema tenemos una primera solución para lograr la autenticación, nos creamos un usuario para ese “algo” intermedio en nuestro directorio activo, lo damos de alta también en la base de datos de Agilepoint, y ala, cuando llamemos al “algo” este se podrá autenticar y hacer el trabajo sin problemas. Esto funciona, pero tiene un problema de base, que todos los usuarios trabajarán contra el BPM usando el mismo usuario, y esto va en contra del funcionamiento basado en flujos.
Como hemos tratado ya en otros artí­culos, uno de los componentes principales de un motor de flujo es el responsable de cada una de las tareas definidas en el flujo de trabajo. Parte de la gracia de este sistema de trabajo es que la persona que conoce el negocio define las responsabilidades de cada uno de los pasos a seguir, y a partir de esta responsabilidad, los usuarios asignados tendrán constancia de que tienen que realizar cada una de las tareas. Imaginaos entonces que siguiendo un flujo determinado se asigna la responsabilidad de las tareas generadas a una serie de usuarios. ¿Cómo voy a conseguir entonces preguntarle al motor de flujo que me de las tareas de dicho usuario especí­fico si siempre estoy haciendo login a través de un usuario intermedio comíºn a todos? En este caso todos serí­amos el mismo usuario y recibirí­amos siempre las mismas tareas.
Después de toda la puesta en situación inicial llegamos entonces al punto clave y objetivo del artí­culo, el Surrogate. Mediante la “surrogación” (no creo que esté este palabro en ningíºn diccionario) conseguimos decir en la autenticación que el usuario intermedio comíºn a todos hable en nombre de otro. Es decir, nos autenticamos igual, pero en un momento dado dicho usuario le dice a AgilePoint: “Oye tí­o, yo soy el que me autentico siempre, estas son mis credenciales y seguro que además me tienes en tu base de datos, y, a partir de ahora mismo todas las operaciones que voy a mandarte las voy a hacer en nombre de Pepe, por lo tanto, cuando te pida que me des todas las tareas en estado ofrecido me estoy refiriendo a las de Pepe, y cuando te diga que proceses una tarea lo vas a hacer también en nombre de Pepe”.
Claro está, “Pepe” va a tener que estar dado de alta en el repositorio de usuario de AgilePoint, o si no por mucho que le diga “el de siempre” que va a hablar en nombre de “Pepe”, AgilePoint va a responder: “no sé de quién me estás hablando”.
A partir de aquí­, para ver a nivel de código cómo funciona esto, os dejo un link de la página de Ascentn donde podéis ver el ejemplo:
Ejemplo KB-Ascentn
Para acabar, y como podréis ver en el link que os acabo de dejar, no todos los usuario disponibles en el repositorio de usuarios de AgilePoint tienen la capacidad de hablar en el nombre de otros. Para disponer de dicha capacidad, se debe dar de alta el usuario como “Impersonator” a través de la herramienta de configuración del servidor de AgilePoint.
Espero haberme explicado con suficiente claridad, no es precisamente fácil intentar trasladar el uso del Surrogate.
Saludos.
Miguel.

FaultContract – Definiendo Excepciones en WCF

Y es que uno de los principales problemas que nos encontrábamos los desarrolladores de Servicios Web .NET de la versión 2.0, es cómo lanzar las excepciones tipificadas que definí­amos en la capa de negocio para que pudieran ser capturadas desde la capa de presentación.
Para los que os hayáis encontrado ya con el problema, sabréis que toda excepción generada desde un Servicio Web .NET 2.0 llega a la capa de presentación como SoapException… por lo que es imposible tipificar en el cliente cuál ha sido exactamente el error generado por la capa de negocio. Hay algíºn truquillo por ahí­ pasando un XML en la SoapException y leyendo el XML desde el cliente, pero nunca me ha acabado de convencer.
Con la etiqueta FaultContract de WCF el problema ya está resuelto y vamos a ser capaces de definir excepciones en la capa de servicios que pueden ser capturadas desde el cliente. Os adjunto al post la solución de servicios polimórficos que vimos semanas atrás, añadiendo la casuí­stica de la generación de excepciones y captura desde el cliente.
Fijaros entre otras cosas del código situado en Base.DAOException, que es la clase que utilizamos para el transporte de la excepción (atención, no hereda de Exception).
También en el interfaz que expone IMiServicio.cs, que es donde veréis que además del atributo “OperationContract” por cada uno de los métodos, también definimos “FaultContract”, asociado al tipo de excepción que va a ser capaz de lanzar dicho método.
[FaultContract(typeof(Base.DAOException))]
Fijaros en MarcaDAO.Update cómo lanzamos la excepción.
throw new FaultException<Base.DAOException>(new Base.DAOException(ex));
Pero, sobre todo, fijaros cómo se captura en el cliente Form1.cs
catch (FaultException<Servicio.DAOException> ex)
WCF Ejemplo FaultContract
Saludos
Miguel

Saltando de Servicios Web .NET 2.0 a WCF

Hola a todos.
Hace tiempo ya que tení­a pendiente un artí­culo como este, donde se mostraba un ejemplo de evolución de un proyecto realizado con .NET Framework 2.0 y Servicios Web, a un proyecto hecho en WCF (siento el retraso, pero voy muy justo de tiempo ultimamente y casi no puedo avanzar artí­culos para el blog). La idea es que los profesionales que conozcan y estén acostumbrados a trabajar con Servicios Web 2.0, pierdan el miedo a WCF y vean que con cambios muy sutiles podemos reaprovechar el trabajo hecho y migrar a WCF.
Para ello os he preparado una solución que consta de dos proyectos, uno hecho con Servicios Web 2.0 y otro con WCF. El de WCF parte del de Servicios Web 2.0, lo ajusta para su uso en WCF y además aumenta la funcionalidad aprovechando el polimorfismo de WCF (tema que hablamos ya en un artí­culo anterior).
Entre las cosas que me gustarí­a que os fijarais es que en el proyecto de WCF se define un servicio “svc” y que dicho servicio está relacionado a un archivo “.cs” que implementa una interfaz. Esto se ha hecho con los servicios de “venta” y “mantenimiento”. Es obligatorio que cada servicio de WCF implemente una interfaz determinada. En la interfaz empiezan ya a verse atributos especí­ficos de WCF como son “ServiceContract” y “OperationContract”. En cuanto a la capa de acceso a datos, en concreto en los DTO veréis aparecer etiquetas “DataContract”, “DataMember” y “KnowType”.
He añadido como complemento más ejemplos de usos de Polimorfismo en WCF. Como véis hay un servicio llamado “mantenimiento”, el cual llama a la factorí­a correspondiente seleccionando el DAO contra el que va a trabajar en tiempo de ejecución. Como sabéis esto no se puede hacer en Servicios Web 2.0.
Otro tema curioso es cómo se ha implementado el servicio de Venta en cada una de las aplicaciones, como veréis en la solución de WCF el método recibe un IDTO, mientras que como esto no es posible en Servicios Web 2.0, la firma del método cambia.
Ejemplo Transición Servicios Web 2.0 a WCF
Terminar diciendo que el ejemplo ha sido implementado usando como entorno de desarrollo Visual Studio 2008.
Saludos a todos.
Miguel.

¿Servicios Web Polimórficos? (Parte 2 – Solución con WCF y Framework 3.5)

Hace ya bastantes artí­culos atrás estuvimos hablando de Servicios Web y Polimorfismo (aquí­). Introdujimos el tema y le dimos alguna vuelta a la necesidad de poder aplicar el concepto de polimorfismo a las llamadas de un servicio web. Es más, incluso lo intentamos utilizando Servicios Web en .NET mediante el Framework 2.0… y… comprobamos que no era posible.
Quedaron abiertas otras soluciones, pero hasta el momento no habí­a podido invertir tiempo en este tema, así­ que ahora que ya tengo algo que mostraros, allá vamos!
Para empezar, como habréis podido observar la solución parte del uso de WCF (Windows Communication Foundation). En concreto para la solución he empleado Visual Studio 2008 y el Framework 3.5 (remarco lo de la versión del Framework, ya que esta misma solución utilizando el WCF y el Framework 3.0 no os va a funcionar, ya que no se hace igual). Estamos de suerte y la solución con el Framework 3.5 la verdad es que es sencillí­sima.
Paso a mostraros fragmentos de código sueltos y luego os adjuntaré el proyecto para que podáis ver y probar vosotros mismos que funciona. Eso sí­, avanzo que el código del proyecto es simplemente para probar el funcionamiento así­ que le faltarán comentarios y demás cosas que intentaré añadir directamente aquí­.
Bien, antes de nada empezar diciendo que voy a intentar seguir la guí­a del primer intento que hicimos de Servicios Web Polimórficos, en la que la idea era conseguir tener un íºnico Servicio Web que nos ofreciera la posibilidad de realizar el mantenimiento de infinitas entidades de datos, en lugar de tener un servicio diferente para cada una de ellas. Para hacerlo necesitábamos que el cliente que consume el servicio recibiera en la definición de su WSDL las clases que implementaban la interfaz IDTO, pero no habí­a manera de que la aplicación de servicios al generar el WSDL lo hiciera de forma automática.
La idea serí­a tener un servicio web que tuviera métodos como los siguientes (para los que no conozcan la teorí­a de los DAO, DTO y Factorí­as, podéis encontrar literatura en la categorí­a de patrones de este mismo blog):
public void Insert(IDTO dto)
{
    Factory.GetDAO(dto).Insert(dto);
}
public void Update(IDTO dto)
{
    Factory.GetDAO(dto).Update(dto);
}
public void Delete(IDTO dto)
{
   Factory.GetDAO(dto).Delete(dto);

Como véis esto serí­a la leche ya que cualquier llamada al servicio serí­a capaz de ejecutar la acción independientemente del DTO que le llegue…
Por aquí­ dejo el código de la factorí­a, que como véis, segíºn el DTO que recibe, retorna el DAO correspondiente.
public class Factory
{
   public static IDAO GetDAO(IDTO dto)
   {
       if (dto is CocheDTO)
       {
          return CocheDAO.GetInstance();
       }
       else if (dto is MarcaDTO)
       {
          return MarcaDAO.GetInstance();
       }
       throw new Exception(“no existe este dto”);
    }
}
Además, como podréis observar, todos los DAO heredan de IDAO, que es quien define los métodos con los que un DAO puede trabajar, y es lo que usa la factorí­a para actuar con independencia.
Pero bueno, vamos al grano y a lo que interesa, que es cómo conseguir que se entere el cliente que recibe el servicio de los DTO que pueden heredar de IDTO. La clave está cuando definimos la clase IDTO.
[DataContract]
[KnownType(typeof(DTO.CocheDTO))]
[KnownType(typeof(DTO.MarcaDTO))]
public class IDTO
{
}
Sobre la clave DataContract, ya hablaremos cuando hagamos la introducción a WCF, en lo que quiero que os fijéis es en las claves KnowType. Aquí­ es donde estamos marcando al servicio que IDTO tiene como tipos conocidos otras clases, que son las que heredan de ella. Por cierto, habréis visto que IDTO es una clase y no un interfaz… por lo visto el atributo KnowType no puede utilizarse con interfaces, pero bueno nos da lo mismo en este caso.
Con todas estas combinaciones que os he presentando, y si probáis el ejemplo donde tenéis más código, veréis que en el cliente que se ha montado (que es una aplicación de escritorio con un botón), podréis leer el siguiente código:
Servicio.MiServicioClient cliente = new Servicio.MiServicioClient();
Servicio.CocheDTO coche = new Servicio.CocheDTO();    
Servicio.MarcaDTO marca = new Servicio.MarcaDTO();     
coche.Codigo =1;
coche.Matricula=”IB-4444-TRT”;
coche.NumeroPuertas=1;
cliente.Insert(coche);
marca.Codigo = 4;
marca.Nombre = “Mercedes”;
marca.Pais = “España”;
cliente.Update(marca);
Bingo! El cliente es capaz de instanciar objetos que no son retornados o pasados por parámetro explí­citamente por un método de un servicio (que era uno de los problemas que tení­amos con el Framework 2.0). “Mágicamente” podemos utilizar los DTO en cliente, rellenarlos y pasárlos a los correspondientes métodos de Insert y Update. Al llegar la petición al servicio, la factorí­a decide el DAO a llamar en tiempo de ejecución y a correr.
Con un íºnico servicio podrí­amos realizar toda la fachada para mantener y consultar infinitas entidades de negocio. ¡Objetivo cumplido!
Os invito a descargar la solución de ejemplo que os adjunto y a lanzarla en modo debug, veréis que si lo seguí­s la ejecución mantiene el flujo que hemos definido sin problemas.
Servicio WCF Polimórfico
Saludos.
Miguel.

Evento Microsoft sobre la Arquitectura Orientada a Servicios

El próximo jueves 8 de mayo se va a producir un evento on-line por parte de Microsoft relacionado con la Arquitectura Orientada a Servicios.
La descripción del evento es la siguiente:
Uno de los temas más polémicos en los íºltimos tiempos en Arquitectura de Software es la orientación a servicios, y cómo esto mejora la agilidad, flexibilidad y el rehíºso de mis soluciones. En esta sesión, nos enfocaremos en la orientación a servicios desde una perspectiva de arquitectura de software, analizaremos cómo un enfoque orientado a servicios difiere de arquitecturas basadas en objetos y componentes, así­ como también la discusión de algunos retos organizacionales que se experimentan al adoptar una arquitectura orientada a servicios”
Muy interesante a priori, el íºnico problema es que para poder verlo en directo tendréis que estar delante del ordenador de 11 a 12 de la noche… 🙂 O esperar más adelante a que pongan a disposición la grabación para ver el ví­deo off-line.
Mas información y suscripción al evento Aquí­
Un saludo.
Miguel.

¿Servicios Web Polimórficos? (Parte I – Intentando solucionar el problema mediante .NET Framework 2.0)

No sé si os habéis planteado alguna vez la posibilidad de aplicar el concepto de polimormisfo en un servicio web.
Es curioso pero así­ como cuando hablamos de la programación orientada objetos lo del polimorfismo está en boca de todos, cuando se habla de servicios web dicho concepto parece que se pierde y que no tenga sentido aplicarlo.
¿Se os ocurre un ejemplo de cómo sacarle utilidad? Seguro que sí­. De todas maneras, os he preparado un ejemplo de lo que serí­a uno de los usos, para que tengáis una idea de cómo serí­a la forma de un servicio web polimórfico. El ejemplo está escrito en VB.NET utilizando el framework 2.0 de .NET.
Servicio Web Polimorfico
Antes de nada (y sobre todo antes de que alguno se emocione con la idea) avanzaros que el ejemplo no es efectivo, porque con la versión 2.0 no se puede aplicar el polimorfismo en servicios web (de ahí­ el tí­tulo del post). Pero, seguro que servirá para haceros una idea de lo que se intenta transmitir en el post. Además, para poder seguir bien el ejemplo tendréis que conocer el funcionamiento de los patrones de diseño DAO y DTO (en el blog hay unos cuantos posts al respecto los cuales podéis consultar para poneros al dí­a).
En el ejemplo podréis ver que tenéis un de servicio web en el que se presentan dos capas, la de negocio (BL) y la de acceso a datos (DL).
En la capa de acceso a datos está implementada una factorí­a de DAO implementando el patrón factorí­a.
Public Class DAOFactory
    Public Shared Function GetDAO(ByVal dto As IDTO) As IDAO   
      If TypeOf (dto) Is Coche.CocheDTO Then
          Return Coche.CocheDAO.GetInstance   
      ElseIf TypeOf (dto) Is Marca.MarcaDTO Then
          Return Marca.MarcaDAO.GetInstance   
      Else
          Throw New DAONoDefinidoException   
      End If
    End Function
End Class
Veréis además que los DAO a parte de heredar de la clase BaseDAO implementan la interfaz IDAO la cual define cuáles son los métodos que debe implementar obligatoriamente cada DAO.
Public Class MarcaDAO : Inherits BaseDAO : Implements IDAO
Para finalizar, los DTO heredan todos de la clase IDTO la cual define una propiedad comíºn a todos los DTO, la propiedad Id, que define el valor que identifica a un DTO de forma íºnica. He dejado medio implementados dos DAO, CocheDAO y MarcaDAO para que se vea un poco mejor la forma de todo.
En la capa de lógica de negocio veréis que hay un íºnico servicio, llamado service.vb. En el se definen los siguientes métodos
Execute
Recibe por parámetro un IDTO y una acción posible a ejecutar. Con el IDTO recibido y utilizando la factorí­a de DAO’s genera un DAO mediante el cual lleva a cabo la acción a realizar.
Public Sub Execute(ByVal dto As IDTO, ByVal theAction As ExecuteAction)
GetUnique
A partir de una id y la factorí­a de DAO retorna un DTO.
Public Function GetUnique(ByVal dto As IDTO) As IDTO
GetMoreThanOne
A partir de un IDTO y una posible acción a ejecutar retorna una lista genérica de IDTO.
Public Function GetMoreThanOne(ByVal dto As IDTO, ByVal theAction As SelectAction) As List(Of IDTO)
Qué fantástico serí­a que funcionara esto ya que como véis desde la capa de presentación no dispondremos de un servicio web de Insert, Update, Delete y consultas restantes por cada entidad en la capa de acceso a datos, si no que tenemos un íºnico servicio, un íºnico interfaz, que luego internamente, una vez recibido el DTO correspondiente lanzará en tiempo de ejecución (mediante polimorfismo) la llamada al método de la capa de acceso a datos correspondiente. ¿Mola no? ¡Nos estarí­amos ahorrando un montón de tiempo de desarrollo y de mantenimiento!
Ahora empieza el chiste de todo esto, ya que, ¿qué ocurre cuando mediante un cliente intentamos referenciar al servicio web? Pues que no sabe qué leches es un IDTO. Esto es debido a que el WSDL que se genera automáticamente no ha definido cuáles son las clases que están en el servicio y que heredan IDTO. Esto es un problemón y es lo que tira para abajo toda esta solución. Probad a referenciar el servicio desde un cliente, añadiendo la referencia y veréis que en el parámetro IDTO lo define así­ “<idto/>” y santas pascuas, no sabe nada más.
Qué penita, esto no nos vale para nada, pero al menos ha servido para introducir el tema y plantear con los siguientes posts soluciones alternativas al mismo 🙂
Nos vemos en la siguiente parte.
Un saludo.
Miguel.

Buenas Prácticas: Los servicios web no deberí­an devolver tipos especí­ficos de la tecnologí­a

Tí­pico ejemplo de esta situación es un servicio web hecho en .NET que devuelve un Dataset.
Si se nos garantiza que el consumidor del servicio va a ser siempre un cliente .NET aíºn la cosa se sostiene un poco. El problema es si por ejemplo intentamos consumir un servicio que da un Dataset por otra tecnologí­a que no es .NET.
Para los que tengáis experiencia trabajando con servicios sabréis que una vez que creas un servicio que devuelve un objeto o tiene por parámetro un objeto definido en el servicio, desde el cliente que consume el servicio tenemos visibilidad sobre la definición de dicho objeto. Si yo tengo un servicio que recibe por parámetro un objeto coche, yo desde el cliente puedo rellenar dicho objeto coche y pasárselo por parámetro al servicio. Lo mismo ocurre si el coche me lo devuelve el servicio, yo puedo conocer sus propiedades y extraer los valores de las mismas.
¿Pero qué ocurre con un dataset? ¿Ocurre lo mismo? Pues no.
El principal problema de un Dataset es que en tiempo de diseño no conocemos cuál es su contenido. Sólo lo sabemos en tiempo de ejecución. Ya “sólo” por este “pequeño” problema tenemos ya un agujero del tamaño de un tonel respecto a la protección de tipos en tiempo de diseño. Podemos pedirle lo que quiera al dataset, porque el compilador no va a darnos ningíºn tipo de alarma, nos vamos a enterar en tiempo de ejecución generando una excepción si la consulta sobre el dataset no era correcta.
Este problema se vuelve más complicado aíºn si consumimos el servicio desde por ejemplo un cliente java, ya que para interpretar el contenido del dataset en tiempo de ejecución no nos va a quedar más remedio que leer el mensaje xml que nos llega con el contenido, leerlo e interpretarlo a pelo.
¿Cual es entonces mi recomendación? No es difí­cil respuesta adivinarlo si leéis los artí­culos de esta web, por mi parte está claro, Data Transfers Objects 🙂 O Value Objects, que es lo mismo 🙂
Saludos!
Miguel.

El negocio es el negocio

En el artí­culo anterior ya estuvimos comentando que lo de la arquitectura orientada a servicios está hoy en dí­a hasta en la sopa, que no hasta en la SOAP (chiste malo).
Qué bonito es lo de la orientación a servicios, vamos a encapsular el negocio, pero… ¿tenemos todos claro qué es lo que tenemos que almacenar en el negocio?
Lo comento porque es un error bastante comíºn pensar que en el negocio de nuestra arquitectura orientada a servicios debemos almacenar por ejemplo nuestro acceso a datos de forma encapsulada. Me explico con un ejemplo. Pongamos que tenemos un servicio que compra un coche, el cual a la hora de llamarlo crea una nueva entrada en la tabla “Compra”. Pero claro, cuando compramos un coche no sólo tenemos que registrarlo en la tabla “Compra” si no que seguramente tendremos que trabajar con el Stock, y dependiendo de nuestro Stock tal vez tengamos que hacer una petición de nuevo Stock. Además, puede darse el hecho que segíºn la petición de nuestro cliente la compra la haga financiada y la compra financiada le obligue a pagar un seguro de vida por cada uno de los meses que se le esté financiado la compra.
Wou, cuantas cosas. ¿Esto quiere decir que tenemos que hacer un servicio web por cada uno de las posibilidades que hablábamos en el anterior párrafo? Pues no, eso es un error de concepto de cómo usar la capa de negocio. La capa de negocio tiene que encapsular el negocio, es decir, ocultarlo a los consumidores del mismo.
Si uno de los clientes que llama al servicio web quiere comprar un coche llamará al servicio web de compra de coche pero no se va a preocupar de todas la otra casuí­stica del stock y de la financiación y toda la historia, porque de eso no sabe nada. Nuestro consumidor del servicio no tiene por qué saber cómo funciona nuestro negocio, eso es cosa nuestra. El servicio web se encargará de todo internamente abstrayendo al cliente. 
¿Se entiende el concepto?
Saludos.
Miguel.