You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by Isaiah Inuwa <is...@moody.edu> on 2019/01/08 21:59:38 UTC

Help Accessing Remote SOAP Service with Authentication via CXF

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

RE: Help Accessing Remote SOAP Service with Authentication via CXF

Posted by Isaiah Inuwa <is...@moody.edu>.
OK, I understand now. I was able to implement it two ways: with the CxfEndpointConfigurer with the "cxf:xxx?cxEndpointConfigurer=#contactServiceConfigurer" and also with a Spring Bean ("cxf:bean:contactServiceProxy"). I think I will keep the latter. Thank you for your help!

Isaiah Inuwa
Database Application Administrator  |  ITS
(312) 329-8081

-----Original Message-----
From: Willem Jiang <wi...@gmail.com> 
Sent: Thursday, January 10, 2019 8:59 AM
To: users@camel.apache.org
Subject: Re: Help Accessing Remote SOAP Service with Authentication via CXF

Hi

the wssec.xml and client class are used as client to invoke the camel route. You can setup the cxfEndpoint in the same way as the test showed in the spring xml way.

If you want to setup the cxfEndpoint in programical way, you could just consider to implement CxfEndpointConfigurer[1] yourself to setup the output interceptors in the method of void configure(AbstractWSDLBasedEndpointFactory factoryBean); You can setup the CxfEndpointConfigure on the cxfEndpoint  by setup the cxf endpoint url just like this "cxf://xxx?cxfEndpointConfigure=#myConfigure" and you need to put the instance of CxfEndpointConfigure into the CamelContext registry.

[1]https://github.com/apache/camel/blob/master/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfEndpointConfigurer.java

Willem Jiang

Twitter: willemjiang
Weibo: 姜宁willem

On Thu, Jan 10, 2019 at 5:38 AM Isaiah Inuwa <is...@moody.edu> wrote:
>
> Hello Willem,
>
> Thank you for your response.
>
> Perhaps this could be my ignorance with Spring and CXF, but do it seems that the link you gave shows how to configure the incoming service to accept a username token rather than the outgoing service. Would either the wssec.xml file [1] or the Client [1] class in that same package be what I need?
>
> I have added the spring-boot-starter to my pom.xml and registered my RouteBuilder class as a Component so Spring will automatically run it on startup successfully. However, I don't know how to get the bean definitions from Spring into the Camel route. If I create the CXF endpoint or client bean in Spring, how do I get Camel to reference it? Sorry if it's a stupid question.
>
> [1] 
> https://github.com/apache/camel/blob/master/components/camel-cxf/src/t
> est/resources/org/apache/camel/component/cxf/wssecurity/client/wssec.x
> ml [2] 
> https://github.com/apache/camel/blob/master/components/camel-cxf/src/t
> est/java/org/apache/camel/component/cxf/wssecurity/client/Client.java
>
> Isaiah Inuwa
>
> -----Original Message-----
> From: Willem Jiang <wi...@gmail.com>
> Sent: Tuesday, January 8, 2019 8:15 PM
> To: users@camel.apache.org
> Subject: Re: Help Accessing Remote SOAP Service with Authentication 
> via CXF
>
> Hi,
>
> I think you may need find the right moment to setup the CXFEndpoint.
> It could be meaningless if the camel route is loaded and the CXFConsumer is created.
> Can you try to use the Spring configuration to setup the cxfEndpoint this way[1]?
> [1] 
> https://github.com/apache/camel/blob/master/components/camel-cxf/src/t
> est/resources/org/apache/camel/component/cxf/wssecurity/camel/camel-co
> ntext.xml
>
> Willem Jiang
>
> Twitter: willemjiang
> Weibo: 姜宁willem
>
> On Wed, Jan 9, 2019 at 5:59 AM Isaiah Inuwa <is...@moody.edu> wrote:
> >
> > 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

Re: Help Accessing Remote SOAP Service with Authentication via CXF

Posted by Willem Jiang <wi...@gmail.com>.
Hi

the wssec.xml and client class are used as client to invoke the camel
route. You can setup the cxfEndpoint in the same way as the test
showed in the spring xml way.

If you want to setup the cxfEndpoint in programical way, you could
just consider to implement CxfEndpointConfigurer[1] yourself to setup
the output interceptors in the method of void
configure(AbstractWSDLBasedEndpointFactory factoryBean);
You can setup the CxfEndpointConfigure on the cxfEndpoint  by setup
the cxf endpoint url just like this
"cxf://xxx?cxfEndpointConfigure=#myConfigure" and you need to put the
instance of CxfEndpointConfigure into the CamelContext registry.

[1]https://github.com/apache/camel/blob/master/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfEndpointConfigurer.java

Willem Jiang

Twitter: willemjiang
Weibo: 姜宁willem

On Thu, Jan 10, 2019 at 5:38 AM Isaiah Inuwa <is...@moody.edu> wrote:
>
> Hello Willem,
>
> Thank you for your response.
>
> Perhaps this could be my ignorance with Spring and CXF, but do it seems that the link you gave shows how to configure the incoming service to accept a username token rather than the outgoing service. Would either the wssec.xml file [1] or the Client [1] class in that same package be what I need?
>
> I have added the spring-boot-starter to my pom.xml and registered my RouteBuilder class as a Component so Spring will automatically run it on startup successfully. However, I don't know how to get the bean definitions from Spring into the Camel route. If I create the CXF endpoint or client bean in Spring, how do I get Camel to reference it? Sorry if it's a stupid question.
>
> [1] https://github.com/apache/camel/blob/master/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/wssecurity/client/wssec.xml
> [2] https://github.com/apache/camel/blob/master/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/wssecurity/client/Client.java
>
> Isaiah Inuwa
>
> -----Original Message-----
> From: Willem Jiang <wi...@gmail.com>
> Sent: Tuesday, January 8, 2019 8:15 PM
> To: users@camel.apache.org
> Subject: Re: Help Accessing Remote SOAP Service with Authentication via CXF
>
> Hi,
>
> I think you may need find the right moment to setup the CXFEndpoint.
> It could be meaningless if the camel route is loaded and the CXFConsumer is created.
> Can you try to use the Spring configuration to setup the cxfEndpoint this way[1]?
> [1] https://github.com/apache/camel/blob/master/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/wssecurity/camel/camel-context.xml
>
> Willem Jiang
>
> Twitter: willemjiang
> Weibo: 姜宁willem
>
> On Wed, Jan 9, 2019 at 5:59 AM Isaiah Inuwa <is...@moody.edu> wrote:
> >
> > 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

RE: Help Accessing Remote SOAP Service with Authentication via CXF

Posted by Isaiah Inuwa <is...@moody.edu>.
Hello Willem,

Thank you for your response. 

Perhaps this could be my ignorance with Spring and CXF, but do it seems that the link you gave shows how to configure the incoming service to accept a username token rather than the outgoing service. Would either the wssec.xml file [1] or the Client [1] class in that same package be what I need?

I have added the spring-boot-starter to my pom.xml and registered my RouteBuilder class as a Component so Spring will automatically run it on startup successfully. However, I don't know how to get the bean definitions from Spring into the Camel route. If I create the CXF endpoint or client bean in Spring, how do I get Camel to reference it? Sorry if it's a stupid question.

[1] https://github.com/apache/camel/blob/master/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/wssecurity/client/wssec.xml
[2] https://github.com/apache/camel/blob/master/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/wssecurity/client/Client.java

Isaiah Inuwa

-----Original Message-----
From: Willem Jiang <wi...@gmail.com> 
Sent: Tuesday, January 8, 2019 8:15 PM
To: users@camel.apache.org
Subject: Re: Help Accessing Remote SOAP Service with Authentication via CXF

Hi,

I think you may need find the right moment to setup the CXFEndpoint.
It could be meaningless if the camel route is loaded and the CXFConsumer is created.
Can you try to use the Spring configuration to setup the cxfEndpoint this way[1]?
[1] https://github.com/apache/camel/blob/master/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/wssecurity/camel/camel-context.xml

Willem Jiang

Twitter: willemjiang
Weibo: 姜宁willem

On Wed, Jan 9, 2019 at 5:59 AM Isaiah Inuwa <is...@moody.edu> wrote:
>
> 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

Re: Help Accessing Remote SOAP Service with Authentication via CXF

Posted by Willem Jiang <wi...@gmail.com>.
Hi,

I think you may need find the right moment to setup the CXFEndpoint.
It could be meaningless if the camel route is loaded and the
CXFConsumer is created.
Can you try to use the Spring configuration to setup the cxfEndpoint
this way[1]?
[1] https://github.com/apache/camel/blob/master/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/wssecurity/camel/camel-context.xml

Willem Jiang

Twitter: willemjiang
Weibo: 姜宁willem

On Wed, Jan 9, 2019 at 5:59 AM Isaiah Inuwa <is...@moody.edu> wrote:
>
> 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