Integração com passagem de filtros e parametros - wsReport

Olá pessoal!

Estou tentando criar um dataset que faça integração com o wsReport e estou tendo problemas ao tentar executar o metodo GenerateReport, mais especificamente na inserção de filtros e parametros.

Eu fiz o procedimento para pegar os filtros e parametros pelo GetReportInfo e tentei criar o dataset da forma abaixo, porem tenho erro na conversao do xml
There was an error deserializing the object of type System.Collections.Generic.List`1[[RM.Rpt.Executor.Intf.RptParameterReportPar, RM.Rpt.Executor.Intf, Version=12.1.2402.232, Culture=neutral, PublicKeyToken=null]]. Data at the root level is invalid. Line 1, position 1.

A fução getFilters vai receber parametros futuramente q seria a expressao de filtro e a tabela de referencia, porem no momento estou tentando fazer funcionar com dados estaticos, mas sem sucesso. Alguem ja passou por algo semelhante ?

Grato pela atenção.

function createDataset(fields, constraints, sortFields)    
{    

    var NOME_SERVICO = "wsReport"; // Nome do serviço criado no Fluig Studio  
    var CAMINHO_SERVICO = "com.totvs.WsReport"; // Caminho do serviço  
    var dataset = DatasetBuilder.newDataset();      
    
    
    var idRelatorio = 2254
    var filters = getFilters()
    var params = getParams()
    var fileName = "teste.pdf"
    var context = "CodColigada=1;CodFilial=2"
    	
    	log.info("filters: " + filters)
    	log.info("params: " + params)

    try {  
        // Obtem a instancia do serviço   
        var servico = ServiceManager.getServiceInstance(NOME_SERVICO);          
        // Inicializa o serviço  
        var instancia = servico.instantiate(CAMINHO_SERVICO);          
        // Obtem o WebService para consumo  
        var ws = instancia.getRMIwsReport();            
        var serviceHelper = servico.getBean();  
        // Autenticação no serviço  
        var authService = serviceHelper.getBasicAuthenticatedClient(ws, "com.totvs.IwsReport", 'usuario', 'senha');  
        
        
        var result = authService.generateReport(1, idRelatorio, filters, params, fileName, context);  
            log.info("!!! INFO !!!");  
            log.info(result);  
         if ((result != null) && (result.indexOf("===") != -1)) {  
            var msgErro = result.substring(0, result.indexOf("==="));  
            log.error("Erro: " + msgErro);  
            throw "Erro: " + msgErro;  
         }
  
    } catch (e) {  
         if (e == null)  
             e = "Erro desconhecido; verifique o log do AppServer";  
         var mensagemErro = "Erro na comunicação com o app (linha: " + e.lineNumber + "): " + e;  
         log.error(mensagemErro);  
         log.info(mensagemErro);  
         dataset.addColumn("ERROR");  
         dataset.addColumn("MESSAGE_ERROR");  
         dataset.addRow(new Array(-1, mensagemErro));  
    }     

    return dataset;  
}


function getFilters(filterExpression, tableName) {
	return '<![CDATA[<?xml version="1.0" encoding="utf-16"?>' +
	' <ArrayOfRptFilterReportPar xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.totvs.com.br/RM/">' +
	  ' <RptFilterReportPar>' +
	    ' <BandName>RptReport</BandName>' +
	    ' <FiltersByTable>' +
	      ' <RptFilterByTablePar>' +
	        ' <Filter>RA = "2100234"</Filter>' +
	        ' <TableName>SALUNO</TableName>' +
	      ' </RptFilterByTablePar>' +
	    ' </FiltersByTable>' +
	    ' <MainFilter>true</MainFilter>' +
	    ' <Value>(RA = "2100234")</Value>' +
	  ' </RptFilterReportPar>' +
	' </ArrayOfRptFilterReportPar>]]>'
}

function getParams() {
	 var xml = '<![CDATA[<?xml version="1.0" encoding="utf-16"?>' +
	    ' <ArrayOfRptParameterReportPar xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.totvs.com.br/RM/">' +
	      ' <RptParameterReportPar>' +
	        ' <Description>Ano Letivo:</Description>' +
	        ' <ParamName>PARAMETRO1</ParamName>' +
	        ' <Type xmlns:d3p1="http://schemas.datacontract.org/2004/07/System" xmlns:d3p2="-mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089-System-System.RuntimeType" i:type="d3p2:RuntimeType" xmlns:d3p3="-mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089-System-System.UnitySerializationHolder" z:FactoryType="d3p3:UnitySerializationHolder" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">' +
	          ' <Data xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:string" xmlns="">System.String</Data>' +
	          ' <UnityType xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:int" xmlns="">4</UnityType>' +
	          ' <AssemblyName xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:string" xmlns="">mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</AssemblyName>' +
	        ' </Type>' +
	        ' <Value xmlns:d3p1="http://www.w3.org/2001/XMLSchema" i:type="d3p1:string">2025</Value>' +
	        ' <Visible>true</Visible>' +
	      ' </RptParameterReportPar>' +
	    ' </ArrayOfRptParameterReportPar>]]>'
	 
	 return xml
}
1 curtida

Acho que nesse caso não precisa do CDATA, por já estar passando parâmetro indicado como XML né.

Ainda não executei relatório chamando assim, só dentro de FV e nele vai o XML completo da chamada (igual ao usado no SoapUI) e aí sim precisa do CDATA porque fica um XML dentro do outro.

1 curtida

Então, eu fiz sem o CDATA e até obtive retorno, mas veio um relatorio vazio como se desconsiderasse o filtro. O filtro funciona corretamente no SOAP UI

Olá, a única coisa diferente que vi aí foi a falta da tabela no campo… pra ser sincero não sei se isso influencia… mais os meus são todos assim… testa aí, de repente é isso

<?xml version="1.0" encoding="utf-16"?>' +
' <ArrayOfRptFilterReportPar xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.totvs.com.br/RM/">' +
  ' <RptFilterReportPar>' +
    ' <BandName>RptReport</BandName>' +
    ' <FiltersByTable>' +
      ' <RptFilterByTablePar>' +
        ' <Filter>SALUNO.RA = "2100234"</Filter>' +
        ' <TableName>SALUNO</TableName>' +
      ' </RptFilterByTablePar>' +
    ' </FiltersByTable>' +
    ' <MainFilter>true</MainFilter>' +
    ' <Value>(SALUNO.RA = "2100234")</Value>' +
  ' </RptFilterReportPar>' +
' </ArrayOfRptFilterReportPar>

Tomara que de certo… abs

Olá Eduardo!

Nesse formato tambem me retornou um relatorio vazio, imaginei que esse nao seria o problema pois pelo SOAP UI o filtro funciona enviando sem especificar a tabela. De qualquer forma obrigado pela sugestão, ainda não tinha tentado essa opção.

1 curtida

Cria o filtro que você precisa lá no report e no SOAPUI roda o método GetReportInfo, passando a coligada e o id do report, ele vai retornar exatamente os XMLs de filtros e parâmetros… compara com o seu e vê se tem alguma coisa diferente.

Valeu… abs

Beleza vou tentar fazer dessa forma atualmente o retorno que tenho do GetInfo esta assim

Solicitei ao meu gestor (ele que cuida do RM) para cadastrar uma copia desse relatorio ja com o filtro para analisar. Assim que testar posto aqui os resultados. Obrigado pela dica!

Eduardo, fiz conforme sua dica esse é o getinfo do relatorio ja com o filtro

A única diferença que notei é que neste tem uma tag “Name” em branco, tentei apenas inserir essa tag porem o relatorio continua vindo vazio. Vou tentar agora no novo relatorio, ver se consigo passar um RA diferente.

Apenas atualizando, tentei passar o xml com RA diferente no novo report cadastrado e o relatorio tambem vem vazio. Se eu passo o filters como string em branco o relatorio vem devidamente preenchido com o filtro que foi cadastrado no RM, no caso apenas do aluno que foi filtrado no RM

Jhonata, deu certo a geração do report? Eu estava enfrendo um problema aqui que ao gerar o relatório ele mostrava em branco no navegador e gerava normalmente no RM. O problema era o tamanho do arquivo gerado, se você não resolveu ainda e quiser ver melhor me avisa aqui. Abraço!!

@eduardo.vantini , você chegou a perceber a partir de qual tamanho dava problema?

Hoje eu só uso esse WS pra gerar Recibos/Contratos de Funcionários e com o Base64 enviar pra um serviço de assinatura digital. Aí acabei esbarrando num limite de uns 2MB só pra não ter que chamar a operação “chunk” várias vezes pra pegar o base64, mas não estudei pra saber se há um limite específico.

Não consegui pegar o limite, no meu cenário ou ficava pequeno ou ficava muito grande e como eu verifiquei que o base64 estava gerando corretamente, justamente chamando o chunk várias vezes, imaginei que o problema fosse o navegador, pois passava o base64 para ele abrir o pdf em outra aba. Para conseguir passa para o navegador certinho, converti para um blob e deu certo.

Mais meu PDF está com mais de 6mb.

1 curtida

Fala pessoal, aqui eu abri um chamado junto a Totvs, o analista nao conseguiu resolver e mandou pro time de produto, estou no aguardo da resolução.

Então, no meu caso ele esta gerando em branco no RM!

Fala pessoal!

Depois de muito tempo o pessoal da Totvs conseguiu me ajudar e eu vou postar a solução aqui para caso alguem passe pela mesma situação

Primeiramente, precisei mudar o link do serviço cadastrado no Fluig
Link que eu estava utilizando: https://meuservidor/wsReport/MEX?wsdl
Link enviado pela TOTVS: https://meuservidor/wsReport/mex?singleWsdl

Não me disseram de onde pegaram esse link, o que eu estava utilizando anteriormente era o que estava disponivel no wspageindex.

Feito isso, a forma de criação dos datasets tambem precisou ser diferente. Me orientaram a criar o dataset pelo painel de criação de dataset simples disponivel na plataforma, configurando a autenticação nesse mesmo painel. Anteriormente eu estava criando pelo eclipse e autenticando via codigo, como sempre fiz.

Depois da criação do dataset peguei o codigo gerado pelo mesmo e alterei para que conseguisse passar os parametros dinamicamente pela widget.

Com tudo isso o codigo final do dataset ficou assim:

function createDataset(fields, constraints, sortFields) {
	try {
		return processResult(callService(fields, constraints, sortFields));
	} catch(e) {
		return processErrorResult(e, constraints);
	}
}

function callService(fields, constraints, sortFields) {
	
	var ra
	var year
	
	for(var j=0; j < constraints.length; j++) {
    	var item = constraints[j]
    	if (item.fieldName == "RA") {
    		ra = item.initialValue
    	}
    	
    	if(item.fieldName == "ANOLETIVO") {
    		year = item.initialValue
    	}
    }
	
	 var msg = "É necessário informar: ";
	    var campos = [];

	    if (year == "") {
	        campos.push("Ano");
	    }
	    if (ra == "") {
	        campos.push("RA");
	    }

	    if (campos.length > 0) {
	        msg += campos.join(", ");
	        throw msg
	    }
	
	
	
	var serviceData = data(ra, year);
	var params = serviceData.inputValues;
	var assigns = serviceData.inputAssignments;
	var properties = {};
	properties["log.soap.messages"] = "false";
	properties["disable.chunking"] = "false";
	properties["use.ssl"] = "false";
	properties["basic.authorization"] = "true";
	properties["basic.authorization.username"] = "usuario";
	properties["basic.authorization.password"] = "senha";

	verifyConstraints(serviceData.inputValues, constraints);

	var serviceHelper = ServiceManager.getService(serviceData.fluigService);
	var serviceLocator = serviceHelper.instantiate(serviceData.locatorClass);
	var service = serviceLocator.getRMIwsReport();
	var headers = getSOAPHeaders(serviceHelper, serviceData.extraParams.headers);
	var customClient = serviceHelper.getCustomClient(service, properties, headers);
	var response = customClient.generateReport(getParamValue(params.codColigada, assigns.codColigada), getParamValue(params.id, assigns.id), 
		getParamValue(params.filters, assigns.filters), getParamValue(params.parameters, assigns.parameters), 
		getParamValue(params.fileName, assigns.fileName), getParamValue(params.contexto, assigns.contexto)
		);

	return response;
}

function defineStructure() {
		addColumn('response');
}

function onSync(lastSyncDate) {
	var serviceData = data();
	var synchronizedDataset = DatasetBuilder.newDataset();

	try {
		var resultDataset = processResult(callService());
		if (resultDataset != null) {
			var values = resultDataset.getValues();
			for (var i = 0; i < values.length; i++) {
				synchronizedDataset.addRow(values[i]);
			}
		}

	} catch(e) {
		log.info('Dataset synchronization error : ' + e.message);

	}
	return synchronizedDataset;
}

function verifyConstraints(params, constraints) {
	if (constraints != null) {
		for (var i = 0; i < constraints.length; i++) {
			try {
				params[constraints[i].fieldName] = JSON.parse(constraints[i].initialValue);
			} catch(e) {
				params[constraints[i].fieldName] = constraints[i].initialValue;
			}
		}
	}
}

function processResult(result) {
	var dataset = DatasetBuilder.newDataset();

	dataset.addColumn("response");
	dataset.addRow([result]);

	return dataset;
}

function processErrorResult(error, constraints) {
	var dataset = DatasetBuilder.newDataset();

	var params = data().inputValues;
verifyConstraints(params, constraints);

dataset.addColumn('error');
	dataset.addColumn('codColigada');
	dataset.addColumn('fileName');
	dataset.addColumn('id');
	dataset.addColumn('filters');
	dataset.addColumn('parameters');
	dataset.addColumn('contexto');

	var codColigada = isPrimitive(params.codColigada) ? params.codColigada : JSONUtil.toJSON(params.codColigada);
	var fileName = isPrimitive(params.fileName) ? params.fileName : JSONUtil.toJSON(params.fileName);
	var id = isPrimitive(params.id) ? params.id : JSONUtil.toJSON(params.id);
	var filters = isPrimitive(params.filters) ? params.filters : JSONUtil.toJSON(params.filters);
	var parameters = isPrimitive(params.parameters) ? params.parameters : JSONUtil.toJSON(params.parameters);
	var contexto = isPrimitive(params.contexto) ? params.contexto : JSONUtil.toJSON(params.contexto);

	dataset.addRow([error.message, codColigada, fileName, id, filters, parameters, contexto]);

	return dataset;
}

function getParamValue(param, assignment) {
	if (assignment == 'VARIABLE') {
		return getValue(param);
	} else if (assignment == 'NULL') {
		return null;
	}
	return param;
}

function hasValue(value) {
	return value !== null && value !== undefined;
}

function isPrimitive(value) {
	return ((typeof value === 'string') || value.substring !== undefined) || typeof value === 'number' || typeof value === 'boolean' || typeof value === 'undefined';
}


function getObjectFactory(serviceHelper) {
	var objectFactory = serviceHelper.instantiate("com.totvs.ObjectFactory");

	return objectFactory;
}

function getSOAPHeaders(serviceHelper, headers) {
	var soapHeaders = [];

	

	return soapHeaders;
}

function data(ra, year) {
	return {
  "fluigService" : "wsReport",
  "operation" : "generateReport",
  "soapService" : "WsReport",
  "portType" : "IwsReport",
  "locatorClass" : "com.totvs.WsReport",
  "portTypeMethod" : "getRMIwsReport",
  "parameters" : [ ],
  "inputValues" : {
    "codColigada" : 1,
    "fileName" : "Relatorio.pdf",
    "id" : 2254,
    "filters" : "<?xml version=\"1.0\" encoding=\"utf-8\"?> <ArrayOfRptFilterReportPar xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.totvs.com.br/RM/\">  <RptFilterReportPar>   <BandName>RptReport</BandName>   <FiltersByTable>    <RptFilterByTablePar>     <Filter>RA = '" + ra + "'</Filter>     <TableName>SALUNO</TableName>    </RptFilterByTablePar>   </FiltersByTable>   <MainFilter>true</MainFilter>   <Value>(RA = '" + ra + "')</Value>  </RptFilterReportPar> </ArrayOfRptFilterReportPar> ",
    "parameters" : "<?xml version=\"1.0\" encoding=\"utf-8\"?> <ArrayOfRptParameterReportPar xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.totvs.com.br/RM/\">  <RptParameterReportPar>   <Description>Ano Letivo:</Description>   <ParamName>PARAMETRO1</ParamName>   <Type xmlns:d3p1=\"http://schemas.datacontract.org/2004/07/System\" xmlns:d3p2=\"-mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089-System-System.RuntimeType\" i:type=\"d3p2:RuntimeType\" xmlns:d3p3=\"-mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089-System-System.UnitySerializationHolder\" z:FactoryType=\"d3p3:UnitySerializationHolder\" xmlns:z=\"http://schemas.microsoft.com/2003/10/Serialization/\">    <Data xmlns:d4p1=\"http://www.w3.org/2001/XMLSchema\" i:type=\"d4p1:string\" xmlns=\"\">System.String</Data>    <UnityType xmlns:d4p1=\"http://www.w3.org/2001/XMLSchema\" i:type=\"d4p1:int\" xmlns=\"\">4</UnityType>    <AssemblyName xmlns:d4p1=\"http://www.w3.org/2001/XMLSchema\" i:type=\"d4p1:string\" xmlns=\"\">mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</AssemblyName>   </Type>   <Value xmlns:d3p1=\"http://www.w3.org/2001/XMLSchema\" i:type=\"d3p1:string\">" + year + "</Value>   <Visible>true</Visible>  </RptParameterReportPar> </ArrayOfRptParameterReportPar>",
    "contexto" : "CodColigada=1;CodFilial=2"
  },
  "inputAssignments" : {
    "codColigada" : "VALUE",
    "fileName" : "VALUE",
    "id" : "VALUE",
    "filters" : "VALUE",
    "parameters" : "VALUE",
    "contexto" : "VALUE"
  },
  "outputValues" : { },
  "outputAssignments" : { },
  "extraParams" : {
    "disableChunking" : false,
    "useSSL" : false,
    "basicAuthentication" : true,
    "basicAuthenticationUsername" : "usuario",
    "basicAuthenticationPassword" : "senha",
    "parseResult" : false,
    "headers" : [ ],
    "datasetkeys" : [ ],
    "enabled" : true
  }
}
}

 function stringToBoolean(param) { if(typeof(param) === 'boolean') {  return param;  }  if (param == null || param === 'null') {  return false;  }  switch(param.toLowerCase().trim()) {  case 'true': case 'yes': case '1': return true;  case 'false': case 'no': case '0': case null: return false;  default: return Boolean(param);  }  } 

E agora o dataset funciona corretamente. Posteriormente criei os datasets para os demais metodos, como o getReportSize e o getFileChunk que retorna o base64 do arquivo.

Agradeço a todos que colaboraram com o tópico!

2 curtidas

Muito bom saber que tem essa diferença. Obrigado por compartilhar.

Também não fazia ideia dessa opção ?singleWsdl.

1 curtida