Atualizando a lista de Timezone da JVM

Olá pessoal vamos falar sobre como atualizar a lista de Timezone da JVM.

O Problema da Mudança de Timezone


Devido uma mudança realizada pelo governo brasileiro, este ano não teremos o horário de verão, que mudava o GMT para -2 em algumas regiões do Pais, com isso, as configurações de Timezone dos servidores são ajustados para não realizar a mudança, mas alguns ambientes onde temos JVM podem acabar mudando e não seguindo o Timezone do S.O, pois a regra antiga ainda encontra-se configurada.

Ambiente Java 10 mudou com Timezone incorreto.

Acima instanciamos um objeto Date() a partir do JShell e notamos a diferença no horário, onde o correto seria exibir 11:05:31.


Lista de Timezone Atualizados


Como aconteceu aqui no Brasil, podem acontecer mudanças de Timezone em qualquer lugar (mesmo não sendo comum), quando ocorrem essas mudanças temos que recorrer a listas de Timezone atualizadas para que os ambientes possam funcionar corretamente.

No caso da JVM, a Oracle mantém a lista de Timezone baseada na IANA.

Para corrigir o nosso problema iremos utilizar a seguinte URL: https://www.iana.org/time-zones/repository/tzdata-latest.tar.gz, esta irá retornar a ultima lista atualizada de Timezones.

A Ferramenta TZUpdater


A Oracle disponibiliza uma ferramenta para atualizar a lista de Timezone chamada TZUpdater, esta é um arquivo jar que deve ser executado passando a lista de atualização como parâmetro.


Realizando a execução


Para executar o utilitário devemos executar o seguinte comando:

java -jar tzupdater.jar  -l https://www.iana.org/time-zones/repository/tzdata-latest.tar.gz


Se tudo ocorrer corretamente o resultado será o seguinte:


Descritivo da execução do comando.

Obs: Vale lembrar que caso você tenha mais de uma JVM no ambiente, ao executar o comando java, a lista que será atualizada é a que for sua JAVA_HOME e estiver configurada em seu PATH, caso sua necessidade seja alterar de outras JVM, use o caminho absoluto, por exemplo: /opt/path_java/bin/java


Após a atualização vamos criar novamente um objeto Date:


Ambiente Java 10 com o Timezone correto.

Após a execução do tzupdater a lista foi alterada e o Timezone esta de acordo com as configurações Locais.

Referências


Skipping Tests, Profiles e Debug com Maven

Olá pessoal, hoje iremos ver alguns comandos utilitários no processo de build do Maven.

O Processo de Build

O Maven é uma ferramenta que trás muitos benefícios ao ambiente de desenvolvimento, com ele gerenciamos dependências, versionamento e configurações dos projetos.

Uma parte muito importante que devemos nos atentar é com o processo de build, este processo é composto pela execução de todo o ciclo de vida do Maven, execução dos plugins presentes no pom.xml e a criação do artefato final.

É comum nos depararmos com builds que demoram vários minutos para completar, caso seja o seu caso, existem algumas métricas que dizem que "um processo de build não deve demorar mais que 5 minutos".

Maven Skip Tests

A execução dos testes é algo fundamental em projetos de softwares, mas as vezes nos deparamos com cenários onde precisamos executar o processo de build e não executar o pipeline de testes, com Maven temos 3 maneiras de executar tal tarefa, sendo:


Plugin


<plugin>        
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-surefire-plugin</artifactId>
 <version>2.12.4</version>
 <configuration>
    <skipTests>true</skipTests>
 </configuration>
</plugin>

Linha de Comando


mvn install -DskipTests

Linha de Comando, evitando a compilação dos Testes


mvn install -Dmaven.test.skip=true

Maven Profiles

Profiles é algo que praticamente todos ambientes de desenvolvimento necessitam, isso porque é comum termos particularidade entre os ambientes de desenvolvimento, testes, homologação e produção.

No Maven temos os profiles de build, estes permitem que de acordo com o profile configurado, diferentes processos e plugins sejam executados, para executarmos profile devemos fazer o seguinte:

<profiles>
   <profile>
      <id>dev</id>
       <!-- Código do build -->
   </profile>
   <profile>
      <id>homolog</id>
      <!-- Código do build -->
   </profile>
   <profile>
      <id>prod</id>
      <!-- Código do build -->
   </profile>
<profiles>

Após termos a configuração no pom.xml, podemos executar informando qual profile queremos executar:

mvn package -P dev

Aqui podemos ver a flag -P esta determina qual profile queremos que nosso build execute.

Maven Debug

Uma coisa muito comum é realizar o debug de um processo de build, esta operação nos permite verificar cada execução do processo, analisando qual o fluxo de cada parte do build.

No Maven, o padrão é executar todo o processo como INFO, ou seja, apesar informações essenciais serão exibidas no console, para executar o build em modo debug podemos passar a flag -X, como o abaixo:

mvn package -X

Todas essas pequenas configurações que realizamos ajudam no processo de build, tornando mais simples encontrar bugs, executar diferentes processos e encontrar problemas de performance.

Até a próxima.

Referências


Analisando na Prática o uso de Primitivos e Wrappers

O uso de tipos primitivos e Wrappers é um tema que traz diversas discussões, inclusive existem vários tutorias que mostram a aplicabilidade de cada uma das estratégias em diferentes cenários.

As Classes Wrappers


As classes Wrappers são aquelas que representam os tipos primitivos da linguagem Java, há algum tempo existiam autores que falavam que Java não era uma linguagem 100% OO por tratar os tipos básicos como primitivos, mas isso acabou quando adicionaram os tipos Wrappers a linguagem.

O Wrappers são classes imutáveis, e possuem vários métodos utilitários que facilitam conversões, parses, formatação, entre outras funcionalidades bem utilizadas no dia a dia.

Vamos analisar cada tipo primitivo e sua representação em classe Wrapper:
  • byte
    • Byte;
  • short
    • Short;
  • int
    • Integer;
  • long
    • Long;
  • boolean
    • Boolean;
  • char
    • Character;
  • float
    • Float;
  • double
    • Double;

Comparação entre Wrappers


Vamos entender como esses objetos funcionam no quesito comparação, já analisei casos onde uma comparação de valores iguais não resultavam em true, vamos analisar alguns motivos para isso ocorrer:

 Integer oneWrapper = 1; //Autoboxing do valor <1> para a variavel oneWrapper
 Integer twoWrapper = 1; //Autoboxing do valor <1> para a variavel twoWrapper
  
 System.out.println(" Comparação de Wrappers \n");
 System.out.println(oneWrapper == twoWrapper);
 System.out.println(oneWrapper != twoWrapper);
 System.out.println(oneWrapper.equals(twoWrapper));

O Resultado do nosso código será o seguinte:
oneWrapper == twoWrapper : true
oneWrapper != twoWrapper : false
oneWrapper.equals(twoWrapper) : true

Para entender os resultado, vamos lembrar que quando criamos as variáveis do tipo Wrapper realizando a atribuição direta de um valor, o compilador realiza o autoboxing, que é a conversão de um tipo primitivo em tipo Wrapper.

Na primeira condição temos oneWrapper == twoWrapper, quando comparamos objetos com == a comparação acontece entre as referências dos objetos, e neste caso como as variáveis foram criadas através de atribuição direta, o valor 1 será reaproveitado do pool de objetos, assim as variáveis apontaram para o mesmo objeto em memória.

Na segunda condição temos oneWrapper != twoWrapper, aqui a explicação é a mesma da primeira.

Na terceira condição temos oneWrapper.equals(twoWrapper), quando aprendemos manipulação de objetos com Java, analisamos o método equals(), que é o método que utilizamos para analisar se um objeto é igual ao outrolembrando que os Wrappers são objetos, portanto o equals é a melhor forma de realizar a comparação.


Integer oneWrapper = 1; //Autoboxing do valor <1> para a variavel oneWrapper
Integer twoWrapper = new Integer(1); //Criação sem reaproveitar o objeto do pool
  
System.out.println(" Comparação de Wrappers com Instância direta \n");
System.out.println(oneWrapper == twoWrapper);
System.out.println(oneWrapper != twoWrapper);
System.out.println(oneWrapper.equals(twoWrapper));

O resultado será o seguinte:

oneWrapper == twoWrapper        : false
oneWrapper != twoWrapper         : true
oneWrapper.equals(twoWrapper) : true

Vamos entender o resultado, no primeiro exemplo é feita uma comparação entre 2 Wrappers utilizando o operador ==, mas os objetos foram criados de forma diferente, na variável oneWrapper foi realizado a atribuição do valor diretamente onde irá ser realizado o autoboxing, já a variável twoWrapper foi criada utilizando o construtor de Integer.

Ao criar utilizando o construtor, não reaproveitamos objetos do pool de objetos, ou seja, foi criado outro objeto em memória, e como já sabemos o operador == realiza a comparação entre referências, portanto resultado da comparação é false.

No segundo exemplo utilizando o operador != aqui o conceito é o mesmo do exemplo anterior, o valor de ambas as variáveis é 1, mas lembrando que o operador irá comparar referências que são diferentes portanto o resultado é true.

Já no terceiro exemplo utilizamos o método equals() para realizar a comparação, neste caso o que será avaliado é o valor das variáveis, portanto o resultado é true.

Analisando a Performance


Um ponto importante é analisarmos a performance das operações de boxing dentro de estruturas de repetição, estas operações são custosas pois exigem  muitas transformação em laços.

Vamos analisar alguns códigos para entendermos os casos.

long init = System.currentTimeMillis();
  
long result = 0;
  
for (long i = 0; i < 1000000000; i++) {
     result += i;
}
  
long end = System.currentTimeMillis();
  
System.out.println(" Tempo: "+(end - init)); 

O Resultado da execução é:  Tempo: 460

Esse é um código onde apenas executamos um soma entre as variáveis result e i utilizando o operador += , perceba que como estamos usando o tipo long a soma acontece sem maiores problemas.


long init = System.currentTimeMillis();
  
Long result = 0L;
  
for (long i = 0; i < 1000000000; i++) {
     result += i;
}
  
long end = System.currentTimeMillis();
  
System.out.println(" Tempo: "+(end - init));

O Resultado da execução é:  Tempo: 5043

Este exemplo é quase igual ao anterior, a unica diferença que a variável result agora é do tipo Wrapper Long e não long primitiva, após a execução notamos um tempo superior ao do primeiro exemplo.

Acontece que o operador += só pode ser usado em operações de tipos primitivos, e em nosso exemplo a variável result é uma Wrapper, e neste caso a JVM é obrigada a realizar a operação de Autoboxing, deixando o laço mais lento.

Conclusão


O uso de Wrapper e Primitivos deve ser analisado em cada cenário, levando em consideração as operações que serão executadas, performance, cálculos, entre outros fatores.

Os recursos de Autoboxing e Unboxing são muito bons e deixaram a criação e manipulação de objetos mais produtiva, mas sempre devemos nos atentar para não utilizar em lugares onde poderemos ter problemas de performance.

Até mais.

Código Fonte

Referências


Ferramentas Gráficas para MongoDB

Olá pessoal, hoje iremos analisar algumas ferramentas gráficas para utilização do banco de dados MongoDB.

As Ferramentas

Em banco de dados relacionais é comum interagirmos com os databases por meio de alguma ferramenta gráfica, por exemplo, com PostgreSQL podemos usar o pgadmin, com Oracle temos o SQL Developer, entre outras.

Com MongoDB, além do tradicional console, temos várias opções no mercado, sendo elas open source ou pagas, vou listar 2 que venho utilizando:
  • Robo3T (conhecido como Robomongo);
  • NoSQLBooster for MongoDB.


Robo3T

Esta foi a primeira ferramenta na qual tive contato ao entrar no mundo do MongoDB, anteriormente era conhecida como RoboMongo, ela possui uma interface simples e de fácil utilização e está disponível para Linux. Mac e Windows.


Interface inicial do Robo3T.

Uma das grandes vantagens que vejo nesta ferramenta é a facilidade de realizar consulta e visualizar os dados, para isso basta clicar sobre uma coleção e a consulta já será realizada fornecendo diferentes opções de visualização, sendo em tree, table ou json. 

Visualização de dados de uma coleção.

Esta é uma ferramenta que venho utilizo bastante, e que também possui uma boa aceitação pelo comunidade de desenvolvimento.

NoSQLBooster for MongoDB

Esta ferramenta é mais robusta e com vários recursos, sua interface lembra uma IDE, onde temos vários recursos interessantes mesmo utilizando a versão free, esta disponível para Linux, Mac e Windows.



Interface inicial do NoSQL Booster for MongoDB.

Até o momento possui uma edição free para uso pessoal/comercial mas com funções limitadas, para detalhes sobre licença e termos de uso, consulte o site oficial da ferramenta.

Detalhes sobre versão e descrição de licença.

No site existe listas de comparação de features disponíveis em cada versão, vale a pena analisar e definir qual versão se adapta melhor a sua necessidade:


A visualização dos dados é bem detalhada, possuindo recursos bem interessantes como exportação, manipulação de dados direto no grid, entre outras. 

Visualização de dados de uma coleção.

A ferramenta possui um recurso bem interessante, ao clicar sobre uma coleção ou index será exibido informações administrativas, como tamanho em disco, engine, etc, isso ajuda bastante quando temos que analisar recursos utilizados pelo database.

Visualizando detalhes da coleção.

Conclusão

Existem várias outras ferramentas disponíveis no mercado, listei as 2 que tenho experiência, e atualmente tenho utilizado, acredito que vale a pena realizar testes e ter ambas em seu ambiente, dessa forma será aproveitado o melhor de cada uma delas.


Referências