WSDL first development? Are they crazy?
From the CXF user guide: ” For new development the preferred path is to design your services in WSDL and then generate the code to implement them.”
Are they insane?
Which would you rather write by hand….
a)
@WebService(
endpointInterface = "com.southwind.PersonFacade",
name = "PersonFacade"
)
public interface PersonFacade {
@WebMethod()
public Person getPerson(@WebParam(name="ssn") String ssn);
}
b)
<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions name="PersonFacadeImplService" targetNamespace="http://southwind.com/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://southwind.services.enrollment.bf/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <wsdl:types> <xs:schema attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="http://southwind.com/" xmlns:tns="http://southwind.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="findPerson" type="tns:findPerson" /> <xs:element name="findPersonResponse" type="tns:findPersonResponse" /> <xs:element name="getPerson" type="tns:getPerson" /> <xs:element name="getPersonResponse" type="tns:getPersonResponse" /> <xs:complexType name="getPerson"> <xs:sequence> <xs:element minOccurs="0" name="ssn" type="xs:string" /> </xs:sequence> </xs:complexType> <xs:complexType name="getPersonResponse"> <xs:sequence> <xs:element minOccurs="0" name="return" type="tns:person" /> </xs:sequence> </xs:complexType> <xs:complexType name="person"> <xs:sequence> <xs:element minOccurs="0" name="birthday" type="xs:dateTime" /> <xs:element maxOccurs="unbounded" minOccurs="0" name="enrollments" nillable="true" type="tns:enrollment" /> <xs:element minOccurs="0" name="firstName" type="xs:string" /> <xs:element minOccurs="0" name="lastName" type="xs:string" /> <xs:element minOccurs="0" name="ssn" type="xs:string" /> </xs:sequence> </xs:complexType> <xs:complexType name="enrollment"> <xs:sequence> <xs:element minOccurs="0" name="planName" type="xs:string" /> <xs:element name="planRate" type="xs:double" /> <xs:element minOccurs="0" name="type" type="tns:type" /> </xs:sequence> </xs:complexType> <xs:complexType name="findPerson"> <xs:sequence> <xs:element minOccurs="0" name="id" type="xs:string" /> </xs:sequence> </xs:complexType> <xs:complexType name="findPersonResponse"> <xs:sequence> <xs:element minOccurs="0" name="return" type="tns:person" /> </xs:sequence> </xs:complexType> <xs:simpleType name="type"> <xs:restriction base="xs:string"> <xs:enumeration value="MEDICAL" /> <xs:enumeration value="DENTAL" /> <xs:enumeration value="VISION" /> <xs:enumeration value="PHARM" /> </xs:restriction> </xs:simpleType> </xs:schema> </wsdl:types> <wsdl:message name="findPerson"> <wsdl:part element="tns:findPerson" name="parameters"> </wsdl:part> </wsdl:message> <wsdl:message name="findPersonResponse"> <wsdl:part element="tns:findPersonResponse" name="parameters"> </wsdl:part> </wsdl:message> <wsdl:message name="getPersonResponse"> <wsdl:part element="tns:getPersonResponse" name="parameters"> </wsdl:part> </wsdl:message> <wsdl:message name="getPerson"> <wsdl:part element="tns:getPerson" name="parameters"> </wsdl:part> </wsdl:message> <wsdl:portType name="PersonFacade"> <wsdl:operation name="getPerson"> <wsdl:input message="tns:getPerson" name="getPerson"> </wsdl:input> <wsdl:output message="tns:getPersonResponse" name="getPersonResponse"> </wsdl:output> </wsdl:operation> <wsdl:operation name="findPerson"> <wsdl:input message="tns:findPerson" name="findPerson"> </wsdl:input> <wsdl:output message="tns:findPersonResponse" name="findPersonResponse"> </wsdl:output> </wsdl:operation> </wsdl:portType> <wsdl:binding name="PersonFacadeImplServiceSoapBinding" type="tns:PersonFacade"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="getPerson"> <soap:operation soapAction="" style="document" /> <wsdl:input name="getPerson"> <soap:body use="literal" /> </wsdl:input> <wsdl:output name="getPersonResponse"> <soap:body use="literal" /> </wsdl:output> </wsdl:operation> <wsdl:operation name="findPerson"> <soap:operation soapAction="" style="document" /> <wsdl:input name="findPerson"> <soap:body use="literal" /> </wsdl:input> <wsdl:output name="findPersonResponse"> <soap:body use="literal" /> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="PersonFacadeImplService"> <wsdl:port binding="tns:PersonFacadeImplServiceSoapBinding" name="PersonFacadeImplPort"> <soap:address location="http://mturanskylptp2:9000/personFacade" /> </wsdl:port> </wsdl:service> </wsdl:definitions>
Categories: Technology
Don’t drop the SOAP!
If you don’t need the interoperability WSDL offers, check out Facebook’s Thrift or Google’s Protocol Buffers (which they just open-sourced)
What, you got something else to do?
I’ve run into this situation with an internal team, but I can’t believe it is being recommended as a best practice on one of the premier web services frameworks. WSDL is so clearly not intended to written by or read by human beings, I don’t understand how developers get this equation so wrong. Having CXF document this as a best practice is, frankly, astounding to me and makes me weep for the future. Development just keeps getting more and more insane every year.
Looks like a very bad case of the Abstract Inversion sindrome.
(http://c2.com/cgi-bin/wiki?AbstractionInversion)
I don’t ever want to type that many “less than” characters in my blog.
Well, It is good approach when you are looking for the service interface perspective. Unfortunately, there are not many tools at this stage that is helping this approach. It may not make sense for someone who are planning to write bunch of webservices and expose them, but this approach helps when you have a larger eneterprise systems with a lot of servcies to be designed.
There things you can express in schema that you can not in java. xs:choice comes to mind. So,
would look like this in in java
class Blah {
String el1;
String el2
}
I guess you could argue that annotations could be used to specify the choice but that would be just as painful.
Then you got max/min number of elements, xs:restrictions (re-defined collections of children), and there are probably more.
better yet, express your service contract in XSD, generate xml->java binding objects using JAXB, and annotate service methods using JSR-181.
When xfire/cxf say “WSDL first”, what they mean conceptually is “Contract First”. They have just chosen to start with WSDL because it is less complex (single file).
Just using JSR-181 to annotate service methods but using java-based parameters that are automagically converted to WSDL can lead to arbitrary interface changes as developers refactor. XSD->Java using JAXB helps with this because WSDL uses XSD to describe endpoint messages, so the Java->WSDL generation is cleaner.
It’s callled “contract first development” and makes a lot of sense on large integrations.
Working in XSD is easy once you get the hang of it, and works across all platforms/languages etc..
http://static.springsource.org/spring-ws/sites/1.5/reference/html/why-contract-first.html
http://msdn.microsoft.com/en-us/magazine/cc163783.aspx