February 23, 2010

JBoss HornetQ component for Apache Camel (English Version)

In a previous post i wrote about the Apache Camel project. Camel is an excellent solution for system integration. Recently JBoss launched their new product, the new generation of messaging system: HornetQ which i have posted about it. In this post i came to show a very simple component for the integration of Apache Camel with JBoss HornetQ.

This is the very first version of the component and i will improve incrementally. This version is still beta, has some limitations but you'll be able to work with the Camel URI using my component to access the queues and topics of HornetQ.

Download and Usage

You can download the source code from my Subversion repository: http://diegopacheco.svn.beanstalkapp.com/sandbox/trunk/community/hornetq-camel-component once you have downloaded you must install the component using the Apache Maven. Just type in the command line (in the root folder of the project) the following command:
$ mvn clean install

Then you're ready to use the component in your project. In the src/test/java  and src/test/resources folder you have an example of how to use the component with the Apache Camel. I will comment it with more details and the usage.

Once installed in the maven the component you must reference it in the POM or in the classpath of your application(for nom-maven users), in pom use the following dependence:

 
<br><groupId>com.blogspot.diegopacheco.java.sandbox</groupId><br><artifactId>hornetq-camel-component</artifactId><br><version>1.0-SNAPSHOT</version><br>

This component is an extension of the Camel JMS component, most things will work through the inherited object, the URI syntax is the same. The ID of the spring bean registered as a component in the spring context must be used in the camel URI that you use for your routing.

Spring Configuration and Customization

<br /> <bean id="hornetq" class="com.blogspot.diegopacheco.camel.hornetq.component.HornetQComponent" ><br />   <property name="useNettyDefaults" value="true" /><br /> </bean><br />

This is the simplest configuration snippet for the component, that assumes that you want use the netty as a  connector and are using the default port on localhost. You can change this setting to use another connector or even create your custom connector of Netty or whatever you want, it is also possible to pass the Client ID  through the customization, it would be something like the XML below:


<br /> <bean id="hornetq" class="com.blogspot.diegopacheco.camel.hornetq.component.HornetQComponent">  <br /> <property name="connectionFactory"><br /> <bean class="com.blogspot.diegopacheco.camel.hornetq.component.HornetQCamelConnectionFactory"><br /> <property name="transportConfiguration"><br /> <bean class="org.hornetq.api.core.TransportConfiguration" ><br /> <constructor-arg index="0"><value>org.hornetq.integration.transports.netty.NettyConnectorFactory</value> </constructor-arg></bean><br /> </property><br /> </bean><br /> </property>  <br /> </bean><br /> 

Using HornetQ through the Camel URI


Well, now is the moment :D Camel URI usage sample. Take a look at XML snippet below:

<br /> <camelcontext xmlns="http://camel.apache.org/schema/spring" ><br /> <route><br /> <from uri="file://src/test/resources/data?delete=true"/><br /> <to uri="hornetq:queue:topic_hornetq"/><br /> </route><br /> <route><br /> <from uri="hornetq:queue:topic_hornetq"/><br /> <to uri="bean:beanConsumer"/><br /> </route><br /> </camelContext><br />

As you can see I'm using the *hornetq* on the URI, this is the ID of the Spring bean that refers to HornetQComponent. You could use another value here, since this value is the same in which this bean in the spring XML file. It is still possible to use Annotationss for Camel producers and comsumers as the same URI style.

Known Limitations and Future Implementations

This is the first version, it is possible that there are bugs(if you find a bug, you can send email or comment on blog), I know some limitations and things that have not implemented yet, this session will talk a little more about things that i will be implementing in future versions. Limitation(first version): 

  •   Create queues and topics in a dynamic way when they do not exist in HornetQ
  •   Access the HornetQ informing User and password to increase security (now uses the 'guest')
  •   Pooling and JNDI Support/Integration
I hope you like it (remembering that it is beta), I'll post  updates, releases and bug fixes. Contributions are welcome.
  
Best Regards,
Diego Pacheco

February 22, 2010

JBoss HornetQ component for Apache Camel

Em um post anterior eu falei sobre o projeto Apache Camel que é um excelente solução para integração de sistemas. Recetemente a JBoss lancou seu novo produto de ultima geração em messageria o HornetQ, em outro post passado escrevi sobre a solução também. Neste post vim mostrar um componente muito simples que fiz para realizar a integração do Apache Camel com o JBoss HornetQ.

Esta é a primeira versão do componente, pretendo ir melhorando o componente de forma incremental aos poucos na sequencia, esta versão ainda é beta, tem algumas limitações. Mas já é possivel você trabalhar com as uri usando o meu componente para acessar as filas e topicos do HornetQ.



Download e Uso do Componente

Você pode baixar os fontes do meu repositório do Subversion: http://diegopacheco.svn.beanstalkapp.com/sandbox/trunk/community/hornetq-camel-component uma vez que você tenha feito o download você tem que instalar o componente usando o Maven. Para fazer isso digite na pasta do projeto o seguinte comando:
$ mvn clean install

Depois disso você esta pronto para usar o componente em seu projeto. Nos diretórios src/test/java e src/test/resources você conta um um exemplo de como usar o mesmo com o camel. Vou comentar com um pouco mais de detalhes a forma de uso.

Uma vez instalado no maven o componente você deve referenciar o mesmo no pom ou no classpath da sua aplicação, para referencia-lo no pom use a seguinte dependência:

<br /> <groupId>com.blogspot.diegopacheco.java.sandbox</groupId><br>    <artifactId>hornetq-camel-component</artifactId><br>    <version>1.0-SNAPSHOT</version>

Este componente é uma extensão do componente de JMS do camel, de forma que a principio muitas coisas já funcionam por herança, a sintax de URI é a mesma. O ID do bean registrado como componente no spring devera ser usado nas uri que você utilizar durante o seu roteamento.

Configuração no Spring e Customização

<br /> <bean id="hornetq" class="com.blogspot.diegopacheco.camel.hornetq.component.HornetQComponent" ><br>        <property name="useNettyDefaults" value="true" /><br>    </bean>

Esta é a configuração mais simples, asssim o componente assume que você quzer usar o netty como connector defaut e esta usando na port default em localhost. Você pode trocar esta configuração para usar outro conector ou até mesmo criar o seu conector customizado do netty, também é possivel passar o id do cliente através da customização, seria algo como no XML a baixo:

<br /> <bean id="hornetq" class="com.blogspot.diegopacheco.camel.hornetq.component.HornetQComponent">        <br>        <property name="connectionFactory"><br>            <bean class="com.blogspot.diegopacheco.camel.hornetq.component.HornetQCamelConnectionFactory"><br>                <property name="transportConfiguration"><br>                    <bean class="org.hornetq.api.core.TransportConfiguration" ><br>                        <constructor-arg index="0"><br>                            <value>org.hornetq.integration.transports.netty.NettyConnectorFactory</value><br>                        </constructor-arg><br>                    </bean><br>                </property><br>            </bean><br>        </property>        <br></bean>

Usando o HornetQ através das URI do Camel

Bom agora chegou a hora mais esperada :D O uso através do padrão de URI do camel.Confira o trecho de XML a baixo:

<br>    <camelContext xmlns="http://camel.apache.org/schema/spring" ><br>        <route><br>            <from uri="file://src/test/resources/data?delete=true"/><br>            <to uri="hornetq:queue:queue_hornetq"/><br>        </route><br>        <route><br>            <from uri="hornetq:queue:queue_hornetq"/><br>            <to uri="bean:beanConsumer"/><br>        </route><br>    </camelContext><br>

Como você pode ver estou usando o *hornetq* na uri, este é o nome do id do bean do Spring que se refere ao HornetQComponent. Você poderia usar outro valor aqui, desde que, este valor seja o mesmo no qual esta no bean do spring. Ainda é possivel usar as anotações para producers e comsumers do Camel uma vez que nas anotações você usa o mesmo estilo de URI.

Limitações Conhecidas e Futuras Implementações

Esta é a primeira versão, é possivel que existam bugs, eu já sei de algumas limitações e coisas que não implementei ainda, nesta sessão vou falar um pouco mais do que vai ser implementado nas próximas versões e que é uma limitação neste momento:

  • Criar filas e topicos de forma dinamica quando elas não existem no HornetQ
  • Acessar o HornetQ passando usuário e senha para aumentar a segurança(hoje usa o 'guest')
  • Suporte pooling e recursos JNDI
Espero que tenham gostando(lembrando que é beta :) ), logo post mais novidades, contribuições são bem vindas.

Abraços e até a próxima.

February 21, 2010

HornetQ: Simples, Performatico e Zumbido

é a terceira geração de soluções em Mesageria da JBoss, sucessora do JBoss Messaging, vem agitando o mercado de mesageria nos ultimos meses. Toda esta agitação não se deve só pelo fato de ser um produto totalmente novo com uma base de código nova em relação ao JBoss messaging(padrão de mesageria no JBoss EAP e JBOSS AS 5.0), mas pelo fato de sua performance bater os resultados anteriores da Spec.

Com a performance superior ao resultado anterior superando 307%, realmente é um número bem impressionate e que reflete o trabalho focado em performance da sua equipe de desenvolvimento. Este trabalho focando em performance tem dois elementos fundamentais: Netty e Persistência.

Netty é um framework focado para construir aplicações que tiram o máximo de performance da rede usando eventos de forma assíncrona. Ele foi criado por Trustin Lee que é o fundador dos projetos Apache Mina e Apiviz. O Transporte é basicamente delegado ao Netty quando o cliente e o servidor estão em diferentes maquinas virtuais ou invm quando o cliente e o servidor estão na mesma maquina. Tudo isto e configuravel e pode ser customizado, caso você queira mais detalhe de uma olhada neste post que fala sobre os Connectors & Acceptors no HornetQ.



Um pouco mais sobre a Arquitetura do Netty



Visão Geral da Arquitetura do Netty

Basicamente você pode efetuar o transporte usando a API de NIO de maneira bloqueante ou não bloqueante. Você ai tem suporte a diversos protocolos e formatos de dados como protocolos binários, procolos baseados em texto e até mesmo o Protobuf que é um protocolo da Google e é bem rápido. Além disso existe suporte a sugurança em SSL e integração com com container como Spring e JBoss Microcontainer.

O HornetQ usa a injeção de dependências do JBoss Microcontainer para configuração, feita através de XML em um estilo muito parecido com o do Spring Framework, isso é bom por que deixa muito fácil a customização do comportamento da soluções e deixa um bom gancho para extenssibilidade.O uso do JBoss Microcontainer é um dos pontos em que ele se difere da solução da Apache o ActiveMQ que é baseado em cima do Spring Framework.

A Persistência do HornetQ

Não existe mais suporte a persistência em banco de dados no HornetQ, na verdade nunca existiu, só nas versões antetiores das soluções de mesageria da JBoss. Já de conhecimento de todos que a persistência em banco de dados é muito lenta, devida a API de JDBC. O banco de dados lhe da muita resiliência mas performance, talvez a equipe do HornetQ esteja puxando um tendência nas soluções de mesageria ao retirar o suporte a banco de dados.

Várias soluções de mesageria tem o seu próprio Journal. Não foi deferente com o HornetQ, além de ter o seu próprio journal ele tem duas formas de escrever no disco basicamamente, a primeira é usando a API de NIO. A outra forma que é realmente rápida é focada para sistemas operacionais Linux e usa uma pequena camada JNI para acessar o libaio do linux.

O Journal da solução é circular e transacional, funciona em nível de kernel graças ao libaio, existem uma serie de arquivos pre-alocados que tem o tamanho mais proximo possível do cilimdro do disco, dai surgiu um valor mistico de 10mb que o pessoal do hornetq achou, mas segundo eles isso pode variar conforme o disco. São apénas usados os arquivos pre alocados, desta forma eles evitam os movimentos do disco rigido. Além disto tudo existe um controle muito otimizado para fazer a deleção e limpeza. Se você quizer mais detalhes confira este post do Clebert.

O HortnetQ comtém muitos exemplos em sua distribuição, mais de 70. Você pode usar a solução dentro do JBoss se quizer usando um modulo de resource adapter que vem na distrinuição da solução. Também é possivel usar a solução de forma standalone e também de forma "embarcada" dentro da sua aplicação.

Um recurso que eu gostei bastante é a detecção de conexões mortas. Isto é feito através do TTL e o proprio servidor mata recursos que estão mortos evitando que o servidor caia por falta de memoria, um warning é emitido no console e nos logs do servidor indicando isso.

O HornetQ realmente esta vindo contudo a performance e simplicidade são absurdamente bons, o unico porem é que não existem muitas funcionalidades fora do básico, na versão 2.1 vai vir suporte a REST e AMQP o que vai ser um boa.

Abraços e até a próxima.

February 16, 2010

Camel e ActiveMQ na prática usando Annotations

No posto anterior falei sobre a simplicidade e poder do Apache Camel. Neste post vou mostrar na prática como usar o camel para manipular diretórios, arquivos, filas JMS e código Java. Neste exemplo vou mostrar uma aplicação muito simples sobre cartão de crédito. Então vamos a aplicação :D

Imagine que você tem um restaurante e que a conta pode ser paga com cartão de credito, este cartão pode ser um VISA, Master, Hypercard ou Banricompras. Você recebe as informações de dos cartões de um sistema legado por exemplo feito em Clipper, ORACLE Forms, VB 6, Delphi ou qualquer outra tecnologia legada.

Você recebe este arquivos via arquivos texto em formato XML, você deve pegar cada XML e analisar o conteudo e de acordo com a bandeira do cartão vai mandar para uma fila especifica do ActiveMQ, desta forma você pode ter consumidores especificos para cada fila e fazer um processamento diferenciado para cada cartão de credito.



Esta aplicação na prática seria bem mais complexa do que estou proponto, meu objetivo aqui é mostrar como usar o apache camel em conjunto com o ActiveMQ usando annotações e o suporte do Spring, o cenário explicado a cima esta resumido a figura a baixo.


A Figura a cima mostra o fluxo de dados des da entrada dos arquivos XML em um diretório até o producer que é um bean do spring anotado com as anotações do camel colocar os dados nas filas corretas. Ao mesmo tempo os comsumer apropriados pegam os dados das filas e aplicam o processamento de negocios adequado.

Bom vamos ao código então. Primeiro vamos ver o pojo de dominio que representa o cartão de credito e depois vamos os serviços de negocio que estão no contexto do spring. Confira o código java a baixo.

CartaoCredito.java
<br /> package com.blogspot.diegopacheco.camel.pojo;<br /> <br /> import java.io.Serializable;<br /> <br /> /**<br />  * Pojo que representa um cartao de credito. A ideia eh que ele seja serializado<br />  * e desserializado pelo xstrean. Sendo que a mesagem em XML trafega pelos<br />  * arquivos e filas JMS.<br />  * <br />  * @author Diego Pacheco<br />  * @version 1.0<br />  * @since 16/02/2010<br />  * <br />  */<br /> public class CartaoCredito implements Serializable {<br /> <br />  private static final long serialVersionUID = 1L;<br /> <br />  private Double numero;<br />  private String bandeira;<br />  private Integer seguranca;<br />  private String nomeProprietario;<br /> <br />  public CartaoCredito() {<br />  }<br /> <br />  public CartaoCredito(Double numero, String bandeira, Integer seguranca,<br />    String nomeProprietario) {<br />   super();<br />   this.numero = numero;<br />   this.bandeira = bandeira;<br />   this.seguranca = seguranca;<br />   this.nomeProprietario = nomeProprietario;<br />  }<br /> <br />  public Double getNumero() {<br />   return numero;<br />  }<br /> <br />  public void setNumero(Double numero) {<br />   this.numero = numero;<br />  }<br /> <br />  public String getBandeira() {<br />   return bandeira;<br />  }<br /> <br />  public void setBandeira(String bandeira) {<br />   this.bandeira = bandeira;<br />  }<br /> <br />  public Integer getSeguranca() {<br />   return seguranca;<br />  }<br /> <br />  public void setSeguranca(Integer seguranca) {<br />   this.seguranca = seguranca;<br />  }<br /> <br />  public String getNomeProprietario() {<br />   return nomeProprietario;<br />  }<br /> <br />  public void setNomeProprietario(String nomeProprietario) {<br />   this.nomeProprietario = nomeProprietario;<br />  }<br /> <br />  @Override<br />  public String toString() {<br />   return "Cartao:" + bandeira + " de numero:" + numero + " - "<br />     + nomeProprietario;<br />  }<br /> <br /> }<br /> 

Este é um simples POJO que representa o cartão de credito, na prática você poderia colocar mais atributos e colocar relacionamento com outros POJOS de dominio como por exemplo Conta, Cliente, Endereço, etc.

Agora vamos ver os serviços de negocio do Spring, estes serviços fazem o processamento a partr das informações no cartão de credito, eu criei uma interface chamada CartaoService e todos os serviços de cartão de credito implementam esta interface, então vamos ver a interface e as suas implementações.

<br /> package com.blogspot.diegopacheco.camel.service;<br /> <br /> import com.blogspot.diegopacheco.camel.pojo.CartaoCredito;<br /> <br /> /**<br />  * Service de Cartao de Credito<br />  * <br />  * @author Diego Pacheco<br />  * @version 1.0<br />  * @since 16/02/2010<br />  * <br />  */<br /> public interface CartaoService {<br />  public void efetuarPagamento(CartaoCredito cc);<br /> }<br />

Esta interface só tem um método o *efetuarPagamento* que recebe como parametro o cartão de credito, vamos ver agora as implementações que fiz em cima desta interface de negócio.

VisaCartaoCredito.java
<br /> package com.blogspot.diegopacheco.camel.service;<br /> <br /> import org.springframework.beans.factory.annotation.Qualifier;<br /> import org.springframework.stereotype.Service;<br /> <br /> import com.blogspot.diegopacheco.camel.pojo.CartaoCredito;<br /> <br /> /**<br />  * Service de Cartao de Credito: Visa<br />  * <br />  * @author Diego Pacheco<br />  * @version 1.0<br />  * @since 16/02/2010<br />  * <br />  */<br /> @Service<br /> @Qualifier("visa")<br /> public class VisaCartaoCredito implements CartaoService {<br />  <br />  @Override<br />  public void efetuarPagamento(CartaoCredito cc) {<br />   System.out.println("Efetuado o pagamento com visa! Usando cartao: " + cc.getNumero());<br />  }<br /> }<br />

Esta implementação efetua o processmaneto de negocio em cima dos cartões da bandeira Visa. Eu simplesmente estou mostrando uma mensagem na tela, mas você poderia fazer o que quizer, acessar o banco de dados, um webservice, aplicar validações, etc. As outras implementações são semelhantes apénas trocando a mensagem. Criei implementação para Master e Outros cartões então só confira o código por cima.

MasterCartaoCredito.java
<br /> package com.blogspot.diegopacheco.camel.service;<br /> <br /> import org.springframework.beans.factory.annotation.Qualifier;<br /> import org.springframework.stereotype.Service;<br /> <br /> import com.blogspot.diegopacheco.camel.pojo.CartaoCredito;<br /> <br /> /**<br />  * Service de Cartao de Credito: Master Card<br />  * <br />  * @author Diego Pacheco<br />  * @version 1.0<br />  * @since 16/02/2010<br />  * <br />  */<br /> @Service<br /> @Qualifier("master")<br /> public class MasterCartaoCredito implements CartaoService {<br />  <br />  @Override<br />  public void efetuarPagamento(CartaoCredito cc) {<br />   System.out.println("Efetuado o pagamento com master! Usando cartao: " + cc.getNumero());<br />  }<br />  <br /> }<br />

OutrosCartaoService.java
<br /> package com.blogspot.diegopacheco.camel.service;<br /> <br /> import org.springframework.beans.factory.annotation.Qualifier;<br /> import org.springframework.stereotype.Service;<br /> <br /> import com.blogspot.diegopacheco.camel.pojo.CartaoCredito;<br /> <br /> /**<br />  * Service de Cartao de Credito: Hypercard ou Banricompras<br />  * <br />  * @author Diego Pacheco<br />  * @version 1.0<br />  * @since 16/02/2010<br />  * <br />  */<br /> @Service<br /> @Qualifier("outros")<br /> public class OutrosCartaoService implements CartaoService {<br />  <br />  @Override<br />  public void efetuarPagamento(CartaoCredito cc) {<br />   System.out.println("Efetuado o pagamento com outros[" + cc.getBandeira() +"]! Usando cartao: " + cc.getNumero());<br />  }<br />  <br /> } <br />

Agora vamos ver o código do Camel para fazer a leitura dos dados que estão em XML no diretório, primeiro confira o formato do arquivo XML com este arquivo de exemplo a baixo;

<br /> <cc><br />   <numero>1.0</numero><br />   <bandeira>Master</bandeira><br />   <seguranca>1</seguranca><br />   <nomeProprietario>FulanoX0</nomeProprietario><br /> </cc><br />

Este XML foi gerado usando o Xstream. Eu criei um alias para o CartaoCredito e chamei de cc. Isto é configurado via código e você vai ver mais a frente. Agora vamos ver o código do producer, a explicação segue a baixo do código.

<br /> package com.blogspot.diegopacheco.camel.pojo.producer;<br /> <br /> import org.apache.camel.Consume;<br /> import org.apache.camel.Produce;<br /> import org.apache.camel.ProducerTemplate;<br /> import org.apache.camel.language.XPath;<br /> <br /> /**<br />  * Pojo que atraves das annotacoes Procuce e Consume le os arquivos xml de um<br />  * diretorio e manda os mesmos para um Fila JMS.<br />  * <br />  * @author Diego Pacheco<br />  * @version 1.0<br />  * @since 16/02/2010<br />  * <br />  */<br /> public class PojoProducer {<br /> <br />  @Produce(uri = "activemq:queue:fila.cartao.visa")<br />  private ProducerTemplate producerVISA;<br /> <br />  @Produce(uri = "activemq:queue:fila.cartao.master")<br />  private ProducerTemplate producerMASTER;<br /> <br />  @Produce(uri = "activemq:queue:fila.cartao.outros")<br />  private ProducerTemplate producerOutros;<br /> <br />  @Consume(uri = "file://C:/temp/arquivos")<br />  public void quandoTemArquivosMandaParaFilaJMS(String msg,@XPath("/cc/bandeira/text()") String bandeira) {<br />   if ("Master".toUpperCase().equals(bandeira.toUpperCase())) {<br />    producerMASTER.sendBody(msg);<br />   } else if ("Visa".toUpperCase().equals(bandeira.toUpperCase())) {<br />    producerVISA.sendBody(msg);<br />   } else {<br />    producerOutros.sendBody(msg);<br />   }<br />  }<br /> <br /> }<br />

A annotation do Camel @Consume é resposável por consumir dados de um componente, neste caso o componente file que esta pegando arquivos do diretório C:/temp/arquivos. Quando entra um arquivo neste diretório o metodo quandoTemArquivosMandaParaFilaJMS é invocado recebendo como parametro uma string contendo o conteudo do arquivo.

Além disso existe uma anotação chamada @XPath ela serve para aplicar uma expressão XPath no XML,esta expressão pega apénas o campo bandeira do XML, isso vai ser usado para saber que tipo de cartão veio na mensagem. Dependendo do cartão a mensagem é roteada para uma fila especifica usando JMS.

Este roteamente se da através da classe ProducerTemplate do Camel em conjunto com a anotação @Produce que indica usar uma fila no ActiveMQ. Depois sera necessário configurar a localização e a forma de acesso ao ActiveMQ no spring, eu mostro isso na sequencia :)

<br /> <?xml version="1.0" encoding="UTF-8"?><br /> <beans xmlns="http://www.springframework.org/schema/beans"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amq="http://activemq.apache.org/schema/core"  xmlns:context="http://www.springframework.org/schema/context"  xsi:schemaLocation="        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd               http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd        http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd" ><br />  <br />  <camelContext xmlns="http://camel.apache.org/schema/spring" /><br />  <br />     <bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent"><br />         <property name="brokerURL" value="tcp://127.0.0.1:61616"/>        <br />     </bean><br />  <br />  <bean class="com.blogspot.diegopacheco.camel.pojo.consumer.PojoConsumer" /><br />  <bean class="com.blogspot.diegopacheco.camel.pojo.producer.PojoProducer" /><br />  <br />   <context:component-scan base-package="com.blogspot.diegopacheco.camel.service" /><br /> <br /> </beans><br />

Perceba que a configuração do activemq esta sendo feita através do bean 'activemq' que é do tipo ActiveMQComponent, dentro dele existe a propriedade 'brokerURL' que aponta para onde esta o activemq, estou acessando via tcp e na porta padrão que vem na instalação padrão.

*Sei que não falei muito sobre ActiveMQ neste post, mas vou abordar o mesmo em detalhes em posts futuros, até o momento você só precisa baixar a ultima versão e subir ele com a configuração padrão.

Voltando ao XML do Spring, podemos ver a declaração explicita do produucer e consumer do camel e tem um context-scan no spring que serve para ler os serviços de negocio do spring que estão sendo registrado com as anotações @Service e @Qualifier.

A tag 'camelContext' não tem nada, serve para indicar ao spring que suba o contexto do camel e jah inicie as rotas e o trabalho de mediação e roteamente imediatamente.

Agora vamos ver como que o Camel facilita a minha vida para ler das filas do ActiveMQ e acessar os serviços de negocio no Spring, para isso confira a classe chamada de PojoConsumer.

<br /> package com.blogspot.diegopacheco.camel.pojo.consumer;<br /> <br /> import org.apache.camel.Consume;<br /> import org.springframework.beans.factory.annotation.Autowired;<br /> import org.springframework.beans.factory.annotation.Qualifier;<br /> <br /> import com.blogspot.diegopacheco.camel.pojo.CartaoCredito;<br /> import com.blogspot.diegopacheco.camel.service.CartaoService;<br /> import com.thoughtworks.xstream.XStream;<br /> <br /> /**<br />  * Pojo que atraves das annotacoes Procuce e Consume le os dados<br />  * em xml das filas do activemq e transforma a mensagem em pojo.<br />  * <br />  * @author Diego Pacheco<br />  * @version 1.0<br />  * @since 16/02/2010<br />  * <br />  */<br /> public class PojoConsumer {<br />  <br />  private XStream xstream;<br />  <br />  @Autowired<br />  @Qualifier("visa")<br />  private CartaoService visa;<br />  <br />  @Autowired<br />  @Qualifier("master")<br />  private CartaoService master;<br />  <br />  @Autowired()<br />  @Qualifier("outros")<br />  private CartaoService outros;<br />  <br />  <br />  public PojoConsumer() {<br />   xstream = new XStream();<br />   xstream.alias("cc", CartaoCredito.class);<br />  }<br />  <br />  private CartaoCredito xmlToPojo(String msg){<br />   return (CartaoCredito)xstream.fromXML(msg);<br />  } <br />  <br />  @Consume(uri = "activemq:queue:fila.cartao.visa")<br />  public void consumeVISA(String msg){<br />   CartaoCredito cc = xmlToPojo(msg);<br />   visa.efetuarPagamento(cc);<br />  }<br />  <br />  @Consume(uri = "activemq:queue:fila.cartao.master")<br />  public void consumeMASTER(String msg){<br />   CartaoCredito cc = xmlToPojo(msg);<br />   master.efetuarPagamento(cc);<br />  }<br />  <br />  @Consume(uri = "activemq:queue:fila.cartao.outros")<br />  public void consumeOutros(String msg){<br />   CartaoCredito cc = xmlToPojo(msg);<br />   outros.efetuarPagamento(cc);<br />  }<br />  <br /> }<br />

Nesta classe eu usei as anotações@Autowired e @Qualifier do Spring para injetar os serviços. Tudo isso é possivel por que o Camel nada mais é do que um conjunto de beans do spring no seu contexto, graças a essa integração fantastica é muito fácil colocar código de negocio aqui.

Perceba que existem 3 metodos diferentes usando a anotação @Consume. Cada um deles esta lendo uma fila diferente do ActiveMQ, depois disso cada um delega o processamento de negocios para o seriço apropriado.

Para rodar a aplicação basta subir o contecto do spring. Se você esta em uma aplicão desktop pode fazer aldo semelhante ao meu código a baixo;

<br /> package com.blogspot.diegopacheco.camel.main;<br /> <br /> import org.springframework.context.support.ClassPathXmlApplicationContext;<br /> <br /> public class CamelBootstraping {<br />  public static void main(String[] args) {  <br />   try{    <br />    new ClassPathXmlApplicationContext(new String[] {"classpath:spring-camel-routing-beans.xml"});   <br />   }catch(Exception e){<br />    e.printStackTrace();<br />   }  <br />  }<br /> }<br /> 

Se você estiver usando Spring em uma aplicação Web basta configurar o listener no web.xml e apontar o arquivo de configurações do spring mostrado a cima neste post.

Ainda seria possivel melhorar muito esta *Arquitetura* você poderia separar os serviços do Spring do roteamente do Camel, assim você teria duas aplicações Web por exemplo, uma com o camel e outra com os beans de negocio do spring. Esta separação é possivel graças a mesageria e o ActiveMQ que é o nosso message broker/provider neste caso.

Se você quizer pode pegar os fontes completo deste projeto no meu repositório do Subversion na web. Espero que vocês tenham gostado deste post, na sequencia vou escrever mais coisas do genero, até lá um abraço e até a próxima Camel Riders!

February 15, 2010

Integração Simplificada com Apache Camel

Integração de sistema sempre foi e sempre sera uma necessidade para qualquer departamento de TI.Esta integração é feita na maioria das vezes de forma manual e pontual, este tipo de abordagem trás diversos problemas como por exemplo a complexidade de construir a integração sem utilizar um framework que lhe de beneficios como padrões, design certo a seguir, reutilização de código, reuso.

É normal se você estiver pensando em um ESB, porem um ESB requer muito conhecimneto, pensamento em design e você vai ter que lidar com uma certa complexidade. Neste post vim falar do Apache Camel que é um framework de integração de sistemas como se fosse um *ESB-Leve* fortemente baseado em Spring.



O Camel é um solução open source da Apache muito simples e extremamente flexivel, parte da sua flexibilidade é dada através da sua excelente integração com o Spring Framework.

Este framework não apénas facilita a sua vida quando você trabalha com JMS ou WebServices por exemplo, facilita também quando você tem que trabalhar com arquivos texto(os bons e velhos *flat-file*).

O Camel possibilita que você realize um roteamento baseado em regras declarativas através de beans do Spring ou através de uma DSL fluente por exemplo em Java ou Groovy.

Se você esta pensando em adotar SOA em sua organização, uma excelente abordagem é começar com o Camel por que ele é muito mais simples que um ESB, mas não perde em facilidades  e simplicidade. Confira a baixo um exemplo de rotamento:








Neste exemplo a cima estou roteamendo tudo que entra no diretório C:/dados para uma fila jms. Esta fila deve ser configurada, para que o camel saida aonde esta esta fila. Neste ponto podemos ver outra grande vantagem do Camel por que ele tem uma integração fantastica com a stack da apache, especificamente falando do Apache CXF para Webservices e o ActiveMQ como message broker.

Ainda seria possivel colocar condições neste roteamente usando a DSL do camel ou até mesmo XPath. A baixo vou mostrar como configurar para que o camel acesse a fila no ActiveMQ.









Esta configuração esta assumindo que você tem o ActiveMQ no ar e rodando na porta default, ele sera acessando via tcp. O Camel faz isso usando seu componente tcp que delega para o Apache Mina. O Camel também implementa a maioria dos padrões de integração de sistema os famosos Enterprise Integration Patterns. A lista completa de todos os compoenentes que o Camel suporte pode ser econtrada aqui.

Espero que tenham gostado, abraçõs e até a próxima camel riders!

February 13, 2010

SOA de verdade focando no retorno

Você pode adotar SOA em sua empresa usando qualquer técnologia na teoria. Na prática você acaba adotando as melhores e mais atuais técnologias. Estas tecnologias muitas vezes não são solução melhores por que são mais novas, mais por que tem um modelo melhor, foram concebidas com o aprendizado dos erros de outras técnologias anteriores.

É muito comum que em uma adoção de SOA algum vendor ou consultor indique que você comece a sua adoção focando em um ESB. Por si só o ESB é uma execelente técnologia porém não basta comprar um ESB, isto não vai fazer a sua adoção de SOA estar finalizada e ter sucesso.



O Que faz uma adoção de SOA ter sucesso?



O primeiro de tudo é focar no negocio, SOA possibilita uma grande vantagem competitiva para as empresas que sabem como usar. Este saber usar significar focar em ROI, pensar primeiro em que objetivos de negocios devem ser atingidos.

Infelismente a grande maioria das adoções de SOA só se baseava em compra de software e grandes investimentos e pouco retorno para o negocio das empresas. Para que a sua adoção de SOA de certo você precisa muito focar no negocio e pensar muito mais muito no que realmente a sua empresa deseja atingiar. Isto é bem diferente da estratégia compre um ESB primeiro.

O Manifesto SOA


O Manifesto SOA tem um papel importante nos dias de hoje, por que ele representa toda esta *segunda-onda-soa*, ou seja, toda esta mudança de pensamento, focando mais em resultados e principios, escolhas de design arquitetural do que compra de software, altos investimentos e pouco ou ZERO retorno.

São priorizados os itens da esquerda sobre os itens da direita no manifesto SOA, isto dá um noção do que é maios importante. não significa que você não possa fazer os itens da direita, mas deve tentar evitar eles focando nos da esquerda, então vamos ao manifesto.

Business value over technical strategy
Strategic goals over project-specific benefits
Intrinsic interoperability over custom integration
Shared services over specific-purpose implementations
Flexibility over optimization
Evolutionary refinement over pursuit of initial perfectionão

O que deve ficar claro com o manifesto é que SOA não é um objetivo mais sim um meio para atingir algo maior, através de SOA você pode atingir os seus objetivos estratégicos. A história já provou que isso requer muita reflexão, cautela e que não vair ser feito apénas com ténologia.

Dando o Segundo passo

Um vez que você sentou com o pessoal de negocios da sua organização e definiu bem os objetivos de negocio, agora você pode começar a pensar como vai fazer isso em termos de software. O manifesto ajuda, mas não vai lhe dar todas as respostas.

Existem várias formas de fazer a sua adoção, logo não existe o certo, existe o que é mais apropriado dependendo do contexto. Ok, mas você não poderia falar um pouco mais de ténologias? Sim eu vou! :D

Falando de Java, você pode usar coisas que já são consagradas como Messageria, Arquitetura em Camadas, Separação de conceitos muito clara, Web Services, REST, ORM e tantas outras ténologias.

Mas não seria interessante começar com um ESB? Isso depende muito. Se a sua equipe já tem experiencia forte com java e adoção de SOA, este é o caminho natural. Mas se as pessoas de sua equipe não estão fanilharizadas com isso, seria bom começar com algo mais simples e focar muito mais muito no DESGIN e na GOVERNAÇA.

Design é tudo, certamente é uma das partes mais dificies por que você tem que pensar em diversos pontos e diversas pequenas decisões que fazem a diverença. O Design pode e deve estar muito ligado com a governança SOA que não deve focar apénas nos aspectos de runtime.

É muito comun ver soluções de governça ai no mercado amarradas a um ESB e politicas de runtime na maioria das vezes associadas as padrões de WebServices, mas a governança é mais, muito mais que isso.

A Governança SOA em termos de runtime deve prover as politicas mas também o repositorio de serviços, aonde você possa consultar serviços, versionar contratos de serviços, ajude você a planejar a trocar e atualização de serviços.

Então a Governaça SOA é só runtime?

Como você pode perceber no paragrafo a cima a a governça foca muito em gestão, analise de impacto e outras coisas relacionadas a serviços. Mas a governça também foca antes do runtime, ou seja, em tempo de projeto ou design.

Neste tempo que você deve pensar nas decisões mais importantes na hora de construir a sua arquitetura e os seus serviços, isto pode ser feito de forma incremental, de cara você não precisa de uma solução de registry e repository, mas precisa sim definir as politicas, práticas e escolhas de design.

Escolhas como por exemplo, qual vai ser a sua estratégia de versionamento de serviços, você vai expor diretamente os seus beans ou vai criar abstrações do serviços para os consumidores, você vai separar como as camadas, quais camdas, quais seram as formas e padrões, formatos de dados e transporte, e assim por diante.

Indo adiante...

Comece com um projeto piloto e simplifique ao máximo a sua arquitetura, foque no design e escolha frameworks e ferramentas simples, tome muito cuidado para não focar mais em frameworks do que propriamente nos seus objetivos de negocios.

Soluções open source sempre são uma boa pedida, mas as vezes precisamos colcoar alguns ingredimentes pagos e proprietários, fique calmo quanto a esse ponto, é natual que em um abimente SOA você não tenho homogenidade, você vai ter diversos vendors e técnologias.

Aprenda com os seus erros e sempre foque no retorno para o negocio, design, governança e não deixe ter fazer as sessões de lições aprendidas, nos aprendemos mais com os nossos erros do que imaginamos. A medida que você for evoluindo nestes apectos você pode começar a usar outras soluções mais complexas em termos de arquitetura.

Lembrese de que a sua adoção SOA não vai ser feita em um ano, pode ser que leve 5 ou mais anos, mas o que importa é o aprendizado e retorno para o negocio. Faça isso sem parar o mundo, por que senão você só vai engorar a lista do Gartner de empresas que não conseguer provar o valor de SOA para o negocio.

Abraços e até a próxima.

February 2, 2010

Construindo um Repositório Corporativo com Artifactory

Ainda me lembro do inferno das DLLs quando trabalhava mais ativamente com produtos da Microsfot. Naquela epoca sofriamos com problemas de dependêcias. Quando comecei a trabalhar com Java sofri o mesmo problema de uma forma um pouco diferente mas na essência era a mesma coisa.

Em java o problema tem o nome de inferno dos jars. É incrével ainda ver empresas que em 2010 ainda passam por este tipo de problema em Java. Isto por que existem duas soluções que resolvem este tipo de problema. Estou falando do Apache Maven 2 e do Apache Ivy. As suas soluções da apache provem a funcionalidade de gestão de dependências.

É comum ver uma pasta chamada *lib* no classpath das aplicações java com mais de 100 jars, sendo que 70% ou mais não serve pra nada, nunca foi usada, nunca se quer foi tocado pelo classloader e dificilmente ira ser todado, mas por que as pessoas ainda fazem isso ? Por dois motivos: 



Problemas de Depedências: Todo mundo ja deve ter visto o famoso ClassNotFoundException
várias vezes. Muitas vezes o que é feito é copiar todas as jars que existem nos servidores de aplicação e que vem nas distribuições dos frameworks para a nossa boa e velha pasta lib. Claro que esta abordagem não é a melhor, mas é muito utilizada e poupa mais tempo. O problema é que você fica cheio de jars que você não precisa e a sua aplicação pode inchar.

Nota: Os Servidores de aplicações mais robustos como o Websphere por exemplo deixam você criar bibliotecas compartilhadas, assim você não precisa empacotar todos os seus jars na sua distribuição(ear, war, jar) e pode deixar o servidor colocar isso no classpath.

Desconhecimento: É incrivel o fato de que ainda eixstem muitas empresas com baixo uso de maven ou ivy para resolução de dependências, como consultor eu vejo isso muito e muito e não só no Brasil mas fora também.

Usando a Gestão de Dependências

Se você ainda não utiliza um framework que faça gestão de dependências,  recomendo começar a usar o quanto antes. Pode ser maven 2 ou ivy mas você deve usar, por que você vai ganhar nos seguintes pontos:
  • Dependências Transitivas: Estas são as dependências das dependências e as que realmente dão trabalho para achar.
  • Dependência certa, versão: Na abordagem da pasta lib, não existe um controle em cima de qual versão do jar é necessário e se esta versão esta em produção ou desenvolvimento, com um framework de resolução de dependências você vai ter um controle fino sem enloquecer com este aspecto.
  • Download automatico: Com uma solução de gestão de dependências você precisar procurar, baixar e colocar o jar e as dependências no classpath da sua aplicação. Esta é uma outra grande vantagem.
  • Atualização de versões: Esta é outra grande dor de cabeça, principalemente se você tem diversas aplicações que usam um jar que você desenvolve internamente, logo pode ser necessário entrar em muitas aplicações e fazer a troca da versão na mão, isso da trabalho e toma tempo.
Espero que você ja esteja convencido de que ter uma solução de gestão de dependências como ivy e maven é uma boa idéia. Az vezes as empresas usam maven ou ivy mas esquecem de ter uma solução de repositório corporativo por traz disso tudo.

Construindo um Repositório Corporativo com Artifactory

Eu já usei em produção soluções de repositório corporativo para java como o nexus e archiva. Mas hoje em dia uso o Artifactory e não me arrependo disso. O problema principal do archiva é que ele é muito lento pare baixar e resolver as dependências, coisa que o artifactory faz muito bem e muito rápido.

Você deve usar o artifactory por que ele prove um console web para que você administre os seus jars(soluções e plugins) de terceiros como spring, hibernate, jboss e os que você faz na sua própria empresa. Esta separação pode ser feita através de repositórios. 

Também é possivel seprar e controlar as versões do que esta em desenvolvimento e o que esta em produção. Muitas vezes as pessoas enchergam o artifactory apénas como uma solução de proxy, evitando que você gaste banda da sua empresa, mas na verdade é muito mais.

Controle das dependências

Com o artifactory você pode controlar através de uusários e grupos, quem e que aplicação pode consumir e usar determinados repositórios e jars. Da forma que você pode restringir o uso de Spring por exemplo apénas para alguns projetos (eu não faria isso :).) Você também passa a controlar melhor as suas dependências internar, das soluções que você faz, limitando e centralizado a forma de acesso a essas dependências da forma que você nunca mais vai perder uma dependência.

Repositório consolidade em M2 e Ivy


O a figura a cima mostra é que através de um repositório *virtual* no artifactory você pode servir a consumidores com maven ou com ant usando ivy. O que é mais legal disso tudo é que o repositório é o mesmo.

Como isso é possivel? Por que o artifactory é flexivel e nos vamos seguir alguns padrões para fazer isso. O Artifactory já trabalha com o padrão de dependências do maven 2que é:
  • GroupID: Grupo da solução, agrupador macro de modulo ou empresa provedora. Ex: org.springframework.
  • ArtifactID: Representa o identificar do artefato em si que esta sendo disponibilizado/consumido. Vai ser muitas vezes o nome do jar da antiga pasta lib como por exemplo: spring.
  • Version: É a versão do jar. No maven quando vemos algo do tipo 1.0 normalmete indica que a solução esta em produção ou se foi disponibilizada usa-se GA. Quando a solução esta em desenvolvimento se utiliza SNAPSHOT e as vezes seguido da data e hora do ultimo build.
Com ivy, as coisas funcionam de forma parecida pois nos temos os atributos: organisation, module e revision que tem equivalencia em ordem a groupid, artifactid e version. A grande diferença é que com ivy nos passamos um pattern estilo regex para a resolução de dependências. Este tipo de coisa não ocorre no maven por que o pattern é o mesmo e pre-definido.

Fato é que o ivy lhe da mais flexibilidade, mas também faz você passar muito mais trabalho. O que sugiro é que você use o mesmo pattern do maven no ivy, assim vamos ter consistência nos deploys feitos no artifactory e desta forma vamos ter o mesmo repositório para ivy e maven.

Configurando i Ivy para para baixar e fazer deploy no Artifactory

Para fazer isso basta utilizar o arquivos xml a baixo que chamei de ivy-artifactory-settings.xml;

<br><ivysettings><br>    <settings defaultResolver="public"/><br>    <credentials <br>        realm="Artifactory Realm"<br>        host="seu_host_do_artifactory" <br>        username="admin_user" <br>        passwd="admin_password"    <br>    />    <br>    <resolvers> <br>        <ibiblio name="public" m2compatible="true" root="http://seu_server:8080/artifactory/seu_proxy_repository" /><br>        <url name="publish_artifactory" m2compatible="true" > <br>            <artifact pattern="http://seu_server:8080/artifactory/seu_repositorio_release_repository/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /> <br>        </url> <br>    </resolvers>     <br></ivysettings><br>

Não esqueça de usar o pattern [organisation]/[module]/[revision]/[type]s/[artifact].[ext] para resolver as dependências. Na hora que você for publicar o seu jar via ivy, você pode usar uma task para fazer o pom do maven a partir das dependências do ivy, seria algo mais ou menos assim:
<ivy-makepom<br>            ivyfile="${ivy.xml.file}" <br>            pomfile="${basedir}/dist/${ivy.organisation}/${ivy.module}/${ivy.revision}/${ivy.module}-${ivy.revision}.pom"<br>        ><br>             <mapping conf="default" scope="compile" /><br>             <mapping conf="runtime" scope="runtime" />           </p>  </ivy-makepom><br>

Levando em conta que você gerou seu jar na pasta dist e que ele segue o pattern do maven 2, ou seja, esta dentro da pasta com a organização depois a pasta do modulo a pasta da versão e o jar com a versão.

Se você quizer saber como consumir os artefatos via maven e publicar os artefatos via maven não tera problema nenhum pois o ivy agora segue o mesmo pattern do maven então um pode consumir dependências geradas pelo outro.

Desta forma não importa se o projeto usa maven 2 ou ant com ivy, usando o artifactory seguindo os padrões e dicas que dei neste post você tera o mesmo repositório para tudo.

Abraços e até a próxima.