Gastaldi's Blog

Mais um blog sobre Java …

Proposta de Design By Contract com Hibernate Validator

Há um tempo atrás, tive uma idéia de aplicar um Design by Contract através de anotações do Hibernate Validator, ou seja, permitir que durante a chamada de um parâmetro, fosse possível realizar validações dos parâmetros em si, e não apenas do estado da classe, algo assim:

public class Calculator {

   public int add(
      @NotNullParam(mssage="Parametro {1} não deve ser nulo !")
      @Positive(message = "Parametro {1} deve ser positivo. Atual: {0}")
      Integer a,

      @NotNullParam
      @Positive(message = "Segundo Parametro: {0}")
      Integer b) {

      return a + b;
   }
}

Assim, quando o método fosse chamado, a validação ocorreria nos parâmetros informados em tempo de execução.
Você pode conferir o código completo da implementação aqui.

Em tempo, encontrei um post do Ricardo Ferreira no seu blog Architecture Journal sobre o Spring DBC, uma nova proposta para subprojeto Spring criada por ele muito interessante : Introdução ao Spring DBC.

Plugins Maven para JIRA

O JIRA é uma ferramenta de issue tracking bastante usado em muitas empresas.
Porém, que muitas empresas precisam é de uma integração maior com as ferramentas de desenvolvimento, principalmente com o Maven.
Para tanto, criei um projeto no google code contendo plugins Maven que integram com o WebService do JIRA. Um dos plugins cria versões no JIRA conforme a versão especificada no pom.xml

Link para quem Quiser Conferir: http://code.google.com/p/jira-maven-plugins/

Tuning and Slimming JBossAS

Este link contém informações de como “tunar” o seu JBoss para obter o máximo de performance:

Tuning and Slimming JBossAS

Acessando o HttpServletRequest no LoginModule (JAAS)

Alguma vez você já precisou acessar um objeto HttpServletRequest dentro de um LoginModule no JAAS ? Para quem não conhecia (isso me inclui !), é necessário utilizar a API JACC (Java Authorization Contract for Containers) :


import javax.security.jacc.PolicyContext;
import javax.security.jacc.PolicyContextException;

   /** The JACC PolicyContext key for the current Subject */
   public static final String WEB_REQUEST_KEY = "javax.servlet.http.HttpServletRequest";

   HttpServletRequest request = (HttpServletRequest) PolicyContext.getContext(WEB_REQUEST_KEY);

Ah ! Essa dica vale para o Glassfish e o JBoss (os servidores de aplicação que testei até então) !

Link: http://www.jboss.org/community/docs/DOC-9048

Criando um cliente REST para Código de barras 2D

De acordo com a wikipédia, um código de barras 2D pode ser usado para capturar informações  (sejam elas impressas, ou disponíveis na tela do seu computador) usando a câmera de um celular comum (com um software especial instalado).

Existem muitos sites online que já oferecem gratuitamente este serviço para geração de uma imagem PNG a partir de um texto. Com a ajuda do RESTEasy, podemos criar um cliente REST que, passados os devidos parametros, gere essa imagem sem preocuparmos com a comunicação HTTP.

Para esse exemplo, escolhi usar o serviço disponível em http://qrcode.kaywa.com/, mas você pode utilizar a API do Google Chart para o mesmo.

Primeiro criamos a interface:

public interface QRCodeClient {

    @GET
    @Produces("image/png")
    public byte[] createImage(
            @QueryParam("s") int size, 
            @QueryParam("d") String text);
}

Podemos criar uma classe utilitária para utilizar somente as APIs padrão REST

import javax.ws.rs.core.MultivaluedMap;

import org.jboss.resteasy.client.ProxyFactory;
import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
import org.jboss.resteasy.spi.ResteasyProviderFactory;

public class RestHelper {
    static {
        // this initialization only needs to be done once per VM
        ResteasyProviderFactory.initializeInstance();
        RegisterBuiltin.register(ResteasyProviderFactory.getInstance());
    }

    /**
     * Cria um mapa de acordo com a implementacao REST
     * @return
     */
    public static MultivaluedMap<String, String> createMultivaluedMap() {
        return new MultivaluedMapImpl<String, String>();
    }

    /**
     * Cria um client usando Apache HTTP Client.
     * Mais informacoes em http://wiki.jboss.org/wiki/RESTeasyClientFramework
     * @param &lt;T&gt;
     * @param clientClass
     * @param restURL
     * @return
     */
    public static <T> T createClient(Class<T> clientClass, String restURL) {
        if (!clientClass.isInterface()) {
            throw new IllegalStateException("Client Class must be an interface !");
        }
        return ProxyFactory.create(clientClass,restURL);
    }

}

Por último, podemos testar nosso cliente REST com uma classe qualquer:

QRCodeClient client = RestHelper.createClient(QRCodeClient.class, "http://qrcode.kaywa.com/img.php");
byte[] img = client.createImage(5, "Oi Mundo REST !!!");

O Array de bytes será o conteúdo de uma imagem PNG. Note que não foi necessário implementar nenhum código HTTP para gerar a imagem : O RESTEasy já faz isso pra você.

Essa é uma das várias utilidades da tecnologia REST. Algo muito bacana que realmente vicia.

Definindo um arquivo de log por aplicação no JBoss

Em muitas instalações de JBoss(es) que encontro por aí, sempre surge uma dúvida (bastante comum): Como fazer com que o JBoss gere um arquivo de log por aplicação ? Na verdade não existe uma receita simples.

A solução que mostro a seguir, utiliza um conceito bastante interessante da API Log4J, que é o uso da interface RepositorySelector (mais informações aqui e neste excelente artigo).

Existe até um chamado no JIRA aberto para que permita a integração de RepositorySelector(s) no JBoss (algo que deve ser incorporado na versão 5.0 do JBoss AS).

Você pode baixar o código fonte alterado aqui.

O chamado descreve a criação de um SAR para permitir que aplicações que possuam o arquivo log4j.properties ou log4j.xml, utilizem-no ao invés de utilizar a estrutura definida no jboss-log4j.xml. No entanto, não queremos modificar nossas aplicações para adaptar configurações de logging. Até porque isto seria um trabalho extremamente tedioso, e propenso a erros (O que garante, por exemplo, que o caminho dos logs a serem gravados não mude em outra máquina ?).

Logo, uma saída seria a de colocar a configuração de log no jboss-log4j.xml.

Tomando como base uma aplicação empacotada como “teste.war”:

1) Configure o log4j para conter o seu appender e a category


<appender name="FILE_teste" class="org.jboss.logging.appender.DailyRollingFileAppender">
<errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
<param name="File" value="${jboss.server.log.dir}/teste/teste.log"/>
<param name="Append" value="false"/>
<param name="Threshold" value="INFO"/>
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority &#91;Category&#93; Message\n -->
<param name="ConversionPattern" value="%d %-5p &#91;%c&#93; %m%n"/>
</layout>
</appender>

<category name="teste" additivity="false">
<priority value="INFO"/>
<appender-ref ref="FILE_teste"/>
</category>

OBS:O Category DEVE ter o mesmo nome do WAR. Isso porque o código do SAR utiliza o mesmo nome do WAR para buscar a categoria selecionada. A flag additivity significa que não iremos utilizar a configuração do RootLogger.

2) Faça um deploy do SAR (codigo fonte aqui – compile com maven)

Faça o deploy rodando o comando:

mvn clean package jboss:harddeploy

Desta forma o arquivo será automaticamente compilado e jogado para um jboss local.

3) Inicie o JBoss

Você verá a saída da sua aplicação no seu novo appender.