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

Reply via email to