Apache camel process(processor) method is not being called - java

I saw in another post how manually adding the camel context and starting it should work, but it hasn't for me. I double checked the from, and to paths and they seem to be correct. Not sure why it's not calling the method and would appreciate some advice
public class CsvRouteBuilder extends DdsRouteBuilder {
private CsvConverterProcessor csvConverterProcessor;
private CamelContext camelContext;
#Autowired
public CsvRouteBuilder(CsvConverterProcessor csvConverterProcessor) throws Exception {
this.csvConverterProcessor = csvConverterProcessor;
camelContext.addRoutes(new RouteBuilder() {
#Override
public void configure() throws Exception {
from("{{input.files.csv}}")
.routeId("CSVConverter")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
System.out.println("hitting");
}
})
.to("{{output.files.csv}}");
}
});
camelContext.start();
}

The processor is not called simply because your route is not properly declared such that Spring Boot is not aware of it.
The proper way is to make your class extend RouteBuilder to define your route(s) and annotate your class with #Component to mark it as candidate for auto-detection when using annotation-based configuration and classpath scanning.
Your code should rather be something like this:
#Component
public class CsvRouteBuilder extends RouteBuilder {
#Override
public void configure() throws Exception {
from("{{input.files.csv}}")
.routeId("CSVConverter")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
System.out.println("hitting");
}
})
.to("{{output.files.csv}}");
}
}

Related

Apache camel Junit mock issue

I am writing a JUnit test case for a Route class. I'm facing a problem while mocking ServiceClass inside the Processor class.
public class SaveRouteTest extends CamelTestSupport {
private Exchange exchange;
protected ProducerTemplate template;
private SaveRequestBuilder saveRequestBuilder;
private SaveRoute route;
private SaveProcessor saveProcessor;
private ApplicationContext springContext = createApplicationContext();
#Mock
SaveServiceClient saveServiceClient;//Not able to mock this class
#BeforeClass
public void prepareTestCamelContext() throws Exception {
route = springContext.getBean("saveRoute", saveRoute.class);
saveProcessor = springContext.getBean("saveProcessor",
SaveProcessor.class);
saveRequestBuilder = springContext.getBean("saveRequestBuilder",
SaveRequestBuilder.class);
}
#BeforeMethod
public void init() throws SQLException, ServiceException {
MockitoAnnotations.initMocks(this);
exchange = new DefaultExchange(context);
}
#Override
protected RouteBuilder[] createRouteBuilders() throws Exception {
template = context.createProducerTemplate();
return new RouteBuilder[]{route};
}
#Test
public void testHotelCommitTransactionRouteSuccessReturn() throws
Exception {
when(saveServiceClient.invokeServiceWithName(anyObject()).
thenReturn("Response");
exchange.getIn().setBody("Request detail");
exchange = template.send("direct:SaveRoute",exchange);
}
protected ApplicationContext createApplicationContext() {
return new ClassPathXmlApplicationContext("classpath*:config/spring/testContext.xml");
}
}
#Component
public class SaveRoute extends SPRouteBuilder {
#Autowired
private SaveProcessor saveProcessor;
#Override
public void configure() throws Exception {
from("direct:SaveRoute")
.routeId("save")
.to("direct:ProcessSaveFlow")
.end();
from("direct:ProcessSaveFlow")
.process(saveProcessor)
.end();
}
}
public class SaveProcessor implements Processor {
#Autowired
SaveServiceClient saveServiceClient;
#Override
public void process(Exchange exchange) throws Exception {
//This line of code not able to mock
String response = saveServiceClient.invokeServiceWithName(exchange);
exchange.getIn().setBody(response);
}
}
How to resolve mocking of saveServiceClient.invokeServiceWithName? The debugger is always going inside this method. I tried using both mock objects and an injected mock. I can't make the method call directly.
You are creating a mock object, however you are not injecting it anywhere (normally you are doing it with #InjectMocks annotation - read about it).
I think there are several possibilities:
Provide a #MockBean object, which will be considered as a bean candidate in context.
There is a code example for mocking beans.
#RunWith ( CamelSpringRunner.class )
#SpringBootTest
public class RouteBuilderTest extends CamelSpringTestSupport {
#Autowired
private ApplicationContext applicationContext;
#MockBean
private ServiceClient serviceClient;
#Override
public void setUp() throws Exception {
MockitoAnnotations.initMocks( this );
super.setUp();
}
#Override
public void tearDown() {
}
#Test
public void test() {
when( serviceClient.doStuff() ).thenReturn( "mockedResponse" );
}
}
Mock SaveProcessor and inject it to Route class - you shouldn't take care of ServiceClient, because you are trying to test too much. Tests for SaveProcessor should be separated, tests for route don't need this logic.

Camel: Mock a processor to test Route

I am trying to create a unit test for the routing.
I have the following route configuration
from ("direct:getA")
.routeId("get-a").startupOrder(1)
.process(exchange -> {
QueryObject queryObject = exchange.getIn().getBody(QueryObject.class);
exchange.getIn().setHeader(foo, queryObject.getH());
exchange.setOut(exchange.getIn());
})
.choice()
.when(header(foo).isEqualTo(fooConstant.bar))
.process("barProcessor")
.when(header(foo).isEqualTo(fooConstant.bie))
.process("bieProcessor")
.end();
My question is, how can I mock "barProcessor" and "bieProcessor"?
I tried to use adviceWith but I could not retrieve the routeDefinition. The context.getRouteDefinitions() returns an empty list.
Edit:
Below is the code snippet from my test.
RouteDefinition routeDef = context.getRouteDefinition("get-a");
routeDef.adviceWith(context, new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception {
interceptSendToEndpoint("*barProcessor*").process(
new Processor() {
#Override
public void process(Exchange exchange) {
System.out.println("bar");
}
}
);
interceptSendToEndpoint("*bieProcessor*").process(
new Processor() {
#Override
public void process(Exchange exchange) {
System.out.println("Bie");
}
}
);
}
});
String request = <JSON Request>;
websocket.sendTest(request);
But the context.getRouteDefinition("get-a"); is returning null. And when I also used context.getRouteDefinitions(), it returns an empty list.
I found the cause of this issue.
I forgot to Override the createRouteBuilder and createJndiContext.
#Override
protected RouteBuilder createRouteBuilder() {
return new SampleRoute(<param>);
}
#Override
protected JndiContext createJndiContext() throws Exception {
JndiContext context = new JndiContext();
context.bind("barProcessor", new BarProcessor());
context.bind("bieProcessor", new BieProcessor());
return context;
}
I found the solution from this link: Unit Test

Ways to mock Camel Endpoint POJO producer

I followed guide here, and I was successfully able to configure a producer on my bean endpoint like this:
#Produce( uri = "activemq:foo" )
private MyListener myListener;
MyListener is:
public interface MyListener {
#InOnly
public void send( String message );
}
and my bean:
public class MyBeanEndpoint {
#Produce( uri = "activemq:foo" )
private MyListener myListener;
#Handler
public void doSomething( final Object body ) {
...
}
public void setMyListener( final MyListener myListener ) {
this.myListener = myListener;
}
Now, how can I test this?
I mean: my test extends CamelTestSupport and I configured my routes with
#Override
public RouteBuilder createRouteBuilder() {
return new RouteBuilder() { ... }
That is: I've reproduced camel context, but I've NO spring context configured and I want (if possible) to avoid instantiating it.
How can I mock producer or make Camel instantiate and inject this bean into my bean endpoint?
What is the best way to test such situation using Apache Camel features like CamelTestSupport and similar utilities?
My reference test is:
public class Test extends CamelTestSupport {
private static BeanEndpoint beanEndpoint
#BeforeClass
public static void init() {
beanEndpoint.setActivemqMyListener( ??? );
}
#Override
public CamelContext createCamelContext() {
context = new DefaultCamelContext();
context.addComponent( "activemq", new SedaComponent() );
return context;
}
#Override
public RouteBuilder createRouteBuilder() {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
from( "activemq:foo" )
.to( "mock:out" );
}
};
}
#Test
public void testFooQueue() throws Exception {}
Let Camel create your bean, then the various dependency injection and whatnot is configured for you.
private static BeanEndpoint beanEndpoint
...
beanEndpoint = camelContext.getInjector().newInstance(BeanEndpoint.class);

Camel and ActiveMQ

I´m very new on the camel world, that is why I´m asking for your help.
Let me tell you what I would like to do:
I have this basic Camel standalone project:
package maventest1;
public class JmsToSql {
private Main main;
public static void main(String[] args) throws Exception {
JmsToSql example = new JmsToSql();
example.boot();
}
public void boot() throws Exception {
main = new Main();
main.enableHangupSupport();
main.bind("foo", new MyBean());
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
main.bind("test-jms",JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));
main.addRouteBuilder(new MyRouteBuilder());
main.run();
}
private static class MyRouteBuilder extends RouteBuilder {
#Override
public void configure() throws Exception {
from("timer:foo?delay=2000")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
//NOT SURE THIS IS THE RIGHT WAY
from("test-jms:queue:order1")
.to("test-jms:queue:order2");
}
})
.beanRef("foo");
}
}
public static class MyBean {
public void callMe() {
System.out.println("MyBean.calleMe method has been called");
}
}
}
All I want to do is read all the messages from an activeMQ queue and pass them into another queue. Does anybody know how I can do this?
Thanks in advance =D
Just do a route from JMS to JMS
private static class MyRouteBuilder extends RouteBuilder {
#Override
public void configure() throws Exception {
from("test-jms:queue:order1")
.to("test-jms:queue:order2");
}
As you are new to Camel, I recommend to also read this article first
http://java.dzone.com/articles/open-source-integration-apache
And if you want to have great documentation and tutorials, then pickup one of the Camel books
http://camel.apache.org/books

How to test multiple RouteBuilders in Apache Camel

I want to test multiple camel RouteBuilder in a single unit test
what I have:
Custom camel processor that changes state
public class MyProcessor implements Processor {
MyState state;
public MyProcessor(MyState state) {this.state = state;}
#Override
public void process(Exchange exchange) throws Exception {
state.setState(state.getState() + 5);
}}
Two simple RouteBuilders: first routes messages from "direct:start" to "direct:endroute1" second pick up messages from "direct:endroute1" and routes somewhere "mock:endroute2"
public class MyRouteBuilder1 extends RouteBuilder {
MyState state;
public MyRouteBuilder1(MyState state) {this.state = state;}
#Override
public void configure() throws Exception {
from("direct:start").process(new MyProcessor(state)).to("direct:endroute1");
}}
public class MyRouteBuilder2 extends RouteBuilder {
MyState state;
public MyRouteBuilder2(MyState state) {this.state = state;}
#Override
public void configure() throws Exception {
from("direct:endroute1").process(new MyProcessor(state)).to("mock:endroute2");
}}
Writing unit test for a single route builder is straightforward:
public class MyTest extends CamelTestSupport {
MyState state = new MyStateImpl();
#EndpointInject(uri = "mock:result")
protected MockEndpoint resultEndpoint;
#Test
public void testSingleRoute() throws Exception {
resultEndpoint.expectedMessageCount(1);
template.sendBody("direct:start", new Object());
assertTrue(state.getState() == 5);
resultEndpoint.assertIsSatisfied();
}
#Override
protected RouteBuilder createRouteBuilder() {
return new MyRouteBuilder1(state) {
public void configure() throws Exception{
super.configure();
from("direct:endroute1").to("mock:result");
}
};
}
}
What I really want to do is somehow to override CamelTestSupport.createRouteBuilder that will test whole chain of message processing from direct:start to mock:endroute2. As a result state.getState() should be 10
Try to override method:
protected RouteBuilder[] createRouteBuilders() {...}
from CamelTestSupport. It's available since version 2.17
you can just add multiple RouteBuilders to the context using the context.addRoutes(RouteBuilder) API
see this unit test for an example:
https://svn.apache.org/repos/asf/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/AddRoutesAtRuntimeTest.java
You could use one RouteBuilder including the routes of multiple other RouteBuilders.

Categories