Friday, November 5, 2010

Polling any Database table with JBoss ESB 4.9 and Apache Camel - Part 1

Introduction


Poll a database table is very common use case when you are integrating systems and applications, according EIPs(http://www.enterpriseintegrationpatterns.com/): Shared Databse is one of Integration Styles available in the industry.

JBoss ESB 4.9 : Support for Apache Camel 

IMHO, this is the greatest improvement in JBoss ESB from the last 3 years,  we community owe this job to David Ward, which pushed this implementation in that newest Community JBoss ESB release.  David wrote about getting started with Apache Camel and JBoss ESB here: http://community.jboss.org/wiki/CamelGateway. If you need some basic overview about Apache Camel, I recommend you take a look on Camel website:  http://camel.apache.org/.

Where is the benefits of Apache Camel in JBoss ESB?

First of all, we have a plenty of new gateways components available, such component's list is huge, you can see them here. In Apache Camel we have to be aware about the difference between the components, basically there are:
  • Consumers - Which can be message listeners from the URI protocols
  • Producers - Which can post a message into the protocol URI
There are components that commonly can be both, but you might see some components that can be only Consumers or only Producers. It depends of the protocols nature or any other related aspect. 

For that demo, I decided use the JPA Component, as which can be both a producer and consumer.

Demo Use Case

We have many customers asking how they could integrate legacy applications, or even applications written in different platforms, such as .Net or PHP, for this matter we have one thing in common: The Database can be shared between many applications. I am not talking about ETL or even Data Services Federation, at this point I want to just get a row from some table and consider it a "Message", as which I can do anything I want using JBoss ESB Actions.

To turn my demo more realistic I am using the very well known opensource CRM: SugarCRM, which has a table called: Lead, which keeps every leads from the system stored. See Image 1 to see my local SugarCRM instance running:


Image 1 - Sugar CRM with my Leads

The SugarCRM stores the data into any relational database, in my case I am using MySql.

The ESB Project

In my ESB Project, I just have to add an Entity class that will reference the Lead Table, in that case I created the following table:

@Entity
@Table(name="leads")
@NamedQuery(name = "NewLeadsQuery", query = "select x from Lead x where x.status='New'")

public class Lead implements Serializable {
 private static final long serialVersionUID = 1L;

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 @Column(unique=true, nullable=false, length=36)
 private String id;

    @Lob()
 @Column(name="account_description")
 private String accountDescription;

   .....

In that Entity you can see that it is a very basic JPA Entity, which contains a named query that will return every Lead that the property status is "New", in other words: Every single Lead will be dispatched to JBoss ESB as a Message, and now you are asking yourself: How ? See the next topic.

Declaring a Camel Gateway in JBoss ESB

What is more important is to know the components that you will interact with, and notice that each component has its dependency, in my case with JPA, I need to add into my project lib folder the camel-jpa-VERSION.jar, which is my component library, I have to do that, because AKAIK just the core camel libraries are in JBoss ESB classpath. Here is my jboss-esb.xml config portion for it:



   
    
   
 


There is a point that I'd like to call your attention: The & symbol as it is declared in XML you have to work with the & representation replacing that symbol

Now, you are able to create any Service in JBoss ESB and several actions to interact with your Message.

In my final release of that demo, I am using JBoss BRMS/Guvnor, that will receive the Lead row as an Object and will decide if it is a Lead that have to be worked by a Sales Rep or an Inside Sales Rep, according some fields on that "Lead fact"


In my upcoming new things in that demo I will have 2 consoles: 1 written using Swing which will listening a JMS Queue for the Inside Sales, which supposedly are inside the company's office, and if it is a lead for an Outside Sales Rep, it will go to an Infinispan Cache, and it will be accessible through an WebSocket HTML 5 Client.

Last Tip about JPA Component

Once you consume a row to the database, maybe you need to change at least the column that makes the row available to be polled, in our case "status=new", So, you can "mark" that row with a new Status, or invoke any other operation, just adding the @Consumed annotation in any method in the JPA Entity.

// Changing 2 column's values in the database, so a polled row, will not be consumed more than one time
@Consumed
 public void checked(){
  
  this.setStatus("EAI-Partner"); 
  this.setStatusDescription("This Lead was Forwarded to a Partner");
  
 }





Next Steps

Partially I have the demo done, I will move that to my Mac, where I can do fancier screencasts, and than you will be able to see it working.


Tuesday, August 10, 2010

RestEasy on GoogleAppEngine: CoreREST

I've been quite busy the last couple of months, with a lot of meetings and customer calls, so far the time to study, to create and researching is becoming rare, activities that I love are becoming less frequent day by day. I have a particular viewing of video games: I hate all them and I hate invitations to play with, I prefer play soccer for real, but in my spare time, between an airport and other, I decided give myself another chance to enjoy Ruby, and to discover why lots of people says so good things about that. So I combined a plenty of subjects that I really enjoy: JAX-RS with RestEasy, JSF2.0 (Sorry, I know a lot of people prefers GWT) and Google AppEngine. The result combination was an open project called: CoreRest (http://corerest.appspot.com)




CoreREST, is a kind of "PaaS"(Platform as a Service), which runs on Google AppEngine, which allows users to create their own lightweight "WebServices" based on REST approach using Groovy, and as sooner as possible with Ruby(powered by JRuby). I also will add many out-of-the-box APIs, such as: Smooks, and XStream, thus will possible: Transform, Convert and create really rich Services.

I used RestEasy 2.0, the JBoss implementation for JAX-RS standard, led by Bill Burke, which runs smoothly on Google AppEngine. I also, decided use another JEE6 standard in GAE: JSF 2.0, which to be honest: Without Seam, JSF seems to be a "Barbacue without salt", but in the end, it is running pretty well.

For persistence, as Google uses BigTable, a noSQL Implementation, the JPA Provider recommended by Google I really didn't liked, so I am using Objectify, which for me was more pleasant and easy to use.

In this first blog entry, I will just let you create and expose a basic "Service" in CoreRest. To do that, see the following instructions:

1- Open http://corerest.appspot.com

2- Click on Groovy logo icon

3 - Fill the following information:

3.1 - Script Name: This is the script name, which will be a kind of "endpoint name", so it will be the key for service invocation, put any simple name for it, your name for instance.

3.2 - URL Mapping - This is the URI that you want for for your service, you will put: /{firstname}/{lastname} .

3.4 - And the Source, will be the groovy script:

String response = lastname.toUpperCase() + ", "+ firstname;
return response;


3.5 - Click on "Save Script"


 


Well, what is happening behind the scenes:

a) the URI is the extension for the "endpoint name", and the location where you will add the variables, exactly as you do according the standard on JAX-RS. In the URL: /{firstname}/{lastname}, we will have 2 variables available for Scripting context, besides the variable "response", which is the variable to return the response as a String, although CoreRest will support some Media types, I am still working on it, once it is totally possible using RestEasy.

To test you script, you just may call you service according the following URL:

http://corerest.appspot.com/service - (Service is the ROOT for endpoints)

http://corerest.appspot.com/service/tutorial/Edgar/Silva

Next Steps:
I will try work on it, improve the UI and the user experience. I would like to say thanks to eXo Platform, for the Groovy Syntax hightlight, and Alexandre Porcelli that helped me to not use Java Regular Expressions and make my code easier :), and Eder Magalhães that tested CoreRest with me last night.

I sooner I get this code not so dirty though, I will publish and let it opensource somewhere, maybe GitHub, once I could at least to do my first commit there without any error :).

Saturday, May 15, 2010

JBoss Technologies presented at 1st nosqlbr

 This saturday, May 15th, we had the 1st Conference about noSQL technologies in São Paulo, Brazil, promoted by Caravela Technologies, in fact, organized by Alexandre Porcelli (former Drools and Hibernate Commiter) - The ANTLR Guy, with his team and his lovely "gang"(his family).

The event started from a simple post on Twitter (#nosqlbr), and from a original planning for 20 people (no regular ones but geeks) going to a bar and between a beer and a cairpirinha, the people would have some discussion about noSQL technologies. However, Porcelli is brazilian, and he never gives up, and in the end the 1st nosqlbr had about 250 attendees in a fancy hotel with an incredible cofee break , good people to talk and so on.

Thursday, April 8, 2010

JBossInBossa 2010 - JBUG:Brasil Conference / May 7th, 8th


We are very happy to announce the JBossInBossa 2010 , the Brazilian JBoss Conference organized by JBUG:Brasil and sponsored by Red Hat and others, which is scheduled for May 7th and 8th.

The audience will be able to meet the following international speakers:
  • Pete Muir , Seam/Weld Project Lead
  • Benjamin Mestrallet, eXo Platform CEO
  • Mauricio Salatino, PlugTree CTO/ Drools Committer 
But the conferece will be in Brazil, so we will count with some JBoss employees providing Workshops and/or Sessions as well, see the following list :
  • Alessandro Lazarotti,
  • Bruno Rossetto Machado,
  • Edgar Silva
  • Flavia Rainone
  • João Paulo Viragine
  • Leandro Abite,
  • Rafael Benevides,
  • Ricardo Ferreira
  • Rodrigo Freire
  • Samuel Tauil
  • Others
We would like also to say thanks to another brazilian companies that are providing really great and worth speakers for our Workshops:
  • Caravela Tech: Alexandre Porcelli (CTO) -Drools Workshop with Mauricio Salatino (Salaboy)
  • Voice Technology - Antonio Anderson Souza (Voice Technology), André Pantalião - Workshop: Social Networking by Phone - Utilizando SeamTelcoFramework
  • Caelum - Paulo Silveira - Workshop: JPA 2.0 na prática, com Hibernate
  • GlobalCode - Alberto Lemos aka Dr.Spock , Vinicius Senger , Yara Senger- Workshop: JSF 2.0 with JBoss 6.x

 We would like to say thanks to James Cobb and his team at JBoss.ORG, they are the people behind the arts, logo and every good visual impact that we are promoting in JBossInBossa Website (http://www.jbossinbossa.com.br).

This is a way to share knowledge, energy and everything good, it is our way to say thanks to the large JBoss Community in Brazil, as well as to celebrate our 3rd birthday of official JBoss presence in Brazil.

This is our agenda for May 8th:

9:00 - 10:00

Seam 3, Weld, CDI , JEE 6 - Pete Muir

10:00 - 10:20

Cofee-Break

10:20 - 11:20

JBoss Application Server 6 Revolutions! - Flavia Rainone

11:20 - 12:20

SOA Showcases - Teiid(MetaMatrix) e BRMS - Ricardo Ferreira


13:20 - 14:20

Plataforma de Portais GateIn - Benjamin Mestrallet

15:30-16:15

Gerenciamento Efetivo de Ambientes JBoss com JOPR/JON - Rodrigo Freire e João Paulo Viragine

15:05-15:30

Cofeebreak - Intervalo

15:30-16:15

Apresentando o Projeto XSeam e Arquiteturas de Referencia em Seam  Alessandro Lazarotti e Rafael Benevides

16:15-17:00

Breakingwoods & JBoss para plataformas de Integração de Sistemas - Edgar Silva

17:00-17:50

Drools Fusion e DroolsFlow - Mauricio Salatino

17:50-18:50

RichFaces 4 e JSF 2.0 - Pete Muir


In the next year, we are already planning a bigger event, who knows in another location, I hope some place like Rio de Janeiro or Fortaleza :)

Cheers

Edgar


    Friday, April 2, 2010

    Speaking at Jazoon 2010


    I am very happy to be accepted to be speaking at Jazoon 2010 with my paper entitled: "Opensource SOA on Steroids: Combining the robustness of JBoss ESB with the flexibility of Apache Camel".  I am very excited with that, and already planning a cool presentation with a lot of energy and ready to share many good topics with the audience.

    Other much more relevant and famous JBossians were also accepted, see the following list :
    • Dan Allen
    • Emmanuel Bernard 
    • Heiko Braun 
    • Jean Deruelle 
    • Wesley Hales 
    • Aslak Knutsen 
    • Anil Saldhana
    See the full list here: http://jazoon.com/Conference/Speakers 

     I am proud to be representing the JBoss Solution Architects Team from Red Hat, and happy to have the chance to meet those incredible technicians there,  as well as all Java community that will be present there.      

    I will try bring with me a "Cachaça bottle"  in order to prepare for my friends some "Brazilian Caipirinhas (http://en.wikipedia.org/wiki/Caipirinha)", which is a really good mixing... Essentially as JBoss ESB and Apache Camel can to be.

    Thursday, February 25, 2010

    IRC Gateway in JBoss ESB via Apache Camel

    The breakingwoods project is happy to announce a new contribution: The initial Apache Camel fully integration. 

    Right now, we are accepting any suggestion, contribution, testing, complains... money etc, anything you judge valuable for make this component a really useful new JBoss ESB 4.7 Component.

    Basically what was done is just a new Gateway that is able to listen the Apache Camel Components, for awhile we just tested two of those: File and IRC.

    IRC can be a good way to receive events or messages that can be delivered to an existing JBoss ESB Service, in other words, this is the finnest integration between these two opensource projects: JBoss ESB and Apache Camel, and the community behind breakingwoods is happy to deliver this new component.

    How it Works

    First of all, we need just to declare a new Service, that will be listener for Apache Camel.



    The properties for this components are the following:
    • protocol-uri : Apache Camel Endpoint URI
    • destination-category : Service Category that will receive the events from the Camel Layer
    • destination-name: Service that will process the event that happened on Camel Layer
    Once you have it done, you will be able to check the event coming from IRC Channel to JBoss ESB.

    We hope that the community enjoy this!


    Check it out in http://code.google.com/p/breakingwoods

    Tuesday, February 9, 2010

    The Bossa Nova Way: JON success cases in Brazil, the rare accent again

    If you lost this presentation during the last JBossWorld 2009 in Chicago, it's your the chance to watch 3 real success histories coming from Brazil.


    JBoss Operations Network - JON is the productization of the Jopr project.  A JON subscription allows customers to perform enterprise management of not only JBoss Application Server , but also several important components such as the OS, Network traffic, Filesystems, Apache Web and Tomcat Servers, as well as internal services utilized by the JBoss Application Server, including: Hibernate, JMS, and Connection Pools.  It allows the JBoss to be recognized as a real "Enterprise Offering" in the market.   JON can be thought of as an enterprise level administration console for JBoss.  As Chris Morgan, Product Manager at Red Hat states: "You never will buy a car without a dashboard...".  JON is the dashboard that you were missing for your car!  In this Webinar, you will discover how three different customers increased the return on their JBoss Enterprise Application Platform investment by using JON.

    Why coming from Brazil? It is not only because this country is in the media or because it is cool, but because Brazil typically has limited resources for deploying technology, so demonstrating how you can do more with less is critical in such an environment.  If it works here, then it can work for you as well!

    More info: https://inquiries.redhat.com/go/redhat/20100209ManagementWebinar

    When:

    Tuesday, February 9 | 2pm EST (GMT-5) / 19:00 GMT

    Tuesday, January 26, 2010

    The Opensource Marginal Cost

    Recently I had a nice discussion on Twtitter. The topic was opensource. I find it interesting a lot of people still believe that opensource is an ideology, or a development model. It is interesting too there are a lot of people who are trying to create new ways to define opensource, such as "Open source is a business tactic, not a business model"[1], I do not understand the problem in considering opensource a business model. Although I am an engineer, I have studied business administration and I am very comfortable with opensource as a "Business Model". Moreover, I believe that a "tactic" is based on some business model. So, I do not see the difference. As a result I will consider “business tactic” and “business model” as synonyms.





    Many of us are used to selling opensource to the "technical departments". But, of times when we are facing a top level management people, for various reasons, we have experience difficult in explaining opensource as a suitable alternative! One of the reasons for this difficulty is we are used to and prepared to explain opensource from technical perspective. But, our technical arguments are not well understood by many management types. Most management types understand business models, business strategies and business tactic, whichever you prefer to call them. That is not a “knock” against management types. They understand their domains just as engineers understand their technical domains. So, you can imagine the difficulty in management understanding the technical reasons for using open source. Likewise, you can imagine the difficulty engineers have in understanding some business models, strategies, tactics, etc.


    I think the question really comes down to, “How are CIOs and managers to trust in something, or rely on something, they do not fully understand from a business perspective or a technical perspective?” It is for this reason, I believe if we better positioned the business case and business reasons for using opensource as an alternative rather than using technical reasons, we would have a much better chance in convincing CIOs and managers opensource solutions can indeed reduce their cost and also provide benefits to their customers.


    In the study of economics there is a concept called "Marginal Costs"[2], In general terms, marginal cost at each level of production includes any additional costs required to produce the next unit. If producing additional vehicles requires, for example, building a new factory, the marginal cost of those “extra” vehicles includes the cost of the new factory. In practice, the analysis is segregated into short and long-run cases, and over the long run, all costs are marginal. At each level of production and time period being considered, marginal costs include all costs which vary with the level of production, and other costs are considered fixed costs. This is a concept that can by also applied into opensource industry.



    For JBoss Enterprise subscriptions, or any other product family, Red Hat has a cost to keep a number of employees contributing, testing, certifying, collaborating, writing documentation, training a support team, consulting team etc. For this reason, the"Opensource Marginal Cost" is really low. That's why Red Hat never charges expensive prices for their products. That is also one of the biggest advantages for any company who follows this kind of business model in order to create a really profitable company offering opensource solutions. Obviously, Red Hat receives many contributions, but any contribution must be certified, and supported by Red Hat. Tor this reason, even for collaborations, there is a cost to test and to provide the security that this contribution will not cause any damage to "Subscription Buyers". However, this cost is still low, compared to "Proprietary Software".

    "Opensource Marginal Cost" offers companies to save as much as 80% in the software acquisition.


    Industry will accept "opensource" when the advantages are tangible factors, and not only merely words of text. I cannot see any company keeping their doors open creating innovative solutions without a way sell them.

    In fact, I saw a huge company trying jump in the opensource market without a good plan, and the result turned out to be catastrophic. This particular company was acquired by another proprietary vendor. Some think this end result is a "proprietary win over the opensource". However, in fact, in my humble opinion this is a "strategic company win over a company with a poor opensource strategy ".


    I live into a country where a lot of companies are looking for ways to reduce their costs in software, not only because opensource is "a new trend", but because some of them must trim their “IT” budgets to make them more competitive. I have seen many companies who have reduced their cost of software licencing, and with the saved software licensing costs they offered their employees not only better salaries, but also better environments for employees to work in as well as additional training and incentives for education.


    Opensource is not only a way to develop software, it is a way to make employees happier by saving money which can then be invested in what is really relevant for the company, the employees!





    There are many others factos that shows how opensource is an alternative for the future, replacing the retrograde proprietary industry software, such as bio alternatives as true substitutes for gasoline and its derivatives. In the end, everything is economics. We must open our minds, and not only think just as engineers, but also begin to think in terms of long term business.


    Monday, January 18, 2010

    Introducing project: breakingwoods - Components Repository and resources for JBoss ESB

    Introduction


    First of all, the main objective of this project is to be a source of new ideas, resources, components and actions for JBoss ESB.  Nobody is interested in creating a fork (or anything like that), but we believe that it could be a nice way to contribute to the evolution of this incredible project, as well as to be an accurate information source and filter for candidate components to be integrated into the core JBoss ESB project.





    At breakingwoods, anybody will be able to contribute.  All contributions are welcome, whether that be a new ESB component, a review of an existing compoenent, ideas, fixes, testing etc... all will be really appreciated  The only thing you need is a Gmail/Google account.


    Freedom to Contribute


    Everybody at the breakingwoods's team believes that JBoss ESB is a very robust solution, but would be even better if we would add more Adapters, Listeners, Gateways (in JBoss ESB it might be the same), as well as new Actions. The same happened with another popular opensource ESB solution: Mule, made by MuleSource.  The Mule community has Mule Forge, which is an extension's repository for MuleESB.  We hope that breakingwoods can be exactly the same for JBoss ESB, offering lots of components, and showing valuable information about which new ideas are rocking or the most downloaded, rated, commented etc.





    Why this project is not hosted under JBoss.ORG?


    Firstly we would like to make the project strong in its own right.  Once it is hosted at Google, we hope people will feel comfortable enough to contribute with whatever they want, once it is not so close to the crowd and the spotlight. Nevertheless, maybe in the future, we could move from Google Code to JBoss.ORG.  This will depend of the success of this initiative.  Alternatively, it could be great to have it isolated.


    How can I contribute?


    There are several ways in which you can help to make this project a success:
    • To Propose / To Create / To Review/ To test: New Adapters/Gateways/Listeners
    • To Propose / To Create / To Review/ To test: New ESB Actions
    • To Propose / To Create / To Review/ To test: New Ideas, Designs, Quickstarts


    Already at breakingwoods:
    • esbgen:  A basic CLI tool similar to seam-gen.  Helps you create the first esb project.
    • TwitterAction:  Action for publishing an ESB Message in Twitter.
    • EMailListener:  Periodically polls in the configured e-mail account, publishing incoming emails to JBoss ESB as an ESB Message.
    • Google Spreadsheet Listener:  Connects to Spreadsheets hosted by GoogleDocs, publishing new records to JBoss ESB.
    •  Apache DBUtils:  Action that executes plain SQLs.


    There are new Actions and Listeners in the pipeline.  The following are some of the next Listeners we are planning.  Maybe you will be able to help:


    • Apache Camel Listener/ Action
    • SalesForce Listener / Action
    • Infinispan Listener/ Action
    • Terracota Listener / Action
    • AMQP Listener/Action
    • Where is yours ? :)


    We are working in some of these, so stay tuned, as lots of good things will appear here at this project.


    Another good point, is that most of these components will be compatible to JBoss SOA Platform.  Obviously Red Hat will not support problems regarding SalesForce, Terracota or anything that is not part of the JBoss SOA-P supported distribution.  However, you will still be able to add these components into your solutions, possibly reducing your development time and increasing your productivity.


    If you have chance, check it out here: http://code.google.com/p/breakingwoods/


    Enjoy one of the best things about open source development: "To learn with others essentially doing something useful".







    breakingwoods Team.

    Saturday, January 2, 2010

    JBoss ESB on the Google's Clouds: Spreeadsheet Listener

    Recently my brother started a new kind of service in his very small consultancy company, he is offering a kind of Consultancy over the Google Apps focused in small business customers, although I believe that Google Apps is not suitable just for small ones, but for bigger companies/clients as well.




    Google Apps offers lots of good functionalities and services, such as: a) E-Mail, b) Site, c) Agenda, d) Documents (An online Office suite). I believe that this is a good strategy, so you might face in a near feature people replacing the older Excel files by new Google Spreadsheets, and than I decide work on it a little bit, creating a new Gateway to interact with this Google Service.

    Getting Started with Google APIs

    Google offers a good documentation over their APIs[1], in fact, everything that Google does, you are able to interact with just using Java, Python or even JavaScript[2].

    You might use Google Spreadsheets for many purposes, since a basic data collecting, or as my friend JP Viragine told me: "Maybe we could use as a "Decision Table on the Clouds", or just a excel replacement. The big advantage, beyond the fact you don't need to install anything in your computer, is the "Collaboration", because you might share the online file with another people that will be able for editing any time and anywhere.

    Another big difference when we are handling such kind of technology is the simple fact that we are totally stateless, once the Http allows us connect, and after the processing the http will give an answer, and that's it, is not that easy we use "Observers/Observables" when we are talking about HTTP (by default Stateless protocol), so my strategy was use "Timers" for polling the http service. I had not found a way to receive a notification from the service using Java, maybe it would make my job easier.

    New JBoss ESB Listeners


    If you create your first JBoss ESB gateway, you will be able to create as much as you need! The only thing that I have to recall when I have to create a new Gateway/Listeners is the wiki section that Tom Fennelly wrote [3]. So everything you will see here in this entry is very well documented there, you must say thanks to Tom, he did a really good job documenting about this subject.


    JBoss ESB in Action with GoogleDocs

    The first step is declare our listener into Jboss-esb.xml, there we will describe everything we need, such as properties and its values as well as the Listener class itself:



    The most important configuration from this listener is the property: gatewayClass, which we are using: org.jboss.soa.jbossesb.gateways.google.GoogleDocsGateway , which is not an ou-of-the-box class from JBoss ESB, it is totally new, and you will see it working pretty soon. Moreover, we defined other properties that will be used by the Listener classes further, this properties are: documentName, feedURL, username, password and so on.

    I created a very ugly class GoogleDocsGateway, that for this entry is handling just the spreadsheet, this is a class that extends AbstractThreadedManagedLifecycle, after this the rest is quite easy. When you are extending this class, you must keep in mind that there are certain tasks to think about:

    1 -Define what you will do in the doInitialise() method, this is the method called when JBoss ESB invokes this service by the first time.

    2- The doRun() is the most important one, this is a method that or will be waiting for an event notification, or you must try get a way to poll the protocol that you are interacting with, in order to don't consume unnecessary resources.

    package org.jboss.soa.jbossesb.gateways.google;
    
    import java.util.Timer;
    import java.util.TimerTask;
    
    import org.jboss.soa.esb.ConfigurationException;
    import org.jboss.soa.esb.Service;
    import org.jboss.soa.esb.client.ServiceInvoker;
    import org.jboss.soa.esb.helpers.ConfigTree;
    import org.jboss.soa.esb.listeners.ListenerTagNames;
    import org.jboss.soa.esb.listeners.lifecycle.AbstractThreadedManagedLifecycle;
    import org.jboss.soa.esb.listeners.lifecycle.ManagedLifecycleException;
    import org.jboss.soa.esb.listeners.message.MessageDeliverException;
    import org.jboss.soa.esb.message.Message;
    import org.jboss.soa.esb.message.format.MessageFactory;
    
    /**
     * Google Gateway Class
     * 
     * @author esilva
     */
    public class GoogleDocsGateway extends AbstractThreadedManagedLifecycle {
    
     private ConfigTree listenerConfig;
     private Service service;
     private ServiceInvoker serviceInvoker;
    
     private GoogleSpreadSheet sheet = new GoogleSpreadSheet();
    
     protected boolean firstExecution = true;
    
     public GoogleDocsGateway(ConfigTree config) throws ConfigurationException {
      super(config);
    
      this.listenerConfig = config;
    
      String serviceCategory = listenerConfig
        .getRequiredAttribute(ListenerTagNames.TARGET_SERVICE_CATEGORY_TAG);
    
      String serviceName = listenerConfig
        .getRequiredAttribute(ListenerTagNames.TARGET_SERVICE_NAME_TAG);
    
      service = new Service(serviceCategory, serviceName);
    
      sheet.setService(config.getAttribute("servicename"));
    
      sheet.setUsername(config.getAttribute("username"));
    
      sheet.setPassword(config.getAttribute("password"));
    
      sheet.setFeedurl(config.getAttribute("feedurl"));
    
      sheet.setDocumentName(config.getAttribute("documentname"));
    
     }
    
     @Override
     protected void doRun() {
    
      publishMessageToESB();
    
      int delay = 10000; 
      int period = 5000; 
      Timer timer = new Timer();
    
      timer.scheduleAtFixedRate(new TimerTask() {
       public void run() {
    
        try {
         if (sheet.hasChanges()) {
    
          System.out
            .println("Changes found, publishing the message again");
    
          publishMessageToESB();
    
         }
    
         else {
    
          System.out.println("No updates found");
    
         }
    
        } catch (Exception e) {
    
         e.printStackTrace();
        }
    
       }
    
      }, delay, period);
    
     }
    
     private void publishMessageToESB() {
      Message esbMessage = MessageFactory.getInstance().getMessage();
    
      try {
    
       esbMessage.getBody().add(sheet.load());
    
      } catch (Exception e) {
    
       e.printStackTrace();
      }
      try {
       serviceInvoker.deliverAsync(esbMessage);
    
      } catch (MessageDeliverException e) {
    
       e.printStackTrace();
      }
     }
    
     @Override
     protected void doInitialise() throws ManagedLifecycleException {
    
      try {
       serviceInvoker = new ServiceInvoker(service);
    
       sheet.initialize();
    
      } catch (MessageDeliverException e) {
    
       throw new ManagedLifecycleException(
         "Failed to create ServiceInvoker for Service listening Google Service: "
           + service + "'.");
      }
    
      catch (Exception e) {
    
       throw new ManagedLifecycleException(e);
      }
    
     }
    
    }
    
    
    

    I created a new class called: GoogleSpreadSheet, that is an abstraction over the tasks we must to do to interact with the Google Spreadsheets, and through the doRun() method I am using a kind of scheduler to poll the url of my spreadsheet according the property configuration made by the "user" of this gateway.

    package org.jboss.soa.jbossesb.gateways.google;
    
    import java.net.URL;
    import java.util.List;
    
    import org.quartz.Job;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    
    import com.google.gdata.client.spreadsheet.SpreadsheetService;
    import com.google.gdata.data.spreadsheet.ListEntry;
    import com.google.gdata.data.spreadsheet.ListFeed;
    import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
    import com.google.gdata.data.spreadsheet.SpreadsheetFeed;
    import com.google.gdata.data.spreadsheet.WorksheetEntry;
    
    public class GoogleSpreadSheet implements Job {
    
     protected static SpreadsheetService myService;
    
     protected URL metafeedUrl;
    
     protected SpreadsheetFeed feed;
    
     protected List spreadsheets;
    
     protected SpreadsheetEntry entry = null;
    
     private String service;
     private String username;
     private String password;
     private String feedurl;
     private String documentName;
     private String lastUpdate;
    
     protected boolean on = false;
    
     public String getService() {
      return service;
     }
    
     public void setService(String service) {
      this.service = service;
     }
    
     public String getUsername() {
      return username;
     }
    
     public void setUsername(String username) {
      this.username = username;
     }
    
     public String getPassword() {
      return password;
     }
    
     public void setPassword(String password) {
      this.password = password;
     }
    
     public String getFeedurl() {
      return feedurl;
     }
    
     public void setFeedurl(String feedurl) {
      this.feedurl = feedurl;
     }
    
     public String getDocumentName() {
      return documentName;
     }
    
     public void setDocumentName(String documentName) {
      this.documentName = documentName;
     }
    
     public String getLastUpdate() {
      return lastUpdate;
     }
    
     public void setLastUpdate(String lastUpdate) {
      this.lastUpdate = lastUpdate;
     }
    
     public GoogleSpreadSheet() {
    
     }
    
     public void initialize() throws Exception {
    
      myService = new SpreadsheetService(service);
    
      System.out
        .println("Initializing Connection between JBoss ESB and Google Docs...");
    
      myService.setUserCredentials(username, password);
    
      metafeedUrl = new URL(feedurl);
    
      feed = myService.getFeed(metafeedUrl, SpreadsheetFeed.class);
    
      spreadsheets = feed.getEntries();
    
      entry = null;
    
      for (int i = 0; i < spreadsheets.size(); i++) {
    
       entry = spreadsheets.get(i);
    
       if (entry.getTitle().getPlainText().equalsIgnoreCase(documentName)) {
    
        setLastUpdate(entry.getUpdated().toString());
    
       }
      }
    
     }
    
     public String load() throws Exception {
    
      StringBuilder builderOut = new StringBuilder();
    
      entry = null;
    
      for (int i = 0; i < spreadsheets.size(); i++) {
    
       entry = spreadsheets.get(i);
    
       if (entry.getTitle().getPlainText().equalsIgnoreCase(documentName)) {
    
        List worksheets = entry.getWorksheets();
    
        for (int j = 0; j < worksheets.size(); j++) {
    
         WorksheetEntry worksheet = worksheets.get(j);
    
         URL listFeedUrl = worksheet.getListFeedUrl();
    
         ListFeed listFeed = myService.getFeed(listFeedUrl,
           ListFeed.class);
    
         if (listFeed.getEntries().size() > 0) {
    
          StringBuilder header = new StringBuilder();
    
          for (String tag : listFeed.getEntries().get(0)
            .getCustomElements().getTags()) {
    
           header.append(tag + ",");
    
          }
    
          builderOut.append(header.toString().substring(0,
            header.lastIndexOf(",")));
    
         }
    
         for (ListEntry entrada : listFeed.getEntries()) {
    
          StringBuilder row = new StringBuilder();
    
          for (String tag : entrada.getCustomElements().getTags()) {
    
           row.append(entrada.getCustomElements()
             .getValue(tag)
             + ",");
    
          }
    
          builderOut.append(row.toString().substring(0,
            row.lastIndexOf(",")));
    
         }
        }
    
       }
    
      }
    
      return builderOut.toString();
    
     }
    
     public boolean hasChanges() throws Exception {
    
      SpreadsheetFeed feed = myService.getFeed(metafeedUrl,
        SpreadsheetFeed.class);
    
      List spreadsheets = feed.getEntries();
    
      entry = null;
    
      for (int i = 0; i < spreadsheets.size(); i++) {
    
       entry = spreadsheets.get(i);
    
       if (entry.getTitle().getPlainText().equalsIgnoreCase(documentName)) {
    
        if (getLastUpdate().equalsIgnoreCase(
          entry.getUpdated().toString())) {
    
         System.out.println(getLastUpdate() + "==========="
           + entry.getUpdated().toString());
    
         return false;
    
        } else {
    
         this.setLastUpdate(entry.getUpdated().toString());
         System.out.println("Changes arriving: " + getLastUpdate()
           + "===========" + entry.getUpdated().toString());
         return true;
    
        }
    
       }
    
      }
      return false;
    
     }
    
     public GoogleSpreadSheet(String service, String username, String password,
       String feedurl, String documentName, String lastUpdate) {
    
     }
    
     public String load(String service, String username, String password,
       String feedurl, String documentName, String lastUpdate)
       throws Exception {
    
      SpreadsheetService myService = new SpreadsheetService(service);
    
      myService.setUserCredentials(username, password);
    
      URL metafeedUrl = new URL(feedurl);
    
      SpreadsheetFeed feed = myService.getFeed(metafeedUrl,
        SpreadsheetFeed.class);
    
      List spreadsheets = feed.getEntries();
    
      SpreadsheetEntry entry = null;
    
      StringBuilder builderOut = new StringBuilder();
    
      for (int i = 0; i < spreadsheets.size(); i++) {
    
       entry = spreadsheets.get(i);
    
       if (entry.getTitle().getPlainText().equalsIgnoreCase(documentName)) {
    
        System.out.println("Last Update: " + entry.getUpdated());
    
        List worksheets = entry.getWorksheets();
    
        for (int j = 0; j < worksheets.size(); j++) {
    
         WorksheetEntry worksheet = worksheets.get(j);
    
         URL listFeedUrl = worksheet.getListFeedUrl();
    
         ListFeed listFeed = myService.getFeed(listFeedUrl,
           ListFeed.class);
    
         if (listFeed.getEntries().size() > 0) {
    
          StringBuilder header = new StringBuilder();
    
          for (String tag : listFeed.getEntries().get(0)
            .getCustomElements().getTags()) {
    
           header.append(tag + ",");
    
          }
    
          System.out.println(header.toString().substring(0,
            header.lastIndexOf(",")));
          builderOut.append(header.toString().substring(0,
            header.lastIndexOf(",")));
    
         }
    
         for (ListEntry entrada : listFeed.getEntries()) {
    
          StringBuilder row = new StringBuilder();
    
          for (String tag : entrada.getCustomElements().getTags()) {
    
           row.append(entrada.getCustomElements()
             .getValue(tag)
             + ",");
    
          }
    
          System.out.println(row.toString().substring(0,
            row.lastIndexOf(",")));
          builderOut.append(row.toString().substring(0,
            row.lastIndexOf(",")));
    
         }
        }
    
       }
    
      }
      return builderOut.toString();
    
     }
    
     @Override
     public void execute(JobExecutionContext ctx) throws JobExecutionException {
    
      try {
       System.out.println("Has Changes: " + this.hasChanges());
      } catch (Exception e) {
    
       e.printStackTrace();
      }
    
     }
    
    }
    
    
    

    Instead to use lots of confusing images, I will use a screencast:



    I hope you liked that idea, and you can feel yourself more comfortable for creating new Listeners/Gateways for JBoss ESB.


    Rerefences

    [1] - http://code.google.com/intl/pt-BR/apis/spreadsheets/
    [2] - http://code.google.com/intl/pt-BR/apis/spreadsheets/data/3.0/developers_guide_java.html
    [3] - http://community.jboss.org/docs/DOC-13193