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
Related
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}}");
}
}
I'm new to camel.
When I get the request to the endpoint, the camel flow should be started. RequestBody is the input to the flow (InputA).
Please let me know how to start this:
InputA -> ProcessA -> OutputA
OutputA -> ProcessB -> OutputB
OutputB -> ProcessC -> OutputC
Just as an example:
public class ProcessA{
public String methodA(String arg){
return arg;
}
}
public class ProcessB{
public String methodB(String arg){
return arg;
}
}
public class ProcessC{
public String methodC(String arg){
return arg;
}
}
How to flow the input and output using Camel data flow.
Any help or links will be appreciated.
I advice you to read the book Camel in action. There are a lot of examples, source code is also awailable. When i started to study camel, I found this book very useful.
Also In addition to Cluas answer i can add an example:
public class Example
{
public static void main(String[] args) throws Exception
{
CamelContext context = new DefaultCamelContext();
context.addRoutes(new RouteBuilder()
{
#Override
public void configure() throws Exception
{
from("InputA").process(exchange -> {
//This is process A.
}).to("OutputA");
from("OutputA").process(exchange -> {
//This is process B.
}).to("OutputB");
from("OutputB").process(exchange -> {
//This is process C.
}).to("OutputC");
}
});
context.start();
//let camel complite his job
Thread.sleep(2000);
context.stop();
}
}
You can build 3 Camel routes, and then use some queue component to separate them, such as the internal direct (no queue by direct method invocation) or seda queues.
Pseudo routes would be something like:
from("someInput").process(...).to("seda:a")
from("seda:a").process(...).to("seda:b");
from("seda:b").process(...).to("seda:c");
Let's say you read the Json from a file and you want to process it inside a processor. Something like this:
from("file:/C:/TEST/")
.process(new MyProcessor())
.to("direct:anotherRouter");
MyProcessor class is a special kind of class that implements Processor. You need to override the process method.
public class MyProcessor implements Processor{
#Override
public void process(Exchange exchange) throws Exception {
}
}
In a camel route, the data is in the body. To get the data in a processor you should get it from the body. In the example, it is something like this
public class MyProcessor implements Processor{
#Override
public void process(Exchange exchange) throws Exception {
String data = exchange.getIn().getBody(String.class);
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(data);
//TODO: All the stuff you want to do with the data.
}
}
I am using Hystrix to improve my services. How can I decapsulate the service calls into Hystrix. I know you can create for each call a special hystrix-class, but this would be too much work without using Spring!
I try to describe my problem with pseudocode:
public class HystrixController extends HystrixCommand {
public static void main(String[] args) throws Exception {
HystrixController hystrixController = new HystrixController();
System.out.print(hystrixController.execute());
}
private final ExampleService exampleService;
protected HystrixController() throws Exception {
super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
this.exampleService = new ExampleService();
}
// Call 1
public List getItemsAsList() {
return exampleService.getItemsByContractId(contractID);
}
// Call 2
public List getItemsByName() {
return exampleService.getItemsByName(contractID);
}
// How can I isolate the two calls ? The run() only allows me to use one.
#Override
protected List run() throws Exception {
return getItemsAsList();
}
}
In the example you can see it is only possible to execute only one call. I would like to have something like that:
public class HystrixController extends HystrixCommand {
public static void main(String[] args) throws Exception {
HystrixController hystrixController = new HystrixController();
System.out.print(hystrixController.execute(1));
System.out.print(hystrixController.execute(2));
}
private final ExampleService exampleService;
protected HystrixController() throws Exception {
super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
this.exampleService = new ExampleService();
}
// Call 1
public List getItemsAsList() {
return exampleService.getItemsByContractId(contractID);
}
// Call 2
public List getItemsByName() {
return exampleService.getItemsByName(contractID);
}
// Multi Threads
#Override
protected List run_getItemsAsList() throws Exception {
return getItemsAsList();
}
#Override
protected List run_getItemsByName() throws Exception {
return getItemsByName();
}
}
Thanks you in advance and I am sorry for my broken English
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);
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.