|
The problem is not so much the mapping of
vector. At least, it is possible to map it to soap and back to java.
Also there is a mapping to/from c#. It uses object [] to map to
this. I've attached some sample files. The original service is in
CustomerServicex.java. I've cleaned this up from some real code I have so
don't worry if there are minor compile errors or the class name doesn't match
the file name. The CustomerService class defines my web service. One
of the methods is getContactsByMemberID. This method returns a
Vector. Presumably this will be filled with references to Contact
objects. Works great in java/rmi/ejb land. Problem is that although
a reasonable mapping happens to soap via a complex type called Vector that is
unbounded and supports xsd:anyType, and although this maps reasonably to a c#
type of object [], the problem happens at run time. If I pass data
through this that can't be serialized I get an exception. Can't be
predicted at compile time because Vector is a collection of 'untyped'
objects. OK, I know that Object is a type, but that's not the point.
You don't know if it's a Contact object that can be serialized or if it is some
FooBar object that cannot be. Plus, the wsdl doesn't know for sure what it
is going across, so it can't for sure have described the complex
type.
I've used C# as the sample client because I figure
it's a reasonable test - service in java, client in c#. I've decided to
always create service interfaces that have completely typed collections.
This means mapping a vector to a typed array. Shouldn't be a
problem. The service interface can still be non-specific relative to the
number of elements of the array. Plus, you aren't going to try to hand
someone a reference to a collection for them to add to it anyway, so the point
of a dynamic collection is lost anyway. Only problem is if you really do
have a collection of heterogeneous object types. If so, you probably want
to figure out a different service interface anyway.
Hope this helps. Also hope that the
attachments come through on the list. I'm more of a lurker, so
contributing to lists is new to me.
tc
|
Contact.java
Description: Binary data
CustomerServicex.java
Description: Binary data
//------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version: 1.0.3705.288 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------
//
// This source code was auto-generated by wsdl, Version=1.0.3705.288.
//
using System.Diagnostics;
using System.Xml.Serialization;
using System;
using System.Web.Services.Protocols;
using System.ComponentModel;
using System.Web.Services;
/// <remarks/>
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(Name="customerserviceSoapBinding",
Namespace="http://customerService.x.com")]
public class CustomerServiceService :
System.Web.Services.Protocols.SoapHttpClientProtocol {
/// <remarks/>
public CustomerServiceService() {
this.Url = "http://localhost:8080/axis/services/customerservice";
}
/// <remarks/>
[System.Web.Services.Protocols.SoapRpcMethodAttribute("",
RequestNamespace="http://customerService.x.com",
ResponseNamespace="http://customerService.x.com")]
public void addContact(Contact in0, Action in1, ID in2) {
this.Invoke("addContact", new object[] {
in0,
in1,
in2});
}
/// <remarks/>
public System.IAsyncResult BeginaddContact(Contact in0, Action in1, ID in2,
System.AsyncCallback callback, object asyncState) {
return this.BeginInvoke("addContact", new object[] {
in0,
in1,
in2}, callback, asyncState);
}
/// <remarks/>
public void EndaddContact(System.IAsyncResult asyncResult) {
this.EndInvoke(asyncResult);
}
/// <remarks/>
[System.Web.Services.Protocols.SoapRpcMethodAttribute("",
RequestNamespace="http://customerService.x.com",
ResponseNamespace="http://customerService.x.com")]
public void updateContact(Contact in0) {
this.Invoke("updateContact", new object[] {
in0});
}
/// <remarks/>
public System.IAsyncResult BeginupdateContact(Contact in0, System.AsyncCallback
callback, object asyncState) {
return this.BeginInvoke("updateContact", new object[] {
in0}, callback, asyncState);
}
/// <remarks/>
public void EndupdateContact(System.IAsyncResult asyncResult) {
this.EndInvoke(asyncResult);
}
/// <remarks/>
[System.Web.Services.Protocols.SoapRpcMethodAttribute("",
RequestNamespace="http://customerService.x.com",
ResponseNamespace="http://customerService.x.com")]
[return:
System.Xml.Serialization.SoapElementAttribute("getContactsByMemberIDReturn")]
public Vector getContactsByMemberID(ID in0) {
object[] results = this.Invoke("getContactsByMemberID", new object[] {
in0});
return ((Vector)(results[0]));
}
/// <remarks/>
public System.IAsyncResult BegingetContactsByMemberID(ID in0, System.AsyncCallback
callback, object asyncState) {
return this.BeginInvoke("getContactsByMemberID", new object[] {
in0}, callback, asyncState);
}
/// <remarks/>
public Vector EndgetContactsByMemberID(System.IAsyncResult asyncResult) {
object[] results = this.EndInvoke(asyncResult);
return ((Vector)(results[0]));
}
}
/// <remarks/>
[System.Xml.Serialization.SoapTypeAttribute("Contact", "http://bom.x.com")]
public class Contact {
/// <remarks/>
public int contactID;
/// <remarks/>
public string contactName;
/// <remarks/>
public string contactPhone;
}
/// <remarks/>
[System.Xml.Serialization.SoapTypeAttribute("Vector",
"http://xml.apache.org/xml-soap")]
public class Vector {
/// <remarks/>
public object[] item;
}
/// <remarks/>
[System.Xml.Serialization.SoapTypeAttribute("ID", "http://bom.x.com")]
public class ID {
/// <remarks/>
[System.Xml.Serialization.SoapElementAttribute("ID")]
public int ID1;
}
/// <remarks/>
[System.Xml.Serialization.SoapTypeAttribute("Action", "http://bom.x.com")]
public class Action {
}
CustomerService.wsdl
Description: Binary data
