/exemplo

Organização básica de projeto em Java (um ponto de partida)

Primary LanguageJava

Build Status SonarCloud Status Known Vulnerabilities Maven Central

Escopo, pré-requisitos e objetivo

Projeto que serve de referência para o desenvolvimento de software em Java.

É um projeto proposto para ser clonado e reutilizado, faz uso de Spring Boot 3, JDK 17 (exigido) e Maven 3.8.6.

Há um conjunto relativamente extenso de ferramentas para avaliação do código do projeto, o que é um bom ponto de partida para implementação de DevOps.

Para ilustrar o projeto inclui: (a) uma biblioteca formada por um único método que identifica o dia da semana para uma data fornecida; (b) uma aplicação que oferece tal funcionalidade via linha de comandos e (c) uma RESTFul API ambas para acesso à funcionalidade da biblioteca.

Objetivo: ilustrar uma organização de código em Java usando "boas práticas" para inspirar projetos reais.

Iniciando...

  • git clone https://github.com/kyriosdata/exemplo
  • cd exemplo

Agora você poderá executar os vários comandos abaixo.

Pré-requisitos

  • mvn --version
    você deverá ver a indicação da versão do Maven instalada e a versão do JDK, dentre outras. Observe que o JDK é obrigatório, assim como a definição das variáveis de ambiente JAVA_HOME e M2_HOME.

Limpar, compilar, executar testes de unidade e cobertura

  • mvn clean
    remove diretório target

  • mvn compile
    compila o projeto, deposita resultados no diretório target

  • mvn test
    executa todos os testes do projeto. Para executar apenas parte dos testes, por exemplo, aqueles contidos em uma dada classe execute mvn -Dtest=NomeDaClasseTest test. Observe que o sufixo do nome da classe de teste é Test (padrão recomendado). Para executar um único teste mvn -Dtest=NomeDaClasseTest#nomeDoMetodo test.

  • mvn verify -P cobertura
    executa testes de unidade e produz relatório de cobertura em target/site/jacoco/index.html além de verificar se limite mínimo de cobertura, conforme configurado, é satisfeito.

Produzindo código executável (depende da JVM)

  • mvn package
    gera arquivo exemplo.jar no diretório target. Observe que o arquivo gerado não é executável. Um arquivo jar é um arquivo no formato zip. Você pode verificar o conteúde deste arquivo ao executar o comando jar vft exemplo.jar.

  • mvn package -P executavel-dir
    gera exemplo-dir.jar, executável, mas dependente do diretório jars, também criado no diretório target. Para executar basta o comando java -jar target/exemplo-dir.jar. Observe que se o diretório jars for removido, então este comando falha. Por último, o diretório jars deve ser depositado no mesmo diretório do arquivo exemplo.jar. A execução deste arquivo refere-se à aplicação via linha de comandos.

  • mvn package -P executavel-unico
    gera jar executável correspondente ao aplicativo a ser executado via linha de comandos, em um único arquivo, target/exemplo-unico.jar, suficiente para ser transferido e executado. Para executá-lo basta o comando java -jar target/exemplo-unico.jar.

  • mvn package -P api
    gera jar executável juntamente com todas as dependências reunidas em um único arquivo, target/api.jar. Este arquivo jar pode ser transferido para outro diretório ou máquina e ser executado pelo comando java -jar target/api.jar.

A execução e exemplos de chamadas são fornecidos na seção seguinte.

Executando a aplicação e a RESTFul API

  • mvn exec:java -Dexec.mainClass="nome.completo.Classe" -Dexec.args="arg1 arg2"
    executa o método main da classe indicada na configuração do plugin pertinente no arquivo pom.xml. Depende de mvn compile.

  • java -jar target/exemplo-unico.jar
    executa o aplicativo por meio do arquivo jar criado pelo comando mvn package -P executavel-unico, conforme comentado anteriormente. Observe que o comando anterior e o corrente produzem o mesmo efeito, contudo, o arquivo jar permite que seja enviado para um outro diretório ou outro computador, onde pode ser executado, enquanto o comando anterior (acima) exige, inclusive, a disponibilidade do Maven (o que pode ser útil em tempo de desenvolvimento).

  • java -jar target/api.jar ou ainda mvn spring-boot:run
    coloca em execução a API gerada por mvn package -P api na porta padrão (8080). Para fazer uso de porta diferente use java -jar -Dserver.port=9876 target/api.jar, por exemplo. Requisições podem ser submetidas conforme abaixo:

Produzindo código executável (native image) (em testes)

  • Depende de GraalVM.
  • JDK 17
  • Visual Studio (Windows)
  • mvn -P native native:compile

Documentação

  • mvn javadoc:javadoc
    produz documentação do projeto depositada em target/site/apidocs/index.html. Este comando está configurado para o JDK 9.

  • mvn jxr:jxr
    Produz documentação do código fonte depositada em target/site/xref/index.html.

Análise estática

Trata-se da análise do código sem que seja executado. Esta análise produz uma "noção de quão bom" está o código sob alguns aspecto e, em consequência, permite orientar eventuais ações de melhoria. Fique atento, "sair bem" na análise estática não significa que "agrada usuários". A análise estática observa o código.

Todas estas análises devem ser realizadas em todos os projetos? Não! Aquelas relevantes para um dado projeto deverão ser configuradas em conformidade com o contexto em questão.

  • Checkstyle

    • mvn checkstyle:checkstyle
      gera análise de estilo em target/site/checkstyle.html. Observe que o uso do plugin jxr é necessário para geração de relatório do código fonte referenciável pelo relatório gerado pelo Checkstyle. Contudo, o uso do jxr não é obrigatório.

    • mvn checkstyle:check
      faz com que o build falhe se pelo menos um estilo é violado

  • Dependency Check (vulnerabilidades)

    • mvn verify -P owasp
      análise de vulnerabilidades depositadas em target/dependency-check-report.html. A primeira execução é relativamente "longa", esteja preparado para esperar...
  • JavaNCSS

    • mvn javancss:check
      verifica limites de complexidade ciclomática (CC) e de linhas de código sem comentário (NCSS). Este comando depende da compilação prévia, ou seja mvn compile

    • mvn javancss:report
      gera relatório em target/site/javancss.html e também depende de compilação prévia, ou seja, mvn compile

  • JDepend

    • mvn jdepend:generate
      gera relatório de algumas métricas, inclusive presença de ciclos em target/site/jdepend-report.html
  • PMD

    • mvn jxr:jxr pmd:pmd
      gera relatório em target/site/pmd.html. Observe que o uso do plugin jxr é necessário para geração de relatório do código fonte referenciável pelo relatório perado pelo PMD. Contudo, o uso do jxr não é obrigatório.

    • mvn pmd:check
      falha se pelo menos uma regra é violada

    • mvn jxr:jxr pmd:cpd
      gera relatório de duplicidades encontradas. Observe que o uso do plugin jxr é necessário para geração de relatório do código fonte referenciável pelo relatório gerado pelo PMD. Contudo, o uso do jxr não é obrigatório. O resultado é depositado no arquivo target/site/cpd.html.

  • Spotbugs

    • mvn spotbugs:spotbugs
      detecção de bugs. Resultado em target/spotbugs.html.
    • mvn spotbugs:check
      apenas verifica se há erros
    • mvn spotbugs:gui
      abre GUI para exibir bugs após mvn spotbugs:spotbugs
  • Spotbugs (security)

    • mvn spotbugs:spotbugs -P security
      detecção de bugs. Resultado em target/spotbugs.html.
    • mvn spotbugs:check -P security
      apenas verifica se há erros
    • mvn spotbugs:gui -P security
      abre GUI para exibir bugs após mvn spotbugs:spotbugs -P security
  • Snyk

    • mvn snyk:test -P security
      Realiza a análise de vulnerabilidade oferecida pelo serviço Snyk. Defina a variável de ambiente SNYK_TOKEN com o valor do token de acesso ao serviço.

    • mvn snyk:monitor -P security
      Disponibiliza relatório em snyk.io (atualiza badge)

Relatório do projeto

  • mvn package site -P cobertura
    Gera documentação do projeto, incluindo relatórios de análises estáticas em target/site/index.html.

  • mvn site:run executa serviço que disponibiliza em http://localhost:8080 a documentação gerada no passo anterior.

Disponibilizando biblioteca no repositório Maven Central

A boa notícia é que este pom.xml está devidamente configurado para publicação no Maven Central, contudo, depende de outras ações e da configuração do arquivo HOMEDIR/.m2/settings.xml.

  • Nexus Staging Maven Plugin
    • mvn deploy -P deploy

A publicação usando o Maven Central é mais complexa do que a alternativa recente oferecida pelo JitPack, ou até mesmo pelo Github Packages, por exemplo.

Dependências

O desenvolvimento de código em Java, em geral, usufrui de um significativo conjunto de bibliotecas e frameworks. Esta reutilização é incorporada em um projeto por meio de dependências. Gerenciá-las torna-se necessário e há dois plugins úteis para tal. Consulte a documentação deles para outros além daqueles ilustrados abaixo: Version Maven Plugin (aqui) e Apache Maven Dependency Plugin (aqui).

  • mvn versions:display-dependency-updates
    Lista dependências para as quais há versões mais recentes do que aquelas empregadas.

  • mvn versions:display-plugin-updates
    Lista plugins para as quais há versões mais recentes do que aquelas empregadas.

  • mvn dependency:analyze
    Analisar as dependências de um projeto. Dependência citada mas não utilizada, dentre outras situações são relatadas por meio desta análise.

  • mvn dependency:purge-local-repository
    limpa dependências do projeto em questão do repositório local e obtém dependências novamente. Útil quando o repositório local é corrompido.

  • mvn dependency:copy-dependencies
    Copia dependências do projeto para o diretório target/dependency.

Banco de Dados H2

Nos cenários onde é feito uso de um banco relacional, aqui são oferecidos recursos para desenvolvimento usando o H2 (https://www.h2database.com).

  • mvn exec:java -P start-shell-h2
    Abre/cria banco para uso via linha de comandos. Para criar o banco de nome bancoNome no diretório dir forneça jdbc:h2:<dir>/bancoNome. Se existir, apenas será aberto. Adicionalmente, forneça como driver a classe org.h2.Driver. Você pode fazer uso do diretório de sua preferência, contudo, a sugestão é criar o banco no diretório target (usado pelo comando seguinte). Na shell que é aberta, digite create table teste (id int primary key, nome varchar(255)); para criar uma tabela de teste. Para inserir um registro, digite insert into teste values (1, 'teste');. Para listar os registros, digite select * from teste;. Para sair, digite exit.

  • mvn exec:java -P start-h2-dev-in-target
    Este comando abre uma interface gráfica, via browser, no endereço http://localhost:8082 com permissão para criar bancos no diretório target. Ou seja, é uma opção apenas para experimentação e durante desenvolvimento. Observe que o comando anterior permite interagir com o banco via linha de comandos. Este comando, ao contrário, assume que o banco a ser aberto está no diretório target. Quando fornecer a URL, use . para representar tal diretório.

Outros recursos

  • mvn help:effective-pom
    exibe POM de fato empregado

  • mvn help:describe -Dcmd=clean
    exibe detalhes da fase clean

Integração contínua

Notou os emblemas (badges) no início da página? Todo commit na presente página automaticamente irá realizar uma série de operações, como compilação, execução dos testes de unidade e várias análises estáticas. O resultado geral é imediatamente acessível por meio dos emblemas (clique neles), onde detalhes são disponibilizados nas páginas correspondentes. Observe que isso se transforma em um significativo instrumento de visibilidade do projeto.

Para projetos open source os serviços oferecidos são gratuitos. Seguem aqui os merecidos agradecimentos a:

A lista acima não tem a pretensão de ser exclusiva. Abaixo seguem outros serviços: