Árvore de páginas

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

Índice

Índice
outlinetrue
exclude.*ndice
stylenone

 

Considerações Gerais

As informações contidas neste documento têm por objetivo demonstrar como realizar a integração entre o fluig e aplicativos externos. Para que se tenha uma compreensão completa destas informações, alguns conhecimentos são considerados pré-requisitos, entre eles:

  • Visão geral sobre o produto fluig
  • Visão geral sobre integração de sistemas
  • JavaScript
  • WebServices
  • SOAP
  • Datasets (Fluigfluig)
  • Java™
  • Apache Flex®

Em várias partes deste documento serão apresentados trechos de códigos em diferentes linguagens de programação, com o intuito de demonstrar o uso das capacidades de integração do Fluigfluig. Entretanto, este documento não tem por objetivo capacitar o leitor no uso destas tecnologias além do propósito acima descrito, sendo responsabilidade do leitor buscar informações aprofundadas sobre estas linguagens.

Com o intuito objetivo de facilitar o entendimento das informações apresentadas e a simulação dos conceitos apresentados, os exemplos citados neste documento utilizam a funcionalidade de Datasets como exemplo de uso das capacidades de integração do produto. Entretanto, é importante ressaltar que outros pontos do produto da plataforma possuem disponíveis as mesmas características de integração existentes nos Datasets, em especial as personalizações de processos e formulários.

 

Visão Geral

Ainda que empíricos, toda empresa possui processos de negócios que permitem à empresa cumprir o seu objetivo, seja ele a prestação de um serviço, a produção de bens materiais ou o comércio de mercadorias. Uma empresa possui uma infinidade de processos, sendo que cada pessoa na organização obrigatoriamente participa em pelo menos um destes processos, e todos eles trocam informações entre si em algum momento. Os processos podem ser formais (como a contratação de um profissional) ou informais (como um incentivo à inovação), críticos (faturamento) ou satélites (controle de envio de cartões de aniversários).

Com o advento das tecnologias de Sistema da Informação, vários sistemas passaram a dar apoio a estes processos de negócio, especialmente àqueles aqueles considerados mais críticos para a operação da empresa. O melhor exemplo disto é a adoção dos sistemas de ERP que dão suporte aos processos de várias áreas da empresa.

O Fluig fluig tem como objetivo ser uma plataforma agnóstica de gestão de processos, documentos e identidades através de uma interface de comunicação colaborativa. Isto pode ser percebido em maior ou menor grau em cada uma das suas funcionalidades, desde as mais simples (como colaboração) até as mais complexas (como DM e BPM).

Entretanto, parte destes processos têm alta dependência dos sistemas de informação já existentes na empresa e, por isso, a arquitetura do Fluig fluig é planejada para permitir integrar-se a estes sistemas, permitindo possibilitando que os processos modelados tenham maior valor agregado.

O Fluig fluig permite tanto o acesso pelo produto aos sistemas externos (para consultar ou alimentar informações), bem como habilita aceita que outros sistemas venham a conectar-se para a consulta de informações ou para execução de operações transacionais.

...

O principal canal de integração do produto da plataforma é através de WebServices, que vêm se tornando o padrão mais comum de integração com qualquer aplicativo. Através deles, é possível ter acesso às funcionalidades do Fluig fluig e dar acesso pelo produto à aplicativos externos. Este documento dedica uma seção específica sobre integração via WebServices.

 

WebServices

A integração via WebServices utiliza o protocolo SOAP e, por ser um padrão aberto, permite que sistemas desenvolvidos em plataformas totalmente diferentes como Java™, Microsoft® .Net, C, C++, PHP, Ruby, Pearl, Python, entre outras, possam trocar informações entre si de forma transparente.

Acessando os WebServices do

...

fluig

O Fluig fluig disponibiliza um conjunto de WebServices que permitem o acesso às informações do produto da plataforma ou a execução de tarefas, como iniciar solicitações de processos por exemplo. Para  Para ter a lista dos WebServices disponíveis, acesse o endereço: 

Sem Formato
http://<host>:<porta>/services 

...

Nota

Atente para cada tipo do de atributo que é esperado, por exemplo, o atributo expirationDate do objeto DocumentDto[] é uma data, porém cada linguagem interpreta de maneira diferente, veja alguns exemplos abaixo:

  • C#: dateTime
  • Java™: XMLGregorianCalendar
  • Progress®: DATETIME-TZ

 

Via Apache Flex®

Como a grande maioria das ferramentas de desenvolvimento, o Apache Flex® permite criar stubs para o acesso a web servicesWebservices. Estes stubs encapsulam todas as operações de empacotamento e desempacotamento das informações do padrão XML para os tipos nativos da plataforma.

Utilize o passo-a-passo para visualizar o processo de criação dos stubs para um serviço disponibilizado pelo Fluigfluig:

Deck of Cards
historyfalse
idstubFlex
Card
defaulttrue
effectDuration0.5
id1
label1º Passo
effectTypefade

A criação dos stubs no Flex® é feito através do menu Data, opção Import WebService(WSDL), conforme a imagem abaixo.

Card
effectDuration0.5
id2
label2º Passo
effectTypefade

Na primeira janela, é solicitada a pasta dentro do projeto corrente onde devem ser gerados os stubs.

Card
effectDuration0.5
id3
label3º Passo
effectTypefade

Na tela a seguir, deve ser informado o endereço do WSDL onde se encontra o serviço. Também é possível definir se ele será acessado da estação cliente ou do servidor LifeCycle Data Services.

Card
effectDuration0.5
id4
label4º Passo
effectTypefade

Na última tela, deve-se informar o package que será utilizado e qual o nome da classe principal (já sugeridos pelo Flex™ Builder™).

Card
effectDuration0.5
id5
labelResultado
effectTypefade

Uma vez finalizado o processo, o Flex™ Builder™ adicionará ao projeto um conjunto de classes que serão utilizadas pelo programador para invocar os serviços, conforme a figura abaixo:

...

O trecho de código abaixo apresenta um exemplo de invocação do WebService Webservice de acesso aos Datasets do Fluigfluig:

Bloco de código
languageactionscript3
themeEclipse
firstline1
titleECMDatasetServiceClient.mxml
linenumberstrue
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="{this.start()}">
	<mx:Script>
		<![CDATA[
			import generated.webservices.ValuesDto;
			import generated.webservices.DatasetDto;
			import generated.webservices.GetDatasetResultEvent;
			import generated.webservices.SearchConstraintDtoArray;
			import generated.webservices.StringArray;
			import generated.webservices.ECMDatasetServiceService;
			import mx.rpc.events.FaultEvent;
			import mx.collections.ArrayCollection;
		
			//Cria uma instância do Stub de acesso ao serviço
			private var ds:ECMDatasetServiceService = new ECMDatasetServiceService();

			public function start() : void {

				//Cria tipos auxiliares, que serão utilizados na chamado do serviço
				var fields:StringArray = new StringArray();
				var constraints:SearchConstraintDtoArray = new SearchConstraintDtoArray();
				var order:StringArray = new StringArray();

				//Define as funções para tratamento do retorno
				ds.addEventListener(GetDatasetResultEvent.GetDataset_RESULT, resultGetDataset);
				ds.addEventListener(FaultEvent.FAULT,faultGetDataset);
				
				//invoca o método getDataset do serviço
				ds.getDataset("adm", 1, "adm", constraints, order, fields, "colleague");
			}
			
			//Tratamento dos dados retornados do serviço invocado.
			public function resultGetDataset(ev:GetDatasetResultEvent) : void {

				//Recupera o retorno do serviço, na forma de um DatasetDto
				var dataset:DatasetDto = ev.result as DatasetDto;

				//Monta uma string com todos os dados do dataset
				var line:String = "";
				
				//Cabeçalho com o nome dos campos
				var columnsArray:ArrayCollection = new ArrayCollection(dataset.columns);
				for (var j:int = 0; j < columnsArray.length; j++) {
					line += columnsArray.getItemAt(j) + "\t";
				}

				//Linha de dados
				var valuesArray:ArrayCollection = new ArrayCollection(dataset.values);
				for (var j:int = 0; j < valuesArray.length; j++) {
					var row:ValuesDto = valuesArray.getItemAt(j) as ValuesDto;
					line += "\n" + j + ":";
					
					for (var i:int = 0; i < row.length; i++) {
						line += row.getItemAt(i) + "\t";
					}
				}
				
				//Mostra a string criada em um textarea na tela
				this.sysout.text = line;
			}
			
			public function faultGetDataset(ev:FaultEvent) : void {
				this.sysout.text = ev.fault.faultString;
			}
		]]>
	</mx:Script>
	<mx:TextArea id="sysout" name="sysout" width="100%" height="100%" 
		paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5"/>
</mx:Application>
Nota

Existe um bug do Flex® que impede o funcionamento correto de serviços que trabalhem com matrizes multidimensionais de dados, como no exemplo acima, onde é retornado um array (de linhas do Dataset) de array (das colunas de cada registro).

Para contornar este problema, é preciso alterar a classe gerada pelo Flex™ Builder™ que irá encapsular o array multidimensional. No exemplo acima, este classe é a DatasetDto, que deverá ser alterada (linha 11) conforme o exemplo abaixo:

Bloco de código
languageactionscript3
themeEclipse
firstline1
linenumberstrue
public class DatasetDto
{
	/**
	 * Constructor, initializes the type class
	 */
	public function DatasetDto() {}
            
	[ArrayElementType("String")]
	public var columns:Array;
	[ArrayElementType("ValuesDto")]
	public var values:Array = new Array(); //iniciando o array
}

Outros serviços que não trabalhem com arrays multidimensionais não exigem alterações no código gerado.

 

Via Java™

Existem muitas implementações de uso de WebServices em Java™ e neste exemplo vamos utilizar as bibliotecas disponíveis no Java™ 7.

...

Nota

Ao utilizar os WebServices via Java™, deve-se atentar para o tipo de cada atributo e para o tipo de retorno do WebService. Por exemplo, para valores do tipo data deve ser utilizado a classe XMLGregorianCalendar:

Bloco de código
languagejava
themeEclipse
firstline1
linenumberstrue
DocumentDto document = new DocumentDto();

XMLGregorianCalendar date = DatatypeFactory.newInstance().newXMLGregorianCalendar();
date.setYear(2013);
date.setMonth(10);
date.setDay(16);
date.setHour(0);
date.setMinute(0);
date.setSecond(0);

document.setExpirationDate(date);

 

Via Progress® 4GL

Assim como nos exemplos anteriores, o primeiro passo para consumir um Webservice em Progress® é utilizar um utilitário que irá ler o endereço WSDL e gerar as informações necessárias para acessá-lo. Diferente do Java™ e Flex®, o Progress® não gera objetos de stub, mas apenas uma documentação sobre como consumir os serviços descritos no arquivo WSDL. Embora em algumas situações seja possível utilizar os tipos nativos do Progress® como parâmetros, dependendo do tipo de dado utilizado é preciso manipular o XML SOAP para extrair ou enviar uma informação.

...

Bloco de código
languagejavafx
themeEclipse
firstline1
titlewsECMDatasetService.p
linenumberstrue
/* 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.

Acessando WebServices a partir do Fluig

O Fluig permite fazer chamadas a WebServices de terceiros através do cadastro de Serviços na Visualização de Serviços do Fluig Studio.

...

Bloco de código
languagejavascript
themeEclipse
firstline1
titleperiodicTable.js
linenumberstrue
		//Servico "<url_fluig>/webdesk/ECMCardService?wsdl"cadastrado com o código "CardService"
        var cardServiceProvider = ServiceManager.getServiceInstance("CardService");
        var cardServiceLocator = cardServiceProvider.instantiate("com.totvs.technology.ecm.dm.ws.ECMCardServiceServiceLocator");
        var cardService = cardServiceLocator.getCardServicePort();
        var cardFieldDtoArray = cardServiceProvider.instantiate("com.totvs.technology.ecm.dm.ws.CardFieldDtoArray");
        var cardField = cardServiceProvider.instantiate("com.totvs.technology.ecm.dm.ws.CardFieldDto");
     
        //Seta valor no campo com name = 'nome'
        cardField.setField("nome");
        cardField.setValue("Valor alterado via WS dentro de um evento workflow");
 
        var vetCardFields = new Array();
        vetCardFields.push(cardField);
        cardFieldDtoArray.setItem(vetCardFields);
     
        //Altera o(s) campo(s) do registro de formulário.
        //updateCardData(tenantId, login, senha, codRegistroForm, cardFieldDtoArray);
        cardService.updateCardData(1, "adm", "adm", 8, cardFieldDtoArray);

 

WebServices com Autenticação Básica
Nota
titleAtenção

Esta opção é válida apenas para serviços criados utilizando a API CXF.

WebServices com Autenticação Básica no acesso ao WSDL

Para criar serviços de WebServices que utilizam Autenticação Básica no acesso ao seu WSDL, é necessário marcar a opção Requer Autenticação no cadastro de serviços do fluig, conforme exemplo abaixo:

...

Para finalizar o cadastro será apresentada a janela para autenticação abaixo:

Consumindo WebServices com Autenticação Básica

Para consumir WebServices que fazem uso de autenticação básica, é necessário utilizar o método getBasicAuthenticatedClient localizado no provider do serviço (o mesmo que é obtido via ServiceManager). Este método disponibiliza um client autenticado.

...

Bloco de código
languagejavascript
themeEclipse
firstline1
linenumberstrue
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 com client personalizado
Nota
titleAtenção

Esta técnica é válida para o Fluig 1.3.7 ou superior.

Em integrações que utilizem serviços criados com o CXF com sistemas que não suportam o protocolo HTTP/1.1 (Protheus, por exemplo), é necessário utilizar este método configurando o parâmetro "disable.chunking" com o valor "true".

...

Nota
titleImportante

O tempo de timeout de requisição padrão do fluig deveria ser suficiente para a realização de uma integração convencional. Antes de aumentar o tempo de timeout de integrações do Fluig verifique o fato que levou a esta decisão.

Por exemplo, revise códigos e dimensionamento do servidor que recebe as integrações. Otimizações de códigos podem reduzir o tempo necessário para realizar uma transação e oferecer as pessoas que utilizam o fluig uma navegação mais fluida.

Resolvendo conflitos utilizando arquivos de bind JAXB
Nota
titleAtenção

Esta técnica é válida apenas para serviços criados utilizando a API CXF.

...

Nota
titleImportante

Além de WebServices o fluig também pode realizar chamadas Progress. Entretanto essa técnica está descontinuada, e nossa recomendação é usar serviços SOAP.

Caso seu projeto já utilize essa técnica acesse a documentação depreciada.

 

Integrações Assíncronas em Solicitações

Para a realização de integrações assíncronas em processos Workflow, a recomendação atual é a utilização de atividades do tipo Serviço configuradas com execução automatizada, onde é possível selecionar a mensagem de sucesso e a quantidade de tentativas que o script tentará executar antes de seguir a um fluxo de erro.

...