Árvore de páginas

Versões comparadas

Chave

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

<div id="main-content" class="wiki-content group">
	<h1 id="IntegraçãoComAplicativosExternos-Índice">Índice</h1>
	<p>&#160;</p>
	<p>
		<style type='text/css'>/*<![CDATA[*/
div.rbtoc1412695546456 {
	padding: 0px;
}
div.rbtoc1412695546456 ul {
	list-style: none;
	margin-left: 0px;
}
div.rbtoc1412695546456 li {
	margin-left: 0px;
	padding-left: 0px;
}
/*]]>*/
</style>
	<div class='toc-macro rbtoc1412695546456'>
		<ul class='toc-indentation'>
			<li><span class='TOCOutline'>1</span> <a
				href='#IntegraçãoComAplicativosExternos-ConsideraçõesGerais'>Consideraciones
					Generales</a></li>
			<li><span class='TOCOutline'>2</span> <a
				href='#IntegraçãoComAplicativosExternos-VisãoGeral'>Visión
					General</a></li>
			<li><span class='TOCOutline'>3</span> <a
				href='#IntegraçãoComAplicativosExternos-WebServices'>WebServices</a>
				<ul class='toc-indentation'>
					<li><span class='TOCOutline'>3.1</span> <a
						href='#IntegraçãoComAplicativosExternos-AcessandoosWebServicesdoFluig'>Acceso
							a WebServices de Fluig</a>
						<ul class='toc-indentation'>
							<li><span class='TOCOutline'>3.1.1</span> <a
								href='#IntegraçãoComAplicativosExternos-ViaApacheFlex®'>Vía
									Apache Flex®</a></li>
							<li><span class='TOCOutline'>3.1.2</span> <a
								href='#IntegraçãoComAplicativosExternos-ViaJava™'>Vía Java™</a></li>
							<li><span class='TOCOutline'>3.1.3</span> <a
								href='#IntegraçãoComAplicativosExternos-ViaProgress®4GL'>Vía
									Progress® 4GL</a></li>
						</ul></li>
					<li><span class='TOCOutline'>3.2</span> <a
						href='#IntegraçãoComAplicativosExternos-AcessandoWebServicesapartirdoFluig'>Acceso
							a WebServices desde Fluig</a>
						<ul class='toc-indentation'>
							<li><span class='TOCOutline'>3.2.1</span> <a
								href='#IntegraçãoComAplicativosExternos-WebServicescomAutenticaçãoBásica'>WebServices
									con Autenticación Básica</a></li>
							<li><span class='TOCOutline'>3.2.2</span> <a
								href='#IntegraçãoComAplicativosExternos-WebServicecomclientcustomizado'>WebService
									con cliente personalizado</a></li>
						</ul></li>
					<li><span class='TOCOutline'>3.3</span> <a
						href='#IntegraçãoComAplicativosExternos-CasodeUso'>Caso de Uso</a></li>
					<li><span class='TOCOutline'>3.4</span> <a
						href='#IntegraçãoComAplicativosExternos-ConfiguraçãodoAppServer'>Configuración
							de AppServer</a></li>
					<li><span class='TOCOutline'>3.5</span> <a
						href='#IntegraçãoComAplicativosExternos-Expondocódigos4GLcomProxyGen'>Exponiendo
							códigos 4GL con ProxyGen</a></li>
					<li><span class='TOCOutline'>3.6</span> <a
						href='#IntegraçãoComAplicativosExternos-ConfiguraçãodoServiçonoFluig'>Configuración
							del Servicio en Fluig</a></li>
					<li><span class='TOCOutline'>3.7</span> <a
						href='#IntegraçãoComAplicativosExternos-VisãoGeraldosObjetosEnvolvidos'>Visión
							general de los objetos involucrados</a>
						<ul class='toc-indentation'>
							<li><span class='TOCOutline'>3.7.1</span> <a
								href='#IntegraçãoComAplicativosExternos-ProceduresPersistenteseNão-Persistentes'>Procedures
									Persistentes y No Persistentes</a></li>
							<li><span class='TOCOutline'>3.7.2</span> <a
								href='#IntegraçãoComAplicativosExternos-ParâmetrosdeEntradaeSaída'>Parámetros
									de Entrada y Salida</a></li>
						</ul></li>
					<li><span class='TOCOutline'>3.8</span> <a
						href='#IntegraçãoComAplicativosExternos-CriaçãodosDatasets'>Creación
							de los Datasets</a>
						<ul class='toc-indentation'>
							<li><span class='TOCOutline'>3.8.1</span> <a
								href='#IntegraçãoComAplicativosExternos-TiposdeCentrodeCusto'>Tipos
									de Centro de Costo</a></li>
							<li><span class='TOCOutline'>3.8.2</span> <a
								href='#IntegraçãoComAplicativosExternos-NaturezadosCentrosdeCusto'>Naturaleza
									de los Centros de Costo</a></li>
							<li><span class='TOCOutline'>3.8.3</span> <a
								href='#IntegraçãoComAplicativosExternos-CentrosdeCusto'>Centros
									de Costo</a>
								<ul class='toc-indentation'>
									<li><span class='TOCOutline'>3.8.3.1</span> <a
										href='#IntegraçãoComAplicativosExternos-CodificaçãoProgress®9'>Codificación
											Progress® 9</a></li>
									<li><span class='TOCOutline'>3.8.3.2</span> <a
										href='#IntegraçãoComAplicativosExternos-CodificaçãoOpenEdge®10'>Codificación
											OpenEdge® 10</a></li>
								</ul></li>
							<li><span class='TOCOutline'>3.8.4</span> <a
								href='#IntegraçãoComAplicativosExternos-UsuáriosemComum'>Usuarios
									en Común</a>
								<ul class='toc-indentation'>
									<li><span class='TOCOutline'>3.8.4.1</span> <a
										href='#IntegraçãoComAplicativosExternos-CodificaçãoProgress®9.1'>Codificación
											Progress® 9</a></li>
									<li><span class='TOCOutline'>3.8.4.2</span> <a
										href='#IntegraçãoComAplicativosExternos-CodificaçãoOpenEdge®10.1'>Codificación
											OpenEdge® 10</a></li>
								</ul></li>
						</ul></li>
					<li><span class='TOCOutline'>3.9</span> <a
						href='#IntegraçãoComAplicativosExternos-ServiceHelper'>Service
							Helper</a></li>
				</ul></li>
			<li><span class='TOCOutline'>4</span> <a
				href='#IntegraçãoComAplicativosExternos-ThirdPartyTrademarks'>Third
					Party Trademarks</a></li>
		</ul>
	</div>
	</p>
	<h1 id="IntegraçãoComAplicativosExternos-ConsideraçõesGerais">Consideraciones
		Generales</h1>
	<p>La información contenida en este documento tiene el objetivo de
		demostrar cómo realizar la integración entre Fluig y aplicaciones
		externas. Para una comprensión completa de esta información, algunos
		conocimientos se consideran requisitos previos, incluyendo entre
		ellos:</p>
	<ul>
		<li class="O1">Visión general del producto Fluig</li>
		<li class="O1">Visión general de la integración de sistemas</li>
		<li class="O1">JavaScript</li>
		<li class="O1">WebServices</li>
		<li class="O1">SOAP</li>
		<li class="O1"><p>
				<span style="font-size: 10.0pt; line-height: 13.0pt;">Progress®
					4GL</span>
			</p></li>
		<li class="O1">Progress® Open App Server</li>
		<li class="O1">Progress® Open Client for&#160;<span
			style="font-size: 10.0pt; line-height: 13.0pt;">Java</span></li>
		<li class="O1">Datasets (Fluig)</li>
		<li class="O1">Java™</li>
		<li class="O1">Apache Flex®</li>
	</ul>
	<p>En varias partes de este documento se presentarán fragmentos de
		código en diferentes lenguajes de programación, con el fin de
		demostrar el uso de las capacidades de integración de Fluig. Sin
		embargo, este documento no pretende capacitar al lector en el uso de
		estas tecnologías más allá de los fines anteriormente descritos,
		siendo responsabilidad del lector buscar información en profundidad
		sobre estos lenguajes.</p>
	<p>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.</p>
	<h1 id="IntegraçãoComAplicativosExternos-VisãoGeral">Visión
		General</h1>
	<p>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).</p>
	<p>Con la llegada de las tecnologías de Sistema de Información,
		varios sistemas comenzaron a apoyar estos procesos de negocio, en
		especial aquellos considerados más críticos para la operación de la
		empresa. El mejor ejemplo de ello es la adopción de los sistemas ERP
		que ofrecen soporte a los procesos de varias áreas de la empresa.</p>
	<p>Fluig pretende ser una plataforma agnóstica de gestión de
		procesos, documentos e identidades a través de una interfaz de
		comunicación colaborativa. Esto se puede percibir en mayor o menor
		grado en cada una de sus funcionalidades, desde las más simples (como
		la colaboración) hasta las más complejas (como DM y BPM).</p>
	<p>No obstante, parte de estos procesos dependen en gran medida de
		los sistemas de información ya existentes en la empresa y por esta
		razón, la arquitectura de Fluig está diseñada para permitir la
		integración a estos sistemas, permitiendo que los procesos modelados
		tengan mayor valor agregado.</p>
	<p>Fluig permite tanto el acceso por el producto a los sistemas
		externos (para consultar o alimentar la información) como también
		posibilita que otros sistemas se conecten para consultar información o
		para ejecutar operaciones de transacción.</p>
	<p>&#160;</p>
	<p>
		<img class="confluence-embedded-image image-center"
			src="http://tdn.totvs.com/download/attachments/73082260/image2013-8-20%2015%3A33%3A42.png?version=1&modificationDate=1377284793000&api=v2"
			data-image-src="http://tdn.totvs.com/download/attachments/73082260/image2013-8-20%2015%3A33%3A42.png?version=1&modificationDate=1377284793000&api=v2">
	</p>
	<p>&#160;</p>
	<p>El principal canal de integración del producto es a través de
		WebServices, que se están convirtiendo en el estándar más común de
		integración con cualquier aplicación. A través de ellos, se puede
		tener acceso a las funcionalidades de Fluig y ofrecer acceso por medio
		del producto a aplicaciones externas. Este documento dedica una
		sección específica a la integración a través de WebServices.</p>
	<p>La otra forma de integración es a través de llamadas a Progress®
		Open AppServer, que se recomienda para usuarios que necesitan integrar
		Fluig con aplicaciones desarrolladas en esta plataforma.</p>
	<h1 id="IntegraçãoComAplicativosExternos-WebServices">WebServices</h1>
	<p>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.</p>
	<h3 id="IntegraçãoComAplicativosExternos-AcessandoosWebServicesdoFluig">Acceso
		a WebServices de Fluig</h3>
	<p>
		Fluig 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.&#160;<span
			style="font-size: 10.0pt; line-height: 13.0pt;">Para tener la
			lista de los WebServices disponibles, ingrese a:&#160;</span>
	</p>
	<div class="preformatted panel" style="border-width: 1px;">
		<div class="preformattedContent panelContent">
			<pre>http://&lt;host>:&lt;porta>/webdesk/services&#160;</pre>
		</div>
	</div>
	<p>Cada link que se muestra dirige el navegador a la URL de WSDL
		del servicio. WSDL (Web Servicio Description Language) tiene la
		descripción del servicio en formato XML y lo utilizan las herramientas
		de desarrollo para crear componentes que representarán este servicio.</p>
	<div class="aui-message warning shadowed information-macro">
		<span class="aui-icon icon-warning">Icon</span>
		<div class="message-content">
			<p>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:</p>
			<ul>
				<li>C#: <strong>dateTime</strong></li>
				<li>Java™: <strong>XMLGregorianCalendar</strong></li>
				<li>Progress®: <strong>DATETIME-TZ</strong></li>
			</ul>
		</div>
	</div>
	<p>&#160;</p>
	<h5 id="IntegraçãoComAplicativosExternos-ViaApacheFlex®">Vía
		Apache Flex®</h5>
	<p>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.</p>
	<p>Utilice el paso a paso para visualizar el proceso de creación de
		los stubs para un servicio ofrecido por Fluig:</p>
	<a name="composition-deck-stubFlex"></a>
	<div id="stubFlex" class="deck" history="false" loopcards="false"
		effecttype="" effectduration="1.0" nextafter="0.0">
		<ul class="tab-navigation"></ul>
		<!-- // .tab-navigation -->
		<div class="deck-cards panel" style="">
			<div id="1" class="deck-card  active-pane" style="" cssclass=""
				accesskey="" label="1&amp;ordm; Passo" title="" nextafter="0"
				effecttype="fade" effectduration="0.5">
				<p>La creación de los stubs en&#160;Flex® se lleva a cabo a
					través del menú Data, opción Import WebService(WSDL), como muestra
					la siguiente imagen.</p>
				<p>
					<img class="confluence-embedded-image"
						src="http://tdn.totvs.com/download/attachments/73082260/image2013-8-21%2010%3A30%3A3.png?version=1&modificationDate=1377284793000&api=v2"
						data-image-src="http://tdn.totvs.com/download/attachments/73082260/image2013-8-21%2010%3A30%3A3.png?version=1&modificationDate=1377284793000&api=v2">
				</p>
			</div>
			<div id="2" class="deck-card " style="" cssclass="" accesskey=""
				label="2&amp;ordm; Passo" title="" nextafter="0" effecttype="fade"
				effectduration="0.5">
				<p>En la primera ventana, se solicita la carpeta dentro del
					proyecto actual donde deben generarse los stubs.</p>
				<p>
					<img class="confluence-embedded-image"
						src="http://tdn.totvs.com/download/attachments/73082260/image2013-8-21%2010%3A34%3A29.png?version=1&modificationDate=1377284793000&api=v2"
						data-image-src="http://tdn.totvs.com/download/attachments/73082260/image2013-8-21%2010%3A34%3A29.png?version=1&modificationDate=1377284793000&api=v2">
				</p>
			</div>
			<div id="3" class="deck-card " style="" cssclass="" accesskey=""
				label="3&amp;ordm; Passo" title="" nextafter="0" effecttype="fade"
				effectduration="0.5">
				<p>En la siguiente pantalla, se debe informar la dirección de
					WSDL donde se encuentra el servicio. También se puede definir si se
					accede desde la estación de cliente o desde el servidor LiveCycle
					Data Services.</p>
				<p>
					<img class="confluence-embedded-image"
						src="http://tdn.totvs.com/download/attachments/73082260/image2013-8-21%2010%3A36%3A18.png?version=1&modificationDate=1377284793000&api=v2"
						data-image-src="http://tdn.totvs.com/download/attachments/73082260/image2013-8-21%2010%3A36%3A18.png?version=1&modificationDate=1377284793000&api=v2">
				</p>
			</div>
			<div id="4" class="deck-card " style="" cssclass="" accesskey=""
				label="4&amp;ordm; Passo" title="" nextafter="0" effecttype="fade"
				effectduration="0.5">
				<p>En la última pantalla, se debe informar el package que se
					utilizará y cuál es el nombre de la clase principal (ya sugeridos
					por Flex™ Builder™).</p>
				<p>
					<img class="confluence-embedded-image"
						src="http://tdn.totvs.com/download/attachments/73082260/image2013-8-21%2010%3A39%3A19.png?version=1&modificationDate=1377284793000&api=v2"
						data-image-src="http://tdn.totvs.com/download/attachments/73082260/image2013-8-21%2010%3A39%3A19.png?version=1&modificationDate=1377284793000&api=v2">
				</p>
			</div>
			<div id="5" class="deck-card " style="" cssclass="" accesskey=""
				label="Resultado" title="" nextafter="0" effecttype="fade"
				effectduration="0.5">
				<p>Una vez finalizado el proceso, Flex ™ Builder ™ agregará al
					proyecto un conjunto de clases que serán utilizadas por el
					programador para invocar los servicios, como se muestra a
					continuación:</p>
				<p>
					<img class="confluence-embedded-image"
						src="http://tdn.totvs.com/download/attachments/73082260/image2013-8-21%2010%3A57%3A40.png?version=1&modificationDate=1377284793000&api=v2"
						data-image-src="http://tdn.totvs.com/download/attachments/73082260/image2013-8-21%2010%3A57%3A40.png?version=1&modificationDate=1377284793000&api=v2">
				</p>
			</div>
		</div>
	</div>
	<!-- // .deck -->
	<div class="aui-message hint shadowed information-macro">
		<span class="aui-icon icon-hint">Icon</span>
		<div class="message-content">
			<p>
				Para el ejemplo que se presenta a continuación, se utilizó IDE
				Adobe® Flex™ Builder™ 3.0 con Flex® SDK 3.2. Para otras versiones de
				IDE y/o SDK, el proceso de creación de los stubs puede sufrir
				algunas variaciones.<span
					style="font-size: 10.0pt; line-height: 13.0pt;">&#160;</span>
			</p>
		</div>
	</div>
	<p>El siguiente fragmento de código presenta un ejemplo de
		invocación de WebService de acceso a los Datasets de Fluig:</p>
	<div class="code panel pdl" style="border-width: 1px;">
		<div class="codeHeader panelHeader pdl"
			style="border-bottom-width: 1px;">
			<b>ECMDatasetServiceClient.mxml</b>
		</div>
		<div class="codeContent panelContent pdl">
			<pre
				class="first-line: 1; theme: Eclipse; brush: actionscript3; gutter: true"
				style="font-size: 12px;">&lt;?xml version="1.0" encoding="utf-8"?>
&lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="{this.start()}">
	&lt;mx:Script>
		&lt;![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;
		
			//Crea una instancia de stub de acceso al servicio
			private var ds:ECMDatasetServiceService = new ECMDatasetServiceService();
			public function start() : void {
				//Crea tipos auxiliares que se utilizarán en la llamada de servicio
				var fields:StringArray = new StringArray();
				var constraints:SearchConstraintDtoArray = new SearchConstraintDtoArray();
				var order:StringArray = new StringArray();
				//Define las funciones para tratamiento de la devolución
				ds.addEventListener(GetDatasetResultEvent.GetDataset_RESULT, resultGetDataset);
				ds.addEventListener(FaultEvent.FAULT,faultGetDataset);
				
				//invoca el método getDataset del servicio
				ds.getDataset("adm", 1, "adm", constraints, order, fields, "colleague");
			}
			
			//Tratamiento de los datos devueltos por el servicio invocado.
			public function resultGetDataset(ev:GetDatasetResultEvent) : void {
				//Recupera la devolución del servicio, en forma de un DatasetDto
				var dataset:DatasetDto = ev.result as DatasetDto;
				//Instala una string con todos los datos del dataset
				var line:String = "";
				
				//Encabezado con el nombre de los campos
				var columnsArray:ArrayCollection = new ArrayCollection(dataset.columns);
				for (var j:int = 0; j &lt; columnsArray.length; j++) {
					line += columnsArray.getItemAt(j) + "\t";
				}
				//Línea de datos
				var valuesArray:ArrayCollection = new ArrayCollection(dataset.values);
				for (var j:int = 0; j &lt; valuesArray.length; j++) {
					var row:ValuesDto = valuesArray.getItemAt(j) as ValuesDto;
					line += "\n" + j + ":";
					
					for (var i:int = 0; i &lt; row.length; i++) {
						line += row.getItemAt(i) + "\t";
					}
				}
				
				//Muestra la string creada en un textarea en la pantalla
				this.sysout.text = line;
			}
			
			public function faultGetDataset(ev:FaultEvent) : void {
				this.sysout.text = ev.fault.faultString;
			}
		]]>
	&lt;/mx:Script>
	&lt;mx:TextArea id="sysout" name="sysout" width="100%" height="100%" 
		paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5"/>
&lt;/mx:Application></pre>
		</div>
	</div>
	<div class="aui-message warning shadowed information-macro">
		<span class="aui-icon icon-warning">Icon</span>
		<div class="message-content">
			<p>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).</p>
			<p>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:</p>
			<div class="code panel pdl" style="border-width: 1px;">
				<div class="codeContent panelContent pdl">
					<pre
						class="first-line: 1; theme: Eclipse; brush: actionscript3; gutter: true"
						style="font-size: 12px;">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 el array
}</pre>
				</div>
			</div>
			<p>Otros servicios que no trabajan con arrays multidimensionales
				no exigen cambios en el código generado.</p>
		</div>
	</div>
	<p>&#160;</p>
	<h5 id="IntegraçãoComAplicativosExternos-ViaJava™">Vía Java™</h5>
	<p>Existen muchas implementaciones de uso de WebServices en Java ™
		y en este ejemplo vamos a utilizar las bibliotecas disponibles en Java
		™ 7.</p>
	<p>Del mismo modo que en el ejemplo anterior, en Apache Flex®, el
		primer paso consiste en utilizar la dirección WSDL para generar los
		stubs en Java ™. El siguiente comando presenta un ejemplo de cómo
		generar estos stubs:</p>
	<div class="preformatted panel" style="border-width: 1px;">
		<div class="preformattedContent panelContent">
			<pre>wsimport -d &lt;output_directory> &lt;wsdl_url></pre>
		</div>
	</div>
	<p>A través de este comando se generan los stubs en el directorio
		de destino (output_directory), según la descripción del archivo wsdl
		(wsdl_url).</p>
	<p>
		<img class="confluence-embedded-image"
			src="http://tdn.totvs.com/download/attachments/73082260/image2013-8-20%2016%3A0%3A2.png?version=1&modificationDate=1377284793000&api=v2"
			data-image-src="http://tdn.totvs.com/download/attachments/73082260/image2013-8-20%2016%3A0%3A2.png?version=1&modificationDate=1377284793000&api=v2">
	</p>
	<p>A partir de los stubs generados, se puede consumir el WebService
		como se muestra en el siguiente ejemplo:</p>
	<div class="code panel pdl" style="border-width: 1px;">
		<div class="codeHeader panelHeader pdl"
			style="border-bottom-width: 1px;">
			<b>ECMDatasetServiceClient.java</b>
		</div>
		<div class="codeContent panelContent pdl">
			<pre class="first-line: 1; theme: Eclipse; brush: java; gutter: true"
				style="font-size: 12px;">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;
/*
 * Clase para invocar servicio DatasetService
 */
public class ECMDatasetServiceClient {
	//Instancia DatasetServiceService.
	private ECMDatasetServiceService ecmDatasetServiceService = new ECMDatasetServiceService();
	private DatasetService service = ecmDatasetServiceService.getDatasetServicePort();
	
	//Inicia ejecución de la clase
	public static void main(String[] args) {
		ECMDatasetServiceClient client = new ECMDatasetServiceClient();
		
		//Configura acceso a 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 {
		
		//Crea los parámetros utilizados en la llamada
		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 el servicio de dataset
		DatasetDto result = service.getDataset(
				companyId, username, password, name, fields, constraints, order);
		
		//Presenta el encabezado
		for (String columnName : result.getColumns()) {
			System.out.print(columnName + "\t");
		}
		System.out.println();
		
		//Presenta las líneas del dataset
		for (ValuesDto row : result.getValues()) {
			for (Object value : row.getValue()) {
				System.out.print(value + "\t");
			}
			System.out.println();
		}
	}
}</pre>
		</div>
	</div>
	<div class="aui-message warning shadowed information-macro">
		<span class="aui-icon icon-warning">Icon</span>
		<div class="message-content">
			<p>
				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 tipo <strong>fecha </strong>se debe
				utilizar la clase <strong>XMLGregorianCalendar:</strong>
			</p>
			<div class="code panel pdl" style="border-width: 1px;">
				<div class="codeContent panelContent pdl">
					<pre
						class="first-line: 1; theme: Eclipse; brush: java; gutter: true"
						style="font-size: 12px;">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);</pre>
				</div>
			</div>
		</div>
	</div>
	<p>&#160;</p>
	<h5 id="IntegraçãoComAplicativosExternos-ViaProgress®4GL">Vía
		Progress® 4GL</h5>
	<p>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.</p>
	<p>
		Para generar la documentación de un servicio, se debe utilizar la
		utilidad <strong>bprowsdldoc</strong> como en el siguiente ejemplo:
	</p>
	<div class="preformatted panel" style="border-width: 1px;">
		<div class="preformattedContent panelContent">
			<pre>bprowsdldoc &lt;URL_TO_WSDL></pre>
		</div>
	</div>
	<p>Mediante la ejecución de esta utilidad se generarán algunos
		archivos HTML con la información sobre la forma de consumir el
		servicio. Esta documentación proporciona información y ejemplos de
		cómo llevar a cabo la conexión con el servicio y cómo utilizar los
		métodos y datatypes del servicio.&#160;</p>
	<p>
		<span style="font-size: 10.0pt; line-height: 13.0pt;">El
			siguiente código presenta un ejemplo de cómo consumir el servicio:</span>
	</p>
	<div class="code panel pdl" style="border-width: 1px;">
		<div class="codeHeader panelHeader pdl"
			style="border-bottom-width: 1px;">
			<b>wsECMDatasetService.p</b>
		</div>
		<div class="codeContent panelContent pdl">
			<pre
				class="first-line: 1; theme: Eclipse; brush: javafx; gutter: true"
				style="font-size: 12px;">/* Parte I - Invocar el 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 ítem NO-UNDO
    NAMESPACE-URI ""
    FIELD contraintType AS CHARACTER
	FIELD fieldName     AS CHARACTER
	FIELD finalValue    AS CHARACTER
	FIELD initialValue  AS CHARACTER.
&#160;
DEFINE DATASET dConstraints NAMESPACE-URI "http://ws.dataservice.ecm.technology.totvs.com/"
	FOR ítem.
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 - Realiza el parser de XML y crear un archivo de texto separado por tabulación */
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).
/* Recorre las columnas &lt;columns> */ 
DO iCount = 1 TO hRoot:NUM-CHILDREN WITH 20 DOWN:
    hRoot:GET-CHILD(hEntry, iCount).
    IF hEntry:NAME &lt;> "columns" THEN
        NEXT.
    hEntry:GET-CHILD(hText, 1).
    PUT UNFORMATTED hText:NODE-VALUE "~t".
    DOWN.
END.
PUT UNFORMATTED SKIP.
/* Recorre los registros &lt;values> */
DO iCount = 1 TO hRoot:NUM-CHILDREN WITH 20 DOWN:
    hRoot:GET-CHILD(hValues, iCount).
    IF hValues:NAME &lt;> "values" THEN
        NEXT.
    /* Recorre los campos &lt;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.</pre>
		</div>
	</div>
	<h3
		id="IntegraçãoComAplicativosExternos-AcessandoWebServicesapartirdoFluig">Acceso
		a WebServices desde Fluig</h3>
	<p>Fluig permite realizar llamadas a WebServices de terceros a
		través del registro de Servicios en la visualización de Servicios de
		Fluig&#160;Studio.</p>
	<p>
		Para agregar un nuevo WebService, es necesario ingresar a la opción <strong>Incluir
			Servicio,&#160;</strong>abriendo el asistente Nuevo Servicio, e informar al
		servidor de Fluig donde se agregará el servicio,&#160;<span
			style="font-size: 10.0pt; line-height: 13.0pt;">un código
			identificador para él, su descripción, la URL para WSDL y su tipo (en
			este caso WebService).&#160;</span><span
			style="font-size: 10.0pt; line-height: 13.0pt;">En el
			siguiente ejemplo, se utilizará un WebService público para consultar
			la tabla periódica, cuya dirección de WSDL es&#160;</span><span
			class="nolink" style="font-size: 10.0pt; line-height: 13.0pt;"><a
			href="http://www.webservicex.com/periodictable.asmx?wsdl"
			class="external-link" rel="nofollow">http://www.webservicex.com/periodictable.asmx?wsdl</a></span><span
			style="font-size: 10.0pt; line-height: 13.0pt;">.</span>
	</p>
	<p>
		<span style="font-size: 10.0pt; line-height: 13.0pt;"><img
			class="confluence-embedded-image image-center"
			src="http://tdn.totvs.com/download/attachments/73082260/acesso-ws-1.png?version=1&modificationDate=1377284793000&api=v2"
			data-image-src="http://tdn.totvs.com/download/attachments/73082260/acesso-ws-1.png?version=1&modificationDate=1377284793000&api=v2"></span>
	</p>
	<p>Basado en esta información, Fluig extraerá la información sobre
		el WebService informado y finalizará el registro de este
		servicio.&#160;</p>
	<p>
		<span style="font-size: 10.0pt; line-height: 13.0pt;">Una vez
			que el servicio está registrado, se pueden ver las clases y métodos
			disponibles en este servicio y que se utilizarán en los códigos
			JavaScript que lo usarán. La siguiente pantalla presenta un ejemplo
			de visualización de WebService.</span>
	</p>
	<p>
		<span style="font-size: 10.0pt; line-height: 13.0pt;"><img
			class="confluence-embedded-image image-center"
			src="http://tdn.totvs.com/download/attachments/73082260/acesso-ws-2.png?version=1&modificationDate=1377284793000&api=v2"
			data-image-src="http://tdn.totvs.com/download/attachments/73082260/acesso-ws-2.png?version=1&modificationDate=1377284793000&api=v2"></span>
	</p>
	<p>
		Los servicios agregados en Fluig se pueden instanciar y utilizar en
		los puntos donde el producto permite personalización utilizando
		JavaScript, como en scripts para eventos globales, eventos de
		procesos, eventos de definición de formulario o Datasets.&#160;<span
			style="font-size: 10.0pt; line-height: 13.0pt;">En el
			siguiente ejemplo se creará un Dataset que usará este servicio para
			traer los datos de la tabla periódica.</span>
	</p>
	<p>El siguiente código presenta una implementación de ejemplo del
		uso de un servicio en la construcción de un Dataset:</p>
	<div class="code panel pdl" style="border-width: 1px;">
		<div class="codeHeader panelHeader pdl"
			style="border-bottom-width: 1px;">
			<b>periodicTable.js</b>
		</div>
		<div class="codeContent panelContent pdl">
			<pre
				class="first-line: 1; theme: Eclipse; brush: javascript; gutter: true"
				style="font-size: 12px;">function createDataset(fields, constraints, sortFields) {
	//Crea el dataset
	var dataset = DatasetBuilder.newDataset();
	dataset.addColumn("elementName");
	// Conecta el servicio y busca los libros
	var periodicService = ServiceManager.getService('PeriodicTable');
	var serviceHelper = periodicService.getBean();
	var serviceLocator = serviceHelper.instantiate('net.webservicex.Periodictable');
	var service = serviceLocator.getPeriodictableSoap();
	//Invoca el servicio
	try {
		var result = service.getAtoms();
		var NewDataSet = new XML(result);
		for each(element in NewDataSet.Table) {
			dataset.addRow(new Array(element.ElementName.toString()));
		}
	} catch(erro) {
		dataset.addRow(new Array(erro));
	}
	return dataset;
}</pre>
		</div>
	</div>
	<p>
		El primer paso para invocar el servicio es solicitar a Fluig que
		cargue el servicio, a partir del método <strong>ServiceManager.getService('PeriodicTable')</strong>.
		El valor informado como parámetro debe ser el código utilizado cuando
		se registró el servicio.
	</p>
	<p>
		Cuando el servicio se haya cargado, se utiliza el método <strong>getBean()</strong>
		para devolver una utilidad para acceder a las clases del servicio, a
		través del método <strong>instantiate</strong>. A través de esta
		utilidad, se pueden instanciar las clases disponibles, que se
		encuentran en el registro del Servicio (como se puede ver en la imagen
		anterior).
	</p>
	<p>Después de que se haya instanciado el objeto utilidad del
		servicio, las clases se deben instanciar y los métodos que se deben
		invocar depende de cada WebService utilizado y, deben recurrir a su
		documentación para obtener más información.</p>
	<p>Para el servicio de la tabla periódica es necesario realizar los
		siguientes pasos:</p>
	<div class="code panel pdl" style="border-width: 1px;">
		<div class="codeContent panelContent pdl">
			<pre
				class="first-line: 1; theme: Eclipse; brush: javascript; gutter: true"
				style="font-size: 12px;">var serviceLocator = serviceHelper.instantiate('net.webservicex.Periodictable');
var service = serviceLocator.getPeriodictableSoap();
var result = service.getAtoms();</pre>
		</div>
	</div>
	<p>Donde:</p>
	<ul>
		<li><p>
				<strong>Paso 1:&#160;</strong>Instanciar la clase&#160;<strong><span
					style="font-size: 10.0pt; line-height: 13.0pt;">net.webservicex.Periodictable</span></strong><span
					style="font-size: 10.0pt; line-height: 13.0pt;">&#160;para
					tener acceso al localizador del servicio;&#160;</span>
			</p></li>
		<li><span style="font-size: 10.0pt; line-height: 13.0pt;"><strong>Paso
					2:</strong> Invocar el método <strong>getPeriodictableSoap</strong> para
				instanciar el servicio;</span></li>
		<li><span style="font-size: 10.0pt; line-height: 13.0pt;"><strong>Paso
					3:</strong> Invocar el método <strong>getAtoms</strong> para tener la lista
				de los elementos.</span><br />
		<span style="font-size: 10.0pt; line-height: 13.0pt;"><br /></span></li>
	</ul>
	<p>
		En el caso de este servicio, el método <strong>getAtoms</strong>
		devuelve una string que contiene un XML con la lista de todos los
		elementos, como se muestra en el siguiente ejemplo:
	</p>
	<div class="code panel pdl" style="border-width: 1px;">
		<div class="codeContent panelContent pdl">
			<pre
				class="first-line: 1; theme: Eclipse; brush: html/xml; gutter: true"
				style="font-size: 12px;">&lt;NewDataSet>
	&lt;Table>
		&lt;ElementName>Actinium&lt;/ElementName>
	&lt;/Table>
	&lt;Table>
		&lt;ElementName>Aluminium&lt;/ElementName>
	&lt;/Table>
	...
&lt;/NewDataSet></pre>
		</div>
	</div>
	<p>
		Para recorrer el XML y extraer los datos disponibles, se utilizan las
		funcionalidades de tratamiento de XML de JavaScript que facilita la
		manipulación de datos de este tipo. Para más información sobre esta
		funcionalidad, ingrese a :&#160;<a
			href="http://www.ecma-international.org/publications/standards/Ecma-357.htm"
			style="font-size: 10.0pt; line-height: 13.0pt;" class="external-link"
			rel="nofollow">http://www.ecma-international.org/publications/standards/Ecma-357.htm</a><span
			style="font-size: 10.0pt; line-height: 13.0pt;"> o </span><a
			href="http://www.xml.com/pub/a/2007/11/28/introducing-e4x.html"
			style="font-size: 10.0pt; line-height: 13.0pt;" class="external-link"
			rel="nofollow">http://www.xml.com/pub/a/2007/11/28/introducing-e4x.html</a><span
			style="font-size: 10.0pt; line-height: 13.0pt;">.</span>
	</p>
	<p>El siguiente ejemplo presenta el código utilizado para recorrer
		el XML devuelto:</p>
	<div class="code panel pdl" style="border-width: 1px;">
		<div class="codeContent panelContent pdl">
			<pre
				class="first-line: 1; theme: Eclipse; brush: javascript; gutter: true"
				style="font-size: 12px;">var NewDataSet = new XML(result);
for each(element in NewDataSet.Table) {
	dataset.addRow(new Array(element.ElementName.toString()));
}</pre>
		</div>
	</div>
	<p>Una vez implementado el código del Dataset, es posible
		visualizarlo, como muestra la siguiente figura:</p>
	<p>
		<img class="confluence-embedded-image image-center"
			src="http://tdn.totvs.com/download/attachments/73082260/acesso-ws-3.png?version=1&modificationDate=1377284793000&api=v2"
			data-image-src="http://tdn.totvs.com/download/attachments/73082260/acesso-ws-3.png?version=1&modificationDate=1377284793000&api=v2">
	</p>
	<p>&#160;</p>
	<h5
		id="IntegraçãoComAplicativosExternos-WebServicescomAutenticaçãoBásica">WebServices
		con Autenticación Básica</h5>
	<p>
		Para consumir WebServices que utilizan la autenticación básica (<em>WSS</em>
		o <em>WS-Security</em>), es necesario utilizar el método&#160;<strong>getBasicAuthenticatedClient&#160;</strong>localizado
		en provider del servicio (el mismo que se obtiene vía <strong>ServiceManager).&#160;</strong>Este
		método proporciona un client autenticado.
	</p>
	<p>&#160;</p>
	<p>Los parámetros que se deben informar en el método siguen el
		siguiente orden:</p>
	<ol>
		<li>Instancia del servicio</li>
		<li>Nombre de la clase del servicio</li>
		<li>Usuario para la autenticación</li>
		<li>Contraseña para la autenticación</li>
	</ol>
	<p>
		Utilizando el ejemplo del servicio&#160;<strong>PeriodicTable&#160;</strong>presentado
		anteriormente, el código de la llamada tendría los siguientes cambios:
	</p>
	<div class="code panel pdl" style="border-width: 1px;">
		<div class="codeContent panelContent pdl">
			<pre
				class="first-line: 1; theme: Eclipse; brush: javascript; gutter: true"
				style="font-size: 12px;">var serviceLocator = serviceHelper.instantiate('net.webservicex.Periodictable');
var service = serviceLocator.getPeriodictableSoap();
var authenticatedService = serviceHelper.getBasicAuthenticatedClient(service, "net.webservicex.PeriodictableSoap", 'usuario', 'contraseña');
var result = authenticatedService.getAtoms();</pre>
		</div>
	</div>
	<h5
		id="IntegraçãoComAplicativosExternos-WebServicecomclientcustomizado">
		<span
			style="color: rgb(0, 0, 0); font-size: 1.8em; font-weight: bold; line-height: normal;"><br /></span>WebService
		con client personalizado
	</h5>
	<div class="aui-message warning shadowed information-macro">
		<p class="title">Atención</p>
		<span class="aui-icon icon-warning">Icon</span>
		<div class="message-content">
			<p>Esta técnica es válida para Fluig 1.3.7 o superior.</p>
			<p>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".</p>
		</div>
	</div>
	<p>
		Para personalizar el client que accede al servicio se debe utilizar el
		método <strong>getCustomClient</strong>,&#160;localizado en provider
		del servicio (el mesmo que se obtiene vía&#160;<strong>ServiceManager</strong>).
		Esta configuración exige la creación de un mapa de parámetros con sus
		respectivos valores para pasar al método, según el siguiente <em
			style="line-height: 1.4285715;">snippet</em>:
	</p>
	<div class="code panel pdl" style="border-width: 1px;">
		<div class="codeContent panelContent pdl">
			<pre class="theme: Eclipse; brush: js; gutter: false"
				style="font-size: 12px;">		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";
		
		var serviceLocator = serviceHelper.instantiate('net.webservicex.Periodictable');
		var service = serviceLocator.getPeriodictableSoap();
		var customClient = serviceHelper.getCustomClient(service, "net.webservicex.PeriodictableSoap", properties);
		var result = customClient.getAtoms();</pre>
		</div>
	</div>
	<p>&#160;</p>
	<p>Los parámetros que se pueden configurar son los siguientes:</p>
	<div class="table-wrap">
		<table class="confluenceTable">
			<tbody>
				<tr>
					<th class="confluenceTh">Propriedad</th>
					<th class="confluenceTh">Función</th>
				</tr>
				<tr>
					<td class="confluenceTd"><pre>basic.authorization</pre></td>
					<td class="confluenceTd"><p>
							Cuando se define como "true", hace lo mismo que el método&#160;<strong>getBasicAuthenticatedClient</strong>,
							pero permite aplicar la configuración de autenticación junto con
							las demás personalizaciones que se detallan a continuación. Para
							configurar la autenticación<span style="line-height: 1.4285715;">,
								las siguientes propiedades con "username" y "password" también
								necesitan definirse.</span>
						</p></td>
				</tr>
				<tr>
					<td class="confluenceTd"><pre>basic.authorization.username</pre></td>
					<td class="confluenceTd">Usuario que se utilizará para
						autenticación básica.</td>
				</tr>
				<tr>
					<td class="confluenceTd"><pre>basic.authorization.password</pre></td>
					<td class="confluenceTd">Contraseña de usuario utilizado para
						autenticación básica.</td>
				</tr>
				<tr>
					<td class="confluenceTd"><pre>disable.chunking</pre></td>
					<td class="confluenceTd"><p>Cuando se define como "true",
							desactiva el envío de solicitudes grandes en "fragmentos"
							menores. Puede ser útil cuando el servicio llamado no admite este
							tipo de solicitud.</p></td>
				</tr>
				<tr>
					<td colspan="1" class="confluenceTd"><pre>log.soap.messages</pre></td>
					<td colspan="1" class="confluenceTd">Cuando se define como
						"true", permite que los mensajes SOAP utilizados en las
						solicitudes realizadas a los servicios se presenten en el log del
						servidor, lo que facilita la depuración en caso de fallas.</td>
				</tr>
			</tbody>
		</table>
	</div>
	<p>&#160;</p>
	<p>
		<span
			style="color: rgb(0, 0, 0); font-size: 1.8em; font-weight: bold; line-height: normal;">Progress®
			Open AppServer</span>
	</p>
	<p>Así como es posible invocar operaciones en WebServices, Fluig
		también permite realizar llamadas a programas en Progress® 4GL (o ABL)
		expuestos vía Progress® Open AppServer.</p>
	<p>En los siguientes ejemplos, se crearán Datasets que a través de
		la capa de servicio, tendrán acceso a las lógicas en 4GL que
		realizarán la extracción de datos. Aunque los códigos 4GL, en este
		ejemplo, sean muy simples, abarcan los casos más comunes requeridos en
		el día a día, ya que la complejidad de la integración se encuentra en
		las interfaces (parámetros de entrada y salida) de cada procedure
		expuesto y no en su lógica interna.</p>
	<p>Tenga en cuenta que los ejemplos que aquí se presentan pretenden
		demostrar la dinámica de la integración entre Progress® y Fluig sin
		entrar en detalles específicos de las tecnologías involucradas. La
		capa de servicios Progress® de Fluig 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®.</p>
	<h3 id="IntegraçãoComAplicativosExternos-CasodeUso">Caso de Uso</h3>
	<p>
		Los ejemplos que se muestran a continuación, tienen como objetivo
		crear cuatro Datasets&#160;<sup>1</sup> en Fluig:
	</p>
	<ol>
		<li><strong>Tipos de Centro de Costo,&#160;</strong>que deben
			devolver los tipos de centros de coste existente en la aplicación en
			Progress® (en este caso, EMS2).</li>
		<li><strong>Naturaleza de los Centros de Costo,&#160;</strong>que
			debe devolver los tipos posibles de naturaleza, según la aplicación
			en Progress® (en este caso, EMS2).</li>
		<li><strong>Centros de Costo,&#160;</strong>que debe devolver los
			registros en la tabla cuenta&#160;<sup>2</sup>.</li>
		<li><p>
				<strong>Usuarios Comunes,&#160;</strong>que debe generar una lista
				de usuarios comunes entre Fluig y la aplicación en Progress®
				(utilizando la tabla usuar_mestre).
			</p>
			<div class="aui-message warning shadowed information-macro">
				<span class="aui-icon icon-warning">Icon</span>
				<div class="message-content">
					<p>
						<span>1 - Los ejemplos utilizan una base de datos de EMS2
							para consultar los centros de costo y los usuarios. No obstante,
							sólo dos tablas y seis campos se utilizan en total, lo que no
							debe perjudicar la comprensión de la lógica por parte del lector,
							ni impedir la creación de un esquema equivalente para pruebas, en
							caso de ser necesario.</span>
					</p>
					<p>
						<span>2 - El código presentado para extracción de los
							centros de costo tiene fines puramente educativos y no puede
							considerarse para el uso en producción. Para obtener más
							información acerca de cómo extraer los centros de costos de EMS2,
							consulte su documentación técnica.</span>
					</p>
				</div>
			</div></li>
	</ol>
	<p>Para los tres primeros casos, la lógica de extracción de la
		información deseada estará expuesta en un programa con varios
		procedures, uno para cada necesidad que aquí se presenta:</p>
	<div class="code panel pdl" style="border-width: 1px;">
		<div class="codeHeader panelHeader pdl"
			style="border-bottom-width: 1px;">
			<b>CostCenterUtils.p</b>
		</div>
		<div class="codeContent panelContent pdl">
			<pre
				class="first-line: 1; theme: Eclipse; brush: javafx; gutter: true"
				style="font-size: 12px;">/**************************************************************************
** Utilidad que ofrece procedures para la extracción de información
** sobre centros de costo.
**************************************************************************/
DEFINE TEMP-TABLE ttCC NO-UNDO
    FIELD cuenta    LIKE cuenta.ct-codigo /* CHARACTER */
    FIELD naturaleza LIKE cuenta.naturaleza  /* INTEGER   */
    FIELD tipo     LIKE cuenta.tipo      /* INTEGER   */
    FIELD titulo   LIKE cuenta.titulo.   /* CHARACTER */
&#160;
/*-------------------------------------------------------------------
  Procedure: readCostCenters
   Objetivo: Devuelve una temp-table con la lista de centros de costo.
----------------------------------------------------------------------*/
PROCEDURE readCostCenters:
    DEFINE OUTPUT PARAMETER TABLE FOR ttCC.
    FOR EACH cuenta:
        CREATE ttCC.
        ASSIGN
            ttCC.cuenta    = cuenta.ct-codigo
            ttCC.naturaleza = cuenta.naturaleza
            ttCC.tipo     = cuenta.tipo
            ttCC.titulo   = cuenta.titulo.
    END.
END.
/*-------------------------------------------------------------------
  Procedure: readCostNatureTypes
   Objetivo: Devuelve una string con las naturalezas de los centros de costo,
             separadas por coma.
----------------------------------------------------------------------*/
PROCEDURE readCostNatureTypes:
    DEFINE OUTPUT PARAMETER cNatureList AS CHARACTER NO-UNDO.
    cNatureList = {adinc/i01ad047.i 03}.
END.
/*-------------------------------------------------------------------
  Procedure: readCostTypes
   Objetivo: Devuelve una string con los tipos de centro de costo,
             separados por coma.
----------------------------------------------------------------------*/
PROCEDURE readCostTypes: 
    DEFINE OUTPUT PARAMETER cTypeList   AS CHARACTER NO-UNDO.
    cTypeList = {adinc/i02ad047.i 3}.
END.</pre>
		</div>
	</div>
	<p>En el caso de la extracción de usuarios comunes a los dos
		productos, se utilizará un único programa, según el siguiente código:</p>
	<div class="code panel pdl" style="border-width: 1px;">
		<div class="codeHeader panelHeader pdl"
			style="border-bottom-width: 1px;">
			<b>verifyUsers.p</b>
		</div>
		<div class="codeContent panelContent pdl">
			<pre
				class="first-line: 1; theme: Eclipse; brush: javafx; gutter: true"
				style="font-size: 12px;">/**************************************************************************
** Utilidad que recibe una temp-table con una lista de usuarios y devuelve
** otra, sólo con los usuarios de la lista que existan en la base de datos.
**************************************************************************/
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.</pre>
		</div>
	</div>
	<p>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.</p>
	<h3 id="IntegraçãoComAplicativosExternos-ConfiguraçãodoAppServer">
		<a name="_Toc324776230" rel="nofollow"></a>Configuración de AppServer
	</h3>
	<p>Algunas informaciones importantes en la configuración del
		AppServer:</p>
	<ol>
		<li>AppServer debe cargarse en el modo Stateless;</li>
		<li><p>En la configuración del agente, en el campo Propath,
				se debe agregar el directorio donde están ubicados los archivos
				compilados (.r).</p>
			<div class="aui-message warning shadowed information-macro">
				<span class="aui-icon icon-warning">Icon</span>
				<div class="message-content">
					<p>
						<strong>Importante:</strong> 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.
					</p>
				</div>
			</div></li>
	</ol>
	<h3 id="IntegraçãoComAplicativosExternos-Expondocódigos4GLcomProxyGen">Exponiendo
		códigos 4GL con ProxyGen</h3>
	<p>
		<span style="font-size: 10.0pt; font-family: Arial, sans-serif;">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.</span>
	</p>
	<p>Utilice el paso a paso para visualizar el proceso de creación
		del proxy:</p>
	<a name="composition-deck-proxyGen"></a>
	<div id="proxyGen" class="deck" history="false" loopcards="false"
		effecttype="fade" effectduration="0.5" nextafter="0.0">
		<ul class="tab-navigation"></ul>
		<!-- // .tab-navigation -->
		<div class="deck-cards panel" style="">
			<div id="1" class="deck-card  active-pane" style="" cssclass=""
				accesskey="" label="1&amp;ordm; Passo" title="" nextafter="0"
				effecttype="default" effectduration="-1.0">
				<p>
					<span
						style="font-size: 10.0pt; line-height: 13.0pt; text-align: justify;">En
						la primera pantalla del ProxyGen, el punto principal que se debe
						tener en cuenta es el nombre del Proyecto (en el ejemplo,
						EMSProxies). La información de este campo será utilizada por
						ProxyGen para nombrar la clase de acceso al servicio, y se
						utilizará en la configuración del servicio en Fluig. En esta
						pantalla también es necesario configurar PROPATH de manera
						correcta, para que se puedan encontrar los archivos compilados
						(.r).</span>
				</p>
				<p>
					<span
						style="font-size: 10.0pt; line-height: 13.0pt; text-align: justify;"><img
						class="confluence-embedded-image"
						src="http://tdn.totvs.com/download/attachments/73082260/proxygen-1.png?version=1&modificationDate=1377284793000&api=v2"
						data-image-src="http://tdn.totvs.com/download/attachments/73082260/proxygen-1.png?version=1&modificationDate=1377284793000&api=v2"><br /></span>
				</p>
			</div>
			<div id="2" class="deck-card " style="" cssclass="" accesskey=""
				label="2&amp;ordm; Passo" title="" nextafter="0"
				effecttype="default" effectduration="-1.0">
				<p>
					<span
						style="font-size: 10.0pt; line-height: 13.0pt; text-align: justify;">El
						segundo paso consiste en introducir los procedures que se
						expondrán de forma persistente o no persistente. La elección de la
						opción que se va a utilizar depende de la forma en la que se
						construyó cada objeto expuesto. Después de introducidos los
						procedures, haga clic en la opción <strong>Generate.</strong>
					</span>
				</p>
				<p>
					<span
						style="font-size: 10.0pt; line-height: 13.0pt; text-align: justify;"><img
						class="confluence-embedded-image"
						src="http://tdn.totvs.com/download/attachments/73082260/proxygen-2.png?version=1&modificationDate=1377284793000&api=v2"
						data-image-src="http://tdn.totvs.com/download/attachments/73082260/proxygen-2.png?version=1&modificationDate=1377284793000&api=v2"><br /></span>
				</p>
			</div>
			<div id="3" class="deck-card " style="" cssclass="" accesskey=""
				label="3&amp;ordm; Passo" title="" nextafter="0"
				effecttype="default" effectduration="-1.0">
				<p>
					D<span
						style="font-size: 10.0pt; line-height: 13.0pt; text-align: justify;">urante
						el </span><span
						style="font-size: 10.0pt; line-height: 13.0pt; text-align: justify;">proceso
						de generación de proxy, en la pestaña General, marque la opción
						Java en Client Proxy e ingresar el directorio en el que se
						generará el proxy en Output Dir. </span><span
						style="font-size: 10.0pt; line-height: 13.0pt; text-align: justify;">Observe
						también el campo AppService, éste debe ser el </span><span
						style="font-size: 10.0pt; line-height: 13.0pt; text-align: justify;">nombre
						del servicio publicado en AppServer, de lo contrario no se </span><span
						style="font-size: 10.0pt; line-height: 13.0pt; text-align: justify;">podrá
						conectar al servidor. </span>
				</p>
				<p>
					<span
						style="font-size: 10.0pt; line-height: 13.0pt; text-align: justify;"><img
						class="confluence-embedded-image"
						src="http://tdn.totvs.com/download/attachments/73082260/proxygen-3.png?version=1&modificationDate=1377284793000&api=v2"
						data-image-src="http://tdn.totvs.com/download/attachments/73082260/proxygen-3.png?version=1&modificationDate=1377284793000&api=v2"><br /></span>
				</p>
			</div>
			<div id="4" class="deck-card " style="" cssclass="" accesskey=""
				label="4&amp;ordm; Passo" title="" nextafter="0"
				effecttype="default" effectduration="-1.0">
				<p>
					<span style="font-size: 10.0pt; font-family: Arial, sans-serif;">La
						última información relevante para la generación de proxy es el
						nombre del paquete (package) donde se crearán las clases. Esta
						información se utiliza durante la configuración del servicio
						Progress® en Fluig. Para finalizar haga clic en el botón <strong>OK.</strong>
					</span>
				</p>
				<p>
					<span style="font-size: 10.0pt; font-family: Arial, sans-serif;">&#160;</span><img
						class="confluence-embedded-image"
						src="http://tdn.totvs.com/download/attachments/73082260/proxygen-4.png?version=1&modificationDate=1377284793000&api=v2"
						data-image-src="http://tdn.totvs.com/download/attachments/73082260/proxygen-4.png?version=1&modificationDate=1377284793000&api=v2">
				</p>
			</div>
			<div id="5" class="deck-card " style="" cssclass="" accesskey=""
				label="&amp;Uacute;ltimo Passo" title="" nextafter="0"
				effecttype="default" effectduration="-1.0">
				<p style="text-align: left;">
					<span
						style="font-size: 10.0pt; line-height: 13.0pt; text-align: justify;">Una
						vez </span><span
						style="font-size: 10.0pt; line-height: 13.0pt; text-align: justify;">creadas
						las clases, es necesario empaquetarlas en un archivo .JAR. Esto se
						puede </span><span
						style="font-size: 10.0pt; line-height: 13.0pt; text-align: justify;">realizar
						por línea de comando, utilizando el siguiente comando:</span>
				</p>
				<div class="preformatted panel" style="border-width: 1px;">
					<div class="preformattedContent panelContent">
						<pre>jar -cvf &lt;jar_file_name> &lt;directorio></pre>
					</div>
				</div>
				<p class="MsoNormal"
					style="margin-bottom: 6.0pt; text-align: justify;">
					Sólo tenga en cuenta que en el archivo generado, es necesario que
					las clases estén en los directorios correctos. En el ejemplo
					presentado, el directorio<strong> con</strong> debe incluirse y
					estar en la raíz del archivo JAR. <span
						style="font-size: 10.0pt; line-height: 13.0pt;">Por ser
						compatible con el formato ZIP, otra opción es generar un </span><span
						style="font-size: 10.0pt; line-height: 13.0pt;">archivo con
						las clases generadas (respetando los directorios) y renombrarlo
						con </span><span style="font-size: 10.0pt; line-height: 13.0pt;">la
						extensión .JAR.</span>
				</p>
			</div>
		</div>
	</div>
	<!-- // .deck -->
	<div class="aui-message hint shadowed information-macro">
		<span class="aui-icon icon-hint">Icon</span>
		<div class="message-content">
			<p>
				<span style="font-size: 10.0pt; font-family: Arial, sans-serif;">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</span>
			</p>
		</div>
	</div>
	<h3 id="IntegraçãoComAplicativosExternos-ConfiguraçãodoServiçonoFluig">Configuración
		del Servicio en Fluig</h3>
	<p>
		El registro de un servicio se realiza a través de Fluig&#160;Studio,
		en la view Visualización de Servicios, en la opción &#160;<strong>Incluir
			Servicio.&#160;</strong>La siguiente pantalla muestra el asistente del nuevo
		servicio y los campos utilizados para el registro del servicio
		Progress®:
	</p>
	<p>
		<img class="confluence-embedded-image image-center"
			src="http://tdn.totvs.com/download/attachments/73082260/servico-process-1.png?version=1&modificationDate=1377284793000&api=v2"
			data-image-src="http://tdn.totvs.com/download/attachments/73082260/servico-process-1.png?version=1&modificationDate=1377284793000&api=v2">
	</p>
	<p>Donde:</p>
	<ul>
		<li><strong><strong>Servidor</strong>:&#160;</strong>Servidor de
			Fluig donde se agregará el servicio;</li>
		<li><strong>Código:&#160;</strong>Código único que identificará
			el servicio en el sistema.&#160;Este código se utilizará en los
			códigos JavaScript para acceder a este servicio;</li>
		<li><strong>Descripción:&#160;</strong>Texto que describe el
			servicio de datos;</li>
		<li><strong style="font-size: 10.0pt; line-height: 13.0pt;">URL:&#160;</strong><span
			style="font-size: 10.0pt; line-height: 13.0pt;">Identifica la
				URL de acceso al servicio AppServer, como por ejemplo
				AppServer://&lt;servidor>/&lt;nome_serviço>;</span><br />
		<span style="font-size: 10.0pt; line-height: 13.0pt;">En caso
				de que no esté utilizando el NameServer estándar se debe informar el
				puerto de acceso a NameServer Ej.:
				AppServer://&lt;servidor>:&lt;porta_NameServer>/&lt;nome_serviço>.&#160;</span><br />
		<span style="font-size: 10.0pt; line-height: 13.0pt;">Tenga en
				cuenta que dependiendo de la configuración del servicio y/o de la
				forma de conexión, la URL puede sufrir cambios. Verifique la
				documentación de Open AppServer para más información.</span></li>
		<li><strong style="font-size: 10.0pt; line-height: 13.0pt;">Tipo:&#160;</strong><span
			style="font-size: 10.0pt; line-height: 13.0pt;">Identifica el
				tipo de servicio (Progress o WebService). Se debe seleccionar
				Progress;</span></li>
		<li><strong style="font-size: 10.0pt; line-height: 13.0pt;">Objeto
				Remoto:&#160;</strong><span style="font-size: 10.0pt; line-height: 13.0pt;">Identifica
				la clase de acceso de proxy. Esta clase generalmente está compuesta
				por el nombre del paquete utilizado para generar las clases Proxy,
				más el nombre del proyecto en ProxyGen.&#160;</span><br />
		<span style="font-size: 10.0pt; line-height: 13.0pt;">Ejemplo:
				En las pantallas que presentan ProxyGen, se utilizó el paquete </span><strong
			style="font-size: 10.0pt; line-height: 13.0pt;">com.fluig.samples.ems</strong><span
			style="font-size: 10.0pt; line-height: 13.0pt;">, y el nombre
				que se dio al proyecto en ProxyGen fue </span><strong
			style="font-size: 10.0pt; line-height: 13.0pt;">EMSProxies</strong><span
			style="font-size: 10.0pt; line-height: 13.0pt;">. En este
				caso, la clase del objeto remoto será </span><strong
			style="font-size: 10.0pt; line-height: 13.0pt;">com.fluig.samples.ems.EMSProxies</strong><span
			style="font-size: 10.0pt; line-height: 13.0pt;">;</span></li>
		<li><strong style="font-size: 10.0pt; line-height: 13.0pt;">Usuario:&#160;</strong><span
			style="font-size: 10.0pt; line-height: 13.0pt;">Usuario
				utilizado para conectarse al servicio, como se define en la
				configuración de AppServer;</span></li>
		<li><strong style="font-size: 10.0pt; line-height: 13.0pt;">Contraseña:&#160;</strong><span
			style="font-size: 10.0pt; line-height: 13.0pt;">Contraseña
				utilizada para conectarse al servicio, como se define en la
				configuración de AppServer;</span></li>
		<li><strong style="font-size: 10.0pt; line-height: 13.0pt;">Parámetros
				Extras:&#160;</strong><span style="font-size: 10.0pt; line-height: 13.0pt;">Parámetros
				extras (y opcionales) utilizados para conectarse a AppServer.
				Verifique la documentación de Open AppServer para verificar las
				opciones disponibles en cada versión de Progress®;</span></li>
		<li><strong style="font-size: 10.0pt; line-height: 13.0pt;">Directorio
				del archivo de Proxy:&#160;</strong><span
			style="font-size: 10.0pt; line-height: 13.0pt;">Archivo .JAR
				que contiene las clases generadas por ProxyGen. Se debe utilizar el
				botón Seleccionar Archivo para localizarlo.</span><br />
		<span style="font-size: 10.0pt; line-height: 13.0pt;"><br /></span></li>
	</ul>
	<p>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:</p>
	<p>
		<strong><img class="confluence-embedded-image image-center"
			src="http://tdn.totvs.com/download/attachments/73082260/servico-process-2.png?version=1&modificationDate=1377284793000&api=v2"
			data-image-src="http://tdn.totvs.com/download/attachments/73082260/servico-process-2.png?version=1&modificationDate=1377284793000&api=v2"><br /></strong>
	</p>
	<h3
		id="IntegraçãoComAplicativosExternos-VisãoGeraldosObjetosEnvolvidos">Visión
		general de los objetos involucrados</h3>
	<p>El acceso a los procedures expuestos en AppServer implica cuatro
		elementos que interactúan entre sí de acuerdo al siguiente diagrama:</p>
	<p>&#160;</p>
	<p>
		<img class="confluence-embedded-image image-center"
			src="attachments/73082260/73406794.png"
			data-image-src="attachments/73082260/73406794.png">
	</p>
	<p>&#160;</p>
	<p>Donde:</p>
	<ul>
		<li><strong>Script Code</strong>: 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.</li>
		<li><strong>Service Provider:</strong> 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.</li>
		<li><strong>Service Helper:</strong> 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
			<a href="73082260.html">aquí</a>.</li>
		<li><strong>ProxyGen Clases:</strong> 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&#160;Studio.</li>
	</ul>
	<div>&#160;</div>
	<h5
		id="IntegraçãoComAplicativosExternos-ProceduresPersistenteseNão-Persistentes">Procedures
		Persistentes y No Persistentes</h5>
	<p>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.</p>
	<p>Los procedures expuestos de forma no persistente dan origen a
		métodos en la clase configurada como Objeto Remoto (o Proxy) en el
		Servicio, y su ejecución se lleva a cabo llamando al método
		correspondiente, por ejemplo:</p>
	<div class="preformatted panel" style="border-width: 1px;">
		<div class="preformattedContent panelContent">
			<pre>serviceHelper.getProxy().verifyUsers(inputTT, holder).</pre>
		</div>
	</div>
	<p>
		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&#160;Studio se pueden verificar los métodos disponibles en la
		clase), o por el método <strong>createManagedObject</strong>. La
		llamada a través del método <strong>createManagedObject</strong>
		permite que &#160;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 <strong>_release()</strong>), bajo
		pena de bloquear un nuevo agente de AppServer en cada invocación del
		método.
	</p>
	<p>&#160;</p>
	<h5 id="IntegraçãoComAplicativosExternos-ParâmetrosdeEntradaeSaída">Parámetros
		de Entrada y Salida</h5>
	<p>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.</p>
	<p>Para los tipos más simples, como strings, datas o valores
		enteros, ProxyGen utiliza un mapeo directo para los tipos o clases
		estándares del lenguaje Java™. Para tipos complejos, como temp-tables
		y buffers, ProxyGen utiliza clases que forman parte de la biblioteca
		de runtime de estos servicios.</p>
	<p>
		Cuando los parámetros son de entrada y salida (INPUT-OUTPUT) o de
		salida (OUTPUT), los tipos primitivos deben sustituirse por clases <em>Holders</em>,
		que contendrán el valor devuelto después de la ejecución del método.
		Los ejemplos más comunes son StringHolder o ResultSetHolder.
	</p>
	<p>Los tipos de datos utilizados por cada método se pueden
		consultar a través de la Visualización de Servicios en
		Fluig&#160;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®.</p>
	<h3 id="IntegraçãoComAplicativosExternos-CriaçãodosDatasets">Creación
		de los Datasets</h3>
	<p>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.</p>
	<p>La forma de invocar las rutinas expuestas por el servicio es
		siempre la misma, independientemente de qué punto se está llamando.
		Sin embargo, para facilitar la comprensión del uso de servicios
		Progress®&#160;en Fluig y facilitar la reproducción de los ejemplos
		presentados en el entorno del lector, todos los siguientes ejemplos
		utilizarán Datasets como meta.</p>
	<p>
		Como ya se ha visto anteriormente, los Datasets que se presentarán
		aquí son <strong>Tipos de Centro de Costo</strong>, <strong>Naturaleza
			de los Centros de Costo</strong>, <strong>Centros de Costo</strong> y <strong>Usuarios
			en Común</strong>.
	</p>
	<p>&#160;</p>
	<h5 id="IntegraçãoComAplicativosExternos-TiposdeCentrodeCusto">Tipos
		de Centro de Costo</h5>
	<p>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:</p>
	<div class="code panel pdl" style="border-width: 1px;">
		<div class="codeHeader panelHeader pdl"
			style="border-bottom-width: 1px;">
			<b>dsTipoCentroCosto.js</b>
		</div>
		<div class="codeContent panelContent pdl">
			<pre
				class="first-line: 1; theme: Eclipse; brush: javascript; gutter: true"
				style="font-size: 12px;">function createDataset(fields, constraints, sortFields) {
	
	//Paso 1 - Crea el dataset
	var dataset = DatasetBuilder.newDataset();
    dataset.addColumn("id");
    dataset.addColumn("descripcion");
   &#160;
	//Paso 2 - Invoca el servicio registrado en Fluig
	var servico = ServiceManager.getService("EMS2");
&#160;
	//Paso 3 - Carga el objeto utilidad para integración con Progress
    var serviceHelper = servico.getBean();
&#160;
	//Paso 4 - Carga el procedure persistente CostCenterUtils.p
    var remoteObj = serviceHelper.createManagedObject("CostCenterUtils");
	//Paso 5 - Invoca el procedure que devuelve una string con los tipos de CC
    var types = serviceHelper.createStringHolder();
    remoteObj.readCostTypes(types);
	//Paso 6 - Rompe la string en un array con cada uno de los tipos
    var typeArray = types.getStringValue().split(",");
&#160;
	//Paso 7 - Agrega cada tipo devuelto
    for(var pos = 0; pos &lt; typeArray.length; pos++) {
        dataset.addRow(new Array(pos + 1, typeArray[pos]));
    }
    return dataset;
}</pre>
		</div>
	</div>
	<p>Donde:</p>
	<ul>
		<li><strong>Paso 1:&#160;</strong>Crea el dataset y agrega los
			campos del mismo;</li>
		<li><strong>Paso 2:</strong>&#160;La invocación del servicio
			registrada en Fluig se realiza por el método <strong>ServiceManager.getService</strong>,
			y el valor pasado como parámetro debe ser el código del servicio.
			Tenga en cuenta que en este punto no es necesario informar ningún
			parámetro de conexión al servicio, puesto que esto ya se realizó en
			su registro;</li>
		<li><strong>Paso 3:</strong> Utiliza el método <strong>getBean</strong>&#160;para
			devolver un objeto utilidad para servicios Progress®. Esta utilidad
			proporciona una serie de métodos que facilitan la interacción con el
			proxy generado y sus métodos se presentarán con más detalle, más
			adelante en este documento;</li>
		<li><strong>Paso 4:</strong> Realiza la carga del objeto <strong>CostCenterUtils</strong>
			de manera gestionada, a través del método <strong>createManagedObject</strong>
			de la utilidad creada anteriormente;</li>
		<li><strong>Paso 5:</strong> Invoca el método deseado, en este
			caso <strong>readCostTypes</strong>, pasando un StringHolder que
			recibirá el valor de salida;</li>
		<li><strong>Paso 6:</strong> Transforma la string recibida como
			parámetro en un array con las opciones. El carácter , (como) se
			utiliza para determinar los puntos de ruptura de string;</li>
		<li><strong>Paso 7:</strong> Recorre el array creado, agregando
			una línea en el Dataset para cada ítem del array.&#160;</li>
	</ul>
	<p>La siguiente pantalla presenta la visualización de los datos del
		Dataset creado:</p>
	<p>
		<img class="confluence-embedded-image"
			src="http://tdn.totvs.com/download/attachments/73082260/diagrama%20objetos%20envolvidos.png?version=1&modificationDate=1377284793000&api=v2"
			data-image-src="http://tdn.totvs.com/download/attachments/73082260/diagrama%20objetos%20envolvidos.png?version=1&modificationDate=1377284793000&api=v2">
	</p>
	<p>&#160;</p>
	<h5 id="IntegraçãoComAplicativosExternos-NaturezadosCentrosdeCusto">Naturaleza
		de los Centros de Costo</h5>
	<p>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:</p>
	<div class="code panel pdl" style="border-width: 1px;">
		<div class="codeHeader panelHeader pdl"
			style="border-bottom-width: 1px;">
			<b>dsNaturalezaCentroCosto.js</b>
		</div>
		<div class="codeContent panelContent pdl">
			<pre
				class="first-line: 1; theme: Eclipse; brush: javascript; gutter: true"
				style="font-size: 12px;">function createDataset(fields, constraints, sortFields) {
	var dataset = DatasetBuilder.newDataset();
    dataset.addColumn("id");
    dataset.addColumn("descripcion");
	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 &lt; typeArray.length; pos++) {
        dataset.addRow(new Array(pos + 1, typeArray[pos]));
    }
    return dataset;
}</pre>
		</div>
	</div>
	<p>Después del registro del Dataset, se puede ver su contenido:</p>
	<p>
		<img class="confluence-embedded-image"
			src="http://tdn.totvs.com/download/attachments/73082260/ems-dt2.png?version=1&modificationDate=1377284793000&api=v2"
			data-image-src="http://tdn.totvs.com/download/attachments/73082260/ems-dt2.png?version=1&modificationDate=1377284793000&api=v2">
	</p>
	<p>&#160;</p>
	<h5 id="IntegraçãoComAplicativosExternos-CentrosdeCusto">Centros
		de Costo</h5>
	<p>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.</p>
	<p>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.</p>
	<h6 id="IntegraçãoComAplicativosExternos-CodificaçãoProgress®9">Codificación
		Progress® 9</h6>
	<p>Las temp-table en Progress® 9 son manejadas por los objetos que
		implementan la interfaz java.sql.ResultSet:</p>
	<div class="code panel pdl" style="border-width: 1px;">
		<div class="codeHeader panelHeader pdl"
			style="border-bottom-width: 1px;">
			<b>dsCentroCostoP9.js</b>
		</div>
		<div class="codeContent panelContent pdl">
			<pre
				class="first-line: 1; theme: Eclipse; brush: javascript; gutter: true"
				style="font-size: 12px;">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;
}</pre>
		</div>
	</div>
	<h6 id="IntegraçãoComAplicativosExternos-CodificaçãoOpenEdge®10">Codificación
		OpenEdge® 10</h6>
	<p>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:</p>
	<div class="code panel pdl" style="border-width: 1px;">
		<div class="codeHeader panelHeader pdl"
			style="border-bottom-width: 1px;">
			<b>dsCentroCostoOE10.js</b>
		</div>
		<div class="codeContent panelContent pdl">
			<pre
				class="first-line: 1; theme: Eclipse; brush: javascript; gutter: true"
				style="font-size: 12px;">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.createProDataGraphHolder();
    remoteObj.readCostCenters(holder);
    
	//Recorre los registros, cargando el Dataset con los datos
    var ttCC = holder.getProDataGraphValue().getProDataObjects("ttCC");
    for (var row_index = 0; row_index &lt; ttCC.size(); row_index++) {
        var row = ttCC.get(row_index);
        dataset.addRow(new Array(row.get("cuenta"),
                                 row.get("titulo"),
                                 row.get("naturaleza"),
                                 row.get("tipo")));
    }
    
    return dataset;
}</pre>
		</div>
	</div>
	<p>Visualización del Dataset:</p>
	<p>
		<img class="confluence-embedded-image"
			src="http://tdn.totvs.com/download/attachments/73082260/ems-dt3.png?version=1&modificationDate=1377284793000&api=v2"
			data-image-src="http://tdn.totvs.com/download/attachments/73082260/ems-dt3.png?version=1&modificationDate=1377284793000&api=v2">
	</p>
	<p>&#160;</p>
	<h5 id="IntegraçãoComAplicativosExternos-UsuáriosemComum">Usuarios
		en Común</h5>
	<p>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.</p>
	<p>La segunda diferencia es que el código 4GL se implementa en un
		programa no persistente, lo que cambia la forma como la lógica se
		invoca desde el código JavaScript.</p>
	<p>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).</p>
	<h6 id="IntegraçãoComAplicativosExternos-CodificaçãoProgress®9.1">Codificación
		Progress® 9</h6>
	<div class="code panel pdl" style="border-width: 1px;">
		<div class="codeHeader panelHeader pdl"
			style="border-bottom-width: 1px;">
			<b>dsUsuariosComunesP9.js</b>
		</div>
		<div class="codeContent panelContent pdl">
			<pre
				class="first-line: 1; theme: Eclipse; brush: javascript; gutter: true"
				style="font-size: 12px;">function createDataset(fields, constraints, sortFields) {
    
    //Crea el nuevo Dataset
    

Índice

 

Índice
outlinetrue
stylenone
exclude.*ndice

 

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
  • Progress® 4GL

  • Progress® Open App Server
  • Progress® Open Client for Java
  • Datasets (Fluig)
  • 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 Fluig. 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 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 possuem disponíveis as mesmas características de integração existentes nos Datasets, em especial as customizaçõ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 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 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 é planejada para permitir integrar-se a estes sistemas, permitindo que os processos modelados tenham maior valor agregado.

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

 

Image Removed

 

O principal canal de integração do produto é 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 e dar acesso pelo produto à aplicativos externos. Este documento dedica uma seção específica sobre integração via WebServices.

A outra forma de integração é via chamadas ao Progress® Open AppServer e é indicada para usuários que precisem integrar o  Fluig com aplicativos desenvolvidos nesta plataforma.

 

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 disponibiliza um conjunto de WebServices que permitem o acesso às informações do produto ou a execução de tarefas, como iniciar solicitações de processos por exemplo. Para ter a lista dos WebServices disponíveis, acesse o endereço: 

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

Cada link apresentado direciona o navegador para a URL do WSDL do serviço. O WSDL (Web Service Description Language) possui a descrição do serviço no formato XML e é utilizado pelas ferramentas de desenvolvimento para a criação dos componentes que representarão este serviço.

Nota

Atente para cada tipo do 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 services. 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 Fluig:

Deck of Cards
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.

Image Removed

Card
effectDuration0.5
id2
label2º Passo
effectTypefade

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

Image Removed

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.

Image Removed

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™).

Image Removed

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:

Image Removed

Informações

Para o exemplo apresentado abaixo, foi utilizado a IDE Adobe® Flex™ Builder™ 3.0 com Flex® SDK 3.2. Para outras versões da IDE e/ou SDK, o processo para criação dos stubs pode sofrer algumas variações. 

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

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

 

Via Java™

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

Da mesma forma como no exemplo anterior, em Apache Flex®, o primeiro passo consiste em utilizar o endereço WSDL para a geração dos stubs em Java™. O comando abaixo apresenta um exemplo de como gerar estes stubs:

Sem Formato
wsimport -d <output_directory> <wsdl_url>

Através deste comando são gerados os stubs no diretório de destino (output_directory), conforme a descrição do arquivo wsdl (wsdl_url).

Image Removed

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

Bloco de código
themeEclipse
languagejava
titleECMDatasetServiceClient.java
firstline1
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
themeEclipse
languagejava
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.

Para gerar a documentação de um serviço, deve-se utilizar o utilitário bprowsdldoc como no exemplo abaixo:

Sem Formato
bprowsdldoc <URL_TO_WSDL>

Com a execução deste utilitário, serão gerados alguns arquivos HTML com as informações sobre como consumir o serviço. Esta documentação apresenta informações e exemplos de como realizar a conexão com o serviçoe e a utilizar as métodos e datatypes do serviço. 

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

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

Para adicionar um novo WebService, é preciso clicar na opção Incluir Serviço, abrindo o assistente Novo Serviço, e informar o servidor do Fluig onde será adicionado o serviço, um código identificador para ele, a sua descrição, a URL para o WSDL e o seu tipo (neste caso WebService). No exemplo abaixo, será utilizado um WebService público para consulta à tabela periódica, cujo endereço do WSDL é http://www.webservicex.com/periodictable.asmx?wsdl.

Image Removed

Com base nestas informações, o Fluig irá extrair as informações sobre o WebService informado e finalizará o cadastro deste serviço. 

Uma vez que o serviço esteja cadastrado, é possível visualizar as classes e métodos disponíveis neste serviço e que serão utilizados nos códigos JavaScript que farão uso do mesmo. A tela abaixo apresenta um exemplo de visualização de WebService.

Image Removed

Os serviços adicionados no Fluig podem ser instanciados e utilizados nos pontos onde o produto permite customização utilizando-se JavaScript, como nos scripts para eventos globais, eventos de processos, eventos de definição de formulário ou Datasets. No exemplo a seguir, será criado um Dataset que fará uso deste serviço para trazer os dados da tabela periódica.

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
themeEclipse
languagejavascript
titleperiodicTable.js
firstline1
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 NewDataSet.Table) {
			dataset.addRow(new Array(element.ElementName.toString()));
		}
	} catch(erro) {
		dataset.addRow(new Array(erro));
	}

	return dataset;
}

O primeiro passo para invocar o serviço é solicitar ao Fluig que carregue o serviço, a partir do método ServiceManager.getService('PeriodicTable'). O valor passado como parâmetro, deve ser o código utilizado quando cadastrado o serviço.

Uma vez que o serviço tenha sido carregado, é utilizado o método getBean() para retornar um utilitário para acesso às classes do serviço, através do método instantiate. Através deste utilitário, é possível instanciar as classes disponíveis e que estão listadas no cadastro do Serviço (conforme imagem vista anteriormente).

Uma vez que se tenha instanciado o objeto utilitário do serviço, as classes que devem ser instanciadas e os métodos que devem ser invocados dependem de cada WebService utilizado, e deve-se recorrer à sua documentação para mais informações.

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

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

Onde:

...

Passo 1: Instanciar a classe net.webservicex.Periodictable para ter acesso ao localizador do serviço; 

...

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:

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

Para percorrer o XML e extrair o dados disponíveis, são utilizadas as funcionalidades de tratamento de XML do JavaScript que facilita a manipulação de dados deste tipo. Para mais informações sobre esta funcionalidade, acesse: http://www.ecma-international.org/publications/standards/Ecma-357.htm ou http://www.xml.com/pub/a/2007/11/28/introducing-e4x.html.

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

Bloco de código
themeEclipse
languagejavascript
firstline1
linenumberstrue
var NewDataSet = new XML(result);
for each(element in NewDataSet.Table) {
	dataset.addRow(new Array(element.ElementName.toString()));
}

Uma vez implementado o código do Dataset, é possível visualizá-lo, conforme a figura abaixo:

Image Removed

 

WebServices com Autenticação Básica

Para consumir WebServices que fazem uso de autenticação básica (WSS ou WS-Security), é 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.

 

Os parâmetros que devem ser informados no método seguem a ordem abaixo:

  1. Instância do serviço
  2. Nome da classe do serviço
  3. Usuário para a autenticação
  4. Senha para a autenticação

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

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

...

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".

Para customizar 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
themeEclipse
languagejs
		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";
		
		var serviceLocator = serviceHelper.instantiate('net.webservicex.Periodictable');
		var service = serviceLocator.getPeriodictableSoap();
		var customClient = serviceHelper.getCustomClient(service, "net.webservicex.PeriodictableSoap", properties);
		var result = customClient.getAtoms();

 

Os parâmetros que podem ser definidos são os seguintes:

PropriedadeFunção
basic.authorization

Quando definido como "true", faz o mesmo que o método getBasicAuthenticatedClient, porém permite aplicar as configurações de autenticação juntamente com as demais customizações abaixo. Para configurar a autenticação, as propriedades com "username" e "password" abaixo também precisam ser definidas.

basic.authorization.username
Usuário a ser utilizado para autenticação básica.
basic.authorization.password
Senha do usuário utilizado para autenticação básica.
disable.chunking

Quando definido como "true", desabilita o envio de requisições grandes em "pedaços" menores. Pode ser útil quando o serviço chamado não suporta este tipo de requisição.

log.soap.messages
Quando definido como "true", permite que as mensagens SOAP utilizadas nas requisições feitas aos serviços sejam apresentadas no log do servidor, facilitando a depuração em caso de falhas.

 

Progress® Open AppServer

Assim como é possível invocar operações em WebServices, o Fluig também permite fazer chamadas a programas em Progress® 4GL (ou ABL) expostos via Progress® Open AppServer.

Nos exemplos a seguir, serão criados Datasets que, via camada de serviço, farão o acesso à lógicas em 4GL que farão a extração dos dados. Embora os códigos 4GL, neste exemplo, sejam muito simples, eles compreendem os casos mais comuns exigidos no dia-a-dia, uma vez que a complexidade da integração se encontra nas interfaces (parâmetros de entrada e saída) de cada procedure exposta, e não na sua lógica interna.

Observe que os exemplos aqui apresentados têm por objetivo demonstrar a dinâmica de integração entre Progress® e o Fluig sem entrar em detalhes específicos das tecnologias envolvidas. A camada de serviço Progress® do Fluig cria uma interface em JavaScript para a biblioteca Java Open AppServer Client, da Progress® e, por isso, para mais informações sobre como integrar aplicativos Java™ e Progress® consulte a documentação fornecida pela Progress®.

Caso de Uso

Os exemplos exibidos a seguir, têm por objetivo a criação de quatro Datasets 1 no Fluig:

  1. Tipos de Centro de Custo, que deve retornar os tipos de centro de custo existentes no aplicativo em Progress® (neste caso, o EMS2).
  2. Natureza dos Centros de Custo, que deve retornar os tipos possíveis de natureza, conforme o aplicativo em Progress® (neste caso, o EMS2).
  3. Centros de Custo, que deve retornar os registros na tabela conta 2.
  4. Usuários Comuns, que deve gerar uma lista de usuários comuns entre o Fluig e o aplicativo em Progress® (utilizando a tabela usuar_mestre).

    Nota

    1 - Os exemplos utilizam uma base de dados do EMS2 para consulta de centros de custo e usuários. Entretanto, apenas duas tabelas e 6 campos são utilizados no total, o que não deve prejudicar o entendimento da lógica pelo leitor, nem impedir a criação de um esquema equivalente para testes, caso necessário.

    2 - O código apresentado para extração dos centros de custo tem fins meramente didáticos e não pode ser considerado para uso em produção. Para ter mais informações sobre como extrair centros de custos do EMS2, consulte a documentação técnica do mesmo.

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
themeEclipse
languagejavafx
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
themeEclipse
languagejavafx
titleverifyUsers.p
firstline1
linenumberstrue
/**************************************************************************
** 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.

Os dois códigos apresentados têm diferenças significativas na forma como são utilizados e na forma como serão expostos pelo Progress®. No primeiro, o programa é carregado de forma persistente e suas procedures podem ser executadas de forma independente. No segundo caso, o programa é executado de forma não-persistente e a lógica principal se encontra no main-block. As procedures internas, caso existam, têm por objetivo melhorar a organização do código e não podem ser utilizadas de forma isolada.

Configuração do AppServer

Algumas informações importantes na configuração do AppServer:

  1. O AppServer deve ser carregado no modo Stateless;
  2. Na configuração do agente, no campo Propath, deve ser adicionado o diretório onde estão localizados os arquivos compilados (.r).

    Nota

    Importante: Quando utilizado um caminho relativo (\\servidor\pasta), o serviço Windows® do Progress® (AdminService) deve ser iniciado com um usuário de rede que possua permissão de acesso ao diretório informado.

Expondo códigos 4GL com ProxyGen

O primeiro passo para que seja possível executar rotinas em Progress® 4GL é criar a biblioteca cliente, o que é feito com o uso do aplicativo ProxyGen, que acompanha a instalação do Progress®, conforme o exemplo abaixo.

Utilize o passo-a-passo para visualizar o processo de criação do proxy:

 

...

startHiddenfalse
effectDuration0.5
idproxyGen
historyfalse
effectTypefade

...

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).

Image Removed

...

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.

Image Removed

...

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.

Image Removed

...

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.

 Image Removed

 

...

id5
labelÚltimo Passo

...

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.

Informações

Dependendo da versão do Progress®, as telas podem sofrer alguma variação na quantidade e disposição dos campos. Consulte a documentação em caso de dúvida

 

 

Configuração do Serviço no Fluig

O cadastro de um serviço é realizado através do Fluig Studio, na view Visualização de Serviços, pela opção Incluir Serviço. A tela abaixo apresenta o assistente de novo serviço e os campos utilizados para o cadastro do serviço Progress®:

Image Removed

 

Onde:

...

Uma vez que o serviço tenha sido adicionado, é possível visualizar as classes disponíveis e os métodos existentes em cada uma delas. Estas informações são importantes para guiar o desenvolvimento dos códigos de customização que farão uso deste serviço. Para visualizar as classes e métodos do serviço, utilize a opção Consulta Serviço na Visualização de Serviços, conforme a tela abaixo:

Image Removed

Visão Geral dos Objetos Envolvidos

O acesso às procedures expostas no AppServer envolve quatro elementos que interagem entre si, conforme o diagrama abaixo:

 

Image Removed

 

Onde:

  • Script Code: é o código em JavaScript que fará uso das procedures expostas no AppServer. Como mencionado anteriormente, este JavaScript pode ser de qualquer natureza, como a implementação de um Dataset ou a customização de um evento de processo.
  • Service Provider: Objeto recuperado através do método ServiceManager.getService e que fornece o acesso às funcionalidades do serviço. Este objeto é responsável por gerenciar a conexão e recursos alocados pelo serviço durante a execução do script.
  • Service Helper: Objeto recuperado via método getBean no ServiceProvider e que disponibiliza um conjunto de métodos utilitários que permitem, entre outras coisas, criar objetos específicos do Progress® (StringHolder, ResultSetHolder, etc.), ter acesso ao objeto remoto do ProxyGen e instanciar classes. Para mais informações sobre o Service Helper consultar aqui.
  • ProxyGen Classes: Classes geradas pelo ProxyGen e que serão utilizadas pelo desenvolvedor para execução das rotinas em Progress®. A lista das classes disponíveis, bem como os seus métodos, podem ser visualizados na Visualização de Serviços do Fluig Studio.
 
Procedures Persistentes e Não-Persistentes

Quando uma procedure é adicionada ao projeto do ProxyGen, ela deve ser configurada em duas listas: Procedures Persistentes ou Não-Persistentes. Esta decisão implica diretamente na forma como estes objetos são acessados pela biblioteca gerada e, consequentemente, na forma como o desenvolvedor irá acessá-las nos códigos JavaScript.

As procedures expostas de forma não-persistente dão origem à métodos na classe configurada como Objeto Remoto (ou Proxy) no Serviço, e a sua execução é feita chamando o método correspondente, por exemplo:

Sem Formato
serviceHelper.getProxy().verifyUsers(inputTT, holder).

As procedures expostas de forma persistente dão origem à novas classes que podem ser instanciadas via chamadas a métodos no Objeto Remoto (através da Visualização de Serviços no Fluig Studio é possível verificar os métodos disponíveis na classe), ou via o método createManagedObject. A chamada via o método createManagedObject permite que o Fluig tenha controle sobre o ciclo de vida deste objeto, liberando-o automaticamente ao fim do método. Caso o objeto seja instanciado manualmente, o desenvolvedor deve codificar a liberação do objeto (método _release()), sob pena de bloquear um novo agente do AppServer a cada invocação do método.

 

Parâmetros de Entrada e Saída

Outro ponto importante na invocação das rotinas em 4GL é observar quais os tipos de parâmetros de entrada e saída de cada procedure ou programa. Dependendo do tipo de dado (CHARACTER, INTEGER, TEMP-TABLE, etc.), do tipo de parâmetro (INPUT, INPUT-OUTPUT, BUFFER, etc.) e da versão utilizada do Progress®, a forma de se manipular estes parâmetros pode variar.

Para os tipos mais simples, como strings, datas ou valores inteiros, o ProxyGen utiliza um mapeamento direto para os tipos ou classes padrões da linguagem Java™. Para tipos complexos, como temp-tables e buffers, o ProxyGen utiliza classes que fazem parte da biblioteca de runtime destes serviços.

Quando os parâmetros são de entrada e saída (INPUT-OUTPUT) ou de saída (OUTPUT), os tipos primitivos precisam ser substituídos por classes Holders, que conterão o valor retornado após a execução do método. Os exemplos mais comuns são StringHolder ou ResultSetHolder.

Os tipos de dados utilizados em cada método podem ser consultado através da Visualização de Serviços no Fluig Studio. Observe que dependendo da versão do Progress® pode haver variação nos tipos de parâmetros utilizados e na forma de utilizá-los. Em caso de dúvida, consulte a documentação fornecida pela Progress®.

Criação dos Datasets

Uma vez que o serviço Progress® tenha sido adicionado no Fluig, é possível utilizá-lo nos pontos onde o produto permite customização utilizando-se JavaScript, como nos scripts para eventos globais, eventos de processos, eventos de definição de formulário ou Datasets.

A forma de se invocar as rotinas expostas pelo serviço é sempre a mesma, independente de qual ponto está sendo chamado. Entretanto, para facilitar o entendimento do uso dos serviços Progress® no Fluig e facilitar a reprodução dos exemplos apresentados no ambiente do leitor, todos os exemplos abaixo utilizarão Datasets como alvo.

Conforme visto anteriormente, os Datasets que serão apresentados aqui são Tipos de Centro de Custo, Natureza dos Centros de Custo, Centros de Custo e Usuários em Comum.

 

Tipos de Centro de Custo

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
themeEclipse
languagejavascript
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;
}

 

Onde:

  • Passo 1: Cria o dataset e adiciona os campos do mesmo;
  • Passo 2: É feita a invocação do serviço cadastrado no Fluig, através do método ServiceManager.getService, e o valor passado como parâmetro deve ser o código do serviço. Note que neste ponto não é preciso informar qualquer parâmetro de conexão ao serviço, uma vez que isto já foi feito no seu cadastro;
  • Passo 3: Utiliza o método getBean para retornar um objeto utilitário para serviços Progress®. Este utilitário disponibiliza uma série de métodos que facilitam a interação com o proxy gerado e seus métodos serão apresentados em mais detalhes adiante neste documento;
  • Passo 4: Faz a carga do objeto CostCenterUtils de forma gerenciada, através do método createManagedObject do utilitário criado anteriormente;
  • Passo 5: Invoca o método desejado, neste caso o readCostTypes, passando um StringHolder que irá receber o valor de saída;
  • Passo 6: Transforma a String recebida por parâmetro em um array com as opções. O caractere , (vírgula) é utilizado para determinar os pontos de quebra da string;
  • Passo 7: Percorre o array criado, adicionando uma linha no Dataset para cada item do array. 

A tela abaixo apresenta a visualizaçào dos dados do Dataset criado:

Image Removed

 

Natureza dos Centros de Custo

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
themeEclipse
languagejavascript
titledsNaturezaCentroCusto.js
firstline1
linenumberstrue
function createDataset(fields, constraints, sortFields) {

	var dataset = DatasetBuilder.newDataset();
    dataset.addColumn("idusuario");
    dataset.addColumn("nombre");
    
	//Recupera los usuarios de Fluig
    var campos = new Array("descricao");

	"colleaguePK.colleagueId", "colleagueName");
    var colleaguesDataset = DatasetFactory.getDataset("colleague", campos, null, null);
    
    //Instancia el servicio
    var servico = ServiceManager.getService("EMS2");
	    var serviceHelper = servico.getBean();
	var remoteObj    
    //Transforma el dataset en un ResultSet (v9) y crea holder de salida
    var inputTT = serviceHelpercolleaguesDataset.createManagedObjecttoResultSet("CostCenterUtils");

	    var typesholder = serviceHelper.createStringHoldercreateResultSetHolder();
	remoteObj.readCostNatureTypes(types);

    var typeArray = types.getStringValue().split(",");
    
    //Invoca el procedure en el Progress
    serviceHelper.getProxy().verifyUsers(inputTT, holder);
    
    for(var posrs = 0; pos < typeArray.length; pos++holder.getResultSetValue();
    while (rs.next()) {
        dataset.addRow(new Array(pos + 1, typeArray[pos](rs.getObject("cod_usuar"), rs.getObject("nom_usuario")));
    }
    
    return dataset;
}

 

Após o cadastro do Dataset, é possível visualizar o seu conteúdo:

Image Removed

 

Centros de Custo

O Dataset de Centros de Custo possui uma estrutura muito semelhante aos dois Datasets vistos anteriormente. A diferença principal é que, neste caso, a procedure retorna uma temp-table com os centros de custo, o que altera a forma como os dados são manipulados.

Dependendo da versão do Progress®, os objetos utilizados podem variar. A seguir, são apresentados exemplos da codificação para Progress® 9 e OpenEdge® 10, respectivamente. Em ambos os casos, o resultado apresentado pelo Dataset será o mesmo.

Codificação Progress® 9

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

Bloco de código
themeEclipse
languagejavascript
titledsCentroCustoP9.js
firstline1
linenumberstrue
function</pre>
		</div>
	</div>
	<h6 id="IntegraçãoComAplicativosExternos-CodificaçãoOpenEdge®10.1">Codificación
		OpenEdge® 10</h6>
	<div class="code panel pdl" style="border-width: 1px;">
		<div class="codeHeader panelHeader pdl"
			style="border-bottom-width: 1px;">
			<b>dsUsuariosComunesOE10.js</b>
		</div>
		<div class="codeContent panelContent pdl">
			<pre
				class="first-line: 1; theme: Eclipse; brush: javascript; gutter: true"
				style="font-size: 12px;">function createDataset(fields, constraints, sortFields) {
    
	//CriaCrea ael estrutura donuevo Dataset
    var dataset = DatasetBuilder.newDataset();
    dataset.addColumn("contausuario");
    dataset.addColumn("titulonombre");
    dataset.addColumn("natureza");
    dataset.addColumn("tipo");
    
	//Recupera olos serviçousuarios e carrega o objeto remotode Fluig
    var servicocampos = ServiceManager.getService("EMS2 new Array("colleaguePK.colleagueId", "colleagueName");
    var serviceHelpercolleaguesDataset = servicoDatasetFactory.getBean();
    var remoteObj = serviceHelper.createManagedObject("CostCenterUtils"getDataset("colleague", campos, null, null);
    
    //Instancia asel contas correntesservicio
    var holderservico = serviceHelperServiceManager.createResultSetHoldergetService("EMS2");
    var serviceHelper = remoteObjservico.readCostCentersgetBean(holder);;
	
    
//Transforma el dataset en //Percorreun os registros, carregando o Dataset com os dadosProDataGraph (v10) y crea holder de salida
    var rsinputTT = holderserviceHelper.getResultSetValuetoProDataGraph(colleaguesDataset);
    while (rs.next()) {var holder = serviceHelper.createProDataGraphHolder();
    
    //Invoca el procedure en el varProgress
 conta 	 = rs.getObject("conta"serviceHelper.getProxy().verifyUsers(inputTT, holder);
    
    var naturezattCC = rs.getObjectholder.getProDataGraphValue().getProDataObjects("naturezattOutUsers");
    for (var row_index = var tipo 	 = rs.getObject("tipo");0; row_index &lt; ttCC.size(); row_index++) {
        var titulo  row = rsttCC.getObject("titulo"get(row_index);
	
        dataset.addRow(new Array(conta, titulo, natureza, tipo(row.get("cod_usuar"), row.get("nom_usuario")));
    }
    
    return dataset;
}
Codificação OpenEdge® 10

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
themeEclipse
languagejavascript
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;
}

 

Visualização do Dataset:

Image Removed

 

Usuários em Comum

A primeira diferença entre o Dataset de usuários comuns e os exemplos anteriores, é que neste caso é preciso passar uma temp-table como parâmetro para a procedure invocada.

A segunda diferença é que o código 4GL está implementado em um programa não-persistente, o que altera a forma como a lógica é invocada a partir do código JavaScript.

A terceira diferença que pode se observar neste caso é que é possível transformar um Dataset nos tipos de dados requeridos pelo Progress® (ResultSet ou ProDataGraph).

 

Codificação Progress® 9

 

Bloco de código
themeEclipse
languagejavascript
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
themeEclipse
languagejavascript
titledsUsuariosComunsOE10.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 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;
}

 

Visualização do Dataset:

Image Removed

...

 

Service Helper

A tabela abaixo apresenta a lista de métodos existentes na classe utilitária para serviços Progress®:

...

Cria um objeto Holder para o tipo DECIMAL

...

Cria um objeto Holder para o tipo LOGICAL

...

Cria um objeto Holder para o tipo RAW

...

Cria um objeto Holder para o tipo COM-HANDLE

...

Cria um objeto Holder para o tipo DATE

...

Cria um objeto Holder para o tipo WIDGET-HANDLE (Handle)

...

Cria um objeto Holder para o tipo INTEGER

...

Cria um objeto Holder para o tipo RECID

...

Lê um arquivo .p ou .r que tenha sido exposto via AppServer de forma persistente. Através deste método o provedor do serviço pode gerenciar o ciclo de vida destes objetos, liberando-os ao final da execução do script.

...

Cria um objeto Holder para o tipo MEMPTR

...

Cria um objeto da classe ProDataGraph

...

Cria um objeto Holder para o tipo ProDataGraphHolder

...

Cria um objeto da classe ProDataGraphMetadata

...

Cria um objeto da classe ProDataObjectMetadata.
Cria um objeto para um dataset (Temp-table).

...

Cria um objeto Holder para o tipo TABLE

...

Cria um objeto Holder para o tipo ROWID

...

Cria um objeto Holder para o tipo CHARACTER.

...

Retorna a instância do objeto de conexão ao AppServer, já conectado e disponível para uso. O objeto remoto é a principal classe gerada pelo ProxyGen.

...

Instancia um objeto de uma classe dentro da biblioteca do proxy.

...

</pre>
		</div>
	</div>
	<p>Visualización del Dataset:</p>
	<p>
		<img class="confluence-embedded-image"
			src="http://tdn.totvs.com/download/attachments/73082260/ems-dt4.png?version=1&modificationDate=1377284793000&api=v2"
			data-image-src="http://tdn.totvs.com/download/attachments/73082260/ems-dt4.png?version=1&modificationDate=1377284793000&api=v2">
	</p>
	<p>
		<span class="confluence-anchor-link"
			id="IntegraçãoComAplicativosExternos-servicehelper"></span>
	</p>
	<h3 id="IntegraçãoComAplicativosExternos-ServiceHelper">Service
		Helper</h3>
	<p>La siguiente tabla presenta la lista de métodos existentes en la
		clase utilidad para servicios Progress®:</p>
	<div class="table-wrap">
		<table class="confluenceTable">
			<tbody>
				<tr>
					<th class="confluenceTh">Devolución</th>
					<th class="confluenceTh">Método y Descripción</th>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>createBigDecimalHolder</strong></span>()
						</code>
						<div class="block">Crea un objeto Holder para el tipo
							DECIMAL</div></td>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>createBooleanHolder</strong></span>()
						</code>
						<div class="block">Crea un objeto Holder para el tipo
							LOGICAL</div></td>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>createByteArrayHolder</strong></span>()
						</code>
						<div class="block">Crea un objeto Holder para el tipo RAW</div></td>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>createCOMHandleHolder</strong></span>()
						</code>
						<div class="block">Crea un objeto Holder para el tipo
							COM-HANDLE</div></td>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>createDateHolder</strong></span>()
						</code>
						<div class="block">Crea un objeto Holder para el tipo DATE</div></td>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>createHandleHolder</strong></span>()
						</code>
						<div class="block">Crea un objeto Holder para el tipo
							WIDGET-HANDLE (Handle)</div></td>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>createIntHolder</strong></span>()
						</code>
						<div class="block">Crea un objeto Holder para el tipo
							INTEGER</div></td>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>createLongHolder</strong></span>()
						</code>
						<div class="block">Crea un objeto Holder para el tipo RECID</div></td>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>createManagedObject</strong></span>(java.lang.String&#160;objName)
						</code>
						<div class="block">
							Lee un archivo .p o .r que haya sido expuesto a través de
							AppServer de forma persistente. <span
								style="color: rgb(53, 56, 51);">A través de este método
								el proveedor del servicio puede administrar el ciclo de vida de
								estos objetos, liberándolos al final de la ejecución del script.</span>
						</div></td>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>createMemptrHolder</strong></span>()
						</code>
						<div class="block">Crea un objeto Holder para el tipo MEMPTR</div></td>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>createProDataGraph</strong></span>(java.lang.Object&#160;metadata)
						</code>
						<div class="block">Crea un objeto de la clase ProDataGraph</div></td>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>createProDataGraphHolder</strong></span>()
						</code>
						<div class="block">Crea un objeto Holder para el tipo
							ProDataGraphHolder</div></td>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>createProDataGraphMetaData</strong></span>(java.lang.String&#160;name)
						</code>
						<div class="block">Crea un objeto de la clase
							ProDataGraphMetadata</div></td>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>createProDataObjectMetaData</strong></span>(java.lang.String&#160;tableName,
							int&#160;numFields, boolean&#160;bimageFlag, int&#160;numIndexes,
							java.lang.String&#160;multiIxCols,
							java.lang.String&#160;XMLNamespace,
							java.lang.String&#160;XMLPrefix)
						</code>
						<div class="block">Crea un objeto de la clase
							ProDataObjectMetadata.</div>
						<div class="block">Crea un objeto para un dataset
							(Temp-table).</div></td>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>createResultSetHolder</strong></span>()
						</code>
						<div class="block">Crea un objeto Holder para el tipo TABLE</div></td>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>createRowidHolder</strong></span>()
						</code>
						<div class="block">Crea un objeto Holder para el tipo ROWID</div></td>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>createStringHolder</strong></span>()
						</code>
						<div class="block">Crea un objeto Holder para el tipo
							CHARACTER.</div></td>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>getProxy</strong></span>()
						</code>
						<div class="block">
							Devuelve la instancia del objeto de conexión a AppServer, ya
							conectado y disponible para su uso. <span
								style="color: rgb(53, 56, 51);">El objeto remoto es la
								principal clase generada por ProxyGen.</span>
						</div></td>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>instantiate</strong></span>(java.lang.String&#160;className)
						</code>
						<div class="block">Instancia un objeto de una clase dentro
							de la biblioteca de proxy.</div></td>
				</tr>
				<tr>
					<td class="confluenceTd"><code>java.lang.Object</code></td>
					<td class="confluenceTd"><code>
							<span style="color: rgb(51, 102, 255);"><strong>toProDataGraph</strong></span>(com.datasul.technology.webdesk.dataset.DefaultDataset&#160;d)
						</code>
						<div class="block">Transforma un dataset en un ProDataGraph.</div></td>
				</tr>
			</tbody>
		</table>
	</div>
	<h1 id="IntegraçãoComAplicativosExternos-ThirdPartyTrademarks">Third
		Party Trademarks</h1>
	<p>Adobe and&#160;Flex Builder&#160;are either registered
		trademarks or trademarks of Adobe Systems Incorporated in the United
		States and/or other countries.</p>
	<p>Apache Flex is a&#160;registered&#160;trademark of The Apache
		Software Foundation.</p>
	<p>JavaScript is a trademark of Oracle Corporation.</p>
	<p>Microsoft and Windows are registered trademarks of Microsoft
		Corporation in the United States and/or other countries.</p>
	<p>Java is a trademark of Oracle and/or its affiliates. Other names
		may be trademarks of their respective owners.</p>
	<p>Progress and OpenEdge are trademarks or registered trademarks of
		Progress Software Corporation or one of its subsidiaries or affiliates
		in the U.S. and other countries.</p>
	<p>This product includes software developed by the Visigoth
		Software Society.</p>
	<p>
		<span style="font-size: 10.0pt; line-height: 13.0pt;">Any other
			third party trademarks are the property of their respective owners.</span>
	</p>
	<p>
		<span style="font-size: 10.0pt; line-height: 13.0pt;"><br /></span>
	</p>
</div>