30 março 2009

Leverage EIP with Apache Camel and Twitter: Part 2

On my first post I introduced you about a problem a customer brought to me to solve. And I thought using Apache Camel to advertise on Twitter could actually fit into his business needs (and mine as well). The first thing I had to think about was on how to receive ads from different customers in different formats. This way I could let them continue to use any format they are already using to publish ads online.


Fig 1. receiving advertisements

To receive messages in different formats is easy. Just open endpoints where they can connect to and publish their files/messages/whatever. Camel comes with a lot of different components to implement these “incoming” endpoints. I had to put some Pipes and Filters before the Message Normalizer to load data into Message Exchange headers, and to drop invalid messages.

After a valid message arrives into CamelContext, they need to be normalized to a common format. Using the pattern Message Normalizer (a Content-based routing connected to different message translators), I convert all messages into TweetAd Java objects. This class looks like this:
public class TweetAd {
private TwitterAccount account;
private String advertisement;
// getters and setters
}

To translate messages, I did something like this kind of route:
    from("file:ads-inbox")
.to("bean:loadTwitterAccountHeaders")
.to("bean:transformIntoTweetAd")
.to("direct:tweets");

Cool, now I have a normalized Twitter Advertise a. What's next? Just forward it to a Message Endpoint that publishes TweetAd objects.

I didn't want my Twitter Publisher to require all incoming messages to be a TweetAd object type. So I've coded it in a way that could also publish whatever String context that message could supply. If the Message Exchange's body wasn't a TweetAd, with a valid TwitterAccount object associated to it, this endpoint would require username and password.
This is how my route looks like after having a valid TweetAd object:
    from("direct:tweets").to("twitter:publisher");

And I could have routes like this, for non-TweetAd objects:
    from("bean:amazonAWSAds")
.transform(body().convertToString())
.to("twitter:amazon?user=amazon&pass=nozama");

Done. Now I can publish ads coming from different customers, in different formats, to different Twitter accounts massively. Problem 1 solved. On my next post I will show you the code of Twitter Publisher.

See ya!

2 comentários:

Claus Ibsen disse...

Camel supports pluggable Type Converters, so in your twitter publisher you could do the type convertion to the TweetAd object. Or even supp

You can add a TweetAdConverter class and add methods to support convertering from different formats to TweetAd object.

Then you dont need the bean in your route that converts to TweetAd

Ryan disse...

Are you going to submit this to Camel?

Is it only a producer or can it also consume?

For instance - could you have it snag tweets directed at a specific account?

That would be pretty cool to have something that could pull in both @tweets and DM tweets and then handle things accordingly.

Imagine how cool it would be to have your DeadLetterChannel post tweets and let all its followers know of errors (ok, maybe a private account that you pre-approve the followers to - but you get the idea)

Contato

Email:bruno.borges(at)gmail.com

LinkedIn: www.linkedin.com/in/brunocborges
Twitter: www.twitter.com/brunoborges
Comprei e Não Vou
Rio de Janeiro, RJ Brasil
Oracle
São Paulo, SP Brasil