Grails-Plugin-Consortium / grails-cxf-client

Easy cxf client for grails
http://grails.org/plugin/cxf-client
27 stars 30 forks source link

How enable WSA-Addresing for client? #63

Open michmzr opened 8 years ago

michmzr commented 8 years ago

I imported classes from xsd file with configuration, but server require WSA-Attributes in soap header("wsa:action", "wsa:to"). Unfortunettly client service dont inject these attributes and server return http code 400. How could I repair my code?

Configuration in Config.groovy

    birCompanyDataEndPoint {
            wsdl = "wsdl/UslugaBIRzewnPubl.xsd"
            namespace = "pl.truesoftware.crm.company.regon"

            client = true

            contentType = "application/soap+xml"
            mtomEnabled = true
            exsh = true

            or = true

            wsdlArgs = ['-autoNameResolution']

            clientInterface = IUslugaBIRzewnPubl
            serviceEndpointAddress = "https://wyszukiwarkaregontest.stat.gov.pl/wsBIR/UslugaBIRzewnPubl.svc"
        }

Main xsd file: https://wyszukiwarkaregontest.stat.gov.pl/wsBIR/wsdl/UslugaBIRzewnPubl.xsd I use grails 2.5.0

Update: I used annotation javax.xml.ws.soap.Addressing for actions and soap request header included WS-Addresing, but was wrong for webserver.

ctoestreich commented 8 years ago

I think you need to use an out interceptor and modify the header in the interceptor. Here is some pseudo code for one I have done in the past.

package com.foo.bar

import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SmartApiMetaOutInterceptor extends AbstractPhaseInterceptor<Message> {

    @Autowired
    EndpointConfiguration endpointConfiguration;

    public SmartApiMetaOutInterceptor() {
        super(Phase.PREPARE_SEND);
    }

    @Override
    public void handleMessage(Message message) {
        if(message != null) {
            Map<String, List<String>> headers = (Map<String, List<String>>) message.get(Message.PROTOCOL_HEADERS);
            if (headers == null) {
                headers = new HashMap<>();
                message.put(Message.PROTOCOL_HEADERS, headers);
            }
            headers.put("X-Cache-Enabled", Collections.singletonList(endpointConfiguration.isCacheEnabled().toString()));
            headers.put("X-Cache-Remote-Url", Collections.singletonList(endpointConfiguration.getFopBaseServiceUrl()));
            headers.put("X-Cache-Prefix", Collections.singletonList(endpointConfiguration.getCachePrefix()));
        }
    }
}
ctoestreich commented 8 years ago

@michmzr Did the out interceptor work for you?

michmzr commented 8 years ago

Thanks for help, but interceptor only injected HTTP headers. I need to modify SOAP Request do add xml with soap header

ctoestreich commented 8 years ago

Still possible via SoapPreProtocolOutInterceptor

http://cxf.apache.org/docs/interceptors.html

ctoestreich commented 8 years ago

http://cxf.547215.n5.nabble.com/Adding-SOAPHeader-using-an-Interceptor-td567851.html

ctoestreich commented 8 years ago

http://stackoverflow.com/questions/18527863/add-header-to-all-outgoing-cxf-request

michmzr commented 8 years ago

Thank you for help :) Finally, I found the solution. I created a Interceptor, which iterate SOAP Header's tags from SOAP request. First, I added annotation @Addressing(enabled=true, required=true) to every webservice client's function

My interceptor

public class BirSoapHeaderInterceptor extends AbstractSoapInterceptor
{
    public BirSoapHeaderInterceptor() {
        super(Phase.PRE_PROTOCOL);
    }
    @Override
    public void handleMessage(SoapMessage message) throws Fault
    {
        List
list = message.getHeaders() //----------------- copy values from old header String wsaAction = "" String wsaTo = "" list.each{tag -> System.out.println("${tag.name} ${tag.dataBinding}") String tagName = (tag.name as String) def objectValue = tag.object?.value if(!wsaAction && tagName.contains("Action")) wsaAction = objectValue?.value if(!wsaTo && tagName.contains("To")) wsaTo = objectValue?.value } list.clear() //-----------------wsa:To Header headTo = new Header(new QName("", "wsa:To"), wsaTo, new JAXBDataBinding(String.class)) list.add(headTo) //-----------------wsa:Action Header headAction = new Header(new QName("", "wsa:Action"), wsaAction, new JAXBDataBinding(String.class)) list.add(headAction) message.put(Header.HEADER_LIST, list) } }
ctoestreich commented 8 years ago

:)