Scenarios
A: Client -> interface.java -> Databinding(JAXB) -> binding.sca -> Databinding(JAXB) -> interface.java -> Service (local)
B: Client -> interface.java -> Databinding(JAXB) -> binding.sca -> Databinding(JAXB) -> interface.java -> Service (@Remotable)
C: Client -> interface.java -> Databinding(JAXB) -> Databinding(Axiom) -> binding.ws -> interface.java -> Databindng(Axiom) -> Databinding(JAXB) -> Service (@Remotable)
D: Client -> interface.wsdl -> Databinding(JAXB) -> Databinding(Axiom) -> binding.ws -> interface.wsdl -> Databindng(Axiom) -> Databinding(JAXB) -> Service (@Remotable)
E: Client -> interface.java -> Databinding(JAXB) -> Databinding(Axiom) -> binding.ws -> interface.wsdl -> Databindng(Axiom) -> Databinding(JAXB) -> Service (@Remotable)
F: Client -> interface.wsdl -> Databinding(JAXB) -> Databinding(Axiom) -> binding.ws -> interface.java -> Databindng(Axiom) -> Databinding(JAXB) -> Service (@Remotable)
Support
Data Type | A | B | C doc/lit/wrapped | C doc/lit/bare | C ?wsdl | D | E | F | Notes |
---|---|---|---|---|---|---|---|---|---|
PrimitiveTypes |
|
|
|
|
|
|
|
| |
boolean |
|
|
|
|
|
|
|
|
|
byte |
|
|
|
|
|
|
|
|
|
short |
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
|
|
|
|
|
long |
|
|
|
|
|
|
|
|
|
float |
|
|
|
|
|
|
|
|
|
double |
|
|
|
|
|
|
|
|
|
Standard Types |
|
|
|
|
|
|
|
| |
java.lang.String |
|
|
|
|
|
|
|
|
|
java.math.BigInteger |
|
|
|
|
|
|
|
|
|
java.math.BigDecimal |
|
|
|
|
|
|
|
|
|
java.util.Calendar |
|
|
|
|
|
|
|
|
|
java.util.Date |
|
|
|
|
|
|
|
|
|
javax.xml.namespace.QName |
|
|
|
|
|
|
|
|
|
java.net.URI |
|
|
|
|
|
|
|
|
|
javax.xml.datatype.XMLGregorianCalendar |
|
|
|
|
|
|
|
|
|
javax.xml.datatype.Duration |
|
|
|
|
|
|
|
|
|
java.lang.Object |
|
|
|
|
|
|
|
|
|
java.awt.Image |
|
|
|
|
|
|
|
|
|
javax.activation.DataHandler |
|
|
|
|
|
|
|
|
|
javax.xml.transform.Source |
|
|
|
|
|
|
|
| How to compare two "source" objects? |
java.util.UUID |
|
|
|
|
|
|
|
|
|
Arrays |
|
|
|
|
|
|
|
| |
boolean |
|
|
|
|
|
|
|
|
|
byte |
|
|
|
|
|
|
|
|
|
short |
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
|
|
|
|
|
long |
|
|
|
|
|
|
|
|
|
float |
|
|
|
|
|
|
|
|
|
double |
|
|
|
|
|
|
|
|
|
java.lang.String |
|
|
|
|
|
|
|
|
|
java.math.BigInteger |
|
|
|
|
|
|
|
|
|
java.math.BigDecimal |
|
|
|
|
|
|
|
|
|
java.util.Calendar |
|
|
|
|
|
|
|
|
|
java.util.Date |
|
|
|
|
|
|
|
|
|
javax.xml.namespace.QName |
|
|
|
|
|
|
|
|
|
java.net.URI |
|
|
|
|
|
|
|
|
|
javax.xml.datatype.XMLGregorianCalendar |
|
|
|
|
|
|
|
|
|
javax.xml.datatype.Duration |
|
|
|
|
|
|
|
|
|
java.lang.Object |
|
|
|
|
|
|
|
|
|
java.awt.Image |
|
|
|
|
|
|
|
|
|
javax.activation.DataHandler |
|
|
|
|
|
|
|
|
|
javax.xml.transform.Source |
|
|
|
|
|
|
|
| How to compare two "source" objects? |
java.util.UUID |
|
|
|
|
|
|
|
|
|
Collections |
|
|
|
|
|
|
|
| |
List<String>, ArrayList<String> |
|
|
|
|
|
|
|
|
|
Map<String, String>, HashMap<String, String> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Polymorphic Types |
|
|
|
|
|
|
|
| |
Case1: Bean3 extends Bean2 |
|
|
|
|
|
|
|
|
|
Parameterized Types |
|
|
|
|
|
|
|
| |
TypeExplicit |
|
|
|
|
|
|
|
|
|
TypeUnbound |
|
|
|
|
|
|
|
|
|
TypeExtends |
|
|
|
|
|
|
|
|
|
RecursiveTypeBound |
|
|
|
|
|
|
|
|
|
WildcardUnbound |
|
|
|
|
|
|
|
|
|
WildcardSuper |
|
|
|
|
|
|
|
|
|
WildcardExtends |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Variable Arguments |
|
|
|
|
|
|
|
| |
String... |
|
|
|
|
|
|
|
|
|
Exceptions |
|
|
|
|
|
|
|
| |
|
|
|
|
|
|
|
|
|
|
The following are notes to give more detail of the scenarios and data types.
WSDL
see http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/
JAXWS2.1 describes the supported mappings and the restrictions these place on the Java interfaces.
- Docuement Wrapped
- Document Bare (The java method basically one in and one out parameter)
- RPC
A Service
Code Block |
---|
public interface HelloWorldService { public String getGreetings(String firstName, String lastName); } |
doc / lit / wrapped (The only one supported in Tuscany)
WSDL
Code Block |
---|
<wsdl:types> <schema elementFormDefault="qualified" targetNamespace="http://helloworld" xmlns="http://www.w3.org/2001/XMLSchema"> <element name="getGreetings"> <complexType> <sequence> <element name="firstName" type="xsd:string"/> <element name="lastName" type="xsd:string"/> </sequence> </complexType> </element> <element name="getGreetingsResponse"> <complexType> <sequence> <element name="getGreetingsReturn" type="xsd:string"/> </sequence> </complexType> </element> </schema> </wsdl:types> <wsdl:message name="getGreetingsRequest"> <wsdl:part element="tns:getGreetings" name="parameters"/> </wsdl:message> <wsdl:message name="getGreetingsResponse"> <wsdl:part element="tns:getGreetingsResponse" name="parameters"/> </wsdl:message> <wsdl:portType name="HelloWorld"> <wsdl:operation name="getGreetings"> <wsdl:input message="tns:getGreetingsRequest" name="getGreetingsRequest"/> <wsdl:output message="tns:getGreetingsResponse" name="getGreetingsResponse"/> </wsdl:operation> </wsdl:portType> <wsdl:binding name="HelloWorldSoapBinding" type="tns:HelloWorld"> <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="getGreetings"> <wsdlsoap:operation soapAction=""/> <wsdl:input name="getGreetingsRequest"> <wsdlsoap:body use="literal"/> </wsdl:input> <wsdl:output name="getGreetingsResponse"> <wsdlsoap:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding> |
SOAP
Code Block |
---|
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"> <Body> <ns1:getGreetingsxmlns:ns1="http://helloworld"> <ns1:firstName>fred</ns1:firstName> <ns1:secondNameName>bloggs</ns1:secondName> </ns1:getGreetings> </Body> </Envelope> |
doc / lit / bare (unwrapped) wsdl
There is some support but we need to find the tests
rpc / literal
We don't support this in Tuscany
rpc / encoded
We don't support this in Tuscany
Not WS-I compliant
in/out, out params & Holders
Excluded by SCA
Discussed in JAXWS
There is a JIRA http://issues.apache.org/jira/browse/TUSCANY-2332
Namespaces
What do we need to say about this?
XSD (JAXB)
Am assuming as JAXB 2.1 (6)
Java (JAXB)
Primitive Types
As JAXB 2.1 (8.5.1)
Code Block |
---|
boolean byte short int long float double |
Standard Types
As JAXB 2.1 (8.5.2)
Code Block |
---|
java.lang.String java.math.BigInteger java.math.BigDecimal java.util.Calendar java.util.Date javax.xml.namespace.QName java.net.URI javax.xml.datatype.XMLGregorianCalendar javax.xml.datatype.Duration java.lang.Object java.awt.Image javax.activation.DataHandler javax.xml.transform.Source java.util.UUID |
Parameterized Types/Generics
As JAXB (8.5.3)
XSD generated using wsgen
Some beans
Code Block |
---|
class Bean1<T> { T item; } <xs:complexType name="bean1"> <xs:sequence> <xs:element name="item" type="xs:anyType" minOccurs="0"/> </xs:sequence> </xs:complexType> |
Code Block |
---|
class Bean2 { String name } <xs:complexType name="bean2"> <xs:sequence> <xs:element name="name" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:complexType> |
Code Block |
---|
class Bean3 extends Bean2{ String address } |
Code Block |
---|
class Bean4<T extends Bean2> { T aType; } |
Code Block |
---|
class Bean5 extends Bean1<String>{ } |
Code Block |
---|
class Bean6<T extends Bean5<String>> { T aType; } |
Method with explicit type -> type
Code Block |
---|
Bean1<String> someMethodTypeExplicit(Bean1<String>) |
Code Block |
---|
<xs:complexType name="someMethodTypeExplicit"> <xs:sequence> <xs:element name="arg0" type="tns:bean1" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:complexType name="someMethodTypeExplicitResponse"> <xs:sequence> <xs:element name="return" type="tns:bean1" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:element name="someMethodTypeExplicit" type="tns:someMethodTypeExplicit"/> <xs:element name="someMethodTypeExplicitResponse" type="tns:someMethodTypeExplicitResponse"/> <message name="someMethodTypeExplicit"> <part name="parameters" element="tns:someMethodTypeExplicit"/> </message> <message name="someMethodTypeExplicitResponse"> <part name="parameters" element="tns:someMethodTypeExplicitResponse"/> </message> |
Method without type bound -> any
Code Block |
---|
<T> Bean1<T> someMethodTypeUnbound(T[] anArray) |
Code Block |
---|
<xs:complexType name="someMethodTypeUnbound"> <xs:sequence> <xs:element name="arg0" type="xs:anyType" nillable="true" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="someMethodTypeUnboundResponse"> <xs:sequence> <xs:element name="return" type="tns:bean1" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:element name="someMethodTypeUnbound" type="tns:someMethodTypeUnbound"/> <xs:element name="someMethodTypeUnboundResponse" type="tns:someMethodTypeUnboundResponse"/> <message name="someMethodTypeUnbound"> <part name="parameters" element="tns:someMethodTypeUnbound"/> </message> <message name="someMethodTypeUnboundResponse"> <part name="parameters" element="tns:someMethodTypeUnboundResponse"/> </message> |
Method with type extends -> type
Code Block |
---|
<T extends Bean2> Bean1<T> someMethodTypeExtends(T[] anArray) |
Code Block |
---|
<xs:complexType name="someMethodTypeExtends"> <xs:sequence> <xs:element name="arg0" type="tns:bean2" nillable="true" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="someMethodTypeExtendsResponse"> <xs:sequence> <xs:element name="return" type="tns:bean1" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:element name="someMethodTypeExtends" type="tns:someMethodTypeExtends"/> <xs:element name="someMethodTypeExtendsResponse" type="tns:someMethodTypeExtendsResponse"/> <message name="someMethodTypeExtends"> <part name="parameters" element="tns:someMethodTypeExtends"/> </message> <message name="someMethodTypeExtendsResponse"> <part name="parameters" element="tns:someMethodTypeExtendsResponse"/> </message> |
Method with type super -> type
Code Block |
---|
NOT SURE THIS IS VALID <T super Bean3> Bean1<T> someMethodTypeSuper(T[] anArray) |
This is not a valid construct.
Type variable with recursive type extends-> type
Code Block |
---|
<T extends Bean1<String>> Bean1<T> someMethodRecursiveTypeBound(T[] anArray) |
Code Block |
---|
<xs:complexType name="someMethodRecursiveTypeBound"> <xs:sequence> <xs:element name="arg0" type="tns:bean1" nillable="true" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="someMethodRecursiveTypeBoundResponse"> <xs:sequence> <xs:element name="return" type="tns:bean1" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:element name="someMethodRecursiveTypeBound" type="tns:someMethodRecursiveTypeBound"/> <xs:element name="someMethodRecursiveTypeBoundResponse" type="tns:someMethodRecursiveTypeBoundResponse"/> <message name="someMethodRecursiveTypeBound"> <part name="parameters" element="tns:someMethodRecursiveTypeBound"/> </message> <message name="someMethodRecursiveTypeBoundResponse"> <part name="parameters" element="tns:someMethodRecursiveTypeBoundResponse"/> </message> |
Wildcard without bounds -> any
Code Block |
---|
Bean1<?> someMethodWildcardUnbound(Bean1<?>) |
Code Block |
---|
<xs:complexType name="someMethodWildcardUnbound"> <xs:sequence> <xs:element name="arg0" type="tns:bean1" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:complexType name="someMethodWildcardUnboundResponse"> <xs:sequence> <xs:element name="return" type="tns:bean1" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:element name="someMethodWildcardUnbound" type="tns:someMethodWildcardUnbound"/> <xs:element name="someMethodWildcardUnboundResponse" type="tns:someMethodWildcardUnboundResponse"/> <message name="someMethodWildcardUnbound"> <part name="parameters" element="tns:someMethodWildcardUnbound"/> </message> <message name="someMethodWildcardUnboundResponse"> <part name="parameters" element="tns:someMethodWildcardUnboundResponse"/> </message> |
Wildcard with super type -> any
Code Block |
---|
Bean1<? super Bean3> someMethodWildcardSuper(Bean1<? super Bean3>) |
Code Block |
---|
<xs:complexType name="someMethodWildcardSuper"> <xs:sequence> <xs:element name="arg0" type="tns:bean1" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:complexType name="someMethodWildcardSuperResponse"> <xs:sequence> <xs:element name="return" type="tns:bean1" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:element name="someMethodWildcardSuper" type="tns:someMethodWildcardSuper"/> <xs:element name="someMethodWildcardSuperResponse" type="tns:someMethodWildcardSuperResponse"/> <message name="someMethodWildcardSuper"> <part name="parameters" element="tns:someMethodWildcardSuper"/> </message> <message name="someMethodWildcardSuperResponse"> <part name="parameters" element="tns:someMethodWildcardSuperResponse"/> </message> |
Wildcard with extends type -> type
Code Block |
---|
Bean1<? extends Bean2> someMethodWildcardExtends(Bean1<? extends Bean2>) |
Code Block |
---|
<xs:complexType name="someMethodWildcardExtends"> <xs:sequence> <xs:element name="arg0" type="tns:bean1" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:complexType name="someMethodWildcardExtendsResponse"> <xs:sequence> <xs:element name="return" type="tns:bean1" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:element name="someMethodWildcardExtends" type="tns:someMethodWildcardExtends"/> <xs:element name="someMethodWildcardExtendsResponse" type="tns:someMethodWildcardExtendsResponse"/> <message name="someMethodWildcardExtends"> <part name="parameters" element="tns:someMethodWildcardExtends"/> </message> <message name="someMethodWildcardExtendsResponse"> <part name="parameters" element="tns:someMethodWildcardExtendsResponse"/> </message> |
Collections
As JAXB 2.1 (8.5.4)
- java.util.Map and its subtypes
Code Block HashMap<String, Bean> someMethod(HashMap<String, Bean> aList)
- java.util.Collection and its subtypes
Code Block List<String> someMethod(List<String> aList)
- Arrays
Code Block String[] someMethod (String[], String[]) Bean1[1] someMethod(Bean1[], Bean1[])
- Java Bean Indexed properties (effectively arrays)
Polymorphic Types
xsi:type
Case 1:
Code Block |
---|
class Bean2 { } class Bean3 extends Bean2 { } Bean2 someMethod(Bean2) ref.someMethod(Bean3) |
Variable Arguments
Code Block |
---|
String someMethod(String... params) |
Business Exceptions/Faults
This section describes Tuscany's Java<-->WSDL mapping for business exceptions on remotable interfaces.
Top-Down (start with WSDL fault)
Start with a WSDL portType, with a fault message defined in terms of a fault elem and generate the Java from that. If you use a tool like wsimport which you'll get a generated Java exception wrappering a fault in the JAX-WS Sec. 2.5 pattern. That's it. The top-down case is a lot simpler.
Bottom-Up (start with Java checked exception)
First, it might not be a best practice to design a remotable interface which throws a technology exception, e.g. java.sql.SQLException. This might be more appropriate for a local interface rather than a coarse-grained remotable interface.
If you're working bottom-up from Java and you have a genuine Java business exception, well, it does get a bit ugly, at least if your exception wrappers fault data (i.e. it wrappers some data like an error code or object which it needs to convey). If your exception only contains a String 'message', then you won't experience the pain.
There are two options:
- Converts the exception to follow the JAX-WS Section 2.5 pattern (getFaultInfo(), ctor with faultBean as parm)
- Rely on our Tuscany interpretation/implementation the JAX-WS Sec 3.7 pattern. This basically works the same whether you run a dev-time tool which supports this pattern (like wsgen) or if you leverage the runtime WSDL2Java.
Of these, the first is better, and if you are willing/able to modify your Java business exception in this fashion, you gain the ability to use this exception as part of the client programming model. The downside is it requires developer understanding of the pattern and the ability and effort to modify the exception.
The second option will be used in both the case where the user won't/can't change the exception class and also the case where the user is ignorant of the WSDL mapping.
In either of those two cases, as long as the exception doesn't contain fault data, this will "just work" without any complexity seen by the user. For exceptions with fault data, the data will be handled correctly (or not) field by field. For each exception data field with a public getter/setter (i.e. we will serialize the exception by viewing it as a JavaBean) we will handle the data correctly (and we will lose the data without a getter/setter pair.
Some issues with this second option:
- It won't be obvious to a user what the supported pattern is. One exception, even though it has fault data (with getter/setter) is handled correctly while another is not. Running wsgen at development time is no help either, since this generates the schema based on the exception's getters without assuring that the corresponding setters exist in order to populate the exception during unmarshalling.
This seems an area for improvement, either by issuing warnings somewhere along the way or if we ever factor the Tuscany J2W functionality into a dev-time tool.
- If you run W2J against the generated WSDL you will end up with a different exception class (which does follow the Sec 2.5 pattern). So your client/service programming model are different which might confuse the Java-centered programmer. You might even need to add a JAXB customization to get around some mapping quirks to generate the client, and you might see weird names like MyException_Exception.
Tuscany
TODO - Add some details of which bits of tuscany do what w.r.t databindings, mappings and transformations in typical scenarios, e.g.
Code Block |
---|
<component name="HelloWorldClientComponent"> <implementation.java class="helloworld.HelloWorldClientImpl" /> <reference name="helloWorldService"> <interface.wsdl interface="http://helloworld#wsdl.interface(HelloWorld)" /> <binding.ws uri="http://localhost:8085/HelloWorldService"/> </reference> </component> <component name="HelloWorldServiceComponent"> <implementation.java class="helloworld.HelloWorldImpl" /> <service name="HelloWorldService"> <interface.wsdl interface="http://helloworld#wsdl.interface(HelloWorld)" /> <binding.ws uri="http://localhost:8085/HelloWorldService"/> </service> </component> |
Where all the conversions and mapping happen.
- databinding mapping - Creates in memory models of the WSDL interfaces and the java introspected component types.
- interface contract mapper - Checks compatibility of
- interfaces with component types
- references with services
Code Block |
---|
<service name="HelloWorldService"> <interface.java ... |
Would lead to a java2wsdl mapping -
1 Specs
- SCA
- JAXWS
- JAXB
- WS-I
- WSDL
- ?