Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

SOAP - Returning response from Server to Client request based on the <Action>

by chanakya (Friar)
on Apr 04, 2005 at 13:33 UTC ( [id://444669]=perlquestion: print w/replies, xml ) Need Help??

chanakya has asked for the wisdom of the Perl Monks concerning the following question:

Greetings !

I've written a client and server using SOAP::Lite. After days of headaches I've finally managed to add headers and values.

Currently I have a problem. The SOAP envelope generated from the client has a <Action> tag within a <MessengerHeader>, the <Action> contains the type of action, i.e "New Ticket", "Update Ticket", "Close Ticket". What I'm trying to do is, once the server program gets the SOAP envelope, it should check the value within <Action>...</Action> tags and based on the value call a subroutine. The calls to the subroutines will vary according the value within the <Action>tag.

Can anyone let me know how to proceed with this.

Below is the SOAP envelope generated from the Client call
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/1999/XMLSchema-instanc +e" 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"> <SOAP-ENV:Body> <byName xmlns="Delivery"> <MessengerHeader> <Password>test-password</Password> <Username>Bannu</Username> <Action>New Ticket</Action> <Account>local-account</Account> </MessengerHeader> <TicketInformation> <createStatus>Private</createStatus> <AS>ABC 111 00</AS> <ISPCustomer>N</ISPCustomer> <Embargo>false</Embargo> </TicketInformation> </byName> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

Below is the client code:
#!/usr/local/bin/perl #CLIENT use warnings; use strict; use SOAP::Lite +trace => qw(debug); my $uri = 'Delivery'; #Data to be added to the request my (@data) = ( SOAP::Data->name(MessengerHeader => { Action => "New Tick +et", Username => "Bannu" +, Password => "test-p +assword", Account => "local-a +ccount" } ), SOAP::Data->name(TicketInformation =>{ createStatus => "P +rivate", ISPCustomer => "N" +, AS => "ABC 111 00" +, Embargo=>"false" } ) ); #Enable fault management globally use SOAP::Lite on_fault => sub { my($soap, $res) = @_; eval { die ref $res ? $res->faultstring : $soap->transport->stat +us }; return ref $res ? $res : new SOAP::SOM; }; #print $soap->fault ? $soap->faultstring. "\n" : $soap->result; my $soap = SOAP::Lite -> proxy('http://localhost/perl/soap-dbi.pl') -> serializer($serializer) -> uri($uri); my $res = $soap->byName(@data); #print $soap->retrieveDocument->result; print $res->fault ? $res->faultstring. "\n" : $res->result;

I'm also trying to access the values from the SOAP envelope on the server side,but failing miserably. The following is the server code
#!/usr/local/bin/perl #SERVER use SOAP::Transport::HTTP; my $uri = 'Delivery'; SOAP::Transport::HTTP::CGI -> dispatch_to('Delivery') -> handle; package Delivery; use vars qw(@ISA); @ISA = qw(SOAP::Server::Parameters); sub byName { #Get the headers passed from the client my ($self, $in) = @_; my @input = %{$in}; foreach my $input (@input) { print $self . "==> " . $input, "\n"; } if ($input == 'New Ticket'){ & sendAcknowledgement(); } # send a response based on the <Action> value, currently not working sendAcknowledgement(); sub sendAcknowledgement { my (@response) = ( SOAP::Data->name(Acknowledgement =>{ createStatus => "O +K", Received => "0", } ) ); # use Data::Dumper; # print Dumper(@response); return map { $_ } %{$response}; }
The following is the output from the server:
Delivery==> test-password Delivery==> Action Delivery==> New Ticket Delivery==> Username Delivery==> Bannu Delivery==> Account Delivery==> local-account Status: 200 OK Content-Length: 388 Content-Type: text/xml; charset=utf-8 SOAPServer: SOAP::Lite/Perl/0.60 <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/1999/XMLSchema-instan +ce" 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"> <SOAP-ENV:Body> <byNameResponse xmlns="Delivery"><s-gensym15/></byNameResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

Replies are listed 'Best First'.
Re: SOAP - Returning response from Server to Client request based on the <Action>
by jhourcle (Prior) on Apr 05, 2005 at 01:12 UTC
    This is one of those times when use strict; is in order:
    Global symbol "$input" requires explicit package name at /tmp/soap.pl +line 28. Global symbol "$response" requires explicit package name at /tmp/soap. +pl line 52. Missing right curly or square bracket at /tmp/soap.pl line 53, at end +of line syntax error at /tmp/soap.pl line 53, at EOF /tmp/soap.pl had compilation errors.

    You have a few problems with the server side of the code. The first big one, that won't show up even from 'use strict' -- you're printing. That's bad when you're doing SOAP, unless you make sure that they're valid headers. (and even then, I don't recommend it).

    Anyway, to answer your initial question -- as SOAP::Lite does RPC/encoded, you need to hand off to a specific function that acts as a switchboard, that can look at the value of the field in question, and then passes off to your other functions. You're also using SOAP::Transport::HTTP::CGI when you seem to be using mod_perl, based on the '<s-gensym15/>' that was returned, and the URL that you used in the client.

    Try something more like the following for the server:

    It uses 'warn', not 'print', so the debugging info is sent to the webserver's error logs. Note that I've also used 'eq' not '==' for the string comparison. What you got returned was an empty hash, because $response wasn't defined. (which is why use strict is your friend) Also, in the client code, you're using a custom serializer, but you've never defined $serializer.

      jhorcule, first of all thanks for insisting on "use strict" pragma. In every program, I make it a point to use "strict" and "warning" pragmas, Here I left it go somehow.

      The modified "byName sub" in your server code, gave what I was looking for.
      "Warn" also helped me to check the structure of the document passed to the server.

      Regarding the custom serializer,I've implemented the serializer and deserializer on both client/server ends which looks as below:

        From the looks of things, you're serializing in the document/literal style, as opposed to RPC/encoded. The only thing that I can think of is that you might get some oddities from multiple references to the same object. (but you'd know the data you're sending out better than others, and you may not ever pass that sort of thing)

        As for the XML Schema 2001, I think all that you need to do is to inherit from SOAP::XMLSchema2001::Serializer rather than SOAP::Serializer in your serializer. (but I've never tried doing that).

        The differing namespaces determine the SOAP version, the '1999' versions specify SOAP 1.1, you can set the version to 1.2 using the soapversion() method of SOAP::Lite

        /J\

Re: SOAP - Returning response from Server to Client request based on the <Action>
by rob_au (Abbot) on Apr 04, 2005 at 21:15 UTC
    I've only spent a few minutes looking through your code but you do not appear to be actually returning any value from the byName subroutine in your server Delivery package. If you return a value from this subroutine, it will be serialised and dispatched back in the response. For example:
    sub byName { #Get the headers passed from the client my ($self, $in) = @_; my @input = %{$in}; return "Hello World!"; }
    This code (untested of course) should return the string Hello World! in the SOAP server response. Additional complexity with respect to the SOAP server response components can be achieved using SOAP::Data in the same way as it has been used in the SOAP client.

     

    perl -le "print unpack'N', pack'B32', '00000000000000000000001000000000'"

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://444669]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (3)
As of 2024-04-26 04:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found