I did some investigation and the following is what happens. We would really
appreciate some explanation on why this is like this because it surely does
not look right to me.
The steps we used to simulate a weird scenario in apache CXF. We created a
class called TestService. The first example shows a generated wsdl from
this class which only have Java interfaces where the second example show an
example using concrete java classes. Apache CXF responds differently for
both implementations and the second leads to runtime issues.
1) Example without List implementation.
*import* javax.jws.WebMethod;
*import* javax.jws.WebService;
@WebService(name="TestService")
*public* *class* TestService {
@WebMethod
*public* *List* methodA(){
*return* *null*;
}
@WebMethod
*public* *List* methodB(){
*return* *null*;
}
}
<?xml version=*"1.0"* encoding=*"UTF-8"*?>
<wsdl:definitions name=*"TestServiceService"*targetNamespace=*"
http://test.portal.adp.com/"*xmlns:wsdl=*"http://schemas.xmlsoap.org/wsdl/"*
xmlns:tns=*"http://test.portal.adp.com/"*xmlns:xsd=*"
http://www.w3.org/2001/XMLSchema"*xmlns:soap=*"
http://schemas.xmlsoap.org/wsdl/soap/"*>
<wsdl:types>
<xs:schema xmlns:xs=*"http://www.w3.org/2001/XMLSchema"*xmlns:tns=*"
http://test.portal.adp.com/"* elementFormDefault=*"unqualified"*
targetNamespace=*"http://test.portal.adp.com/"* version=*"1.0"*>
<xs:element name=*"methodA"* type=*"tns:methodA"*/>
<xs:element name=*"methodAResponse"* type=*"tns:methodAResponse"*/>
<xs:element name=*"methodB"* type=*"tns:methodB"*/>
<xs:element name=*"methodBResponse"* type=*"tns:methodBResponse"*/>
<xs:complexType name=*"methodA"*>
<xs:sequence/>
</xs:complexType>
<xs:complexType name=*"methodAResponse"*>
<xs:sequence>
<xs:element maxOccurs=*"unbounded"* minOccurs=*"0"* name=*"return"*
type=*"xs:anyType"*/>
</xs:sequence>
</xs:complexType>
<xs:complexType name=*"methodB"*>
<xs:sequence/>
</xs:complexType>
<xs:complexType name=*"methodBResponse"*>
<xs:sequence>
<xs:element maxOccurs=*"unbounded"* minOccurs=*"0"* name=*"return"*
type=*"xs:anyType"*/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name=*"methodBResponse"*>
<wsdl:part name=*"parameters"* element=*"tns:methodBResponse"*>
</wsdl:part>
</wsdl:message>
<wsdl:message name=*"methodAResponse"*>
<wsdl:part name=*"parameters"* element=*"tns:methodAResponse"*>
</wsdl:part>
</wsdl:message>
<wsdl:message name=*"methodB"*>
<wsdl:part name=*"parameters"* element=*"tns:methodB"*>
</wsdl:part>
</wsdl:message>
<wsdl:message name=*"methodA"*>
<wsdl:part name=*"parameters"* element=*"tns:methodA"*>
</wsdl:part>
</wsdl:message>
<wsdl:portType name=*"TestService"*>
<wsdl:operation name=*"methodA"*>
<wsdl:input name=*"methodA"* message=*"tns:methodA"*>
</wsdl:input>
<wsdl:output name=*"methodAResponse"* message=*"tns:methodAResponse"*>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name=*"methodB"*>
<wsdl:input name=*"methodB"* message=*"tns:methodB"*>
</wsdl:input>
<wsdl:output name=*"methodBResponse"* message=*"tns:methodBResponse"*>
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name=*"TestServiceServiceSoapBinding"* type=*
"tns:TestService"*>
<soap:binding style=*"document"* transport=*"
http://schemas.xmlsoap.org/soap/http"*/>
<wsdl:operation name=*"methodA"*>
<soap:operation soapAction=*""* style=*"document"*/>
<wsdl:input name=*"methodA"*>
<soap:body use=*"literal"*/>
</wsdl:input>
<wsdl:output name=*"methodAResponse"*>
<soap:body use=*"literal"*/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name=*"methodB"*>
<soap:operation soapAction=*""* style=*"document"*/>
<wsdl:input name=*"methodB"*>
<soap:body use=*"literal"*/>
</wsdl:input>
<wsdl:output name=*"methodBResponse"*>
<soap:body use=*"literal"*/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name=*"TestServiceService"*>
<wsdl:port name=*"TestServicePort"* binding=*
"tns:TestServiceServiceSoapBinding"*>
<soap:address location=*"http://localhost:9090/TestServicePort"*/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
2)Example using ArrayList.
*package* com.adp.portal.test;
*import* java.util.ArrayList;
*import* javax.jws.WebMethod;
*import* javax.jws.WebService;
@WebService(name="TestService")
*public* *class* TestService {
@WebMethod
*public* ArrayList<String> methodA(){
*return* *null*;
}
@WebMethod
*public* ArrayList<String> methodB(){
*return* *null*;
}
}
<?xml version=*"1.0"* encoding=*"UTF-8"*?>
<wsdl:definitions name=*"TestServiceService"*targetNamespace=*"
http://test.portal.adp.com/"*xmlns:wsdl=*"http://schemas.xmlsoap.org/wsdl/"*
xmlns:tns=*"http://test.portal.adp.com/"*xmlns:xsd=*"
http://www.w3.org/2001/XMLSchema"*xmlns:soap=*"
http://schemas.xmlsoap.org/wsdl/soap/"*>
<wsdl:types>
<xs:schema xmlns:xs=*"http://www.w3.org/2001/XMLSchema"*xmlns:tns=*"
http://test.portal.adp.com/"* elementFormDefault=*"unqualified"*
targetNamespace=*"http://test.portal.adp.com/"* version=*"1.0"*>
<xs:element name=*"methodA"* type=*"tns:methodA"*/>
<xs:element name=*"methodAResponse"* type=*"tns:methodAResponse"*/>
<xs:element name=*"methodB"* type=*"tns:methodB"*/>
<xs:element name=*"methodBResponse"* type=*"tns:methodBResponse"*/>
<xs:complexType name=*"methodA"*>
<xs:sequence/>
</xs:complexType>
<xs:complexType name=*"methodAResponse"*>
<xs:sequence>
<xs:element maxOccurs=*"unbounded"* minOccurs=*"0"* name=*"return"*
type=*"xs:string"*/>
</xs:sequence>
</xs:complexType>
<xs:complexType name=*"arrayList"*>
<xs:complexContent>
<xs:extension base=*"tns:abstractList"*>
<xs:sequence/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType abstract=*"true"* name=*"abstractList"*>
<xs:complexContent>
<xs:extension base=*"tns:abstractCollection"*>
<xs:sequence/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType abstract=*"true"* name=*"abstractCollection"*>
<xs:sequence/>
</xs:complexType>
<xs:complexType name=*"methodB"*>
<xs:sequence/>
</xs:complexType>
<xs:complexType name=*"methodBResponse"*>
<xs:sequence>
<xs:element maxOccurs=*"unbounded"* minOccurs=*"0"* name=*"return"*
type=*"xs:string"*/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name=*"methodBResponse"*>
<wsdl:part name=*"parameters"* element=*"tns:methodBResponse"*>
</wsdl:part>
</wsdl:message>
<wsdl:message name=*"methodAResponse"*>
<wsdl:part name=*"parameters"* element=*"tns:methodAResponse"*>
</wsdl:part>
</wsdl:message>
<wsdl:message name=*"methodB"*>
<wsdl:part name=*"parameters"* element=*"tns:methodB"*>
</wsdl:part>
</wsdl:message>
<wsdl:message name=*"methodA"*>
<wsdl:part name=*"parameters"* element=*"tns:methodA"*>
</wsdl:part>
</wsdl:message>
<wsdl:portType name=*"TestService"*>
<wsdl:operation name=*"methodA"*>
<wsdl:input name=*"methodA"* message=*"tns:methodA"*>
</wsdl:input>
<wsdl:output name=*"methodAResponse"* message=*"tns:methodAResponse"*>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name=*"methodB"*>
<wsdl:input name=*"methodB"* message=*"tns:methodB"*>
</wsdl:input>
<wsdl:output name=*"methodBResponse"* message=*"tns:methodBResponse"*>
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name=*"TestServiceServiceSoapBinding"* type=*
"tns:TestService"*>
<soap:binding style=*"document"* transport=*"
http://schemas.xmlsoap.org/soap/http"*/>
<wsdl:operation name=*"methodA"*>
<soap:operation soapAction=*""* style=*"document"*/>
<wsdl:input name=*"methodA"*>
<soap:body use=*"literal"*/>
</wsdl:input>
<wsdl:output name=*"methodAResponse"*>
<soap:body use=*"literal"*/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name=*"methodB"*>
<soap:operation soapAction=*""* style=*"document"*/>
<wsdl:input name=*"methodB"*>
<soap:body use=*"literal"*/>
</wsdl:input>
<wsdl:output name=*"methodBResponse"*>
<soap:body use=*"literal"*/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name=*"TestServiceService"*>
<wsdl:port name=*"TestServicePort"* binding=*
"tns:TestServiceServiceSoapBinding"*>
<soap:address location=*"http://localhost:9090/TestServicePort"*/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
The second example shows that when using ArrayList as the return type
apache cxf is creating complex types using JDK classes (arrayList,
abstractList abstractCollection). This is not desired in wsdl and it is
creating problems on the client side since it tries to generate this jdk
classes.
On Thu, Mar 14, 2013 at 8:30 PM, Florian Popescu
<[email protected]>wrote:
> I know it is a bit tricky to describe the issue here but the high level is
> that when generating a WSDL file using the java2ws tool (the tool itself or
> maven plugin have the same effect), I end up with a mostly correct WSDL
> file. Most of the WSDL file is as expected but I get 3 type definitions
> that should not be there in my opinion. They are modeling JDK classes and
> they are not referred to anywhere in the WSDL file. This is what I am
> talking about:
>
> <xs:complexType name="arrayList">
> <xs:complexContent>
> <xs:extension base="tns:abstractList">
> <xs:sequence/>
> </xs:extension>
> </xs:complexContent>
> </xs:complexType>
> <xs:complexType abstract="true" name="abstractList">
> <xs:complexContent>
> <xs:extension base="tns:abstractCollection">
> <xs:sequence/>
> </xs:extension>
> </xs:complexContent>
> </xs:complexType>
> <xs:complexType abstract="true" name="abstractCollection">
> <xs:sequence/>
> </xs:complexType>
>
> What is going on now is that I am running the opposite operation and
> generate Java VOs from this WSDL. Everything seems fine at first sight but
> when deployed I end up not being able to call any of the methods of this
> web service since CXF is complaining about improperly generated Java
> classes.
>
> I had this project running perfectly with the Metro stack and tooling and
> I am in the process of switching to CXF. Everything worked like a charm
> there and there were no references to any 'arrayList' or anything of that
> nature in the WSDL generated by Metro.
>
> I am using CXF 2.7.3 (I tried the same with 2.7.1 and 2.6.1 - same result)
> and JDK 6. I tried it with JDK 7 with same result again.
>
> I would appreciate some help on this!
>
> Thanks!
>
>