Issues

ZF-6349: Zend_Soap_AutoDiscover does not generate interoperable document-literal WSDL

Description

Note to admins reading this: there should be a Zend_Soap_AutoDiscover component, I had to use Zend_Soap_Wsdl here instead.

Zend_Soap_AutoDiscover support setting WSDL binding and operation styles (such as rpc-encoded, rpc-literal, document-literal) since rev 13137 (ZF-5188). However, the generated document-literal WSDL does not comply with the www.ws-i.org/Profiles/BasicProfile-1.1.html" rel="nofollow">WS-I Basic Profile 1.1 and is not interoperable with other popular clients such as .NET, JAX-RPC, JAX-WS, or gSOAP (see ZF-6049 for a example with JAX-WS).

The WS-I Basic Profile 1.1 specifies that document-literal WSDL documents must use an {{element}} attribute in message parts (R2204), and that message can only contain zero or one {{part}} (R2210). This makes functions with more than 1 parameter impossible to represent this way. A commonly accepted workaround implemented in .NET and Java (probably others too, except PHP...) is to wrap parameters in a {{complexType}}, and have this {{complexType}} in an element with the same name as the function. The message {{part}} would then be named "parameters" and make reference to the said element.

For more information about this "document-literal-wrapped" convention, see the following links: * [http://ibm.com/developerworks/webservices/…] * [http://msdn.microsoft.com/en-us/library/…] * [http://atmanes.blogspot.com/2005/03/…]

The attached patch adds support for WS-I compliant and interoperable document-literal WSDL generation. It also fixes rpc-literal WSDL generation to be WS-I compliant. I will detail what this patch does exactly in a comment below.

Making PHP work with the generated WSDL is beyond the scope of this issue, I think, so I created ZF-6351 to discuss it.

Note: this patch depends on 2 others patches I submitted earlier under ZF-6346 and ZF-6348.

Comments

This patch makes Zend_Soap_AutoDiscover generate valid WSDL with respect to the WSDL Schema and www.ws-i.org/Profiles/BasicProfile-1.1.html" rel="nofollow">WS-I Basic Profile 1.1. Points to note: * A new {{_addFunctionToWsdl()}} protected method avoids duplicating code in {{setClass()}} and {{addFunction()}} * The {{types}} node must precede (almost) all other elements (R2023), so {{addSchemaTypeSection()}} is called right after instantiating Zend_Soap_Wsdl. * When using the *document* style, parameters (arguments and return value) are wrapped as described in the issue description above. Using elements to describe parameters instead of parts also allows having *optional* (nillable) parameters. * When using the *RPC* style, parameters are described in typed message parts (as before). Additionally, a *namespace* attribute is automatically added to the {{_operationBodyStyle}} if not already present, as required by R2717 * Function *documentation* is now supported (depends on ZF-6346) * Message names had to be changed from {{$name.'Request'}} / {{$name.'Response'}} to *{{$name.'In'}} / {{$name.'Out'}}* (inspired by .NET) to avoid confusion, because the return value's wrapper element must be named {{$name.'Response'}} too

Here is another patch to update AutoDiscover tests. With this patch applied, all tests pass.

Additionally, during the development of these patches, I used a custom ZFTestService project and TestService class to test compliance and interoperability with other SOAP clients. The produced document-literal and rpc-literal WSDL documents were tested with: * the WS-I Interoperability Testing Tools 1.1 - and passed compliance tests. Note though that the {{ArrayOfTypeSequence}} strategy must be used instead of {{ArrayOfTypeComplex}}, as the latter uses soap-enc:Array, which is forbidden by the WS-I Basic Profile 1.1. * a .NET 2.0 client in C# - everything worked * a JAX-RPC client (for rpc-literal) and JAX-WS client (for document-literal) - everything worked * a C++ client using gSOAP - everything worked

Since these tests need external tools, I don't think they could be integrated in automated tests.. what to do with them?

Thanks Fabien. I do confirm that when I tried to generate a Web Service Java client with Nebeans 6.7, the wsdl generated by 1.8 zend soap autodiscover seems to be invalid: [WARNING] R2716 WSI-BasicProfile ver. 1.0, namespace attribute not allowed in doc/lit for soapbind:body: "get_token" [WARNING] ignoring operation "get_token": message part does not refer to a schema element declaration


$autodiscover = new Zend_Soap_AutoDiscover();
  
$autodiscover->setOperationBodyStyle(
                    array('use' => 'literal',
                          'namespace' => $CFG->wwwroot)
                );
              
$autodiscover->setBindingStyle(
                    array('style' => 'document')
                );

$autodiscover->setClass('ws_authentication',$CFG->wwwroot);
                $autodiscover->handle();

/**
 * authentication class 
 */
class ws_authentication {
    /**
     *
     * @param array|struct $params
     * @return integer
     */
    function get_token($params) {
        if ($params['username'] == 'wsuser' && $params['password'] == 'wspassword') {
            return '456';
        } else {
            throw new moodle_exception('wrongusernamepassword');
        }
    }
}

Btw it is hard to find any document on how to make a basic Java or .Net client for Zend_SOAP. Does someone know a blog/document explaining about to write/setup an autodiscover working with any basic Java client generator.

Fixed in trunk as of issue r15832.

Please test this patch against your Zend_Soap_AutoDiscover production code!!