This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 010251049e09 CAMEL-23220: Added support for idempotent consumption in 
the camel-at… (#22114)
010251049e09 is described below

commit 010251049e0929e63573b158a025897cbc6dab46
Author: Dennis Bohnstedt <[email protected]>
AuthorDate: Thu Apr 30 10:07:35 2026 +0200

    CAMEL-23220: Added support for idempotent consumption in the camel-at… 
(#22114)
    
    * CAMEL-23220: Added support for idempotent consumption in the camel-atom 
component.
    
    The fix support idempotency with a plugable strategy for recognizing 
already seen atom entries. Them component defaults to
    idempotent consumption, as it did in versions up to 3.16.
    
    * CAMEL-23220: Added camel-catalog file for Camel-Atom idempotency options
    
    * CAMEL-23220: Added missing AtomEndpointBuilderFactory for Camel-Atom 
idempotency change
    
    * CAMEL-23220: Added @UriParam for idempotentRepository to enable pluggable 
IdempotentRepository selection, and updated documentation of idempotency in the 
compoent.
---
 .../org/apache/camel/catalog/components/atom.json  |  31 +-
 .../component/atom/AtomEndpointConfigurer.java     |  15 +
 .../component/atom/AtomEndpointUriFactory.java     |   5 +-
 .../org/apache/camel/component/atom/atom.json      |  31 +-
 .../camel-atom/src/main/docs/atom-component.adoc   |  38 +++
 .../apache/camel/component/atom/AtomComponent.java |  45 ++-
 .../apache/camel/component/atom/AtomEndpoint.java  |  48 ++++
 .../component/atom/AtomEntryPollingConsumer.java   |  18 +-
 .../component/atom/AtomIdempotentStrategy.java     |  27 ++
 .../atom/ItemUpdatedIdempotentStrategy.java        |  66 +++++
 .../atom/RepositoryGuidIdempotentStrategy.java     |  58 ++++
 .../component/feed/FeedEntryPollingConsumer.java   |  16 +-
 .../camel-atom/src/test/data/updated-feed.atom     | 316 +++++++++++++++++++++
 .../atom/AtomGoodBlogDefaultIdempotencyTest.java   | 125 ++++++++
 .../atom/AtomGoodBlogNotIdempotentTest.java        |  76 +++++
 ...ava => AtomGoodBlogsCustomItempotencyTest.java} |  70 ++---
 ...sRepositoryItempotencyCustomRepositoryTest.java | 113 ++++++++
 ...=> AtomGoodBlogsRepositoryItempotencyTest.java} |  80 ++----
 .../camel/component/atom/AtomGoodBlogsTest.java    |   2 +-
 .../atom/ItemUpdatedIdempotentStrategyTest.java    | 117 ++++++++
 .../atom/RepositoryGuidIdempotentStrategyTest.java |  68 +++++
 .../endpoint/dsl/AtomEndpointBuilderFactory.java   | 124 ++++++++
 22 files changed, 1357 insertions(+), 132 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/atom.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/atom.json
index b72bfb770777..2d648aab5ee9 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/atom.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/atom.json
@@ -41,19 +41,22 @@
     "exchangePattern": { "index": 7, "kind": "parameter", "displayName": 
"Exchange Pattern", "group": "consumer (advanced)", "label": 
"consumer,advanced", "required": false, "type": "enum", "javaType": 
"org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], 
"deprecated": false, "autowired": false, "secret": false, "description": "Sets 
the exchange pattern when the consumer creates an exchange." },
     "pollStrategy": { "index": 8, "kind": "parameter", "displayName": "Poll 
Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", 
"required": false, "type": "object", "javaType": 
"org.apache.camel.spi.PollingConsumerPollStrategy", "deprecated": false, 
"autowired": false, "secret": false, "description": "A pluggable 
org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your 
custom implementation to control error handling usually occurred during the pol 
[...]
     "feedHeader": { "index": 9, "kind": "parameter", "displayName": "Feed 
Header", "group": "advanced", "label": "advanced", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": true, "description": "Sets whether to add the 
feed object as a header." },
-    "backoffErrorThreshold": { "index": 10, "kind": "parameter", 
"displayName": "Backoff Error Threshold", "group": "scheduler", "label": 
"consumer,scheduler", "required": false, "type": "integer", "javaType": "int", 
"deprecated": false, "autowired": false, "secret": false, "description": "The 
number of subsequent error polls (failed due some error) that should happen 
before the backoffMultipler should kick-in." },
-    "backoffIdleThreshold": { "index": 11, "kind": "parameter", "displayName": 
"Backoff Idle Threshold", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "integer", "javaType": "int", "deprecated": false, 
"autowired": false, "secret": false, "description": "The number of subsequent 
idle polls that should happen before the backoffMultipler should kick-in." },
-    "backoffMultiplier": { "index": 12, "kind": "parameter", "displayName": 
"Backoff Multiplier", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "integer", "javaType": "int", "deprecated": false, 
"autowired": false, "secret": false, "description": "To let the scheduled 
polling consumer backoff if there has been a number of subsequent idles\/errors 
in a row. The multiplier is then the number of polls that will be skipped 
before the next actual attempt is h [...]
-    "delay": { "index": 13, "kind": "parameter", "displayName": "Delay", 
"group": "scheduler", "label": "consumer,scheduler", "required": false, "type": 
"integer", "javaType": "long", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 500, "description": "Milliseconds before the 
next poll." },
-    "greedy": { "index": 14, "kind": "parameter", "displayName": "Greedy", 
"group": "scheduler", "label": "consumer,scheduler", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": false, "description": "If greedy is enabled, 
then the ScheduledPollConsumer will run immediately again, if the previous run 
polled 1 or more messages." },
-    "initialDelay": { "index": 15, "kind": "parameter", "displayName": 
"Initial Delay", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "integer", "javaType": "long", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": 1000, "description": 
"Milliseconds before the first poll starts." },
-    "repeatCount": { "index": 16, "kind": "parameter", "displayName": "Repeat 
Count", "group": "scheduler", "label": "consumer,scheduler", "required": false, 
"type": "integer", "javaType": "long", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 0, "description": "Specifies a maximum limit 
of number of fires. So if you set it to 1, the scheduler will only fire once. 
If you set it to 5, it will only fire five times. A value of zero or negative 
means fire forever." },
-    "runLoggingLevel": { "index": 17, "kind": "parameter", "displayName": "Run 
Logging Level", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "enum", "javaType": "org.apache.camel.LoggingLevel", 
"enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": 
false, "autowired": false, "secret": false, "defaultValue": "TRACE", 
"description": "The consumer logs a start\/complete log line when it polls. 
This option allows you to configure the log [...]
-    "scheduledExecutorService": { "index": 18, "kind": "parameter", 
"displayName": "Scheduled Executor Service", "group": "scheduler", "label": 
"consumer,scheduler", "required": false, "type": "object", "javaType": 
"java.util.concurrent.ScheduledExecutorService", "deprecated": false, 
"autowired": false, "secret": false, "description": "Allows for configuring a 
custom\/shared thread pool to use for the consumer. By default each consumer 
has its own single threaded thread pool." },
-    "scheduler": { "index": 19, "kind": "parameter", "displayName": 
"Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": 
false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": "none", "description": "To 
use a cron scheduler from either camel-spring or camel-quartz component. Use 
value spring or quartz for built in scheduler" },
-    "schedulerProperties": { "index": 20, "kind": "parameter", "displayName": 
"Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "object", "javaType": 
"java.util.Map<java.lang.String, java.lang.Object>", "prefix": "scheduler.", 
"multiValue": true, "deprecated": false, "autowired": false, "secret": false, 
"description": "To configure additional properties when using a custom 
scheduler or any of the Quartz, Spring based scheduler. This i [...]
-    "startScheduler": { "index": 21, "kind": "parameter", "displayName": 
"Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "boolean", "javaType": "boolean", "deprecated": 
false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Whether the scheduler should be auto started." },
-    "timeUnit": { "index": 22, "kind": "parameter", "displayName": "Time 
Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, 
"type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [ 
"NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", 
"DAYS" ], "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and 
delay options." },
-    "useFixedDelay": { "index": 23, "kind": "parameter", "displayName": "Use 
Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in 
JDK for details." }
+    "idempotent": { "index": 10, "kind": "parameter", "displayName": 
"Idempotent", "group": "filter", "label": "consumer,filter", "required": false, 
"type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": true, "description": "Option to use the 
Idempotent Consumer EIP pattern to let Camel skip already processed entries. By 
default it skips Atom entries that is older that the last read entry, using 
Atom updatedDate and publishedD [...]
+    "idempotentRepository": { "index": 11, "kind": "parameter", "displayName": 
"Idempotent Repository", "group": "filter", "label": "consumer,filter", 
"required": false, "type": "object", "javaType": 
"org.apache.camel.spi.IdempotentRepository", "deprecated": false, "autowired": 
false, "secret": false, "description": "A pluggable repository 
org.apache.camel.spi.IdempotentRepository which by default use 
MemoryIdempotentRepository if none is specified and idempotent is true." },
+    "idempotentStrategy": { "index": 12, "kind": "parameter", "displayName": 
"Idempotent Strategy", "group": "filter (advanced)", "label": 
"consumer,filter,advanced", "required": false, "type": "enum", "javaType": 
"org.apache.camel.component.atom.AtomIdempotentStrategy", "enum": [ "default", 
"repository" ], "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "default", "description": "A pluggable strategy 
org.apache.camel.component.FeedIdempotentStrategy to use when [...]
+    "backoffErrorThreshold": { "index": 13, "kind": "parameter", 
"displayName": "Backoff Error Threshold", "group": "scheduler", "label": 
"consumer,scheduler", "required": false, "type": "integer", "javaType": "int", 
"deprecated": false, "autowired": false, "secret": false, "description": "The 
number of subsequent error polls (failed due some error) that should happen 
before the backoffMultipler should kick-in." },
+    "backoffIdleThreshold": { "index": 14, "kind": "parameter", "displayName": 
"Backoff Idle Threshold", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "integer", "javaType": "int", "deprecated": false, 
"autowired": false, "secret": false, "description": "The number of subsequent 
idle polls that should happen before the backoffMultipler should kick-in." },
+    "backoffMultiplier": { "index": 15, "kind": "parameter", "displayName": 
"Backoff Multiplier", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "integer", "javaType": "int", "deprecated": false, 
"autowired": false, "secret": false, "description": "To let the scheduled 
polling consumer backoff if there has been a number of subsequent idles\/errors 
in a row. The multiplier is then the number of polls that will be skipped 
before the next actual attempt is h [...]
+    "delay": { "index": 16, "kind": "parameter", "displayName": "Delay", 
"group": "scheduler", "label": "consumer,scheduler", "required": false, "type": 
"integer", "javaType": "long", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 500, "description": "Milliseconds before the 
next poll." },
+    "greedy": { "index": 17, "kind": "parameter", "displayName": "Greedy", 
"group": "scheduler", "label": "consumer,scheduler", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": false, "description": "If greedy is enabled, 
then the ScheduledPollConsumer will run immediately again, if the previous run 
polled 1 or more messages." },
+    "initialDelay": { "index": 18, "kind": "parameter", "displayName": 
"Initial Delay", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "integer", "javaType": "long", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": 1000, "description": 
"Milliseconds before the first poll starts." },
+    "repeatCount": { "index": 19, "kind": "parameter", "displayName": "Repeat 
Count", "group": "scheduler", "label": "consumer,scheduler", "required": false, 
"type": "integer", "javaType": "long", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 0, "description": "Specifies a maximum limit 
of number of fires. So if you set it to 1, the scheduler will only fire once. 
If you set it to 5, it will only fire five times. A value of zero or negative 
means fire forever." },
+    "runLoggingLevel": { "index": 20, "kind": "parameter", "displayName": "Run 
Logging Level", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "enum", "javaType": "org.apache.camel.LoggingLevel", 
"enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": 
false, "autowired": false, "secret": false, "defaultValue": "TRACE", 
"description": "The consumer logs a start\/complete log line when it polls. 
This option allows you to configure the log [...]
+    "scheduledExecutorService": { "index": 21, "kind": "parameter", 
"displayName": "Scheduled Executor Service", "group": "scheduler", "label": 
"consumer,scheduler", "required": false, "type": "object", "javaType": 
"java.util.concurrent.ScheduledExecutorService", "deprecated": false, 
"autowired": false, "secret": false, "description": "Allows for configuring a 
custom\/shared thread pool to use for the consumer. By default each consumer 
has its own single threaded thread pool." },
+    "scheduler": { "index": 22, "kind": "parameter", "displayName": 
"Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": 
false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": "none", "description": "To 
use a cron scheduler from either camel-spring or camel-quartz component. Use 
value spring or quartz for built in scheduler" },
+    "schedulerProperties": { "index": 23, "kind": "parameter", "displayName": 
"Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "object", "javaType": 
"java.util.Map<java.lang.String, java.lang.Object>", "prefix": "scheduler.", 
"multiValue": true, "deprecated": false, "autowired": false, "secret": false, 
"description": "To configure additional properties when using a custom 
scheduler or any of the Quartz, Spring based scheduler. This i [...]
+    "startScheduler": { "index": 24, "kind": "parameter", "displayName": 
"Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "boolean", "javaType": "boolean", "deprecated": 
false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Whether the scheduler should be auto started." },
+    "timeUnit": { "index": 25, "kind": "parameter", "displayName": "Time 
Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, 
"type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [ 
"NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", 
"DAYS" ], "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and 
delay options." },
+    "useFixedDelay": { "index": 26, "kind": "parameter", "displayName": "Use 
Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in 
JDK for details." }
   }
 }
diff --git 
a/components/camel-atom/src/generated/java/org/apache/camel/component/atom/AtomEndpointConfigurer.java
 
b/components/camel-atom/src/generated/java/org/apache/camel/component/atom/AtomEndpointConfigurer.java
index b99264ba8ca6..5a8ebb8798f2 100644
--- 
a/components/camel-atom/src/generated/java/org/apache/camel/component/atom/AtomEndpointConfigurer.java
+++ 
b/components/camel-atom/src/generated/java/org/apache/camel/component/atom/AtomEndpointConfigurer.java
@@ -39,6 +39,11 @@ public class AtomEndpointConfigurer extends 
PropertyConfigurerSupport implements
         case "feedheader":
         case "feedHeader": target.setFeedHeader(property(camelContext, 
boolean.class, value)); return true;
         case "greedy": target.setGreedy(property(camelContext, boolean.class, 
value)); return true;
+        case "idempotent": target.setIdempotent(property(camelContext, 
boolean.class, value)); return true;
+        case "idempotentrepository":
+        case "idempotentRepository": 
target.setIdempotentRepository(property(camelContext, 
org.apache.camel.spi.IdempotentRepository.class, value)); return true;
+        case "idempotentstrategy":
+        case "idempotentStrategy": 
target.setIdempotentStrategy(property(camelContext, 
org.apache.camel.component.atom.AtomIdempotentStrategy.class, value)); return 
true;
         case "initialdelay":
         case "initialDelay": target.setInitialDelay(property(camelContext, 
long.class, value)); return true;
         case "pollstrategy":
@@ -89,6 +94,11 @@ public class AtomEndpointConfigurer extends 
PropertyConfigurerSupport implements
         case "feedheader":
         case "feedHeader": return boolean.class;
         case "greedy": return boolean.class;
+        case "idempotent": return boolean.class;
+        case "idempotentrepository":
+        case "idempotentRepository": return 
org.apache.camel.spi.IdempotentRepository.class;
+        case "idempotentstrategy":
+        case "idempotentStrategy": return 
org.apache.camel.component.atom.AtomIdempotentStrategy.class;
         case "initialdelay":
         case "initialDelay": return long.class;
         case "pollstrategy":
@@ -140,6 +150,11 @@ public class AtomEndpointConfigurer extends 
PropertyConfigurerSupport implements
         case "feedheader":
         case "feedHeader": return target.isFeedHeader();
         case "greedy": return target.isGreedy();
+        case "idempotent": return target.isIdempotent();
+        case "idempotentrepository":
+        case "idempotentRepository": return target.getIdempotentRepository();
+        case "idempotentstrategy":
+        case "idempotentStrategy": return target.getIdempotentStrategy();
         case "initialdelay":
         case "initialDelay": return target.getInitialDelay();
         case "pollstrategy":
diff --git 
a/components/camel-atom/src/generated/java/org/apache/camel/component/atom/AtomEndpointUriFactory.java
 
b/components/camel-atom/src/generated/java/org/apache/camel/component/atom/AtomEndpointUriFactory.java
index d44ac38da116..4b62c6fcb83d 100644
--- 
a/components/camel-atom/src/generated/java/org/apache/camel/component/atom/AtomEndpointUriFactory.java
+++ 
b/components/camel-atom/src/generated/java/org/apache/camel/component/atom/AtomEndpointUriFactory.java
@@ -23,7 +23,7 @@ public class AtomEndpointUriFactory extends 
org.apache.camel.support.component.E
     private static final Set<String> SECRET_PROPERTY_NAMES;
     private static final Map<String, String> MULTI_VALUE_PREFIXES;
     static {
-        Set<String> props = new HashSet<>(24);
+        Set<String> props = new HashSet<>(27);
         props.add("backoffErrorThreshold");
         props.add("backoffIdleThreshold");
         props.add("backoffMultiplier");
@@ -34,6 +34,9 @@ public class AtomEndpointUriFactory extends 
org.apache.camel.support.component.E
         props.add("feedHeader");
         props.add("feedUri");
         props.add("greedy");
+        props.add("idempotent");
+        props.add("idempotentRepository");
+        props.add("idempotentStrategy");
         props.add("initialDelay");
         props.add("pollStrategy");
         props.add("repeatCount");
diff --git 
a/components/camel-atom/src/generated/resources/META-INF/org/apache/camel/component/atom/atom.json
 
b/components/camel-atom/src/generated/resources/META-INF/org/apache/camel/component/atom/atom.json
index b72bfb770777..2d648aab5ee9 100644
--- 
a/components/camel-atom/src/generated/resources/META-INF/org/apache/camel/component/atom/atom.json
+++ 
b/components/camel-atom/src/generated/resources/META-INF/org/apache/camel/component/atom/atom.json
@@ -41,19 +41,22 @@
     "exchangePattern": { "index": 7, "kind": "parameter", "displayName": 
"Exchange Pattern", "group": "consumer (advanced)", "label": 
"consumer,advanced", "required": false, "type": "enum", "javaType": 
"org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], 
"deprecated": false, "autowired": false, "secret": false, "description": "Sets 
the exchange pattern when the consumer creates an exchange." },
     "pollStrategy": { "index": 8, "kind": "parameter", "displayName": "Poll 
Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", 
"required": false, "type": "object", "javaType": 
"org.apache.camel.spi.PollingConsumerPollStrategy", "deprecated": false, 
"autowired": false, "secret": false, "description": "A pluggable 
org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your 
custom implementation to control error handling usually occurred during the pol 
[...]
     "feedHeader": { "index": 9, "kind": "parameter", "displayName": "Feed 
Header", "group": "advanced", "label": "advanced", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": true, "description": "Sets whether to add the 
feed object as a header." },
-    "backoffErrorThreshold": { "index": 10, "kind": "parameter", 
"displayName": "Backoff Error Threshold", "group": "scheduler", "label": 
"consumer,scheduler", "required": false, "type": "integer", "javaType": "int", 
"deprecated": false, "autowired": false, "secret": false, "description": "The 
number of subsequent error polls (failed due some error) that should happen 
before the backoffMultipler should kick-in." },
-    "backoffIdleThreshold": { "index": 11, "kind": "parameter", "displayName": 
"Backoff Idle Threshold", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "integer", "javaType": "int", "deprecated": false, 
"autowired": false, "secret": false, "description": "The number of subsequent 
idle polls that should happen before the backoffMultipler should kick-in." },
-    "backoffMultiplier": { "index": 12, "kind": "parameter", "displayName": 
"Backoff Multiplier", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "integer", "javaType": "int", "deprecated": false, 
"autowired": false, "secret": false, "description": "To let the scheduled 
polling consumer backoff if there has been a number of subsequent idles\/errors 
in a row. The multiplier is then the number of polls that will be skipped 
before the next actual attempt is h [...]
-    "delay": { "index": 13, "kind": "parameter", "displayName": "Delay", 
"group": "scheduler", "label": "consumer,scheduler", "required": false, "type": 
"integer", "javaType": "long", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 500, "description": "Milliseconds before the 
next poll." },
-    "greedy": { "index": 14, "kind": "parameter", "displayName": "Greedy", 
"group": "scheduler", "label": "consumer,scheduler", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": false, "description": "If greedy is enabled, 
then the ScheduledPollConsumer will run immediately again, if the previous run 
polled 1 or more messages." },
-    "initialDelay": { "index": 15, "kind": "parameter", "displayName": 
"Initial Delay", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "integer", "javaType": "long", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": 1000, "description": 
"Milliseconds before the first poll starts." },
-    "repeatCount": { "index": 16, "kind": "parameter", "displayName": "Repeat 
Count", "group": "scheduler", "label": "consumer,scheduler", "required": false, 
"type": "integer", "javaType": "long", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 0, "description": "Specifies a maximum limit 
of number of fires. So if you set it to 1, the scheduler will only fire once. 
If you set it to 5, it will only fire five times. A value of zero or negative 
means fire forever." },
-    "runLoggingLevel": { "index": 17, "kind": "parameter", "displayName": "Run 
Logging Level", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "enum", "javaType": "org.apache.camel.LoggingLevel", 
"enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": 
false, "autowired": false, "secret": false, "defaultValue": "TRACE", 
"description": "The consumer logs a start\/complete log line when it polls. 
This option allows you to configure the log [...]
-    "scheduledExecutorService": { "index": 18, "kind": "parameter", 
"displayName": "Scheduled Executor Service", "group": "scheduler", "label": 
"consumer,scheduler", "required": false, "type": "object", "javaType": 
"java.util.concurrent.ScheduledExecutorService", "deprecated": false, 
"autowired": false, "secret": false, "description": "Allows for configuring a 
custom\/shared thread pool to use for the consumer. By default each consumer 
has its own single threaded thread pool." },
-    "scheduler": { "index": 19, "kind": "parameter", "displayName": 
"Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": 
false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": "none", "description": "To 
use a cron scheduler from either camel-spring or camel-quartz component. Use 
value spring or quartz for built in scheduler" },
-    "schedulerProperties": { "index": 20, "kind": "parameter", "displayName": 
"Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "object", "javaType": 
"java.util.Map<java.lang.String, java.lang.Object>", "prefix": "scheduler.", 
"multiValue": true, "deprecated": false, "autowired": false, "secret": false, 
"description": "To configure additional properties when using a custom 
scheduler or any of the Quartz, Spring based scheduler. This i [...]
-    "startScheduler": { "index": 21, "kind": "parameter", "displayName": 
"Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "boolean", "javaType": "boolean", "deprecated": 
false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Whether the scheduler should be auto started." },
-    "timeUnit": { "index": 22, "kind": "parameter", "displayName": "Time 
Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, 
"type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [ 
"NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", 
"DAYS" ], "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and 
delay options." },
-    "useFixedDelay": { "index": 23, "kind": "parameter", "displayName": "Use 
Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in 
JDK for details." }
+    "idempotent": { "index": 10, "kind": "parameter", "displayName": 
"Idempotent", "group": "filter", "label": "consumer,filter", "required": false, 
"type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": true, "description": "Option to use the 
Idempotent Consumer EIP pattern to let Camel skip already processed entries. By 
default it skips Atom entries that is older that the last read entry, using 
Atom updatedDate and publishedD [...]
+    "idempotentRepository": { "index": 11, "kind": "parameter", "displayName": 
"Idempotent Repository", "group": "filter", "label": "consumer,filter", 
"required": false, "type": "object", "javaType": 
"org.apache.camel.spi.IdempotentRepository", "deprecated": false, "autowired": 
false, "secret": false, "description": "A pluggable repository 
org.apache.camel.spi.IdempotentRepository which by default use 
MemoryIdempotentRepository if none is specified and idempotent is true." },
+    "idempotentStrategy": { "index": 12, "kind": "parameter", "displayName": 
"Idempotent Strategy", "group": "filter (advanced)", "label": 
"consumer,filter,advanced", "required": false, "type": "enum", "javaType": 
"org.apache.camel.component.atom.AtomIdempotentStrategy", "enum": [ "default", 
"repository" ], "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "default", "description": "A pluggable strategy 
org.apache.camel.component.FeedIdempotentStrategy to use when [...]
+    "backoffErrorThreshold": { "index": 13, "kind": "parameter", 
"displayName": "Backoff Error Threshold", "group": "scheduler", "label": 
"consumer,scheduler", "required": false, "type": "integer", "javaType": "int", 
"deprecated": false, "autowired": false, "secret": false, "description": "The 
number of subsequent error polls (failed due some error) that should happen 
before the backoffMultipler should kick-in." },
+    "backoffIdleThreshold": { "index": 14, "kind": "parameter", "displayName": 
"Backoff Idle Threshold", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "integer", "javaType": "int", "deprecated": false, 
"autowired": false, "secret": false, "description": "The number of subsequent 
idle polls that should happen before the backoffMultipler should kick-in." },
+    "backoffMultiplier": { "index": 15, "kind": "parameter", "displayName": 
"Backoff Multiplier", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "integer", "javaType": "int", "deprecated": false, 
"autowired": false, "secret": false, "description": "To let the scheduled 
polling consumer backoff if there has been a number of subsequent idles\/errors 
in a row. The multiplier is then the number of polls that will be skipped 
before the next actual attempt is h [...]
+    "delay": { "index": 16, "kind": "parameter", "displayName": "Delay", 
"group": "scheduler", "label": "consumer,scheduler", "required": false, "type": 
"integer", "javaType": "long", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 500, "description": "Milliseconds before the 
next poll." },
+    "greedy": { "index": 17, "kind": "parameter", "displayName": "Greedy", 
"group": "scheduler", "label": "consumer,scheduler", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": false, "description": "If greedy is enabled, 
then the ScheduledPollConsumer will run immediately again, if the previous run 
polled 1 or more messages." },
+    "initialDelay": { "index": 18, "kind": "parameter", "displayName": 
"Initial Delay", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "integer", "javaType": "long", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": 1000, "description": 
"Milliseconds before the first poll starts." },
+    "repeatCount": { "index": 19, "kind": "parameter", "displayName": "Repeat 
Count", "group": "scheduler", "label": "consumer,scheduler", "required": false, 
"type": "integer", "javaType": "long", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 0, "description": "Specifies a maximum limit 
of number of fires. So if you set it to 1, the scheduler will only fire once. 
If you set it to 5, it will only fire five times. A value of zero or negative 
means fire forever." },
+    "runLoggingLevel": { "index": 20, "kind": "parameter", "displayName": "Run 
Logging Level", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "enum", "javaType": "org.apache.camel.LoggingLevel", 
"enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": 
false, "autowired": false, "secret": false, "defaultValue": "TRACE", 
"description": "The consumer logs a start\/complete log line when it polls. 
This option allows you to configure the log [...]
+    "scheduledExecutorService": { "index": 21, "kind": "parameter", 
"displayName": "Scheduled Executor Service", "group": "scheduler", "label": 
"consumer,scheduler", "required": false, "type": "object", "javaType": 
"java.util.concurrent.ScheduledExecutorService", "deprecated": false, 
"autowired": false, "secret": false, "description": "Allows for configuring a 
custom\/shared thread pool to use for the consumer. By default each consumer 
has its own single threaded thread pool." },
+    "scheduler": { "index": 22, "kind": "parameter", "displayName": 
"Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": 
false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": "none", "description": "To 
use a cron scheduler from either camel-spring or camel-quartz component. Use 
value spring or quartz for built in scheduler" },
+    "schedulerProperties": { "index": 23, "kind": "parameter", "displayName": 
"Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "object", "javaType": 
"java.util.Map<java.lang.String, java.lang.Object>", "prefix": "scheduler.", 
"multiValue": true, "deprecated": false, "autowired": false, "secret": false, 
"description": "To configure additional properties when using a custom 
scheduler or any of the Quartz, Spring based scheduler. This i [...]
+    "startScheduler": { "index": 24, "kind": "parameter", "displayName": 
"Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "boolean", "javaType": "boolean", "deprecated": 
false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Whether the scheduler should be auto started." },
+    "timeUnit": { "index": 25, "kind": "parameter", "displayName": "Time 
Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, 
"type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [ 
"NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", 
"DAYS" ], "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and 
delay options." },
+    "useFixedDelay": { "index": 26, "kind": "parameter", "displayName": "Use 
Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in 
JDK for details." }
   }
 }
diff --git a/components/camel-atom/src/main/docs/atom-component.adoc 
b/components/camel-atom/src/main/docs/atom-component.adoc
index c951654dbfcb..72eaba3b6309 100644
--- a/components/camel-atom/src/main/docs/atom-component.adoc
+++ b/components/camel-atom/src/main/docs/atom-component.adoc
@@ -69,6 +69,44 @@ Depending on the `splitEntries` flag Camel will either 
return one
 Camel can set the `Feed` object on the In header (see `feedHeader`
 option to disable this):
 
+== Usage
+
+=== Avoid reading the same entry more than once (idempotent consumer)
+
+Camel supports Idempotent Consumer
+directly within the component, so it will skip already processed entries.
+This feature is enabled by default, but can be disabled by setting the 
`idempotent=false` option.
+
+[source,java]
+----
+from("file://inbox?idempotent=false").to("...");
+----
+
+The default Idempotency strategy uses Atom published and updated timestamps to 
identify already
+read entries, by filtering all entries older that the _last read_ entry.
+
+The idempotency strategy can be changed by setting the `idempotentStrategy` 
option. The components support two
+strategies _out-of-the-box_, but custom strategies can be used, by referencing 
a subclass 
+of `org.apache.camel.component.atom.AtomIdempotentStrategy`, with Apache 
Camel's # notation.
+
+[source,java]
+----
+from("file://inbox?idempotentStrategy=#myIdempotentStrategy").to("...");
+----
+
+==== Repository idempotent strategy
+As an alternative to the default idempotent strategy, a repository based 
strategy can be use:
+
+[source,java]
+----
+from("file://inbox?idempotentStrategy=repository").to("...");
+----
+
+This strategy checks for idempotency by storing the Atom Entry GUID in an 
`IdempotentRepository`. The strategy defaults
+a MemoryIdempotentRepository, but the repository can be changes to any 
subclass of `IdempotentRepository`, using the
+`idempotentRepository` option.
+
+
 == Examples
 
 === Consumer Example
diff --git 
a/components/camel-atom/src/main/java/org/apache/camel/component/atom/AtomComponent.java
 
b/components/camel-atom/src/main/java/org/apache/camel/component/atom/AtomComponent.java
index 603cc48b3977..fb59104df67e 100644
--- 
a/components/camel-atom/src/main/java/org/apache/camel/component/atom/AtomComponent.java
+++ 
b/components/camel-atom/src/main/java/org/apache/camel/component/atom/AtomComponent.java
@@ -22,6 +22,7 @@ import java.util.Map;
 import org.apache.camel.Endpoint;
 import org.apache.camel.component.feed.FeedComponent;
 import org.apache.camel.component.feed.FeedEndpoint;
+import org.apache.camel.spi.IdempotentRepository;
 import org.apache.camel.spi.annotations.Component;
 import org.apache.camel.util.URISupport;
 
@@ -31,12 +32,34 @@ import org.apache.camel.util.URISupport;
 @Component("atom")
 public class AtomComponent extends FeedComponent {
 
+    private static final String KEY_FORMAT_IDEMPOTENT_PARAM = "idempotent";
+    private static final String KEY_FORMAT_STRATEGY_PARAM = 
"idempotentStrategy";
+    private static final String KEY_FORMAT_IDEMPOTENT_REPOSITORY_PARAM = 
"idempotentRepository";
+
     public AtomComponent() {
     }
 
     @Override
     protected FeedEndpoint createEndpoint(String uri, String remaining, 
Map<String, Object> parameters) throws Exception {
-        return new AtomEndpoint(uri, this, null);
+        AtomEndpoint endpoint = new AtomEndpoint(uri, this, null);
+        // Setup idempotency
+        endpoint.setIdempotent(getAndRemoveParameter(parameters, 
KEY_FORMAT_IDEMPOTENT_PARAM, Boolean.class, true));
+        if (endpoint.isIdempotent()) {
+            endpoint.setIdempotentRepository(
+                    resolveAndRemoveReferenceParameter(parameters, 
KEY_FORMAT_IDEMPOTENT_REPOSITORY_PARAM,
+                            IdempotentRepository.class));
+            String idempotentStrategy = getAndRemoveParameter(parameters, 
KEY_FORMAT_STRATEGY_PARAM, String.class);
+            AtomIdempotentStrategy atomIdempotentStrategy
+                    = resolveEnumIdempotentStrategy(idempotentStrategy, 
endpoint.getIdempotentRepository());
+            if (atomIdempotentStrategy != null) {
+                parameters.put(KEY_FORMAT_STRATEGY_PARAM, 
atomIdempotentStrategy);
+            } else if (idempotentStrategy != null) {
+                // its not a standard, but a reference - fallback to 
AtomEndpointConfigurator
+                parameters.put(KEY_FORMAT_STRATEGY_PARAM, idempotentStrategy);
+                
//endpoint.setIdempotentStrategy(resolveAndRemoveReferenceParameter(parameters, 
KEY_FORMAT_STRATEGY_PARAM, AtomIdempotentStrategy.class));
+            }
+        }
+        return endpoint;
     }
 
     @Override
@@ -61,4 +84,24 @@ public class AtomComponent extends FeedComponent {
         atom.setFeedUri(feedUri);
     }
 
+    /**
+     * Resolves the standard supported {@link AtomIdempotentStrategy} by a 
name which can be:
+     * <ul>
+     * <li>default - to use the default date strategy</li>
+     * <li>repository - to use the Guid Repository strategy</li>
+     * </ul>
+     *
+     * @param  name the name
+     * @return      the strategy, or <tt>null</tt> if not a standard name.
+     */
+    private static AtomIdempotentStrategy resolveEnumIdempotentStrategy(
+            String name, IdempotentRepository idempotentRepository) {
+        if ("default".equalsIgnoreCase(name)) {
+            return new ItemUpdatedIdempotentStrategy();
+        } else if ("repository".equalsIgnoreCase(name)) {
+            return new RepositoryGuidIdempotentStrategy(idempotentRepository);
+        } else {
+            return null;
+        }
+    }
 }
diff --git 
a/components/camel-atom/src/main/java/org/apache/camel/component/atom/AtomEndpoint.java
 
b/components/camel-atom/src/main/java/org/apache/camel/component/atom/AtomEndpoint.java
index f54b66c88a30..1806f1549f82 100644
--- 
a/components/camel-atom/src/main/java/org/apache/camel/component/atom/AtomEndpoint.java
+++ 
b/components/camel-atom/src/main/java/org/apache/camel/component/atom/AtomEndpoint.java
@@ -23,7 +23,9 @@ import org.apache.camel.component.feed.FeedComponent;
 import org.apache.camel.component.feed.FeedEndpoint;
 import org.apache.camel.component.feed.FeedPollingConsumer;
 import org.apache.camel.spi.EndpointServiceLocation;
+import org.apache.camel.spi.IdempotentRepository;
 import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
 
 /**
  * Poll Atom RSS feeds.
@@ -32,6 +34,22 @@ import org.apache.camel.spi.UriEndpoint;
              category = { Category.DOCUMENT }, lenientProperties = true, 
headersClass = AtomConstants.class)
 public class AtomEndpoint extends FeedEndpoint implements 
EndpointServiceLocation {
 
+    @UriParam(label = "consumer,filter", defaultValue = "true", description = 
"Option to use the Idempotent "
+                                                                              
+ "Consumer EIP pattern to let Camel skip already processed entries. By default 
it skips Atom entries "
+                                                                              
+ "that is older that the last read entry, using Atom updatedDate and 
publishedDate, but this strategy "
+                                                                              
+ "can be changed with the idempotentStrategy option. Idempotency only works 
when splitEntries = true.")
+    protected boolean idempotent = true;
+    @UriParam(label = "consumer,filter,advanced", defaultValue = "default", 
enums = "default,repository",
+              description = "A pluggable strategy 
org.apache.camel.component.FeedIdempotentStrategy "
+                            + "to use when checking idempotency. Camel 
provides two implementations out of the box: default and repository. The 
updated strategy is used as default if idempotent = true. "
+                            + "The default strategy checks the Atom entrys 
updated or published date is newer than the previously read entry. "
+                            + "You can provide your own implementation of the 
org.apache.camel.component.FeedIdempotentStrategy and refer to it using the # 
notation.")
+    protected AtomIdempotentStrategy idempotentStrategy = new 
ItemUpdatedIdempotentStrategy();
+
+    @UriParam(label = "consumer,filter", description = "A pluggable repository 
org.apache.camel.spi.IdempotentRepository "
+                                                       + "which by default use 
MemoryIdempotentRepository if none is specified and idempotent is true.")
+    protected IdempotentRepository idempotentRepository;
+
     public AtomEndpoint() {
     }
 
@@ -78,4 +96,34 @@ public class AtomEndpoint extends FeedEndpoint implements 
EndpointServiceLocatio
         configureConsumer(answer);
         return answer;
     }
+
+    public boolean isIdempotent() {
+        return idempotent;
+    }
+
+    public FeedEndpoint setIdempotent(Boolean idempotent) {
+        this.idempotent = idempotent;
+        return this;
+    }
+
+    public AtomIdempotentStrategy getIdempotentStrategy() {
+        return idempotentStrategy;
+    }
+
+    public FeedEndpoint setIdempotentStrategy(AtomIdempotentStrategy 
idempotentStrategy) {
+        this.idempotentStrategy = idempotentStrategy;
+        return this;
+    }
+
+    public IdempotentRepository getIdempotentRepository() {
+        return idempotentRepository;
+    }
+
+    /**
+     * A pluggable repository org.apache.camel.spi.IdempotentRepository which 
by default use MemoryIdempotentRepository
+     * if none is specified and idempotent is true.
+     */
+    public void setIdempotentRepository(IdempotentRepository 
idempotentRepository) {
+        this.idempotentRepository = idempotentRepository;
+    }
 }
diff --git 
a/components/camel-atom/src/main/java/org/apache/camel/component/atom/AtomEntryPollingConsumer.java
 
b/components/camel-atom/src/main/java/org/apache/camel/component/atom/AtomEntryPollingConsumer.java
index 311f26b1e007..811503e9a03a 100644
--- 
a/components/camel-atom/src/main/java/org/apache/camel/component/atom/AtomEntryPollingConsumer.java
+++ 
b/components/camel-atom/src/main/java/org/apache/camel/component/atom/AtomEntryPollingConsumer.java
@@ -27,7 +27,7 @@ import 
org.apache.camel.component.feed.FeedEntryPollingConsumer;
 /**
  * Consumer to poll atom feeds and return each entry from the feed step by 
step.
  */
-public class AtomEntryPollingConsumer extends FeedEntryPollingConsumer {
+public class AtomEntryPollingConsumer extends FeedEntryPollingConsumer<Item> {
 
     private RssReader rssReader;
     private List<Item> items;
@@ -36,6 +36,11 @@ public class AtomEntryPollingConsumer extends 
FeedEntryPollingConsumer {
         super(endpoint, processor, throttleEntries);
     }
 
+    @Override
+    public AtomEndpoint getEndpoint() {
+        return (AtomEndpoint) super.getEndpoint();
+    }
+
     @Override
     protected void doStart() throws Exception {
         this.rssReader = new RssReader();
@@ -60,11 +65,20 @@ public class AtomEntryPollingConsumer extends 
FeedEntryPollingConsumer {
 
     private List<Item> readItems() throws IOException {
         if (items == null) {
-            items = AtomUtils.readItems(endpoint.getCamelContext(), 
endpoint.getFeedUri(), rssReader, endpoint.isSortEntries());
+            items = AtomUtils.readItems(getEndpoint().getCamelContext(), 
getEndpoint().getFeedUri(), rssReader,
+                    getEndpoint().isSortEntries());
             list = items;
             entryIndex = list.size() - 1;
         }
         return items;
     }
 
+    @Override
+    protected boolean isValidItem(Item entry) {
+        boolean valid = true;
+        if (getEndpoint().isIdempotent()) {
+            valid = getEndpoint().getIdempotentStrategy().isValidItem(entry);
+        }
+        return valid;
+    }
 }
diff --git 
a/components/camel-atom/src/main/java/org/apache/camel/component/atom/AtomIdempotentStrategy.java
 
b/components/camel-atom/src/main/java/org/apache/camel/component/atom/AtomIdempotentStrategy.java
new file mode 100644
index 000000000000..072f6b9790f2
--- /dev/null
+++ 
b/components/camel-atom/src/main/java/org/apache/camel/component/atom/AtomIdempotentStrategy.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.atom;
+
+import com.apptasticsoftware.rssreader.Item;
+
+/**
+ *
+ */
+public interface AtomIdempotentStrategy {
+
+    boolean isValidItem(Item item);
+}
diff --git 
a/components/camel-atom/src/main/java/org/apache/camel/component/atom/ItemUpdatedIdempotentStrategy.java
 
b/components/camel-atom/src/main/java/org/apache/camel/component/atom/ItemUpdatedIdempotentStrategy.java
new file mode 100644
index 000000000000..06040eb70ad3
--- /dev/null
+++ 
b/components/camel-atom/src/main/java/org/apache/camel/component/atom/ItemUpdatedIdempotentStrategy.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.atom;
+
+import java.text.ParseException;
+import java.util.Date;
+import java.util.Optional;
+
+import com.apptasticsoftware.rssreader.Item;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ */
+public class ItemUpdatedIdempotentStrategy implements AtomIdempotentStrategy {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(ItemUpdatedIdempotentStrategy.class);
+    private Date lastUpdate;
+
+    @Override
+    public boolean isValidItem(Item item) {
+        Date updated = toDate(item.getUpdated());
+        if (updated == null) {
+            // never been updated so get published date
+            updated = toDate(item.getPubDate());
+        }
+        if (updated == null) {
+            LOG.debug("No updated time for entry so assuming its valid: 
entry=[{}]", item);
+            return true;
+        }
+        if (lastUpdate != null) {
+            // we need to skip the latest updated entry
+            if (lastUpdate.after(updated) || lastUpdate.equals(updated)) {
+                LOG.debug("Entry is older than lastupdate=[{}], no valid 
entry=[{}]", lastUpdate, item);
+                return false;
+            }
+        }
+        lastUpdate = updated;
+        return true;
+    }
+
+    private Date toDate(Optional<String> dateString) {
+        try {
+            return AtomConverter.toDate(dateString.orElse(null));
+        } catch (NullPointerException | ParseException e) {
+            LOG.debug("Failed to parse date string: {}", dateString, e);
+            return null;
+        }
+    }
+
+}
diff --git 
a/components/camel-atom/src/main/java/org/apache/camel/component/atom/RepositoryGuidIdempotentStrategy.java
 
b/components/camel-atom/src/main/java/org/apache/camel/component/atom/RepositoryGuidIdempotentStrategy.java
new file mode 100644
index 000000000000..ef917f18f3af
--- /dev/null
+++ 
b/components/camel-atom/src/main/java/org/apache/camel/component/atom/RepositoryGuidIdempotentStrategy.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.atom;
+
+import com.apptasticsoftware.rssreader.Item;
+import org.apache.camel.spi.IdempotentRepository;
+import 
org.apache.camel.support.processor.idempotent.MemoryIdempotentRepository;
+
+/**
+ *
+ */
+public class RepositoryGuidIdempotentStrategy implements 
AtomIdempotentStrategy {
+
+    IdempotentRepository idempotentRepository = null;
+
+    public RepositoryGuidIdempotentStrategy() {
+        this(null);
+    }
+
+    public RepositoryGuidIdempotentStrategy(IdempotentRepository 
idempotentRepository) {
+        this.idempotentRepository = idempotentRepository;
+    }
+
+    @Override
+    public boolean isValidItem(Item entry) {
+        boolean valid = true;
+        if (entry != null && entry.getGuid().isPresent()) {
+            valid = getIdempotentRepository().add(entry.getGuid().get());
+        }
+        return valid;
+    }
+
+    protected IdempotentRepository getIdempotentRepository() {
+        if (this.idempotentRepository == null) {
+            this.idempotentRepository = 
MemoryIdempotentRepository.memoryIdempotentRepository();
+        }
+        return this.idempotentRepository;
+    }
+
+    protected RepositoryGuidIdempotentStrategy 
setIdempotentRepository(IdempotentRepository idempotentRepository) {
+        this.idempotentRepository = idempotentRepository;
+        return this;
+    }
+}
diff --git 
a/components/camel-atom/src/main/java/org/apache/camel/component/feed/FeedEntryPollingConsumer.java
 
b/components/camel-atom/src/main/java/org/apache/camel/component/feed/FeedEntryPollingConsumer.java
index 91ead9052b5b..8fd76743643b 100644
--- 
a/components/camel-atom/src/main/java/org/apache/camel/component/feed/FeedEntryPollingConsumer.java
+++ 
b/components/camel-atom/src/main/java/org/apache/camel/component/feed/FeedEntryPollingConsumer.java
@@ -49,11 +49,13 @@ public abstract class FeedEntryPollingConsumer<E> extends 
FeedPollingConsumer {
             E entry = list.get(entryIndex--);
             polledMessages++;
 
-            Exchange exchange = endpoint.createExchange(feed, entry);
-            getProcessor().process(exchange);
-            if (this.throttleEntries) {
-                // return and wait for the next poll to continue from last 
time (this consumer is stateful)
-                return polledMessages;
+            if (isValidItem(entry)) {
+                Exchange exchange = endpoint.createExchange(feed, entry);
+                getProcessor().process(exchange);
+                if (this.throttleEntries) {
+                    // return and wait for the next poll to continue from last 
time (this consumer is stateful)
+                    return polledMessages;
+                }
             }
         }
 
@@ -64,6 +66,10 @@ public abstract class FeedEntryPollingConsumer<E> extends 
FeedPollingConsumer {
         return polledMessages;
     }
 
+    protected boolean isValidItem(E entry) {
+        return true;
+    }
+
     protected abstract void resetList();
 
     protected abstract void populateList(Object feed) throws Exception;
diff --git a/components/camel-atom/src/test/data/updated-feed.atom 
b/components/camel-atom/src/test/data/updated-feed.atom
new file mode 100644
index 000000000000..c3c6f9963d5c
--- /dev/null
+++ b/components/camel-atom/src/test/data/updated-feed.atom
@@ -0,0 +1,316 @@
+<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet 
href="http://www.blogger.com/styles/atom.css"; type="text/css"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<feed xmlns='http://www.w3.org/2005/Atom' 
xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'>
+  <id>tag:blogger.com,1999:blog-637417304187784899</id>
+  <updated>2007-12-01T12:33:31.529Z</updated>
+  <title type='text'>James Strachan's Blog</title>
+  <link rel='alternate' type='text/html' href='http://macstrac.blogspot.com/'/>
+  <link rel='next' type='application/atom+xml'
+        
href='http://macstrac.blogspot.com/feeds/posts/default?start-index=26&amp;max-results=25'/>
+  <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml'
+        href='http://macstrac.blogspot.com/feeds/posts/default'/>
+  <link rel='self' type='application/atom+xml' 
href='http://macstrac.blogspot.com/feeds/posts/default'/>
+  <author>
+    <name>James Strachan</name>
+  </author>
+  <generator version='7.00' uri='http://www.blogger.com'>Blogger</generator>
+  <openSearch:totalResults>54</openSearch:totalResults>
+  <openSearch:startIndex>1</openSearch:startIndex>
+  <openSearch:itemsPerPage>25</openSearch:itemsPerPage>
+
+  <entry>
+    
<id>tag:blogger.com,1999:blog-637417304187784899.post-597595982330434286</id>
+    <published>2007-11-26T08:46:00.000Z</published>
+    <updated>2025-11-26T08:49:10.354Z</updated>
+    <title type='text'>ActiveMQ webinar archive available</title>
+    <content type='html'>Our &lt;a 
href="http://macstrac.blogspot.com/2007/11/webcast-today-on-apache-activemq.html"&gt;previously
+      announced webinar on ActiveMQ&lt;/a&gt; is now available on &lt;a
+      href="http://open.iona.com/resources/video-archived-webinars/"&gt;IONA's 
webinar and screencast archive&lt;/a&gt;.
+      You can &lt;a href="https://cc.readytalk.com/play?id=go5pfj81"&gt;view 
it here&lt;/a&gt;.
+    </content>
+    <link rel='alternate' type='text/html'
+          
href='http://macstrac.blogspot.com/2007/11/activemq-webinar-archive-available.html'
+          title='ActiveMQ webinar archive available'/>
+    <link rel='replies' type='text/html'
+          
href='http://www.blogger.com/comment.g?blogID=637417304187784899&amp;postID=597595982330434286'
+          title='0 Comments'/>
+    <link rel='replies' type='application/atom+xml'
+          
href='http://macstrac.blogspot.com/feeds/597595982330434286/comments/default' 
title='Post Comments'/>
+    <link rel='self' type='application/atom+xml'
+          
href='http://macstrac.blogspot.com/feeds/posts/default/597595982330434286'/>
+    <link rel='edit' type='application/atom+xml'
+          
href='http://www.blogger.com/feeds/637417304187784899/posts/default/597595982330434286'/>
+    <author>
+      <name>James Strachan</name>
+    </author>
+  </entry>
+  <entry>
+    
<id>tag:blogger.com,1999:blog-637417304187784899.post-6948835939296895803</id>
+    <published>2007-11-14T14:18:00.001Z</published>
+    <updated>2025-11-14T19:43:38.291Z</updated>
+    <title type='text'>More thoughts on RESTful Message Queues</title>
+    <content type='html'>Just a small follow up on my previous &lt;span 
style="font-size:100%;"&gt;&lt;a
+      style="font-weight: normal;" 
href="http://macstrac.blogspot.com/2007/08/pure-restful-api-to-activemq-via.html"&gt;Pure
+      RESTful API to ActiveMQ via AtomPub&lt;/a&gt;&lt;/span&gt;. AtomPub 
rocks and all - I was thinking whats the
+      easiest possible RESTful client to subscribe to a message queue.&lt;br 
/&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;GET
+      
queues/foo.bar?user=myUniqueId&amp;amp;timeout=5000&lt;/blockquote&gt;This 
would activate my subscription to the
+      queue &lt;span style="font-style: italic;"&gt;foo.bar&lt;/span&gt; (or 
help to keep it alive) and return my own
+      list of messages as an Atom feed that I am allowed to view and DELETE 
when I have consumed them.&lt;br /&gt;&lt;br
+      /&gt;This operation is idempotent and would work great with proxies and 
caches (assuming the right HTTP headers /
+      ETags stuff) letting clients to keep GETing as often as they like. 
Though if you don't use the subscription for
+      period of time, your subscription can go stale and timeout; any messages 
in your message collection could be
+      removed.&lt;br /&gt;&lt;br /&gt;The slightly smelly thing here is we 
need to either use cookies (such as for HTTP
+      session handling with servlets) or use a custom session ID header in the 
URL to uniquely differentiate the
+      subscriptions. Anyone got a better idea?&lt;br /&gt;&lt;br /&gt;I guess 
we could demand that clients PUT/POST to
+      get a new Location URL on which to GET their subscriptions; but this 
would require a custom REST client.
+    </content>
+    <link rel='alternate' type='text/html'
+          
href='http://macstrac.blogspot.com/2007/11/more-thoughts-on-restful-message-queues.html'
+          title='More thoughts on RESTful Message Queues'/>
+    <link rel='replies' type='text/html'
+          
href='http://www.blogger.com/comment.g?blogID=637417304187784899&amp;postID=6948835939296895803'
+          title='3 Comments'/>
+    <link rel='replies' type='application/atom+xml'
+          
href='http://macstrac.blogspot.com/feeds/6948835939296895803/comments/default' 
title='Post Comments'/>
+    <link rel='self' type='application/atom+xml'
+          
href='http://macstrac.blogspot.com/feeds/posts/default/6948835939296895803'/>
+    <link rel='edit' type='application/atom+xml'
+          
href='http://www.blogger.com/feeds/637417304187784899/posts/default/6948835939296895803'/>
+    <author>
+      <name>James Strachan</name>
+    </author>
+  </entry>
+  <entry>
+    
<id>tag:blogger.com,1999:blog-637417304187784899.post-8132857663967818867</id>
+    <published>2007-11-13T15:30:00.000Z</published>
+    <updated>2025-11-13T16:40:47.166Z</updated>
+    <category scheme='http://www.blogger.com/atom/ns#' term='camel'/>
+    <title type='text'>Feedback on my Camel talk at the IJTC conference</title>
+    <content type='html'>Thanks to &lt;a 
href="http://capedcrusading.blogspot.com/"&gt;John&lt;/a&gt; for the &lt;a
+      
href="http://capedcrusading.blogspot.com/2007/11/ijtc-conference-spring-grails-camel.html"&gt;great
 feedback on my
+      Camel talk&lt;/a&gt; (and other talks too). I started to write a huge 
reply and figured I'd post it here instead
+      then link to it as its easier to reply to different parts.&lt;br 
/&gt;&lt;blockquote&gt;Camel itself is not an ESB
+      per-se, it is a component of an ESB &lt;/blockquote&gt;Agreed. The idea 
is Camel does the routing and &lt;a
+      
href="http://activemq.apache.org/camel/enterprise-integration-patterns.html"; 
title="Enterprise Integration
+      Patterns"&gt;Enterprise Integration Patterns&lt;/a&gt; - you can then 
use it inside a web service stack like &lt;span
+      class="nobr"&gt;&lt;/span&gt;&lt;a 
href="http://incubator.apache.org/cxf/"; title="Visit page outside Confluence"
+      rel="nofollow"&gt;Apache CXF&lt;/a&gt;, a message broker like &lt;span 
style="text-decoration: underline;"&gt;&lt;/span&gt;&lt;span
+      class="nobr"&gt;&lt;a href="http://activemq.apache.org/"; title="Visit 
page outside Confluence" rel="nofollow"&gt;Apache
+      ActiveMQ&lt;/a&gt;&lt;/span&gt; or an ESB like&lt;span 
class="nobr"&gt;&lt;a
+      href="http://incubator.apache.org/servicemix/"; title="Visit page outside 
Confluence" rel="nofollow"&gt; Apache
+      ServiceMix&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;1. One of 
the key messages that came out of the
+      session was how Java-centric the Camel solution is - Strachan went so 
far as to articulate the view that coding in
+      XML was a fundamentally bad idea.&lt;br /&gt;&lt;/blockquote&gt;Maybe 
being the author of &lt;a
+      href="http://commons.apache.org/jelly/"&gt;Jelly&lt;/a&gt; and hating 
writing XSLT has made me a bit too sensitive
+      to the idea of programming by XML. Quite a few customers I talk with 
report frustration of too much XML hacking
+      with Spring (which is being addressed in Guice and Spring 2.5). But heck 
if you like programming in XML be my
+      guest :)&lt;br /&gt;&lt;blockquote&gt;He went on to cast aspersions on 
graphical tools also. His clear preference
+      was that integration logic should be written in Java. Given that I have 
worked with highly skilled Java developers
+      for many years now I was not too surprised to hear this - many good 
developers shy away from tooling, seeing it as
+      compromising their style or the power of the underlying framework - 
hence the longevity of vi and emacs I suppose.&lt;br
+      /&gt;&lt;/blockquote&gt;I didn't mean to cast aspersions on graphical 
tools; more that pretty much all developers
+      understand Java these days, its pretty universal - whereas most complex 
graphical tools require a fair amount of
+      learning to get used to them.&lt;br /&gt;&lt;br /&gt;Personally I 
totally prefer writing in Java rather than XML
+      or using visual tooling but one of the main requirements of Camel is 
that you can configure and specify routes in
+      any way you like - via a graphical IDE (e.g. Cimero) or via XML or Java 
or Groovy or Ruby or one day hopefully a
+      real DSL. Using XML is quite useful as you can just drop your routing 
rules inside a spring XML file such as
+      inside the &lt;span style="text-decoration: 
underline;"&gt;&lt;/span&gt;&lt;span class="nobr"&gt;&lt;a
+      href="http://activemq.apache.org/"; title="Visit page outside Confluence" 
rel="nofollow"&gt;Apache ActiveMQ&lt;/a&gt;&lt;/span&gt;.&lt;br
+      /&gt;&lt;br /&gt;So we're working hard to allow folks to specify routing 
rules however they like - despite what I
+      prefer :). Irrespective of how you write your routing rules, we can &lt;a
+      href="http://activemq.apache.org/camel/visualisation.html"&gt;visualise 
them&lt;/a&gt; so anyone can easily
+      understand them.&lt;br /&gt;&lt;blockquote&gt;However it is important to 
note that all developers are not
+      middleware experts and have no wish to be. Indeed the enterprises they 
work for want their developers to spend as
+      little time and effort as possible on middleware plumbing. They need and 
demand tools which will enable them to
+      get at least 80% of patterns done without having to understand the 
middleware architecture, it's threading model,&lt;br
+      /&gt;&lt;/blockquote&gt;Thats one of the main things we're trying to 
attempt with Camel - letting folks who are
+      not middleware experts easily use the &lt;a
+      
href="http://activemq.apache.org/camel/enterprise-integration-patterns.html"; 
title="Enterprise Integration
+      Patterns"&gt;Enterprise Integration Patterns&lt;/a&gt; using a single 
line of Java code - using &lt;a
+      href="http://activemq.apache.org/camel/components.html"&gt;any transport 
or component &lt;/a&gt;with minimal
+      configuration required.&lt;br /&gt;&lt;blockquote&gt;it's support for 
configurable expression languages etc.&lt;br
+      /&gt;&lt;/blockquote&gt;I find it hard to understand how any tool can be 
usable by folks without some kind of
+      expression language that they understand - whether its Java or SQL or 
XPath/XQuery or whatnot. Even a visual query
+      definer is a language that users need to know.&lt;br 
/&gt;&lt;blockquote&gt;Most people express their requirements
+      in a declarative way- I have data at A that needs to get to B, on it's 
way I need to perform transformation,
+      validation, logging etc. (indeed the EIP book itself does this) . 
However Camel has taken a very Java centric
+      approach and I think this increases it's complexity unnecessarily.&lt;br 
/&gt;&lt;/blockquote&gt;We are actually
+      trying to be as declarative as possible - don't let the fact that you 
can use Java as the DSL confuse you. e.g.
+      here's what you just described in Camel using a single line of Java 
code...&lt;br /&gt;&lt;blockquote&gt;from(a).&lt;br
+      /&gt;to("xsd:org/cheese/something.xsd").&lt;br 
/&gt;to("xslt:com/acme/mytransform.xsl").&lt;br 
/&gt;to("log:com.acme.MyLogger").&lt;br
+      /&gt;to(b);&lt;br /&gt;&lt;/blockquote&gt;Its hard to be more concise 
than that in Java code. But sure - you could
+      use some other language or XML or UI tool etc&lt;br 
/&gt;&lt;blockquote&gt;2. Camel presents transports as
+      nice-simple looking endpoint URIs in Java. However configuration of 
these transports may not be as simple as it
+      seems. There appears to me to be a potential disconnection between the 
Camel processors and the Camel Components
+      in terms of configuration.&lt;br /&gt;&lt;/blockquote&gt;You can always 
configure anything in Camel via Java or
+      Spring; a component, endpoint, processor etc. The URI is just a 
shorthand notation for configurating things; which
+      tends to work well with endpoints as usually all the smart configuration 
is in the component.&lt;br /&gt;&lt;blockquote&gt;In
+      the presentation processors use endpoints which can be configured using 
Spring within Camel. However it would
+      appear that many of the component implementations are inherited from 
ServiceMix and these properties will need to
+      be set presumably within the ServiceMix container configuration? 
&lt;/blockquote&gt;Not so - all the components
+      are configured in Spring via Camel. If you want to talk to ServiceMix 
components and endpoints you can use the NMR
+      and the &lt;a href="http://activemq.apache.org/camel/jbi.html"&gt;JBI 
endpoint&lt;/a&gt;.&lt;br /&gt;&lt;blockquote&gt;When
+      you have multiple XML configurations to use a transport then the pretty 
looking URI is hiding a lot of complexity
+      under the hood.&lt;br /&gt;&lt;/blockquote&gt;I hear you. We've tried 
very hard to make things as easy as is
+      possible with minimal configuration; for example most configuration 
tends to be on the Component rather than the
+      Endpoint. But you can configure things however you like in Java code or 
Guice or Spring.&lt;br /&gt;&lt;blockquote&gt;3.
+      Some of the pattern implementations look a little short on credibility - 
take the aggregator pattern for example
+      the "aggregator" pattern does not seem to have the concept of a store - 
so in essence one must have access to all
+      of the messages which require aggregation or must hold aggregations in 
memory for the configurable timeout period.
+      This will clearly not work in a scalable way. Likewise as regards 
clustering - if you are looking to aggregate 2
+      messages and they turn up on different servers you gotta 
problem.&lt;/blockquote&gt;You're right I purposely
+      missed out some of the detail on a few slides (such as specifying some 
kind of persistence store or strategy for
+      aggregator or for idempotent consumer) but that is easily done via a 
pluggable strategies Spring beans. However
+      just because I missed out some detail on some slides (its kinda hard in 
an hour to present all the detail in all
+      the patterns as well as the rest of Camel) please don't think that 
somehow Camel isn't short on capabilities.&lt;br
+      /&gt;&lt;blockquote&gt;To summarise Camel is clearly a worthy set of 
widgets and they will work for very simple
+      applications without Enterprise requirements.&lt;br 
/&gt;&lt;/blockquote&gt;Ouch :). We've actually lots of
+      customers using Camel today in production with very Enterprise 
requirements. &lt;span class="nobr"&gt;&lt;/span&gt;&lt;a
+      href="http://activemq.apache.org/"; title="Visit page outside Confluence" 
rel="nofollow"&gt;Apache ActiveMQ&lt;/a&gt;
+      5.0 actually ships &lt;a 
href="http://activemq.apache.org/enterprise-integration-patterns.html"&gt;fully
+      integrated with Camel&lt;/a&gt; so we've tons of users in production 
using Camel today.&lt;br /&gt;&lt;br /&gt;I
+      hope I've managed to straighten out some misunderstandings on Camel; its 
definitely a great fit for enterprise
+      requirements. Thanks for your great feedback - I'll definitely take it 
on board on future presentations and try
+      and avoid confusing other folks :).
+    </content>
+    <link rel='alternate' type='text/html'
+          
href='http://macstrac.blogspot.com/2007/11/feedback-on-my-camel-talk-at-ijtc.html'
+          title='Feedback on my Camel talk at the IJTC conference'/>
+    <link rel='replies' type='text/html'
+          
href='http://www.blogger.com/comment.g?blogID=637417304187784899&amp;postID=8132857663967818867'
+          title='2 Comments'/>
+    <link rel='replies' type='application/atom+xml'
+          
href='http://macstrac.blogspot.com/feeds/8132857663967818867/comments/default' 
title='Post Comments'/>
+    <link rel='self' type='application/atom+xml'
+          
href='http://macstrac.blogspot.com/feeds/posts/default/8132857663967818867'/>
+    <link rel='edit' type='application/atom+xml'
+          
href='http://www.blogger.com/feeds/637417304187784899/posts/default/8132857663967818867'/>
+    <author>
+      <name>James Strachan</name>
+    </author>
+  </entry>
+  <entry>
+    
<id>tag:blogger.com,1999:blog-637417304187784899.post-2980017428692756666</id>
+    <published>2007-11-13T13:33:00.000Z</published>
+    <updated>2007-11-13T13:35:25.014Z</updated>
+    <title type='text'>webcast today on Apache ActiveMQ</title>
+    <content type='html'>Sorry for the really late notice - bad James! - but 
I&lt;a
+      href="http://open.iona.com/resources/news/#webinar"&gt;'m doing a 
webinar today&lt;/a&gt; on &lt;a
+      href="http://activemq.apache.org/"&gt;Apache ActiveMQ&lt;/a&gt; with my 
fellow committer &lt;a
+      href="http://hiramchirino.com/index.html"&gt;Hiram Chirino&lt;/a&gt;. 
Feel free to pop by and join us - or if
+      you're snowed you can catch the recording later on.
+    </content>
+    <link rel='alternate' type='text/html'
+          
href='http://macstrac.blogspot.com/2007/11/webcast-today-on-apache-activemq.html'
+          title='webcast today on Apache ActiveMQ'/>
+    <link rel='replies' type='text/html'
+          
href='http://www.blogger.com/comment.g?blogID=637417304187784899&amp;postID=2980017428692756666'
+          title='0 Comments'/>
+    <link rel='replies' type='application/atom+xml'
+          
href='http://macstrac.blogspot.com/feeds/2980017428692756666/comments/default' 
title='Post Comments'/>
+    <link rel='self' type='application/atom+xml'
+          
href='http://macstrac.blogspot.com/feeds/posts/default/2980017428692756666'/>
+    <link rel='edit' type='application/atom+xml'
+          
href='http://www.blogger.com/feeds/637417304187784899/posts/default/2980017428692756666'/>
+    <author>
+      <name>James Strachan</name>
+    </author>
+  </entry>
+  <entry>
+    
<id>tag:blogger.com,1999:blog-637417304187784899.post-8437027470203977326</id>
+    <published>2007-11-13T13:10:00.000Z</published>
+    <updated>2007-11-13T13:32:23.119Z</updated>
+    <title type='text'>my slides on ActiveMQ and Camel from last weeks Dublin 
Conference</title>
+    <content type='html'>They are not that useful if you missed me talk, as 
they are low on bullet points and high on
+      pictures :) But if you were there, here are the slides in PDF 
format...&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;pre&gt;&lt;a
+      
href="http://people.apache.org/%7Ejstrachan/talks/ActiveMQ-Dublin07.pdf"&gt;ActiveMQ-Dublin07.pdf&lt;/a&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;pre&gt;&lt;a
+      
href="http://people.apache.org/%7Ejstrachan/talks/Camel-Dublin07.pdf"&gt;Camel-Dublin07.pdf&lt;/a&gt;
 &lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;</content>
+    <link rel='alternate' type='text/html'
+          
href='http://macstrac.blogspot.com/2007/11/my-slides-on-activemq-and-camel-from.html'
+          title='my slides on ActiveMQ and Camel from last weeks Dublin 
Conference'/>
+    <link rel='replies' type='text/html'
+          
href='http://www.blogger.com/comment.g?blogID=637417304187784899&amp;postID=8437027470203977326'
+          title='0 Comments'/>
+    <link rel='replies' type='application/atom+xml'
+          
href='http://macstrac.blogspot.com/feeds/8437027470203977326/comments/default' 
title='Post Comments'/>
+    <link rel='self' type='application/atom+xml'
+          
href='http://macstrac.blogspot.com/feeds/posts/default/8437027470203977326'/>
+    <link rel='edit' type='application/atom+xml'
+          
href='http://www.blogger.com/feeds/637417304187784899/posts/default/8437027470203977326'/>
+    <author>
+      <name>James Strachan</name>
+    </author>
+  </entry>
+  <entry>
+    
<id>tag:blogger.com,1999:blog-637417304187784899.post-4574479486073739581</id>
+    <published>2007-11-13T13:09:00.000Z</published>
+    <updated>2007-11-13T13:10:23.292Z</updated>
+    <title type='text'>a great presentation on REST, JAX-WS and JSR 311</title>
+    <content type='html'>A great &lt;a
+      
href="http://www.innoq.com/blog/st/presentations/2007/2007-11-06-JSR-311-W-JAX.pdf";
 class="jive-link-external"&gt;presentation&lt;/a&gt;
+      from &lt;a href="http://www.innoq.com/blog/st/"; 
class="jive-link-external"&gt;Stefan Tilkov&lt;/a&gt; on REST,
+      JAX-WS and JSR 311; highly recommended.
+    </content>
+    <link rel='alternate' type='text/html'
+          
href='http://macstrac.blogspot.com/2007/11/great-presentation-on-rest-jax-ws-and.html'
+          title='a great presentation on REST, JAX-WS and JSR 311'/>
+    <link rel='replies' type='text/html'
+          
href='http://www.blogger.com/comment.g?blogID=637417304187784899&amp;postID=4574479486073739581'
+          title='0 Comments'/>
+    <link rel='replies' type='application/atom+xml'
+          
href='http://macstrac.blogspot.com/feeds/4574479486073739581/comments/default' 
title='Post Comments'/>
+    <link rel='self' type='application/atom+xml'
+          
href='http://macstrac.blogspot.com/feeds/posts/default/4574479486073739581'/>
+    <link rel='edit' type='application/atom+xml'
+          
href='http://www.blogger.com/feeds/637417304187784899/posts/default/4574479486073739581'/>
+    <author>
+      <name>James Strachan</name>
+    </author>
+  </entry>
+  <entry>
+    
<id>tag:blogger.com,1999:blog-637417304187784899.post-459928383168678386</id>
+    <published>2007-11-05T10:34:00.000Z</published>
+    <updated>2007-11-05T10:46:07.867Z</updated>
+    <title type='text'>Speaking at the Irish Java Technology Conference on 
Thursday and Friday</title>
+    <content type='html'>I'll be &lt;a 
href="http://ijtc.firstport.ie/bio.aspx?sid=33"&gt;speaking&lt;/a&gt; this week
+      at the &lt;a href="http://ijtc.firstport.ie/"&gt;&lt;span 
id="cmsContent"&gt;&lt;/span&gt;Irish Java Technology
+      Conference&lt;/a&gt; this week on Thursday and Friday. My talks 
are&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a
+      href="http://ijtc.firstport.ie/lecture.aspx?lid=34"&gt;Enterprise 
Messaging With Apache ActiveMQ&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a
+      href="http://ijtc.firstport.ie/lecture.aspx?lid=14"&gt;Easy Enterprise 
Integration Patterns with Apache Camel,
+      ActiveMQ and ServiceMix&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;Do pop along and 
say hi if you're gonna be in the Dublin
+      area this week.
+    </content>
+    <link rel='alternate' type='text/html'
+          
href='http://macstrac.blogspot.com/2007/11/speaking-at-irish-java-technology.html'
+          title='Speaking at the Irish Java Technology Conference on Thursday 
and Friday'/>
+    <link rel='replies' type='text/html'
+          
href='http://www.blogger.com/comment.g?blogID=637417304187784899&amp;postID=459928383168678386'
+          title='3 Comments'/>
+    <link rel='replies' type='application/atom+xml'
+          
href='http://macstrac.blogspot.com/feeds/459928383168678386/comments/default' 
title='Post Comments'/>
+    <link rel='self' type='application/atom+xml'
+          
href='http://macstrac.blogspot.com/feeds/posts/default/459928383168678386'/>
+    <link rel='edit' type='application/atom+xml'
+          
href='http://www.blogger.com/feeds/637417304187784899/posts/default/459928383168678386'/>
+    <author>
+      <name>James Strachan</name>
+    </author>
+  </entry>
+</feed>
\ No newline at end of file
diff --git 
a/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogDefaultIdempotencyTest.java
 
b/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogDefaultIdempotencyTest.java
new file mode 100644
index 000000000000..e1bcb7e34cd2
--- /dev/null
+++ 
b/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogDefaultIdempotencyTest.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.atom;
+
+import org.apache.camel.*;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Atom Good Blog default idempotency test
+ */
+@DisabledOnOs(OS.AIX)
+public class AtomGoodBlogDefaultIdempotencyTest {
+
+    // START SNIPPET: e1
+
+    // This is the CamelContext that is the heart of Camel
+    private CamelContext context;
+    private static final String ROUTE_ID = "1234";
+
+    protected CamelContext createCamelContext() throws Exception {
+        // Create CamelContext and register test routes using the route 
builder DSL syntax
+        context = new DefaultCamelContext();
+        context.addRoutes(createMyRoutes());
+        return context;
+    }
+
+    /**
+     * This is the route builder where we create our routes using the Camel DSL
+     */
+    protected RouteBuilder createMyRoutes() {
+        return new RouteBuilder() {
+            public void configure() {
+                // Idempotent using default strategy in combination of small 
delay and throttleEntries=false, ensures that we
+                // only process each entry once, even though the full blog is 
read multiple times
+                
from("atom:file:src/test/data/feed.atom?splitEntries=true&throttleEntries=false&delay=1000").routeId(ROUTE_ID)
+                        .to("mock:result");
+            }
+        };
+    }
+
+    /**
+     * This test verifies that the correct idempotent strategy is used
+     */
+    @Test
+    void testDefaultIdempotentStrategy() throws Exception {
+        // create and start Camel
+        context = createCamelContext();
+
+        AtomEndpoint endpoint = context.getEndpoint("atom:*", 
AtomEndpoint.class);
+        assertTrue(endpoint.isIdempotent());
+        assertInstanceOf(ItemUpdatedIdempotentStrategy.class, 
endpoint.getIdempotentStrategy());
+
+        // stop Camel after use
+        context.stop();
+    }
+
+    @Test
+    void testIdempotentFilterFullRead() throws Exception {
+        // create and start Camel
+        context = createCamelContext();
+        context.start();
+
+        // Get the mock endpoint
+        MockEndpoint mock = context.getEndpoint("mock:result", 
MockEndpoint.class);
+        Thread.sleep(5000);
+
+        // There should be at least two good blog entries from the feed
+        mock.expectedMessageCount(7);
+
+        // Assert
+        mock.assertIsSatisfied();
+
+        // stop Camel after use
+        context.stop();
+    }
+
+    @Test
+    void testIdempotentFilterSimulateFeedUpdate() throws Exception {
+        // create and start Camel
+        context = createCamelContext();
+        context.start();
+
+        // Get the mock endpoint
+        MockEndpoint mock = context.getEndpoint("mock:result", 
MockEndpoint.class);
+
+        // Read all 7 items from the feed...
+        mock.expectedMessageCount(7);
+        mock.assertIsSatisfied();
+
+        // Simulate feed update by resetting the file...
+        AtomEntryPollingConsumer atomConsumer = (AtomEntryPollingConsumer) 
context.getRoute(ROUTE_ID).getConsumer();
+        
atomConsumer.getEndpoint().setFeedUri("file:src/test/data/updated-feed.atom");
+
+        // Read the three updated entries
+        mock.expectedMessageCount(10);
+        mock.assertIsSatisfied();
+
+        // stop Camel after use
+        context.stop();
+    }
+    // END SNIPPET: e1
+
+}
diff --git 
a/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogNotIdempotentTest.java
 
b/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogNotIdempotentTest.java
new file mode 100644
index 000000000000..891fd52d090b
--- /dev/null
+++ 
b/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogNotIdempotentTest.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.atom;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+
+/**
+ * Atom Good Blog non-idempotent test
+ */
+@DisabledOnOs(OS.AIX)
+public class AtomGoodBlogNotIdempotentTest {
+
+    // This is the CamelContext that is the heart of Camel
+    private CamelContext context;
+    private static final String ROUTE_ID = "1234";
+
+    protected CamelContext createCamelContext() throws Exception {
+        // Create CamelContext and register test routes using the route 
builder DSL syntax
+        context = new DefaultCamelContext();
+        context.addRoutes(createMyRoutes());
+        return context;
+    }
+
+    /**
+     * This is the route builder where we create our routes using the Camel DSL
+     */
+    protected RouteBuilder createMyRoutes() {
+        return new RouteBuilder() {
+            public void configure() {
+                // Atom read setup as not idempotent
+                
from("atom:file:src/test/data/feed.atom?splitEntries=true&throttleEntries=false&delay=1000&idempotent=false")
+                        .routeId(ROUTE_ID)
+                        .to("mock:result");
+            }
+        };
+    }
+
+    @Test
+    void testIdempotentFilterFullRead() throws Exception {
+        // create and start Camel
+        context = createCamelContext();
+        context.start();
+
+        // Get the mock endpoint
+        MockEndpoint mock = context.getEndpoint("mock:result", 
MockEndpoint.class);
+
+        // The blot should be polled least two times
+        mock.expectedMinimumMessageCount(14);
+
+        // Assert
+        mock.assertIsSatisfied();
+
+        // stop Camel after use
+        context.stop();
+    }
+}
diff --git 
a/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogsTest.java
 
b/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogsCustomItempotencyTest.java
similarity index 57%
copy from 
components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogsTest.java
copy to 
components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogsCustomItempotencyTest.java
index a8267cc77f5d..d79874e48d67 100644
--- 
a/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogsTest.java
+++ 
b/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogsCustomItempotencyTest.java
@@ -18,7 +18,6 @@ package org.apache.camel.component.atom;
 
 import com.apptasticsoftware.rssreader.Item;
 import org.apache.camel.CamelContext;
-import org.apache.camel.Exchange;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.impl.DefaultCamelContext;
@@ -27,13 +26,13 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.DisabledOnOs;
 import org.junit.jupiter.api.condition.OS;
 
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+
 /**
- * Example for wiki documentation
+ * Atom Good Blog custom idempotency test
  */
 @DisabledOnOs(OS.AIX)
-public class AtomGoodBlogsTest {
-
-    // START SNIPPET: e1
+public class AtomGoodBlogsCustomItempotencyTest {
 
     // This is the CamelContext that is the heart of Camel
     private CamelContext context;
@@ -42,7 +41,7 @@ public class AtomGoodBlogsTest {
 
         // First we register a blog service in our bean registry
         SimpleRegistry registry = new SimpleRegistry();
-        registry.bind("blogService", new BlogService());
+        registry.bind("myIdempotentStrategy", new CustomIdempotentStrategy());
 
         // Then we create the camel context with our bean registry
         context = new DefaultCamelContext(registry);
@@ -59,28 +58,25 @@ public class AtomGoodBlogsTest {
     protected RouteBuilder createMyRoutes() {
         return new RouteBuilder() {
             public void configure() {
-                // 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&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");
+                // Combination of large delay and throttleEntries=false 
ensures that we only process the full feed once
+                
from("atom:file:src/test/data/feed.atom?delay=10000&splitEntries=true&throttleEntries=false&idempotentStrategy=#myIdempotentStrategy")
+                        .to("mock:result");
             }
         };
     }
 
+    /**
+     * This test verifies that the correct idempotent strategy is used
+     */
+    @Test
+    void testCustomIdempotentStrategy() throws Exception {
+        // create and start Camel
+        context = createCamelContext();
+        AtomEndpoint endpoint
+                = 
context.getEndpoint("atom:feed.atom?idempotentStrategy=#myIdempotentStrategy", 
AtomEndpoint.class);
+        assertInstanceOf(CustomIdempotentStrategy.class, 
endpoint.getIdempotentStrategy());
+    }
+
     /**
      * This is the actual junit test method that does the assertion that our 
routes is working as expected
      */
@@ -94,7 +90,7 @@ public class AtomGoodBlogsTest {
         MockEndpoint mock = context.getEndpoint("mock:result", 
MockEndpoint.class);
 
         // There should be at least two good blog entries from the feed
-        mock.expectedMinimumMessageCount(2);
+        mock.expectedMessageCount(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
@@ -104,25 +100,13 @@ public class AtomGoodBlogsTest {
         // stop Camel after use
         context.stop();
     }
+}
 
-    /**
-     * Services for blogs
-     */
-    public static class BlogService {
-
-        /**
-         * Tests the blogs if its a good blog entry or not
-         */
-        public boolean isGoodBlog(Exchange exchange) {
-            Item entry = exchange.getIn().getBody(Item.class);
-            String title = entry.getTitle().get();
-
-            // We like blogs about Camel
-            return title.toLowerCase().contains("camel");
-        }
+class CustomIdempotentStrategy implements AtomIdempotentStrategy {
 
+    @Override
+    public boolean isValidItem(Item entry) {
+        String ONLY_INTERESTING_TOPIC = "ActiveMQ";
+        return entry.getTitle().orElse("").contains(ONLY_INTERESTING_TOPIC);
     }
-
-    // END SNIPPET: e1
-
 }
diff --git 
a/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogsRepositoryItempotencyCustomRepositoryTest.java
 
b/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogsRepositoryItempotencyCustomRepositoryTest.java
new file mode 100644
index 000000000000..af34c9b695f7
--- /dev/null
+++ 
b/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogsRepositoryItempotencyCustomRepositoryTest.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.atom;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.spi.IdempotentRepository;
+import org.apache.camel.support.SimpleRegistry;
+import 
org.apache.camel.support.processor.idempotent.MemoryIdempotentRepository;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+
+/**
+ * Atom Good Blog repository idempotency test
+ */
+@DisabledOnOs(OS.AIX)
+public class AtomGoodBlogsRepositoryItempotencyCustomRepositoryTest {
+
+    // This is the CamelContext that is the heart of Camel
+    private CamelContext context;
+
+    protected CamelContext createCamelContext() throws Exception {
+        // First we register a IdempotentRepository simulating several reads 
from the same blog
+        SimpleRegistry registry = new SimpleRegistry();
+        IdempotentRepository anyCustomrepository = 
MemoryIdempotentRepository.memoryIdempotentRepository(100);
+        
anyCustomrepository.add("tag:blogger.com,1999:blog-637417304187784899.post-459928383168678386");
+        
anyCustomrepository.add("tag:blogger.com,1999:blog-637417304187784899.post-4574479486073739581");
+        
anyCustomrepository.add("tag:blogger.com,1999:blog-637417304187784899.post-8437027470203977326");
+        
anyCustomrepository.add("tag:blogger.com,1999:blog-637417304187784899.post-2980017428692756666");
+        registry.bind("myIdempotentRepository", anyCustomrepository);
+
+        // 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(createMyRoutes());
+
+        return context;
+    }
+
+    /**
+     * This is the route builder where we create our routes using the Camel DSL
+     */
+    protected RouteBuilder createMyRoutes() {
+        return new RouteBuilder() {
+            public void configure() {
+                // Idempotent using repository strategy in combination of 
small delay and throttleEntries=false, ensures that we
+                // only process each entry once, even though the full blog is 
read multiple times
+                
from("atom:file:src/test/data/feed.atom?splitEntries=true&throttleEntries=false&delay=1000&idempotentStrategy=repository&idempotentRepository=#myIdempotentRepository")
+                        .to("mock:result");
+            }
+        };
+    }
+
+    /**
+     * This test verifies that the correct idempotent strategy is used
+     */
+    @Test
+    void testDefaultIdempotentStrategy() throws Exception {
+        // create and start Camel
+        context = createCamelContext();
+
+        AtomEndpoint endpoint = 
context.getEndpoint("atom:feed.atom?idempotentStrategy=repository", 
AtomEndpoint.class);
+        assertInstanceOf(RepositoryGuidIdempotentStrategy.class, 
endpoint.getIdempotentStrategy());
+
+        // stop Camel after use
+        context.stop();
+    }
+
+    /**
+     * This is the actual junit test method that does the assertion that our 
routes is working as expected
+     */
+    @Test
+    void testFiltering() throws Exception {
+        // create and start Camel
+        context = createCamelContext();
+        context.start();
+
+        // Get the mock endpoint
+        MockEndpoint mock = context.getEndpoint("mock:result", 
MockEndpoint.class);
+
+        // There should be at only three good blog entries, not already in 
customRepository
+        mock.expectedMessageCount(3);
+
+        // Make sure that the component has time for several reads
+        Thread.sleep(3000);
+
+        // Assert
+        mock.assertIsSatisfied(3000);
+
+        // stop Camel after use
+        context.stop();
+    }
+}
diff --git 
a/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogsTest.java
 
b/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogsRepositoryItempotencyTest.java
similarity index 52%
copy from 
components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogsTest.java
copy to 
components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogsRepositoryItempotencyTest.java
index a8267cc77f5d..78b66e44fe25 100644
--- 
a/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogsTest.java
+++ 
b/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogsRepositoryItempotencyTest.java
@@ -16,9 +16,7 @@
  */
 package org.apache.camel.component.atom;
 
-import com.apptasticsoftware.rssreader.Item;
 import org.apache.camel.CamelContext;
-import org.apache.camel.Exchange;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.impl.DefaultCamelContext;
@@ -27,13 +25,13 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.DisabledOnOs;
 import org.junit.jupiter.api.condition.OS;
 
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+
 /**
- * Example for wiki documentation
+ * Atom Good Blog repository idempotency test
  */
 @DisabledOnOs(OS.AIX)
-public class AtomGoodBlogsTest {
-
-    // START SNIPPET: e1
+public class AtomGoodBlogsRepositoryItempotencyTest {
 
     // This is the CamelContext that is the heart of Camel
     private CamelContext context;
@@ -42,7 +40,6 @@ public class AtomGoodBlogsTest {
 
         // First we register a blog service in our bean registry
         SimpleRegistry registry = new SimpleRegistry();
-        registry.bind("blogService", new BlogService());
 
         // Then we create the camel context with our bean registry
         context = new DefaultCamelContext(registry);
@@ -59,70 +56,51 @@ public class AtomGoodBlogsTest {
     protected RouteBuilder createMyRoutes() {
         return new RouteBuilder() {
             public void configure() {
-                // 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&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");
+                // Idempotent using repository strategy in combination of 
small delay and throttleEntries=false, ensures that we
+                // only process each entry once, even though the full blog is 
read multiple times
+                
from("atom:file:src/test/data/feed.atom?splitEntries=true&throttleEntries=false&delay=1000&idempotentStrategy=repository")
+                        .to("mock:result");
             }
         };
     }
 
     /**
-     * This is the actual junit test method that does the assertion that our 
routes is working as expected
+     * This test verifies that the correct idempotent strategy is used
      */
     @Test
-    void testFiltering() throws Exception {
+    void testDefaultIdempotentStrategy() throws Exception {
         // create and start Camel
         context = createCamelContext();
-        context.start();
-
-        // Get the mock endpoint
-        MockEndpoint mock = context.getEndpoint("mock:result", 
MockEndpoint.class);
-
-        // There should be at least 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();
+        AtomEndpoint endpoint = 
context.getEndpoint("atom:feed.atom?idempotentStrategy=repository", 
AtomEndpoint.class);
+        assertInstanceOf(RepositoryGuidIdempotentStrategy.class, 
endpoint.getIdempotentStrategy());
 
         // stop Camel after use
         context.stop();
     }
 
     /**
-     * Services for blogs
+     * This is the actual junit test method that does the assertion that our 
routes is working as expected
      */
-    public static class BlogService {
+    @Test
+    void testFiltering() throws Exception {
+        // create and start Camel
+        context = createCamelContext();
+        context.start();
 
-        /**
-         * Tests the blogs if its a good blog entry or not
-         */
-        public boolean isGoodBlog(Exchange exchange) {
-            Item entry = exchange.getIn().getBody(Item.class);
-            String title = entry.getTitle().get();
+        // Get the mock endpoint
+        MockEndpoint mock = context.getEndpoint("mock:result", 
MockEndpoint.class);
 
-            // We like blogs about Camel
-            return title.toLowerCase().contains("camel");
-        }
+        // There should be at least two good blog entries from the feed
+        mock.expectedMessageCount(7);
 
-    }
+        // Make sure that the component has time for several reads
+        Thread.sleep(3000);
 
-    // END SNIPPET: e1
+        // Assert
+        mock.assertIsSatisfied(3000);
 
+        // stop Camel after use
+        context.stop();
+    }
 }
diff --git 
a/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogsTest.java
 
b/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogsTest.java
index a8267cc77f5d..f90782461d50 100644
--- 
a/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogsTest.java
+++ 
b/components/camel-atom/src/test/java/org/apache/camel/component/atom/AtomGoodBlogsTest.java
@@ -65,7 +65,7 @@ public class AtomGoodBlogsTest {
                 // 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
+                // and restart - but as the Camel Atom component is idempotent 
by default, 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&delay=1000").to("seda:feeds");
diff --git 
a/components/camel-atom/src/test/java/org/apache/camel/component/atom/ItemUpdatedIdempotentStrategyTest.java
 
b/components/camel-atom/src/test/java/org/apache/camel/component/atom/ItemUpdatedIdempotentStrategyTest.java
new file mode 100644
index 000000000000..0f480040005f
--- /dev/null
+++ 
b/components/camel-atom/src/test/java/org/apache/camel/component/atom/ItemUpdatedIdempotentStrategyTest.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.atom;
+
+import java.text.ParseException;
+import java.util.Date;
+import java.util.Optional;
+
+import com.apptasticsoftware.rssreader.Item;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.when;
+
+public class ItemUpdatedIdempotentStrategyTest {
+
+    /**
+     * This class tests the isValidItem method in the 
ItemUpdatedIdempotentStrategy class. The method determines whether
+     * an RSS item is valid based on its updated or published date in relation 
to the previously processed item.
+     */
+
+    @Test
+    void testValidEntryWithNewerUpdatedDate() throws ParseException {
+        // Arrange
+        ItemUpdatedIdempotentStrategy strategy = new 
ItemUpdatedIdempotentStrategy();
+        Item item = Mockito.mock(Item.class);
+
+        Date olderUpdate = AtomConverter.toDate("2023-01-01T00:00:00Z");
+        Date newerUpdate = AtomConverter.toDate("2023-02-01T00:00:00Z");
+        
when(item.getUpdated()).thenReturn(Optional.of("2023-02-01T00:00:00Z"));
+
+        // Act and Assert
+        assertTrue(strategy.isValidItem(item));
+        
when(item.getUpdated()).thenReturn(Optional.of("2023-01-01T00:00:00Z"));
+        assertFalse(strategy.isValidItem(item));
+    }
+
+    @Test
+    void testValidEntryWithPubDateFallback() throws ParseException {
+        // Arrange
+        ItemUpdatedIdempotentStrategy strategy = new 
ItemUpdatedIdempotentStrategy();
+        Item item = Mockito.mock(Item.class);
+
+        when(item.getUpdated()).thenReturn(Optional.empty());
+        
when(item.getPubDate()).thenReturn(Optional.of("2023-03-01T00:00:00Z"));
+
+        // Act and Assert
+        assertTrue(strategy.isValidItem(item));
+
+        
when(item.getPubDate()).thenReturn(Optional.of("2023-01-01T00:00:00Z"));
+        assertFalse(strategy.isValidItem(item));
+    }
+
+    @Test
+    void testValidEntryWithNoDatesAvailable() {
+        // Arrange
+        Item item = Mockito.mock(Item.class);
+        when(item.getUpdated()).thenReturn(Optional.empty());
+        when(item.getPubDate()).thenReturn(Optional.empty());
+
+        ItemUpdatedIdempotentStrategy strategy = new 
ItemUpdatedIdempotentStrategy();
+
+        // Act and Assert
+        assertTrue(strategy.isValidItem(item));
+    }
+
+    @Test
+    void testEntryWithInvalidDateString() {
+        // Arrange
+        Item item = Mockito.mock(Item.class);
+        when(item.getUpdated()).thenReturn(Optional.of("invalid-date"));
+        when(item.getPubDate()).thenReturn(Optional.of("invalid-date"));
+
+        ItemUpdatedIdempotentStrategy strategy = new 
ItemUpdatedIdempotentStrategy();
+
+        // Act
+        boolean isValid = strategy.isValidItem(item);
+
+        // Assert
+        assertTrue(isValid);
+    }
+
+    @Test
+    void testEntryWithEqualDate() throws ParseException {
+        // Arrange
+        Item item1 = Mockito.mock(Item.class);
+        Item item2 = Mockito.mock(Item.class);
+        ItemUpdatedIdempotentStrategy strategy = new 
ItemUpdatedIdempotentStrategy();
+
+        Date date = AtomConverter.toDate("2023-01-01T00:00:00Z");
+        
when(item1.getUpdated()).thenReturn(Optional.of("2023-01-01T00:00:00Z"));
+        
when(item2.getUpdated()).thenReturn(Optional.of("2023-01-01T00:00:00Z"));
+
+        // Act and Assert
+        // First item is valid
+        assertTrue(strategy.isValidItem(item1));
+
+        // Second item is invalid because it has the same updated date
+        assertFalse(strategy.isValidItem(item2));
+    }
+}
diff --git 
a/components/camel-atom/src/test/java/org/apache/camel/component/atom/RepositoryGuidIdempotentStrategyTest.java
 
b/components/camel-atom/src/test/java/org/apache/camel/component/atom/RepositoryGuidIdempotentStrategyTest.java
new file mode 100644
index 000000000000..eed334b958a4
--- /dev/null
+++ 
b/components/camel-atom/src/test/java/org/apache/camel/component/atom/RepositoryGuidIdempotentStrategyTest.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.atom;
+
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.apptasticsoftware.rssreader.Item;
+import com.apptasticsoftware.rssreader.RssReader;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class RepositoryGuidIdempotentStrategyTest {
+
+    @Test
+    void testIsValidItemReturnsTrueForNullEntry() {
+        RepositoryGuidIdempotentStrategy strategy = new 
RepositoryGuidIdempotentStrategy();
+
+        assertTrue(strategy.isValidItem(null));
+    }
+
+    @Test
+    void testIsValidItemAcceptsFirstGuidAndRejectsDuplicate() throws Exception 
{
+        RepositoryGuidIdempotentStrategy strategy = new 
RepositoryGuidIdempotentStrategy();
+        Item item = loadItemsWithGuid(1).get(0);
+
+        assertTrue(strategy.isValidItem(item), "First time GUID should be 
accepted");
+        assertFalse(strategy.isValidItem(item), "Duplicate GUID should be 
rejected");
+    }
+
+    @Test
+    void testIsValidItemAcceptsDifferentGuids() throws Exception {
+        RepositoryGuidIdempotentStrategy strategy = new 
RepositoryGuidIdempotentStrategy();
+        List<Item> items = loadItemsWithGuid(2);
+
+        assertTrue(strategy.isValidItem(items.get(0)), "First GUID should be 
accepted");
+        assertTrue(strategy.isValidItem(items.get(1)), "Second, different GUID 
should also be accepted");
+    }
+
+    private static List<Item> loadItemsWithGuid(int count) throws Exception {
+        try (InputStream is = 
Files.newInputStream(Path.of("src/test/data/feed.atom"))) {
+            return new RssReader()
+                    .read(is)
+                    .filter(item -> item.getGuid().isPresent())
+                    .limit(count)
+                    .collect(Collectors.toList());
+        }
+    }
+}
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/AtomEndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/AtomEndpointBuilderFactory.java
index 829f58b56602..5377305f2103 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/AtomEndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/AtomEndpointBuilderFactory.java
@@ -174,6 +174,80 @@ public interface AtomEndpointBuilderFactory {
             doSetProperty("throttleEntries", throttleEntries);
             return this;
         }
+        /**
+         * Option to use the Idempotent Consumer EIP pattern to let Camel skip
+         * already processed entries. By default it skips Atom entries that is
+         * older that the last read entry, using Atom updatedDate and
+         * publishedDate, but this strategy can be changed with the
+         * idempotentStrategy option. Idempotency only works when splitEntries 
=
+         * true.
+         * 
+         * The option is a: <code>boolean</code> type.
+         * 
+         * Default: true
+         * Group: filter
+         * 
+         * @param idempotent the value to set
+         * @return the dsl builder
+         */
+        default AtomEndpointBuilder idempotent(boolean idempotent) {
+            doSetProperty("idempotent", idempotent);
+            return this;
+        }
+        /**
+         * Option to use the Idempotent Consumer EIP pattern to let Camel skip
+         * already processed entries. By default it skips Atom entries that is
+         * older that the last read entry, using Atom updatedDate and
+         * publishedDate, but this strategy can be changed with the
+         * idempotentStrategy option. Idempotency only works when splitEntries 
=
+         * true.
+         * 
+         * The option will be converted to a <code>boolean</code> type.
+         * 
+         * Default: true
+         * Group: filter
+         * 
+         * @param idempotent the value to set
+         * @return the dsl builder
+         */
+        default AtomEndpointBuilder idempotent(String idempotent) {
+            doSetProperty("idempotent", idempotent);
+            return this;
+        }
+        /**
+         * A pluggable repository org.apache.camel.spi.IdempotentRepository
+         * which by default use MemoryIdempotentRepository if none is specified
+         * and idempotent is true.
+         * 
+         * The option is a:
+         * <code>org.apache.camel.spi.IdempotentRepository</code> type.
+         * 
+         * Group: filter
+         * 
+         * @param idempotentRepository the value to set
+         * @return the dsl builder
+         */
+        default AtomEndpointBuilder 
idempotentRepository(org.apache.camel.spi.IdempotentRepository 
idempotentRepository) {
+            doSetProperty("idempotentRepository", idempotentRepository);
+            return this;
+        }
+        /**
+         * A pluggable repository org.apache.camel.spi.IdempotentRepository
+         * which by default use MemoryIdempotentRepository if none is specified
+         * and idempotent is true.
+         * 
+         * The option will be converted to a
+         * <code>org.apache.camel.spi.IdempotentRepository</code> type.
+         * 
+         * Group: filter
+         * 
+         * @param idempotentRepository the value to set
+         * @return the dsl builder
+         */
+        default AtomEndpointBuilder idempotentRepository(String 
idempotentRepository) {
+            doSetProperty("idempotentRepository", idempotentRepository);
+            return this;
+        }
         /**
          * The number of subsequent error polls (failed due some error) that
          * should happen before the backoffMultipler should kick-in.
@@ -826,6 +900,56 @@ public interface AtomEndpointBuilderFactory {
             doSetProperty("feedHeader", feedHeader);
             return this;
         }
+        /**
+         * A pluggable strategy
+         * org.apache.camel.component.FeedIdempotentStrategy to use when
+         * checking idempotency. Camel provides two implementations out of the
+         * box: default and repository. The updated strategy is used as default
+         * if idempotent = true. The default strategy checks the Atom entrys
+         * updated or published date is newer than the previously read entry.
+         * You can provide your own implementation of the
+         * org.apache.camel.component.FeedIdempotentStrategy and refer to it
+         * using the # notation.
+         * 
+         * The option is a:
+         * <code>org.apache.camel.component.atom.AtomIdempotentStrategy</code>
+         * type.
+         * 
+         * Default: default
+         * Group: filter (advanced)
+         * 
+         * @param idempotentStrategy the value to set
+         * @return the dsl builder
+         */
+        default AdvancedAtomEndpointBuilder 
idempotentStrategy(org.apache.camel.component.atom.AtomIdempotentStrategy 
idempotentStrategy) {
+            doSetProperty("idempotentStrategy", idempotentStrategy);
+            return this;
+        }
+        /**
+         * A pluggable strategy
+         * org.apache.camel.component.FeedIdempotentStrategy to use when
+         * checking idempotency. Camel provides two implementations out of the
+         * box: default and repository. The updated strategy is used as default
+         * if idempotent = true. The default strategy checks the Atom entrys
+         * updated or published date is newer than the previously read entry.
+         * You can provide your own implementation of the
+         * org.apache.camel.component.FeedIdempotentStrategy and refer to it
+         * using the # notation.
+         * 
+         * The option will be converted to a
+         * <code>org.apache.camel.component.atom.AtomIdempotentStrategy</code>
+         * type.
+         * 
+         * Default: default
+         * Group: filter (advanced)
+         * 
+         * @param idempotentStrategy the value to set
+         * @return the dsl builder
+         */
+        default AdvancedAtomEndpointBuilder idempotentStrategy(String 
idempotentStrategy) {
+            doSetProperty("idempotentStrategy", idempotentStrategy);
+            return this;
+        }
     }
 
     public interface AtomBuilders {

Reply via email to