segunda-feira, 5 de janeiro de 2026

Trace Id - O que é e como implementar

        Nesse artigo não vou trazer uma implementação via código do Trace Id, mas o como implementar vai estar ligado a ideia de o que você precisa saber para implementar. 

        Um Trace Id é um Id único que percorre todas as etapas de uma requisição em microsserviços, devendo passar por todos os microsserviços compondo seu log. O Objetivo: Se der um erro, precisamos saber o fluxo completo da requisição para ajudar a identificar a causa raiz, os impactos e se os fluxos de rollback relacionados ao erro deram certo (no caso de um SAGA por exemplo, embora o SAGA tenha o SAGA ID), entre outras coisas. Qual a mensagem origem? Como eram seus dados? Sempre que perguntarmos por algo o Trace Id vai estar relacionado com essa pergunta.

        Para manter o fluxo do Trace Id você vai ter que:

  • Usar filtros para pegá-lo assim que receber a requisição web em todas as APIs;
  • Usar Interceptors para colocá-lo antes de enviar chamadas de uma API para outra;
  • Usar interceptors para o Kafka para colocá-lo no header do producer (ou alguma forma manual) andes de enviar
  • Pegar no @Listener do Kafka para setar no projeto
  • Salvar em bancos que guardam estado (bancos que salvam dados em seus estágios intermediários entre o processamento(Outbox Pattern ou outros)
  • Salvar em tabelas de auditoria (dependendo do caso)
  • Usar em logs
        É algo que vai interferir em todo o projeto, se esquecer em uma etapa fica um buraco de difícil solução. Então implementar requer cuidado, atenção, paciência e teste.

        Fica mais complicado se trabalhar com:
  • Chamada Assíncronas
  • Startar outras threads
  • WebFlux
  • Kafka Consumer
        É preciso estudar o cenário e opções corretas para se ter uma boa implementação pois caso contrário vai falhar. É o tipo de coisa que o conceito a simples, a implementação nem tanto.


sábado, 3 de janeiro de 2026

Padrão Brasileiro para Cálculos Financeiros - Bancos, Fintechs e afins em Java

        Em sistemas financeiros, precisão é uma exigência legal, contábil e auditável. Os tipos primitivos como double e float utilizam representação binária, o que gera erros de precisão. Então o padrão para se trabalhar com valores monetários é o BigDecimal, pois ele traz: precisão decimal exata, controle explícito de escala e controle explícito de arredondamento.

        O padrão para lidar com valores é:

  • Uso de BigDecimal
  • Escala fixa de 4 casas decimais (mesmo que só exiba duas usa 4 nos cálculos)
  • Arredondamento HALF_EVEN (arredondamento bancário)
  • Usar numeric no Banco de Dados (Numeric(19,4))

        Porém para se trabalhar corretamente com BigDecimal é preciso obedecer algumas regras:

  • Nunca iniciar o construtor a partir de um double ou float:

new BigDecimal(10.25);  // errado, faz o valor entrar nos erros de cálculo de repres. binária

  • Existem duas formas para inicializar:

new BigDecimal("10.25");     // A partir de String

BigDecimal.valueOf(10.25);  // Usando valueOf

// criando valores corretamente

BigDecimal valor = new BigDecimal("123.456789")

        .setScale(4, RoundingMode.HALF_EVEN);


  • O arredondamento é o RoundingMode.HALF_EVEN

Exemplo:

new BigDecimal("2.345").setScale(2, RoundingMode.HALF_EVEN); // 2.34 new BigDecimal("2.355").setScale(2, RoundingMode.HALF_EVEN); // 2.36

  • Não usar o equals para fazer comparações entre os objetos. O equals vai comparar as instancias.
    Use o "compareTo".
new BigDecimal("10.0").equals(new BigDecimal("10.00")); // false

new BigDecimal("10.0").compareTo(new BigDecimal("10.0"))

Retorna:         -1 → menor que         0 → igual         1 → maior que

        E a partir daí é usar o que a classe traz de métodos:

Soma:

BigDecimal resultado = valor1.add(valor2).setScale(4, RoundingMode.HALF_EVEN);

Subtração:

BigDecimal resultado = valor1.subtract(valor2).setScale(4, RoundingMode.HALF_EVEN);

Multiplicação:

BigDecimal resultado = valor1.multiply(valor2).setScale(4, RoundingMode.HALF_EVEN);

Divisão:

BigDecimal parcela = valor1.divide( valor2, 4, // escala RoundingMode.HALF_EVEN );


        Um exemplo de uma classe para trabalhar com dinheiro:


public class Money { private final BigDecimal value; public Money(BigDecimal value) { this.value = value.setScale(4, RoundingMode.HALF_EVEN); } public static Money of(String value) { return new Money(new BigDecimal(value)); } public Money add(Money other) { return new Money(this.value.add(other.value)); } public Money subtract(Money other) { return new Money(this.value.subtract(other.value)); } public Money multiply(BigDecimal factor) { return new Money(this.value.multiply(factor)); } public BigDecimal getValue() { return value; } }