简体   繁体   中英

How to generate a SOAP message with a fully populated request from WSDL without code gen

I would like to ask you how I can generate a SOAP request/response in a XML format on the basis of the WSDL file. The target platform is JVM so a wide set of languages can be used (eg Java, Scala, Groovy, JRuby, Jython, etc.). The SOAP request/response generation should be done purely on the XML level without any class-generation and class-loading (WSDL2Java, JAXB or similar approaches are inappropriate in this case). Generation should be done programmatically with the usage of open-source components. The generation technique should support document-literal, rpc-encoded and rpc-literal flavors, so proper encoding of parameters should be handled by the generator. Request/response messages should be fully-populated -> empty nodes should be generated even for empty/blank values.

Cutting the long story short -> I would like to do programmatically the thing that is doable in SoapUI IDE. I already had a look at different Java-related libraries/frameworks (SAAJ, WSDL4J) or Ruby (Savon) but I am struggling to move it any further.

A sample Web-Service definition (WSDL and XSD) that I am working on is stockquote-ws.wsdl and stockquote-schema.xsd .

What I would like to do is:

SoapMessageGenerator generator = new SoapMessageGenerator("stockquote-ws.wsdl");
String request = generator.generateSoapRequest();
String response = generator.generateSoapResponse();

In this case a request should look like this:

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:stoc="http://centeractive.com/stockquote.wsdl" xmlns:stoc1="http://centeractive.com/stockquote.xsd">
   <soapenv:Header/>
   <soapenv:Body>
      <stoc:GetLastTradePrice soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <stoc1:TradePriceRequest>
            <tickerSymbol xsi:type="xsd:string">?</tickerSymbol>
         </stoc1:TradePriceRequest>
      </stoc:GetLastTradePrice>
   </soapenv:Body>
</soapenv:Envelope>

... whereas a response should look like this:

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:stoc="http://centeractive.com/stockquote.wsdl" xmlns:stoc1="http://centeractive.com/stockquote.xsd">
   <soapenv:Header/>
   <soapenv:Body>
      <stoc:GetLastTradePriceResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <stoc1:TradePrice>
            <price xsi:type="xsd:float">?</price>
         </stoc1:TradePrice>
      </stoc:GetLastTradePriceResponse>
   </soapenv:Body>
</soapenv:Envelope>

OK. I managed to fully solve this problem. I have extracted some code from soapUI and started an open-source project to support SOAP in a purely XML way in Java. The main reason behind the class extraction was to separate the code that is responsible for the generation of the SOAP messages from the rest of the soapUIs code that is tightly coupled with other modules, such as soapUIs graphical user interface, etc. You can find the project here: https://github.com/reficio/soap-ws Not only is it able to generate SOAP messages, but also provides SOAP client and server. More details here: http://www.reficio.org/projects

What about the SOAPUI library:

package com.bbog.soap;

import com.eviware.soapui.impl.wsdl.WsdlInterface;
import com.eviware.soapui.impl.wsdl.WsdlOperation;
import com.eviware.soapui.impl.wsdl.WsdlProject;
import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlImporter;
import com.eviware.soapui.model.iface.Operation;

public class WsdlAnalyzer {

    public static void main(String[] args) throws Exception {
        WsdlProject project = new WsdlProject();
        WsdlInterface[] wsdls = WsdlImporter.importWsdl(project, "http://localhost:7000/Solicitud?wsdl");
        WsdlInterface wsdl = wsdls[0];
        for (Operation operation : wsdl.getOperationList()) {
            WsdlOperation op = (WsdlOperation) operation;
            System.out.println("OP:"+op.getName());
            System.out.println(op.createRequest(true));
            System.out.println("Response:");
            System.out.println(op.createResponse(true));
        }
    }
}

I am actually looking to do the same thing. I've been using the javax.wsdl API to pull information from the wsdl and I'm trying to use javax.xml.soap API to create the SOAP request/response. They might be worth taking a look at.

You might be interested in kSOAP project which is used in mobile development. The following kSOAP tutorial will point you to how to serialize the request and the following section show you how to get the response.

kSOAP could create the SOAP message without having to generate the proxy code. This is needed in mobile development due to its processing power that is considerably less than the desktop and having proxy classes and library are considered heavier than directly creating the SOAP message

IBM article

The above article seems to address the technique that I would try for your case: make use of XSLT transformation. After all you're going from XML to XML. If you have better luck than I finding (or developing of course) the specific XSLT stylesheet(s) that you need to go from a WSDL to accompanying SOAP request(s) I'd love to learn about it.

Cheers, Wim

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