O JBoss ESB é de fato um produto viciante, pelo fato de ser ao mesmo tempo poderoso e simples, nesse pequeno exemplo, o que eu estou mostrando é basicamente como integrar um serviço Jabber(XMPP) ao barramento de serviços.
Um serviço Jabber pode ser interessante para vários aspectos, principalmente pela comunicação que pode haver com um serviço Asterisk ou até mesmo alertas etc.
Eu instalei na minha máquina o OpenFire, que é um servidor Jabber, mesmo eu estando muito longe de ser um exímio administrador Linux eu consegui instalar no meu Red Hat Linux, e carregar a interface de administração, configurando-o para uso, bem como adicionando dois usuários: joao e edgar.
Para rodar o Openfire no Linux, você precisa apenas como root (su -), iniciá-lo a partir do /etc/init.d/openfire start , com isso feito, você poderá ver a tela de gerenciamento no endereço: http://localhost:9090 , veja o exemplo:

Openfire - Tela de Administração de Sessão
Claro, muito do que fiz poderia ser economizado se eu quisesse usar uma conta to google/gtalk, mas como com certeza eu iria esquecer minha senha em algum exemplo que enviasse para amigos e clientes, correndo o risco de perder minha conta, ou algum amigo fazer aquelas velhas brincadeiras como estas:

Poderia ser você
Bom, vamos voltar ao JBoss ESB, que é o que este post trata, já que eu tenho meu próprio servidor Jabber
Criando um Scheduler para embutir a API Smack no ESB
Basicamente, como mostrei naquele blog mais sério em inglês que falo da integração com o Apache Camel, você pode embarcar serviços como Listeners no barramento.
Sobre a API Smack
O Smack é uma API super interessante, e existem várias oportunidades de negócio na área de integração VOIP, Mídia, Colaboração etc, então, se o assunto for integrar Jabber clientes com serviços, essa API é na minha opinião a número 1 em termos de simplicidade e facilidade.
Criando o Listener via Scheduler no JBoss ESB
Primeiramente, vamos declarar o Provider Scheduler no jboss-esb.xml como você pode ver abaixo:
<schedule-provider name="XmppProvider">
<cron-schedule cronExpression="0/1 * * * * ?" scheduleid="Xmpp"/>
</schedule-provider>
</providers>
Agora vamos ver as configurações dos Serviços:
<services>
<service category="Extra"
description="Service responsible for interact with Actions based in Project smackesb" name="buddy">
<listeners>
<scheduled-listener event-processor="org.demo.smackesb.XmppListener"
name="cron-schedule-listener" scheduleidref="Xmpp"/>
</listeners>
</service>
<service category="CBR"
description="Service responsible for interact with Actions based in Project smackesb" name="jabber">
<listeners>
<jms-listener busidref="smackesbGwChannel" is-gateway="true"
maxThreads="1" name="JMS-Gateway"/>
<jms-listener busidref="smackesbEsbChannel" maxThreads="1" name="EsbChannel"/>
</listeners>
<actions mep="OneWay">
<action class="org.jboss.soa.esb.smooks.SmooksAction" name="transform-from-csv">
<property name="smooksConfig" value="/smooks-res.xml"/>
<property name="messageProfile" value="source-csv"/>
</action>
<action class="org.jboss.soa.esb.actions.SystemPrintln" name="dumpCanonical">
<property name="message"/>
<property name="printfull" value="false"/>
</action>
<action class="org.jboss.soa.esb.smooks.SmooksAction" name="transform-to-xml">
<property name="smooksConfig" value="/smooks-res.xml"/>
<property name="messageProfile" value="canonical-xml"/>
</action>
<action class="org.jboss.soa.esb.actions.SystemPrintln" name="dumpXML">
<property name="message"/>
<property name="printfull" value="false"/>
</action>
</actions>
</service>
</services>
Configuração do Smooks:
<?xml version='1.0' encoding='UTF-8'?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.0.xsd">
<profiles>
<profile base-profile="source-csv" />
<profile base-profile="canonical-xml" />
</profiles>
<resource-config target-profile="source-csv" selector="org.xml.sax.driver">
<resource>org.milyn.csv.CSVParser</resource>
<param name="fields" type="string-list">
transacao,
valor
</param>
</resource-config>
<resource-config target-profile="canonical-xml" selector="csv-set">
<resource type="xsl">
<![CDATA[
<ROOT>
<xsl:for-each select="csv-record">
<Transacao>
<numero><xsl:value-of select="transacao"/></numero>
<valor><xsl:value-of select="valor"/></valor>
</Transacao>
</xsl:for-each>
</ROOT>
]]>
</resource>
<param name="is-xslt-templatelet">true</param>
</resource-config>
<!-- Popular Transacao -->
<resource-config selector="Transacao">
<resource>org.milyn.javabean.BeanPopulator</resource>
<param name="beanId">transacao</param>
<param name="beanClass">bpmesb.Transacao</param>
<param name="bindings">
<binding property="id" selector="Transacao/@numero" />
<binding property="valor" selector="Transacao/@valor" type="Double"/>
</param>
</resource-config>
</smooks-resource-list>
Agora, vamos mostrar o código fonte do Scheduler ESB:
package org.demo.smackesb;
import org.jboss.soa.esb.ConfigurationException;
import org.jboss.soa.esb.client.ServiceInvoker;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.listeners.message.MessageDeliverException;
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.message.format.MessageFactory;
import org.jboss.soa.esb.schedule.ScheduledEventListener;
import org.jboss.soa.esb.schedule.SchedulingException;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.FromContainsFilter;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.Packet;
public class XmppListener implements ScheduledEventListener {
protected boolean started = false;
protected ConnectionConfiguration config;
protected XMPPConnection connection;
public void onSchedule() throws SchedulingException {
}
public void initialize(ConfigTree arg0) throws ConfigurationException {
try {
config = new ConnectionConfiguration("localhost", 5222, "es");
connection = new XMPPConnection(config);
connection.connect();
connection.login("joao", "123", "Home");
org.jivesoftware.smack.packet.Message chat = new org.jivesoftware.smack.packet.Message();
chat.setTo("edgar@es/Home");
chat.setSubject("SOA Integration");
chat.setBody("JBoss ESB Buddy is online!");
chat.setType(org.jivesoftware.smack.packet.Message.Type.chat);
connection.sendPacket(chat);
PacketFilter filter = new AndFilter(new PacketTypeFilter(
org.jivesoftware.smack.packet.Message.class),
new FromContainsFilter("edgar"));
PacketListener myListener = new MyTracker();
connection.addPacketListener(myListener, filter);
} catch (XMPPException e) {
e.printStackTrace();
}
}
public void uninitialize() {
connection.disconnect();
}
class MyTracker implements PacketListener {
public void processPacket(Packet packet) {
// dispatch messages to ESB from a Jabber Client
org.jivesoftware.smack.packet.Message msg = (org.jivesoftware.smack.packet.Message) packet;
System.out.println("Will forward the Message: " + msg.getBody());
try {
ServiceInvoker invoker = new ServiceInvoker("CBR", "Jabber");
Message message = MessageFactory.getInstance().getMessage();
message.getBody().add(msg.getBody());
invoker.deliverAsync(message);
} catch (MessageDeliverException e) {
e.printStackTrace();
}
}
}
}
Basicamente, nós temos na classe acima, acesso ao ConfigTree, então algumas configurações poderiam vir do XML do JBoss-ESB, mas decidi construir o código de forma mais simples.
Agora, o que acontece é, quando o JBoss ESB é iniciado, ele terá um “buddy” chamado joao, que interage com o edgar, o que acontece então é que eu posso via meu programa de bate-papo fazer algo de fato útil, por exemplo, enviar uma mensagem no formato:
[numero da transacao],[valor da transacao]
Onde, esssa linha, vai ser considerada um CSV, que vai ser transformado pelo serviço de Transformação Smooks do JBoss ESB.
Basicamente, quando a mensagem de edgar vai para o JBoss ESB, o buddy joao converte essa mensagem para uma mensagem no formato do ESB para o barramento, o que garante o processamento dentro do bus.
Veja a interação da demo na seguinte screenshot:

JBoss em ação com o Jabber
Baixe aqui os fontes desta solução, descompacte-o no seu diretório [jboss-esb-home]/samples/quickstarts, e para deploy o comando: ant deploy.
E claro, em próximas apresentações em eventos, ou demonstrações da plataforma SOA JBoss, este deve ser um dos novos caras a ser mostrado.
Em resumo, apesar de ouvir comentários chatos como “JBoss ESB não é um esb robusto”, eu sugiro fortemente a leitura de alguns cases de sucesso dele neste site, e claro, no Brasil existem casos de sucesso também, mas infelizmente ainda estamos trabalhando na escrita destes cases, isto sem falar nos clientes que usam o JBoss ESB .ORG, os quais não tem acesso a suporte e SLA profissional da Red Hat, estes, apenas conhecemos e ajudamos da melhor forma possível, e claro, no intuíto de fazermos com que essas empresas também possam enchergar as vantagens de opensource “profissional”, onde o suporte não fica a cargo somente de pessoas, e sim a cargo de uma empresa de saúde que é a Red Hat e sua divisão JBoss.
Acredito que após ler o site que citei, possa ser um bom ponto de reflexão para comentários e/ou escolhas de tecnologias, já que os casos apresentados, são dignos de sucesso com certeza.
Veja aqui o screencast da solução.
Ah,
o JBoss 5 ? Uma outra hora comento sobre o lançamento dele, primeiro prefiro ouvir, ler…Principalmente porque alguns comentários são bem divertidos, para não dizer outra coisa.
Referências