Como migrar para Java 11 afetou recursos de Localização

Willyan Guimarães
experienceCode
Published in
4 min readJan 20, 2021

Recentemente trabalhei na atualização do Java 8 para 11 em uma aplicação. Dado que o ritmo de atualização da JVM mudou consideravelmente esse trabalho se torna mais frequente e claro muito importante para a vida útil do software.

Tudo se passou em um projeto usando maven, em mais uma aplicação trivial com seus endpoints, banco de dados e nada mais.

A migração ocorreu de forma razoavelmente simples: ajuste de número de versão e aquele momento de aproveitar pra atualizar algumas dependências usadas. Logo o build maven já trazia boas notícias.

[INFO] BUILD SUCCESS

Até aí tudo certo, hora de levar essa nova release para testes.

Alguns dias se passaram e de repente alguns clients da API começaram a visualizar que os body responses recebidos pelo server estavam diferentes.

Verificando os responses pelos recursos da API, não se via nada de anormal:

{

valor:"R$ 300,00"
}

Mesmo assim ainda parecia haver algo diferente na release pois para alguns clients o conteúdo do campo chegava e era interpretado sem o espaço entre o caracter “$” e o "3", como no exemplo acima. E aí?

lascou hehe

Depois de algum tempo sem entender nada surgiu a ideia de copiar o trecho no antes e depois. Em outras palavras, ver se existia diferença entre o conteúdo do dado que a aparecia antes usando Java 8 e depois da atualização. Foi então que copiando o dado diretamente da saída (STDOUT) percebe-se a diferença invisível mas que sim demonstrava um comportamento distinto entre as duas versões:

Com Java 8

Com Java 11

OBS:. Só foi visível essa diferença copiando a saída e colando no IntelliJ. Em vários editores não foi exibido a diferença, apenas sendo representado como espaço.

Pesquisando diretamente sobre a sigla NBSP que apareceu encontra-se a definição na Wikipedia:

Em formatação de texto, espaço rígido (ou espaço fixo; também conhecido por nbsp, acrônimo para non-breaking space) é uma variação do caractere espaço que previne a quebra de linha automática em sua posição.

Nesse momento já havia se compreendido que existia uma problema em que Strings que haviam sido formatadas e construídas pela aplicação antes utilizavam espaço simples e agora usavam um espaço rígido.

Bom, com isso chegamos a raiz do problema: de fato por algum motivo o Java se comportava diferente da versão 8 para 11 em relação a formatação de moeda. Agora resta saber o porquê.

Como o porquê parecia difícil de ser compreendido por hora seria mais fácil buscar todas as referências no código desse tratamento e usar aquele velho e prático replace.

text.replace('\u00A0',' ');

Solução sim, prática e rápida. O problema seria resolvido e estamos todos felizes. Só que a longo prazo, tem alguns cenários a se considerar:

  • Como um novo programador no projeto vai entender o motivo de ver espalhado pelo código instruções replace executando uma alteração de tipo de espaço ?
  • Documentar até seria uma ótima escolha mas como isso fica em mais de uma classe Java ? Replicamos o comportamento e a documentação ?
  • E quando um novo código fazendo tratamento semelhante for criado do zero por um dev que não sabe a respeito do problema ?

Por essas razões, por mais fácil que fosse apenas copiar e colar vários “replaces” pelo código já era possível entender que não seria uma solução definitiva e sustentável com o passar do tempo.

Então voltemos ao problema inicial, vamos pesquisar sobre o assunto…

Se você pesquisar pelas alterações do Java nos Release Notes das versões 9, 10 & 11 não verá nada que explica uma modificação de Locale/i18n em destaque. Mas indo a fundo encontra-se as referências abaixo.

Com o Java 9 os dados padrões de localização e internacionalização passaram a ser o CLDR, um projeto que mantém um repositório de dados centralizado para localização e i18n.

Com essa informação, vemos que é possível ter um comportamento análogo as versões anteriores do Java usando o argumento abaixo na execução da aplicação:

-Djava.locale.providers=COMPAT,SPI

Pensando em solução, vale lembrar que essa escolha depende muito do contexto. Por exemplo, no caso de um software que lide com várias localizações diferentes (por exemplo um software que faça cotações em diferentes moedas) penso que a melhor solução é a a adaptação ao novo formato. Já para uma aplicação que trabalhe com apenas uma Localização isso se torna bem menos problemático e não traz tanto impacto em manter o provider antigo.

A longo prazo, serve considerar que talvez o caminho seja a evolução tendo em vista que o JEP da mudança deixa claro que o CLDR é um padrão bem mais amplamente utilizado pelo mercado. Então, se por hora não considerar mudar pense em lembrar desse item logo a frente nos seus débitos técnicos.

--

--