Loading ...
Sorry, an error occurred while loading the content.

Re: [soaplite] Re: SOAP::Lite/.net interop

Expand Messages
  • Jonathan D. Fields
    Hi All, After considerable experimentation, I was able to develop a SOAP Lite server that works with VB/.NET, Java/AXIS, and SOAP Lite clients, using WSDL and
    Message 1 of 3 , Mar 4, 2005
    • 0 Attachment
      Hi All,

      After considerable experimentation, I was able to develop a SOAP Lite server that works with VB/.NET, Java/AXIS, and SOAP Lite clients, using WSDL and fairly complex types.

      Below is an example. I haven't actually tried compiling this, as I just threw it together, but it should be pretty close to working as it's based on working code. Time permitting I'll put together a more complete and working example server and clients and post that.

      The bottom line is that it's surprisingly difficult to do this, which to me is a drawback to SOAP Lite if you need to develop web services in SOAP Lite that can be accessed by any SOAP client.  If anyone can provide an easier approach I'd appreciate it. I came very close to encoding the XML myself.

      Thanks,
      Jon


      WSDL:




      <?xml version="1.0" encoding="utf-8"?>

      <definitions name="Ex"
                   targetNamespace="urn:Ex/WebSvc"
                   xmlns:ex="urn:Ex/WebSvc"
                   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
                   xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
                   xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
                   xmlns="http://schemas.xmlsoap.org/wsdl/">

        <types>
          <xsd:schema xmlns="http://www.w3.org/2001/XMLSchema"
                      targetNamespace="urn:Ex/WebSvc">

          <xsd:complexType name="IntArray">
            <xsd:complexContent>
              <xsd:restriction base="soapenc:Array">
                 <xsd:attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:int[]"/>
              </xsd:restriction>
            </xsd:complexContent>
          </xsd:complexType>

          <xsd:complexType name="Struct">
            <xsd:all>
              <xsd:element name="elem1"      type="xsd:int"/>
              <xsd:element name="elem2"      type="xsd:string"/>
            </xsd:all>
          </xsd:complexType>

          <xsd:complexType name="StructArray">
            <xsd:complexContent>
              <xsd:restriction base="soapenc:Array">
                 <xsd:attribute ref="soapenc:arrayType" wsdl:arrayType="ex:Struct[]"/>
              </xsd:restriction>
            </xsd:complexContent>
          </xsd:complexType>

          <xsd:complexType name="ResultStruct">
            <xsd:all>
              <xsd:element name="elem1"   type="ex:StructArray"/>
              <xsd:element name="elem2"   type="xsd:string"/>
            </xsd:all>
          </xsd:complexType>

          </xsd:schema>
        </types>

        <message name="ExRequest">
          <part name="param1" type="xsd:string" />
          <part name="param2" type="ex:IntArray" />
        </message>
        <message name="ExResponse">
          <part name="return"    type="ex:ResultStruct" />
        </message>

        <portType name="API">

          <operation name="exOp">
            <input message="ex:ExRequest" />
            <output message="ex:ExResponse" />
          </operation>

        </portType>

        <binding name="SOAPBinding" type="ex:API">
          <soap:binding style="rpc"
                        transport="http://schemas.xmlsoap.org/soap/http"/>

          <operation name="exOp">
            <soap:operation soapAction="urn:Ex/WebSvc#exOp"/>
            <input>
              <soap:body use="encoded"
                         namespace="urn:Ex/WebSvc"
                         encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
            </input>
            <output>

            <output>
              <soap:body use="encoded"
                         namespace="urn:Ex/WebSvc"
                         encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
            </output>
          </operation>

        </binding>

        <service name="SOAPService">
          <port name="API" binding="ex:SOAPBinding">
            <soap:address location="http://ex.websvc.acme.com:4321/"/>
          </port>
        </service>

      </definitions>



      SOAP Lite Server:



      use SOAP::Lite;

      my $daemon = new SOAP::Transport::HTTP::Daemon(LocalPort => 4321);
      $daemon->dispatch_to('/my/perl/lib', 'Ex::WebSvc');
      $daemon->handle;



      The package implementing the server (in Ex/WebSvc.pm):



      package Ex::WebSvc;

      use SOAP::Lite;
      use vars qw(@ISA);

      @ISA = qw(SOAP::Server::Parameters);

      sub exOp
      {
        shift;
        my ($param1, $param2) = SOAP::Server::Parameters::byNameOrOrder([qw(param1 param2)], @_);

        # $param1 contains a string and $param2 a ref to an array of ints
       
        my @structs = (
          SOAP::Data->name("item")->value(\SOAP::Data->value(SOAP::Data->name("elem1")->value(1),
                                                             SOAP::Data->name("elem2")->value("abcd"))),
          SOAP::Data->name("item")->value(\SOAP::Data->value(SOAP::Data->name("elem1")->value(2),
                                                             SOAP::Data->name("elem2")->value("efgh")))

          #...
        );

        my $structCount = @structs;

        return SOAP::Data->name("return")
                         ->value(\SOAP::Data->value(SOAP::Data->name("elem1")
                                                              ->value(\SOAP::Data->value(@structs))
                                                              ->attr({"xsi:type"           => "SOAP-ENC:Array",
                                                                      "SOAP-ENC:arrayType" => "ex:Struct[$structCount]"}),
                                                    SOAP::Data->name("elem2")
                                                              ->value("uvwxy")))
                         ->attr({"xmlns:ex"  => "urn:Ex/WebSvc",
                                 "xsi:type"  => "ex:ResultStruct"});


      }



      For the VB client, you must first run wsdl.exe to generate the stub code, e.g:

      wsdl /l:VB /n:Ex Ex.wsdl

      Then your client looks something like:



      Class Client
        Public Shared Sub Main()
          Dim ex As New Ex.SOAPService
          Dim intArray(2) As Integer
          intArray(0) = 1
          intArray(1) = 2
          Try
            Dim result As Ex.ResultStruct = ex.exOp("abcd", intArray)
          Catch ..
          End Try
        End Sub
      End Class



      Compile the stub code (SOAPService.vb) together with your client (Client.vb):

      vbc /r:System.dll /r:System.Web.Services.dll /r:System.Xml.dll /out:Client.exe SOAPService.vb Client.vb

      You are ready to go at this point. The Java/AXIS code is similar.

      Ironically, I was not able to get a SOAP Lite client to work with this server using

           my $ex = SOAP::Lite->service('file:Ex.wsdl');

      I forget the exact problem, but I think it had something to do with not handling the IntArray "typedef" in the WSDL. In order to call this server using SOAP Lite, I ended up doing something like: 

      my $ex = SOAP::Lite->proxy('ex.websvc.acme.com:4321')->uri('urn:Ex/WebSvc');
      my $resultStruct = $ex->exOp("abcd", [1, 2, 3, 4])->result;

      print $resultStruct->{elem1}->[0]->{elem1}, "\n";
      print $resultStruct->{elem1}->[0]->{elem2}, "\n";
      print $resultStruct->{elem1}->[1]->{elem1}, "\n";
      print $resultStruct->{elem1}->[1]->{elem2}, "\n";
      print $resultStruct->{elem2}, "\n";




      Matt Long wrote:
      Mike,

      I can help you, but keep in mind that I never got it to work with
      complex types. When I return rows of data, I just convert my data to the
      equivalent of a flat file and return that as a string. It's lame, but it
      works.

      Anyhow, the attachment just says hello. You place the files from the
      perl folder in your web tree where SOAP::Lite is running, then you need
      to update the bottom of the WSDL file I included to reflect the web
      location on your local machine of the actual sayhellodispatcher.cgi file
      (e.g. http://localhost/soap/sayhellodispatcher.cgi). Then you need to
      specify to visual studio your local web address to the WSDL file (e.g.
      http://localhost/soap/HelloSOAPLite.wsdl ) when you add a web reference.

      Let me know if you have any questions.

      -Matt

      p.s. I tested this example and it works.



      m_j_conroy wrote:

      >Matt,
      >
      >I saw your post on Google groups with the WSDL snippet.  Do you have
      >an end-to-end example from the .Net code forward for a SOAP::Lite
      >server called by a .Net client?  A simple HelloWorld example is
      >literally sufficient.  Any help would be much obliged... I realize
      >this email is coming out of the blue.
      >
      >Best,
      >Mike Conroy
      >
      >
      >
      >
      >

      >


    • steve_f_maher
      I got this to work after adding xmlns:SOAP-ENC = http://schemas.xmlsoap.org/soap/encoding/ in the last attr() clause. Great example! Steve
      Message 2 of 3 , May 4, 2005
      • 0 Attachment
        I got this to work after adding

        "xmlns:SOAP-ENC" => "http://schemas.xmlsoap.org/soap/encoding/"

        in the last attr() clause.

        Great example!

        Steve
      Your message has been successfully submitted and would be delivered to recipients shortly.