Apache camel Restlet producer cached - apache-camel

I am using camel 2.18.0 version.I am facing a issue while using restlet component in SEDA flow. Please find the route details below
from("timer://foo?repeatCount=1")
.to("http4://localhost:8080/pages")
.split(body())
.to("seda:pageConsumer");
from("seda:pageConsumer?concurrentConsumer=5")
.toD("restlet:${in.body}")
.process(enrich());
Details on route:
"http4://localhost:8080/pages" this rest endpoint returns list of url
url= http://localhost:8080/data?page=1&size=5
seda consumer is used for consuming each page parallel
url "http://localhost:8080/data?page=1&size=5" streams the data (This is a rest endpoint and endpont does not send a list of data instead endpoint streams the data)
restlet endpoint invokes the page url and streams the data.
Issue:
when seda endpoint receives 1st URL all is good i.e. "http://localhost:8080/data?page=1&size=5" rest endpoint is invoked by restlet and expected data is processed in route.
when seda endpoint receives 2nd URL i.e.
"http://localhost:8080/data?page=2&size=5" , this where issue starts instead of invoking rest endpoint with "page=2&size=5" as query param, restlet use query param from 1st URL i.e. "page=1&size=5". and issue continues for rest of the urls.
upon debugging i found out that camel caches producer in ProducerCache
and producer is cached in a hashmap with endpoint uri as the key.
questions why does camel does not honour query param during caching? is there why to avoid the caching?
Please note i got the code working by changing the url to include page details which is ugly. Currently url looks like
http://localhost:8080/data/page/2/size/5.

If the restlet endpoint is calling the same http url (eg host:port) then it can be slightly better to use a plain to with this host:port as static, and then set a header with the dynamic part.
.setHeader(Exchange.HTTP_QUERY, constant("page1=&size=5"))
.to("http:xxxx")
Then the same endpoint/producer is reused and the header then includes the dynamic part with the query parameters.
There is also a header where you can set the context-path as well on Exchange.
If you keep using toD then you can adjust the size of the cache with the cacheSize option - its the same as on recipient list: http://camel.apache.org/recipient-list.html

Related

camel - quartz2 endpoint - Multiple consumers for the same endpoint

I am using apache camel and wants to have multiple routes.The route is as below.
endpoint -> quartz2://tsTimer?cron=0%2F20+*+8-18+%3F+*+MON%2CTUE%2CWED%2CTHU%2CFRI+*&stateful=true&trigger.timeZone=Asia%2FSingapore
Call bean method to get data.
Send to MQ
In this case my route is going to be same as the polling interval is same.
The data from bean method will be different.
And the MQ queue will be same.
Failed to start route route2 because of Multiple consumers for the same endpoint is not allowed: quartz2://tsTimer?cron=0%2F20+*+8-18+%3F+*+MON%2CTUE%2CWED%2CTHU%2CFRI+*&stateful=true&trigger.timeZone=Asia%2FSingapore
How do i achieve this? How do i differentiate camel route in case when the endpoint is quartz2 timer?
I din't notice that in endpoint uri I was having tsTimer which will distinguishes other end-points.
Something like below
quartz2://tsTimer1
quartz2://tsTimer2
quartz2://tsTimer3

Intercept routes without tracing

The application I'm working on is a middleware app that allows routing among tons of applications (mostly SOAP services).
We encountered saturation because of the automatic logs generated by Camel.
The log volume was reduced with the new interceptors. However, if a service is called inside a current route, all I got is the Request Body from the SendToEndpoint interceptor.
Given that all service calls in the application was made that way, I can not change the current routes.
Old interceptors:
getContext().setTracing(true); // <--- trace every step of all routes
interceptFrom().to("log:example");
configureRoutes() {
// route logic
}
New interceptors:
getContext().setTracing(false);
interceptFrom("cxf:*").to("log:example");
interceptSendToEndpoint("cxf:*").to("log:example");
configureRoutes() {
// route logic
}
Example of a route :
from("scheduler endpoint")
.to("DAO method to find the case from database")
.process(//First processor to call the SOAP service)
.to("SOAP endpoint")
.convertBodyTo(SOAP ResponseBody.class) <-- convert the MessageContentsList to SOAP response body generated from the WSDL
.process(//Second processor to check if the response code is OK in the SOAP response body);
How can I implement an interceptor that allows to log also the SOAP response body ?
Thank you for your help.
I dislike to use interceptors to this porpoise, I suggest you to use the EventNotifier interface, you just need to declare it as a bean in camel context and override the notify method.
See: https://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/spi/EventNotifier.html
Here is an usage example: http://camel.apache.org/eventnotifier-to-log-details-about-all-sent-exchanges.html
Note: Camel has some events that you can uss like: CamelContextCreated, ExchangeCreatedEvent, ExchangeSendingEvent, ExchangeSentEvent, ExchangeCompletedEvent, ExchangeFailedEvent, etc.

add query string in Microsoft oauth 2.0 redirect url for token acquisition

I'm currently developing an App using Microsoft LIVE 2.0 API
Currently, I’m using these URLs as my authentication endpoints:
https://login.microsoftonline.com/common/oauth2/v2.0/authorize
https://login.microsoftonline.com/common/oauth2/v2.0/token
However, when I sent the request to the token endpoint with the redirect URL as
https://blabla.com/accept_token.php?api_ver=wave5&csrf=AY7F6O4hF0n8yW3i2O_y6N-ky7zzfULiYV_fttLK1S3JgaeQz2GTk9FOeIGBBH5CvkfkEYCyPOCQCujcrij4KDy2wAMZyXqx24jvwZRtzOv0s9ADGYl1iFtvYtkmgeFmZEY&appdata=%7B%22use_case%22%3A1%2C%22type%22%3A1%2C%22flow%22%3A2%2C%22domain_id%22%3A12%2C%22tracked_params%22%3A%22%5B%5D%22%7D
I got errors saying the reply address does not match the reply addresses configured for the application
For the application, I set the reply address to be https://blabla.com/accept_token.php.
Is it possible that I add some parameters to the url and still make it match?
I'm pretty sure the reply url you send must match exactly the reply url registered on the application, including any query strings.
If there is variable state informaiton you need passed throughout the authentication process, you should use the state variable.
https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols-oauth-code
state
A value included in the request that will also be returned in the token response. It can be a string of any content that you wish. A randomly generated unique value is typically used for preventing cross-site request forgery attacks. The state is also used to encode information about the user's state in the app before the authentication request occurred, such as the page or view they were on.

Http request and response lost after receiving Response from Web Service?

I have an Apache camel application which talks with a web service. This is purely a integration(mediation) application. We take REST request and transform it to a SOAP message (using VM templates) and call the web service. Receive response from web service, transform it to JSON and send back to our client.
REST ---->transform to SOAP req (Velocity template) ---->call WS ---->receive response---->transform into JSON---->return response to caller.
We are using servlet endpoint to receive request from our client. We can obtain HttpSession object from exchange before calling web service as follows :
HttpServletRequest req = exchange.getIn().getBody(HttpServletRequest.class);
HttpSession session = req.getSession();
However, the problem is that I cannot obtain HTTPSession from exchange after receiving response from web service. If I check the Exchange object in debug mode, the Exchange.getIn() is of type DefaultMessage rather than HttpMessage. That is the reason I think I loose Request and response objects.
I tried setting the exchange pattern to InOut but that doesn’t help.
The only solution I could find is to store the original body of the in message in a header or a property and retrieve it at the end. But I think there must be a better solution that this.
Could anybody help please?
Note: We need HttpSession so that we can store corresponding session information like session id created on WS for the session created by our request. We cannot pass session information created on WS to our callers, and need a place on our application to hold this mapping info. HttpSession serves this requirement. Is there any better way?
You can store the http session as an exchange property, camel copy these properties across the exchanges, so you can access it in the route when you need.

Obtaining a previous message within an Apache Camel route

I'm pretty new to camel so perhaps I'm going about this the wrong way but I'm routing messages from one endpoint to another and transforming them on the way. However the next stage is to add authentication to the pipeline. I have a service that tracks authenticated users. My plan is to, in the first stage of the route, to add a filter that checks to see if the current user is authenticated. If the user is not I want to transform the message into an authentication request and send that to my endpoint. All good so far, however, after authentication (if successful) I want to send the original message down the pipeline. Is this something that can be done?
A simplified version of my route would be:
from("seda:in").
filter(method(Authentication.class, "isNotAuthenticated")).
bean(AuthenticationTransformer.class)
to("cxfbean:out")
.end()
.bean(RequestTransformer.class)
.to("cxfbean:out")
The same message would be sent to both transformer beans.
You should preserve the message in the Exchange property setProperty("originalMessage", body()) before transforming it. Afterwards you can access that property using getProperty("originalMessage")

Resources