# Atom Component

## Overview

The Atom component is used for polling atom feeds.

Apache Camel will poll the feed every 60 seconds by default.

| Note
The component currently only supports polling (consuming) feeds.

## Set-up

Maven users will need to add the dependency shown in Example 20, “Atom dependency” to their `pom.xml` to use this component.

Example 20. Atom dependency

    <dependency>
        <groupId>org.apache.camel</groupId>
        <artifactId>camel-atom</artifactId>
        <version>x.x.x</version>
        <!-- use the same version as your Camel core version -->
    </dependency>

## URI format

The URI format for an Atom endpoint is:

    atom://atomUri[?options]

`atomUri` specifies the URI to the Atom feed to poll.

## Options

Table 50, “Atom Component Options” list the options for the Atom endpoint.

Table 50. Atom Component Options

Property | Default | Description
--- | --- | ---
`splitEntries` | `true` | If `true` Apache Camel will poll the feed and for the subsequent polls return each entry poll by poll. If the feed contains 7 entries then Apache Camel will return the first entry on the first poll, the 2nd entry on the next poll, until no more entries where as Apache Camel will do a new update on the feed. If `false` then Apache Camel will poll a fresh feed on every invocation.
`filter` | `true` | Is only used by the split entries to filter the entries to return. Apache Camel will default use the `UpdateDateFilter` that only return new entries from the feed. So the client consuming from the feed never receives the same entry more than once. The filter will return the entries ordered by the newest last.
`lastUpdate` | `null` | Is only used by the filter, as the starting timestamp for selection never entries (uses the `entry.updated` timestamp). Syntax format is: `yyyy-MM-ddTHH:MM:ss`. Example: `2007-12-24T17:45:59`.
`throttleEntries` | `true` | Sets whether all entries identified in a single feed poll should be delivered immediately. If `true`, only one entry is processed per `consumer.delay`. Only applicable when `splitEntries` is set to `true`.
`feedHeader` | `true` | Sets whether to add the Abdera Feed object as a header.
`sortEntries` | `false` | If `splitEntries` is `true`, this sets whether to sort those entries by updated date.
`consumer.delay` | `60000` | Delay in milliseconds between each poll.
`consumer.initialDelay` | `1000` | Specifies the number of milliseconds before polling starts.
`consumer.userFixedDelay` | `false` | If `true`, use fixed delay between pools, otherwise fixed rate is used. See ScheduledExecutorService in JDK for details.

## Exchange data format

Apache Camel will set the In body on the returned `Exchange` with the entries. Depending on the `splitEntries` flag, Apache Camel will either return one `Entry` or a `List<Entry>`.

Option | Value | Behavior
--- | --- | ---
`splitEntries` | `true` | Only a single entry from the currently being processed feed is set: `exchange.in.body(Entry)`
`splitEntries` | `false` | The entire list of entries from the feed is set: `exchange.in.body(List<Entry>)`

Apache Camel can set the `Feed` object on the in header (see `feedHeader` option to disable this):

## Message Headers

Apache Camel atom uses these headers.

Header | Description
--- | ---
`org.apache.camel.component.atom.feed` | Apache Camel 1.x: When consuming the `org.apache.abdera.model.Feed` object is set to this header.
`CamelAtomFeed` | Apache Camel 2.0: When consuming the `org.apache.abdera.model.Feed` object is set to this header.

## Samples

In the following sample we poll James Strachan's blog:

    from("atom://http://macstrac.blogspot.com/feeds/posts/default").to("seda:feeds");

In this sample we want to filter only good blogs we like to a SEDA queue. The sample also shows how to set up Apache Camel standalone, not running in any container or using Spring.

    @Override
    protected CamelContext createCamelContext() throws Exception {
        // We initialize Camel

        SimpleRegistry registry = new SimpleRegistry();
        // First we register a blog service in our bean registry
        registry.put("blogService", new BlogService());

        // Then we create the camel context with our bean registry
        context = new DefaultCamelContext(registry);

        // Then we add all the routes we need using the route builder DSL syntax
        context.addRoutes(createRouteBuilder());

        // And finally we must start Camel to let the magic routing begins
        context.start();

        return context;
    }

    /**
     * This is the route builder where we create our routes in the advanced Camel DSL syntax
     */
    protected RouteBuilder createRouteBuilder() throws Exception {
        return new RouteBuilder() {
            public void configure() throws Exception {
                // We pool the atom feeds from the source for further processing in the seda queue
                // we set the delay to 1 second for each pool as this is a unit test also and we can
                // not wait the default poll interval of 60 seconds.
                // Using splitEntries=true will during polling only fetch one Atom Entry at any given time.
                // As the feed.atom file contains 7 entries, using this will require 7 polls to fetch the entire
                // content. When Camel have reach the end of entries it will refresh the atom feed from URI source
                // and restart - but as Camel by default uses the UpdatedDateFilter it will only deliver new
                // blog entries to "seda:feeds". So only when James Straham updates his blog with a new entry
                // Camel will create an exchange for the seda:feeds.
                from("atom:file:src/test/data/feed.atom?splitEntries=true&consumer.delay=1000").to("seda:feeds");

                // From the feeds we filter each blot entry by using our blog service class
                from("seda:feeds").filter().method("blogService", "isGoodBlog").to("seda:goodBlogs");

                // And the good blogs is moved to a mock queue as this sample is also used for unit testing
                // this is one of the strengths in Camel that you can also use the mock endpoint for your
                // unit tests
                from("seda:goodBlogs").to("mock:result");
            }
        };
    }

    /**
     * This is the actual junit test method that does the assertion that our routes is working
     * as expected
     */
    @Test
    public void testFiltering() throws Exception {
        // Get the mock endpoint
        MockEndpoint mock = context.getEndpoint("mock:result", MockEndpoint.class);

        // There should be two good blog entries from the feed
        mock.expectedMinimumMessageCount(2);

        // Asserts that the above expectations is true, will throw assertions exception if it failed
        // Camel will default wait max 20 seconds for the assertions to be true, if the conditions
        // is true sooner Camel will continue
        mock.assertIsSatisfied();
    }

    /**
     * Services for blogs
     */
    public class BlogService {

        /**
         * Tests the blogs if its a good blog entry or not
         */
        public boolean isGoodBlog(Exchange exchange) {
            Entry entry = exchange.getIn().getBody(Entry.class);
            String title = entry.getTitle();

            // We like blogs about Camel
            boolean good = title.toLowerCase().contains("camel");
            return good;
        }

    }