Question

I'm trying to create a transparent proxy with Switchyard. The idea is having a "promoted" service exposed by Switchyard. Calls to this webservice will be redirected with Camel to a service reference. Service reference (proxified service) and promoted service have the same WSDL.

The problem is that the SOAP calls that the user does contains a custom token in the SOAP Envelope Header that it is NOT propagated. How can I solve that?

SOAP Call Example (User->Propagated Service):

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service.test/">
   <soapenv:Header>
   <token>foo</token>
   </soapenv:Header>
   <soapenv:Body>
      <ser:readSomethings>
         <something>
         </something>
      </ser:readSomethings>
   </soapenv:Body>
</soapenv:Envelope>

SOAP Call that Switchyard does to the "proxified" service (It doesn't contain the token!!):

<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
     <ser:readSomethings xmlns:ser=\"http://service.test/\">
       <something></something>
     </ser:readSomethings>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

switchyard.xml:

<?xml version="1.0" encoding="ASCII"?>
<switchyard xmlns="urn:switchyard-config:switchyard:1.0" xmlns:bean="urn:switchyard-component-bean:config:1.0" xmlns:camel="urn:switchyard-component-camel:config:1.0" xmlns:sca="http://docs.oasis-open.org/ns/opencsa/sca/200912" xmlns:soap="urn:switchyard-component-soap:config:1.0" name="SomethingService" targetNamespace="urn:my.company.something:SomethingService:1.0">
  <sca:composite name="SomethingService" targetNamespace="urn:my.company.something:SomethingService:1.0">
    <sca:service name="PromotedProxyService" promote="ProxyService/ProxyService">
      <soap:binding.soap>
        <soap:contextMapper includes=".*"/>
        <soap:wsdl>META-INF/SomethingWS.wsdl</soap:wsdl>
        <soap:socketAddr>:${jettyPort}</soap:socketAddr>
        <soap:contextPath>SomethingService</soap:contextPath>
      </soap:binding.soap>
    </sca:service>
    <sca:reference name="ProxifiedService" multiplicity="0..1" promote="ProxyService/ProxifiedService">
      <soap:binding.soap>
        <soap:contextMapper includes=".*"/>
        <soap:wsdl>META-INF/SomethingWS.wsdl</soap:wsdl>
        <soap:endpointAddress>http://IP:8080/ws_admin/SomethingWS</soap:endpointAddress>
      </soap:binding.soap>
    </sca:reference>
    <sca:component name="ProxyService">
      <camel:implementation.camel>
        <camel:java class="my.company.something.RouterCamel"/>
      </camel:implementation.camel>
      <sca:service name="ProxyService">
        <sca:interface.wsdl interface="META-INF/SomethingWS.wsdl#wsdl.porttype(SomethingWS)"/>
      </sca:service>
      <sca:reference name="ProxifiedService">
        <sca:interface.wsdl interface="META-INF/SomethingWS.wsdl#wsdl.porttype(SomethingWS)"/>
      </sca:reference>
    </sca:component>
  </sca:composite>
  <domain>
    <properties>
      <property name="org.switchyard.handlers.messageTrace.enabled" value="true"/>
    </properties>
  </domain>
</switchyard>

RouterCamel.java

public class RouterCamel extends org.apache.camel.builder.RouteBuilder{

    public void configure() {
        org.apache.camel.Processor myProc = new org.apache.camel.Processor(){
            public void process(org.apache.camel.Exchange exchange) throws Exception {
                System.out.println("------------------------------ ENTRO\n\n\n\n");
                String body = exchange.getIn().getBody(String.class);
                // change the message to say Hello
                System.out.println("\n\n\n\n------------------------------ BODY: " + body);
                exchange.getOut().setBody(body);
                // copy headers from IN to OUT to propagate them
                System.out.println("Header in values:");
                for(Entry<String, Object> header: exchange.getIn().getHeaders().entrySet()){
                    System.out.println("Header: " +  header.getKey() + " Value: " + header.getValue());
                }
                exchange.getOut().setHeaders(exchange.getIn().getHeaders());
                System.out.println("Header out values:");
                for(Entry<String, Object> header: exchange.getOut().getHeaders().entrySet()){
                    System.out.println("Header: " +  header.getKey() + " Value: " + header.getValue());
                }
            }
        };
      // Define routing rules here:
      from("switchyard://ProxyService").process(myProc).to("switchyard://ProxifiedService");
    }
}
Was it helpful?

Solution

The header was not propagated because it didn't have a namespace.

I found the answer here: https://developer.jboss.org/thread/243364

OTHER TIPS

<sca:reference name="ProxyReference" multiplicity="0..1" promote="Proxy/ProxyService">
    <sca:interface.wsdl interface="META-INF/wsdl/RegisterService.wsdl#wsdl.porttypePortType)"/>
<soap:binding.soap name="soap">
<soap:contextMapper class="WSHeaderContextMapper"/>
<soap:wsdl>META-INF/wsdl/RegisterService.wsdl</soap:wsdl>
<soap:endpointAddress>${service.address}</soap:endpointAddress>
<soap:timeout>12000</soap:timeout>
</soap:binding.soap>
</sca:reference>

import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.dom.message.WSSecUsernameToken;
import org.switchyard.Context;
import org.switchyard.component.soap.composer.SOAPBindingData;
import org.switchyard.component.soap.composer.SOAPContextMapper;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPFactory;

public class WSHeaderContextMapper extends SOAPContextMapper {
    private String user = "user";
    private String password = "pass";

    @Override
    public void mapTo(Context context, SOAPBindingData target) throws Exception {
        SOAPFactory factory = SOAPFactory.newInstance();
        SOAPElement element = factory.createElement("Security", "wsse", WSConstants.WSSE_NS);
        WSSecUsernameToken utBuilder = createUsernameToken(this.user, password);
        utBuilder.prepare(element.getOwnerDocument());
        element.addChildElement(factory.createElement(utBuilder.getUsernameTokenElement()));
        context.setProperty(element.getElementQName().toString(), element);
        super.mapTo(context, target);
    }

    private WSSecUsernameToken createUsernameToken(String userName, String password) {
        WSSecUsernameToken utBuilder = new WSSecUsernameToken();
        utBuilder.setUserInfo(userName, password);
        utBuilder.setPasswordType(WSConstants.PASSWORD_TEXT);
        return utBuilder;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top