Camel Routes started but not run when using Camel Cache - java

I am trying to make use of Camel Cache for the first time. So I have created a small app based on camel-java maven archetype.
My code is based on the examples from here. Here is the snippet
public class AddingToCache extends RouteBuilder {
public void configure() {
from("direct:start")
.log("START")
.setHeader(CacheConstants.CACHE_OPERATION, constant(CacheConstants.CACHE_OPERATION_ADD))
.setHeader(CacheConstants.CACHE_KEY, constant("Custom_key"))
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
exchange.getOut().setBody("My custom out");
}
})
.log("starting ...")
.to("cache://cache1")
.to("direct:next");
}
}
public class ReadingFromCache extends RouteBuilder {
#Override
public void configure() throws Exception {
from("direct:next")
.setHeader(CacheConstants.CACHE_OPERATION, constant(CacheConstants.CACHE_OPERATION_GET))
.setHeader(CacheConstants.CACHE_KEY, constant("Custom_key"))
.to("cache://cache1")
.choice()
.when(header(CacheConstants.CACHE_ELEMENT_WAS_FOUND).isNotNull())
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
Object body = exchange.getIn().getBody();
System.out.println("Cache body - " + body);
}
})
.otherwise()
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
Object body = exchange.getIn().getBody();
System.out.println("Cache body when not found - " + body);
}
})
.end()
.to("direct:finish");
}
}

your routes are likely running, you just haven't invoked them yet (from the code you posted above anyways). you need to send a message to the direct:start or direct:next routes using a ProducerTemplate to exercise the routes...
ProducerTemplate template = camelContext.createProducerTemplate();
template.sendBody("direct:start", "message");

Related

Apache Camel: best practice how to consume data from multiple REST endpoints

I am consuming data from REST endpoints (order of 1000+) which all have the same structure:
<server uri>/v1/source/<some ID>
I am using RouteBuilder components like this connecting to the individual endpoint <ID>:
#Component
public class Route_to_<ID> extends RouteBuilder {
#Override
public void configure() throws Exception {
from("timer:mytimer?repeatCount=1") //
.setBody(simple("${null}")) //
.setHeader(Exchange.CONTENT_TYPE, simple("text/event-stream"))
.setHeader("CamelHttpMethod", simple("GET"))
.to(
<server uri>/v1/source/<ID>
+ _deviceName + "::" + _deviceProperty //
+ "?disableStreamCache=true" //
) //
.process(data -> {
... do same stuff for all endpoints ...
});
}
}
The corresponding SpringBootApplicationlooks like this:
#SpringBootApplication
#ComponentScan(basePackages = "my.package.where.components.reside")
public class MyRouteHandler {
}
Is there an elegant way to start all the individual routes to endpoints <ID>in one go using one single SpringBootApplication? Or does every route need an individual SpringBootApplication which is to be started individually?
You could use toD with dynamic uri that gets the version, source and id from message body, headers or exchange properties. You can also use property-placeholders to define host, port and other configs.
Since the REST endpoints all use the same structure you can change the version, source and id and use the same URI for most if not all the REST API calls.
Example:
public class ExampleTest extends CamelTestSupport {
static final String API_DYNAMIC_URI = "https://{{api.uri}}:{{api.port}}/{{api.version}}"
+ "/${exchangeProperty.source}/${exchangeProperty.id}"
+ "?disableStreamCache=true";
#Test
public void exampleTest() throws Exception {
context.adviceWith(context.getRouteDefinition("exampleRoute"),
new AdviceWithRouteBuilder(){
#Override
public void configure() throws Exception {
weaveById("apiEndpoint")
.replace()
.toD("mock:${exchangeProperty.source}/${exchangeProperty.id}")
.setBody().simple("Source: ${exchangeProperty.source} id: ${exchangeProperty.id}");
}
});
Map<String, Object> body1 = new HashMap<>();
body1.put("source", "source1");
body1.put("id", "A");
Map<String, Object> body2 = new HashMap<>();
body2.put("source", "source2");
body2.put("id", "B");
MockEndpoint source1MockEndpoint = getMockEndpoint("mock:source1/A");
source1MockEndpoint.expectedMessageCount(1);
MockEndpoint source2MockEndpoint = getMockEndpoint("mock:source2/B");
source2MockEndpoint.expectedMessageCount(2);
startCamelContext();
template.sendBody("direct:start", body1);
template.sendBody("direct:start", body2);
template.sendBody("direct:start", body2);
source1MockEndpoint.assertIsSatisfied();
source2MockEndpoint.assertIsSatisfied();
}
#Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
from("direct:start")
.routeId("exampleRoute")
.setProperty("source").simple("${body['source']}")
.setProperty("id").simple("${body['id']}")
.toD(API_DYNAMIC_URI).id("apiEndpoint")
.log("Received: ${body}");
}
};
}
#Override
protected Properties useOverridePropertiesWithPropertiesComponent() {
Properties properties = new Properties();
properties.put("api.uri", "localhost");
properties.put("api.port", "3000");
properties.put("api.version", "v1");
return properties;
}
#Override
public boolean isUseAdviceWith() {
return true;
}
}

Transfer Date header removed from Camel DefaultHeaderFilterStrategy

I was try to hit REST API with authorization from two header fileds: Authorization and Date but Date field has removed from DefaultHeaderFilterStrategy. I was try to replace it with mine filter and set it into Jetty client, but Date header still missing into RequestProcessor and RestProcessor. I need to can transfer this header globally for all our requests. Here is a parts of my code.
#Component
public class RestAPIClientRoute extends RouteBuilder {
#Autowired
private CamelContext camelContext;
#Override
public void configure() throws Exception {
JettyHttpComponent jettyComponent = camelContext.getComponent("jetty", JettyHttpComponent.class);
jettyComponent.setHeaderFilterStrategy(new HeaderFilter());
restConfiguration().component("jetty").scheme("http").port(80).host("localhost");
interceptSendToEndpoint("rest:post:*").process(new Processor() {
public void process(Exchange exchange) {
Properties authProperties = CryptoUtil.duoAuthRequestEncode( duoConfig,"POST", exchange);
Message msg = exchange.getMessage();
msg.setHeader("Authorization", "Basic " + authProperties.getProperty("auth"));
msg.setHeader("Date", authProperties.getProperty("timestamp"));
}
});
rest("/rest")
.post("/accounts/v1/account/list")
.to("direct:hello");
from("direct:hello")
.process(new RequestProcessor());
from("timer:rest-client?period=60s")
.to("direct:accountList");
from("direct:accountList")
.to("rest:post:/rest/accounts/v1/account/list")
.process(new RestProcessor());
}
}
#Component
public class HeaderFilter implements HeaderFilterStrategy {
#Override
public boolean applyFilterToCamelHeaders(String headerName, Object headerValue, Exchange exchange) {
return false;
}
#Override
public boolean applyFilterToExternalHeaders(String headerName, Object headerValue, Exchange exchange) {
return false;
}
}
Actually the problem is coming from the REST component. He set HeaderFilter which override the other setted filter in HTTP component. REST component can not set HeaderFilterStrategy and always use default one. I was start to use only http component with setted mine customised filter instead rest and now can transfer deleted headers from DefaultHeaderFilterStrategy.
I replace it
.to("rest:post:/rest/accounts/v1/account/list")
with
.setHeader(Exchange.HTTP_METHOD, constant("POST"))
.setHeader(Exchange.HTTP_QUERY, constant(urlQuery))
.to("https://host.domain.com/rest/accounts/v1/account/list")

Apache Camel test expectedBodiesReceived check if the body is null?

I have a route that a processor consumes the message and set the body to null.
public class KafkaRedirect implements Processor {
#Override
public void process(final Exchange exchange) throws Exception {
... some logic to send to another party
/**
* This is added to consume the message
*/
exchange.getIn().setBody(null);
}
}
In the test I send message to the route and I want to test if the message is sent and the body is null.
#Test
public void testMyRoute() throws Exception {
final MockEndpoint thirdPartyEndpoin = getMandatoryEndpoint("mock://myRoute", MockEndpoint.class);
context().getRouteDefinition("myRouteId")
.adviceWith(context(), new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception {
weaveById("myProcessId").after().to(thirdPartyEndpoin);
}
});
startCamelContext();
thirdPartyEndpoin.expectedMessageCount(1);
/* I NEED TO TEST IF THE BODY IS NULL*/
thirdPartyEndpoin.expectedBodiesReceived(null);
template.sendBody(ROUTE_DIRECT_START, "{\"foo\":\"foo\"}");
thirdPartyEndpoin.assertIsSatisfied(TimeUnit.SECONDS.toMillis(EXPECTED_TIMEOUT_SECONDS));
}
Try with something like (typed from top of my head)
thirdPartyEndpoin.message(0).body().isNull();

Camel saves full http request but I want only attached file

I have the following code base:
#Component
public class DummyRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
rest("/upload").post().to("file://rest_files");
}
#Bean
public ServletRegistrationBean servletRegistrationBean() {
SpringServerServlet serverServlet = new SpringServerServlet();
ServletRegistrationBean regBean = new ServletRegistrationBean( serverServlet, "/rest/*");
Map<String,String> params = new HashMap<>();
params.put("org.restlet.component", "restletComponent");
regBean.setInitParameters(params);
return regBean;
}
#Bean
public org.restlet.Component restletComponent() {
return new org.restlet.Component();
}
#Bean
public RestletComponent restletComponentService() {
return new RestletComponent(restletComponent());
}
}
I upload file using postman:
It is actually usual csv.
But when I open file my application stored - I see file with following content:
Obvious that file contains full request information.
How can I save only file without other data from http request?
P.S.
I tried to register callback:
#Override
public void process(Exchange exchange) throws Exception {
System.out.println(exchange);
final MultipartFile mandatoryBody = exchange.getIn().getBody(MultipartFile.class);
but it returns null

Using a http proxy with Apache Camel's http4 endpoint

I'm attempting to use a http proxy with Camel's http4 component. The proxy works when testing using Intellij's HTTP Proxy "Check Connection" option.
However I don't know how to configure it correctly via Camel. When running the following integration test a "ConnectException: Connection timed out" is thrown. Can anyone clarify how to set the proxy details correctly please?
public class SimpleHttpProxyIT extends CamelTestSupport {
public static final String DIRECT_START = "direct:start";
public static final String MOCK_RESULT = "mock:result";
#Produce(uri = DIRECT_START)
protected ProducerTemplate basic;
#EndpointInject(uri = MOCK_RESULT)
protected MockEndpoint resultEndpoint;
#Test
public void testBasic() throws Exception {
basic.sendBody(null);
resultEndpoint.setExpectedMessageCount(1);
resultEndpoint.assertIsSatisfied();
}
#Override
public RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
from(DIRECT_START)
.id("SunriseTest")
.log(LoggingLevel.INFO, "About to hit sunrise")
.setHeader(Exchange.HTTP_URI, simple("http://api.sunrise-sunset.org/json?lat=36.7201600&lng=-4.4203400"))
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
exchange.getProperties().put("http.proxyAuthHost", "myproxy.company.org");
exchange.getProperties().put("http.proxyAuthPort", "10000");
exchange.getProperties().put("http.proxyAuthMethod", "Basic");
exchange.getProperties().put("http.proxyAuthUsername", "myusername");
exchange.getProperties().put("http.proxyAuthPassword", "mypassword");
}
})
.recipientList(simple("http4:dummyhost"))
.log(LoggingLevel.INFO, "Done")
.to(MOCK_RESULT);
}
};
}
}
I would think it should should be exchange.setProperty(...)
Setting the properties in the URI worked. I misread the documentation on "Using Proxy Settings Outside of the URI" (http://camel.apache.org/http4.html) as this was referring to setting them on the context, not the exchange.
public class SimpleHttpProxyIT extends CamelTestSupport {
public static final String DIRECT_START = "direct:start";
public static final String MOCK_RESULT = "mock:result";
#Produce(uri = DIRECT_START)
protected ProducerTemplate basic;
#EndpointInject(uri = MOCK_RESULT)
protected MockEndpoint resultEndpoint;
#Test
public void testBasic() throws Exception {
basic.sendBody(null);
resultEndpoint.setExpectedMessageCount(1);
resultEndpoint.assertIsSatisfied();
}
#Override
public RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
from(DIRECT_START)
.id("SunriseTest")
.log(LoggingLevel.INFO, "About to hit sunrise")
.setHeader(Exchange.HTTP_URI, simple("http://api.sunrise-sunset.org/json?lat=36.7201600&lng=-4.4203400"))
.recipientList(simple("http4:dummyhost?proxyAuthHost=myproxy.company.org&proxyAuthPort=10000&proxyAuthUsername=myusername&proxyAuthPassword=mypassword"))
.log(LoggingLevel.INFO, "Done")
.to(MOCK_RESULT);
}
};
}
}

Categories

Resources