简体   繁体   中英

Add header to SOAP service client

I need to exchange data with a SOAP service. This service provides many WSDL endpoints so I took one of them to generate Java code (I followed this tutorial: https://www.baeldung.com/maven-wsdl-stubs ). Many classes were generated plus an interface and a service. Consider this code:

CodesService Interface:

package my.package.soapconsumer.models.service.getCodes;

import org.springframework.web.bind.annotation.RequestHeader;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;


/**
 * This class was generated by the JAX-WS RI.
 * JAX-WS RI 2.3.2
 * Generated source version: 2.2
 * 
 */
@WebService(name = "CodesService", targetNamespace = "https://thewsdlprovider.xyz/")
@XmlSeeAlso({
    ObjectFactory.class
})
public interface CodesService {


    /**
     * 
     * @param requestMethodOne
     * @return
     *     returns my.package.soapconsumer.models.service.getCodes.ResponseMethodOne
     */
    @WebMethod
    @WebResult(name = "ResponseMethodOne", targetNamespace = "")
    @RequestWrapper(localName = "methodOne", targetNamespace = "https://thewsdlprovider.xyz/", className = "my.package.soapconsumer.models.service.getCodes.MethodOne")
    @ResponseWrapper(localName = "methodOneResponse", targetNamespace = "https://thewsdlprovider.xyz/", className = "my.package.soapconsumer.models.service.getCodes.MethodOneResponse")
    public ResponseMethodOne methodOne(
        @WebParam(name = "RequestMethodOne", targetNamespace = "")
        RequestMethodOne requestMethodOne);

    /**
     * 
     * @return
     *     returns my.package.soapconsumer.models.service.getCodes.ResponseComunicacion
     */
    @WebMethod
    @WebResult(name = "ResponseTwo", targetNamespace = "")
    @RequestWrapper(localName = "methodTwo", targetNamespace = "https://thewsdlprovider.xyz/", className = "my.package.soapconsumer.models.service.getCodes.VerificarComunicacion")
    @ResponseWrapper(localName = "methodTwoResponse", targetNamespace = "https://thewsdlprovider.xyz/", className = "my.package.soapconsumer.models.service.getCodes.VerificarComunicacionResponse")
    public ResponseComunicacion methodTwo();

    /**
     * 
     * @param requestMethodThreeApp
     * @return
     *     returns my.package.soapconsumer.models.service.getCodes.ResponseMethodThree
     */
    @WebMethod
    @WebResult(name = "ResponseMethodThree", targetNamespace = "")
    @RequestWrapper(localName = "methodThree", targetNamespace = "https://thewsdlprovider.xyz/", className = "my.package.soapconsumer.models.service.getCodes.MethodThree")
    @ResponseWrapper(localName = "methodThreeResponse", targetNamespace = "https://thewsdlprovider.xyz/", className = "my.package.soapconsumer.models.service.getCodes.MethodThreeResponse")
    public ResponseMethodThree methodThree(
        @WebParam(name = "RequestMethodThreeApp", targetNamespace = "")
        RequestMethodThreeApp requestMethodThreeApp);

    /**
     * 
     * @param requestMethodFour
     * @return
     *     returns my.package.soapconsumer.models.service.getCodes.ResponseMethodFour
     */
    @WebMethod
    @WebResult(name = "ResponseMethodFour", targetNamespace = "")
    @RequestWrapper(localName = "methodFour", targetNamespace = "https://thewsdlprovider.xyz/", className = "my.package.soapconsumer.models.service.getCodes.MethodFour")
    @ResponseWrapper(localName = "methodFourResponse", targetNamespace = "https://thewsdlprovider.xyz/", className = "my.package.soapconsumer.models.service.getCodes.MethodFourResponse")
    public ResponseMethodFour methodFour(
        @WebParam(name = "RequestMethodFour", targetNamespace = "")
        RequestMethodFour requestMethodFour);

    /**
     * 
     * more methods
     *
     */
}

CodesService_Service Service

package my.package.soapconsumer.models.service.getCodes;

import org.springframework.web.bind.annotation.RequestHeader;

import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebEndpoint;
import javax.xml.ws.WebServiceClient;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceFeature;


/**
 * This class was generated by the JAX-WS RI.
 * JAX-WS RI 2.3.2
 * Generated source version: 2.2
 * 
 */
@WebServiceClient(name = "CodesService", targetNamespace = "https://thewsdlprovider.xyz/Codes", wsdlLocation = "https://codes.thewsdlprovider.xyz/v2/Codes?wsdl")

public class CodesService_Service
    extends Service
{

    private final static URL CODES_SERVICE_WSDL_LOCATION;
    private final static WebServiceException CODES_SERVICE_EXCEPTION;
    private final static QName CODES_SERVICE_QNAME = new QName("https://thewsdlprovider.xyz/Codes", "CodesService");

    static {
        URL url = null;
        WebServiceException e = null;
        try {
            url = new URL("https://codes.thewsdlprovider.xyz/v2/Codes?wsdl");

        } catch (MalformedURLException ex) {
            e = new WebServiceException(ex);
        }
        CODES_SERVICE_WSDL_LOCATION = url;
        CODES_SERVICE_EXCEPTION = e;
    }

    public CodesService_Service() {
        super(__getWsdlLocation(), CODES_SERVICE_QNAME);

    }

    public CodesService_Service(WebServiceFeature... features) {
        super(__getWsdlLocation(), CODES_SERVICE_QNAME, features);
    }

    public CodesService_Service(URL wsdlLocation) {
        super(wsdlLocation, CODES_SERVICE_QNAME);
    }

    public CodesService_Service(URL wsdlLocation, WebServiceFeature... features) {
        super(wsdlLocation, CODES_SERVICE_QNAME, features);
    }

    public CodesService_Service(URL wsdlLocation, QName serviceName) {
        super(wsdlLocation, serviceName);
    }

    public CodesService_Service(URL wsdlLocation, QName serviceName, WebServiceFeature... features) {
        super(wsdlLocation, serviceName, features);
    }

    /**
     * 
     * @return
     *     returns CodesService
     */
    @WebEndpoint(name = "CodesServicePort")
    public CodesService getCodesServicePort() {
        return super.getPort(new QName("https://thewsdlprovider.xyz/Codes", "CodesServicePort"), CodesService.class);
    }

    /**
     * 
     * @param features
     *     A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy.  Supported features not in the <code>features</code> parameter will have their default values.
     * @return
     *     returns CodesService
     */
    @WebEndpoint(name = "CodesServicePort")
    public CodesService getCodesServicePort(WebServiceFeature... features) {
        return super.getPort(new QName("https://thewsdlprovider.xyz/Codes", "CodesServicePort"), CodesService.class, features);
    }

    private static URL __getWsdlLocation() {
        if (CODES_SERVICE_EXCEPTION!= null) {
            throw CODES_SERVICE_EXCEPTION;
        }
        return CODES_SERVICE_WSDL_LOCATION;
    }

    public String getWsdlLocation(){
        return CODES_SERVICE_WSDL_LOCATION.toString();
    }
}

I need to use the methods or functions provided by the interface so to testing them I'm using a REST controller:

@RestController
@RequestMapping("/codes")
public class CodigosRestController {
    @GetMapping
    public String obtainCode(){
        CodesService_Service service = new CodesService_Service();
        String code = service.getCodesServicePort().methodTwo().toString();
        return code;
    }
}

But when I run it to query the REST endpoint I get the following error:

{
    "timestamp": "2022-02-18T13:44:03.234+00:00",
    "status": 500,
    "error": "Internal Server Error",
    "trace": "com.sun.xml.internal.ws.fault.ServerSOAPFaultException: Client received SOAP Fault from server: THE SERVICE REQUIRES API KEY Please see the server log to find more detail regarding exact cause of the failure.\n\tat com.sun.xml.internal.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:178)\n\tat com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:116)\n\tat com.sun.xml.internal.ws.client.sei.StubHandler.readResponse(StubHandler.java:238)\n\tat ...
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732)\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n\tat java.lang.Thread.run(Thread.java:748)\n",
    "message": "Client received SOAP Fault from server: THE SERVICE REQUIRES API KEY Please see the server log to find more detail regarding exact cause of the failure.",
    "path": "/codes"
}

It is necessary to send an API KEY in the headers but I don't know how.

So I used SoapUI to test the SOAP endpoint adding this header and I received a correct answer: SOAP 标头

What I tried:

  • Use the WebServiceFeature... features constructor parameter but I it seems that a header can't be added to this object. In fact, I don't know what those three points mean.
  • Use the @RequestHeader but it reports that is not applicable to web methods

So how can I add a header to my interface or service? Thanks in advance.

To work with the raw request you either need to create a request interceptor or just set the headers on the requested context on the service port. So in your case, it should be as simple as

@RestController
@RequestMapping("/codes")
public class CodigosRestController {
    @GetMapping
    public String obtainCode(){
        CodesService_Service service = new CodesService_Service();
        CodesService port = service.getCodesServicePort();
        // generate the headers
        Map<String, List<String>> requestHeaders = new HashMap<>();
        requestHeaders.put("apiKey",Arrays.asList("TokeApi yourtokenhere"));
        BindingProvider bindingProvider = (BindingProvider) port;   
        // set the headers on the request context
        bindingProvider.getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, requestHeaders);

        String code = port.methodTwo().toString();
        return code;
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM