Documentation for a newer release is available. View Latest

DSL 4 - Uso de un dominio externo

Comenzando

Este paso del tutorial utiliza la solución "add_domain_function" del proyecto como punto de partida.

Si en cualquier momento quieres ver la solución de este paso, la encontrarás en la solución "add_external_domain".

En esta sección vamos a investigar cómo podemos solicitar información a sistemas externos y recibir sus respuestas.

¿Qué es un dominio externo?

Desde la perspectiva del DSL, un dominio externo es cualquier otro dominio con el que necesitemos interactuar. A esto nos referimos como un "Dominio Externo". Normalmente es otro sistema bancario como Fraude o Contabilidad, pero podría ser, por ejemplo, otro sistema IPF.

Podemos interactuar con un dominio externo de tres formas clave:

  • Vía una "Instrucción": cuando el dominio externo empuja información hacia nosotros.

  • Vía una "Petición": cuando pedimos información a un dominio externo.

  • Vía una "Notificación": cuando empujamos información a un dominio externo.

Como ejemplo para nuestro flujo, vamos a añadir un paso que nos permita realizar una llamada a un Sistema de Contabilidad que valide nuestra cuenta.

Desde el punto de vista lógico, aquí queremos enviar la información de la cuenta y recuperar si la cuenta es válida. Para hacerlo un poco más complejo, diremos que el sistema contable puede devolver tres respuestas:

  • Success

  • Failure

  • Not Found

Y en el caso de fallo diremos que el fallo puede deberse a que la cuenta ha sido bloqueada o a que se ha producido alguna excepción desconocida.

Por lo tanto, en nuestro ejemplo estamos "pidiendo" datos, de ahí que usaremos una petición en este caso.

Configuración del DSL

Configurar los códigos de respuesta y de razón

En DSL 3 - Using a Domain Function, usamos los códigos de respuesta por defecto "AcceptOrReject" para determinar el resultado de la llamada a la función de dominio. Aquí hemos definido un requisito un poco más difícil que requiere el uso de los conceptos de petición y códigos de respuesta.

Los códigos de respuesta

Primero, consideremos los códigos de respuesta. Tenemos tres resultados: "Success", "Failure" o "Not Found". Añadámoslos como un nuevo conjunto de códigos de respuesta que podamos usar.

Si hacemos clic derecho en nuestro modelo y elegimos New  v2Flo  Response Code Library, deberíamos ver esta pantalla.

external 1

Aquí podemos proporcionar el nombre de nuestra biblioteca e introducir en ella los códigos de respuesta. Llamemos a nuestra biblioteca 'Account Validation Response Codes', proporciona una descripción adecuada y luego haz clic en el botón "Add Response Code"; esto mostrará una nueva tabla con los códigos de respuesta. Configurémoslos como sigue:

external 2

Observa aquí que para las opciones "Failed" y "Not Found" hemos marcado la casilla de fallo (is failure). Esto indica al DSL que estos códigos de respuesta son de fallo y que debe almacenar los motivos del fallo contra el pago para su análisis.

Los códigos de razón

Habiendo configurado nuestros códigos de respuesta, hagamos lo mismo para los códigos de razón: es esencialmente el mismo proceso pero usando la biblioteca de códigos de razón en lugar de los de respuesta. Si lo configuras correctamente debería verse así:

external 3
Definiciones alternativas

En este tutorial hemos definido los resultados de la validación de cuentas como una combinación de códigos de respuesta y de razón. Hay muchas formas diferentes de configurar tu flujo dependiendo de tus requisitos y de lo que mejor funcione para ti. Por ejemplo, también sería válido configurar un conjunto de cuatro códigos de respuesta donde 'Blocked' también estuviera representado de esa manera.

Ahora que hemos configurado nuestros códigos de respuesta y de razón, configuremos el dominio externo y úsalos dentro de él.

Añadir un dominio externo

El primer paso es añadir el Sistema de Contabilidad como un dominio externo, similar a cuando creamos la biblioteca de funciones de dominio. Para ello seleccionamos el flujo de proceso (IpftutorialFlow), hacemos clic derecho y seleccionamos New  v2Flo  External Domain. Esto debería mostrar la siguiente vista:

external 4

Añadamos un nombre y una descripción para empezar:

  • name - Accounting System

  • description - A sample account system

Para nuestro requisito vamos a pedir al sistema de cuentas que valide nuestros datos, por lo que debemos modelar esto como una "Request". Así que haz clic en el botón add request y luego proporciona:

  • un nombre: "Account Validation Request"

  • una descripción: "Validates the accounts system"

  • los datos de negocio que contienen "Customer Credit Transfer"

external 5

Esto es ahora una función que podríamos llamar desde nuestro flujo, que tomará la transferencia de crédito del cliente que hemos recibido de la iniciación del pago y la enviará a las capacidades de validación del sistema contable. Observa que, si el sistema contable requiriera un formato específico, podríamos definirlo aquí y usar las capacidades de mapeo de IPF para transformarlo. Más sobre esto más adelante…​

Observa que, como antes, podemos ver que nuestra petición ha sido resaltada como inválida ya que aún no la hemos completado.

A continuación necesitamos añadir nuestra respuesta; así, al igual que con las funciones de dominio, pulsa return en la sección "Responses" y luego definiremos:

  • un nombre: "Account Validation Response"

  • una descripción: "The result message from the accounting system"

  • sin datos de negocio

  • un conjunto de códigos de respuesta: "Account Validation Response Codes" ("CTRL + Space" para listar y seleccionar)

  • un conjunto de códigos de razón: "Account Validation Reason Codes" ("CTRL + Space" para listar y seleccionar)

  • una marca de finalización establecida en true

Cuando esté completo, el dominio externo debería verse así:

external 6

Actualizar el flujo

Habiendo creado nuestro dominio externo, necesitamos conectarlo con nuestro flujo, así que volvamos al flujo y empecemos añadiendo un nuevo estado para cuando nuestra aplicación está validando la cuenta:

Estados

external 7
Consejo

Para reordenar entradas en la tabla mantén pulsado "Shift + Ctrl" y usa las flechas arriba/abajo.

Eventos

Ahora vamos a añadir tres eventos nuevos a nuestro flujo:

  • uno para cuando la verificación pasa

  • uno para fallo

  • uno para no conocido

Como siempre, lo hacemos pulsando el botón "Add Event" en el flujo e introduciendo los detalles como a continuación:

external 8

Comportamientos de entrada

Como con las funciones de dominio, el manejo de las respuestas del sistema contable se gestiona como "Input Behaviours". Así que pulsa el botón "Add Input Behaviour" y añade comportamientos de entrada para cada una de nuestras opciones e introduce los detalles como a continuación. De nuevo utilizaremos CTRL + SPACE para seleccionar la entrada de la petición que creamos arriba y luego seleccionaremos tanto el primer código de respuesta, es decir, Accepted, como el evento relevante "Fraud OK". Repite para el código de respuesta "Rejected" para el evento

external 9

Finalmente, necesitamos conectar tanto la llamada al sistema de validación como la forma en que manejamos la recepción de nuestros tres eventos en la sección "Event Behaviour" del flujo.

Comportamientos de evento

Empecemos añadiendo la llamada a la nueva petición de validación. Anteriormente, al recibir la confirmación de verificación de duplicados (evento - "Duplicate Check Passed"), completábamos el flujo. Ahora cambiemos esto para que, en su lugar, pasemos a nuestro nuevo estado "Validating Account" y llamemos a "Account Validation Request". Lo hacemos eligiendo realizar una acción y luego seleccionando nuestra petición. Debería verse como a continuación cuando esté listo:

external 10

Ahora que llama a la petición, necesitamos gestionar la respuesta. En nuestro caso, diremos que success va a complete mientras que tanto not found como failed irán a nuestro estado rejected.

Para el caso de fallo, usaremos una nueva funcionalidad del comportamiento de evento que aún no hemos visto: la capacidad de usar la condición "On Any Of". Esto significa que podemos decir que cuando llegue cualquiera de los eventos "Account Not Found" o "Account Validation Failed", podemos realizar la misma funcionalidad.

Lo hacemos como antes, excepto eligiendo "On Any Of" en el desplegable "When". Una vez seleccionado el primero de nuestros dos eventos, simplemente pulsa return y luego podemos usar nuestro enfoque de selección normal para elegir otro.

Una vez completado debería verse como:

external 11

Con esto ya está todo el trabajo de definición del flujo, pero antes de seguir, abramos de nuevo el visor de flujos (Tools > Open Flow Viewer) y veamos nuestro nuevo diagrama.

external 12

Y como era de esperar, aquí podemos ver que ahora hemos incluido nuestra petición de validación de cuenta en nuestro "happy path".

Ahora miramos la parte de implementación; si no te interesa, puedes saltar directamente al ejercicio.

Implementación en Java

Cambiemos ahora a IntelliJ y veamos cómo conectamos esto con nuestro código de implementación. Como es habitual, comenzaremos ejecutando una build desde una ventana de terminal en el directorio raíz de nuestro proyecto:

mvn clean install

Una vez construido, podemos volver a mirar el código generado en /domain-root/domain/target, y ahora deberíamos encontrar el puerto para llamar a nuestro sistema contable así:

package com.iconsolutions.ipf.tutorial.adapters;

import om.iconsolutions.ipf.tutorial.actions.AccountValidationRequestAction;
import java.util.concurrent.CompletionStage;

public interface AccountingSystemActionPort {
    CompletionStage<Void> execute(AccountValidationRequestAction var1);
}

Al igual que con nuestras funciones de dominio, esto es lo que necesitamos implementar para poder llamar a nuestros sistemas externos. Este es el punto en el que, en una implementación típica, usaríamos el framework de conectores para realizar una llamada al sistema externo a través de un protocolo (p. ej., kafka). Tratarás el framework de conectores más adelante en esta serie de tutoriales, así que por ahora usaremos otra característica de nuestro código generado: la aplicación de ejemplo.

Primero tenemos que añadir la dependencia a la aplicación de ejemplo; lo hacemos añadiendo la siguiente dependencia en el pom de ipf-tutorial-app (ipf-tutorial-app/pom.xml).

<dependency>
     <groupId>com.iconsolutions.ipf.tutorial.{solution}.domain</groupId>
     <artifactId>sampleapp</artifactId>
     <version>${project.version}</version>
</dependency>

Observa que solution será la carpeta de solución en la que estés trabajando actualmente; por ejemplo, initial sería com.iconsolutions.ipf.tutorial.initial.domain. Si se construyó desde el scaffolder, es simplemente ipftutorialsolution.

Si miramos dentro del proyecto sample app (domain-root/sampleapp/target/generated-sources/com/iconsolutions/ipf/tutorial/ipftutorialmodel/sample_app/adapter), podemos ver implementaciones de ejemplo de todos nuestros puertos. Funcionalmente, lo único que hacen es devolver el primer código de respuesta disponible, pero son suficientes para poner en marcha una aplicación en funcionamiento. Esto los hace extremadamente útiles, ya que pueden utilizarse inmediatamente para poner en marcha nuestra aplicación y luego sustituirse uno a uno a medida que se desarrollan implementaciones reales.

Añadamos ahora la implementación de ejemplo de AccountSystemActionPort a nuestra configuración. Lo hacemos volviendo a nuestra IpfTutorialConfig y añadiendo una línea extra:

@Bean
public IpftutorialmodelDomain init(ActorSystem actorSystem) {
    // All adapters should be added to the domain model
    return new IpftutorialmodelDomain.Builder(actorSystem)
            .withDomainFunctionAdapter(input -> CompletableFuture.completedStage(new DuplicateCheckResponseInput.Builder(input.getId(), AcceptOrRejectCodes.Accepted).build()))
            .withAccountingSystemActionAdapter(new SampleAccountingSystemActionAdapter())
            .build();
}

Aquí podemos ver que hemos añadido una declaración para usar nuestro SampleAccountSystemActionAdapter.

Eso es todo lo que necesitamos hacer para añadir una implementación sencilla de nuestra llamada al sistema contable. En secciones posteriores proporcionaremos ejemplos más complejos y cómo podríamos usar el framework de conectores de Icon para llamar a sistemas reales.

Comprobación de nuestra solución

Ya estamos listos para ejecutar de nuevo nuestra aplicación. Iniciémosla como antes (las instrucciones están disponibles en Revisión de la aplicación inicial si necesitas recordarlas).

Luego podemos enviar un pago:

curl -X POST localhost:8080/submit | jq

Y, por último, si abrimos el pago en la GUI para desarrolladores y abrimos la pestaña de eventos de dominio (buscar por unit of work id, hacer clic en view, hacer clic en domain events)

external 13

Aquí podemos ver que ahora tenemos tres eventos que llegan, incluido nuestro nuevo "Account Validation Passed" como tercer evento.

Ejercicio

Como ejercicio, añadamos otro paso a nuestro flujo. Imaginemos que necesitamos ejecutar una comprobación de fraude como parte de nuestro flujo. Los requisitos del servicio de comprobación de fraude al que llamaremos son:

  • Toma un pacs008 como dato de entrada.

  • Puede devolver pass o fail.

  • Solo ejecutamos la comprobación de fraude si la cuenta ha sido validada correctamente.

  • Si la comprobación falla, el pago debe ser rechazado.

  • Si la comprobación pasa, el pago debe completarse.

Adelante, intenta implementar una solución para esto. Usa el servicio de consulta para comprobar que tu nueva capacidad de Fraude ha sido invocada.

Cuando estés listo puedes comparar tu solución con la solución "add_external_domain".

Conclusiones

En esta sección:

  • creamos con éxito nuestro primer dominio externo que nos permitió simular una llamada a un servicio contable externo.

  • configuramos una petición dentro de nuestro dominio e integramos eso en nuestro comportamiento de evento para enviar una petición y posteriormente recibir una respuesta del sistema de cuentas.

  • tuvimos una breve introducción a los códigos de respuesta.

Ahora que hemos configurado nuestra aplicación para hacer llamadas a un servicio externo, descubramos cómo usar lógica de enrutamiento en nuestros flujos mediante: DSL 5 - Usar una decisión