Is there a way to set a property at the level of a Route, rather than an Exchange.
As a simplified example, if I wanted to have something like invocation-count or last-invoked-time and check/update it each time the route was triggered, how would I implement it?
You could implement that a number of ways.. using a simple Java class as a processor right after the "from", or as an interceptor (use interceptFrom): http://camel.apache.org/intercept.html.
Curiously though.. you should consider using the out-of-the-box Camel metrics. You should be covered by the defaults.
Related
I'm working on a project that requires that most UI state is reproducible via URL. In a traditional (server-side) app, I could use both URL parameters like:
/resources/:id
and unordered optional query string parameters, like:
/resources/:id?page=5&sort=date
Is there an idiomatic way to achieve this with Backbone/Marionette routing? I don't want to have to configure routes for every possible combination of parameters.
The fact that I don't see this addressed much makes me think I may be barking up the wrong tree, approach-wise, but I do think being able to represent as much UI state as possible in the URL is pretty important to a lot of projects.
It looks like the best option is the now-orphaned backbone-query-parameters project.
It supports routes exactly in the form I'm looking for:
#resources/:id?flag=true
URL parameters are not really enforced by Backbone/Marionette. One possible reason is that URL parameters are not SEO friendly.
Instead, you can configure optional URL fragments which will work pretty much like URL parameters, this way:
/resources/:id(/page/:page)(/sort/:sort)
If you do this way, the only gotcha here is that this sequence of "parameters" need to be ordered.
HOWEVER if you need it to be unordered, you can simply use Regular Expressions with router.route() method inside your initialize, as explained in Router#route
Is there a way to tell Camel to use the Saxon library by default, so I would not need to specify it in every XLST transformation? E.g.:
.to("xslt:my-file.xsl?transformerFactoryClass=net.sf.saxon.TransformerFactoryImpl")
Specifying it in every endpoint makes code less readable.
I've seen suggestions (though in some other contexts) on setting environment property:
javax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl
Would this somehow be possible to be set within single camel context?
P.S. I am using Camel 2.10, so the saxon parameter suggestion is unfortunately not an option yet...
According to the documentation you can use:
.to("xslt:my-file.xsl?saxon=true")
which is much more readable
The system property setting is working for the whole JVM, it is not good way for the container setting.
You can extend the XsltComponent to set the transformerFactoryClass for you as camel-2.11.x does or you can just add an constant which hold the option of transformerFactoryClass.
We have lots of routes which do common stuff. I would like to move that stuff into a Base Route and add/overwrite functionality (e.g. adding system dependent headers, doing system dependent enrichments, etc) in the extension.
What is a good approach for that? Would it make sense to use the AdviceWithRouteBuilder since I saw only examples where it is used in unit tests?
Are there other ideas?
Thanks
Yusuf
You can do "sub routes". I have found them very useful for doing common tasks.
Create something like this inside a "CommonRoutes" route builder:
// Example
from("direct:extractCommonMetadata")
.setHeader("orderid").xpath("/data/orderid")
.setHeader("customer").xpath("/data/customer")
from("direct:enrichWithCommonStuff")
.enrich("foo:baz")
Then you can simply do this in your various routes:
from("foo:bar")
.inOut("direct:extractCommonMetadata")
.inOut("direct:enrichWithCommonStuff
.foo("bar")
from("bar:foo")
.inOut("direct:extractCommonMetadata")
.to("the little house on the hill");
The overhead of using the direct protocol is very low and a good way to break out common functionality.
If you use Java then its just java, and you can create a base RouteBuilder class, and do some shared stuff in the configure method, and call super.configure() from extended classes.
I want to perform custom logic in an IdempotentConsumer. I've extended the class and implemented the logic. How can I add this to my route?
Do I have to make my own Definition class? Do I add it as a Processor? How do I get the parameters passed to the constructor?
Well, custom consumer/producer could be little overkill. I think for some kind of custom logic is enough to do it trough processor or custom bean.
1.Bean
Look at bean binding you can use simple language to pass arguments to your method. It will looks like this:
.bean(OrderService.class, "doSomething(${body}, true)")
.to("bean:orderService?method=doSomething(null, true)")
2.Processor
You have to realize your classes should be stateless because of concurrent matter of camel framework. Your constructor should be empty and your variables final otherwise whole bunch of magic could happen. Everything you want to pass to your logic component/processor should be passed via Exchange object. You can store your variables in getin() or getOut() messages as headers or body or Exchange properties and pass it to next endpoint. The exchange will change dynamically as it flows trough you camel routes. It should be your one and only one mutable object.
The DirectComponent documentation gives the following example:
from("activemq:queue:order.in")
.to("bean:orderServer?method=validate")
.to("direct:processOrder");
from("direct:processOrder")
.to("bean:orderService?method=process")
.to("activemq:queue:order.out");
Is there any difference between that and the following?
from("activemq:queue:order.in")
.to("bean:orderServer?method=validate")
.to("bean:orderService?method=process")
.to("activemq:queue:order.out");
I've tried to find documentation on what the behaviour of the to() method is on the Java DSL, but beyond the RouteDefinition javadoc (which gives the very curt "Sends the exchange to the given endpoint") I've come up blank :(
In the very case above, you will not notice much difference. The "direct" component is much like a method call.
Once you start build a bit more complex routes, you will want to segment them in several different parts for multiple reasons.
You can, for instance, create "sub routes" that could be reused among multiple routes in your Camel context. Much like you segment out methods in regular programming to allow reusability and make code more clear. The same goes for sub routes using, for instance the direct component.
The same approach can be extended. Say you want multiple protocols to be used as endpoints to your route. You can use the direct endpoint to create the main route, something like this:
// Three endpoints to one "main" route.
from("activemq:queue:order.in")
.to("direct:processOrder");
from("file:some/file/path")
.to("direct:processOrder");
from("jetty:http://0.0.0.0/order/in")
.to("direct:processOrder");
from("direct:processOrder")
.to("bean:orderService?method=process")
.to("activemq:queue:order.out");
Another thing is that one route is created for each "from()" clause in DSL. A route is an artifact in Camel, and you could do certain administrative tasks towards it with the Camel API, such as start, stop, add, remove routes dynamically. The "to" clause is just an endpoint call.
Once starting to do some real cases with somewhat complexity in Camel, you will note that you cannot get too many "direct" routes.
Direct Component is used to name the logical segment of the route. This is similar process to naming procedures in structural programming.
In your example there is no difference in message flow. In the terms of structural programming, we could say that you make a kind of inline expansion to your route.
Another difference is Direct component doesn't has any thread pool, the direct consumer process method is invoked by the calling thread of direct producer.
Mainly its used for break the complex route configuration like in java we used to have method for reusability. And also by configuring threads at direct route we can reduce the work for calling thread .
from(A).to(B).to(OUT)
is chaining
A --- B --- OUT
But
from(A ).to( X)
from(B ).to( X)
from( X).to( OUT )
where X is a direct:?
is basically like a join
A
\____ OUT
/
B
obviously these are different behaviours, and with the second you could implement anylogic you wanted, not just a serial chain