You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by honghebox <ao...@gmail.com> on 2012/02/11 05:01:28 UTC
Cron job removed from quartz scheduler by DefaultCamelContext
My route builder has a route starts with a cron job that executes every 5
minutes, but it never get kicked off by quartz scheduler and from the log
file, seems the job is removed because of routes shut down by the camel
context, here is what I did:
*1. the way I run camel in standalone mode:*
java MyMain appContext.xml
*2. MyMain class:*
public class MyMain extends RouteBuilder {
public static void main(String... args) {
try {
org.apache.camel.spring.Main.main(args);
}
catch(Exception e) {
e.printStackTrace();
}
}
public void configure() {
}
}
*3. appContext.xml defines a camel context:*
<camelContext id="myCamelContext"
xmlns="http://camel.apache.org/schema/spring">
<packageScan>
<package>com.mycompany.routes</package>
.............................
*4. my route builder:*
public class MyCronJobRouteBuilder extends RouteBuilder {
public void configure() {
from("quartz://myGroup/myTimer?cron=0+0/5+*+*+*+?")
.routeId("MyCronJobRoute}")
.log(LoggingLevel.INFO, "My cron job started at ${header.fireTime} ")
................................
}
}
the "My cron job started at ${header.fireTime}" never get logged so the cron
job never started, from the log file, seems the route was created, scheduler
started and the job was added to scheduler too, but it was removed from the
scheduler when the DefaultCamelContext shuts down the route, anyone can help
me with a solution to prevent the camel context shut down the route and
remove the cron job? Thanks in advance ......
[ main] QuartzScheduler INFO Quartz
Scheduler v.1.8.3 created.
[ main] RAMJobStore INFO
RAMJobStore initialized.
[ main] QuartzScheduler INFO
Scheduler meta-data: Quartz Scheduler (v1.8.3) 'DefaultQuartzScheduler' with
instanceId 'NON_CLUSTERED'
Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
NOT STARTED.
Currently in standby mode.
Number of jobs executed: 0
Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support
persistence. and is not clustered.
[ main] StdSchedulerFactory INFO Quartz
scheduler 'DefaultQuartzScheduler' initialized from default resource file in
Quartz package: 'quartz.properties'
[ main] StdSchedulerFactory INFO Quartz
scheduler version: 1.8.3
[ main] QuartzComponent INFO
Starting Quartz scheduler: DefaultQuartzScheduler
[ main] QuartzScheduler INFO
Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
[ main] DefaultComponent DEBUG
Creating endpoint uri=[quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F],
path=[myGroup/myTimer], parameters=[{cron=0 0/5 * * * ?}]
[ main] DefaultCamelContext DEBUG
quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F converted to endpoint:
Endpoint[quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F] by component:
org.apache.camel.component.quartz.QuartzComponent@487c5f
[ main] QuartzConsumer DEBUG
Starting consumer: Consumer[quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F]
[ main] QuartzEndpoint DEBUG Adding
consumer Instrumentation:route[UnitOfWork(Pipeline[[Channel[Log[My cron job
started at ${header.fireTime}, cron job expression -
quartz://myGroup/myTimer?cron=0+0+0/4+*+*+?]], Channel[BeanProcessor[bean:
...................................................................
*[ main] QuartzComponent DEBUG
Adding job using trigger: *staleMeter/staleMeterDetectionTimer
[ main] DefaultCamelContext INFO Route:
quartz:MyCronJobRoute started and consuming from:
Endpoint[quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F]
...................................
[ main] DefaultExecutorServiceStrategy DEBUG
ShutdownNow ExecutorService: java.util.concurrent.ThreadPoolExecutor@a84b47
[ main] DefaultCamelContext INFO Apache
Camel 2.5.0 (CamelContext:myCamelContext) is shutting down
[ main] DefaultShutdownStrategy INFO
Starting to graceful shutdown 1 routes (timeout 10 seconds)
[ Camel Thread 0 - ShutdownTask] QuartzComponent DEBUG
Pausing job using trigger: myGroup/myTimer
*[ Camel Thread 0 - ShutdownTask] QuartzEndpoint DEBUG
Removing consumer* Instrumentation:route[UnitOfWork(Pipeline[[Channel[Log[My
cron job started at ${header.fireTime}]],
...................
--
View this message in context: http://camel.465427.n5.nabble.com/Cron-job-removed-from-quartz-scheduler-by-DefaultCamelContext-tp5474330p5474330.html
Sent from the Camel - Users mailing list archive at Nabble.com.
Re: Cron job removed from quartz scheduler by DefaultCamelContext
Posted by honghebox <ao...@gmail.com>.
Thanks a lot for the response!
The scheduler is partially working now --
1. Camel keep running all the time, scheduler NOT forced to shut down
because of Camel routes stopped.
2. Scheduler started and did add the job using the trigger -- see below
logging output
But the job never get invoked, looks like the DefaultQuartzScheduler keep
trying to kick off the job for every second (the cron job suppose to run
every 2 minutes), but the job never run (Camel version: 2.5.0, OS: RedHat
Enterprise 5.5, JDK 1.6):
--
View this message in context: http://camel.465427.n5.nabble.com/Cron-job-removed-from-quartz-scheduler-by-DefaultCamelContext-tp5474330p5484828.html
Sent from the Camel - Users mailing list archive at Nabble.com.
Re: Cron job removed from quartz scheduler by DefaultCamelContext
Posted by Claus Ibsen <cl...@gmail.com>.
Hi
Yeah the run method on the main instance should be able to keep
running, until, you ask Camel to stop.
And using the enableHangupSupport is a good idea, as then when you
terminate the JVM then its detected
and Camel is shutting down nicely. For example pressing cltr + d /
cltr + c in a console etc.
On Sat, Feb 11, 2012 at 7:04 PM, Vincent Nonnenmacher
<vi...@gmail.com> wrote:
> On Sat, Feb 11, 2012 at 5:01 AM, honghebox <ao...@gmail.com> wrote:
>
>> My route builder has a route starts with a cron job that executes every 5
>> minutes, but it never get kicked off by quartz scheduler and from the log
>> file, seems the job is removed because of routes shut down by the camel
>> context, here is what I did:
>> *1. the way I run camel in standalone mode:*
>> java MyMain appContext.xml
>> *2. MyMain class:*
>> public class MyMain extends RouteBuilder {
>> public static void main(String... args) {
>> try {
>> org.apache.camel.spring.Main.main(args);
>> }
>> catch(Exception e) {
>> e.printStackTrace();
>> }
>> }
>> public void configure() {
>> }
>> }
>> *3. appContext.xml defines a camel context:*
>> <camelContext id="myCamelContext"
>> xmlns="http://camel.apache.org/schema/spring">
>> <packageScan>
>> <package>com.mycompany.routes</package>
>> .............................
>> *4. my route builder:*
>> public class MyCronJobRouteBuilder extends RouteBuilder {
>> public void configure() {
>> from("quartz://myGroup/myTimer?cron=0+0/5+*+*+*+?")
>> .routeId("MyCronJobRoute}")
>> .log(LoggingLevel.INFO, "My cron job started at
>> ${header.fireTime} ")
>> ................................
>> }
>> }
>>
>> the "My cron job started at ${header.fireTime}" never get logged so the
>> cron
>> job never started, from the log file, seems the route was created,
>> scheduler
>> started and the job was added to scheduler too, but it was removed from the
>> scheduler when the DefaultCamelContext shuts down the route, anyone can
>> help
>> me with a solution to prevent the camel context shut down the route and
>> remove the cron job? Thanks in advance ......
>>
>
> I don't see that you wait for camel to stop (by what means it depends of
> your app)
>
> but it sound like you start the routing and immediately ask camel to
> shutdown
> didn't your code should me something like :
>
>
> org.apache.camel.spring.Main camelMain = new Main();
> camelMain.setApplicationContextUri(<your spring context
> uri>);
> camelMain.enableTrace();
> camelMain.enableHangupSupport();
> // start the server, Main class will handle all signals, shutdown and
> // implement proper exit strategy and then set the done flag
> camelMain.start();
> while(!camelMain.isStopped())
> {
> // do monitoring, heath care and perhaps
> // some preventive GC from time to time
> Thread.sleep(1000L);
> }
>
> ...
>
>
>>
>> [ main] QuartzScheduler INFO
>> Quartz
>> Scheduler v.1.8.3 created.
>> [ main] RAMJobStore INFO
>> RAMJobStore initialized.
>> [ main] QuartzScheduler INFO
>> Scheduler meta-data: Quartz Scheduler (v1.8.3) 'DefaultQuartzScheduler'
>> with
>> instanceId 'NON_CLUSTERED'
>> Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
>> NOT STARTED.
>> Currently in standby mode.
>> Number of jobs executed: 0
>> Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
>> Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support
>> persistence. and is not clustered.
>>
>> [ main] StdSchedulerFactory INFO
>> Quartz
>> scheduler 'DefaultQuartzScheduler' initialized from default resource file
>> in
>> Quartz package: 'quartz.properties'
>> [ main] StdSchedulerFactory INFO
>> Quartz
>> scheduler version: 1.8.3
>> [ main] QuartzComponent INFO
>> Starting Quartz scheduler: DefaultQuartzScheduler
>> [ main] QuartzScheduler INFO
>> Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
>>
>> [ main] DefaultComponent DEBUG
>> Creating endpoint uri=[quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F],
>> path=[myGroup/myTimer], parameters=[{cron=0 0/5 * * * ?}]
>> [ main] DefaultCamelContext DEBUG
>> quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F converted to endpoint:
>> Endpoint[quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F] by component:
>> org.apache.camel.component.quartz.QuartzComponent@487c5f
>> [ main] QuartzConsumer DEBUG
>> Starting consumer:
>> Consumer[quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F]
>> [ main] QuartzEndpoint DEBUG
>> Adding
>> consumer Instrumentation:route[UnitOfWork(Pipeline[[Channel[Log[My cron job
>> started at ${header.fireTime}, cron job expression -
>> quartz://myGroup/myTimer?cron=0+0+0/4+*+*+?]], Channel[BeanProcessor[bean:
>> ...................................................................
>>
>> *[ main] QuartzComponent DEBUG
>> Adding job using trigger: *staleMeter/staleMeterDetectionTimer
>> [ main] DefaultCamelContext INFO
>> Route:
>> quartz:MyCronJobRoute started and consuming from:
>> Endpoint[quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F]
>>
>> ...................................
>>
>> [ main] DefaultExecutorServiceStrategy DEBUG
>> ShutdownNow ExecutorService: java.util.concurrent.ThreadPoolExecutor@a84b47
>> [ main] DefaultCamelContext INFO
>> Apache
>> Camel 2.5.0 (CamelContext:myCamelContext) is shutting down
>> [ main] DefaultShutdownStrategy INFO
>> Starting to graceful shutdown 1 routes (timeout 10 seconds)
>> [ Camel Thread 0 - ShutdownTask] QuartzComponent DEBUG
>> Pausing job using trigger: myGroup/myTimer
>> *[ Camel Thread 0 - ShutdownTask] QuartzEndpoint DEBUG
>> Removing consumer*
>> Instrumentation:route[UnitOfWork(Pipeline[[Channel[Log[My
>> cron job started at ${header.fireTime}]],
>> ...................
>>
>> --
>> View this message in context:
>> http://camel.465427.n5.nabble.com/Cron-job-removed-from-quartz-scheduler-by-DefaultCamelContext-tp5474330p5474330.html
>> Sent from the Camel - Users mailing list archive at Nabble.com.
>>
--
Claus Ibsen
-----------------
FuseSource
Email: cibsen@fusesource.com
Web: http://fusesource.com
Twitter: davsclaus, fusenews
Blog: http://davsclaus.blogspot.com/
Author of Camel in Action: http://www.manning.com/ibsen/
Re: Cron job removed from quartz scheduler by DefaultCamelContext
Posted by Vincent Nonnenmacher <vi...@gmail.com>.
On Sat, Feb 11, 2012 at 5:01 AM, honghebox <ao...@gmail.com> wrote:
> My route builder has a route starts with a cron job that executes every 5
> minutes, but it never get kicked off by quartz scheduler and from the log
> file, seems the job is removed because of routes shut down by the camel
> context, here is what I did:
> *1. the way I run camel in standalone mode:*
> java MyMain appContext.xml
> *2. MyMain class:*
> public class MyMain extends RouteBuilder {
> public static void main(String... args) {
> try {
> org.apache.camel.spring.Main.main(args);
> }
> catch(Exception e) {
> e.printStackTrace();
> }
> }
> public void configure() {
> }
> }
> *3. appContext.xml defines a camel context:*
> <camelContext id="myCamelContext"
> xmlns="http://camel.apache.org/schema/spring">
> <packageScan>
> <package>com.mycompany.routes</package>
> .............................
> *4. my route builder:*
> public class MyCronJobRouteBuilder extends RouteBuilder {
> public void configure() {
> from("quartz://myGroup/myTimer?cron=0+0/5+*+*+*+?")
> .routeId("MyCronJobRoute}")
> .log(LoggingLevel.INFO, "My cron job started at
> ${header.fireTime} ")
> ................................
> }
> }
>
> the "My cron job started at ${header.fireTime}" never get logged so the
> cron
> job never started, from the log file, seems the route was created,
> scheduler
> started and the job was added to scheduler too, but it was removed from the
> scheduler when the DefaultCamelContext shuts down the route, anyone can
> help
> me with a solution to prevent the camel context shut down the route and
> remove the cron job? Thanks in advance ......
>
I don't see that you wait for camel to stop (by what means it depends of
your app)
but it sound like you start the routing and immediately ask camel to
shutdown
didn't your code should me something like :
org.apache.camel.spring.Main camelMain = new Main();
camelMain.setApplicationContextUri(<your spring context
uri>);
camelMain.enableTrace();
camelMain.enableHangupSupport();
// start the server, Main class will handle all signals, shutdown and
// implement proper exit strategy and then set the done flag
camelMain.start();
while(!camelMain.isStopped())
{
// do monitoring, heath care and perhaps
// some preventive GC from time to time
Thread.sleep(1000L);
}
...
>
> [ main] QuartzScheduler INFO
> Quartz
> Scheduler v.1.8.3 created.
> [ main] RAMJobStore INFO
> RAMJobStore initialized.
> [ main] QuartzScheduler INFO
> Scheduler meta-data: Quartz Scheduler (v1.8.3) 'DefaultQuartzScheduler'
> with
> instanceId 'NON_CLUSTERED'
> Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
> NOT STARTED.
> Currently in standby mode.
> Number of jobs executed: 0
> Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
> Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support
> persistence. and is not clustered.
>
> [ main] StdSchedulerFactory INFO
> Quartz
> scheduler 'DefaultQuartzScheduler' initialized from default resource file
> in
> Quartz package: 'quartz.properties'
> [ main] StdSchedulerFactory INFO
> Quartz
> scheduler version: 1.8.3
> [ main] QuartzComponent INFO
> Starting Quartz scheduler: DefaultQuartzScheduler
> [ main] QuartzScheduler INFO
> Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
>
> [ main] DefaultComponent DEBUG
> Creating endpoint uri=[quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F],
> path=[myGroup/myTimer], parameters=[{cron=0 0/5 * * * ?}]
> [ main] DefaultCamelContext DEBUG
> quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F converted to endpoint:
> Endpoint[quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F] by component:
> org.apache.camel.component.quartz.QuartzComponent@487c5f
> [ main] QuartzConsumer DEBUG
> Starting consumer:
> Consumer[quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F]
> [ main] QuartzEndpoint DEBUG
> Adding
> consumer Instrumentation:route[UnitOfWork(Pipeline[[Channel[Log[My cron job
> started at ${header.fireTime}, cron job expression -
> quartz://myGroup/myTimer?cron=0+0+0/4+*+*+?]], Channel[BeanProcessor[bean:
> ...................................................................
>
> *[ main] QuartzComponent DEBUG
> Adding job using trigger: *staleMeter/staleMeterDetectionTimer
> [ main] DefaultCamelContext INFO
> Route:
> quartz:MyCronJobRoute started and consuming from:
> Endpoint[quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F]
>
> ...................................
>
> [ main] DefaultExecutorServiceStrategy DEBUG
> ShutdownNow ExecutorService: java.util.concurrent.ThreadPoolExecutor@a84b47
> [ main] DefaultCamelContext INFO
> Apache
> Camel 2.5.0 (CamelContext:myCamelContext) is shutting down
> [ main] DefaultShutdownStrategy INFO
> Starting to graceful shutdown 1 routes (timeout 10 seconds)
> [ Camel Thread 0 - ShutdownTask] QuartzComponent DEBUG
> Pausing job using trigger: myGroup/myTimer
> *[ Camel Thread 0 - ShutdownTask] QuartzEndpoint DEBUG
> Removing consumer*
> Instrumentation:route[UnitOfWork(Pipeline[[Channel[Log[My
> cron job started at ${header.fireTime}]],
> ...................
>
> --
> View this message in context:
> http://camel.465427.n5.nabble.com/Cron-job-removed-from-quartz-scheduler-by-DefaultCamelContext-tp5474330p5474330.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>
Re: Cron job removed from quartz scheduler by DefaultCamelContext
Posted by Claus Ibsen <cl...@gmail.com>.
Hi
You need to keep the main app running. See this FAQ
http://camel.apache.org/running-camel-standalone-and-have-it-keep-running.html
On Sat, Feb 11, 2012 at 5:01 AM, honghebox <ao...@gmail.com> wrote:
> My route builder has a route starts with a cron job that executes every 5
> minutes, but it never get kicked off by quartz scheduler and from the log
> file, seems the job is removed because of routes shut down by the camel
> context, here is what I did:
> *1. the way I run camel in standalone mode:*
> java MyMain appContext.xml
> *2. MyMain class:*
> public class MyMain extends RouteBuilder {
> public static void main(String... args) {
> try {
> org.apache.camel.spring.Main.main(args);
> }
> catch(Exception e) {
> e.printStackTrace();
> }
> }
> public void configure() {
> }
> }
> *3. appContext.xml defines a camel context:*
> <camelContext id="myCamelContext"
> xmlns="http://camel.apache.org/schema/spring">
> <packageScan>
> <package>com.mycompany.routes</package>
> .............................
> *4. my route builder:*
> public class MyCronJobRouteBuilder extends RouteBuilder {
> public void configure() {
> from("quartz://myGroup/myTimer?cron=0+0/5+*+*+*+?")
> .routeId("MyCronJobRoute}")
> .log(LoggingLevel.INFO, "My cron job started at ${header.fireTime} ")
> ................................
> }
> }
>
> the "My cron job started at ${header.fireTime}" never get logged so the cron
> job never started, from the log file, seems the route was created, scheduler
> started and the job was added to scheduler too, but it was removed from the
> scheduler when the DefaultCamelContext shuts down the route, anyone can help
> me with a solution to prevent the camel context shut down the route and
> remove the cron job? Thanks in advance ......
>
> [ main] QuartzScheduler INFO Quartz
> Scheduler v.1.8.3 created.
> [ main] RAMJobStore INFO
> RAMJobStore initialized.
> [ main] QuartzScheduler INFO
> Scheduler meta-data: Quartz Scheduler (v1.8.3) 'DefaultQuartzScheduler' with
> instanceId 'NON_CLUSTERED'
> Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
> NOT STARTED.
> Currently in standby mode.
> Number of jobs executed: 0
> Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
> Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support
> persistence. and is not clustered.
>
> [ main] StdSchedulerFactory INFO Quartz
> scheduler 'DefaultQuartzScheduler' initialized from default resource file in
> Quartz package: 'quartz.properties'
> [ main] StdSchedulerFactory INFO Quartz
> scheduler version: 1.8.3
> [ main] QuartzComponent INFO
> Starting Quartz scheduler: DefaultQuartzScheduler
> [ main] QuartzScheduler INFO
> Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
>
> [ main] DefaultComponent DEBUG
> Creating endpoint uri=[quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F],
> path=[myGroup/myTimer], parameters=[{cron=0 0/5 * * * ?}]
> [ main] DefaultCamelContext DEBUG
> quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F converted to endpoint:
> Endpoint[quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F] by component:
> org.apache.camel.component.quartz.QuartzComponent@487c5f
> [ main] QuartzConsumer DEBUG
> Starting consumer: Consumer[quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F]
> [ main] QuartzEndpoint DEBUG Adding
> consumer Instrumentation:route[UnitOfWork(Pipeline[[Channel[Log[My cron job
> started at ${header.fireTime}, cron job expression -
> quartz://myGroup/myTimer?cron=0+0+0/4+*+*+?]], Channel[BeanProcessor[bean:
> ...................................................................
>
> *[ main] QuartzComponent DEBUG
> Adding job using trigger: *staleMeter/staleMeterDetectionTimer
> [ main] DefaultCamelContext INFO Route:
> quartz:MyCronJobRoute started and consuming from:
> Endpoint[quartz://myGroup/myTimer?cron=0+0%2F5+*+*+*+%3F]
>
> ...................................
>
> [ main] DefaultExecutorServiceStrategy DEBUG
> ShutdownNow ExecutorService: java.util.concurrent.ThreadPoolExecutor@a84b47
> [ main] DefaultCamelContext INFO Apache
> Camel 2.5.0 (CamelContext:myCamelContext) is shutting down
> [ main] DefaultShutdownStrategy INFO
> Starting to graceful shutdown 1 routes (timeout 10 seconds)
> [ Camel Thread 0 - ShutdownTask] QuartzComponent DEBUG
> Pausing job using trigger: myGroup/myTimer
> *[ Camel Thread 0 - ShutdownTask] QuartzEndpoint DEBUG
> Removing consumer* Instrumentation:route[UnitOfWork(Pipeline[[Channel[Log[My
> cron job started at ${header.fireTime}]],
> ...................
>
> --
> View this message in context: http://camel.465427.n5.nabble.com/Cron-job-removed-from-quartz-scheduler-by-DefaultCamelContext-tp5474330p5474330.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
--
Claus Ibsen
-----------------
FuseSource
Email: cibsen@fusesource.com
Web: http://fusesource.com
Twitter: davsclaus, fusenews
Blog: http://davsclaus.blogspot.com/
Author of Camel in Action: http://www.manning.com/ibsen/