Histórico da Página
Índice
Índice | ||||||
---|---|---|---|---|---|---|
|
Consideraciones Generales
La información contenida en este documento tiene el objetivo de demostrar cómo realizar la integración entre TOTVS Fluig Plataforma y aplicaciones externas. Para una comprensión completa de esta información, algunos conocimientos se consideran requisitos previos, incluyendo entre ellos:
...
Con el fin de facilitar la comprensión de la información que se presenta y la simulación de los conceptos presentados, los ejemplos citados en este documento utilizan la funcionalidad de Datasets como un ejemplo del uso de las capacidades de integración del producto. Sin embargo, es importante señalar que otros puntos del producto tienen disponibles las mismas características de integración existentes en los Datasets, especialmente las personalizaciones de procesos y formularios.
Visión General
Aunque empíricos, todas las empresas tienen procesos de negocio que permiten que la empresa cumpla con su objetivo, ya sea la prestación de un servicio, la producción de bienes materiales o el comercio de mercancías. Una empresa posee una infinidad de procesos, así cada persona en la organización participa obligatoriamente en al menos uno de estos procesos, y todos ellos comparten información entre sí en algún momento. Los procesos pueden ser formales (como la contratación de un profesional) o informales (como un incentivo para la innovación), críticos (facturación) o satélites (control de envío de tarjetas de cumpleaños).
...
La otra forma de integración es a través de llamadas a Progress® Open AppServer, que se recomienda para usuarios que necesitan integrar TOTVS Fluig Plataforma con aplicaciones desarrolladas en esta plataforma.
WebServices
La integración a través de WebServices utiliza el protocolo SOAP y, al ser un estándar abierto, permite que sistemas desarrollados en plataformas completamente diferentes como Java ™, Microsoft® .Net, C, C ++, PHP, Ruby, Pearl, Python, entre otras, puedan intercambiar información entre sí de manera transparente.
Acceso a WebServices de TOTVS Fluig Plataforma
TOTVS Fluig Plataforma ofrece un conjunto de WebServices que permiten el acceso a la información del producto o la ejecución de tareas, como por ejemplo iniciar solicitudes de procesos. Para tener la lista de los WebServices disponibles, ingrese a:
...
Nota |
---|
Tenga en cuenta que cada tipo de atributo que se espera, por ejemplo el atributo expirationDate del objeto DocumentDto[] es una fecha, pero cada lenguaje lo interpreta de manera diferente, vea a continuación algunos ejemplos:
|
Vía Apache Flex®
Al igual que la mayoría de las herramientas de desarrollo, Apache Flex® permite crear stubs para acceder a web services. Estos stubs encapsulan todas las operaciones de empaquetado y desempaquetado de la información del estándar XML para los tipos nativos de la plataforma.
...
Nota | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
Existe un bug de Flex® que impide el funcionamiento correcto de servicios que trabajan con matrices multidimensionales de datos, como en el ejemplo anterior, donde se devuelve un array (de líneas del Dataset) de array (de las columnas de cada registro). Para solucionar este problema, es necesario cambiar la clase generada por Flex™ Builder™ que encapsulará el array multidimensional. En el ejemplo anterior, esta clase es DatasetDto, que deberá cambiarse (línea 11) como se muestra en el siguiente ejemplo:
Otros servicios que no trabajan con arrays multidimensionales no exigen cambios en el código generado. |
Via Java™
Existen muchas implementaciones de uso de WebServices en Java ™ y en este ejemplo vamos a utilizar las bibliotecas disponibles en Java ™ 7.
...
Nota | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
Al utilizar los WebServices vía Java ™, se debe prestar atención al tipo de cada atributo y al tipo de devolución de WebService. Por ejemplo, para valores del tipofecha se debe utilizar la clase XMLGregorianCalendar:
|
Vía Progress® 4GL
Al igual que en los ejemplos anteriores, el primer paso para consumir un Webservice en Progress® es utilizar una utilidad que leerá la dirección WSDL y generará la información necesaria para su acceso. A diferencia de Java™ y Flex®, Progress® no genera objetos de stub, pero sí una documentación sobre cómo consumir los servicios descritos en el archivo WSDL. Aunque en algunas situaciones es posible utilizar los tipos nativos de Progress® como parámetros, dependiendo del tipo de dato utilizado es necesario manipular el XML SOAP para extraer o enviar una información.
...
Bloco de código | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
/* Parte I - Invocar o WebService */ DEFINE VARIABLE hWebService AS HANDLE NO-UNDO. DEFINE VARIABLE hDatasetService AS HANDLE NO-UNDO. DEFINE VARIABLE cFields AS CHARACTER EXTENT 0 NO-UNDO. DEFINE VARIABLE cOrder AS CHARACTER EXTENT 0 NO-UNDO. DEFINE VARIABLE cDataset AS LONGCHAR NO-UNDO. DEFINE TEMP-TABLE item NO-UNDO NAMESPACE-URI "" FIELD contraintType AS CHARACTER FIELD fieldName AS CHARACTER FIELD finalValue AS CHARACTER FIELD initialValue AS CHARACTER. DEFINE DATASET dConstraints NAMESPACE-URI "http://ws.dataservice.ecm.technology.totvs.com/" FOR item. CREATE SERVER hWebService. hWebService:CONNECT("-WSDL 'http://localhost:8080/webdesk/ECMDatasetService?wsdl'"). RUN DatasetService SET hDatasetService ON hWebService. RUN getDataset IN hDatasetService(INPUT 1, INPUT "adm", INPUT "adm", INPUT "colleague", INPUT cFields, INPUT DATASET dConstraints, INPUT cOrder, OUTPUT cDataset). DELETE OBJECT hDatasetService. hWebService:DISCONNECT(). DELETE OBJECT hWebService. /* Parte II - Faz o parser do XML e criar um arquivo texto separado por tabulacao */ DEFINE VARIABLE iCount AS INTEGER NO-UNDO. DEFINE VARIABLE iCount2 AS INTEGER NO-UNDO. DEFINE VARIABLE hDoc AS HANDLE NO-UNDO. DEFINE VARIABLE hRoot AS HANDLE NO-UNDO. DEFINE VARIABLE hValues AS HANDLE NO-UNDO. DEFINE VARIABLE hEntry AS HANDLE NO-UNDO. DEFINE VARIABLE hText AS HANDLE NO-UNDO. DEFINE VARIABLE cValue AS CHARACTER NO-UNDO. OUTPUT TO c:\dataset.txt. CREATE X-DOCUMENT hDoc. CREATE X-NODEREF hRoot. CREATE X-NODEREF hEntry. CREATE X-NODEREF hText. CREATE X-NODEREF hValues. hDoc:LOAD("longchar", cDataset, FALSE). hDoc:GET-DOCUMENT-ELEMENT(hRoot). /* Percorre as colunas <columns> */ DO iCount = 1 TO hRoot:NUM-CHILDREN WITH 20 DOWN: hRoot:GET-CHILD(hEntry, iCount). IF hEntry:NAME <> "columns" THEN NEXT. hEntry:GET-CHILD(hText, 1). PUT UNFORMATTED hText:NODE-VALUE "~t". DOWN. END. PUT UNFORMATTED SKIP. /* Percorre os registros <values> */ DO iCount = 1 TO hRoot:NUM-CHILDREN WITH 20 DOWN: hRoot:GET-CHILD(hValues, iCount). IF hValues:NAME <> "values" THEN NEXT. /* Percorre os campos <value> */ DO iCount2 = 1 TO hValues:NUM-CHILDREN: hValues:GET-CHILD(hEntry, iCount2). IF hEntry:NUM-CHILDREN = 0 THEN cValue = "". ELSE DO: hEntry:GET-CHILD(hText, 1). cValue = hText:NODE-VALUE. END. PUT UNFORMATTED cValue "~t". END. PUT UNFORMATTED SKIP. END. OUTPUT CLOSE. DELETE OBJECT hValues. DELETE OBJECT hText. DELETE OBJECT hEntry. DELETE OBJECT hRoot. DELETE OBJECT hDoc. |
Acceso a WebServices desde TOTVS Fluig Plataforma
TOTVS Fluig Plataforma permite realizar llamadas a WebServices de terceros a través del registro de Servicios en la visualización de Servicios de Fluig Studio.
...
Una vez implementado el código del Dataset, es posible visualizarlo, como muestra la siguiente figura:
WebServices con Autenticación Básica
Para consumir WebServices que utilizan la autenticación básica (WSS o WS-Security), es necesario utilizar el método getBasicAuthenticatedClient localizado en provider del servicio (el mismo que se obtiene vía ServiceManager). Este método proporciona un client autenticado.
...
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
var serviceLocator = serviceHelper.instantiate('net.webservicex.Periodictable'); var service = serviceLocator.getPeriodictableSoap(); var authenticatedService = serviceHelper.getBasicAuthenticatedClient(service, "net.webservicex.PeriodictableSoap", 'usuario', 'senha'); var result = authenticatedService.getAtoms(); |
WebService con client personalizado
Nota | ||
---|---|---|
| ||
Esta técnica es válida para atualización 1.3.7 o superior. En integraciones que utilizan los servicios creados con CXF con sistemas que no soportan el protocolo HTTP/1.1 (Protheus, por ejemplo), se debe utilizar este método configurando el parámetro "disable.chunking" con el valor "true". |
...
Tenga en cuenta que los ejemplos que aquí se presentan pretenden demostrar la dinámica de la integración entre Progress® y TOTVS Fluig Plataforma sin entrar en detalles específicos de las tecnologías involucradas. La capa de servicios Progress® de TOTVS Fluig Plataforma crea una interfaz en JavaScript para la biblioteca Java Open AppServer Client, de Progress® y, por lo tanto, para más información sobre cómo integrar aplicaciones Java ™ y Progress® vea la documentación suministrada por Progress®.
Caso de Uso
Los ejemplos que se muestran a continuación, tienen como objetivo crear cuatro Datasets 1 en TOTVS Fluig Plataforma:
...
Los dos códigos presentados tienen diferencias significativas en la forma en la que se utilizan y en cómo van a ser expuestos por Progress®. En el primer caso, el programa se carga de manera persistente y sus procedures se pueden ejecutar de forma independiente. En el segundo, el programa se ejecuta de manera no persistente y la lógica principal se encuentra en el main-block. Los procedures internos, si existen, están destinados a mejorar la organización del código y no se pueden utilizar de manera aislada.
Configuración de AppServer
Algunas informaciones importantes en la configuración del AppServer:
- AppServer debe cargarse en el modo Stateless;
En la configuración del agente, en el campo Propath, se debe agregar el directorio donde están ubicados los archivos compilados (.r).
Nota Importante: Cuando se utiliza una ruta relativa (\\servidor\carpeta), el servicio Windows® de Progress® (AdminService) se debe iniciar con un usuario de la red que posea permiso para acceder al directorio informado.
Exponiendo códigos 4GL con ProxyGen
El primer paso para poder ejecutar rutinas en Progress® 4GL es crear la biblioteca cliente, que se realiza mediante la aplicación ProxyGen, que acompaña a la instalación de Progress®, como se muestra a continuación.
...
Informações |
---|
Dependiendo de la versión de Progress®, las pantallas pueden sufrir alguna variación en la cantidad y disposición de los campos. En caso de dudas consulte la documentación |
Configuración del Servicio en Fluig
El registro de un servicio se realiza a través de Fluig Studio, en la view Visualización de Servicios, en la opción Incluir Servicio. La siguiente pantalla muestra el asistente del nuevo servicio y los campos utilizados para el registro del servicio Progress®:
...
Cuando el servicio se haya agregado, se pueden ver las clases disponibles y los métodos existentes en cada una de ellas. Esta información es importante para guiar el desarrollo de los códigos de personalización que harán uso de este servicio. Para ver las clases y los métodos del servicio, utilice la opción Consulta Servicio en Visualización de Servicios, como muestra la siguiente pantalla:
Visión general de los objetos involucrados
El acceso a los procedures expuestos en AppServer implica cuatro elementos que interactúan entre sí de acuerdo al siguiente diagrama:
...
- Script Code: es el código en JavaScript que hará uso de los procedures expuestos en AppServer. Como se mencionó anteriormente, este JavaScript puede ser de cualquier naturaleza, tales como la implementación de un Dataset o la personalización de un evento de proceso.
- Service Provider: Objeto recuperado a través del método ServiceManager.getService que proporciona el acceso a las funcionalidades del servicio. Este objeto se encarga de gestionar la conexión y los recursos asignados por el servicio durante la ejecución del script.
- Service Helper: Objeto recuperado a través del método getBean en ServiceProvider que pone a disposición un conjunto de métodos de utilidad que permiten, entre otras cosas, crear objetos específicos de Progress® (StringHolder, ResultSetHolder, etc.), tener acceso al objeto remoto de ProxyGen e instanciar clases. Para más información sobre Service Helper consulte aquí.
- ProxyGen Clases: Clases generadas por ProxyGen y serán utilizadas por el desarrollador para la ejecución de las rutinas en Progress®. La lista de las clases disponibles, así como sus métodos, se pueden ver en la Visualización de Servicios de Fluig Studio.
Procedures Persistentes y No Persistentes
Cuando se agrega un procedure al proyecto de ProxyGen, éste debe configurarse en dos listas: Procedures Persistentes o No Persistentes Esta decisión implica directamente en la forma en la que se accede a estos objetos por la biblioteca generada y, por consiguiente, en la forma en la que el desarrollador accederá a ella en los códigos JavaScript.
...
Los procedures expuestos de forma persistente dan origen a nuevas clases que pueden instanciarse a través de llamadas a métodos en el Objeto Remoto (a través de la Visualización de Servicios en Fluig Studio se pueden verificar los métodos disponibles en la clase), o por el método createManagedObject. La llamada a través del método createManagedObject permite que Fluig tenga control sobre el ciclo de vida de este objeto, liberándolo de forma automática al final del método. Si el objeto es instanciado de forma manual, el desarrollador debe codificar la liberación del objeto (método _release()), bajo pena de bloquear un nuevo agente de AppServer en cada invocación del método.
Parámetros de Entrada y Salida
Otro punto importante en la invocación de las rutinas en 4GL es observar cuales son tipos de parámetros de entrada y salida de cada procedure o programa. Dependiendo del tipo de dato (CHARACTER, INTEGER, TEMP-TABLE, etc.), del tipo de parámetro (INPUT, INPUT-OUTPUT, BUFFER, etc.) y de la versión utilizada de Progress®, la forma de manipular estos parámetros puede variar.
...
Los tipos de datos utilizados por cada método se pueden consultar a través de la Visualización de Servicios en Fluig Studio. Tenga en cuenta que dependiendo de la versión de Progress® puede existir variación en los tipos de parámetros utilizados y en la manera de utilizarlos. En caso de duda, consulte la documentación suministrada por Progress®.
Creación de los Datasets
Cuando el servicio Progress® se haya agregado en Fluig, es posible utilizarlo en los puntos donde el producto permite la personalización utilizando JavaScript, como en los scripts para eventos globales, eventos de procesos, eventos de definición de formulario o Datasets.
...
Como ya se ha visto anteriormente, los Datasets que se presentarán aquí son Tipos de Centro de Costo, Naturaleza de los Centros de Costo, Centros de Costo yUsuarios en Común.
Tipos de Centro de Costo
El siguiente código presenta la implementación del Dataset de Tipos de Centro de Costo. La explicación de cada paso de la implementación se presentará después del código:
...
La siguiente pantalla presenta la visualización de los datos del Dataset creado:
Naturaleza de los Centros de Costo
El Dataset de Naturaleza de los Centros de Costo es muy similar al Dataset de tipo de centros de costo. En la práctica, el único cambio es que el procedure se llama:
...
Después del registro del Dataset, se puede ver su contenido:
Centros de Costo
El Dataset de Centro de Costo posee una estructura muy similar a la de los dos Dataset visto anteriormente. La principal diferencia es que, en este caso, el procedure devuelve una temp-table con los centros de costos, lo que cambia la forma en la que se manipulan los datos.
Dependiendo de la versión de Progress®, los objetos utilizados pueden variar. A continuación, se presentan ejemplos de la codificación para Progress® 9 y OpenEdge® 10, respectivamente. En ambos casos, el resultado presentado por Dataset será el mismo.
Codificación Progress® 9
Las temp-table en Progress® 9 son manejadas por los objetos que implementan la interfaz java.sql.ResultSet:
Bloco de código | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
function createDataset(fields, constraints, sortFields) { //Crea la estructura del Dataset var dataset = DatasetBuilder.newDataset(); dataset.addColumn("cuenta"); dataset.addColumn("titulo"); dataset.addColumn("naturaleza"); dataset.addColumn("tipo"); //Recupera el servicio y carga el objeto remoto var servico = ServiceManager.getService("EMS2"); var serviceHelper = servico.getBean(); var remoteObj = serviceHelper.createManagedObject("CostCenterUtils"); //Lee las cuentas corrientes var holder = serviceHelper.createResultSetHolder(); remoteObj.readCostCenters(holder); //Recorre los registros, cargando el Dataset con los datos var rs = holder.getResultSetValue(); while (rs.next()) { var cuenta = rs.getObject("cuenta"); var naturaleza = rs.getObject("naturaleza"); var tipo = rs.getObject("tipo"); var titulo = rs.getObject("titulo"); dataset.addRow(new Array(cuenta, titulo, naturaleza, tipo)); } return dataset; } |
Codificación OpenEdge® 10
En OpenEdge® 10, las temp-tables devueltas se encapsulan como objetos de la clase ProDataGraph. Esta clase también se utiliza cuando se usan parámetros del tipo DATASET:
...
Visualización del Dataset:
Usuarios en Común
La primera diferencia entre el Dataset de usuarios comunes y los ejemplos anteriores, es que en este caso es necesario pasar una temp-table como parámetro al procedure invocado.
...
La tercera diferencia que se puede observar en este caso es que es posible transformar un Dataset en los tipos de datos requeridos por Progress® (ResultSet o ProDataGraph).
Codificación Progress® 9
Bloco de código | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
function createDataset(fields, constraints, sortFields) { //Crea el nuevo Dataset var dataset = DatasetBuilder.newDataset(); dataset.addColumn("usuario"); dataset.addColumn("nombre"); //Recupera los usuarios de TOTVS Fluig Plataforma var campos = new Array("colleaguePK.colleagueId", "colleagueName"); var colleaguesDataset = DatasetFactory.getDataset("colleague", campos, null, null); //Instancia el servicio var servico = ServiceManager.getService("EMS2"); var serviceHelper = servico.getBean(); //Transforma el dataset en un ResultSet (v9) y crea holder de salida var inputTT = colleaguesDataset.toResultSet(); var holder = serviceHelper.createResultSetHolder(); //Invoca el procedure en el Progress serviceHelper.getProxy().verifyUsers(inputTT, holder); var rs = holder.getResultSetValue(); while (rs.next()) { dataset.addRow(new Array(rs.getObject("cod_usuar"), rs.getObject("nom_usuario"))); } return dataset; } |
Codificación OpenEdge® 10
Bloco de código | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
function createDataset(fields, constraints, sortFields) { //Crea el nuevo Dataset var dataset = DatasetBuilder.newDataset(); dataset.addColumn("usuario"); dataset.addColumn("nombre"); //Recupera los usuarios de TOTVS Fluig Plataforma var campos = new Array("colleaguePK.colleagueId", "colleagueName"); var colleaguesDataset = DatasetFactory.getDataset("colleague", campos, null, null); //Instancia el servicio var servico = ServiceManager.getService("EMS2"); var serviceHelper = servico.getBean(); //Transforma el dataset en un ProDataGraph (v10) y crea holder de salida var inputTT = serviceHelper.toProDataGraph(colleaguesDataset); var holder = serviceHelper.createProDataGraphHolder(); //Invoca el procedure en el Progress serviceHelper.getProxy().verifyUsers(inputTT, holder); var ttCC = holder.getProDataGraphValue().getProDataObjects("ttOutUsers"); for (var row_index = 0; row_index < ttCC.size(); row_index++) { var row = ttCC.get(row_index); dataset.addRow(new Array(row.get("cod_usuar"), row.get("nom_usuario"))); } return dataset; } |
...
Visualización del Dataset:
Service Helper
La siguiente tabla presenta la lista de métodos existentes en la clase utilidad para servicios Progress®:
...