Hi, all.

I have searched the archives, but have not gotten quite enough of a clue to solve the problem I face. I wish to use Java to get the results from a call to a SOAP server running Perl SOAP::Lite. The function returns a hash ref, encoded as SOAP::Lite encodes. (raw soap call/return below.)

I apologize for the long message, but I have found that God is in the details in this space, and if it is just a simple typo in some routine, the real source is required.

The server is running SOAP::Lite 0.55. It is sending back a hashref, and I have not been able to create the proper WSDL to see it, possibly because of how SOAP::Lite is sending back that hashref. I can handle simple types like ints and strings, but this is not working.

I am using stubs created by wsdl2java, so clearly I need to express this soap-struct in my WSDL, but I do not seem to be able to create the proper type in the WSDL, or at least, it is not being used.

I cannot really change the underlying routines on the server, as they are used for many things, but I can modify the dispatch function called by mod_perl. I have attached it at the end.

The request:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
URL: http://feature.alodar.com/gbib-soap/
-->
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/";
soap:encodingstyle="http://schemas.xmlsoap.org/soap/encoding/";
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
xmlns:xsd="http://www.w3.org/2001/XMLSchema";>
<soap:Body>
<s0:get_user_ids_by_name xmlns:s0="http://feature.alodar.com/Alodar/GBIB/UserUtils";>
<s0:arg1Name>config_name</s0:arg1Name>
<s0:arg1Value>feature</s0:arg1Value>
</s0:get_user_ids_by_name>
</soap:Body>
</soap:Envelope>


The response:

<?xml version="1.0" encoding="UTF-8"?>
<soap-env:envelope xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"; xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/"; xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"; xmlns:xsd="http://www.w3.org/1999/XMLSchema"; xmlns:namesp2="http://xml.apache.org/xml-soap"; soap-env:encodingstyle="http://schemas.xmlsoap.org/soap/encoding/";>
<soap-env:body>
<namesp1:get_user_ids_by_nameresponse xmlns:namesp1="http://feature.alodar.com/Alodar/GBIB/UserUtils";>
<s-gensym3 xsi:type="namesp2:SOAPStruct">
<admin xsi:type="xsd:int">
1
</admin>
<guest xsi:type="xsd:int">
2
</guest>
</s-gensym3>
</namesp1:get_user_ids_by_nameresponse>
</soap-env:body>
</soap-env:envelope>


my WSDL:

<?xml version="1.0" encoding="utf-8"?>
<definitions name="GBIB"
  targetNamespace="http://feature.alodar.com/Alodar/GBIB/";
  xmlns:schema="http://www.w3.org/2001/XMLSchema";
  xmlns:tns="http://feature.alodar.com/Alodar/GBIB/";
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/";
  xmlns:xml-soap="http://xml.apache.org/xml-soap";
  xmlns="http://schemas.xmlsoap.org/wsdl/";
  >

<types>
<!-- I could use the following by defining the type returned from a
part of a message as
<message name="ListOfUsers">
<part name="models" type="tns:Vector">
</message>
<xsd:schema
targetNamespace="http://feature.alodar.com/Alodar/GBIB/";
xmlns="http://www.w3.org/2001/XMLSchema/";>
<schema:complexType name="Vector">
<xsd:element name="elementData" type="schema:String" />
<xsd:element name="elementCount" type="schema:int" />
</schema:complexType>
</xsd:schema>
-->
<schema
xmlns="http://www.w3.org/2001/XMLSchema";
targetNamespace="http://feature.alodar.com/Alodar/GBIB/";
>
<complexType name="idNameMap">
<element name="elementData" type="string" />
<element name="elementCount" type="int" />
</complexType>
<complexType name="SOAPStruct">
<all>
<element name="varString" type="string"/>
<element name="varInt" type="int"/>
</all>
</complexType>
</schema>
</types>


<message name="config_nameRequest">
<part name="arg1Name" type="schema:string" />
<part name="arg1Value" type="schema:string" />
</message>
<message name="stringStringRequest">
<part name="arg1Name" type="schema:string" />
<part name="arg1Value" type="schema:string" />
<part name="arg2Name" type="schema:string" />
<part name="arg2Value" type="schema:string" />
</message>
<message name="stringIntRequest">
<part name="arg1Name" type="schema:string" />
<part name="arg1Value" type="schema:string" />
<part name="arg2Name" type="schema:string" />
<part name="arg2Value" type="schema:int" />
</message>
<message name="idNameMapResponse">
<!-- part name="idNameMapReturnValue" type="xml-soap:Map" / -->
<part name="idNameMapReturnValue" type="tns:idNameMap" />
</message>
<message name="stringResponse">
<part name="stringReturnValue" type="schema:string" />
</message>
<message name="intResponse">
<part name="stringReturnValue" type="schema:int" />
</message>
<message name="get_public_listsResponse">
<part name="get_public_listsReturnValue" type="schema:anyType" />
</message>

<portType name="UserUtilsPort">
<!-- ports are analogous to method calls. SR says analogous to library/module/class -->
<!-- name must match some binding's type -->
<operation name="get_user_ids_by_name">
<input message="tns:config_nameRequest" />
<output message="tns:idNameMapResponse" />
</operation>
<operation name="get_id_for_username">
<input message="tns:stringStringRequest" />
<output message="tns:intResponse" />
</operation>
<operation name="get_username_for_id">
<input message="tns:stringIntRequest" />
<output message="tns:stringResponse" />
</operation>
</portType>

<portType name="ListUtilsPort">
<!-- ports are analogous to method calls. -->
<!-- name must match some binding's type -->
<operation name="get_public_lists">
<input message="tns:config_nameRequest" />
<output message="tns:stringResponse" />
</operation>
</portType>

<binding name="UserUtils" type="tns:UserUtilsPort">
<!-- binding elements tell code how to move data. We are using SOAP -->
<!-- These are analagous to classes -->
<!-- type matches name of some port -->
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"; />
<operation name="get_id_for_username">
<soap:operation style="rpc" />
<input>
<soap:body use="encoded" namespace="http://feature.alodar.com/Alodar/GBIB/UserUtils"; encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; />
</input>
<output>
<soap:body use="encoded" namespace="http://feature.alodar.com/Alodar/GBIB/UserUtils"; encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; />
</output>
</operation>
<operation name="get_user_ids_by_name">
<soap:operation style="rpc" />
<input>
<soap:body use="encoded" namespace="http://feature.alodar.com/Alodar/GBIB/UserUtils"; encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; />
</input>
<output>
<soap:body use="encoded" namespace="http://feature.alodar.com/Alodar/GBIB/UserUtils"; encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; />
</output>
</operation>
<operation name="get_username_for_id">
<soap:operation style="rpc" />
<input>
<soap:body use="encoded" namespace="http://feature.alodar.com/Alodar/GBIB/UserUtils"; encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; />
</input>
<output>
<soap:body use="encoded" namespace="http://feature.alodar.com/Alodar/GBIB/UserUtils"; encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; />
</output>
</operation>
</binding>


<binding name="ListUtils" type="tns:ListUtilsPort">
<!-- binding elements tell code how to move data. We are using SOAP -->
<!-- These are analagous to classes -->
<!-- type matches name of some port -->
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"; />
<operation name="get_public_lists">
<soap:operation style="rpc" />
<input>
<soap:body use="encoded" namespace="http://feature.alodar.com/Alodar/GBIB/ListUtils"; encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; />
</input>
<output>
<soap:body use="encoded" namespace="http://feature.alodar.com/Alodar/GBIB/ListUtils"; encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; />
</output>
</operation>
</binding>


<service name="GBIBService">
<!-- service tells us what bindings to use. These give actual machines that implement the protocol. -->
<!-- document>
For a complete description of this service, go to the following URL:
<a href="http://feature.alodar.com/";>
http://feature.alodar.com/
</a>
</document -->
<port name="UserUtils" binding="tns:UserUtils">
<soap:address location="http://feature.alodar.com/gbib-soap"; />
</port>
<port name="ListUtils" binding="tns:ListUtils">
<soap:address location="http://feature.alodar.com/gbib-soap"; />
</port>
</service>
</definitions>


The java code:

   public void callFeatureStub() {
                try{
                        String endpoint = "http://feature.alodar.com/gbib-soap/";;

UserUtilsPort userUtilsPort = new GBIBServiceLocator().getUserUtils(new URL(endpoint));
((UserUtilsStub)userUtilsPort).setTimeout(60000);
ListUtilsPort listUtilsPort = new GBIBServiceLocator().getListUtils(new URL(endpoint));
((ListUtilsStub)listUtilsPort).setTimeout(60000);


// works great!

int get_id_for_usernameResult=userUtilsPort.get_id_for_username("config_name ", config_name, "username", "admin");
printResult("get_id_for_username", get_id_for_usernameResult);


//works great!

String get_username_for_idResult=userUtilsPort.get_username_for_id("config_name ", config_name, "user_id", 1);
printResult("get_username_for_id", get_username_for_idResult);


// throws exception
Object get_user_ids_by_nameResult = userUtilsPort.get_user_ids_by_name("config_name", config_name);
printResult("get_user_ids_by_name", get_user_ids_by_nameResult);


       } catch (Exception e) {
           System.err.println("Error: "+e.toString());
       }
   }

The dispatcher is very simple:

sub handler {
  SOAP::Transport::HTTP::Apache -> dispatch_to(
      qw(
          Alodar::GBIB::ListUtils::get_public_lists
          Alodar::GBIB::UserUtils::get_id_for_username
          Alodar::GBIB::UserUtils::get_user_ids_by_name
          Alodar::GBIB::UserUtils::get_username_for_id
      )
  ) ->handler(@_)

I can add more things to this, as long as they can go here.

The exception is:

[java] Result of get_id_for_username was type int, value 1
[java] Result of get_username_for_id was type java.lang.String, value admin
[java] - Exception:
[java] org.xml.sax.SAXException: Deserializing parameter 's-gensym39': could not find deserializer for type {http://xml.apache.org/xml-soap}SOAPStruct
[java] at org.apache.axis.message.RPCHandler.onStartChild(RPCHandler.java:302)
[java] Error: org.xml.sax.SAXException: Deserializing parameter 's-gensym39': could not find deserializer for type {http://xml.apache.org/xml-soap}SOAPStruct
[java] at org.apache.axis.encoding.DeserializationContextImpl.startElement(Deseria lizationContextImpl.java:963)
[java] at org.apache.axis.message.SAX2EventRecorder.replay(SAX2EventRecorder.java: 198)
[java] at org.apache.axis.message.MessageElement.publishToHandler(MessageElement.j ava:722)
[java] at org.apache.axis.message.RPCElement.deserialize(RPCElement.java:233)
[java] at org.apache.axis.message.RPCElement.getParams(RPCElement.java:347)
[java] at org.apache.axis.client.Call.invoke(Call.java:2272)
[java] at org.apache.axis.client.Call.invoke(Call.java:2171)
[java] at org.apache.axis.client.Call.invoke(Call.java:1691)
[java] at com.alodar.feature.Alodar.GBIB.UserUtilsStub.get_user_ids_by_name(UserUt ilsStub.java:187)
[java] at axisTest.callFeatureStub(axisTest.java:71)
[java] at axisTest.main(axisTest.java:46)


Scott



Reply via email to