Apache Camel : "direct:start" endpoint - what does it mean? - apache

I'm new to Apache Camel. Can someone explain what "direct:start" means in Camel.
Please see
https://camel.apache.org/components/latest/http-component.html
from("direct:start")
.to("http://myhost/mypath");
Thanks.

The "direct:start" above is simply saying that the route starts with a Direct Component named "start".
The direct endpoint provides synchronous invocation of a route. If you want to send an Exchange to the direct:start endpoint you would create a ProducerTemplate and use the various send methods.
ProducerTemplate template = context.createProducerTemplate();
template.sendBody("direct:start", "This is a test message");
There is nothing special about the name start. It is simply the name you are going to use when referring to the endpoint and could have just as easily been direct:foo.

Assume like the direct route as a method with name start , so we need to call the start method /direct route to perform certain operation. The below example will help .
The first route will be triggered when an input file is available in XXXX location and when it reaches line , the actual flow will go to second route. Basically the direct route with from endpoint will be triggered by some producer endpoint.
<route id="fileRoute">
<from uri="file:XXXX">
..
<to uri="direct:start">
</route>
<route id="directStartRoute">
<from uri="direct:start">
<to uri="http://myhost/mypath">
</route>

Apache Camel direct is basically for sending Exchange from one route to another in SAME Camel context. So let’s say you are getting message from AMQ and you want to populate headers for every message you get and then send it to mail recipient list. So here you need to create new router which has following description
from(“direct:populateHeaders”)
.setHeader(“myHeader”, “myHeaderValue”)
.end()
And from any route you can send your Exchange object to this route by writing
...
.to(“direct:populateHeaders”)
...
Its important to keep in mind that this will not work out of your Camel Context.

direct:start provides synchronous ways to communicate between 2 endpoints and this is only been used if you want to communicate using camel messages and not generic file or xml messages.

Consider it like this :
There are two things whenever you are sending a message to camel route.
1. The URI scheme, which defines how your message is going to be delivered. And to which component type it is going to be delivered.
2. URI path, which defines the instance of that component.
Now, to your direct:start location.
'direct' tells that this message should send synchronously to the Direct Component.
'start' tells which instance of the Direct Component this message should be delivered.
Importance of different URI path:
Now consider if you are having to different routes. And wants to produce message from two different threads synchronously. Using 'direct:start' as start point for the routes will not work. Unless you are having some conditional processing component, forget this if you are beginner.
For, successfully deliver the messages to both the routes , you will have to add 2 entries i.e. 'direct:somename1' and 'direct:somename2'. 'start' is not a mandatory thing , you can give whatever name you like to.
I recommend you to read some chapters from Martin Fowler's EIP books. It is a wonderful resource to begin with. This will make you very easy to understand Camel.

It should be fairly easy to explain: exchange is always sent from a source to a destination. For that to happen, you need to create those 02 endpoints: one will consume (yes the start) and the other one will emit.
from("direct:start") means "directly consume the exchange from the "start" endpoint and process it anyhow.
to("direct:start") means "send" the exchange to the "start" endpoint "directly" within the same camel context.
What makes this really ambiguous is that the endpoint itself (i.e: "direct:start") is implicitly created on the fly so when writing your code, you are assuming that there is an endpoint called "direct:start" so you can retrieve exchange from it but you can also send an exchange to it.
Good luck!

forget about start. start is just a name of a halt point (direct).
Direct component can be take as a bridge between routes in same context.

Related

Messages Patterns - RabbitMQ/NestJS

I'm trying to integrate to a project done using NestJS, a simple api where you can publish messages with a name (or pattern) and send it to that system that has implemented a handler that matches the name.
The system I'm building is really small, it wouldn't make much of a sense using NestJS for that.
The problem I'm having is the following:
I'm creating a simple api that triggers the publish of the message onto a queue.
The consumer is on a system using NestJS.
I can't figure out how to give that messages a pattern that is recognized by that system.
For example:
Let's say I want to publish a message that has a name of "CreateRecord" with a payload to be processed from the other system that has a handler with the same name with an implementation.
Using amqplib how do I give messages a name or pattern?
You can provide a pattern in the content object when you are publishing a message.
publish(
'my_exchange',
'routing_key',
{ pattern: 'CreateRecord', data: 'Record' },
);

Request URI too long on spartacus services

I've been trying to make use of service.getNavigation() method, but apparently the Request URI is too long which causes this error:
Request-URI Too Long
The requested URL's length exceeds the capacity limit for this server.
Is there a spartacus config that can resolve this issue?
Or is this supposed to be handled in the cloud (ccv2) config?
Not sure which service are you talking about specifically and what data are you passing there. For starters, please read this: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/414
Additionally it would benefit everyone if you could say something about the service you're using and the data you are trying to pass/get.
The navigation component is firing a request for all componentIds. If you have a navigation with a lot of (root?) elements, the maximum length of HTTP GET request might be too long for the given client or server.
The initial implementation of loading components was actually done by a POST request, but the impression was that we would not need to support requests with so many components. I guess we were wrong.
Luckily, the legacy POST based request is still in the code base, it's OccCmsComponentAdapter.findComponentsByIdsLegacy.
The easiest way for you to use this code, is to provide a CustomOccCmsComponentAdapter, that extends from OccCmsComponentAdapter. Then you can override the findComponentsByIds method and simply call the super.findComponentsByIdsLegacy and pass in a copy of the arguments.
A more cleaner way would be to override the CmsComponentConnector and directly delegate the load to the adapter.findComponentsByIdsLegacy. I would not start here, as it's more complicated. Do a POC with the first suggested approach.

Two-way Apache Camel Routes - Infinite loop

I have 2 endpoints that I would like to establish routes between. Due to the nature of these endpoints (JMS topics), I would like the bridging to be bidirectional.
The underlying JmsComponent for the Tibco endpoint has the pubSubNoLocal parameter enabled which ensures that a consumer does not receive messages it has itself sent as per http://camel.apache.org/jms.html
pubSubNoLocal false
Specifies whether to inhibit the delivery of messages published by its own connection.
However this has no effect since the 2 routes create separate connections to the JMS topic my.topic.
As a result, the following will create an infinite loop.
As mentioned, I need the routes to operate in both directions for "seamless integration"
<c:route>
<c:from uri="tibco:topic:my.topic"/>
<c:to uri="solace-jms:topic:mytopic" />
</c:route>
<c:route>
<c:from uri="solace-jms:topic:mytopic"/>
<c:to uri="tibco:topic:my.topic" />
</c:route>
I suggest le consideration the concepts of message selectors and headers.
The way I see it, you do 2 things:
Add a "PRODUCER" header with your Server ID (however you define it)
All your listeners must be configured with a negative selector "NOT (PRODUCER='YOUR_ID')"
Done ?
(Of course, you could also use 2 topics... but I assume it is out of the question...)
You will need to add some indication in the message that it has been sent through either bridge. You could play with existing properties (redelivery ?) or better add a new one. For example set property bridged=true when it passes your bridge. Then inside your definition you can filter out each message already bridged.

Mule Web Service Consumer Warning : Operation Messages With More then 1 Part Are Not Supported

Hi I am working with Mule Web Service Consumer and i was trying to call operation with Multiple Parameters it is warning me that
Warning : Operation Messages With More then 1 Part Are Not Supported
I just want to pass multiple parameters to access my SOAP method to achieve the task.
Is this the problem with Web Service Consumer or is their any way to deal with this.
I'm afraid this is a known limitation of the web services consumer. However you can accomplish this with the cxf component.
I having the same issue and found some information around it ...
There is a improvement logged in JIRA, may help if you vote for it :)
This link suggests that you can still use WSConsumer but need to do some hand crafting of the request XML ... I could not understand what that exactly it meant so if anyone has an example on it would be great
PS: The problem I had with using CXF component is that it does not play well with the new Dataweave transformer as the Dataweave needs to be placed within the response block and from there it cannot datasense the response coming out from the CXF component
The Solution here is very simple. You just have to comment other messages and then load metadata for non-commented message (for one which you're trying to load metadata). Repeat this procedure for all the other messages and you're good to go.
Hope this helps !

Is it safe to rely on session variables to store information to be shared between multiple asynchronous flows?

I have a couple of flows that rely on session variables that are generated in one flow and then passed to the other. Is it safe to rely on session variables used by two asynchronous flows? I guess I don't fully understand the scope of 'sessionVars' in a mule application or in a given mule message.
The mule session has nothing to do with the Java EE session that is shared across threads. The mule session is part of the MuleMessage and how they works is explained here, therefor if you want to share something across multiple flows processing the same message that is the way to go.
If instead you are looking into a way to store a value from a flow processing the message A and pick that value from a flow processing the message B you should consider store this value into the objectstore
I am pretty sure that session variables are returned to http endpoints that are request-response. This could expose sensitive data. I am trying to locate the original mention and official mitigation strategy but have yet to locate it again.
But an easy solution is to remove them at return point of a flow
Edit:
Found the thing I was looking for...
`
<http:connector name="NoSessionConnector">
<service-overrides sessionHandler="org.mule.session.NullSessionHandler"/>
</http:connector>
`
found here under 'HTTP Response Header'
http://www.mulesoft.org/documentation/display/current/HTTP+Transport+Reference
Or, you can also create a custom SessionHandler