Hello everyone, This is my first foray into Camel. I am looking into alternatives to MuleSoft ever since they released Mule 4.0 and dropped tooling for the Community Edition.
My main question is how to configure a CXF client in Camel with UsernameToken authentication. (I have more questions besides this, but I'll start here.) My task is to synchronize contact information between our local system and a third-party service using SOAP. Here is the basic flow: - Read JSON objects from RabbitMQ - Convert Objects to JAXB Objects required for third-party service - POST objects to SOAP service I am able to read from the RabbitMQ instance, but I am confused on how to use CXF to access the remote service. Most of the information I see concerns using CXF as a service rather than as a client. Here is what I have so far: // Application.java public class Application { private static CamelContext context; public static void main(String args[]) throws Exception { context = new DefaultCamelContext(); context.addRoutes(new MyRouteBuilder()); context.start(); } } //MyRouteBuilder.java public class MyRouteBuilder extends RouteBuilder { @Override public void configure() throws Exception { from("rabbitmq:...") .to("direct:start"); JsonDataFormat jsonDataFormat = new JsonDataFormat(); jsonDataFormat.setLibrary(JsonLibrary.Jackson); jsonDataFormat.setUnmarshalType(ContactInfo.class); from("direct:start") .unmarshal(jsonDataFormat) .process(new ContactInfoToOSCContactProcessor()) // returns a JAXB Object generated by service WSDL .choice() ... .to("direct:updatecontact"); String contactServiceUri = "cxf://https://thirdparty.example.com/ContactService" + "?serviceClass=" + ContactService.class.getCanonicalName() + "&wsdlURL=contactservice.wsdl"; from("direct:updatecontact") .setHeader("operationName", constant("updateContact")) .to(contactServiceUri) .unmarshal(soapDF) .log("The response was ${body[0]}"); } } >From here, I get an error: > org.apache.cxf.ws.policy.PolicyException: A encryption username needs to be > declared. Makes sense, because I need to set the UsernameToken for the request. I am pretty sure that with CXF, I need to add an outgoing interceptors like this, so I tried creating a CXF Endpoint from the Camel Context and modifying it there: ... CxfEndpoint contactServiceEndpoint = (CxfEndpoint) getContext().getEndpoint(contactServiceUri); Map<String,Object> outProps = new HashMap<>(); outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN + " " + WSHandlerConstants.TIMESTAMP); outProps.put(WSHandlerConstants.PASSWORD_TYPE, "PasswordDigest"); outProps.put(WSHandlerConstants.USER, "psadmin"); outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, UTPasswordCallback.class.getName()); WSS4JOutInterceptor outInterceptor = new WSS4JOutInterceptor(outProps); contactServiceEndpoint.getOutInterceptors().add(outInterceptor); ... from("direct:updatecontact") .setHeader("operationName", constant("updateContact")) .to(contactServiceEndpoint) .unmarshal(soapDF) .log("The response was ${body[0]}"); but I get the same error. So I have two questions: 1) Is using the cxf: component in this way the canonical way of accessing a remote client? 2) How do I configure a CXF client endpoint with authentication? I hope that shows what I am talking about; trying to learn Camel and CXF at the same time is confusing. (Note that I am not using Spring in my example since I haven't had much experience with it yet am trying to learn one thing at a time. But if using Spring in this case is the better way to go, then I'm all for it.) Thank you in advance for your help! Isaiah Inuwa