quinta-feira, 3 de novembro de 2022

Pegando um arquivo de uma URL com Java usando Proxy

      As vezes nem tudo é tão simples. No artigo anterior eu mostrei como pegar um arquivo com Java a partir de uma URL, porém na maioria das empresas para se ter acesso a internet é preciso usar um proxy devido a configurações de segurança e tal. Então para acessar arquivos de URLs sem usar proxy provavelmente só vai rolar se for de URLs internas da empresa. Mas calma, usar o proxy muda pouca coisa no nosso código e vou seguir com os mesmos exemplos. Como no artigo anterior isso pode ser aplicado a um PDF, uma imagem, etc. Vou mostrar uma forma apenas com Java puro e outra que usa o org.apache.commons.io.IOUtils para copiar do InputStream para o OutputStream.

      No problema em questão a necessidade original era buscar um arquivo e retorná-lo em memória para um método que irá guardá-lo no banco de dados.

       Segue o exemplo de código apenas com o Java puro:

try {
    URL url = new URL("http://www.pdf995.com/samples/pdf.pdf");
    
    //cria o proxy com ip e porta do proxy
    URLConnection openConnection = url.openConnection(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("ip_do_proxy", 8080)));
    
    // muda a chamado do stream
    InputStream in = new BufferedInputStream(openConnection.getInputStream());
    ByteArrayOutputStream out = new ByteArrayOutputStream();
   
    byte[] buf = new byte[121072]; //quantidade de bytes lida por vez
    int i = 0;
   
    while (-1 != (i = in.read(buf))){
         out.write(buf, 0, i);
    }
   
    out.close();
    in.close();
   
    byte[] dadosRecebidos = out.toByteArray();
           
    File pdf = File.createTempFile("nomedoc"".pdf"); //cria arquivo temporário
    FileOutputStream fos = new FileOutputStream(pdf); // passa o arquivo para o fos
    fos.write(dadosRecebidos); //escreve os dados no arquivo criado
    fos.close();
                 
    return pdf;
                 
           
catch (Exception e) {
    e.printStackTrace();
}

       Segue o exemplo usando o apache commons:

try {
    URL url = new URL("http://www.pdf995.com/samples/pdf.pdf");

    //cria o proxy com ip e porta do proxy
   URLConnection openConnection = url.openConnection(new Proxy(Proxy.Type.HTTPnew InetSocketAddress("ip_do_proxy", 8080)));

    InputStream in = new BufferedInputStream(
openConnection.getInputStream());
   
    File pdf = File.createTempFile("nomedoc"".pdf"); //cria arquivo temporário
    FileOutputStream fos = new FileOutputStream(pdf); // passa o arquivo para o fos
       
    IOUtils.copy(in, fos); // usando org.apache.commons.io.IOUtils para passar os dados para o arquivo
   
    in.close();
    fos.close();
    return pdf;
 
catch (Exception e) {
    e.printStackTrace();
}

       Para este artigo é isso. Se quiser saber como fazer sem o proxy está aqui o artigo:

Pegando um arquivo de uma URL com Java

Pegando um arquivo de uma URL com Java

     Nesse artigo vou mostrar como ler um arquivo de uma URL. Isso pode ser aplicado a um PDF, uma imagem, etc. Vou mostrar uma forma apenas com Java puro e outra que usa o org.apache.commons.io.IOUtils para copiar do InputStream para o OutputStream.

      No problema em questão a necessidade original era buscar um arquivo e retorná-lo em memória para um método que irá guardá-lo no banco de dados.

       Segue o exemplo de código apenas com o Java puro:

try {
    URL url = new URL("http://www.pdf995.com/samples/pdf.pdf");
    InputStream in = new BufferedInputStream(url.openStream());
    ByteArrayOutputStream out = new ByteArrayOutputStream();
   
    byte[] buf = new byte[121072]; //quantidade de bytes lida por vez
    int i = 0;
   
    while (-1 != (i = in.read(buf))){
         out.write(buf, 0, i);
    }
   
    out.close();
    in.close();
   
    byte[] dadosRecebidos = out.toByteArray();
           
    File pdf = File.createTempFile("nomedoc", ".pdf"); //cria arquivo temporário
    FileOutputStream fos = new FileOutputStream(pdf); // passa o arquivo para o fos
    fos.write(dadosRecebidos); //escreve os dados no arquivo criado
    fos.close();
                 
    return pdf;
                 
           
} catch (Exception e) {
    e.printStackTrace();
}

       Segue o exemplo usando o apache commons:

try {
    URL url = new URL("http://www.pdf995.com/samples/pdf.pdf");
    InputStream in = new BufferedInputStream(url.openStream());
   
    File pdf = File.createTempFile("nomedoc", ".pdf"); //cria arquivo temporário
    FileOutputStream fos = new FileOutputStream(pdf); // passa o arquivo para o fos
       
    IOUtils.copy(in, fos); // usando org.apache.commons.io.IOUtils para passar os dados para o arquivo
   
    in.close();
    fos.close();
    return pdf;
 
} catch (Exception e) {
    e.printStackTrace();
}

       Para este artigo é isso.

sábado, 23 de julho de 2022

Como e porquê configurar o cache do Hibernate

Nesse artigo vou trazer algo que vi sobre a importância de fazer uso correto de cache do Hibernate em um artigo do Vlad Mihalcea que deixo no final para que possam acessar e ver outros detalhes como o gráfico que mostra a diferença de tempo entre a consulta que usa e a que não usa o cache.

 

Não vou me prender a demonstração da melhora de performance pois isto está no artigo dele. Aqui quero apenas mostrar a configuração necessária e dizer o porquê configurar o cache de acordo com o tamanho da sua aplicação.

 

As consultas JPQL são compiladas antes da execução, e como sabemos, há um custo para se compilar um código. Então, caso o cache não esteja configurado corretamente, todas as vezes que as consultas forem executas elas serão compiladas, gerando sempre esse custo adicional. As consultas usando Criteria API também passam por esse impacto porque são transformadas em JPQL;

 

Por padrão o Hibernate coloca 2048 consultas no cache, mas se seu sistema for muito grande isso pode não ser suficiente.

 

A propriedade que trata dessa configuração é a hibernate.query.plan_cache_max_size. Basta calcular quantas consultas seu sistema tem e configurar essa propriedade para atender essa demanda. Lembrando que o cache não armazena apenas JPQL, então o valor precisa ser a soma de todas as consultas do sistema.

 

No caso que Native Queries, embora não haja esse processo de compilação, o hibernate guarda metadados sobre os parâmetros passados, e a configuração desse cache é feita na propriedade hibernate.query.plan_parameter_metadata_max_size. O valor default é 128, mas como mostrado no artigo do Mihalcea, a diferença para Native Queries não é tão grande com ou sem o cache configurado.


Você pode configurar essas propriedades no persistence.xml como abaixo:


<persistence>
    <persistence-unit name="my-persistence-unit">
        ...
        <properties>
            <! – consultas - default: 2048 – >
            <property name="hibernate.query.plan_cache_max_size" value="4096"/>
            <! – metadados - default: 128 – >
            <property name="hibernate.query.plan_parameter_metadata_max_size"
                value="256"/>
        </properties>
    </persistence-unit>

</persistence>


Fonte: https://vladmihalcea.com/hibernate-query-plan-cache/

quinta-feira, 16 de junho de 2022

Visualizando processos Java rodando em um ambiente Linux com os comandos TOP e PS

Nesse artigo eu vou mostrar duas formas de exibir os processos Java que estão rodando em uma máquina Linux. Isso é muito importante pra ver de forma rápida quantidade de uso de memória, quantidade de intâncias de aplicações rodando, parâmetros passado para JVM, tempo de atividade de cada processo, etc.

 

A primeira é mais resumida, onde as principais informações que vamos ter são: número do processo, usuário responsável, tempo de execução e memória em uso. Para isto basta executar o comando:

 

$ top -bc -n 1 |grep java

 

A segunda é mais longa pois além das informações da primeira, ela também mostra os argumentos passados para a JVM, o que pode ser muito útil quando precisamos ver se alguma configuração feita realmente está sendo utilizada.

 

$ ps aux | grep -i java


        Para esse artigo é só, espero que ajude no dia a dia das atividades de monitoramento e manutenção das aplicações.

quinta-feira, 2 de junho de 2022

Matriz de Rastreabilidade - Mapeando os impactos das alterações do sistema

 

Nesse artigo eu falar sobre Matriz de Rastreabilidade. Essa matriz é um gráfico que mostra a dependência entre partes do sistema.

 

         O objetivo é ter uma ferramenta visual de rápida identificação de áreas que precisam ser testadas para evitar erros em produção devido à falta de testes suficientes após alterações que parecem pontuais, mas na verdade tem um impacto maior.

 

         A matriz possui 2 eixos: Manutenção e Impacto; e é construída colocando o nome dos módulos do sistema (ou partes importantes que se deseja controlar, como por exemplo, um método que é muito usado) em ambos os eixos, e depois marcando os pontos onde há dependências.

 

         Aqui abaixo tem um exemplo:

 


 

         A matriz de rastreabilidade pode ser feita por qualquer pessoa da equipe, mas um DEV tem maior conhecimento dessas dependências e pode dar uma grande ajuda.

 

Essa matriz pode ser bem grande dependendo do tamanho do sistema e do nível de detalhes, que pode mudar de acordo com a necessidade, por exemplo, pode ser mapeado módulos mas também classes ou métodos muito utilizados.

 

Deve ser atualizada sempre que novas dependências forem encontradas e estar disponível para a equipe de testes e homologação calcular o que testar e ter uma ideia do tempo dos testes.

segunda-feira, 16 de maio de 2022

Erro "Invalid secret key format" ao iniciar o Jboss na migração do Java da Oracle para o OpenJDK

         Neste artigo vou mostrar a solução para o erro java.io.IOException: Invalid secret key format, que ocorre ao usar o Vault do Jboss para armazenar senhas criptografadas. Esse erro ocorre no módulo PicketBox, que é um framework de segurança Java para prover aos desenvolvedores as seguintes funcionalidades:


  • Suporte a autenticação;
  • Suporte a autorização;
  • Suporte a auditoria;
  • Etc.


        Ao usar o OpenJDK o módulo Picketbox não tem acesso ao módulo "sun.jdk", então ele não pode usar a classe "com.sun.crypto.provider.SealedObjectForKeyProtector", ocasionando em um dos erros abaixo: 


Caused by: java.io.IOException: Invalid secret key format
    at com.sun.crypto.provider.JceKeyStore.engineLoad(JceKeyStore.java:856)
    at java.security.KeyStore.load(KeyStore.java:1445)
    at org.picketbox.util.KeyStoreUtil.getKeyStore(KeyStoreUtil.java:201)
    at org.picketbox.util.KeyStoreUtil.getKeyStore(KeyStoreUtil.java:151)
    at org.picketbox.plugins.vault.PicketBoxSecurityVault.getKeyStore(PicketBoxSecurityVault.java:688)
    ... 11 more

ou

  Caused by: java.io.IOException: Invalid secret key format
  at com.sun.crypto.provider.JceKeyStore.engineLoad(JceKeyStore.java:856)
  at java.security.KeyStore.load(KeyStore.java:1445) [rt.jar:1.8.0_191-1-redhat]
  at org.wildfly.security.credential.store.impl.KeyStoreCredentialStore.load(KeyStoreCredentialStore.java:859) [wildfly-elytron-1.6.1.Final-redhat-00001.jar:1.6.1.Final-redhat-00001]
  ... 11 more

        

        Para corrigir o problema, é necessário adicionar ao PicketBox a dependência ao "sun.jdk", no arquivo %JBOSS_HOME%/modules/system/layers/base/org/picketbox/main/module.xml a seguinte linha:


<module name="sun.jdk"/>


            Pode-se também adicionar um parametro na JVM da seguinte forma:


-Djboss.modules.system.pkgs=org.jboss.byteman,com.sun.crypto.provider           


         Dessa forma, o módulo em questão é carregado e o uso do Vault e criptografia do JBoss funciona normalmente como no JDK da Oracle. A partir da versão 7.1 do JBoss EAP esse problema foi corrigido, a primeira solução que mostrei já vem por padrão. 



Fonte:

https://picketbox.jboss.org/

http://www.mastertheboss.com/jbossas/jboss-security/solving-java-io-ioexception-invalid-secret-key-format/

https://issues.redhat.com/browse/JBEAP-14660

 

quarta-feira, 4 de maio de 2022

Criando um link simbólico para um diretório no Linux

          Nesse artigo vou mostrar como links simbólicos no Linux. Links simbólicos servem para apontarmos para um diretório ou arquivo de outro lugar. Para isso usamos o comando ln:

 

$ ln -sf /diretorioOrigem /diretorioLink

 

No parâmetro “-sf” o s é para especificar que vai ser um link simbólico e o f é pra forçar a criação caso o destino já seja um link simbólico. 

terça-feira, 3 de maio de 2022

Mudando usuário e grupo de um arquivo no Linux (chown e chgrp)

         Nesse artigo vou mostrar como mudar o proprietário de pastas e arquivos no Linux. Vamos imaginar que temos a pasta /home/usuario/meus_arquivos e queremos atribuir a um usuário e grupo específicos estes arquivos arquivos:

 

Para isso usamos o comando chown:

 

chown -R nomeUsuario:nomeGrupo /home/usuario/meus_arquivos/

 

O parâmetro “-R” é para aplicar de modo recursivo, assim ele vai alterar as pastas, subpastas e arquivos que existirem na pasta definida. Logo em seguida vem o nome do usuario e nome do grupo que serão atribuídos como donos e são separados por ":" (dois pontos)  e depois a pasta a ter o dono alterado. Não é necessário informar o grupo caso queira mudar só o usuário, e se quiser mudar só o grupo use o chgrp.


Isso é bastante usado no Linux pois determina quem pode fazer determinadas coisas com os arquivos sem ter que dar permissões para todo mundo.

terça-feira, 12 de abril de 2022

Glowroot - Ferramenta grátis para profiling remoto de aplicações Java

       Hoje vou apresentar uma ferramenta de profiling gratuita para aplicações Java, o Glowroot. 
   
    Mas primeiro uma rápida explicação dobre o que é profiling. Profiling é o processo de monitoramento e medição de desempenho das aplicações para manutenção e melhoria de performance e busca de erros que levam a queda do sistema. 
    
    Existe uma vasta variedade de programas que fazem esse tipo de serviço, a maioria deles é pago, e os gratuitos geralmente são bem limitados ou não tem uma interface web para acesso remoto. O Glowroot é uma boa opção porque é gratuito e tem a interface web, facilitando o trabalho. Antes dele eu usava o Jvisualvm que já vem por padrão nas JDKs (até a versão 8 se não me engano) mas é bem limitado e exige que o servidor tenha a parte gráfica habilitada e o acesso direto ao programa. 
    
    O Glowroot permite acompanharmos o uso de memória, mostra as falhas a nível de métodos, permite vermos as consultas mais pesadas da aplicação, etc. Ou seja, uma ferramenta completa e de fácil instalação. 

     A ferramenta pode ser baixada no seguinte endereço: https://glowroot.org/ 
    
    Lá também tem as instruções de instalação. Após instalar o Glowroot, na pasta glowroot vai ser criada uma subpasta de logs e uns arquivos. Para disponibilizar o Glowroot pela web é preciso alterar o endereço de 127.0.0.1 para 0.0.0.0 no arquivo admin.json. 

    A versão disponível nesse endereço é sempre a última, para versões anteriores você pode acessar o repositório do projeto: https://github.com/glowroot/glowroot/releases.

    Você também pode ver uma demo da aplicação rodando como na imagem abaixo:

quinta-feira, 31 de março de 2022

Pegando valores de Propriedades do Sistema e Arquivos de Configuração .properties

           Nesse artigo vou mostrar como pegar valores de propriedades do sistema, seja carregando uma variável de ambiente como as setadas no standalone.xml do JBoss ou de um arquivo de propriedades .properties.

         

Primeiro vamos as variáveis de ambiente como as definidas no standalone.xml. Nesse arquivo, temos uma seção chamada <system-properties> e nela temos as propriedades definidas como:

 

<property name=”chave” value=”valor” />

 

Esses valores podem ser resgatados da seguinte forma:

 

String configDir = System.getProperty("chave");

 

     Geralmente toda aplicação tem também um ou mais arquivos de configuração com a extensão .properties. São arquivos que tem chave e valor também e são separados pelo sinal de “=” (igual). Esses arquivos podem ser carregados da seguinte forma:

 

InputStream in = new FileInputStream("diretorioDoArquivo" + "nomeDoArquivo.properties");

java.util.Properties configuracaoProperties = new Properties();

configuracaoProperties.load(in);

in.close();

 

Depois usa-se assim:

 

configuracaoProperties.getProperty("PalavraChave");

 

Para este artigo é só. Tem algumas outras curiosidades nesse artigo sobre System Properties:

https://jboss-books.gitbooks.io/wildfly/content/configuracao/system-properties/system_properties.html

Compactando arquivos no linux

            Nesse artigo vou mostrar como compactar e descompactar arquivos e diretórios no Linux. Vamos imaginar que temos a pasta /home/usuario/meus_arquivos e queremos compactar seus arquivos:

 

Para compactar, usamos:

 

$ zip -r nomeArquivoZip.zip /home/usuario/meus_arquivos/

 

O parâmetro “-r” é de recursivo, assim ele vai incluir as pastas, subpastas e arquivos que existirem na pasta definida. Logo em seguida vem o nome do arquivo zip que será criado, e depois a pasta a ser compactada.

 

Para zipar apenas alguns arquivos, podemos separar os arquivos por espaço.

 

Agora para descompactar usamos o unzip:

 

$ unzip nomeArquivoZip.zip

 

             Para ver o conteúdo sem descompactar podemos passar o parâmetro -l.