You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@camel.apache.org by Claus Ibsen <cl...@gmail.com> on 2010/10/16 15:26:40 UTC

[DISCUSS] - Easier Camel route debugging from Camel Test Kit

Hi

At first read this blog post
http://davsclaus.blogspot.com/2010/10/paris-and-easier-camel-route-debugging.html

Then this example with full source code. Notice how we use the debug
method with the breakpoint
to have Camel invoke the beforeProcess at each step in the route. This
allows you easily to debug the route.
See the screenshot in the blog post.

public class DebugTest extends CamelTestSupport {

    public void testDebugger() throws Exception {
        // you can debug camel routes easily as shown below:
        debug(new BreakpointSupport() {
            public void beforeProcess(Exchange exchange, Processor
processor, ProcessorDefinition definition) {
                // this method is invoked before we are about to enter
the given processor
                // from your Java editor you can just add a breakpoint
in the code line below
                log.info("Before " + definition + " with body " +
exchange.getIn().getBody());
            }
        });

        // set mock expectations
        getMockEndpoint("mock:a").expectedMessageCount(1);
        getMockEndpoint("mock:b").expectedMessageCount(1);

        // send a message
        template.sendBody("direct:start", "World");

        // assert mocks
        assertMockEndpointsSatisfied();
    }

    @Override
    protected RouteBuilder createRouteBuilder() throws Exception {
        return new RouteBuilder() {
            @Override
            public void configure() throws Exception {
                // this is the route we want to debug
                from("direct:start")
                    .to("mock:a")
                    .transform(body().prepend("Hello "))
                    .to("mock:b");
            }
        };
    }
}



To do this requires the anonymous inner class (poor mans closures) and
can be a bit verbose.
What if we provide the debugger out of the box in the sense we have it
implemented directly in the CamelTestSupport class.

Then all you need to do is to override the beforeProcess class on the
CamelTestSupport which makes the code less verbose
This makes the code a bit smaller. And therefore all the end user need
to do is to override either/or both beforeProcess, afterProcess to
easily debug the route.

We can also provide both approaches so you can do both if you like?

Any thoughts?


public class DebugTest extends CamelTestSupport {

    @Override
    protected void beforeProcess(Exchange exchange, Processor
processor, ProcessorDefinition definition) {
        // this method is invoked before we are about to enter the
given processor
        // from your Java editor you can just add a breakpoint in the
code line below
        log.info("Before " + definition + " with body " +
exchange.getIn().getBody());
    }

    public void testDebugger() throws Exception {
        // set mock expectations
        getMockEndpoint("mock:a").expectedMessageCount(1);
        getMockEndpoint("mock:b").expectedMessageCount(1);

        // send a message
        template.sendBody("direct:start", "World");

        // assert mocks
        assertMockEndpointsSatisfied();
    }

    @Override
    protected RouteBuilder createRouteBuilder() throws Exception {
        return new RouteBuilder() {
            @Override
            public void configure() throws Exception {
                // this is the route we want to debug
                from("direct:start")
                    .to("mock:a")
                    .transform(body().prepend("Hello "))
                    .to("mock:b");
            }
        };
    }
}



-- 
Claus Ibsen
Apache Camel Committer

Author of Camel in Action: http://www.manning.com/ibsen/
Open Source Integration: http://fusesource.com
Blog: http://davsclaus.blogspot.com/
Twitter: http://twitter.com/davsclaus

Re: [DISCUSS] - Easier Camel route debugging from Camel Test Kit

Posted by Jean-Baptiste Onofré <jb...@nanthrax.net>.
Hi Claus,

I'm playing with CamelTestSupport in new components.

Overriding beforeProcess() method is very helpful to reduce the verbosity.

+1 to override it in the CamelTestSupport.

Regards
JB

On 10/16/2010 03:26 PM, Claus Ibsen wrote:
> Hi
>
> At first read this blog post
> http://davsclaus.blogspot.com/2010/10/paris-and-easier-camel-route-debugging.html
>
> Then this example with full source code. Notice how we use the debug
> method with the breakpoint
> to have Camel invoke the beforeProcess at each step in the route. This
> allows you easily to debug the route.
> See the screenshot in the blog post.
>
> public class DebugTest extends CamelTestSupport {
>
>      public void testDebugger() throws Exception {
>          // you can debug camel routes easily as shown below:
>          debug(new BreakpointSupport() {
>              public void beforeProcess(Exchange exchange, Processor
> processor, ProcessorDefinition definition) {
>                  // this method is invoked before we are about to enter
> the given processor
>                  // from your Java editor you can just add a breakpoint
> in the code line below
>                  log.info("Before " + definition + " with body " +
> exchange.getIn().getBody());
>              }
>          });
>
>          // set mock expectations
>          getMockEndpoint("mock:a").expectedMessageCount(1);
>          getMockEndpoint("mock:b").expectedMessageCount(1);
>
>          // send a message
>          template.sendBody("direct:start", "World");
>
>          // assert mocks
>          assertMockEndpointsSatisfied();
>      }
>
>      @Override
>      protected RouteBuilder createRouteBuilder() throws Exception {
>          return new RouteBuilder() {
>              @Override
>              public void configure() throws Exception {
>                  // this is the route we want to debug
>                  from("direct:start")
>                      .to("mock:a")
>                      .transform(body().prepend("Hello "))
>                      .to("mock:b");
>              }
>          };
>      }
> }
>
>
>
> To do this requires the anonymous inner class (poor mans closures) and
> can be a bit verbose.
> What if we provide the debugger out of the box in the sense we have it
> implemented directly in the CamelTestSupport class.
>
> Then all you need to do is to override the beforeProcess class on the
> CamelTestSupport which makes the code less verbose
> This makes the code a bit smaller. And therefore all the end user need
> to do is to override either/or both beforeProcess, afterProcess to
> easily debug the route.
>
> We can also provide both approaches so you can do both if you like?
>
> Any thoughts?
>
>
> public class DebugTest extends CamelTestSupport {
>
>      @Override
>      protected void beforeProcess(Exchange exchange, Processor
> processor, ProcessorDefinition definition) {
>          // this method is invoked before we are about to enter the
> given processor
>          // from your Java editor you can just add a breakpoint in the
> code line below
>          log.info("Before " + definition + " with body " +
> exchange.getIn().getBody());
>      }
>
>      public void testDebugger() throws Exception {
>          // set mock expectations
>          getMockEndpoint("mock:a").expectedMessageCount(1);
>          getMockEndpoint("mock:b").expectedMessageCount(1);
>
>          // send a message
>          template.sendBody("direct:start", "World");
>
>          // assert mocks
>          assertMockEndpointsSatisfied();
>      }
>
>      @Override
>      protected RouteBuilder createRouteBuilder() throws Exception {
>          return new RouteBuilder() {
>              @Override
>              public void configure() throws Exception {
>                  // this is the route we want to debug
>                  from("direct:start")
>                      .to("mock:a")
>                      .transform(body().prepend("Hello "))
>                      .to("mock:b");
>              }
>          };
>      }
> }
>
>
>

Re: [DISCUSS] - Easier Camel route debugging from Camel Test Kit

Posted by Richard Kettelerij <ri...@gmail.com>.
Nice work Claus. Occasionally i've also felt the need for easier debugging of
Camel routes (although proper unit- and integration tests help reduce this
issue a lot).

When debugging I think it might be useful for users to call getShortName()
on the provided ProcessorDefinition in beforeProcess() to limit the number
of invocations and quickly find the right processor. For example:

  @Override
  protected void beforeProcess(Exchange exchange, Processor, processor,
ProcessorDefinition definition) {
     if ("transform".equals(definition.getShortName()) {
         // place breakpoint in IDE on log statement below
         log.info("Body before transformation " +
exchange.getIn().getBody())
     }
  }

I'll say +1 for including before/afterProcess() methods in CamelTestSupport. 

-----
Richard Kettelerij,
http://github.com/rkettelerij
-- 
View this message in context: http://camel.465427.n5.nabble.com/DISCUSS-Easier-Camel-route-debugging-from-Camel-Test-Kit-tp3215088p3216041.html
Sent from the Camel Development mailing list archive at Nabble.com.

Re: [DISCUSS] - Easier Camel route debugging from Camel Test Kit

Posted by Christian Müller <ch...@gmail.com>.
Yep, this make sense...

Christian

Re: [DISCUSS] - Easier Camel route debugging from Camel Test Kit

Posted by Claus Ibsen <cl...@gmail.com>.
On Sun, Oct 24, 2010 at 11:25 PM, Christian Müller
<ch...@gmail.com> wrote:
> I'm very impressed how easy it looks like and how quick you add really great
> feature to Camel - each time again...
>

Thanks we will get this in Camel 2.6 as 2.5 is being cut today. Don't
wanna risk anything on this release.

Also it gives us a bit time to thinker about the API when we got a
couple of months to use it before we do the 2.6 release.


> Thanks,
> Christian
>



-- 
Claus Ibsen
Apache Camel Committer

Author of Camel in Action: http://www.manning.com/ibsen/
Open Source Integration: http://fusesource.com
Blog: http://davsclaus.blogspot.com/
Twitter: http://twitter.com/davsclaus

Re: [DISCUSS] - Easier Camel route debugging from Camel Test Kit

Posted by Christian Müller <ch...@gmail.com>.
I'm very impressed how easy it looks like and how quick you add really great
feature to Camel - each time again...

Thanks,
Christian

Re: [DISCUSS] - Easier Camel route debugging from Camel Test Kit

Posted by Claus Ibsen <cl...@gmail.com>.
>>> A common issue with Camel is there are often many threads and inputs
>>> all processing concurrently and breakpoints can fire at any point in
>>> any route which can be confusing. I wonder if we could add some kind
>>> of 'flow' conditional method, so we could let the IDE stop at a common
>>> breakpoint but it would only fire subsequently for one complete flow
>>> through the route until we told the runtime to 'continue'. Kinda like
>>> a virtual 'step' operation.
>>>
>>> e.g. imagine we had a isFlowMessage() function we could use as a
>>> conditional breakpoint we set in the IDE. This method returns true for
>>> the first invocation; a header is added to the message; it then
>>> returns false for all other invocations until its the next step in the
>>> flow for the original message. Then it'd be much easier to 'step
>>> through' camel routes.
>>>

Yeah of course just let the IDE do the conditional breakpoints.
We should just make it easier for it having the short name and a few
other infos easily avail for it.

Good idea.


-- 
Claus Ibsen
Apache Camel Committer

Author of Camel in Action: http://www.manning.com/ibsen/
Open Source Integration: http://fusesource.com
Blog: http://davsclaus.blogspot.com/
Twitter: http://twitter.com/davsclaus

Re: [DISCUSS] - Easier Camel route debugging from Camel Test Kit

Posted by James Strachan <ja...@gmail.com>.
On 18 October 2010 14:56, Claus Ibsen <cl...@gmail.com> wrote:
> On Mon, Oct 18, 2010 at 1:11 PM, James Strachan
> <ja...@gmail.com> wrote:
>> Good idea!
>>
>> We should make it as easy as possible to set conditional breakpoints
>> in your debugger using the available context and your IDE. e.g.
>>
>> * the id of the Definition node in the route (stop at a specific point
>> in a route). e.g. condition: getDefinition().getId() == "AMC"
>> * the kind of node (e.g. on a ToDefinition in all routes. e.g.
>> condition: getDefinition().getShortName() == "to"
>> * the value of a header on a message
>>
>> A common issue with Camel is there are often many threads and inputs
>> all processing concurrently and breakpoints can fire at any point in
>> any route which can be confusing. I wonder if we could add some kind
>> of 'flow' conditional method, so we could let the IDE stop at a common
>> breakpoint but it would only fire subsequently for one complete flow
>> through the route until we told the runtime to 'continue'. Kinda like
>> a virtual 'step' operation.
>>
>> e.g. imagine we had a isFlowMessage() function we could use as a
>> conditional breakpoint we set in the IDE. This method returns true for
>> the first invocation; a header is added to the message; it then
>> returns false for all other invocations until its the next step in the
>> flow for the original message. Then it'd be much easier to 'step
>> through' camel routes.
>>
>
> We could probably do 2 things
>
> 1)
> Let CamelTestSupport offer the beforeProcess / afterProcess methods
> which end users can override to easily just debug the test they are
> doing.

I'm not sure if I explained myself terribly well in my previous ramble
- I was basically imagining us adding a few more methods available to
the beforeProcess() debug context, so when you add a breakpoint in
your IDE then, say, in IDEA, right click on the breakpoint ->
Properties -> Condition - you can then easily enter a mini-DSL in the
"Condition" text field where you can describe the way you want to
debug the route. So providing a few new methods to access the current
Definition node, its id, shortName, the current message and so forth
so its easy to filter out noise.

So rather than hacking your Java code to add a DSL, I was imagining
using this kind of thing most often inside the Breakpoint UI in your
IDE. Though its cool hacking a DSL in your test case/code too - I'm
just wondering how much we can just use the existing IDE features
(with a few new helper methods here or there).

-- 
James
-------
http://macstrac.blogspot.com/

Open Source Integration
http://fusesource.com/

Re: [DISCUSS] - Easier Camel route debugging from Camel Test Kit

Posted by Claus Ibsen <cl...@gmail.com>.
On Mon, Oct 18, 2010 at 1:11 PM, James Strachan
<ja...@gmail.com> wrote:
> Good idea!
>
> We should make it as easy as possible to set conditional breakpoints
> in your debugger using the available context and your IDE. e.g.
>
> * the id of the Definition node in the route (stop at a specific point
> in a route). e.g. condition: getDefinition().getId() == "AMC"
> * the kind of node (e.g. on a ToDefinition in all routes. e.g.
> condition: getDefinition().getShortName() == "to"
> * the value of a header on a message
>
> A common issue with Camel is there are often many threads and inputs
> all processing concurrently and breakpoints can fire at any point in
> any route which can be confusing. I wonder if we could add some kind
> of 'flow' conditional method, so we could let the IDE stop at a common
> breakpoint but it would only fire subsequently for one complete flow
> through the route until we told the runtime to 'continue'. Kinda like
> a virtual 'step' operation.
>
> e.g. imagine we had a isFlowMessage() function we could use as a
> conditional breakpoint we set in the IDE. This method returns true for
> the first invocation; a header is added to the message; it then
> returns false for all other invocations until its the next step in the
> flow for the original message. Then it'd be much easier to 'step
> through' camel routes.
>

We could probably do 2 things

1)
Let CamelTestSupport offer the beforeProcess / afterProcess methods
which end users can override to easily just debug the test they are
doing.


2)
Offer a fluent builder you would use inside the test method, something
similar on my blog.
The builder allows you to fine grained detail when the debugger should trigger.

Kinda like a bit what we have with the NotifierBuilder which offers
you to build a predicates using AND / OR and whatnot.
http://camel.apache.org/notifybuilder.html

But imagine a nice fluent API for debugging. The hard part is to come
up with good and catchy builder names.

debug().from("jms:*").when().sendTo("file:*").singleStep(new
BreakpointSupport()) {
// the poor mans closure here
};

We could also have some configuration to easily filter out processing
steps which you dont like / care about.
Such as .convertBodyTo, .marshal etc.

But for starters we could maybe shot for the filter and having debug
fluent builder.
Then later we can add nice builder methods to define fine grained when
to invoke it.
Having the filter allows you to let it filter out the noise.




>
>
> On 16 October 2010 14:26, Claus Ibsen <cl...@gmail.com> wrote:
>> Hi
>>
>> At first read this blog post
>> http://davsclaus.blogspot.com/2010/10/paris-and-easier-camel-route-debugging.html
>>
>> Then this example with full source code. Notice how we use the debug
>> method with the breakpoint
>> to have Camel invoke the beforeProcess at each step in the route. This
>> allows you easily to debug the route.
>> See the screenshot in the blog post.
>>
>> public class DebugTest extends CamelTestSupport {
>>
>>    public void testDebugger() throws Exception {
>>        // you can debug camel routes easily as shown below:
>>        debug(new BreakpointSupport() {
>>            public void beforeProcess(Exchange exchange, Processor
>> processor, ProcessorDefinition definition) {
>>                // this method is invoked before we are about to enter
>> the given processor
>>                // from your Java editor you can just add a breakpoint
>> in the code line below
>>                log.info("Before " + definition + " with body " +
>> exchange.getIn().getBody());
>>            }
>>        });
>>
>>        // set mock expectations
>>        getMockEndpoint("mock:a").expectedMessageCount(1);
>>        getMockEndpoint("mock:b").expectedMessageCount(1);
>>
>>        // send a message
>>        template.sendBody("direct:start", "World");
>>
>>        // assert mocks
>>        assertMockEndpointsSatisfied();
>>    }
>>
>>    @Override
>>    protected RouteBuilder createRouteBuilder() throws Exception {
>>        return new RouteBuilder() {
>>            @Override
>>            public void configure() throws Exception {
>>                // this is the route we want to debug
>>                from("direct:start")
>>                    .to("mock:a")
>>                    .transform(body().prepend("Hello "))
>>                    .to("mock:b");
>>            }
>>        };
>>    }
>> }
>>
>>
>>
>> To do this requires the anonymous inner class (poor mans closures) and
>> can be a bit verbose.
>> What if we provide the debugger out of the box in the sense we have it
>> implemented directly in the CamelTestSupport class.
>>
>> Then all you need to do is to override the beforeProcess class on the
>> CamelTestSupport which makes the code less verbose
>> This makes the code a bit smaller. And therefore all the end user need
>> to do is to override either/or both beforeProcess, afterProcess to
>> easily debug the route.
>>
>> We can also provide both approaches so you can do both if you like?
>>
>> Any thoughts?
>>
>>
>> public class DebugTest extends CamelTestSupport {
>>
>>    @Override
>>    protected void beforeProcess(Exchange exchange, Processor
>> processor, ProcessorDefinition definition) {
>>        // this method is invoked before we are about to enter the
>> given processor
>>        // from your Java editor you can just add a breakpoint in the
>> code line below
>>        log.info("Before " + definition + " with body " +
>> exchange.getIn().getBody());
>>    }
>>
>>    public void testDebugger() throws Exception {
>>        // set mock expectations
>>        getMockEndpoint("mock:a").expectedMessageCount(1);
>>        getMockEndpoint("mock:b").expectedMessageCount(1);
>>
>>        // send a message
>>        template.sendBody("direct:start", "World");
>>
>>        // assert mocks
>>        assertMockEndpointsSatisfied();
>>    }
>>
>>    @Override
>>    protected RouteBuilder createRouteBuilder() throws Exception {
>>        return new RouteBuilder() {
>>            @Override
>>            public void configure() throws Exception {
>>                // this is the route we want to debug
>>                from("direct:start")
>>                    .to("mock:a")
>>                    .transform(body().prepend("Hello "))
>>                    .to("mock:b");
>>            }
>>        };
>>    }
>> }
>>
>>
>>
>> --
>> Claus Ibsen
>> Apache Camel Committer
>>
>> Author of Camel in Action: http://www.manning.com/ibsen/
>> Open Source Integration: http://fusesource.com
>> Blog: http://davsclaus.blogspot.com/
>> Twitter: http://twitter.com/davsclaus
>>
>
>
>
> --
> James
> -------
> http://macstrac.blogspot.com/
>
> Open Source Integration
> http://fusesource.com/
>



-- 
Claus Ibsen
Apache Camel Committer

Author of Camel in Action: http://www.manning.com/ibsen/
Open Source Integration: http://fusesource.com
Blog: http://davsclaus.blogspot.com/
Twitter: http://twitter.com/davsclaus

Re: [DISCUSS] - Easier Camel route debugging from Camel Test Kit

Posted by James Strachan <ja...@gmail.com>.
Good idea!

We should make it as easy as possible to set conditional breakpoints
in your debugger using the available context and your IDE. e.g.

* the id of the Definition node in the route (stop at a specific point
in a route). e.g. condition: getDefinition().getId() == "AMC"
* the kind of node (e.g. on a ToDefinition in all routes. e.g.
condition: getDefinition().getShortName() == "to"
* the value of a header on a message

A common issue with Camel is there are often many threads and inputs
all processing concurrently and breakpoints can fire at any point in
any route which can be confusing. I wonder if we could add some kind
of 'flow' conditional method, so we could let the IDE stop at a common
breakpoint but it would only fire subsequently for one complete flow
through the route until we told the runtime to 'continue'. Kinda like
a virtual 'step' operation.

e.g. imagine we had a isFlowMessage() function we could use as a
conditional breakpoint we set in the IDE. This method returns true for
the first invocation; a header is added to the message; it then
returns false for all other invocations until its the next step in the
flow for the original message. Then it'd be much easier to 'step
through' camel routes.



On 16 October 2010 14:26, Claus Ibsen <cl...@gmail.com> wrote:
> Hi
>
> At first read this blog post
> http://davsclaus.blogspot.com/2010/10/paris-and-easier-camel-route-debugging.html
>
> Then this example with full source code. Notice how we use the debug
> method with the breakpoint
> to have Camel invoke the beforeProcess at each step in the route. This
> allows you easily to debug the route.
> See the screenshot in the blog post.
>
> public class DebugTest extends CamelTestSupport {
>
>    public void testDebugger() throws Exception {
>        // you can debug camel routes easily as shown below:
>        debug(new BreakpointSupport() {
>            public void beforeProcess(Exchange exchange, Processor
> processor, ProcessorDefinition definition) {
>                // this method is invoked before we are about to enter
> the given processor
>                // from your Java editor you can just add a breakpoint
> in the code line below
>                log.info("Before " + definition + " with body " +
> exchange.getIn().getBody());
>            }
>        });
>
>        // set mock expectations
>        getMockEndpoint("mock:a").expectedMessageCount(1);
>        getMockEndpoint("mock:b").expectedMessageCount(1);
>
>        // send a message
>        template.sendBody("direct:start", "World");
>
>        // assert mocks
>        assertMockEndpointsSatisfied();
>    }
>
>    @Override
>    protected RouteBuilder createRouteBuilder() throws Exception {
>        return new RouteBuilder() {
>            @Override
>            public void configure() throws Exception {
>                // this is the route we want to debug
>                from("direct:start")
>                    .to("mock:a")
>                    .transform(body().prepend("Hello "))
>                    .to("mock:b");
>            }
>        };
>    }
> }
>
>
>
> To do this requires the anonymous inner class (poor mans closures) and
> can be a bit verbose.
> What if we provide the debugger out of the box in the sense we have it
> implemented directly in the CamelTestSupport class.
>
> Then all you need to do is to override the beforeProcess class on the
> CamelTestSupport which makes the code less verbose
> This makes the code a bit smaller. And therefore all the end user need
> to do is to override either/or both beforeProcess, afterProcess to
> easily debug the route.
>
> We can also provide both approaches so you can do both if you like?
>
> Any thoughts?
>
>
> public class DebugTest extends CamelTestSupport {
>
>    @Override
>    protected void beforeProcess(Exchange exchange, Processor
> processor, ProcessorDefinition definition) {
>        // this method is invoked before we are about to enter the
> given processor
>        // from your Java editor you can just add a breakpoint in the
> code line below
>        log.info("Before " + definition + " with body " +
> exchange.getIn().getBody());
>    }
>
>    public void testDebugger() throws Exception {
>        // set mock expectations
>        getMockEndpoint("mock:a").expectedMessageCount(1);
>        getMockEndpoint("mock:b").expectedMessageCount(1);
>
>        // send a message
>        template.sendBody("direct:start", "World");
>
>        // assert mocks
>        assertMockEndpointsSatisfied();
>    }
>
>    @Override
>    protected RouteBuilder createRouteBuilder() throws Exception {
>        return new RouteBuilder() {
>            @Override
>            public void configure() throws Exception {
>                // this is the route we want to debug
>                from("direct:start")
>                    .to("mock:a")
>                    .transform(body().prepend("Hello "))
>                    .to("mock:b");
>            }
>        };
>    }
> }
>
>
>
> --
> Claus Ibsen
> Apache Camel Committer
>
> Author of Camel in Action: http://www.manning.com/ibsen/
> Open Source Integration: http://fusesource.com
> Blog: http://davsclaus.blogspot.com/
> Twitter: http://twitter.com/davsclaus
>



-- 
James
-------
http://macstrac.blogspot.com/

Open Source Integration
http://fusesource.com/