You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by Dale King <da...@gmail.com> on 2013/09/03 17:51:44 UTC

Simple way to do some elementary bean operations

Through simple and OGNL we have nice easy ways to read the properties of
beans in the body, headers, or properties. But what I cannot find is an
easy way to invoke a setter on a bean property, but perhaps I am missing
something.

I can certainly create a bean or processor to invoke the setter, but it
seems to me that if I am forced to do it for something as simple as setting
a property then something is missing in Camel. I try to do as much as
possible in Camel.

I can certainly use another language like javascript, groovy, or el to do
it, but once again bringing in a whole new language seems like overkill
just to set a property.

So 3 operations that i don't see an easy way to do in Camel without
resorting to these heavyweight solutions are:

 - Set a bean property
 - More generally, you should be able to invoke any method on a bean
including with parameters
 - Create a new instance of a bean (possibly with parameters)

Correct me if I am wrong and there is a simple way to do these.

-- 
Dale King

Re: Simple way to do some elementary bean operations

Posted by Claus Ibsen <cl...@gmail.com>.
Hi

The DSL in camel is intended to be as identical between Java and XML
as possible. In fact the XML is generated based on Java classes.

This allows people to easily transition between java and xml dsl. And
also read examples in Java and understand how to do that in XML - and
vice versa etc.

So we are a bit careful also to not bloat and expand the DSL etc. As
it should not grow too big etc. But stay in sight of its DNA of being
for routing and mediation.

Today you can add builder methods to your own RouteBuilder classes so
you can add a method to set a property on the message body from an
expression etc.

The simple language allows to call methods on the message body so you can do

simple("${body.setFoo(${header.bar})}") if you want. And you can do
that in both Java and XML etc. But there is of course no code
assistence from the editor as its just a String you type.

Where as a in java we could have more builder methods on body() so you can do

body().setProperty("foo", header("bar"))

Though what if you want to call a method on the body and pass in more arguments

body().callMethod("foo", header("bar"), true, xpath("/foo/bar"), 123)


Though all that becomes easier in Java 8 where we have lambda
expressions, and would be able to easier inline java code in the
routes without all the verboseness as today.





On Tue, Sep 3, 2013 at 8:09 PM, Dale King <da...@gmail.com> wrote:
> Yeah, LIKE I SAID, I know I can break out to a bean or a processor, but
> that is such a heavyweight solution to do something so simple that really
> should be built into Camel. You have to create a class, come up with some
> meaningful name of the class, repeat that name a couple of times if using a
> Spring DSL, etc.
>
> Let's say we do it with anonymous classes in a Java DSL:
>
>   process(new Processor()
>   {
>         @Override
>          public void process(Exchange exchange) throws Exception
>          {
>                exchange.getIn().getBody(MyBodyType.class)
>
> .setSomeProperty(exchange.getIn().getHeader("foo", SomeType.class);
>          }
>   })
>
> Or perhaps better as a bean:
>
>   bean( new Object()
>   {
>       public void set( @Body MyBodyType body, @Header("foo") value)
>       {
>           body.setSomeProperty(value);
>       }
>   }
>
> I personally would rather replace any of those with something more like
> this in DSL:
>
>   body().set("someProperty", header("foo"))
>
> This is much more obvious what is happening when looking at the route.
>
>
>
> On Tue, Sep 3, 2013 at 1:51 PM, Claus Ibsen <cl...@gmail.com> wrote:
>
>> On Tue, Sep 3, 2013 at 5:51 PM, Dale King <da...@gmail.com> wrote:
>> > Through simple and OGNL we have nice easy ways to read the properties of
>> > beans in the body, headers, or properties. But what I cannot find is an
>> > easy way to invoke a setter on a bean property, but perhaps I am missing
>> > something.
>> >
>> > I can certainly create a bean or processor to invoke the setter, but it
>> > seems to me that if I am forced to do it for something as simple as
>> setting
>> > a property then something is missing in Camel. I try to do as much as
>> > possible in Camel.
>> >
>> > I can certainly use another language like javascript, groovy, or el to do
>> > it, but once again bringing in a whole new language seems like overkill
>> > just to set a property.
>> >
>> > So 3 operations that i don't see an easy way to do in Camel without
>> > resorting to these heavyweight solutions are:
>> >
>> >  - Set a bean property
>> >  - More generally, you should be able to invoke any method on a bean
>> > including with parameters
>> >  - Create a new instance of a bean (possibly with parameters)
>> >
>> > Correct me if I am wrong and there is a simple way to do these.
>> >
>>
>> Well there is something called Java programming language, where you
>> can do all that ;)
>>
>> > --
>> > Dale King
>>
>>
>>
>> --
>> Claus Ibsen
>> -----------------
>> Red Hat, Inc.
>> Email: cibsen@redhat.com
>> Twitter: davsclaus
>> Blog: http://davsclaus.com
>> Author of Camel in Action: http://www.manning.com/ibsen
>>
>
>
>
> --
> Dale King



-- 
Claus Ibsen
-----------------
Red Hat, Inc.
Email: cibsen@redhat.com
Twitter: davsclaus
Blog: http://davsclaus.com
Author of Camel in Action: http://www.manning.com/ibsen

Re: Simple way to do some elementary bean operations

Posted by Dale King <da...@gmail.com>.
On Fri, Sep 20, 2013 at 1:54 AM, Claus Ibsen <cl...@gmail.com> wrote:

> Hi
>
> You can use the language component, and set transform=false
> http://camel.apache.org/language
>

That seems to do the trick, but having to add ?transform=false is a pain. I
personally would argue that the default for transform should have been
false since there are easier ways to do that in the DSL using the transform
DSL element, but at this point don't think I would win that argument.


> Though the idea of having a <script> in the DSL seems good. Though we
> are often a bit careful to add to the DSL to not make it too big.
>

But as Einstein supposedly said, things should be as simple as possible,
but no simpler.

I am certainly not the only person asking for such at thing. E.g
http://stackoverflow.com/questions/17708962/set-property-on-body-using-bean

I think there should be an easy way to run arbitrary script from the DSL
along with setting properties of beans and invoking arbitrary methods with
arguments.
-- 
Dale King

Re: Simple way to do some elementary bean operations

Posted by Claus Ibsen <cl...@gmail.com>.
Hi

You can use the language component, and set transform=false
http://camel.apache.org/language

Though the idea of having a <script> in the DSL seems good. Though we
are often a bit careful to add to the DSL to not make it too big.


On Thu, Sep 19, 2013 at 8:23 PM, Dale King <da...@gmail.com> wrote:
> Thinking about this some more the real issue is not so much direct support
> for setting properties or invoking arbitrary methods because we have things
> like OGNL which can do that work for us. For example, the OGNL expression:
>
>    request.body.someProperty = request.headers.foo
>
> would do the trick for setting a property without resorting to Java.
>
> The real problem is that there is no way to just invoke a script like this
> without requiring you to do something with the result (store it in the
> body, a property, a header, use the value as a filter, etc.) We need a way
> to just say invoke this expression which could be in OGNL, Groovy,
> Javascript, etc. without being forced to do something with the result.
>
> Looking at the code there is the EvaluateExpressionProcessor which would be
> perfect for this. It evaluates an expression and stores the result in a
> property "CamelEvaluateExpressionResult". All we need is DSL to create an
> instance of this.
>
> So in Java DSL it would be something like:
>
>     .eval().ognl("request.body.someProperty = request.headers.foo")
>
> In Spring DSL it would be something like:
>
>     <eval><ognl>request.body.someProperty =
> request.headers.foo</ognl></eval>
>
> The workaround for now is to do the equivalent:
>
>     .setProperty("dummy").ognl("request.body.someProperty =
> request.headers.foo")
>
>
> On Tue, Sep 3, 2013 at 2:09 PM, Dale King <da...@gmail.com> wrote:
>
>> Yeah, LIKE I SAID, I know I can break out to a bean or a processor, but
>> that is such a heavyweight solution to do something so simple that really
>> should be built into Camel. You have to create a class, come up with some
>> meaningful name of the class, repeat that name a couple of times if using a
>> Spring DSL, etc.
>>
>> Let's say we do it with anonymous classes in a Java DSL:
>>
>>   process(new Processor()
>>   {
>>         @Override
>>          public void process(Exchange exchange) throws Exception
>>          {
>>                exchange.getIn().getBody(MyBodyType.class)
>>
>> .setSomeProperty(exchange.getIn().getHeader("foo", SomeType.class);
>>          }
>>   })
>>
>> Or perhaps better as a bean:
>>
>>   bean( new Object()
>>   {
>>       public void set( @Body MyBodyType body, @Header("foo") value)
>>       {
>>           body.setSomeProperty(value);
>>       }
>>   }
>>
>> I personally would rather replace any of those with something more like
>> this in DSL:
>>
>>   body().set("someProperty", header("foo"))
>>
>> This is much more obvious what is happening when looking at the route.
>>
>>
>>
>> On Tue, Sep 3, 2013 at 1:51 PM, Claus Ibsen <cl...@gmail.com> wrote:
>>
>>> On Tue, Sep 3, 2013 at 5:51 PM, Dale King <da...@gmail.com> wrote:
>>> > Through simple and OGNL we have nice easy ways to read the properties of
>>> > beans in the body, headers, or properties. But what I cannot find is an
>>> > easy way to invoke a setter on a bean property, but perhaps I am missing
>>> > something.
>>> >
>>> > I can certainly create a bean or processor to invoke the setter, but it
>>> > seems to me that if I am forced to do it for something as simple as
>>> setting
>>> > a property then something is missing in Camel. I try to do as much as
>>> > possible in Camel.
>>> >
>>> > I can certainly use another language like javascript, groovy, or el to
>>> do
>>> > it, but once again bringing in a whole new language seems like overkill
>>> > just to set a property.
>>> >
>>> > So 3 operations that i don't see an easy way to do in Camel without
>>> > resorting to these heavyweight solutions are:
>>> >
>>> >  - Set a bean property
>>> >  - More generally, you should be able to invoke any method on a bean
>>> > including with parameters
>>> >  - Create a new instance of a bean (possibly with parameters)
>>> >
>>> > Correct me if I am wrong and there is a simple way to do these.
>>> >
>>>
>>> Well there is something called Java programming language, where you
>>> can do all that ;)
>>>
>>> > --
>>> > Dale King
>>>
>>>
>>>
>>> --
>>> Claus Ibsen
>>> -----------------
>>> Red Hat, Inc.
>>> Email: cibsen@redhat.com
>>> Twitter: davsclaus
>>> Blog: http://davsclaus.com
>>> Author of Camel in Action: http://www.manning.com/ibsen
>>>
>>
>>
>>
>> --
>> Dale King
>>
>
>
>
> --
> Dale King



-- 
Claus Ibsen
-----------------
Red Hat, Inc.
Email: cibsen@redhat.com
Twitter: davsclaus
Blog: http://davsclaus.com
Author of Camel in Action: http://www.manning.com/ibsen

Re: Simple way to do some elementary bean operations

Posted by Dale King <da...@gmail.com>.
Thinking about this some more the real issue is not so much direct support
for setting properties or invoking arbitrary methods because we have things
like OGNL which can do that work for us. For example, the OGNL expression:

   request.body.someProperty = request.headers.foo

would do the trick for setting a property without resorting to Java.

The real problem is that there is no way to just invoke a script like this
without requiring you to do something with the result (store it in the
body, a property, a header, use the value as a filter, etc.) We need a way
to just say invoke this expression which could be in OGNL, Groovy,
Javascript, etc. without being forced to do something with the result.

Looking at the code there is the EvaluateExpressionProcessor which would be
perfect for this. It evaluates an expression and stores the result in a
property "CamelEvaluateExpressionResult". All we need is DSL to create an
instance of this.

So in Java DSL it would be something like:

    .eval().ognl("request.body.someProperty = request.headers.foo")

In Spring DSL it would be something like:

    <eval><ognl>request.body.someProperty =
request.headers.foo</ognl></eval>

The workaround for now is to do the equivalent:

    .setProperty("dummy").ognl("request.body.someProperty =
request.headers.foo")


On Tue, Sep 3, 2013 at 2:09 PM, Dale King <da...@gmail.com> wrote:

> Yeah, LIKE I SAID, I know I can break out to a bean or a processor, but
> that is such a heavyweight solution to do something so simple that really
> should be built into Camel. You have to create a class, come up with some
> meaningful name of the class, repeat that name a couple of times if using a
> Spring DSL, etc.
>
> Let's say we do it with anonymous classes in a Java DSL:
>
>   process(new Processor()
>   {
>         @Override
>          public void process(Exchange exchange) throws Exception
>          {
>                exchange.getIn().getBody(MyBodyType.class)
>
> .setSomeProperty(exchange.getIn().getHeader("foo", SomeType.class);
>          }
>   })
>
> Or perhaps better as a bean:
>
>   bean( new Object()
>   {
>       public void set( @Body MyBodyType body, @Header("foo") value)
>       {
>           body.setSomeProperty(value);
>       }
>   }
>
> I personally would rather replace any of those with something more like
> this in DSL:
>
>   body().set("someProperty", header("foo"))
>
> This is much more obvious what is happening when looking at the route.
>
>
>
> On Tue, Sep 3, 2013 at 1:51 PM, Claus Ibsen <cl...@gmail.com> wrote:
>
>> On Tue, Sep 3, 2013 at 5:51 PM, Dale King <da...@gmail.com> wrote:
>> > Through simple and OGNL we have nice easy ways to read the properties of
>> > beans in the body, headers, or properties. But what I cannot find is an
>> > easy way to invoke a setter on a bean property, but perhaps I am missing
>> > something.
>> >
>> > I can certainly create a bean or processor to invoke the setter, but it
>> > seems to me that if I am forced to do it for something as simple as
>> setting
>> > a property then something is missing in Camel. I try to do as much as
>> > possible in Camel.
>> >
>> > I can certainly use another language like javascript, groovy, or el to
>> do
>> > it, but once again bringing in a whole new language seems like overkill
>> > just to set a property.
>> >
>> > So 3 operations that i don't see an easy way to do in Camel without
>> > resorting to these heavyweight solutions are:
>> >
>> >  - Set a bean property
>> >  - More generally, you should be able to invoke any method on a bean
>> > including with parameters
>> >  - Create a new instance of a bean (possibly with parameters)
>> >
>> > Correct me if I am wrong and there is a simple way to do these.
>> >
>>
>> Well there is something called Java programming language, where you
>> can do all that ;)
>>
>> > --
>> > Dale King
>>
>>
>>
>> --
>> Claus Ibsen
>> -----------------
>> Red Hat, Inc.
>> Email: cibsen@redhat.com
>> Twitter: davsclaus
>> Blog: http://davsclaus.com
>> Author of Camel in Action: http://www.manning.com/ibsen
>>
>
>
>
> --
> Dale King
>



-- 
Dale King

Re: Simple way to do some elementary bean operations

Posted by Dale King <da...@gmail.com>.
Yeah, LIKE I SAID, I know I can break out to a bean or a processor, but
that is such a heavyweight solution to do something so simple that really
should be built into Camel. You have to create a class, come up with some
meaningful name of the class, repeat that name a couple of times if using a
Spring DSL, etc.

Let's say we do it with anonymous classes in a Java DSL:

  process(new Processor()
  {
        @Override
         public void process(Exchange exchange) throws Exception
         {
               exchange.getIn().getBody(MyBodyType.class)

.setSomeProperty(exchange.getIn().getHeader("foo", SomeType.class);
         }
  })

Or perhaps better as a bean:

  bean( new Object()
  {
      public void set( @Body MyBodyType body, @Header("foo") value)
      {
          body.setSomeProperty(value);
      }
  }

I personally would rather replace any of those with something more like
this in DSL:

  body().set("someProperty", header("foo"))

This is much more obvious what is happening when looking at the route.



On Tue, Sep 3, 2013 at 1:51 PM, Claus Ibsen <cl...@gmail.com> wrote:

> On Tue, Sep 3, 2013 at 5:51 PM, Dale King <da...@gmail.com> wrote:
> > Through simple and OGNL we have nice easy ways to read the properties of
> > beans in the body, headers, or properties. But what I cannot find is an
> > easy way to invoke a setter on a bean property, but perhaps I am missing
> > something.
> >
> > I can certainly create a bean or processor to invoke the setter, but it
> > seems to me that if I am forced to do it for something as simple as
> setting
> > a property then something is missing in Camel. I try to do as much as
> > possible in Camel.
> >
> > I can certainly use another language like javascript, groovy, or el to do
> > it, but once again bringing in a whole new language seems like overkill
> > just to set a property.
> >
> > So 3 operations that i don't see an easy way to do in Camel without
> > resorting to these heavyweight solutions are:
> >
> >  - Set a bean property
> >  - More generally, you should be able to invoke any method on a bean
> > including with parameters
> >  - Create a new instance of a bean (possibly with parameters)
> >
> > Correct me if I am wrong and there is a simple way to do these.
> >
>
> Well there is something called Java programming language, where you
> can do all that ;)
>
> > --
> > Dale King
>
>
>
> --
> Claus Ibsen
> -----------------
> Red Hat, Inc.
> Email: cibsen@redhat.com
> Twitter: davsclaus
> Blog: http://davsclaus.com
> Author of Camel in Action: http://www.manning.com/ibsen
>



-- 
Dale King

Re: Simple way to do some elementary bean operations

Posted by Claus Ibsen <cl...@gmail.com>.
On Tue, Sep 3, 2013 at 5:51 PM, Dale King <da...@gmail.com> wrote:
> Through simple and OGNL we have nice easy ways to read the properties of
> beans in the body, headers, or properties. But what I cannot find is an
> easy way to invoke a setter on a bean property, but perhaps I am missing
> something.
>
> I can certainly create a bean or processor to invoke the setter, but it
> seems to me that if I am forced to do it for something as simple as setting
> a property then something is missing in Camel. I try to do as much as
> possible in Camel.
>
> I can certainly use another language like javascript, groovy, or el to do
> it, but once again bringing in a whole new language seems like overkill
> just to set a property.
>
> So 3 operations that i don't see an easy way to do in Camel without
> resorting to these heavyweight solutions are:
>
>  - Set a bean property
>  - More generally, you should be able to invoke any method on a bean
> including with parameters
>  - Create a new instance of a bean (possibly with parameters)
>
> Correct me if I am wrong and there is a simple way to do these.
>

Well there is something called Java programming language, where you
can do all that ;)

> --
> Dale King



-- 
Claus Ibsen
-----------------
Red Hat, Inc.
Email: cibsen@redhat.com
Twitter: davsclaus
Blog: http://davsclaus.com
Author of Camel in Action: http://www.manning.com/ibsen