artigo

integração: o mecanismo errado hoje é o incidente de sexta à noite

Como escolher entre REST Message, Import Set e Scripted REST API sem transformar a integração na maior fonte de chamados da instância.

6 min de leitura avançado servicenow arquitetura integração

#nenhuma instância vive sozinha

Pega qualquer implementação ServiceNow madura e olha embaixo do capô: tem sistema de monitoramento mandando evento, ERP sincronizando departamento, diretório de usuário alimentando cadastro, e um punhado de planilhas que "só por enquanto" viraram fonte de dados oficial. A plataforma nunca é uma ilha — ela é o hub que conversa com todo o resto da empresa.

O problema não é conectar. O ServiceNow tem ferramenta de sobra para isso. O problema é escolher a ferramenta errada para o volume errado, porque a maioria das integrações instáveis em produção não quebrou por causa de bug — quebrou porque alguém usou uma mototáxi para mudança de apartamento.

#a pergunta que vem antes da ferramenta

Antes de abrir qualquer tela de configuração, responde três perguntas: esse dado precisa de resposta agora ou pode esperar minutos? É um registro por vez ou milhares de uma vez? Quem inicia a conversa — o ServiceNow ou o sistema de fora?

situaçãoferramenta que costuma resolverpor que não a outra opção
poucas chamadas por minuto, resposta precisa vir na horaREST Message V2Import Set foi feito para lote, não para "preciso da resposta em 2 segundos"
milhares de registros por dia, resposta pode esperarImport Set + Transform MapREST síncrono para 50 mil registros é uma fila de gente esperando uma pessoa só no caixa
sistema externo empurrando eventos sem pararScripted REST API recebendo + fila para processar depoisprocessar cada evento na hora que chega trava a instância no primeiro pico
sistema legado só fala JDBC, SSH ou PowerShellMID Servernão tem API REST do lado de lá — precisa de alguém dentro da rede que fale a língua
ServiceNow é o fornecedor da informação para outro sistemaScripted REST API versionadanão é para integração interna entre tabelas da própria instância

O erro mais caro dessa lista é tratar REST síncrono como martelo universal. Funciona liso em homologação com 10 registros de teste. Em produção, com carga real, vira fila de espera — e o usuário que está só tentando salvar um formulário é quem paga o preço.

#toda chamada de fora vai falhar algum dia

Não é pessimismo, é estatística: rede tem latência variável, sistema externo tem janela de manutenção, API tem rate limit. Uma integração sem plano para isso transforma um problema de 30 segundos — que se resolveria sozinho — numa falha permanente que alguém precisa destrancar manualmente às 2h da manhã.

A saída é retry com backoff progressivo, e a parte que mais gente esquece: nem todo erro merece retry. Um 4xx significa que a requisição em si está errada — tentar de novo do jeito que está só repete o erro. Um 5xx pode ser o sistema externo engasgado momentaneamente, e aí vale insistir.

javascript
// �
 cliente de integração com retry seletivo e log de cada tentativa
var ERPClient = Class.create();
ERPClient.prototype = {

    initialize: function() {
        this.delays = [5000, 15000, 45000]; // backoff progressivo
    },

    syncEmployee: function(payload) {
        for (var tentativa = 0; tentativa < this.delays.length; tentativa++) {
            try {
                var rm = new sn_ws.RESTMessageV2("ERPIntegration", "syncEmployee");
                rm.setHttpTimeout(20000);
                rm.setRequestBody(JSON.stringify(payload));

                var resp = rm.execute();
                var status = resp.getStatusCode();

                gs.info("[ERPClient] tentativa " + (tentativa + 1) + " -> HTTP " + status);

                if (status >= 200 && status < 300) {
                    return { ok: true, body: resp.getBody() };
                }

                if (status >= 400 && status < 500) {
                    // erro do lado de quem pediu — retry não resolve, precisa corrigir o payload
                    gs.error("[ERPClient] erro de cliente " + status + ", sem retry: " + resp.getBody());
                    return { ok: false, status: status };
                }
                // 5xx cai aqui e tenta de novo depois do delay

            } catch (e) {
                gs.error("[ERPClient] exceção na tentativa " + (tentativa + 1) + ": " + e);
            }

            if (tentativa < this.delays.length - 1) {
                gs.sleep(this.delays[tentativa]);
            }
        }
        return { ok: false, status: null, error: "esgotou as tentativas" };
    },

    type: "ERPClient"
};

#import set: o caminhão que esquece a lista de conferência

Import Set é o mecanismo certo para volume alto: os dados chegam numa tabela de staging, o Transform Map traduz e valida, e só depois vira registro de verdade na tabela de destino. Até aqui, sem susto.

O detalhe que derruba integração de carga em produção é o Coalesce — o campo (ou conjunto de campos) que diz "esse registro que está chegando é o mesmo que eu já tenho, ou é novo?". Sem Coalesce configurado, toda carga cria registro novo, mesmo quando o dado já existe.

javascript
// �
 onBefore: valida, normaliza e resolve referência antes do commit
function onBefore(source, target, action, response, ignore) {
    var obrigatorios = ["u_matricula", "u_email"];
    var faltando = obrigatorios.filter(function (campo) {
        return !source[campo] || !source[campo].toString().trim();
    });

    if (faltando.length > 0) {
        ignore = true; // pula o registro, não deixa dado incompleto virar cadastro
        gs.warn("ImportFuncionarios: registro descartado, faltando " + faltando.join(", "));
        return;
    }

    source.u_email = source.u_email.toString().trim().toLowerCase();
}

O Coalesce em si você configura na tela do Transform Map, não no script — mas é fácil esquecer justamente porque não é código, é uma caixinha marcada num formulário de setup que ninguém revisita depois que a integração "já está funcionando".

#quando o servicenow atende o telefone

Quando é outro sistema que precisa chamar o ServiceNow, a peça certa é a Scripted REST API. E aqui tem uma prática que separa API que envelhece bem de API que vira dor de cabeça: versionar a URL desde o primeiro dia, tipo /api/x_acme/v1/incidentes.

#segurança é parte do desenho, não um passo extra

Uma lista curta que vale revisar em toda integração nova, porque cada item dela já causou incidente em algum lugar:

  • Credencial vive em Connection & Credential Alias, criptografada — nunca hardcoded no script ou em System Property em texto plano.
  • Autenticação por OAuth 2.0 ou certificado, não Basic Auth sem TLS.
  • Todo parâmetro que chega de fora é validado antes de entrar numa query — nunca direto num addEncodedQuery().
  • API exposta tem limite de chamadas, com HTTP 429 quando estoura — sem isso, um script mal configurado do outro lado vira um DDoS sem querer.
  • Toda chamada relevante fica logada: quem chamou, quando, com que status — sem isso, o primeiro sinal de problema é a ligação do outro time reclamando.

#e agora?

  • Na sua instância de dev, procure a integração mais antiga que existe e pergunta: ela tem retry configurado? Diferencia 4xx de 5xx, ou tenta de novo para qualquer erro?
  • Se você mantém algum Import Set, abre o Transform Map dele agora e confirma que o Coalesce está de fato marcado no campo certo — é dois cliques que evitam duplicação silenciosa.
  • Este artigo conversa direto com flow designer: boa parte das integrações mais recentes usa IntegrationHub Spokes dentro de um Flow, em vez de REST Message solto num Script Include.
LinkedIn X/Twitter WhatsApp ☕ me paga um café