nov 03

Utilizando C3p0 para resolver problemas de falha na conexão com banco

Coloquei uma aplicação no servidor da DailyRazor,  utilizando hibernate com hbm e mysql. Rodando a aplicação localmente no meu tomcat, e apontando para o banco remoto funcionava perfeitamente, porém quando rodava do servidor acessando o banco de dados local, funcionava por um minuto e em seguida a seguinte exceção era lançada: “com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure”. Procurando na internet ( lê-se google) achei vários motivos, que em nada me ajudaram, como por exemplo não permissão de acesso ao banco via TCP/IP, banco fora do ar, etc. Então preferi passar a bola para o pessoal da hospedagem e abri um ticket (Um parenteses aqui: O serviço de suporte do Daily Razor é excelente, resolvem tudo muito rápido.) e logo em seguida foi-me passada a solução: utilizar o C3p0 setando as seguintes configurações no hibernate.cfg.xml:

<property name="hibernate.c3p0.acquire_increment">1</property>
<property name="hibernate.c3p0.idle_test_period">300</property>
<property name="hibernate.c3p0.timeout">120</property>
<property name="hibernate.c3p0.max_size">25</property>
<property name="hibernate.c3p0.min_size">1</property>
<property name="hibernate.c3p0.max_statement">0</property>
<property name="hibernate.c3p0.preferredTestQuery">select 1;</property>


Essa é a configuração default, a única coisa que precisei modificar foi o tempo de timeout, já que eles tem como tempo de timeout para o MySQL 300, segundo eles por questões de estabilidade.
Fica aí a dica, mesmo que não precise recomendo a utilização do C3p0 para pooling de conexão com o banco de dados, pois melhora a performance da aplicação. Nesse blog aqui tem algumas informações a mais.

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 14

Biblioteca de componentes para JSF 2

Venho aqui neste post recomendar apenas, para quem quer utilizar JSF 2, e estava acostumado a utilizar richfaces, que para a versão 2 do JSF não está ainda com versão estável, recomendo o primefaces , que é uma suite de componentes muito completa, de muito fácil utilização. Bastando apenas baixar o jar do primefaces, e adicionar a suas páginas o namespace xmlns:p=”http://primefaces.prime.com.tr/ui”. No site, há um livedemo, que mostra cada componente, e o código de sua utilização.


Um problema apenas que eu tive em utilizá-lo, foi quando tive que usar outro componente que utilizava jquery em mesma página que estivesse utilizando o primefaces, pois como ele utiliza o jquery embutido no jar, ele acaba referenciando o arquivo jquery errado, o que faz com que os componentes não funcionem.

Mas se você não for usar outro componente que utilize jquery também, é uma ótima pedida o primefaces.

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

Hospedar aplicações java

Depois de muito tempo sem postar, resolvi voltar. Vou falar um pouco da experiência que estou tendo em contratar um serviço de hospedagem JAVA. Andei pesquisando e não é muito fácil encontrar algo BBB aqui no Brasil, a mais em conta é a Kinghost, que por 44,00 realzes mensais você consegue uma hospedagem com algumas limitações, mas dá pra brincar  já. Mas , porém, contudo , no entanto, não gosto muito que limitem meus meguetas de espaço, portanto fui procurar por hospedagens fora das terras tupiniquins, achei muitas barganhas, mas nem todas atendiam o que queria, até que achei o Daily Razor que é bem tentador, por um preço menor que a King host, porém com muito mais recursos, logo contratei na mesma hora! Porém, como tudo tem um porém, esse não ficaria pra trás. Assim que foi cobrado meu paypal, tentei descobrir como acessar o painel de controle da hospedagem para subir algumas aplicações para testar, falei com o suporte técnico e para minha surpresa recebi a notícia, para ativar sua conta você precisa ligar para um número nos EUA e confirmar sua conta! Que legal, agora além de pagar pra hospedar tenho que pagar uma baba de conta telefônica. Mas no final acabei não precisando ligar, bastou mandar um e-mail para o departamento de vendas pedindo para ativar a conta que em 10 minutos foi liberado! Agora é usar pra ver como é. Em breve postarei aqui minhas avaliações e recomendações (Or not)!!

out 01

Fazendo richfaces funcionar com JSF no tomcat 6

Depois de muito garimpar  consegui fazer funcionar o richfaces , vou resumir do que precisamos:

1)Baixar os JARs e colocalos no classpath da aplicação

1.1) richfaces-api-3.3.0.GA.jar

1.2)richfaces-impl-3.3.0.GA.jar

1.3)richfaces-ui-3.3.0.GA.jar

1.4)commons-logging-1.1.1.jar

1.5)commons-digester-1.8.jar

1.6)commons-beanutils-1.6.1.jar

2)adicionar ao web.xml do seu projeto o seguinte

<context-param>

<param-name>org.richfaces.SKIN</param-name>

<param-value>blueSky</param-value>

</context-param>

<context-param>

<param-name>org.richfaces.CONTROL_SKINNING</param-name>

<param-value>enable</param-value>

</context-param>

<filter>

<display-name>RichFaces Filter</display-name>

<filter-name>richfaces</filter-name>

<filter-class>org.ajax4jsf.Filter</filter-class>

</filter>

<filter-mapping>

<filter-name>richfaces</filter-name>

<servlet-name>Faces Servlet</servlet-name>

<dispatcher>REQUEST</dispatcher>

<dispatcher>FORWARD</dispatcher>

<dispatcher>INCLUDE</dispatcher>

</filter-mapping>

3) Adicione às suas JSPs

<%@ taglib uri="http://richfaces.org/a4j" prefix="a4j"%>
<%@ taglib uri="http://richfaces.org/rich" prefix="rich"%>

e pronto , agora para mais detalhes sobre como desfrutar desse framework  fenomenal acesse sua documentação .

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.