[
https://issues.apache.org/jira/browse/CAMEL-12910?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16681037#comment-16681037
]
Cristian Donoiu edited comment on CAMEL-12910 at 11/9/18 8:26 AM:
------------------------------------------------------------------
Thank you [~ancosen]. I will start work on a PR (note: will not be fast since I
am new to Camel). I am assigning this ticket to myself.
Thanks [~onders]. Where is the dev-list accessible?
Related to the 12319 which you mentioned, *yes* it is similar but the
*calling* *is different*. Here is why:
||Options||Description||
|1|Providing the parameters in the route has benefits in that it gives more
control to the route which is good. E.g. {code:java}
from(X)
.bean(UserService.class, UserService::authenticateUser, body(),
exchangeProperty("locale"))
.bean(UserService.class, UserService::checkUserPermissions, body(),
exchangeProperty("locale"))
.bean(UserService.class, UserService::doWork, body(), header("..."))
.to(Y){code}
|
|2|I would prefer the route to just reference methods on an already
*instantiated*/wired bean instance(not class like above) and *no parameters*
specified: {code:java}
@Autowire UserService userService;
...
.bean(userService::authenticateUser)
.bean(userService::checkUserPermissions)
.bean(userService::doWork){code}
Then on the bean instance I use the annotations
([http://camel.apache.org/parameter-binding-annotations.html]) to let Camel do
the mapping. Also I learned @Body is *not* needed if automatic matching based
on type can be done by Camel and there are other smart rules also. {code:java}
public void validate(@ExchangeProperty("P1") UserRequest request, String
accountId) {...} // accountId is message body.{code}
Benefits:
- Route DSL code is less.
- The method being referenced on the object and not on the class allows for
runtime selection of the method based on the actual type of an interface type.
The details of what the method takes in or not remain at the choice of the
target method by using the needed annotations within the method definition/or
in the target bean class or one of his implemented interfaces. Also in case the
target method changes signature like adding a new parameter that references an
existing exchange property then adding the new parameter would not require any
change in the route dsl. Still someone would prefer to see all the dependencies
in the route DSL so this is debatable.
- In case of auto wiring an interface type as we often do, e.g.{code:java}
@Autowire UserService userService;{code}
the target bean you may get may be different depending of the one that is
injected. You may get a SingleTenantUserServiceImpl or a
MultiTenantUserServiceImpl and SingleTenantUserServiceImpl#authenticateUser
would need body and header H1 while MultiTenantUserServiceImpl#authenticateUser
would need body, header H2. This would be easily possible with using the
corresponding annotations at the method level and will require some choice
based on type if we do it in the route DSL. Debatable as the one above.|
*Conclusion.*
Supporting *both* options could be achieved by using the same ".bean" call
since we could differentiate based on the number of parameters to the ".bean"
call.
But I would implement first only method reference(option 2) in route and have
in a *later* ticket (if needed) the capability of specifying parameters in
route(option 1).
was (Author: doncristiano):
Thank you [~ancosen]. I will start work on a PR (note: will not be fast since I
am new to Camel). I am assigning this ticket to myself.
Thanks [~onders]. Where is the dev-list accessible?
Related to the 12319 which you mentioned, *yes* it is similar but the
*calling* *is different*. Here is why:
||Options||Description||
|1|Providing the parameters in the route has benefits in that it gives more
control to the route which is good. E.g. {code:java}
from(X)
.bean(UserService.class, UserService::authenticateUser, body(),
exchangeProperty("locale"))
.bean(UserService.class, UserService::checkUserPermissions, body(),
exchangeProperty("locale"))
.bean(UserService.class, UserService::doWork, body(), header("..."))
.to(Y){code}
|
|2|I would prefer the route to just reference methods on an already
*instantiated*/wired bean instance(not class like above) and *no parameters*
specified: {code:java}
@Autowire UserService userService;
...
.bean(userService::authenticateUser)
.bean(userService::checkUserPermissions)
.bean(userService::doWork){code}
Then on the bean instance I use the annotations
([http://camel.apache.org/parameter-binding-annotations.html]) to let Camel do
the mapping. Also I learned @Body is *not* needed if automatic matching based
on type can be done by Camel and there are other smart rules also. {code:java}
public void validate(@ExchangeProperty("P1") UserRequest request, String
accountId) {...} // accountId is message body.{code}
# Route DSL code is less.
# The method being referenced on the object and not on the class allows for
runtime selection of the method based on the actual type of an interface type.
The details of what the method takes in or not remain at the choice of the
target method by using the needed annotations within the method definition/or
in the target bean class or one of his implemented interfaces. Also in case the
target method changes signature like adding a new parameter that references an
existing exchange property then adding the new parameter would not require any
change in the route dsl. Still someone would prefer to see all the dependencies
in the route DSL so this is debatable.
# In case of auto wiring an interface type as we often do, e.g.{code:java}
@Autowire UserService userService;{code}
the target bean you may get may be different depending of the one that is
injected. You may get a SingleTenantUserServiceImpl or a
MultiTenantUserServiceImpl and SingleTenantUserServiceImpl#authenticateUser
would need body and header H1 while MultiTenantUserServiceImpl#authenticateUser
would need body, header H2. This would be easily possible with using the
corresponding annotations at the method level and will require some choice
based on type if we do it in the route DSL. Debatable as the one above.|
*Conclusion.*
Supporting *both* options could be achieved by using the same ".bean" call
since we could differentiate based on the number of parameters to the ".bean"
call.
But I would implement first only method reference(option 2) in route and have
in a *later* ticket (if needed) the capability of specifying parameters in
route(option 1).
> Add support for method references bean::methodName
> --------------------------------------------------
>
> Key: CAMEL-12910
> URL: https://issues.apache.org/jira/browse/CAMEL-12910
> Project: Camel
> Issue Type: Improvement
> Components: camel-core, camel-spring-integration
> Reporter: Cristian Donoiu
> Priority: Major
> Labels: features
> Attachments: Bean.java
>
>
> Hi
> This is not related only to spring integration.
> I like to be able to use a spring service annotated class or bean directly
> from route but without using the method name as string, i.e. .bean(instance,
> "<method name") and instead use a method reference: .bean(instance::method)
> But why?:
> *1.* not being able to navigate quickly(open) that method from the IDE. Need
> to do some intermediary steps to reach that method.
> *2.* using of reflection internally by Camel to call that method.
> *3.* not being able to rename the method without breaking the route.
> *4.* not being able to see quickly (Alt+F7) who calls a methods in the IDE.
> *5.* using strings to reference a method when we have method references seems
> *not right.*
> As a workaround I had to add a helper class to simulate passing of method
> references and then internally to translate to method.
> In case it helps explaining I am attaching the helper Bean.java class (you
> can use it for free or to do better).
> You can use the class in any route like this:
> from (X)
> .bean(*call*(cancelSubscriptionService::buildSalesforceCase))
> .to(Y)
> .routeId(Z);
> As you see I am forced to use the intermediary helper 'call' in order to
> translate to an Expression.
> I would like to not have to use my helper and have the support built directly
> into Camel if possible. Let me know if there is a better solution to my
> problem.
> Thanks
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)