out 15

Java básico – Convenções de código Java (Parte 1)

Vou começar agora uma série de posts sobre como devemos escrever programas em java, tudo que eu escrever está baseado na Code Conventions para a linguagem de programação Java, ou seja, nada que eu tenha inventado.

Mas é sempre bom ter mais uma fonte de informação sobre um assunto, e em português também!

Comecemos com a seguinte pergunta: Porque programar padronizado?

Primeiramente, padrão é um “como se fazer alguma coisa”, logo quanto mais pessoas fizerem da mesma maneira, mais fácil fica a manutenção desta coisa. Um exemplo prático é: programas duram bastante tempo, desde a etapa de desenvolvimento, testes, homologação e produção. E nem sempre a mesma equipe que começou o desenvolvimento continua até o final da vida de um software, logo, quanto mais padronizado estiver, mais fácil para se dar manutenção e para se entender o que foi feito, ganhando-se assim tempo, e como tempo é dinheiro…


Agora vou falar um pouco dos padrões de arquivo e a estrutura de um arquivo.

Todos os programas em Java contém 2 tipos de sufixo:

  1. .java  – arquivos de código-fonte
  2. .class – arquivos de bytecode java, ou seja, os arquivos fontes compilados.

Um arquivo fonte java deve conter seções de código separadas por linhas em branco e opcionalmente conter comentários que identifiquem cada seção. Não é recomendado que um arquivo fonte tenha mais de 2000 linhas de código.

Este arquivo se estrutura da seguinte maneira:

  • Início dos comentários – deve conter o nome da classe, informação de versão, data, e notas de direito de cópia
/*
 * Nome da classe
 *
 * Informações de versão
 *
 * Data
 *
 * Nota de direitos de cópia
 */
  • Declarações de pacotes e imports – necessariamente nesta ordem.
package java.blah;

import java.blah.blahdy.BlahBlah;
  • Declaração de classes e de interfaces
    • Começamos com os comentários de documentação da classe, contendo a descrição, versão, data e nome do autor.
    • /**
       * Descrição da classe.
       *
       * @versão e data 1.82 18 Mar 1999
       *
       * @autor Nome Sobrenome
       */
    • Em seguida a declaração da classe ou da interface
    public class Blah  {
    • Caso necessário, um comentário sobre a implementação, quando este  não puder ser explicitado no comentário de descrição, por exemplo.
    <em>/* Comentário sobre a implementação da classe */</em>
    • Declaração das variáveis da classe que são as static, onde primeiro se declaram as variáveis public, depois as protected, por conseguinte as de nível de pacote(sem a declaração do modificador de acesso), e por fim as private.
    • /**
      *  comentario de documentacao da varClasse1
      */
      public static int varClasse1;
      
      /**
      *  comentario da varClasse2 que possui
      *  mais de uma linha
      */
      private static Object varClasse2;
    • Declaração das variáveis de instância, seguindo o mesmo padrão das de classe.
    • /**
      * comentario de documentacao da varInstancia1
      */
      public Object varInstancia1;
      
      /**
      * comentario de documentacao da varInstancia2
      */
      protected int varInstancia2;
      
      /**
      * comentario de documentacao da varInstancia3
      */
      private Object[] varInstancia3;
    • Construtores da classe
    • /**
      * comentario de documentacao do contrutor Blah
      */
      public Blah() {
      
      // ...implementação aqui...
      }
    • Métodos – é recomendado agrupar os métodos por funcionalidade, não por escopo ou acessibilidade.
    • /**
      *  comentario de documentacao do metodo fazAlgo
      */
      public void fazAlgo() {
      
      // ...implementação aqui...
      }

É isso por enquanto, no próximo post pretendo abordar as convenções para identação, indentação ou endentação, como preferir, já que esta palavra não existe no português.

out 11

Tratar exceção de unique constraint com JPA 2 e Hibernate

Em uma aplicação simples de cadastro, quando se tem campos únicos, como por exemplo cadastro de usuários, onde o nome do usuário não pode se repetir é interessante mostrar para o usuário qual o erro resultante do não cadastramento dos seus dados. No código abaixo eu tenho uma transação que persistirá um objeto do tipo usuário.

em.getTransaction().begin();
em.persist(usuario);
em.getTransaction().commit();

Porém a exceção lançada pelo JPA 2 é apenas PersistenceException, o que não diz muita coisa. Porém ela contém a cadeia de exceções lançadas desde o provider do banco de dados. Logo, uma alternativa para se descobrir qual a causa raiz da exceção é iterar pela causa da exceção, até chegar a BatchUpdateException, que é a exceção que contém uma SQLException como nextException. Esta SQLException é necessária para se extrair o nome da restrição que gerou a exceção.

catch (PersistenceException e) {

			 Throwable lastCause = e;
			 String constraintName =null;
			 while (lastCause != null){
		    	     if(lastCause.toString().startsWith("java.sql.BatchUpdateException")){
		    		     BatchUpdateException bu = (BatchUpdateException) lastCause;
		    		     constraintName = PersistenceUtil.getViolatedConstraintNameExtracter().
                                                      extractConstraintName(bu.getNextException());

		    	     }
		    	  lastCause = lastCause.getCause();

			  }

			   if(constraintName !=null){
		               throw new ConstraintViolationException("Mensagem",
                                     new SQLException(), constraintName);

		          }
        }

Para se extrair o nome da restrição é necessário utilizar o seguinte código.

public static ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() {

        return EXTRACTER;
   }

	private static ViolatedConstraintNameExtracter EXTRACTER =
           new TemplatedViolatedConstraintNameExtracter() {

	      /**
	       * Extract the name of the violated constraint from the given SQLException.
	       *
	       * @param sqle The exception that was the result of the constraint violation.
	       * @return The extracted constraint name.
	       */
	      public String extractConstraintName(SQLException sqle) {
	         String constraintName = null;

	         int sqlError = Integer.valueOf(JDBCExceptionHelper.extractSqlState(sqle));

	         if(sqlError == 23505){

	            constraintName = extractUsingTemplate("violates unique constraint \"","\"",
                                      sqle.getMessage());
	         }	         

	         return constraintName;
	      }

	   };

Onde ViolatedConstraintNameExtracter é uma interface do pacote org.hibernate.exception e TemplatedViolatedConstraintNameExtracter é a classe abstrata que implementa esta interface.
É necessário implementar o método extractConstraintName(SQLException sqle) herdado da interface.
Nele eu verifico qual o código de erro, utilizando o JDBCExceptionHelper do pacote org.hibernate.exception. No meu caso eu estou utilizando PostgreSQL, e neste endereço: http://www.postgresql.org/docs/8.1/interactive/errcodes-appendix.html temos todos os códigos de erro gerados.
Dependendo do código de erro eu utilizo o método extractUsingTemplate da classe TemplatedViolatedConstraintNameExtracter, passando como parâmetros o padrão da mensagem até o início do nome da restrição, o padrão da mensagem após o nome da restrição e a mensagem da SQLException.

Está um pouco confuso, mas realmente é bem chato tratar essa exceção usando JPA 2, mas basicamente utilizando esses códigos e fazendo as devidas personalizações para a sua aplicação, você conseguirá resolver esse problema.

out 09

Java Básico – Por que utilizar interfaces

Uma interface é basicamente um conjunto de métodos com o corpo vazio. Então você se pergunta, pra que eu quero métodos sem corpo? Vou mostrar um exemplo básico e espero que possam compreender sua utilização.

Digamos que você tenha que desenvolver um aplicativo que simule uma corrida de carros, e na sua equipe temos 3 desenvolvedores(d1, d2 e d3) e um líder de projeto(l1).  E esse líder passa para cada desenvolvedor a responsabilidade de implementar um tipo de carro: d1 desenvolve uma ferrari, d2 uma mclaren e d3 um fusca. O que vai sair disso? Um carnaval de atributos e métodos, cada um vai definir o que achar conveniente, caso o líder não estipule algum padrão. Esse padrão se dá com a utilização da interface.


Um exemplo de uma interface para um carro de corrida seria:

public interface Carro{
     public void acelerar(int incremento);
     public void frear(int decremento);
     public void trocarMarcha(int proximaMarcha);
}

Assim a partir dessa interface uma classe de um fusca poderia ficar da seguinte maneira:

public class Fusca implements Carro{
     int velocidade;
     int marcha;

    public Fusca(){
         this.velocidade = 0;
         this.marcha =0;
    }
    public void acelerar(int incremento){
         this.velocidade += incremento;
    }
    public void frear(int decremento){
         this.velocidade -= decremento;
    }

     public void trocarMarcha(int proximaMarcha){
          this.marcha = proximaMarcha;
     }
}

É isso aí, é bem simples, mas muito útil!

out 07

Bibliotecas no Eclipse

Um detalhe que vou atentar aqui foi um problema que estava passando, e procurando no google a única solução que o pessoal mostrava era  para rever meu classpath.

O problema: CLASS NOT FOUND EXCEPTION de uma classe contida dentro do jar do hibernate. Porém todos os jar estavam direitinho dentro do classpath e também dentro de WEB-INF/lib. O único porém: os arquivos jar estavam dentro de uma subpasta : WEB-INF/lib/hibernate. Isso não dá erro de compilação, gera apenas warning, avisando de possível lançamento da exceção em tempo de execução.

Fica aí a dica: sempre coloque seus jar diretamente abaixo da WEB-INF/lib, nada de querer organizar direitinho por subpastas, pois pode lançar esta exceção, nem sempre ocorre, mas é melhor não correr esse risco!

out 06

Manipulando XML com XStream

Documentos XML são muito utilizados por nós programadores, e as APIs para seu processamento mais famosas(DOM e SAX) são bem úteis e relativamente fáceis de utilizar. Mas quando se trata de agilidade no desenvolvimento do tratamento de XML, não conte com essas APIs. Se você precisa manipular XML e está com o prazo apertado, experimente a biblioteca XStream.No site deles você deve baixar o .jar e também possui alguns exemplos de como utilizar.

Com ela você pode transformar seus documentos XML em objetos java e vice-versa, com pouquíssimas linhas de código.  Basta você criar a sua classe com a estrutura do XML ou a estrutura desejada, necessitando algumas diretrizes, e mandar ele gerar/ler o XML.

Um exemplo simples é o seguinte: quero gerar um documento XML de leiaute para validações. Sua estrutura basicamente é:

<leiaute>
  <metadados>
    <nome></nome>
    <metadado>
      ...
    </metadado>
    <metadado>
     ...
    </metadado>
  </metadados>
</leiaute>

para isso eu crio uma classe ObjXML, uma classe Metadados, e outra Metadado como vistas abaixo:

<code>
public class ObjXML {</code>

  private List conjunto_metadados;

  public List getLeiaute() {
    return conjunto_metadados;
  }

  public void setLeiaute(List metadados) {
    this.conjunto_metadados = metadados;
  }
}

<code>
public class Metadados {
  private String nome;
  private List metadados;</code>

<code>
  public String getNome() {
   return nome;
  }
  public void setNome(String nome) {
    this.nome = nome;
  }
  public List getMetadados() {
    return metadados;
  }
  public void setMetadados(List metadados) {
    this.metadados = metadados;
  }
}
</code>
<code>
public class Metadado {
  private String metadado;</code>

  public String getMetadado() {
    return metadado;
  }
  public void setMetadado(String metadado) {
    this.metadado = metadado;
  }
}

Com isso após tratar o carregamento dos dados no objeto basta escrevermos o seguinte:

<ol>

	<li>XStream xStream = new XStream(new DomDriver());</li>


	<li>File xml = new File("nome_do_arquivo.xml");</li>


	<li>FileOutputStream os = new FileOutputStream(xml);</li>


	<li>xStream.alias("leiaute", objXML.getClass());</li>


	<li>xStream.alias("metadado", Metadado.class);</li>


	<li>xStream.alias("metadados", Metadados.class);</li>


	<li>xStream.addImplicitCollection(objXML.getClass(), "conjunto_metadados");</li>


	<li>xStream.addImplicitCollection(Metadados.class, "metadados");</li>


	<li>xStream.toXML(objXML,os);</li>

</ol>

Na linha 1 instancio um objeto Xstream passando como parâmetro o parser.
Na linha 2 crio o arquivo de saida e na 3 o outputstream para escrever no arquivo.
Nas linhas 4,5 e 6 seto o nome das tags desejadas para minhas classes objXML,Metadados e Metadado. É necessário apenas fazer o alias para a tag raiz do documento.
Nas linhas 7 e 8, eu digo que não quero que as coleções apareçam no documento.
E por fim na linha 9 eu executo o método de criação do arquivo passando o objeto a ser transformado e o arquivo a ser escrito.
E pronto sem muita firula, você consegue gerar um documento XML válido.

out 01

Problemas com Datatable

Vou começar com um pequeno problema , simples porém me levou um tempo para descobrir a solução( méritos para meu caro colega Salomão) . Um pequeno briefing do caso:

Estava eu desenvolvendo uma aplicação simples utilizando JSF + hibernate quando me deparei com um pequeno problema, como passar o objeto listado na linha da minha datatable para uma outra página JSP para possível detalhamento, exclusão ou alteração das propriedades do objeto, o qual é um managed bean. Depois de algumas horas perdidas no google em vão, meu caro amigo Salomão me forneceu a malda, utilizar a tag <f:setPropertyActionListener>. Vou mostrar um exemplo para facilitar o entendimento do uso da tag.

<h:form>

<h:datatable value=”#{usuario.livros}”  var =”livrousu”>

<h:commandLink  value = “#{livrousu.nome}” action=”detalhar”>

<f:setPropertyActionListener value = “#{livrousu.id}” target = “#{livro.id}” />

<f:setPropertyActionListener value = “#{livrousu.nome}” target = “#{livro.nome}” />

<f:setPropertyActionListener value = “#{livrousu.resumo}” target = “#{livro.resumo}” />

</h:commandLink>

</h:datatable>

<h:/form>

Onde livro é um managed bean com escopo REQUEST o qual se relaciona com usuário através de um ArrayList de livros na classe Usuario.
Na tag o atributo value é preenchido com a expressão do atributo do objeto que está sendo listado na datatable e o atributo target é a expressão com o atributo do managed bean Livro que tem escopo Request o qual será setado o valor do objeto listado.
Assim sendo ao clicar no commandLink eu sou levado para a página de detalhamento do livro que irá buscar no Managed Bean Livro suas propriedades, setadas através da tag .

Ainda não consegui descobrir um meio de passar o objeto inteiro, apenas passar seus atributos. Mas isso já resolveu meu problema.

Se alguém souber outros métodos de fazer a passagem de valores através do datatable por favor poste comentários sobre tal.