Hi,
I tried to exchange the following data structure over SOAP by using SOAP 2.2
Bean Serializer class
public class Employee implements Serializable
{
// not null
public String name;
// null if no manager
public Employee manager;
// null if no subordinates,this is a Employee Vector
public Vector subordinates;
}
It runs into the following serialization problem:
<stackTrace>
<detail>
java.lang.StackOverflowError
at java.lang.Class.toString(Class.java:82)
at java.lang.String.valueOf(String.java:1925)
at
org.apache.soap.util.xml.XMLJavaMappingRegistry.getKey(XMLJavaMappingRegistr
y.java:265)
at
org.apache.soap.util.xml.XMLJavaMappingRegistry.queryElementType(XMLJavaMapp
ingRegistry.java:192)
at
org.apache.soap.encoding.SOAPMappingRegistry.queryElementType(SOAPMappingReg
istry.java:460)
at
org.apache.soap.encoding.soapenc.SoapEncUtils.generateStructureHeader(SoapEn
cUtils.java:129)
at
org.apache.soap.encoding.soapenc.SoapEncUtils.generateStructureHeader(SoapEn
cUtils.java:116)
at
org.apache.soap.encoding.soapenc.BeanSerializer.marshall(BeanSerializer.java
:86)
at
org.apache.soap.util.xml.XMLJavaMappingRegistry.marshall(XMLJavaMappingRegis
try.java:238)
at
org.apache.soap.encoding.soapenc.ArraySerializer.marshall(ArraySerializer.ja
va:133)
......
......
......
at
org.apache.soap.encoding.soapenc.BeanSerializer.marshall(BeanSerializer.java
:131)
</stackTrace>
</detail>
</SOAP-ENV:Fault>
Basically I found out that SOAP 2.2 BeanSerializer can not handle Employee
class having
subordinate field as a Vector of Employee (or Employee[]). When I shanged
subordinates field
to Vector of String (or String[]) there was no StackOverflow problem. There
is no problem in
exchanging this data structure over EJB (i.e Java RMI). I also found out
that SOAP 2.2 XML
serialization does not implement reference semantics as it is done in basic
Java/RMI serialization.
What this means is that XML messages tend to be very large in situations
where Employee contains
reference to another Employee(i.e manager). What SOAP 2.2 BeanSerializer
does is to LITERALLY
INCLUDE ALL DETAILS OF MANAGER in EACH SUBORDINATE OF THAT MANAGER.
This is very naive implementation and will cause very large XML messages.
XML permits ID, IDERF,
why not use that? Why to literally REPEAT Manager details in each Employee?
Can somebody from SOAP development team confirm that these are indeed
BeanSerializer bug/shortcomings?
I am attaching complete Employee class below.
Regards,
Soumen Sarkar
Atoga Systems Inc. (http://www.atoga.com)
510-743-0254
Employee class
------------------------
//Writing Employee as an ideal bean by providing get and set methods
package AnotherEmployeeSLBean;
import java.io.*;
import java.util.*;
public class Employee implements Serializable
{
// not null
public String name;
// null if no manager
public Employee manager;
// null if no subordinates,this is a Employee Vector
public Vector subordinates;
// not null
public String ssn;
public double salary;
// null if no dependents
public Dependent[] dependents;
public Employee()
{ }
public Employee(String name,Employee manager,Employee[] subordinates,String
ssn,double salary,Dependent[] dependents)
{ this.name = name;
this.manager = manager;
this.subordinates = subordinates;
this.ssn = ssn;
this.salary = salary;
this.dependents = dependents;
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Employee getManager() { return manager; }
public void setManager(Employee manager) { this.manager = manager; }
public Vector getSubordinates() { return subordinates; }
public void setSubordinates(Vector subordinates) { this.subordinates =
subordinates; }
public String getSsn() { return ssn; }
public void setSsn(String ssn) { this.ssn = ssn; }
public double getSalary() { return salary; }
public void setSalary(double salary) { this.salary = salary; }
public Dependent[] getDependents() { return dependents; }
public void setDependents(Dependent[] dependents) { this.dependents =
dependents; }
public String toString()
{ String retVal = "Employee" + "\n"; retVal += "{" + "\n";
retVal += "name = " + name + "\n";
retVal += "ssn = " + ssn + "\n";
retVal += "salary = " + salary + "\n";
retVal += "manager = " + manager + "\n";
if(subordinates!= null)
{ retVal += "Subordinates are:";
for(int i = 0; i < subordinates.size(); ++i)
{ retVal += subordinates.elementAt(i)+ "\n"; }
}
if(dependents!= null)
{ retVal += "Dependents are:";
for(int i = 0; i < dependents.length; ++i) { retVal += dependents[i]+ "\n";
}
}
retVal += "}" + "\n"; return retVal;
}
}
//Writing Dependent as an ideal bean by providing get and set methods
package AnotherEmployeeSLBean;
import java.io.*;
public class Dependent implements Serializable
{
public String name;
public int age;
public String relationship;
public Dependent(String name,int age,String relationship)
{ this.name = name; this.age = age; this.relationship = relationship; }
public Dependent() { }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public String getRelationship() { return relationship; }
public void setRelationship(String relationship) { this.relationship =
relationship; }
public String toString()
{ String retVal = "Dependent" + "\n";
retVal += "{" + "\n";
retVal += "name = " + name + "\n";
retVal += "age = " + age + "\n";
retVal += "relationship = " + relationship + "\n";
retVal += "}" + "\n"; return retVal;
}
}