<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>System Mobile</title>
	<atom:link href="http://www.systemmobile.com/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.systemmobile.com</link>
	<description></description>
	<lastBuildDate>Wed, 14 Mar 2012 04:08:12 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.2</generator>
		<item>
		<title>Dynamic Routes with Apache Camel</title>
		<link>http://www.systemmobile.com/?p=427</link>
		<comments>http://www.systemmobile.com/?p=427#comments</comments>
		<pubDate>Fri, 09 Mar 2012 16:46:16 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Entry]]></category>
		<category><![CDATA[apache camel]]></category>
		<category><![CDATA[camel]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.systemmobile.com/?p=427</guid>
		<description><![CDATA[If you&#8217;ve spent any time with Apache Camel, you&#8217;ve likely wanted to make your routes more flexible. For example, you may want to redirect a route to a different endpoint based on changing criteria or conditions defined in a database. This post looks at two methods Apache Camel provides for altering your routes at runtime:...]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve spent any time with Apache Camel, you&#8217;ve likely wanted to make your routes more flexible.  For example, you may want to redirect a route to a different endpoint based on changing criteria or conditions defined in a database.  This post looks at two methods Apache Camel provides for altering your routes at runtime: Routing Slip and Dynamic Router.</p>
<h3>Routing Slip</h3>
<p>The first method to alter a route&#8217;s process is the Routing Slip pattern.  The Routing Slip allows you to define a list of endpoints that should receive the message.  In the Camel DSL, this looks like: </p>
<pre class="brush: java; title: ; notranslate">
from(&quot;direct:start&quot;).routingSlip(&quot;decisionSlip&quot;);
</pre>
<p>The &#8220;decisionSlip&#8221; is header placed on the exchange containing a delimited list of the destination endpoints.  The header can either be set on the ProducerTemplate:</p>
<pre class="brush: java; title: ; notranslate">
producerTemplate.sendBodyAndHeader(&quot;direct:start&quot;, 
  order, &quot;decisionSlip&quot;, 
  &quot;direct:verify-account,direct:check-inventory,direct:place-order&quot;);
</pre>
<p>or using a bean method returning a list of endpoints:</p>
<pre class="brush: java; title: ; notranslate">
from(&quot;direct:start&quot;)
  .setHeader(&quot;decisionSlip&quot;).method(OrderProcessorBean.class, &quot;calculateRoute&quot;)
  .routingSlip(&quot;decisionSlip&quot;);
</pre>
<p>Additionally, you can use the @RoutingSlip annotation on a bean method, then call the bean in your route.  First, the bean:</p>
<pre class="brush: java; title: ; notranslate">
public class OrderProcessorBean {
  @RoutingSlip
  public String calculateRoute(@Body Order order) {...}
}
</pre>
<p>Calling the the OrderProcessorBean and invoking the annotated method looks like any other Camel route:</p>
<pre class="brush: java; title: ; notranslate">
from(&quot;direct:start&quot;).bean(OrderProcessorBean.class);
</pre>
<p>While the @RoutingSlip annotation has its uses, I prefer to use other methods as the annotation isn&#8217;t obvious to the person reading or maintaining the route.</p>
<p>There are two important things to note about the Routing Slip.  First and most obvious, the header containing the delimited list must be set in the route before the routingSlip(&#8230;) call is reached.  The second point is the Routing Slip is only evaluated once, not after each step in the route.  To determine the destination endpoint after each point in the route, we need to use a Dynamic Router.</p>
<h3>Dynamic Router</h3>
<p>Building on the Routing Slip is the Dynamic Router.  Unlike the Routing Slip pattern, the Dynamic Router calculates the next endpoint at each step in the route.  For example, if the route &#8220;direct:verify-account&#8221; returned an unverified account, the Dynamic Router can reroute to &#8220;direct:create-account&#8221;.  The two steps to using a Dynamic Router are 1) define the logic and 2) define the route.  The routing logic can be defined in a bean:</p>
<pre class="brush: java; title: ; notranslate">
public class DynamicOrderProcessorBean {
  public String calculateRoute(@Body Order order, 
                               @Header(Exchange.SLIP_PREVIOUS) String prev) {
    if (prev == null) {
      return &quot;direct:verify-account&quot;;
    }
    else if (order.getStatus() == OrderStatus.NO_ACCOUNT) {
      return &quot;direct:create-account&quot;;
    }
    else if (order.getStatus() == OrderStatus.CHECK_INVENTORY) {
      return &quot;direct:check-inventory&quot;;
    }
    else if (order.getStatus() == OrderStatus.IN_STOCK) {
      return &quot;direct:place-order&quot;;
    }
    else {
      return null;
    }
  }
}
</pre>
<p>The above code is obviously contrived, but you get the idea.  With the bean defined, the next step is to define the route:</p>
<pre class="brush: java; title: ; notranslate">
from(&quot;direct:start&quot;)
  .dynamicRouter(DynamicOrderProcessorBean.class, &quot;calculateRoute&quot;);
</pre>
<p>That&#8217;s really all there is to the Dynamic Router.  Camel also supports a @DynamicRouter annotation which has similar usage to the @RoutingSlip annotation.  </p>
<p>To find out more information on dynamic routing with Apache Camel, be sure to read the documentation on the <a href="http://camel.apache.org/routing-slip.html" target="_blank">Routing Slip</a> and <a href="http://camel.apache.org/dynamic-router.html" target="_blank">Dynamic Router</a> patterns.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.systemmobile.com/?feed=rss2&#038;p=427</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Aggregating with MongoDB</title>
		<link>http://www.systemmobile.com/?p=412</link>
		<comments>http://www.systemmobile.com/?p=412#comments</comments>
		<pubDate>Thu, 01 Mar 2012 06:44:45 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Entry]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[spring framework]]></category>

		<guid isPermaLink="false">http://www.systemmobile.com/?p=412</guid>
		<description><![CDATA[Moving from a relational database to a NoSQL data store isn&#8217;t without some costs. If you&#8217;re like me and largely living in a Java world, one cost is immediately losing the expressiveness of ORM tools like Hibernate or JPA. Outside of the Java domain, several of SQL&#8217;s projection or aggregation functions are lost. For example,...]]></description>
			<content:encoded><![CDATA[<p>Moving from a relational database to a NoSQL data store isn&#8217;t without some costs.  If you&#8217;re like me and largely living in a Java world, one cost is immediately losing the expressiveness of ORM tools like Hibernate or JPA.  Outside of the Java domain, several of SQL&#8217;s projection or aggregation functions are lost. For example, it&#8217;s hard for any application to easily live without the count(), avg(), min() and max() functions.  </p>
<p>MongoDB, my choice for NoSQL data stores, addressed this shortcoming with its built-in map/reduce functionality.  Suppose you want to count number of blog posts Bill has made.  In a basic relational model, the SQL statement is straightforward:</p>
<pre class="brush: sql; title: ; notranslate">
select count(*) from blogposts where username='Bill';
</pre>
<p>Things are not so simple in MongoDB.  To accomplish the same thing as the SQL statement shown above, you need to break out a map/reduce function.  One representation of this function may look like: </p>
<pre class="brush: jscript; title: ; notranslate">
db.blogPosts.group({
    cond: {username: 'Bill'},
    reduce: function(obj,prev) { prev.count++ },
    initial: {count : 0},
});
</pre>
<p>We can see how this new function maps to the SQL statement.  The &#8216;cond&#8217; parameter defines the conditions we want to match.  In this case we&#8217;re selecting documents where the username attribute equals &#8220;Bill&#8221;.  Next we define the reduce function.  Put simply, this function does something with the objects the condition returns.  The reduce function is passed the current object (obj) and the counter object (prev).  Finally, the initial parameter initializes the attributes on the counter object.  Executing the above function returns the count: </p>
<pre class="brush: jscript; title: ; notranslate">
[ { &quot;count&quot; : 27 } ]
</pre>
<p>If you&#8217;re trying to accomplish this aggregation with the <a href="http://www.springsource.org/spring-data/mongodb" target="_blank">Spring Framework&#8217;s Data</a> project, it&#8217;s quite a bit more cumbersome:</p>
<pre class="brush: java; title: ; notranslate">
DBCollection collection = mongoTemplate.getCollection(&quot;blogPosts&quot;);
GroupCommand cmd = new GroupCommand(collection,
    null,
    new BasicDBObject(&quot;username&quot;, &quot;Bill&quot;),
    new BasicDBObject(&quot;count&quot;, 0),
    &quot;function(obj,prev) {prev.count++;}&quot;,
    null);
return collection.group(cmd);
</pre>
<p>The &#8216;collection.group(cmd)&#8217; statement returns a DBObject containing the count results.  </p>
<p>MongoDB 2.2 introduces a simplified aggregation framework, making these operations much easier to understand and implement.  This new aggregation framework will be the subject of a future post.  In the meantime, I hope this has shed some light on how to perform operations in MongoDB you would normally take for granted in relational databases.  This post has only scratched the surface of the current state of aggregation in MongoDB.  For the full scoop, refer to the <a href="http://www.mongodb.org/display/DOCS/Aggregation+Framework" target="_blank">MongoDB Aggregation Framework</a> documentation.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.systemmobile.com/?feed=rss2&#038;p=412</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple Master Election with Camel and ZooKeeper</title>
		<link>http://www.systemmobile.com/?p=399</link>
		<comments>http://www.systemmobile.com/?p=399#comments</comments>
		<pubDate>Tue, 28 Feb 2012 06:46:33 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Entry]]></category>
		<category><![CDATA[apache camel]]></category>
		<category><![CDATA[camel]]></category>
		<category><![CDATA[distributed systems]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[zookeeper]]></category>

		<guid isPermaLink="false">http://www.systemmobile.com/?p=399</guid>
		<description><![CDATA[Most modern, distributed applications require some form of coordination service to ensure tasks or jobs run only where they&#8217;re supposed to. For example, it may be necessary to run a cleanup task on dedicated servers. Writing your own master election or coordination service can be difficult. This is where Apache ZooKeeper comes in. ZooKeeper provides...]]></description>
			<content:encoded><![CDATA[<p>Most modern, distributed applications require some form of coordination service to ensure tasks or jobs run only where they&#8217;re supposed to. For example, it may be necessary to run a cleanup task on dedicated servers.  Writing your own master election or coordination service  can be difficult. This is where <a href="http://zookeeper.apache.org/" title="Apache ZooKeeper" target="_blank">Apache ZooKeeper</a> comes in.  ZooKeeper provides &#8220;centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services.&#8221;  </p>
<p>Unfortunately, ZooKeeper isn&#8217;t the easiest collection of services to just drop into your application.  The learning curve can be fairly steep.  This is where another Apache project comes in: <a href="http://camel.apache.org" title="Apache Camel" target="_blank">Camel</a>.  Camel provides a ZooKeeper component and some supporting classes to take advantage of ZooKeeper&#8217;s more powerful features.  The feature I&#8217;m most interested in is master election.  </p>
<p>Camel&#8217;s ZooKeeper component supports master election using a standard route policy.  The ZooKeeperRoutePolicy monitors a common znode on the ZooKeeper ensemble.  For example:</p>
<pre class="brush: java; title: ; notranslate">
ZooKeeperRoutePolicy routePolicy = 
    new ZooKeeperRoutePolicy(&quot;zookeeper://10.211.55.4:2181/status/reportgen&quot;, 1);
</pre>
<p>This route policy allows one client to bind to the &#8220;/status/reportgen&#8221; znode.  If I wanted three clients to be able to bind to the znode, I would simply change the number in the route policy to 3.  Once the route policy is defined, it is plugged into the route: </p>
<pre class="brush: java; title: ; notranslate">
from(&quot;quartz://cluster/heartbeat?cron=0/30+*+*+*+*+?&quot;)
    .routePolicy(routePolicy)
    .to(&quot;mock:generate-reports&quot;);
</pre>
<p>The above Camel route executes every 30 seconds.  The &#8220;mock:generate-reports&#8221; is only executed on the client able to bind to the relevant znode.</p>
<p>Before I discovered Camel&#8217;s ZooKeeper component, I tried several options for distributed master election, including ActiveMQ&#8217;s exclusive consumer and rolling my own master election process.  From my experience, ZooKeeper offers the easiest out of the box solution for a distributed environment.</p>
<p>In the future, I&#8217;ll explore some of the additional challenges I faced implementing Camel&#8217;s ZooKeeper component.  If you&#8217;re using ZooKeeper, let me know in the comments.  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.systemmobile.com/?feed=rss2&#038;p=399</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Performance problem in Apache Camel&#8217;s conversion mechanism</title>
		<link>http://www.systemmobile.com/?p=382</link>
		<comments>http://www.systemmobile.com/?p=382#comments</comments>
		<pubDate>Mon, 20 Feb 2012 00:12:08 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Entry]]></category>
		<category><![CDATA[apache camel]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[thread]]></category>

		<guid isPermaLink="false">http://www.systemmobile.com/?p=382</guid>
		<description><![CDATA[Performance testing a complex application is never particularly easy. In the best cases, it&#8217;s tedious and mildly frustrating. It&#8217;s easy to spend hours or days diagnosing why you&#8217;re not getting the expected throughput. This occurred just last week during some load and performance testing of an application making heavy use of Apache Camel. We found...]]></description>
			<content:encoded><![CDATA[<p>Performance testing a complex application is never particularly easy.  In the best cases, it&#8217;s tedious and mildly frustrating.  It&#8217;s easy to spend hours or days diagnosing why you&#8217;re not getting the expected throughput.  This occurred just last week during some load and performance testing of an application making heavy use of <a href="http://camel.apache.org" title="Link to Apache Camel website" target="_blank">Apache Camel</a>.  We found a number of blocked threads in the Tomcat executor pool which clearly limited the application&#8217;s throughput.  </p>
<p>After firing up YourKit, probably my second-favorite Java development utility to IDEA, the problem became readily apparent.  The Camel route passed a payload from CXF as a MessageContentsList to a custom Processor implementation which called the following:</p>
<pre class="brush: java; title: ; notranslate">
DecisionRequest req = exchange.getIn().getBody(DecisionRequest.class);
</pre>
<p>Since a conversion from MessageContentsList to DecisionRequest was required, Camel looks up the necessary converter in the BaseTypeConverterRegistry&#8217;s getOrFindTypeConverter(&#8230;) method.  Here&#8217;s the version of that method in Apache Camel 2.9.0:</p>
<pre class="brush: java; title: ; notranslate">
    protected &lt;T&gt; TypeConverter getOrFindTypeConverter(Class&lt;?&gt; toType, Object value) {
        Class&lt;?&gt; fromType = null;
        if (value != null) {
            fromType = value.getClass();
        }
        TypeMapping key = new TypeMapping(toType, fromType);
        TypeConverter converter;
        synchronized (typeMappings) {
            converter = typeMappings.get(key);
            if (converter == null) {
                converter = lookup(toType, fromType);
                if (converter != null) {
                    typeMappings.put(key, converter);
                }
            }
        }
        return converter;
    }
</pre>
<p>By synchronizing access to the collection of typeMappings, threads were forced to block until they could access the collection.  The easiest workaround was to avoid using Camel&#8217;s conversion mechanism and implement a custom converter in the processor.  </p>
<p>Luckily, the Apache Camel team was quick to recognize and resolve the problem.  The version of this method in Apache Camel 2.9.1 and 2.10 removes this block.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.systemmobile.com/?feed=rss2&#038;p=382</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Your Data For Sale</title>
		<link>http://www.systemmobile.com/?p=370</link>
		<comments>http://www.systemmobile.com/?p=370#comments</comments>
		<pubDate>Thu, 09 Feb 2012 06:35:16 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Entry]]></category>
		<category><![CDATA[advanced advertising]]></category>
		<category><![CDATA[invidi]]></category>
		<category><![CDATA[privacy]]></category>

		<guid isPermaLink="false">http://www.systemmobile.com/?p=370</guid>
		<description><![CDATA[Earlier this week Joseph Turow published an article on The Atlantic&#8217;s website titled &#8220;A Guide to the Digital Advertising Industry That&#8217;s Watching Your Every Click&#8221;. The article presented a few scenarios surrounding the level of targeted messaging available to marketers with digital tracking, as well as an overview of public reaction. One aspect left unexplored...]]></description>
			<content:encoded><![CDATA[<p>Earlier this week Joseph Turow published an article on The Atlantic&#8217;s website titled <a href="http://www.theatlantic.com/technology/archive/2012/02/a-guide-to-the-digital-advertising-industry-thats-watching-your-every-click/252667/" title="A Guide to the Digital Advertising Industry That's Watching Your Every Click" target="_blank">&#8220;A Guide to the Digital Advertising Industry That&#8217;s Watching Your Every Click&#8221;</a>.  The article presented a few scenarios surrounding the level of targeted messaging available to marketers with digital tracking, as well as an overview of public reaction.  One aspect left unexplored is who is investing in these companies, especially Invidi.  </p>
<p>In 2010, Invidi <a href="http://news.cnet.com/8301-1023_3-20004172-93.html" title="Google ups its TV bet, invests in Invidi" target="_blank">closed a $23m investment round</a>.  The round was led by Google, arguably the keeper of more personal data than any other company, except for possibly Facebook.  The Google investment isn&#8217;t earth-shattering.  After all, Google&#8217;s quarterly golden egg is driven by advertising.  Another company taking part in Invidi&#8217;s Series D round is far more disturbing.  </p>
<p>Experian, the global purveyor of consumer information, not only invested in Invidi, but formed a partnership and obtained an observer seat on Invidi&#8217;s board of directors.  Experian was able to buy a place at the digital advertising table for a few million dollars.  The close relationship between a source of consumer data and a company able to translate that into pervasive advertising decisions signals the further erosion of consumer privacy.  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.systemmobile.com/?feed=rss2&#038;p=370</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
