I would like to access existing xml context inside java code for creating producer template. Is there any annotation or any other way to achieve.
#Context context
ProducerTemplate template = context.createProducerTemplate();
public void method(Exchange exchange) {
ProducerTemplate template = exchange.getContext().createProducerTemplate();
}
Context can be accessed from exchange.
Related
I'd like to know if it is possible to use Project Reactor with Apache Camel, so applications be fully reactive and non-blocking IO. I'd like to know how does the Project Reactor support works when integrating other Apache Camel's components.
Can I read for example from S3 reactively (therefore I'll need to use the Async S3 client behind the scenes)? Or will I block when reading from S3 and then just create a Flux out of what has been returned?
Where reactiveness is needed, you should use the relevant spring and reactor libraries. there are pseudo camel code also u can db call in camel bean or processors etc
#RestController
#RequestMapping(value = "/api/books")
#RequiredArgsContructor
public class HomeController {
private final BookRepository bookRepository;
private final ProducerTemplate template
#GetMapping("")
public Flux<Book> getHome() {
List <Book> books=bookRepository.findAll();
X ret = template.requestBody("direct:something", books, X.class);
}
}
#Component
public class SomeRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
from("direct:something")
.process(e-> {
List<Book> books = e.getIn.getBody(List.class)
// some logic
e.getIn.setBody(new X( ))
})
}
What is the proper way to use endpoint DSL and then reference the endpoint with ProducerTemplate? When creating a route and using endpoint DSL, it seems that Camel is creating a different uri for the endpoint. My EndpointRouteBuilder class:
#Component
public class MyRoutes extends EndpointRouteBuilder {
#Override
public void configure() throws Exception {
from(seda("STATUS_ENDPOINT"))
.routeId("stateChangeRoute")
.to(activemq("topic:statusTopic"))
}
}
and then injecting the endpoint to ProducerTemplate
#Component
public class StateChangePublisher {
#EndpointInject(value="seda:STATUS_ENDPOINT")
private ProducerTemplate producer;
public void publish(String str) {
try {
producer.sendBody(str);
} catch(CamelExecutionException e) {
e.printStackTrace();
}
}
}
When camel starts, I see two entries in the log:
o.a.camel.component.seda.SedaEndpoint : Endpoint seda:STATUS_ENDPOINT is using shared queue: seda:STATUS_ENDPOINT with size: 1000
o.a.camel.component.seda.SedaEndpoint : Endpoint seda://STATUS_ENDPOINT is using shared queue: seda://STATUS_ENDPOINT with size: 1000
The queue eventually fills up and nothing gets delivered to the "to" endpoint.
If I define the route without using the endpoint DSL method "seda()"
from("seda:STATUS_ENDPOINT")
then it works.
Is this a bug or am I doing something wrong?
I'm using camel 3.2.0 and
This was a bug in the endpoint dsl. Try upgrading to camel 3.3.0. I think it was fixed in the new release.
https://issues.apache.org/jira/browse/CAMEL-14859
How can I get multiple different ProducerTemplate instances with Auto-Configured Producer Templates? If I use the auto configured ProducerTemplate, how can I get multiple different ProducerTemplate instances?
For example, I need to use producertemplate to send different exchanges to different endpoints. In this case, do I need different producer template instances? If so, how can I do that?
Auto-Configured Consumer and Producer Templates
Camel auto-configuration provides pre-configured ConsumerTemplate and ProducerTemplate instances. You can simply inject them into your Spring-managed beans:
#Component
public class InvoiceProcessor {
#Autowired
private ProducerTemplate producerTemplate;
#Autowired
private ConsumerTemplate consumerTemplate;
public void processNextInvoice() {
Invoice invoice = consumerTemplate.receiveBody("jms:invoices", Invoice.class);
...
producerTemplate.sendBody("netty-http:http://invoicing.com/received/" + invoice.id());
}
}
You do not need different ProducerTemplates just to send messages to different endpoints. However, it can be convenient.
Send messages to whatever endpoint
Use the send* (InOnly) and request* (InOut) methods of ProducerTemplate that take the target endpoint URI as first argument.
template.sendBody("activemq:MyQueue", "<hello>world!</hello>");
template.requestBody("direct:MyEndpoint", "<hello>world!</hello>");
Inject multiple ProducerTemplates with Camel Annotation
See Camel docs about this for details.
#EndpointInject(uri = "activemq:MyQueue")
protected ProducerTemplate myQueueProducer;
#EndpointInject(uri = "direct:MyEndpoint")
protected ProducerTemplate myEndpointProducer;
Autowire multiple ProducerTemplates (Spring)
Since you want multiple instances of the same type, you have to inject them by name with the #Qualifier annotation. It would be better to configure the default endpoint in your Spring Bean configuration, I just added the setDefaultEndpointUri calls to show how to do it.
#Autowired
#Qualifier("myQueueProducer")
protected ProducerTemplate myQueueProducer;
#Autowired
#Qualifier("myEndpointProducer")
protected ProducerTemplate myEndpointProducer;
...
myQueueProducer.setDefaultEndpointUri("activemq:MyQueue")
myEndpointProducer.setDefaultEndpointUri("direct:MyEndpoint")
I am having this issue in my apache camel code which I am trying to resolve from last two days, but I could not resolve it.
I have two routes. First route is as below:
public class XXXRoute1 extends RouteBuilder {
public void configure() {
String endpointUri = "cxf:/XXX;
String logEndpoint = "log:" + XXX() + "?level=DEBUG";
from(endpointUri)
.to(logEndpoint).to(ROUTE2.ENDPOINT_URI)
.to(logEndpoint);
}
Second Route:(In second route , I am catching some exception through onException)
public class Route2 extends RouteBuilder {
public void configure() throws Exception{
String integrationEndpoint = "xxx.integration";
onException(RuntimeException.class).handled(true).onWhen(exceptionMessage().contains("Invalid")).bean(translator, "translateSomeError(${property.XXX})").end();
from(ENDPOINT_URI)
.
.
. so on
Now , In my case, the object which I am populating through onException
public SomeObjectResponse translateSomeError(Object someObject) throws Exception{
SomeObjectResponse someObjectResponse = new SomeObjectResponse();
someObjectResponse.setError("someError");
return someObjectResponse ;
}
However, In SOAP UI while testing I am getting an empty SOAP envelop
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body/>
</soap:Envelope>
I am using cxf component in apache camel.
Can you post your route completely ? Where you have the onException ?
Also before you use your custom class, can you try this ? Just want to make sure anything set at onException is propagated back to CXF endpoint:
onException(RuntimeException.class).handled(true).setBody().simple("</Unexpected exception> ");
The onException() block appears to be in your second route and is consequently not in scope of your first route.
Make the onException() block global or add it to your CXF route so it's in scope.
I'm using the Main class from Apache Camel to run it as standalone.
I need to use the JMS component so I have to add it to the CamelContext instance used by the Main class.
Of course I need to do that before calling main.run(args) method.
The problem is the following ...
Using main.getCamelContexts().get(0) returns an index out of bounds exception.
Using main.getOrCreateCamelContext() returns a valid CamelContext instance named "camel-1" to which I'm able to add my JMS component but .... when I execute main.run(args), another CamelContext named "camel-2" is used !
The only way I found to add my JMS component is to use :
main.bind("jms", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));
Is this the only way or the CamelContext way should work ?
Thanks,
Paolo.
You can provide completely own camel context to be used. To achieve that you can inherit org.apache.camel.main.Main and override only one method
protected Map<String, CamelContext> getCamelContextMap()
Here is the example of inherited body:
#Override
protected Map<String, CamelContext> getCamelContextMap() {
Map<String, CamelContext> camelContextMap = new HashMap<>();
DefaultCamelContext camelContext = new DefaultCamelContext();
camelContext.setName("MyContext");
// Add your context configuration here
camelContextMap.put("connectorContext", camelContext);
return camelContextMap;
}
In general it is better to create context map not in the "getCamelContextMap()" inherited method but somewhere in the constructor.
Old Question, but was able to figure it out - tried with camel 2.17.x version
private void runMyExample() {
//Add a Main Listener
main.addMainListener(new MyMainListener);
main.run();
}
public static class MyMainListener extends MainListenerSupport {
#Override
public void afterStart(MainSupport main) {
System.out.println("MainExample with Camel is now started!");
//This is the right instance
CamelContext context = main.getCamelContexts().get(0);
}
#Override
public void beforeStop(MainSupport main) {
System.out.println("MainExample with Camel is now being stopped!");
}
}
Regards,
R.