You are viewing a plain text version of this content. The canonical link for it is here.
Posted to soap-user@ws.apache.org by "Jacob S. Barrett" <jb...@amduat.net> on 2001/08/17 22:50:11 UTC

Returning Multiple Arrays and Multidimentional Arrays

I am running into some problems returning multiple arrays and multiple
multidimentional arrays.  I am using SOAP 2.2 and Xerces 1.4.2.

The provider (totally moched up so don't laugh at me) code fragment
below compiles, runs and appears to responde ok:
  >>>>
java.util.Vector params = new java.util.Vector();
params.add(new Parameter("Customers_Customer_CustomerID",
String[].class, new String[] {"1", "2"}, Constants.NS_URI_SOAP_ENC));
params.add(new Parameter("Customers_Customer_ContactTitle",
String[].class, new String[] {"CEO", "President"},
Constants.NS_URI_SOAP_ENC));
params.add(new Parameter("Customers_Customer_Country",String[].class,
new String[] {"US", "DE"}, Constants.NS_URI_SOAP_ENC));
params.add(new Parameter("Customers_Customer_Addresses_Address_Label",
String[][].class, new String[][] {new String[] {"home", "office"}, new
String[] {"home", "batcave"}}, Constants.NS_URI_SOAP_ENC));
params.add(new Parameter("Customers_Customer_Addresses_Address_Street",
String[][].class, new String[][] {new String[] {"12345 Fake St.", "54321
Saint Fake Ln."}, new String[] {"10100 Binary Rd.", "1 Dark Road"}},
Constants.NS_URI_SOAP_ENC));
params.add(new Parameter("Customers_Customer_Addresses_Address_City",
String[][].class, new String[][] {new String[] {"Springfield",
"Shelbyville"}, new String[] {"Komputar", "Ubertown"}},
Constants.NS_URI_SOAP_ENC));
params.add(new Parameter("Customers_Customer_Addresses_Address_State",
String[][].class, new String[][] {new String[] {"IL", "IL"}, new
String[] {"MU", "MU"}}, Constants.NS_URI_SOAP_ENC));
params.add(new Parameter("Customers_Customer_Addresses_Address_Zip",
String[][].class, new String[][] {new String[] {"86213", "86321"}, new
String[] {"HFD234", "HFD567"}}, Constants.NS_URI_SOAP_ENC));
params.add(new Parameter("Customers_Customer_Age", String[].class, new
String[] {"45", "35"}, Constants.NS_URI_SOAP_ENC));
try
{

      Response resp = new Response(m_TargetObjectURI, // URI
          m_MethodName, // Method
          new Parameter("Result", Boolean.class, new Boolean(true),
Constants.NS_URI_SOAP_ENC), // ReturnValue
          params, // Params
          null, // Header
          Constants.NS_URI_SOAP_ENC, // encoding
          responseContext); // response soapcontext - not supported yet

      Envelope env = resp.buildEnvelope();
      StringWriter sw = new StringWriter();
      env.marshall(sw, m_Call.getSOAPMappingRegistry(), responseContext);
      responseContext.setRootPart(sw.toString(),
Constants.HEADERVAL_CONTENT_TYPE_UTF8);
}
catch (Exception e)
<<<<

With the test client code below:
  >>>>
Call call = new Call();
call.setTargetObjectURI("urn:eightball-simple-request");
call.setMethodName("fortune");
Response resp = call.invoke(
      new java.net.URL("http://localhost:8080/soap/servlet/rpcrouter"),
"urn:eightball-simple-request");
if (resp.generatedFault())
{
      Fault fault = resp.getFault();
      System.out.println(fault.toString());
      fail(fault.toString());
}
else
{
      Parameter ret = resp.getReturnValue();
      System.out.println(ret.getValue().toString());
}

I get the following evelopes:
  >>>>
<?xml version='1.0' encoding='UTF-8'?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:fortune xmlns:ns1="urn:eightball-simple-request">
</ns1:fortune>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
<<<<
 >>>>
<?xml version='1.0' encoding='UTF-8'?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:fortuneResponse xmlns:ns1="urn:eightball-simple-request"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<Result xsi:type="xsd:boolean">true</Result>
<Customers_Customer_CustomerID
xmlns:ns2="http://schemas.xmlsoap.org/soap/encoding/" 
xsi:type="ns2:Array" ns2:arrayType="xsd:string[2]">
<item xsi:type="xsd:string">1</item>
<item xsi:type="xsd:string">2</item>
</Customers_Customer_CustomerID>
<Customers_Customer_ContactTitle
xmlns:ns3="http://schemas.xmlsoap.org/soap/encoding/" 
xsi:type="ns3:Array" ns3:arrayType="xsd:string[2]">
<item xsi:type="xsd:string">CEO</item>
<item xsi:type="xsd:string">President</item>
</Customers_Customer_ContactTitle>
<Customers_Customer_Country
xmlns:ns4="http://schemas.xmlsoap.org/soap/encoding/" 
xsi:type="ns4:Array" ns4:arrayType="xsd:string[2]">
<item xsi:type="xsd:string">US</item>
<item xsi:type="xsd:string">DE</item>
</Customers_Customer_Country>
<Customers_Customer_Addresses_Address_Label
xmlns:ns5="http://schemas.xmlsoap.org/soap/encoding/" 
xsi:type="ns5:Array" ns5:arrayType="ns5:Array[2]">
<item xsi:type="ns5:Array" ns5:arrayType="xsd:string[2]">
<item xsi:type="xsd:string">home</item>
<item xsi:type="xsd:string">office</item>
</item>
<item xsi:type="ns5:Array" ns5:arrayType="xsd:string[2]">
<item xsi:type="xsd:string">home</item>
<item xsi:type="xsd:string">batcave</item>
</item>
</Customers_Customer_Addresses_Address_Label>
<Customers_Customer_Addresses_Address_Street
xmlns:ns6="http://schemas.xmlsoap.org/soap/encoding/" 
xsi:type="ns6:Array" ns6:arrayType="ns6:Array[2]">
<item xsi:type="ns6:Array" ns6:arrayType="xsd:string[2]">
<item xsi:type="xsd:string">12345 Fake St.</item>
<item xsi:type="xsd:string">54321 Saint Fake Ln.</item>
</item>
<item xsi:type="ns6:Array" ns6:arrayType="xsd:string[2]">
<item xsi:type="xsd:string">10100 Binary Rd.</item>
<item xsi:type="xsd:string">1 Dark Road</item>
</item>
</Customers_Customer_Addresses_Address_Street>
<Customers_Customer_Addresses_Address_City
xmlns:ns7="http://schemas.xmlsoap.org/soap/encoding/" 
xsi:type="ns7:Array" ns7:arrayType="ns7:Array[2]">
<item xsi:type="ns7:Array" ns7:arrayType="xsd:string[2]">
<item xsi:type="xsd:string">Springfield</item>
<item xsi:type="xsd:string">Shelbyville</item>
</item>
<item xsi:type="ns7:Array" ns7:arrayType="xsd:string[2]">
<item xsi:type="xsd:string">Komputar</item>
<item xsi:type="xsd:string">Ubertown</item>
</item>
</Customers_Customer_Addresses_Address_City>
<Customers_Customer_Addresses_Address_State
xmlns:ns8="http://schemas.xmlsoap.org/soap/encoding/" 
xsi:type="ns8:Array" ns8:arrayType="ns8:Array[2]">
<item xsi:type="ns8:Array" ns8:arrayType="xsd:string[2]">
<item xsi:type="xsd:string">IL</item>
<item xsi:type="xsd:string">IL</item>
</item>
<item xsi:type="ns8:Array" ns8:arrayType="xsd:string[2]">
<item xsi:type="xsd:string">MU</item>
<item xsi:type="xsd:string">MU</item>
</item>
</Customers_Customer_Addresses_Address_State>
<Customers_Customer_Addresses_Address_Zip
xmlns:ns9="http://schemas.xmlsoap.org/soap/encoding/" 
xsi:type="ns9:Array" ns9:arrayType="ns9:Array[2]">
<item xsi:type="ns9:Array" ns9:arrayType="xsd:string[2]">
<item xsi:type="xsd:string">86213</item>
<item xsi:type="xsd:string">86321</item>
</item>
<item xsi:type="ns9:Array" ns9:arrayType="xsd:string[2]">
<item xsi:type="xsd:string">HFD234</item>
<item xsi:type="xsd:string">HFD567</item>
</item>
</Customers_Customer_Addresses_Address_Zip>
<Customers_Customer_Age
xmlns:ns10="http://schemas.xmlsoap.org/soap/encoding/" 
xsi:type="ns10:Array" ns10:arrayType="xsd:string[2]">
<item xsi:type="xsd:string">45</item>
<item xsi:type="xsd:string">35</item>
</Customers_Customer_Age>
</ns1:fortuneResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
<<<<

Unforunatly I get this exception on the client side:
  >>>>
.java.lang.NullPointerException
      at
org.apache.crimson.tree.ElementNode.getAttributeNodeNS(ElementNode.java:417)
      at org.apache.soap.util.xml.DOMUtils.getAttributeNS(DOMUtils.java:105)
      at
org.apache.soap.util.xml.DOMUtils.getNamespaceURIFromPrefix(DOMUtils.java:255)
      at
org.apache.soap.encoding.soapenc.SoapEncUtils.getAttributeValue(SoapEncUtils.java:210)
      at
org.apache.soap.encoding.soapenc.SoapEncUtils.getTypeQName(SoapEncUtils.java:255)
      at
org.apache.soap.encoding.soapenc.ParameterSerializer.unmarshall(ParameterSerializer.java:173)
      at
org.apache.soap.util.xml.XMLJavaMappingRegistry.unmarshall(XMLJavaMappingRegistry.java:260)
      at org.apache.soap.rpc.RPCMessage.unmarshall(RPCMessage.java:417)
      at
org.apache.soap.rpc.RPCMessage.extractFromEnvelope(RPCMessage.java:197)
      at org.apache.soap.rpc.Response.extractFromEnvelope(Response.java:142)
      at org.apache.soap.rpc.Call.invoke(Call.java:233)
      ...
<<<<

The exception is at this line:
Response resp = call.invoke(new
java.net.URL("http://localhost:8080/soap/servlet/rpcrouter"),
"urn:eightball-simple-request");

Does anyone have any clues as to what is causing this?  Please
understand that the array thing is not my idea.  It comes as a
requirement from someone who makes a lot more money than I do and has no
clue about SOAP and XML.  I would much rather be returning the actual
XML DOM but we have a requirement not to.  Don't ask me why, I really
don't know...

-Jake


-- 
Jacob S. Barrett
jbarrett@amduat.net
http://www.amduat.net


Returning a slightly different data object

Posted by "Michael J. Hudson" <mh...@blueprinttech.com>.
Ok... here's my dillema.

Upon the Java object providing the SOAP service, I could
1) create a method that takes one XML string as a parameter into my
class
2) create a method that takes on or more data objects parameters into my
class

Now... doing #2 is cool because both sides are dealing completely
with data objects and there is no XML parsing needed or going on.
However, #1 is better if one thinks that additional elements might
be added and passed back and forth.  With an XML document, the server
can always parse it and ignore what it doesn't need, and only get
what it needs.  And thus... the XML document can change and have
additional elements added to it... yet, neither the sender or receiver
need to change any code.

So... the big question is... what if I REALLY want to do #2.  I did
a quick test just to see what would happen, if I added just one field
called 'info' to the object being passed back and forth.  The sender
code added the field... so the receiver code isn't necessarily aware
of it.  And it spit out:

  Fault String = Unable to retrieve PropertyDescriptor for property
'info' of class 'class test.parameters.orderID'.

SOoooo... is there anyway to get SOAP to ignore PropertyDescriptor's
that
it can't retrieve.  So... if the sender ends up sending an object with
more fields than its aware of... then the reciever just fills out IT'S 
object with just the fields that it IS aware of.  Thus... it would see
that 'info' field... look at it's object, realize it's not there to
set, and just ignore it, and go on to the next field to set.

Is that possible?  I'm guessing there really is no clean easy way to do
it, but MAN... it would awesome, if someone did know a way!

Thanks!

-----------------
Michael J. Hudson
Software/Framework Engineer
mhudson@blueprinttech.com

cell-phone: 703.362.8039
voice-mail: 703.827.0638 ext. 4786
fax: 703.734.0987

Blueprint Technologies
"Great software starts with great architecture"
http://www.blueprinttech.com

Returning a slightly different data object

Posted by "Michael J. Hudson" <mh...@blueprinttech.com>.
Ok... here's my dillema.

Upon the Java object providing the SOAP service, I could
1) create a method that takes one XML string as a parameter into my
class
2) create a method that takes on or more data objects parameters into my
class

Now... doing #2 is cool because both sides are dealing completely
with data objects and there is no XML parsing needed or going on.
However, #1 is better if one thinks that additional elements might
be added and passed back and forth.  With an XML document, the server
can always parse it and ignore what it doesn't need, and only get
what it needs.  And thus... the XML document can change and have
additional elements added to it... yet, neither the sender or receiver
need to change any code.

So... the big question is... what if I REALLY want to do #2.  I did
a quick test just to see what would happen, if I added just one field
called 'info' to the object being passed back and forth.  The sender
code added the field... so the receiver code isn't necessarily aware
of it.  And it spit out:

  Fault String = Unable to retrieve PropertyDescriptor for property
'info' of class 'class test.parameters.orderID'.

SOoooo... is there anyway to get SOAP to ignore PropertyDescriptor's
that
it can't retrieve.  So... if the sender ends up sending an object with
more fields than its aware of... then the reciever just fills out IT'S 
object with just the fields that it IS aware of.  Thus... it would see
that 'info' field... look at it's object, realize it's not there to
set, and just ignore it, and go on to the next field to set.

Is that possible?  I'm guessing there really is no clean easy way to do
it, but MAN... it would awesome, if someone did know a way!

Thanks!

-----------------
Michael J. Hudson
Software/Framework Engineer
mhudson@blueprinttech.com

cell-phone: 703.362.8039
voice-mail: 703.827.0638 ext. 4786
fax: 703.734.0987

Blueprint Technologies
"Great software starts with great architecture"
http://www.blueprinttech.com