Unable to execute OS Command from Camel - apache-camel

I'm trying to execute OS commands using Camel's exec Component. Unfortunately I don't see any output of the Commands executed. Here is my code which contains a simple exec taken from the Documentation:
public class CamelExampleTest extends CamelTestSupport {
#Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
from("direct:startpoint").id("route1") //
.to("exec:wc?args=--words /usr/share/dict/words")//
.convertBodyTo(String.class) //
.process(new Processor() {
#Override
public void process(Exchange exchng) throws Exception {
String body = exchng.getIn().getBody(String.class);
System.out.println(body);
}
}).to("mock:endpoint");
}
};
}
#Test
public void test() throws InterruptedException {
System.out.println("running test");
MockEndpoint resultEndpoint = context.getEndpoint("mock:endpoint", MockEndpoint.class);
}
}
Any apparent mistake in my code?

You send nothing to direct:startpoint.
Try something like this:
#Test
public void test() throws InterruptedException {
System.out.println("running test");
MockEndpoint resultEndpoint = context.getEndpoint("mock:endpoint", MockEndpoint.class);
context.createProducerTemplate().sendBody("direct:startpoint","Hello world");
}

Related

Test case for Camel Springboot application takes a longer build time

I have written camel test case for my spring boot application as below.
#RunWith(CamelSpringRunner.class)
#SpringBootTest
#ActiveProfiles("test")
#ContextConfiguration(classes = Application.class)
#DirtiesContext(classMode = AFTER_EACH_TEST_METHOD)
#UseAdviceWith
public class CamelTestClass {
#Autowired
private CamelContext camelContext;
private String routeID = "routeId";
Logger log = Logger.getLogger(String.valueOf(CamelSpringBootApplication.class));
#Test
#DirtiesContext
public void test1() throws Exception {
ModelCamelContext mcc = camelContext.adapt(ModelCamelContext.class);
RouteReifier.adviceWith(mcc.getRouteDefinition(routeID), mcc, new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception {
doSOmething
}
});
mcc.start();
assertion
mcc.stop();
}
#Test
#DirtiesContext
public void test2() throws Exception {
ModelCamelContext mcc = camelContext.adapt(ModelCamelContext.class);
RouteReifier.adviceWith(mcc.getRouteDefinition(routeID), mcc, new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception {
doSomething
}
});
mcc.start();
assertion
mcc.stop();
}
#Test
#DirtiesContext
public void test3() throws Exception {
ModelCamelContext mcc = camelContext.adapt(ModelCamelContext.class);
RouteReifier.adviceWith(mcc.getRouteDefinition(routeID), mcc, new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception {
doSomething
}
});
mcc.start();
assertion
mcc.stop();
}
}
So there are 3 test cases written, On each beginning of the test case I had to start the camel context and clear it at the end. With this setup, On a maven build test tests are taking a long time to get it completed. with around 30 test cases, the build is taking 25 mins for completion. Is there a scope for optimization of test cases in terms of running time here?

Mock not found in the registry for Camel route test

I am trying to test a Camel route (polling messages from an SQS queue) containing
.bean("messageParserProcessor")
where messageParserProcessor is a Processor.
The test:
public class SomeTest extends CamelTestSupport {
private final String queueName = ...;
private final String producerTemplateUri = "aws-sqs://" + queueName + ...;
private static final String MESSAGE_PARSER_PROCESSOR_MOCK_ENDPOINT = "mock:messageParserProcessor";
#EndpointInject(uri = MESSAGE_PARSER_PROCESSOR_MOCK_ENDPOINT)
protected MockEndpoint messageParserProcessor;
#Override
public boolean isUseAdviceWith() {
return true;
}
#Before
public void setUpContext() throws Exception {
context.getRouteDefinitions().get(0).adviceWith(context, new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception {
interceptSendToEndpoint("bean:messageParserProcessor")
.skipSendToOriginalEndpoint()
.process(MESSAGE_PARSER_PROCESSOR_MOCK_ENDPOINT);
}
});
}
#Test
public void testParser() throws Exception {
context.start();
String expectedBody = "test";
messageParserProcessor.expectedBodiesReceived(expectedBody);
ProducerTemplate template = context.createProducerTemplate();
template.sendBody(producerTemplateUri, expectedBody);
messageParserProcessor.assertIsSatisfied();
context.stop();
}
}
When I run the test I get this error:
org.apache.camel.FailedToCreateRouteException:
Failed to create route route1 at:
>>> InterceptSendToEndpoint[bean:messageParserProcessor -> [process[ref:mock:messageParserProcessor]]] <<< in route: Route(route1)[[From[aws-sqs://xxx...
because of No bean could be found in the registry for: mock:messageParserProcessor of type: org.apache.camel.Processor
Same error if I replace interceptSendToEndpoint(...) with mockEndpointsAndSkip("bean:messageParserProcessor")
The test can be executed (but obviously doesn't pass) when I don't use a mock:
interceptSendToEndpoint("bean:messageParserProcessor")
.skipSendToOriginalEndpoint()
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {}
});
So the problem is the mock that is not found, what is wrong in the way I create it?
So I found a workaround to retrieve mocks from the registry:
interceptSendToEndpoint("bean:messageParserProcessor")
.skipSendToOriginalEndpoint()
.bean(getMockEndpoint(MESSAGE_PARSER_PROCESSOR_MOCK_ENDPOINT));
// Instead of
// .process(MESSAGE_PARSER_PROCESSOR_MOCK_ENDPOINT);
But I still don't understand why using .process("mock:someBean") doesn't work...

Use Camel route to listen a topic

When I send a message to the topic, why the processor get 10 exchanges? This is my code.
public class RouteTest extends RouteBuilder {
public void configure() throws Exception {
from("activemq:topic:Topic.ansyncMessage").process(new Processor() {
public void process(Exchange exchange) throws Exception {
System.out.println(exchange.getIn().getBody());
}
});
}
}
You have a typo 'ansyc' -> 'async'

Apache Camel: all modifications of onRedelivery's processor is reset in next redelivery

All modifications of onRedelivery's processor is reset in next redelivery. Is there any way to make the modifications becomes permanent?
Properties are kept at each redelivery. You can use them to store information that you want to use after.
Code :
public class OnRedeliveryTest extends CamelTestSupport {
public static final String PROP_TEST = "PROP_TEST";
#Produce(uri = "direct:start")
ProducerTemplate producerTemplate;
#Override
public RouteBuilder createRouteBuilder() {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
onException(Exception.class)
.onRedelivery(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
final String current = (String) exchange.getProperty(PROP_TEST);
exchange.setProperty(PROP_TEST, "property" + current);
System.out.println((String) exchange.getProperty(PROP_TEST));
}
})
.maximumRedeliveries(3).redeliveryDelay(0)
.handled(true)
.end();
from("direct:start")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
}
})
.throwException(new Exception("BOOM"))
.to("mock:end");
}
};
}
#Test
public void smokeTest() throws Exception {
producerTemplate.sendBody("1");
}
}
In output, you will have :
propertynull
propertypropertynull
propertypropertypropertynull

Doing bean inject in camel test

I have a camel app which look something like below which has a route like below:-
from("direct:getMarketplaceOrders").to("bean:orderHelper?method=getMarketplaceOrders");
The entry point of the code look something like below:
public class OrderMainApp {
public static void main(String... args) throws Exception {
OrderMainApp orderMainApp = new OrderMainApp();
DefaultCamelContext camelContext = new DefaultCamelContext();
ProducerTemplate producer = camelContext.createProducerTemplate();
camelContext.setRegistry(orderMainApp.createRegistry(producer));
camelContext.addRoutes(new OrderRouteBuilder(producer));
camelContext.start();
}
protected JndiRegistry createRegistry(ProducerTemplate producer) throws Exception {
JndiRegistry jndi = new JndiRegistry();
OrderHelper orderHelper = new OrderHelper();
orderHelper.setProducer(producer);
jndi.bind("orderHelper", orderHelper);
return jndi;
}
}
In OrderRouteBuilder configure has routes like below:-
//processor is a custom JSONProcessor extending Processor
from("jetty:http://localhost:8888/orchestratorservice").process(processor);
from("direct:getMarketplaceOrders").to("bean:orderHelper?method=getMarketplaceOrders");
My goal is to test the response I receive from bean:orderHelper?method=getMarketplaceOrders when I place a request on direct:getMarketplaceOrders
orderHelper.getMarketplaceOrders looks like below:-
public OrderResponse getMarketplaceOrders(GetMarketplaceOrdersRequest requestParam) throws Exception
My test class look something like below:-
public class OrderMainAppTest extends CamelTestSupport {
#Produce(uri = "direct:getMarketplaceOrders")
protected ProducerTemplate template;
#EndpointInject(uri = "bean:orderHelper?method=getMarketplaceOrders")
protected MockEndpoint resultEndpoint;
#Test
public void testSendMatchingMessage() throws Exception {
String expectedBody = "<matched/>";
template.sendBody("{\"fromDateTime\": \"2016-01-11 10:12:13\"}");
resultEndpoint.expectedBodiesReceived(expectedBody);
resultEndpoint.assertIsSatisfied();
}
#Override
protected RouteBuilder createRouteBuilder() {
return new RouteBuilder() {
#Override
public void configure() {
from("direct:getMarketplaceOrders").to("bean:orderHelper?method=getMarketplaceOrders");
}
};
}
}
Whenever I am running the test I am getting the below exception:-
java.lang.IllegalArgumentException: Invalid type: org.apache.camel.component.mock.MockEndpoint which cannot be injected via #EndpointInject/#Produce for: Endpoint[bean://orderHelper?method=getMarketplaceOrders]
I am guessing this is because I am not able to pass on OrderHelper to the camel test context. Can some one let me know how can I inject the bean in the mock result end point?
EDIT:-
I tried modifying my test class as follows:-
public class OrderMainAppTest extends CamelTestSupport {
protected OrderHelper orderHelper = new OrderHelper();
#Produce(uri = "direct:getMarketplaceOrders")
protected ProducerTemplate template;
#EndpointInject(uri = "mock:intercepted")
MockEndpoint mockEndpoint;
#Before
public void preSetup() throws Exception {
orderHelper.setProducer(template);
};
#Test
public void testSendMatchingMessage() throws Exception {
GetMarketplaceOrdersRequest request = new GetMarketplaceOrdersRequest();
request.setFromDateTime("2016-01-11 10:12:13");
request.setApikey("secret_key");
request.setMethod("getMarketplaceOrders");
request.setLimit(10);
request.setOffset(2);
template.sendBody(request);
mockEndpoint.expectedBodiesReceived("{\"success\":\"false\"");
}
#Override
protected RouteBuilder createRouteBuilder() {
return new RouteBuilder() {
#Override
public void configure() {
interceptSendToEndpoint("bean:orderHelper?method=getMarketplaceOrders")
.to("mock:intercepted"); from("direct:getMarketplaceOrders").to("bean:orderHelper?method=getMarketplaceOrders");
}
};
}
#Override
protected JndiRegistry createRegistry() throws Exception {
return getRegistry();
}
protected JndiRegistry getRegistry() {
JndiRegistry jndi = new JndiRegistry();
jndi.bind("orderHelper", orderHelper);
return jndi;
}
}
The above code is making the request correctly and is flowing through my app correctly. But I am not able to intercept the response of orderHelper.getMarketplaceOrders. The above code is intercepting only the request. I tried changing to template.requestBody(request). But still no luck.
This error means you can't inject a bean: endpoint into a MockEndpoint.
If you want to "intercept" the call into your OrderHelper, you can use interceptSendToEndpoint in your route :
#EndpointInject(uri = "mock:intercepted")
MockEndpoint mockEndpoint;
...
#Override
protected RouteBuilder createRouteBuilder() {
return new RouteBuilder() {
#Override
public void configure() {
interceptSendToEndpoint("bean:orderHelper?method=getMarketplaceOrders")
.to("mock:intercepted");
from("direct:getMarketplaceOrders")
.to("bean:orderHelper?method=getMarketplaceOrders");
}
};
See : http://camel.apache.org/intercept.html
By updating my createRouteBuilder as shown below. I am able to intercept the response and send it to a mock endpoint where I can do the assertion.
#Override
protected RouteBuilder createRouteBuilder() {
return new RouteBuilder() {
#Override
public void configure() {
from("direct:getMarketplaceOrders").to("bean:orderHelper?method=getMarketplaceOrders").onCompletion()
.to("mock:intercepted");
}
};
}

Resources