I want to perform a post using netty4 in camel but its returning bad request 400, i have tried many permutations of http options to see if any work but the result is same (as consumer its working but as producer its not)
#Component
public class RestDslRouteBuilder extends RouteBuilder {
#Override
public void configure() throws Exception {
restConfiguration()
.component("netty4-http")
.host("localhost").port("8686")
.enableCORS(true)
.corsHeaderProperty("Access-Control-Allow-Origin", "*")
.corsHeaderProperty("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
.bindingMode(RestBindingMode.json);
rest("/api")
.get("/")
.to("bean:helloBean")
.post().type(PostRequestType.class)
.to("bean:postBean");
/*from("netty4-http:http://localhost:8686/foo")
.transform().constant("Bye World");
*/
from("netty4-http:http://localhost:8686/foo")
.log("Logged id issue without body: ${header.id}")
.to("netty4-http:http://ptsv2.com/t/8wl8p-1547734804/post?bridgeEndpoint=true");
}
Related
Issue:
I have multiple route sending messages to an ActiveMQ queue which later gets processed by a processor to save status information
The same message sending from ProducerTemplate to ActiveMQ queue somehow breakes the same code by not triggering logs on console, and saving status information to a randomly generated file name.
Desired Behavior:
Both sending method gets the messages processed the same way
Code Explanation:
On below codes the Save processor is the one producing the weird behavior where logs dont show up on console and writes to some random file, file name is basically the clientID from ActiveMQ
StartRoute calling the activemq:save works correctly
Code:
public class Save implements Processor {
public void process(Exchange exchange) throws Exception {
try {
Map<String, Object> map = new HashMap<String, Object>() {};
map.put(".....", ".....");
map.put(".....", ".....");
map.put(".....", ".....");
map.put(".....", ".....");
ProducerTemplate template = exchange.getContext().createProducerTemplate();
String response = template.requestBodyAndHeaders("activemq:save", "Batch Job Started", map, String.class);
FluentProducerTemplate FluentTemplate = exchange.getContext().createFluentProducerTemplate();
String result = FluentTemplate
.withHeader(".....", ".....")
.withHeader(".....", ".....")
.withHeader(".....", ".....")
.withHeader(".....", ".....")
.withHeader(".....", ".....")
.to("activemq:save")
.request(String.class);
} catch (Exception e) {
.....
}
}
}
public class StartRoute extends RouteBuilder {
restConfiguration()
.component("servlet")
.enableCORS(true);
rest("/start").id("start")
.post("/{filename}")
.route()
.....
.process(new Save())
.wireTap(startBackgroundProcessRoute)
.to("activemq:save")
.endRest();
}
public class SaveRoute extends RouteBuilder {
from("activemq:save")
.log("started saving")
.process(new FormatText())
.to("file:///status");
}
This question came from my original problem described here:
Camel Multicast Route call order
Solution can be found also there:
Camel Multicast Route call order
However to satisfy this question:
It seems Camel have few bugs regarding producer templates and maybe ActiveMQ, this is my initial conclusion.
The Only way i was able to use ProducerTemplate without issue is to use the send function with Exchanges, send() sends the messages correctly to the ActiveMQ same way as the to() however for whatever reason the content was still not written to the file.
After I dropped the ActiveMQ between the routes, everything started to work consistently. So possible miss configuration on ActiveMQ component or possible another camel framework bug.
If anyone knows the exact answer i would be happy to hear / see the reason for this behavior.
Code example:
public class SaveProcessor implements Processor {
public void process(Exchange exchange) throws Exception {
ProducerTemplate template = exchange.getContext().createProducerTemplate();
template.send(Utilities.trackBatchJobStatus, exchange);
/** NOTE
* DO NOT USE any other functions which are not working with EXCHANGES.
* Functions that uses body, header values and such are bugged
*/
}
}
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
To retrieve some open data from a remote web server to process, I'm trying out Apache Camel.
The problem is that it seems that the data is never received. I have tried the jetty, ahc and cxf components but can't get it to work. For example like this:
import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
public class CamelHttpDemo {
public static void main(final String... args) {
final CamelContext context = new DefaultCamelContext();
try {
context.addRoutes(new RouteBuilder() {
#Override
public void configure() throws Exception {
this.from("direct:start")
.to("ahc:http://camel.apache.org/")
.process(exchange -> {
System.out.println(exchange);
});
}
});
context.start();
Thread.sleep(10000);
context.stop();
} catch (final Exception e) {
e.printStackTrace();
}
}
}
No output is written so the line System.out.println(exchange); is never executed and I assume the data is not retrieved.
I'm using the most recent version of Apache Camel, 2.17.1.
You need some message producer in your route to emit Exchange that would trigger the http component. Your route starts with direct:start which cannot emit new Exchanges, it just sits and waits for someone to initiate the process.
The easiest way to make your route work is to replace direct:start with some producer. For instance, replacing it with this timer .from("timer://foo?fixedRate=true&period=10000") will trigger your http-request once every 10 seconds.
If you want to initiate the request manually, you need to create a ProducerTemplate and use it to send a message to direct:start. That would be:
ProducerTemplate template = context.createProducerTemplate();
template.sendMessage("direct:start", "Message body");
In wildfly 8.1 with REST services, I wanted to implement CORS ContainerRequestFilter and ContainerResponseFilter.
My request filter is working properly but ContainerResponseFilter never gets loaded nor called
package org.test.rest;
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.ext.Provider;
#Provider
#PreMatching // <-- EDIT : This was my mistake ! DO NOT ADD THIS
public class CorsResponseFilter implements ContainerResponseFilter {
public CorsResponseFilter() {
System.out.println("CorsResponseFilter.init");
}
#Override
public void filter(ContainerRequestContext req,
ContainerResponseContext resp) throws IOException {
System.out.println("CorsResponseFilter.filter");
resp.getHeaders().add("Access-Control-Allow-Origin", "*");
resp.getHeaders().add("Access-Control-Allow-Credentials", "true");
resp.getHeaders().add("Access-Control-Allow-Methods",
"GET, POST, DELETE, PUT");
resp.getHeaders().add("Access-Control-Allow-Headers",
"Content-Type, Accept");
}
}
This seems to me as a Wildfly / resteasy bug. Do you have another idea / am I missing something ?
You are mixing ContainerRequestFilter and ContainerResponseFilter in your question. As you want to send additional Headers to the client the ContainerResponseFilter is the right one.
The #PreMatching annotation can be applied to a ContainerRequestFilter "to indicate that such filter should be applied globally on all resources in the application before the actual resource matching occurs".
Adding it to a ContainerResponseFilter does not make sense. Just remove the annotation and your filter should work.
I would like to set up a Camel CXF endpont, and have the SOAP response asynchronous to much of my Camel Route. The route will have a lot of processing steps, and I do not want to have the response generated at the very end.
An example endpoint:
<cxf:cxfEndpoint id="someEndpoint"
address="/Service"
serviceClass="com.SomeImpl" />
An example route:
public class MyRouteBuilder extends RouteBuilder {
#Override
public void configure() throws Exception {
from("cxf:bean:someEndpoint")
to("bean:processingStep1")
to("bean:replyToSOAP") // I would like to respond to cxf:cxfEndpoint here!
to("bean:processingStep2")
to("bean:processingStep3")
to("bean:processingStep4");
// The response to cxf:cxfEndpoint actually happens here.
}
}
I have tried many options in MyRouteBuilder to "fork" the process (i.e. bean:replyToSOAP):
.multicast().parallelProcessing()
In-memory Asynchronous messaging ("seda" and "vm")
I have NOT tried JMS. It could be overkill for what I want to do.
I can get the route steps to process in parallel, but all steps must be completed before the response is generated.
In addition to the answer Claus gives below, I'd like to add that the placement of wireTap is important. Using:
.wireTap("bean:replyToSOAP")
will not get the desired behavior. What will is:
public class MyRouteBuilder extends RouteBuilder {
#Override
public void configure() throws Exception {
from("cxf:bean:someEndpoint")
to("bean:processingStep1")
.wireTap("direct:furtherProcessing")
to("bean:replyToSOAP") // respond to cxf:cxfEndpoint here
from("direct:furtherProcessing") // steps happen independantly of beann:replyToSOAP
to("bean:processingStep2")
to("bean:processingStep3")
to("bean:processingStep4");
}
}
There is the WireTap EIP which can spin of a copy of the message to be processed independently from the current route: http://camel.apache.org/wire-tap