camel-cxfrs with custom http headers - cxf

I have a route that defines a CXFRS endpoint. I need to retrieve custom HTTP header values from the inbound request...
from(CXF_RS_ENDPOINT_URI)
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
Message inMessage = exchange.getIn();
System.out.println("headers->" + inMessage.getHeaders());
...
here is my unit test code to simulate a client request...
HttpGet get = new HttpGet("http://localhost:9000/rest/customerservice/customers/126");
get.addHeader("myHeader", "1234");
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(get);
The problem is that the custom header "myHeader" is unavailable from my route. Is there another way to get to it?
From looking at the camel-cxf source code, I can see that the default header strategy/binding logic only sets up predefined HTTP headers. Is there a reason why other headers aren't passed through as well?
Either way, what is the best approach to override this behavior?
thanks

After more investigating, this was found to be a bug in CAMEL-CXF. It has been fixed to support custom headers in the Camel trunk (slated for 2.5 release)...

Related

Lost Header values in Camel route while testing using RouteReifer.adviceWith(..)

Using camel 3.4.4, I've a route that calls a cxf endpoint with .to(getCxfEndpoint()) and I've a header that's set earlier in the route like process(exchange -> exchange.getIn().setHeader("myKey", "myValue"):
from(someEndpoint)
.process(exchange -> exchange.getIn().setHeader("myKey", "myValue")
.to(getCxfEndpoint())
.process(exchange -> String value = exchange.getIn().getHeader("myKey");
I'm trying to unit test this using the following:
RouteReifer.adviceWith(routeDefinition, mcc, new AdviceWithRouteBuilder() {
#Override
public void configure() {
weaveByString("To[http://myurl.com/xxx").replace()
process(exchange -> {
log.debug("Assume external call is made and I can see the headers in exchange here");
});
}
});
But in the route, when I try to get the header exchange.getIn().getHeader("myKey"), it's null. This only happens in test - it actually works when you run the real route. I'm unable to figure out why the header is lost after I mock the call using weaveByString. Also the headers are still present in the lambda in process above.
Thanks in advance.

Can I know which endpoint is finally targeted when using load balancer?

I have a route using a customized load balancer as,
from("timer://myTimer?period=2000")
.loadBalance(new MyCustomLoadBalancer())
.to("mock:em1").to("mock:em2").to("mock:em3")
.end();
In the customized balancer class, it seems only processors can be gotten.
public class MyCustomLoadBalancer extends SimpleLoadBalancerSupport {
public void process(Exchange exchange) throws Exception {
List<Processor> pList = getProcessors();
.......
//It is wanted to log which endpoint is finally targeted.
foo.process(exchange);
}
}
But here, I want to log actually which endpoint is targeted when using this load balancer.
In product environment, Jetty or HTTP endpoints will be used instead of these mock endpoints.
Is there a way to realized this?
===================================================================
Based on the suggestion from Ibsen, I used the Jetty endpoint to do test.
from("jetty:http://0.0.0.0:8043?matchOnUriPrefix=true")
.loadBalance(new MyCustomLoadBalancer())
.to("jetty:http://localhost:80?bridgeEndpoint=true&throwExceptionOnFailure=false")
.to("jetty:http://www.google.com?bridgeEndpoint=true&throwExceptionOnFailure=false")
.end();
But the Processors are not class of SendProcessor("foo instanceof SendProcessor" returns false), so I can't get the endpoint by getDestination.
I believe there should be some relationship between the endpoint and processor.
Could you give me more help?
Thanks.
The Processor is a SendProcessor where you can get the endpoint it will send the exchange to.
if (foo instanceof SendProcessor) {
SendProcessor send = (SendProcessor) foo;
Endpoint dest = send.getDestination();
...
}

Apache Camel: Response is get lost when reached explicitly on route

I am getting a strange situation at the code below which simply routes request to Google and returns response.
It works well but when I activate the line commented out as "//Activating this line causes empty response on browser" to print out returned response from http endpoint (Google), response is disappear, nothing is displayed on browser. I thought it might be related with input stream of http response which can be consumed only once and I activated Stream Caching on context but nothing changed.
Apache Camel version is 2.11.0
Any suggestions are greatly appreciated, thanks in advance.
public class GoogleCaller {
public static void main(String[] args) throws Exception {
CamelContext context = new DefaultCamelContext();
context.addRoutes(new RouteBuilder() {
public void configure() {
from("jetty:http://0.0.0.0:8081/myapp/")
.to("jetty://http://www.google.com?bridgeEndpoint=true&throwExceptionOnFailure=false")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
System.out.println("Response received from Google, is streamCaching = " + exchange.getContext().isStreamCaching());
System.out.println("----------------------------------------------IN MESSAGE--------------------------------------------------------------");
System.out.println(exchange.getIn().getBody(String.class));
System.out.println("----------------------------------------------OUT MESSAGE--------------------------------------------------------------");
//System.out.println(exchange.getOut().getBody(String.class)); //Activating this line causes empty response on browser
}
});
}
});
context.setTracing(true);
context.setStreamCaching(true);
context.start();
}
}
As you use a custom processor to process the message, you should keep it in mind the in message of the exchange has response message from the google, if you are using exchange.getOut(), camel will create a new empty out message for you and treat it as response message.
Because you don't set the out message body in the processor, it makes sense that you get the empty response in the browser.

Setting custom Soap-Header to pojo-message in Camel-CXF

I have a Problem with cxf soap-headers. I set up an cxf-project with the Contract-firs-development method. I want to call a web-service with an cxf-component, which looks like this.
<cxf:cxfEndpoint id="ICCSCustomerService"
address="http://localhost:8080/iccs-xsoap/CustomerService/updateCustomer"
serviceClass="de.iccs.xsoap.customer.v1.CustomerServiceImpl" >
</cxf:cxfEndpoint>
I want to send an pojo-message throw an direct-component as an request for the ws. My route looks like this:
<route id="CustomerServiceUpdateCustomerTest">
<camel:from uri="direct:iccsUpdateCustomerRequest"/>
<camel:process ref="addCredentials"/>
<to uri="cxf:bean:ICCSCustomerService"/>
<camel:to uri="stream:out"/>
</route>
I need to implement a soap header like this one:
<ns2:Header>
<simpleAuth xmlns="http://xsoap.iccs.de/v1" password="abc" username="xxx"/>
</ns2:Header>
To archive this I wrote an processor like this one (see also example at http://camel.apache.org/cxf.html):
#Override
public void process(Exchange exchange) throws Exception {
List<SoapHeader> soapHeaders = CastUtils.cast((List<?)exchange.getOut().getHeader(Header.HEADER_LIST));
// Insert a new header
String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><outofbandHeader "
+ "xmlns=\"http://cxf.apache.org/outofband/Header\" hdrAttribute=\"testHdrAttribute\" "
+ "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" soap:mustUnderstand=\"1\">"
+ "<name>simpleAuth username=\"xxx\" password=\"abc\" xmlns=\"http://xsoap.iccs.de/v1\"</name></outofbandHeader>";
SoapHeader newHeader = new SoapHeader(new QName("http://xsoap.iccs.de/v1", "simpleAuth"),
DOMUtils.readXml(new StringReader(xml)).getDocumentElement());
// make sure direction is OUT since it is a response message.
newHeader.setDirection(Direction.DIRECTION_OUT);
//newHeader.setMustUnderstand(false);
soapHeaders.add(newHeader);
}
Unfortunately I get an null-pointer Exception in this statement:
List soapHeaders = CastUtils.cast((List
Obviously there are no soap-headers in this message. And it seems not to be an soap message at all.
Marschaling like this
<camel:marshal>
<soapjaxb contextPath="de.iccs.xsoap.customer.v1" />
</camel:marshal>
<camel:process ref="addCredentials"/>
does not work, as it produces only an soap-envelope without an soap-header. (and of corse this dosen't work as cxf-endpoint works in pogo-mode)
Could you provide me an example how to set an soap message (with soap-header) from an pojo-message.
Thank you
Gabriel
Don't know if you solved your problem already, but I experienced something similar as well, so maybe someone will benefit.
If your NPE is due to there being no existing headers, it is perfectly acceptable to create a new list if needed.
if (message.getHeader(Header.HEADER_LIST) == null) {
message.setHeader(Header.HEADER_LIST, new ArrayList<SoapHeader>());
}
But you may have another problem with the hand-crafted XML being used to populate the SoapHeader. You're still using the outofbandHeader element from the original CXF example; this is a specific header in the example, not a general wrapper for out-of-band headers. Also, your simpleAuth is not marked up as an element (although it's difficult to read...).
If you have annotated class (generated or created) with an #XMLRootElement for your simpleAuth element, you can use the SoapHeader constructor that takes a JAXBDataBinding.
CXF will marshal the header for you.
#Override
public void process(Exchange exchange) throws Exception {
Message in = exchange.getIn();
if (in.getHeader(Header.HEADER_LIST) == null) {
in.setHeader(Header.HEADER_LIST, new ArrayList<SoapHeader>());
}
List<SoapHeader> headers = CastUtils.cast((List<?>)in.getHeader(Header.HEADER_LIST));
SimpleAuth auth = new SimpleAuth();
auth.setUsername("xxx");
auth.setPassword("abc");
try {
SoapHeader header = new SoapHeader(new QName("http://xsoap.iccs.de/v1", "simpleAuth"),
auth, new JAXBDataBinding(SimpleAuth.class));
header.setDirection(Direction.DIRECTION_OUT);
header.setMustUnderstand(true);
soapHeaders.add(header);
} catch (JAXBException e) {
e.printStackTrace();
}
}

apache cxf interceptor attributes

I have the following interceptor
public class MyInterceptorextends AbstractPhaseInterceptor<Message>{
public void handleMessage(Message message) throws Fault {
message.put("myatt", "value");
}
}
And I'm creating a JAXWS Client proxy
CalculatorService proxy = JAXRSClientFactory.create("http://eisoukr.victoria-insbg.com/API", CalculatorService.class, providers);
ClientConfiguration config = WebClient.getConfig(proxy);
config.getInInterceptors().add(new MyInterceptor());
How can I read the "myatt" attribute from the proxy or is there another way to exchange attributes between the proxy and the interceptor?
There is a ClientConfiguration has a getResponseContext() method on it that can be used to retrieve the various properties set on the message.

Resources