Histórico da Página
Índice
Índice | ||||||
---|---|---|---|---|---|---|
|
Objetivo
Além de algumas APIs REST, o fluig disponibiliza também uma série de Web Services SOAP (Simple Object Access Protocol). Neste documento mostraremos como habilitar ou desabilitar esses serviços, como gerar os stubs para utilizá-los em softwares terceiros e como utilizá-los dentro do próprio fluig.
Pré-requisitos
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 fluig
- Visão geral sobre integração de sistemas
- Web Services
Antes de começar
Os Web Services SOAP, apesar de continuarem funcionais, não recebem mais novos serviços nem alterações nos parâmetros de entrada. Caso haja, opte por usar a função correspondente nas APIs REST.
Como acessar
Para acessar os webservices do TOTVS Fluig Plataforma, é preciso acessar o URL https://<endereco_fluig:porta>/services.
Nossos serviços estão descritos no formato WSDL (Linguagem de Descrição de Serviços Web)
Segurança
Existem dois principais dispositivos de segurança para o uso dos Web Services SOAP.
Permissão por Web Services e/ou métodos
Por padrão, todos os usuários do fluig podem acessar os serviços. Isso facilita integrações e widgets que possam fazer uso dos serviços SOAP. Mas o administrador do sistema, caso queira, pode bloquear o uso dos serviços como um todo ou de alguns métodos.
Por motivos de retrocompatibilidade, é impossível bloquear o acesso dos serviços SOAP a todos os usuários. O fluig entende que se não há ninguém nas permissões é porque o administrador não quer configurar essa permissão, então para bloquear o acesso dos usuários normais ele deve dar permissão apenas a um usuário (o próprio administrador por exemplo);
Para bloquear o acesso a todos os métodos de um serviço, por exemplo, ECMWorkflowEngineService, o administrador deve entrar no painel de controle e acessar a opção de permissões. Pesquisar por ECMWorkflowEngineService. Irá listar tanto o acesso geral à API ECMWorkflowEngineService quanto a cada um dos métodos.
O administrador pode adicionar permissões para ele próprio no serviço geral do ECMWorkflowEngineService e isso fará com que nenhum usuário possa acessar os métodos desse serviço. Caso queira liberar um método específico , por exemplo startProcess, o administrador pode, mantendo a configuração anterior, acessar as permissões do recurso ECMWorkflowEngineService.startProcess adicionar as permissões conforme a sua necessidade.
Ou se quiser manter acesso a todos os outros métodos mas bloquear somente um método específico, ele deve manter as permissões gerais do serviço sem nenhuma configuração de permissão, e adicionar o usuário administrador nas permissões do método que deseja que seja bloqueado aos demais usuários.
Nota | ||
---|---|---|
| ||
Alguns métodos não foram criados para retornar erros. Então alguns métodos podem retornar informações vazias caso o acesso seja negado. Nestes casos, o log pode ser consultado para verificar a negação de acesso ao serviço. |
Personificação
Por lidar com integrações, alguns métodos permitem que o usuário integrador tome uma ação em nome de outro usuário (por exemplo, um serviço terceiro que utiliza um usuário para integrações pode abrir um chamado em nome de um usuário normal do fluig). Você pode limitar os usuários que conseguem tomar ação em nome de outros usuários pelos Web Services entrando no painel de controle e acessando a opção de permissões. Pesquisar por Personificação.
Nota | ||
---|---|---|
| ||
Assim como nas permissões dos Web Services, o fluig entende que se não há ninguém nas permissões é porque o administrador não quer configurar essa permissão, então para bloquear o acesso dos usuários normais ele deve dar permissão apenas a um usuário (o próprio administrador por exemplo) |
Permissões das funções acessadas
Independente das permissões anteriores, o fluig continua respeitando as permissões inerentes às funções acessadas. Ou seja, para configurar um processo, o usuário precisa ter acesso a página de configurar processos. Para acessar um documento, o usuário precisa ter permissão para visualizar o documento em si.
Como utilizar os Web Services em softwares terceiros
Verificando os serviços e chamadas manuais
Se você quer verificar o uso dos serviços ou mesmo fazer uma chamada individual você pode fazê-lo através de um aplicativo qualquer com suporte a requisições do tipo SOAP. Insira a url de um dos serviços disponíveis na url /services e preencha os dados conforme solicitado pelo aplicativo.
Criando rotinas automatizadas
O primeiro passo é fazer o download dos stubs, que são classes modelos que irão auxiliar no preenchimento dos dados utilizados por cada um dos serviços.
JDK 11 e superiores
Nas versões mais recentes da JDK o utilitário wsimport foi removido. Você pode baixar por outras fontes ou utilizar no lugar o Apache CXF (https://cxf.apache.org/) e gerando a biblioteca com os arquivos baixados
Bloco de código | ||||
---|---|---|---|---|
| ||||
wsdl2java -client -d C:\stubs\ -classdir C:\stubs\ -encoding UTF-8 -compile https://<endereco_fluig:porta>/webdesk/ECMWorkflowEngineService?wsdl
jar -cvf fluig-ws-client.jar C:\stubs\*.* |
JDK 8 e inferiores
Se você usa a JDK do java na versão 8 ou inferior, você pode utilizar este utilitário que disponibilizamos para gerar os stubs de todos os serviços.
Ou fazer de forma manual, caso precise apenas de um Web Service específico, usando o comando wsimport e gerando a biblioteca:
Bloco de código | ||||
---|---|---|---|---|
| ||||
wsimport -d C:\stubs\ https://<endereco_fluig:porta>/webdesk/ECMWorkflowEngineService?wsdl
jar -cvf fluig-ws-client.jar C:\stubs\*.* |
Importando a lib e desenvolvendo sua integração
Após a geração do arquivo fluig-ws-client.jar (conforme descrito nos passos anteriores) você pode desenvolver sua própria API.
Se quiser gerar uma biblioteca para usar dentro do próprio Fluig, ou mesmo alguns exemplos de como utilizar as integrações, você pode consultar nossa documentação
Para saber como ou então aprender como utilizar a biblioteca gerada, aqui você encontra um exemplo prático de utilização em artefatos publicados no fluig.
POST, não PUT
É importante salientar que todos os dados enviados (ou não enviados) em um método de alteração são considerados. Se um campo não for enviado, o sistema vai considerar que o valor dele deve ser deixado em branco, nulo ou zerado, conforme o tipo de dado. Então, mesmo que você queira apenas modificar a descrição do arquivo, você deve passar todos os outros dados do documento.
Disponibilidade dos Web Services
Lembre-se que a sua integração pode ocorrer em um momento que o fluig não está no ar. Seja por uma atualização ou regra de economia de energia, esteja preparado nas suas integrações para indisponibilidade do servidor. Ou seja, use try/catch.
Como utilizar os Web Services do Fluig no próprio Fluig?
Você pode utilizar os serviços do Fluig no próprio Fluig, da mesma forma que utiliza serviços de terceiros. Para isso, o administrador deve entrar no Painel de Controle e acessar a opção de Serviços. Criar um novo serviço do tipo SOAP, definir um nome (por exemplo ECMWorkflowEngineService, este nome será usado depois para referenciar este cadastro), uma descrição para outros identificarem que serviço é este e a URL do serviço (por exemplo, https://<endereco_fluig:porta>/webdesk/ECMWorkflowEngineService?wsdl)
Usando o editor web (sem codificação)
Na configuração de processo, crie ou edite um processo e adicione uma atividade de serviço. Acesse as propriedades dessa atividade e selecione o serviço ECMWorkflowEngineService (ou o nome que você utilizou no cadastro) e selecione a operação (por exemplo, startProcess).
Preencha os campos que serão utilizados e confirme.
Codificando
Você também pode fazer a codificação da chamada dos métodos dos serviços, fazendo com quem um dataset faça a inicialização da solicitação ou mesmo caso a opção sem codificação não atenda as suas necessidades. Para lhe ajudar, criamos este exemplo:
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
function startProcess() {
var serviceHelper = ServiceManager.getService("ECMWorkflowEngineService").getBean();
var serviceLocator = serviceHelper.instantiate("com.totvs.technology.ecm.workflow.ws.ECMWorkflowEngineServiceService");
var service = serviceLocator.getWorkflowEngineServicePort();
// Lista das matrículas de usuários que irão receber a atividade. Normalmente é um usuário, mas no caso de um consenso podem ser vários
var colleagueIds = serviceHelper.instantiate('net.java.dev.jaxb.array.StringArray');
colleagueIds.getItem().add("adm");
// Chama o serviço para iniciar a solicitação e recebe o retorno
// O retorno do startProcess é um String[][], ou no Soap, um StringArrayArray
var retornoStartProcess = service.startProcess(
'integrador', // matrícula do usuário integrador
'9a411f45fcea479ffb839a3ee605c18d', // senha do usuário
1, // código da empresa
"processoASerIniciado", // código do processo
2, // código da atividade para qual a solicitação vai ser movimentada
colleagueIds,
"Iniciado via ws", // Comentário da movimentação
'integrador', // Usuário que ficará como o inicializador da solicitação. O usuário integrador precisa ter personificação caso seja um usuário diferente do integrador
true, // Se vai completar a tarefa inicial (true) ou não, vai apenas salvar a solicitação para gerar um código e preencher o formulário, anexos e comentários
serviceHelper.instantiate('com.totvs.technology.ecm.workflow.ws.ProcessAttachmentDtoArray'), // Lista de anexos. Mesmo que não seja enviado nenhum, é necessário enviar a lista vazia
serviceHelper.instantiate('net.java.dev.jaxb.array.StringArrayArray'), // Dados do formulário. Mesmo que não tenha formulário ou não seja preenchido, é necessário enviar a lista vazia
serviceHelper.instantiate('com.totvs.technology.ecm.workflow.ws.ProcessTaskAppointmentDtoArray'), // Apontamentos da solicitação. Não é mais utilizado, mas por compatibilidade é necessário enviar a lista vazia
false // Se a movimentação é feita como usuário responsável pela atividade ou como gestor do processo
);
var retorno = stringArrayArrayToSimpleObject(retornoStartProcess);
if (retorno.ERROR) {
// Interrompe a execução ou movimentação e retorna um erro com a resposta do serviço
throw "Solicitação não iniciada: " + retorno.ERROR;
} else {
// Imprime o código da solicitação criada pelo serviço e depois imprime todos os dados que foram retornados
log.info("Solicitação " + retorno.iProcess + " criada com sucesso");
log.dir(retorno)
}
}
function stringArrayArrayToSimpleObject(stringArrayArray) {
var objeto = {};
for(var i = 0; i < stringArrayArray.getItem().size(); i++) {
var item = stringArrayArray.getItem().get(i).getItem();
objeto[item.get(0)] = item.get(1);
}
return objeto;
}
|
Ou, se preferir um exemplo um pouco maior, mas contendo mais detalhes sobre o que é cada parâmetro e desenvolvido para ser melhor re-utilizável, você pode conferir este exemplo que faz o mesmo que o exemplo anterior
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
//configure os dados do seu usuário integrador
var INTEGRADOR = {
matricula: 'integrador',
senha: '9a411f45fcea479ffb839a3ee605c18d',
empresa: 1
};
// conforme o cadastro do fluig
var SERVICOS = {
workflowEngineService: "ECMWorkflowEngineService"
}
/**
* Função que cria uma solicitação via Soap no Fluig
*
*/
function startProcess() {
var serviceHelper = getECMWorkflowEngineServiceHelper();
var service = getECMWorkflowEngineService(serviceHelper);
// Nome do processo a ser iniciado
var processId = "processoASerIniciado";
// Atividade para qual será movimentada a solicitação
var choosedState = 2;
// Lista das matrículas de usuários que irão receber a atividade. Normalmente é um usuário, mas no caso de um consenso podem ser vários
var colleagueIds = createStringArray(serviceHelper);
colleagueIds.getItem().add("adm");
// Comentário da movimentação
var comments = "Iniciado via ws";
// Usuário que ficará como o inicializador da solicitação. O usuário integrador precisa ter personificação caso seja um usuário diferente do integrador
var userId = INTEGRADOR.matricula;
// Se vai completar a tarefa inicial (true) ou não, vai apenas salvar a solicitação para gerar um código e preencher o formulário, anexos e comentários
var completeTask = true;
// Lista de anexos. Mesmo que não seja enviado nenhum, é necessário enviar a lista vazia
var attachments = createProcessAttachmentDtoArray(serviceHelper);
// Dados do formulário. Mesmo que não tenha formulário ou não seja preenchido, é necessário enviar a lista vazia
var cardData = createStringArrayArray(serviceHelper);
// Apontamentos da solicitação. Não é mais utilizado, mas por compatibilidade é necessário enviar a lista vazia
var appointments = createProcessTaskAppointmentDtoArray(serviceHelper);
// Se a movimentação é feita como usuário responsável pela atividade ou como gestor do processo
var managerMode = false;
// Chama o serviço para iniciar a solicitação e recebe o retorno
// O retorno do startProcess é um String[][], ou no Soap, um StringArrayArray
var retornoStartProcess = service.startProcess(
INTEGRADOR.matricula,
INTEGRADOR.senha,
INTEGRADOR.empresa,
processId,
choosedState,
colleagueIds,
comments,
userId,
completeTask,
attachments,
cardData,
appointments,
managerMode
);
var retorno = stringArrayArrayToSimpleObject(retornoStartProcess);
if (retorno.ERROR) {
// Interrompe a execução ou movimentação e retorna um erro com a resposta do serviço
throw "Solicitação não iniciada: " + retorno.ERROR;
} else {
// Imprime o código da solicitação criada pelo serviço e depois imprime todos os dados que foram retornados
log.info("Solicitação " + retorno.iProcess + " criada com sucesso");
log.dir(retorno)
}
}
function getECMWorkflowEngineServiceHelper() {
return ServiceManager.getService(SERVICOS.workflowEngineService).getBean();
}
function getECMWorkflowEngineService(serviceHelper) {
var serviceLocator = serviceHelper.instantiate("com.totvs.technology.ecm.workflow.ws.ECMWorkflowEngineServiceService");
return serviceLocator.getWorkflowEngineServicePort();
}
/**
* Cria uma variável similar ao String[] que é utilizado pelo Soap
* @param serviceHelper O wsdl que contém o mapeamento da estrutura de um objeto do tipo net.java.dev.jaxb.array.StringArray
* @returns Um objeto do tipo net.java.dev.jaxb.array.StringArray conforme o mapeamento do wsdl
*/
function createStringArray(serviceHelper) {
return serviceHelper.instantiate('net.java.dev.jaxb.array.StringArray');
}
/**
* Cria uma variável similar ao String[][] que é utilizado pelo Soap
* @param serviceHelper O wsdl que contém o mapeamento da estrutura de um objeto do tipo net.java.dev.jaxb.array.StringArrayArray
* @returns Um objeto do tipo net.java.dev.jaxb.array.StringArrayArray conforme o mapeamento do wsdl
*/
function createStringArrayArray(serviceHelper) {
return serviceHelper.instantiate('net.java.dev.jaxb.array.StringArrayArray');
}
/**
* Cria uma variável similar ao ProcessAttachmentDto[] que é utilizado pelo Soap
* @param serviceHelper O wsdl que contém o mapeamento da estrutura de um objeto do tipo com.totvs.technology.ecm.workflow.ws.ProcessAttachmentDtoArray
* @returns Um objeto do tipo com.totvs.technology.ecm.workflow.ws.ProcessAttachmentDtoArray conforme o mapeamento do wsdl
*/
function createProcessAttachmentDtoArray(serviceHelper) {
return serviceHelper.instantiate('com.totvs.technology.ecm.workflow.ws.ProcessAttachmentDtoArray');
}
/**
* Cria uma variável similar ao ProcessTaskAppointmentDto[] que é utilizado pelo Soap.
*
* Estes apontamentos não são mais usados, mas como não devemos mexer na assinatura dos métodos Soap para não quebrar os stubs já gerados é obrigatório mandar, ainda que vazio
*
* @param serviceHelper O wsdl que contém o mapeamento da estrutura de um objeto do tipo com.totvs.technology.ecm.workflow.ws.ProcessTaskAppointmentDtoArray
* @returns Um objeto do tipo com.totvs.technology.ecm.workflow.ws.ProcessTaskAppointmentDtoArray conforme o mapeamento do wsdl
*/
function createProcessTaskAppointmentDtoArray(serviceHelper) {
return serviceHelper.instantiate('com.totvs.technology.ecm.workflow.ws.ProcessTaskAppointmentDtoArray');
}
/**
* Transforma um objeto do tipo StringArrayArray (String[][]) em um objeto Javascript
*
* <item>
* <item>campo</item>
* <item>valor</item>
* </item>
*
* Vira:
*
* {'campo': 'valor'}
*
* @param stringArrayArray
* @returns Um objeto do tipo javascript
*/
function stringArrayArrayToSimpleObject(stringArrayArray) {
var objeto = {};
for(var i = 0; i < stringArrayArray.getItem().size(); i++) {
var item = stringArrayArray.getItem().get(i).getItem();
objeto[item.get(0)] = item.get(1);
}
return objeto;
} |
Objetivo
O objetivo deste documento é descrever a utilização de Webservices, mostrar e explicar todos seus métodos, disponibilizar exemplos de classes que utilizam esses Webservices e mostrar exemplos de geração de stubs que são necessários para que os client’s possam se comunicar com o serviço.
Criar Stubs
Os stubs são necessários para que os client’s que utilizam os métodos dos Webservices possam se comunicar com o serviço.
Para criar um stub é necessário que o serviço do Fluig esteja inicializado. Depois de iniciar o serviço, deve-se abrir o Prompt de comando e utilizar a sintaxe: wsimport -d <output_directory> <wsdl_url>, onde output_directory é o diretório onde o stub será criado e wsdl_url é a url de acesso ao serviço. Após isso, basta apertar Enter e o resultado aparecerá conforme mostra a figura 1.
Figura 1: Exemplo de criação de stub
Expandir | ||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||||||||||||||||||||||||||||||||||||||||
No quadro 1, é mostrado o comando necessário para criação de stubs de cada serviço disponível no Fluig.
Quadro 1: Comandos para criação de stubs
|
Considerações Métodos de Update
Para os métodos de update que recebem objetos complexos (DocumentDto, ColleagueDto, GroupDto, etc) é obrigatório passar todos os campos do objeto alterado. Os campos não informados serão substituídos por branco, nulo ou zero, dependendo do seu tipo.
Para evitar esta situação, sugerimos sempre utilizar os métodos get para recuperar o objeto, efetuar as alterações nos campos necessários e enviá-lo para o método update.
ECMAttributionMecanismService
Webservices responsável por realizar operações referentes aos mecanismos de atribuição cadastrados no Fluig. Pode ser utilizado para pesquisar os mecanismos de atribuição de uma determinada empresa.
Métodos
Expandir | ||
---|---|---|
| ||
Quadro 2: Métodos da AttributionMecanismService
|
Exemplo de utilização
No diretório de documentação do Fluig na pasta Documentos de Customização\Arquivos Adicionais\Exemplos Webservices\ExemplosAttributionMecanismService é disponibilizada a classe AttributionMecanismServiceClient.java, esta exemplifica a utilização de todos os métodos da classe AttributionMecanismService.
ECMBusinessPeriodService
Webservices responsável por realizar operações referentes aos expedientes cadastrados no Fluig. Pode ser utilizado para pesquisar os expedientes de uma determinada empresa.
Métodos
Expandir | ||
---|---|---|
| ||
No quadro 3, é mostrado todos os métodos disponíveis na classe ECMBusinessPeriodService.
Quadro 3: Métodos da ECMBusinessPeriodService |
Exemplo de utilização
No diretório de documentação do ECM na pasta Documentos de Customização\Arquivos Adicionais\Exemplos Webservices\ExemplosBusinessPeriodService é disponibilizada a classe BusinessPeriodServiceClient.java, esta exemplifica a utilização de todos os métodos da classe BusinessPeriodService.
ECMCardIndexService
Webservices responsável por realizar operações referentes aos fichários cadastrados no Fluig.
Métodos
Expandir | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||||||||||||
No quadro 4, é mostrado todos os métodos disponíveis na classe ECMCardIndexService.
Quadro 4: Métodos da ECMCardIndexService
|
Exemplo de utilização
No diretório de documentação do Fluig na pasta Documentos de Customização\Arquivos Adicionais\Exemplos Webservices\ExemplosCardIndexService é disponibilizada a classe CardIndexServiceClient.java, esta exemplifica a utilização de todos os métodos da classe CardIndexService.
ECMCardService
Webservices responsável por realizar operações referentes a fichas no ECM. Pode ser utilizado para criar, alterar, excluir e pesquisar fichas, entre outras funcionalidades.
Métodos
Expandir | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
No quadro 5, é mostrado todos os métodos disponíveis na classe ECMCardService.
Quadro 5: Métodos da ECMCardService
|
Exemplo de utilização
No diretório de documentação do Fluig na pasta Documentos de Customização\Arquivos Adicionais\Exemplos Webservices\ExemplosCardService é disponibilizada a classe CardServiceClient.java, esta exemplifica a utilização de todos os métodos da classe CardService.
...