Mantis - Resin
Viewing Issue Advanced Details
1838 block always 06-28-07 12:27 07-03-07 14:15
johndidion  
emil  
normal  
closed 3.1.1  
fixed  
none    
none 3.1.2  
0001838: Resin generates invalid WSDL for SOAP web services
I wrote a simple web service (called "commerce") and deployed it. The wsdl generated at http://localhost:8080/commerce/soap?wsdl [^] is invalid. WSDL validity can be checked in several different ways, but I used SoapUI. I also tried to generate the client using Axis' wsdl2java, and that failed as well.

I put severity as "block" because this is blocking us from deploying on Resin 3.1. We can't release a service that can only be consumed by people using Resin clients.
----------------------------------------------------------
WS interface
----------------------------------------------------------
import javax.jws.WebService;
import javax.jws.WebMethod;
import java.util.List;

@WebService
public interface CommerceService {
    @WebMethod
    boolean purchase(String productId);

    @WebMethod
    List<String> listPurchases();
}
----------------------------------------------------------
WS impl
----------------------------------------------------------
import javax.jws.WebService;
import javax.jws.WebMethod;
import java.util.List;
import java.util.ArrayList;

@WebService(endpointInterface = "commerce.CommerceService")
public class CommerceServiceImpl implements CommerceService {
    private List<String> purchases = new ArrayList<String>();

    @WebMethod
    public boolean purchase(String productId) {
        if (this.purchases.contains(productId)) {
            return false;
        }

        this.purchases.add(productId);

        return true;
    }

    @WebMethod
    public List<String> listPurchases() {
        return this.purchases;
    }
}
----------------------------------------------------------
web.xml
----------------------------------------------------------
<web-app xmlns="http://caucho.com/ns/resin"> [^]
  <servlet-mapping url-pattern="/soap/*"
                   servlet-class="commerce.CommerceServiceImpl">
    <protocol type="soap"/>
  </servlet-mapping>
</web-app>
----------------------------------------------------------
generated WSDL
----------------------------------------------------------
<?xml version="1.0" standalone="yes"?>
<definitions targetNamespace="http://commerce/" [^] name="CommerceServiceImplService" xmlns="http://schemas.xmlsoap.org/wsdl/" [^] xmlns:ns0="http://www.w3.org/2001/XMLSchema" [^] xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" [^] xmlns:m="http://commerce/"> [^]
  <types>
    <ns0:schema>
      <ns0:import namespace="http://commerce/" [^] schemaLocation="CommerceServiceImplService_schema1.xsd"/>
    </ns0:schema>
  </types>
  <message name="listPurchases">
    <part name="parameters" element="m:listPurchases"/>
  </message>

  <message name="listPurchasesResponse">
    <part name="parameters" element="m:listPurchasesResponse"/>
  </message>
  <message name="purchase">
    <part name="parameters" element="m:purchase"/>
  </message>
  <message name="purchaseResponse">
    <part name="parameters" element="m:purchaseResponse"/>
  </message>

  <portType name="CommerceServiceImpl">
    <operation name="listPurchases">
      <input message="m:listPurchases"/>
      <output message="m:listPurchasesResponse"/>
    </operation>
    <operation name="purchase">
      <input message="m:purchase"/>
      <output message="m:purchaseResponse"/>
    </operation>

  </portType>
  <binding name="CommerceServiceImplPortBinding" type="m:CommerceServiceImpl">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" [^] style="document"/>
    <operation name="listPurchases">
      <soap:operation soapAction=""/>
      <input>
        <soap:body use="literal"/>
      </input>
      <output>

        <soap:body use="literal"/>
      </output>
    </operation>
    <operation name="purchase">
      <soap:operation soapAction=""/>
      <input>
        <soap:body use="literal"/>
      </input>
      <output>

        <soap:body use="literal"/>
      </output>
    </operation>
  </binding>
  <service name="CommerceServiceImplService">
    <port name="CommerceServiceImplPort" binding="m:CommerceServiceImplPortBinding">
      <soap:address location=""/>
    </port>
  </service>

</definitions>
----------------------------------------------------------
SoapUI errors
----------------------------------------------------------
Thu Jun 28 11:48:12 PDT 2007:ERROR:Could not find element [{http://commerce/}listPurchases] [^] specified in part [parameters]
Thu Jun 28 11:48:12 PDT 2007:ERROR:Could not find element [{http://commerce/}purchase] [^] specified in part [parameters]

Notes
(0002091)
johndidion   
06-28-07 14:17   
I deployed XFire's sample web service with both Resin and XFire. It may be helpful to look at the differences between the WSDLs they generate. It seems the only difference is that XFire inlines the schema, whereas Resin tries to import a non-existent schema.

-------------------------------------
Resin
-------------------------------------
<?xml version="1.0" standalone="yes"?>
<definitions targetNamespace="http://xfire/" [^] name="SimpleServiceImplService" xmlns="http://schemas.xmlsoap.org/wsdl/" [^] xmlns:ns0="http://www.w3.org/2001/XMLSchema" [^] xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" [^] xmlns:m="http://xfire/"> [^]
  <types>
    <ns0:schema>
      <ns0:import namespace="http://xfire/" [^] schemaLocation="SimpleServiceImplService_schema1.xsd"/>
    </ns0:schema>
  </types>
  
  <message name="echoMethod">
    <part name="parameters" element="m:echoMethod"/>
  </message>

  <message name="echoMethodResponse">
    <part name="parameters" element="m:echoMethodResponse"/>
  </message>
  
  <portType name="SimpleServiceImpl">
    <operation name="echoMethod">
      <input message="m:echoMethod"/>
      <output message="m:echoMethodResponse"/>
    </operation>
  </portType>

  <binding name="SimpleServiceImplPortBinding" type="m:SimpleServiceImpl">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" [^] style="document"/>
    <operation name="echoMethod">
      <soap:operation soapAction=""/>
      <input>
        <soap:body use="literal"/>
      </input>
      <output>
        <soap:body use="literal"/>

      </output>
    </operation>
  </binding>
  <service name="SimpleServiceImplService">
    <port name="SimpleServiceImplPort" binding="m:SimpleServiceImplPortBinding">
      <soap:address location=""/>
    </port>
  </service>
</definitions>

----------------------------------------
XFire
----------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://test/TestService" [^] xmlns:soapenc12="http://www.w3.org/2003/05/soap-encoding" [^] xmlns:tns="http://test/TestService" [^] xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" [^] xmlns:xsd="http://www.w3.org/2001/XMLSchema" [^] xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/" [^] xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" [^] xmlns:soapenc11="http://schemas.xmlsoap.org/soap/encoding/" [^] xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"> [^]

<wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" [^] targetNamespace="http://test/TestService" [^] elementFormDefault="qualified" attributeFormDefault="qualified">
<xsd:element name="echoMethod">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" nillable="true" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="echoMethodResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="out" type="xsd:string" nillable="true" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>

</xsd:complexType>
</xsd:element>
</xsd:schema>
  </wsdl:types>

  <wsdl:message name="echoMethodResponse">
    <wsdl:part name="parameters" element="tns:echoMethodResponse">
    </wsdl:part>
  </wsdl:message>
  
  <wsdl:message name="echoMethodRequest">
    <wsdl:part name="parameters" element="tns:echoMethod">
    </wsdl:part>
  </wsdl:message>
  
  <wsdl:portType name="TestServicePortType">
    <wsdl:operation name="echoMethod">
      <wsdl:input name="echoMethodRequest" message="tns:echoMethodRequest">
    </wsdl:input>
      <wsdl:output name="echoMethodResponse" message="tns:echoMethodResponse">
    </wsdl:output>
    </wsdl:operation>

  </wsdl:portType>
  
  <wsdl:binding name="TestServiceHttpBinding" type="tns:TestServicePortType">
    <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> [^]
    <wsdl:operation name="echoMethod">
      <wsdlsoap:operation soapAction=""/>
      <wsdl:input name="echoMethodRequest">
        <wsdlsoap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="echoMethodResponse">
        <wsdlsoap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  
  <wsdl:service name="TestService">
    <wsdl:port name="TestServiceHttpPort" binding="tns:TestServiceHttpBinding">
      <wsdlsoap:address location="http://localhost:8080/xfire/services/TestService"/> [^]
    </wsdl:port>
  </wsdl:service>
    
</wsdl:definitions>
(0002099)
emil   
07-03-07 14:15   
This is indeed an issue with not finding the schema. At the moment, the default is to generate the schema separately, but there is a switch to generate it inline by adding an attribute to the protocol tag in your web.xml:

<web-app xmlns="http://caucho.com/ns/resin"> [^]
  <servlet-mapping url-pattern="*"
                   servlet-class="commerce.CommerceServiceImpl">
    <protocol type="soap" separate-schema="false"/>
  </servlet-mapping>
</web-app>

I'll change the default to generate the schema inline as this seems to be a pretty reasonable behavior. The other behavior is more consistent with the offline WSDL generation in the JAX-WS RI.

That being said, the WSDL generation in Resin is currently considered to be in the alpha stage.

Thanks very much for trying it out and filing this bug. We appreciate helpful bug reports like this one.