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.
#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ção | ferramenta que costuma resolver | por que não a outra opção |
|---|---|---|
| poucas chamadas por minuto, resposta precisa vir na hora | REST Message V2 | Import Set foi feito para lote, não para "preciso da resposta em 2 segundos" |
| milhares de registros por dia, resposta pode esperar | Import Set + Transform Map | REST síncrono para 50 mil registros é uma fila de gente esperando uma pessoa só no caixa |
| sistema externo empurrando eventos sem parar | Scripted REST API recebendo + fila para processar depois | processar cada evento na hora que chega trava a instância no primeiro pico |
| sistema legado só fala JDBC, SSH ou PowerShell | MID Server | nã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 sistema | Scripted REST API versionada | nã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.
// �
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.
// �
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.