Gastaldi's Blog

Mais um blog sobre Java …

Arquivos Mensais: dezembro 2008

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.

Anúncios

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.