Árvore de páginas

Versões comparadas

Chave

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

Índice

 

Índice
outlinetrue
stylenone
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:

...

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

Deck of Cards
historyfalse
idstubFlex
historyfalse
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 de acesso aos Datasets do Fluig:

Bloco de código
languageactionscript3
themeEclipse
languagefirstlineactionscript31
titleECMDatasetServiceClient.mxmlfirstline1
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
languageactionscript3
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.

...

A partir dos stubs gerados, é possível consumir o WebService como no exemplo abaixo:

Bloco de código
languagejava
themeEclipse
languagefirstlinejava1
titleECMDatasetServiceClient.javafirstline1
linenumberstrue
package com.fluig.examples;

import javax.xml.ws.BindingProvider;

import net.java.dev.jaxb.array.StringArray;

import com.totvs.technology.ecm.dataservice.ws.DatasetDto;
import com.totvs.technology.ecm.dataservice.ws.DatasetService;
import com.totvs.technology.ecm.dataservice.ws.ECMDatasetServiceService;
import com.totvs.technology.ecm.dataservice.ws.SearchConstraintDtoArray;
import com.totvs.technology.ecm.dataservice.ws.ValuesDto;

/*
 * Classe para invocar serviço DatasetService
 */
public class ECMDatasetServiceClient {

	//Instancia DatasetServiceService.
	private ECMDatasetServiceService ecmDatasetServiceService = new ECMDatasetServiceService();
	private DatasetService service = ecmDatasetServiceService.getDatasetServicePort();
	
	//Inicia execução da classe
	public static void main(String[] args) {
		ECMDatasetServiceClient client = new ECMDatasetServiceClient();
		
		//Configura acesso ao WebServices.
		BindingProvider bp = (BindingProvider) client.service;
		bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, 
				"http://localhost:8080/webdesk/ECMDatasetService");

		try {
			client.getDataset();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void getDataset() throws Exception {
		
		//Cria os parâmetros utilizados na chamada
		int companyId = 1;
		String username = "adm";
		String password = "adm";
		String name = "colleague";
		StringArray fields = new StringArray();
		SearchConstraintDtoArray constraints = new SearchConstraintDtoArray();
		StringArray order = new StringArray();
		
		//Invoca o serviço de dataset
		DatasetDto result = service.getDataset(
				companyId, username, password, name, fields, constraints, order);
		
		//Apresenta o cabeçalho
		for (String columnName : result.getColumns()) {
			System.out.print(columnName + "\t");
		}
		System.out.println();
		
		//Apresenta as linhas do dataset
		for (ValuesDto row : result.getValues()) {
			for (Object value : row.getValue()) {
				System.out.print(value + "\t");
			}
			System.out.println();
		}
	}

}
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
language
languagejava
themeEclipse
javafirstline1
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);

...

O código abaixo apresenta um exemplo de como consumir o serviço:

Bloco de código
languagejavafx
themeEclipse
languagefirstlinejavafx1
titlewsECMDatasetService.pfirstline1
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.

...

O código abaixo apresenta uma implementação de exemplo do uso de um serviço na construção de um Dataset:

Bloco de código
languagejavascript
themeEclipse
languagefirstlinejavascript1
titleperiodicTable.jsfirstline1
linenumberstrue
function createDataset(fields, constraints, sortFields) {

	//Cria o dataset
	var dataset = DatasetBuilder.newDataset();
	dataset.addColumn("elementName");

	// Conecta o servico e busca os livros
	var periodicService = ServiceManager.getService('PeriodicTable');
	var serviceHelper = periodicService.getBean();
	var serviceLocator = serviceHelper.instantiate('net.webservicex.Periodictable');
	var service = serviceLocator.getPeriodictableSoap();

	//Invoca o serviço
	try {
		var result = service.getAtoms();
		var NewDataSet = new XML(result);
		for each(element in(var i = 0; i < NewDataSet.Table.length; i++) {
			var element = NewDataSet.Table[i];
			dataset.addRow(new Array(element.ElementName.toString()));
		}
	} catch(erro) {
		dataset.addRow(new Array(erro));
	}

	return dataset;
}

...

Para o serviço da tabela periódica é necessário realizar os seguintes passos:

Bloco de código
languagejavascript
themeEclipselanguagejavascript
firstline1
linenumberstrue
var serviceLocator = serviceHelper.instantiate('net.webservicex.Periodictable');
var service = serviceLocator.getPeriodictableSoap();
var result = service.getAtoms();

...

No caso deste serviço, o método getAtoms retorna uma string contendo um XML com a lista de todos os elementos, conforme o exemplo abaixo:

theme
Bloco de código
Eclipselanguagehtml/xml
themeEclipse
firstline1
linenumberstrue
<NewDataSet>
	<Table>
		<ElementName>Actinium</ElementName>
	</Table>
	<Table>
		<ElementName>Aluminium</ElementName>
	</Table>
	...
</NewDataSet>

...

O exemplo abaixo apresenta o código utilizado para percorrer o XML retornado:

Bloco de código
languagejavascript
themeEclipselanguagejavascript
firstline1
linenumberstrue
var NewDataSet = new XML(result);
for each(element in(var i = 0; i < NewDataSet.Table.length; i++) {
	var element = NewDataSet.Table[i];
	dataset.addRow(new Array(element.ElementName.toString()));
}

...

Utilizando o exemplo do serviço PeriodicTable apresentado anteriormente, o código da chamada teria as alterações abaixo:

Bloco de código
languagejavascript
themeEclipselanguagejavascript
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();

...

Para personalizar o client que acessa os serviços, é necessário utilizar o método getCustomClient, localizado no provider do serviço (o mesmo que é obtido via ServiceManager). Esta configuração exige a criação de um mapa de parâmetros com seus respectivos valores para passar ao método, conforme snippet abaixo:

Bloco de código
languagejs
themeEclipselanguagejs
		var properties = {};
		properties["basic.authorization"] = "true";
		properties["basic.authorization.username"] = "username";
		properties["basic.authorization.password"] = "password";
		properties["disable.chunking"] = "true";
		properties["log.soap.messages"] = "true";
		//A propriedade receive.timeout está disponível a partir da versão 1.4.10
		properties["receive.timeout"] = "60000";
		
		var serviceLocator = serviceHelper.instantiate('net.webservicex.Periodictable');
		var service = serviceLocator.getPeriodictableSoap();
		var customClient = serviceHelper.getCustomClient(service, "net.webservicex.PeriodictableSoap", properties);
		var result = customClient.getAtoms();

...

O que indica que temos duas declarações de propriedades conflitantes, conforme o fragmento do WSDL abaixo:

Eclipse
Bloco de código
theme
languagehtml/xml
themeEclipse
firstline1
linenumberstrue
<s:complexType name="STRUCT_SA1">
	<s:sequence>
		...
		<s:element minOccurs="1" maxOccurs="1" name="_A1COD_MUN" type="s:string"/>
		...
		<s:element minOccurs="1" maxOccurs="1" name="_A1CODMUN" type="s:string"/>
		...	
	</s:sequence>
</s:complexType>

...

Para resolver esse conflito, pode ser utilizado o arquivo de bind abaixo :

Bloco de código
themeEclipse
languagehtml/xml
themeEclipse
firstline1
linenumberstrue
<?xml version="1.0" encoding="utf-8"?>
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jxb:extensionBindingPrefixes="xjc">
    <jxb:bindings schemaLocation="http://localhost:8080/pcliente/CHAMTEC.apw?WSDL#types1" node="/xsd:schema">
        <jxb:bindings node="//xsd:complexType[@name='STRUCT_SA1']//xsd:sequence//xsd:element[@name='_A1COD_MUN']">
            <jxb:property name="_A1COD_MUN2"/>
        </jxb:bindings>
    </jxb:bindings>
</jxb:bindings>

...

O que indica que temos duas propriedades com a identificação "any" no nosso elemento, conforme o fragmento do arquivo WSDL abaixo:

Eclipse
Bloco de código
theme
languagehtml/xml
themeEclipse
firstline1
linenumberstrue
<s:element name="RealizarConsultaSQLDataTableResponse">
   <s:complexType>
      <s:sequence>
         <s:element minOccurs="0" maxOccurs="1" name="RealizarConsultaSQLDataTableResult">
            <s:complexType>
               <s:sequence>
                  <s:any minOccurs="0" maxOccurs="unbounded" namespace="http://www.w3.org/2001/XMLSchema" processContents="lax" />
                  <s:any minOccurs="1" namespace="urn:schemas-microsoft-com:xml-diffgram-v1" processContents="lax" />
               </s:sequence>
            </s:complexType>
         </s:element>
      </s:sequence>
   </s:complexType>
</s:element>
...
<s:element name="RealizarConsultaSQLDataTableAuthResponse">
   <s:complexType>
      <s:sequence>
         <s:element minOccurs="0" maxOccurs="1" name="RealizarConsultaSQLDataTableAuthResult">
            <s:complexType>
               <s:sequence>
                  <s:any minOccurs="0" maxOccurs="unbounded" namespace="http://www.w3.org/2001/XMLSchema" processContents="lax" />
                  <s:any minOccurs="1" namespace="urn:schemas-microsoft-com:xml-diffgram-v1" processContents="lax" />
               </s:sequence>
            </s:complexType>
         </s:element>
      </s:sequence>
   </s:complexType>
</s:element>

...

Para resolver esse conflito, pode ser utilizado o arquivo de bind abaixo :

Eclipse
Bloco de código
theme
languagehtml/xml
themeEclipse
firstline1
linenumberstrue
<?xml version="1.0" encoding="utf-8"?>
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jxb:extensionBindingPrefixes="xjc">
    <jxb:bindings schemaLocation="http://localhost:8080/tbc/wsConsultaSQL.asmx?WSDL#types1" node="/xsd:schema">
        <jxb:bindings node="//xsd:element[@name='RealizarConsultaSQLDataTableResponse']//xsd:sequence//xsd:any[position()=2]">
            <jxb:property name="any2"/>
        </jxb:bindings>
        <jxb:bindings node="//xsd:element[@name='RealizarConsultaSQLDataTableAuthResponse']//xsd:sequence//xsd:any[position()=2]">
            <jxb:property name="any2"/>
        </jxb:bindings>
    </jxb:bindings>
</jxb:bindings>

...

Para os três primeiros casos, a lógica de extração das informações desejadas será exposta em um programa com várias procedures, uma para cada necessidade aqui apresentada:

Bloco de código
languagejavafx
themeEclipse
languagefirstlinejavafx1
titleCostCenterUtils.p
firstline1
linenumberstrue
/**************************************************************************
** Utilitário que disponibiliza procedures para a extração de informações
** sobre centros de custo.
**************************************************************************/
DEFINE TEMP-TABLE ttCC NO-UNDO
    FIELD conta    LIKE conta.ct-codigo /* CHARACTER */
    FIELD natureza LIKE conta.natureza  /* INTEGER   */
    FIELD tipo     LIKE conta.tipo      /* INTEGER   */
    FIELD titulo   LIKE conta.titulo.   /* CHARACTER */
 
/*-------------------------------------------------------------------
  Procedure: readCostCenters
   Objetivo: Retorna uma temp-table com a lista de centros de custo.
----------------------------------------------------------------------*/
PROCEDURE readCostCenters:
    DEFINE OUTPUT PARAMETER TABLE FOR ttCC.
    FOR EACH conta:
        CREATE ttCC.
        ASSIGN
            ttCC.conta    = conta.ct-codigo
            ttCC.natureza = conta.natureza
            ttCC.tipo     = conta.tipo
            ttCC.titulo   = conta.titulo.
    END.
END.

/*-------------------------------------------------------------------
  Procedure: readCostNatureTypes
   Objetivo: Retorna uma string com as naturezas dos centros de custo,
             separadas por vírgula.
----------------------------------------------------------------------*/
PROCEDURE readCostNatureTypes:
    DEFINE OUTPUT PARAMETER cNatureList AS CHARACTER NO-UNDO.
    cNatureList = {adinc/i01ad047.i 03}.
END.

/*-------------------------------------------------------------------
  Procedure: readCostTypes
   Objetivo: Retorna uma string com os tipos de centro de custo,
             separados por vírgula.
----------------------------------------------------------------------*/
PROCEDURE readCostTypes: 
    DEFINE OUTPUT PARAMETER cTypeList   AS CHARACTER NO-UNDO.
    cTypeList = {adinc/i02ad047.i 3}.
END.

No caso da extração de usuários comuns aos dois produtos, será utilizado um programa único, conforme o código abaixo:

Bloco de código
firstline
languagejavafx
themeEclipse
languagefirstlinejavafx1
titleverifyUsers.p
1linenumberstrue
/**************************************************************************
** Utilitário que recebe um temp-table com uma lista de usuários e retorna
** outra, apenas com os usuários da lista que existam na base de dados.
**************************************************************************/
DEFINE TEMP-TABLE ttUsers
    FIELD cod_usuar   AS CHARACTER
    FIELD nom_usuario AS CHARACTER
    INDEX principal	  IS PRIMARY UNIQUE cod_usuar.
	
DEFINE TEMP-TABLE ttOutUsers LIKE ttUsers.

DEFINE INPUT  PARAMETER TABLE FOR ttUsers.
DEFINE OUTPUT PARAMETER TABLE FOR ttOutUsers.

FOR EACH ttUsers:
   IF CAN-FIND(usuar_mestre WHERE usuar_mestre.cod_usuar = ttUsers.cod_usuar) THEN DO:
        CREATE ttOutUsers.
        BUFFER-COPY ttUsers TO ttOutUsers.
    END.
END.

...

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


  • Na primeira tela do ProxyGen, o principal ponto que deve ser observado é o nome do Projeto (no exemplo, EMSProxies). A informação deste campo será utilizada pelo ProxyGen para nomear a classe de acesso ao serviço, e que será utilizada na configuração do serviço no Fluig. Nesta tela também é preciso configurar o PROPATH corretamente, para que seja possível encontrar os arquivos compilados (.r).


Card
id2
label2º Passo


  • O segundo passo consiste em inserir quais procedures serão expostas de forma persistente ou não-persistente. A escolha de qual opção utilizar depende da forma como cada objeto exposto foi construído. Após inseridas as procedures, clicar na opção Generate.


Card
id3
label3º Passo

 

  • Durante o processo de geração do proxy, na aba General, assinalar a opção Java em Client Proxy e informar o diretório onde o proxy será gerado em Output Dir. Observe também o campo AppService, este deve ser o nome do serviço publicado no AppServer, caso contrário não será possível conectar ao servidor.


Card
id4
label4º Passo


  • A última informação relevante para a geração do proxy é o nome do pacote (package) onde as classes serão criadas. Esta informação é utilizada durante a configuração do serviço Progress® no Fluig. Para finalizar clicar no botão OK.

 

 

Card
id5
labelÚltimo Passo


  • Uma vez criadas as classes, é preciso empacotá-las em um arquivo .JAR. Isto pode ser feito via linha de comando, utilizando-se o comando abaixo:

Sem Formato
jar -cvf <jar_file_name> <diretorio>

 

Observe apenas que no arquivo gerado, é preciso que as classes estejam nos diretórios corretos. No exemplo apresentado, o diretório com deve ser incluído e estar no raiz do arquivo JAR. Por ser compatível com o formato ZIP, uma outra opção é gerar um arquivo com as classes geradas (respeitando-se os diretórios) e renomeá-lo para a extensão .JAR.


...

O código abaixo apresenta a implementação do Dataset de Tipos de Centro de Custo. A explicação de cada passo da implementação será apresentada após o código:

Bloco de código
languagejavascript
themeEclipse
languagefirstlinejavascript1
titledsTipoCentroCusto.js
firstline1
linenumberstrue
function createDataset(fields, constraints, sortFields) {
	
	//Passo 1 - Cria o dataset
	var dataset = DatasetBuilder.newDataset();
    dataset.addColumn("id");
    dataset.addColumn("descricao");
    
	//Passo 2 - Invoca o serviço cadastrado no Fluig
	var servico = ServiceManager.getService("EMS2");
 
	//Passo 3 - Carrega o objeto utilitário para integração com Progress
    var serviceHelper = servico.getBean();
 
	//Passo 4 - Carrega a procedure persistente CostCenterUtils.p
    var remoteObj = serviceHelper.createManagedObject("CostCenterUtils");

	//Passo 5 - Invoca a procedure que retorna uma string com os tipos de CC
    var types = serviceHelper.createStringHolder();
    remoteObj.readCostTypes(types);

	//Passo 6 - Quebra a string em um array com cada um dos tipos
    var typeArray = types.getStringValue().split(",");
 
	//Passo 7 - Adiciona cada tipo retornado
    for(var pos = 0; pos < typeArray.length; pos++) {
        dataset.addRow(new Array(pos + 1, typeArray[pos]));
    }

    return dataset;
}

...

O Dataset de Natureza dos Centros de Custo é muito similar ao Dataset de tipo de centro de custo. Na prática, a única alteração é a procedure que é chamada:

Bloco de código
firstline
languagejavascript
themeEclipse
languagefirstlinejavascript1
titledsNaturezaCentroCusto.js
1linenumberstrue
function createDataset(fields, constraints, sortFields) {

	var dataset = DatasetBuilder.newDataset();
    dataset.addColumn("id");
    dataset.addColumn("descricao");

	var servico = ServiceManager.getService("EMS2");
	var serviceHelper = servico.getBean();
	var remoteObj = serviceHelper.createManagedObject("CostCenterUtils");

	var types = serviceHelper.createStringHolder();
	remoteObj.readCostNatureTypes(types);

    var typeArray = types.getStringValue().split(",");

    for(var pos = 0; pos < typeArray.length; pos++) {
        dataset.addRow(new Array(pos + 1, typeArray[pos]));
    }

    return dataset;
}

...

As temp-table no Progress® 9 são tratadas através de objetos que implementam a interface java.sql.ResultSet:

Bloco de código
languagejavascript
themeEclipse
languagefirstlinejavascript1
titledsCentroCustoP9.jsfirstline1
linenumberstrue
function createDataset(fields, constraints, sortFields) {
    
	//Cria a estrutura do Dataset
    var dataset = DatasetBuilder.newDataset();
    dataset.addColumn("conta");
    dataset.addColumn("titulo");
    dataset.addColumn("natureza");
    dataset.addColumn("tipo");
    
	//Recupera o serviço e carrega o objeto remoto
    var servico = ServiceManager.getService("EMS2");
    var serviceHelper = servico.getBean();
    var remoteObj = serviceHelper.createManagedObject("CostCenterUtils");
    
    //Lê as contas correntes
    var holder = serviceHelper.createResultSetHolder();
    remoteObj.readCostCenters(holder);
    
    //Percorre os registros, carregando o Dataset com os dados
    var rs = holder.getResultSetValue();
    while (rs.next()) {
        var conta 	 = rs.getObject("conta");
        var natureza = rs.getObject("natureza");
        var tipo 	 = rs.getObject("tipo");
        var titulo   = rs.getObject("titulo");
	
        dataset.addRow(new Array(conta, titulo, natureza, tipo));
    }
    
    return dataset;
}

...

No OpenEdge® 10, as temp-tables retornadas são encapsuladas como objetos da classe ProDataGraph. Esta classe também é utilizada quando se utilizam parâmetros do tipo DATASET:

Bloco de código
languagejavascript
themeEclipse
languagefirstlinejavascript1
titledsCentroCustoOE10.js
firstline1
linenumberstrue
function createDataset(fields, constraints, sortFields) {
    
	//Cria a estrutura do Dataset
    var dataset = DatasetBuilder.newDataset();
    dataset.addColumn("conta");
    dataset.addColumn("titulo");
    dataset.addColumn("natureza");
    dataset.addColumn("tipo");
    
	//Recupera o serviço e carrega o objeto remoto
    var servico = ServiceManager.getService("EMS2");
    var serviceHelper = servico.getBean();
    var remoteObj = serviceHelper.createManagedObject("CostCenterUtils");
    
    //Lê as contas correntes
    var holder = serviceHelper.createProDataGraphHolder();
    remoteObj.readCostCenters(holder);
    
	//Percorre os registros, carregando o Dataset com os dados
    var ttCC = holder.getProDataGraphValue().getProDataObjects("ttCC");
    for (var row_index = 0; row_index < ttCC.size(); row_index++) {
        var row = ttCC.get(row_index);
        dataset.addRow(new Array(row.get("conta"),
                                 row.get("titulo"),
                                 row.get("natureza"),
                                 row.get("tipo")));
    }
    
    return dataset;
}

...

Codificação Progress® 9

 

Bloco de código
languagejavascript
themeEclipse
languagefirstlinejavascript1
titledsUsuariosComunsP9.js
firstline1
linenumberstrue
function createDataset(fields, constraints, sortFields) {
    
    //Cria o novo Dataset
    var dataset = DatasetBuilder.newDataset();
    dataset.addColumn("usuario");
    dataset.addColumn("nome");
    
	//Recupera os usuários do Fluig
    var campos = new Array("colleaguePK.colleagueId", "colleagueName");
    var colleaguesDataset = DatasetFactory.getDataset("colleague", campos, null, null);
    
    //Instancia o servico
    var servico = ServiceManager.getService("EMS2");
    var serviceHelper = servico.getBean();
    
    //Transforma o dataset em um ResultSet (v9) e cria holder para saida
    var inputTT = colleaguesDataset.toResultSet();
    var holder = serviceHelper.createResultSetHolder();
    
    //Invoca a procedure no 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;
}
Codificação OpenEdge® 10

 

Bloco de código
languagejavascript
themeEclipse
languagefirstlinejavascript1
titledsUsuariosComunsOE10.jsfirstline1
linenumberstrue
function createDataset(fields, constraints, sortFields) {
    
	//Cria o novo Dataset
    var dataset = DatasetBuilder.newDataset();
    dataset.addColumn("usuario");
    dataset.addColumn("nome");
    
	//Recupera os usuários do Fluig
    var campos = new Array("colleaguePK.colleagueId", "colleagueName");
    var colleaguesDataset = DatasetFactory.getDataset("colleague", campos, null, null);
    
    //Instancia o servico
    var servico = ServiceManager.getService("EMS2");
    var serviceHelper = servico.getBean();
	
    //Transforma o dataset em um ProDataGraph (v10) e cria holder para saida
    var inputTT = serviceHelper.toProDataGraph(colleaguesDataset);
    var holder = serviceHelper.createProDataGraphHolder();
    
    //Invoca a procedure no 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;
}

...