apache cxf interceptor attributes - cxf

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.

Related

#AfterReturning from ExceptionHandler not working

I have a GlobalExceptionHandler class which contain multiple methods annotated with #ExceptionHandler.
#ExceptionHandler({ AccessDeniedException.class })
public final ResponseEntity<Object> handleAccessDeniedException(
Exception ex, WebRequest request) {
return new ResponseEntity<Object>(
"Access denied message here", new HttpHeaders(), HttpStatus.FORBIDDEN);
}
I have a AOP which is suppose to be triggered after the exception handler returns response.
#AfterReturning(value="#annotation(exceptionHandler)",returning="response")
public void afterReturningAdvice(JoinPoint joinPoint, Object response) {
//do something
}
But the #AfterReturning is not triggered after the handler returns a valid response.
Tried full qualified name but not working
#AfterReturning(value = "#annotation(org.springframework.web.bind.annotation.ExceptionHandler)", returning = "response"){
public void afterReturningAdvice(JoinPoint joinPoint, Object response) {
//do something
}
Please go through the documentation to understand the proxying mechanisms in Spring framework.
Assuming the ExceptionHandler code written was of the following format
#ControllerAdvice
public class TestControllerAdvice {
#ExceptionHandler({ AccessDeniedException.class })
final public ResponseEntity<Object> handleAccessDeniedException(
Exception ex, WebRequest request) {
return new ResponseEntity<Object>(
"Access denied message here", new HttpHeaders(), HttpStatus.FORBIDDEN);
}
}
key points from the documentation pertaining to the question are
Spring AOP uses either JDK dynamic proxies or CGLIB to create the
proxy for a given target object.
If the target object to be proxied implements at least one
interface, a JDK dynamic proxy is used. All of the interfaces
implemented by the target type are proxied. If the target object
does not implement any interfaces, a CGLIB proxy is created.
With CGLIB, final methods cannot be advised, as they cannot be overridden in runtime-generated subclasses.
OP identified the issue based on the comments and hints , this answer is for any future references.

Using Camel Endpoint DSL with #EndpointInject creating different endpoints

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

Apache camel cxf endpoint - specify http(s) proxy?

I have been trying to set up a CXF endpoint in Camel, using spring java config like so:
#Bean
public CxfEndpoint anEndpoint() {
CxfEndpoint endpoint = new CxfEndpoint();
endpoint.setAddress(getEndpointUrl());
endpoint.setServiceClass(ServiceSOAP.class);
endpoint.setWsdlURL("/wsdl/ServiceSOAP.wsdl");
String httpProxyHost = httpProxyHost();
String httpProxyPort = httpProxyPort();
Map<String, Object> properties = new HashMap<>();
properties.put("https.proxyHost", httpProxyHost());
properties.put("https.proxyPort", httpProxyPort());
properties.put("http.proxyHost", httpProxyHost());
properties.put("http.proxyPort", httpProxyPort());
endpoint.setProperties(properties);
return endpoint;
}
However, this is not working on either http or https endpoint urls.
I have also tried setting these properties on CamelContext directly with the same result.
The route is working fine in the environment with a direct connection to the internet, e.g., locally, but not where it is deployed behind an http proxy.
We're using apache camel 2.15.2 and apache cxf 3.1.0. Any help is greatly appreciated!
The resolution turned out to be simple if tortuous to figure out. One has to use a CxfEndpointConfigurator to set up HTTPConduit properties like so:
#Bean
public CxfEndpoint anEndpoint() {
CxfEndpoint endpoint = new CxfEndpoint();
endpoint.setAddress(getEndpointUrl());
endpoint.setServiceClass(ServiceSOAP.class);
endpoint.setWsdlURL("/wsdl/ServiceSOAP.wsdl");
endpoint.setCxfEndpointConfigurer(anEndpointClientConfigurer());
return endpoint;
}
private CxfEndpointConfigurer anEndpointClientConfigurer() {
return new CxfEndpointConfigurer() {
#Override
public void configure(AbstractWSDLBasedEndpointFactory factoryBean) {
}
#Override
public void configureClient(Client client) {
HTTPConduit conduit = (HTTPConduit) client.getConduit();
HTTPClientPolicy policy = new HTTPClientPolicy();
policy.setProxyServer(httpProxyHost());
policy.setProxyServerPort(httpProxyPort());
conduit.setClient(policy);
}
}
References: 1 and 2

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();
...
}

camel-cxfrs with custom http headers

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)...

Resources