How can I invoke a RESTful service through Apache Camel? - java

I am currently using a HTTP method for invoking some URL which will create a JIRA issue.
Now I want to use Apache Camel, how can I use that?
I need to invoke the following link through Camel:
http://localhost:8080/rest/api/2/project/" + key + /components
As I'm new to Camel, please suggest some solutions and examples too.
Thanks

See also this FAQ about using dynamic to endpoints in Camel
http://camel.apache.org/how-do-i-use-dynamic-uri-in-to.html
Essentially the EIP pattern for this is the recipient list.
So in your case it could also be simplified to as one EIP
<recipientList>
<simple>http://localhost:8080/rest/api/2/project/${header.myKey}/components</simple>
</recipientList>
Mind the http component in Camel is fully synchronous. If you want to do request/reply over HTTP and avoid having the caller block while waiting for the reply message, then you can use some of the other HTTP components from Camel such as:
camel-ahc
camel-http4
camel-jetty

You could easily use the CXFRS Component; if you need to do it using the HTTP Component for some reason you could easily use that as well:
<setHeader headerName="CamelHttpUri">
<simple>http://localhost:8080/rest/api/2/project/${header.myKey}/components</simple>
</setHeader>
<inOut uri="http://doesnt.matter.we/override/it/anyways" />
And of course you will need to enrich your message with the myKey header before getting to this part of the route.

I am using apache camel jetty
CamelContext context = new DefaultCamelContext();
public void configure(){
context.addRoutes(new RouteBuilder(){
from("jetty:localhost:9000/offers")
.to("direct:getOffers")
.end();
}
});
so here when the user will hit http://localhost:9000/offers then the endpoint direct:getOffers will get invoked
so now defining the getOffers end point
context.addRoutes(new RouteBuilder(){
public void configure(){
from("direct:getOffers")
.to("jetty:http://localhost:9008/api/v2.0/offers?
bridgeEndpoint=true")
.end();
}
});
Here another service is running at 9008 having a rest resource of
http://localhost:9008/api/v2.0/offers and this is the resource that i am trying to consume.
so when camel instance starts it registers both the routes then it does the processing as described above
Note Its important to add the option of ?bridgeEndpoint=true for this to work

You can consume REST service from camel using CXFRS Component.Apache camel has enough information about this.
http://camel.apache.org/cxfrs.html

Related

How #Consume from Apache Camel does the mapping in Spring Boot project?

I'm learning about Apache Camel routes in Spring Boot projects and I have a project that does extension from some endpoints. The endpoints are not in this project, only the extension is done here. The extension is done using #Consume from org.apache.camel in this way:
#Consume(uri = "direct:products.create.validate.interceptor")
public void executeCreate(RequestWrapper<Product> productWrapper) {
...
}
I try to understand how this direct:products.create.validate.interceptor is mapped to an endpoint from another service. Can somebody explain me how this #Consume annotation does the mapping?
Or another example is this:
#Consume(uri = "direct:listAccountsPostHook")
public void executeCreate(RequestWrapper<Account> accountWrapper) {
...
}
Where should I look to understand how they are mapped? In the controller of the other service? I can't find any example with #Consume. Thank you!
The #Consume annotation in Apache Camel is used to subscribe to a Camel endpoint and consume messages from it. The endpoint can be either a direct endpoint or any other type of endpoint such as a JMS queue or a REST endpoint, depending on your use case.
The endpoint URI, which is specified in the uri attribute of the #Consume annotation, determines where the messages are consumed from. In your example, direct:products.create.validate.interceptor and direct:listAccountsPostHook are both direct endpoints.
In Apache Camel, direct endpoints are in-memory endpoints that allow you to send messages directly to another endpoint in the same JVM. The mapping between the endpoint and the method that consumes the messages is done by Camel's routing engine.
More on Camel Direct endpoints you can read here.
To understand how the messages are being consumed, you should look at the Camel routes that are defined in your project. In a Spring Boot project, you can define your Camel routes in a RouteBuilder class. This is where you would specify the mapping between the direct endpoint and the method that will consume the messages.
For example, if you have a RouteBuilder class that looks like this:
public class MyRouteBuilder extends RouteBuilder {
#Override
public void configure() {
from("direct:products.create.validate.interceptor")
.to("bean:myBean?method=executeCreate");
}
}
In this example, the direct endpoint direct:products.create.validate.interceptor is mapped to the executeCreate method in the myBean bean. The ?method=executeCreate part of the to URI tells Camel to call the executeCreate method on the myBean bean when a message is received at the endpoint.
So, in short, you should look for the Camel routes in your project that define the mapping between the endpoint and the method that consumes the messages.

What is service activator component in spring integration?

I am learning spring integration reading/watching a different stuff but I can't understand what service activator is.
I understood that there are two types of integration:
chanel and gateways. chanel is unidirectional integration but gateways is request/reply model. Gateways can be inbound(our system gets request and sends response) and outbound (our system sends request and receives response)
When I read about gateways I often see termin "service activator"
Could you clarify what does it mean ?
The outbound gateway is essentially a particular case for a service activator abstraction for request/reply scenarios. Another case is an outbound channel adapter, which is a one-way, but still can be treated as a service activator because when we send a message to its inputChannel, we are going to call some code - which we can treat as a service. Therefore activating it.
A general component service activator exists there for all the use-cases which are not covered by particular implementation. Let's imaging you need to call some REST service. Right, you can use an HTTP Outbound Gateway with some specific options. Or you can write some custom code which uses a RestTemplate to call that service. you wrap your code into a service activator configuration and you end up with the same behavior for the whole integration solution.
A service activator is a call to a method in a bean.
<service-activator ref="myService" method="aMethod"/>
will call
#Service
public class MyService {
public A aMethod(#Header(value = "param1") String param){
//code
}
}
#Header annotation allows to use an existing value in the header. That is an example.
You can also use it like this:
<service-activator expression="#myService.aMethod('My param')"/>

Apache Camel mockEndpoints() mocks all endpoints, instead of endpoints in advised route only

I am trying to advice and mock endpoints of one particular route as follows:
RouteDefinition route = context.getRouteDefinition("process-search");
route.adviceWith(context, new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception {
mockEndpoints();
}
});
Here, I expect that mockEndpoints will mock only endpoints within advised process-search route, but I see that endpoints within Camel Context are being adviced, as if I am using context.getRouteDefinitions() and then advice each of the route individually.
From mockEndpoints() JavaDocs -
Mock all endpoints in the route.
I assume that endpoints are not associated with particular endpoint, they are reused. But in that case how can I limit advising to endpoints of the particular route only, without explicitly referencing them manually.
Version of Camel is 2.17.0.redhat-630310
The javadoc is a bit mistaken, it is really mocking all endpoints for all routes. You can only auto-mock by using filters, wildcards etc. We will update the javadoc for future Camel versions.
What is the specific reason you want to limit to endpoints in the route only. An endpoint can be shared among other routes etc, such as when you link routes together etc. Also mocking other endpoints for testing will not affect these endpoints.

How to modify a camel endpoint at runtime

The problem
I have a spring mvc application that uses apache camel. I am confused on the role that the RouteBuilder class plays and how it actually gets initialized. I know that the docs say that the configure() method is:
Called on initialization to build the routes using the fluent builder syntax.
but when does this initialization occur? Does it occur at application startup or some time later when the route is about to be used?
The purpose of this question is ultimately to ask how I can modify the route at runtime. I want to be able to build different routes as needed.
Examples
xml definitions:
<service name="myService" tier="3">
<requestType>my.package.RequestType</requestType>
<responseType>my.package.ResponseType</responseType>
<endpoint>
<httpEndpoint>
<url default="true" value="someUrl"/>
<timeout value="5000"/>
</httpEndpoint>
</endpoint>
</service>
Route Builder template:
public class myRouteBuilder extends RouteBuilder {
#Override
public void configure() throws Exception {
// When does this method get executed?
}
}
Questions
When does configure() execute?
How can I dynamically set the endpoint url?
You are able to use toD to dynamically change the endpoint at runtime based on an expression. See the documentation
If you want to change more of the route or add a completely new route then look at the API on the CamelContext. This Stackoverflow question has an example of adding a completely new route.
The lifecycle of the Camel service is documented here : https://camel.apache.org/lifecycle.html
Camel uses a simple lifecycle interface called Service which has a single start() and stop() method.
Various classes implement Service such as CamelContext along with a number of Component and Endpoint classes.
When you use Camel you typically have to start the CamelContext which will start all the various components and endpoints and activate the routing rules until the context is stopped again.
It is when the context starts that the various components start. Not sure i understand the dynamic url part. If it is to indicate a dynamic endpoint (if the data is this , then queue1 else queue2) you should be able to use something like the DynamicRouter EIP which is as explained here (https://camel.apache.org/dynamic-router.html)
You have several options.
Inject them as spring properties.
Inject them from external properties source.
Inject them from some bean method.
Then you can put the property value in a header and later put the value in the .toD("$header.routeEndpoint"). This can take care of dynamic endpoints.
Off course to rebuild the entire route you need to play with the API.

Spring MVC like processing of AMQP messages

What I want to do is process AMQP messages in a very similar way the Http Requests are processed using spring-webmvc annotations such as #RequestMapping, #RequestParam etc. But, instead of the Http Request my source object will be an AMQP message. The AMQP message request will have two headers, for example -
method="POST"
url="/api/myobjects/{someParam}"
and the payload will contain data in json format.
If you have noticed, this is nothing but HTTP REST api mapped to AMQP message.
I want to be able to write a controller like handler, for example -
#Controller
public class MyObjectHandler {
#RequestMapping(value="/api/myobjects/{someParam}", method="POST")
public MyObject createMyObject(#Payload MyObject myObj, #PathParam String someParam) {
//... some processing
return myObj;
}
// ...more handlers
}
I have looked at spring-amqp/rabbitmq annotations and also spring integration annotations. They are close to what I want, but would not allow routing to handler methods based on header parameters, especially the REST url.
I don't expect that a readymade solution would be available for this. Just want to make sure I choose the best possible option. Some of the options I think are (in order of precedence)
If the spring-webmvc annotation processing mechanism is extensible, just extend it to use AMQP message as source instead of Http Request
Modify the spring-webmvc annotation processing mechanism to take the AMQP message as input instead of Http Request
Write your own solution with custom annotaions and their processors, which I think is a very involving task
Or any other possible approach than above?
Any guidance/direction is appreciated.
I think the starting point is likely AbstractMethodMessageHandler in spring-messaging.
There's currently a SimpAnnotationMethodMessageHandler implementation for websockets which invokes #Controllers.
You could use a #RabbisListener method that has a Message<?> parameter (Spring AMQP will convert the underlying Rabbit message to a spring-messaging message, including the headers). Then, invoke the message handler to route to the appropriate controller method.
If you come up with a robust implementation, please consider contributing it.

Categories