FAQ

On 13 Nov 2008, at 09:46, Zbigniew Lukasiak wrote:

We have tried to reuse the WSDL files from our legacy Java server in
the new Perl implementation - but that turned to be difficult (and
impossible automatically - because it uses RPC style calls). Now the
plan is to generate the WSDL file for our services. I've tried to
google for solutions to this problem and I found:

1) http://search.cpan.org/~pdenis/WSDL-Generator-0.02/lib/WSDL/Generator.pm
- development of this one stopped in 2002 and does not work in 5.8 -
rather scary

2) http://search.cpan.org/~tareka/Pod-WSDL-0.05/lib/Pod/WSDL.pm -
looks nice but generates RPC style calls - which are problematic with
XML-Compile as I understand.
At $work we're using document literal style, and luckily the schemas
we're using turned out to be easy enough to generate from a simple
little script which builds up the various pieces of the WSDL together.
I know I've shared this script somewhere before, but can't remember if
it was here or on the Catalyst list. It's nothing special, and makes
assumptions based on the schema file names. That may or may not work
for you, but perhaps it will give you a jump start.

In my case, the schema filenames are like: TTI_PkgCostRQ.xsd,
TTI_PkgCostRS.xsd, TTI_PkgBookRQ.xsd, TTI_PkgBookRS.xsd, etc which
makes for easy autogeneration. :-) And yes, I know that names are
independent within each type, but it helps my poor brain keep them all
together if I include the type in the name.

Drew

The relevant portions of my WSDL generator are below:

----------8<---------------------8<----------------------
use FindBin qw($Bin);
use Path::Class qw(dir file);
use Getopt::Long;
use File::Copy;
use File::Path;
use Pod::Usage;
my @operations = qw(OTA_Ping TTI_ProductSearch TTI_PkgAvail
TTI_PkgCost TTI_PkgBook);

# find schemas to <include>
# RQ/RS pair for each operation
my $schema_dir = dir($opt{schema_dir});
my @schemas;
foreach my $op (@operations)
{
push @schemas,
file($schema_dir, $op.'RQ.xsd')->basename,
file($schema_dir, $op.'RS.xsd')->basename;
}

$schema_dir = dir($schema_dir);
print "Schema dir: $schema_dir\n" if $verbose;
foreach my $file ($schema_dir->children)
{
next if $file->is_dir; # CVS, etc
my $basename = $file->basename();
next if $basename !~ /.xsd$/; # schema files only
next if $basename =~ /(RQ|RS).xsd$/; # already included
push @schemas, $basename;
}
$opt{schemas} = \@schemas;

print "Writing $opt{filename} with schemas:\n " . join("\n ",
@schemas) . "\n";
print "and operations:" . join("\n ", @operations) . "\n\n\n";

write_static_files();

sub write_static_files
{
my $wsdl = make_wsdl();
# print $wsdl if $verbose;

my $wsdl_dir = "$Bin/../webservices/root/static/wsdl/v
$opt{version}";
mkpath($wsdl_dir) unless -d $wsdl_dir;
my $wsdl_file = "$wsdl_dir/$opt{filename}";
print "Writing WSDL to $wsdl_file\n" if $verbose;
open(my $FH, ">", $wsdl_file) || die "Error opening file
($wsdl_file): $!";
print $FH $wsdl;
close $FH;

foreach my $schema (@schemas)
{
print "Copying schema $schema to $wsdl_dir\n" if $verbose;
copy(file($opt{schema_dir}, $schema), file($wsdl_dir,
$schema));
}
}

sub make_wsdl
{
my $wsdl = make_header();
$wsdl .= make_types(@{ $opt{schemas} });
foreach my $op (@operations)
{
$wsdl .= make_message_pair($op);
$wsdl .= make_port_type($op);
}
# bindings & services at bottom so we can split out easily
foreach my $op (@operations)
{
$wsdl .= make_binding($op);
}
$wsdl .= make_service();
$wsdl .= make_footer();

return $wsdl;
}

sub make_header
{
return <<"END_XML";
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/
soap/"
xmlns:schema="$opt{namespace}"
xmlns:tns="$opt{namespace}"
name="$opt{name}"
targetNamespace="$opt{namespace}">
END_XML
}

sub make_footer
{
return <<"END_XML";
</wsdl:definitions>
END_XML
}

sub make_types
{
my @schemas = @_;
my $base_url = $opt{host}.'/static/wsdl/v'.$opt{version};
my $includes;
$includes .= qq{ <xsd:include schemaLocation="${base_url}/
$_"/>\n} foreach @schemas;
chomp $includes;

return <<"END_XML";
<wsdl:types>
$includes
</wsdl:types>
END_XML
}

sub make_message_pair
{
my $name = shift;

return <<"END_XML";
<wsdl:message name="${name}RQMessage">
<wsdl:part name="body" element="schema:${name}RQ"/>
</wsdl:message>
<wsdl:message name="${name}RSMessage">
<wsdl:part name="body" element="schema:${name}RS"/>
</wsdl:message>
END_XML
}

sub make_port_type
{
my $name = shift;

return <<"END_XML";
<wsdl:portType name="${name}PortType">
<wsdl:operation name="${name}">
<wsdl:input name="${name}" message="tns:${name}RQMessage"/>
<wsdl:output name="${name}Response" message="tns:$
{name}RSMessage"/>
</wsdl:operation>
</wsdl:portType>
END_XML
}

sub make_binding
{
my $name = shift;

return <<"END_XML";
<wsdl:binding name="${name}Binding" type="tns:${name}PortType">
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http
"/>
<wsdl:operation name="${name}">
<wsdlsoap:operation soapAction="${name}"/>
<wsdl:input name="${name}">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="${name}Response">
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
END_XML
}

sub make_service
{
my $port_list;
foreach my $op (@operations)
{
$port_list .= <<"END_XML";
<wsdl:port name="${op}Port" binding="tns:${op}Binding">
<wsdlsoap:address location="$opt{host}$opt{path}/v
$opt{version}/${op}"/>
</wsdl:port>
END_XML
}
chomp $port_list;

return <<"END_XML";
<wsdl:service name="$opt{name}Service">
$port_list
</wsdl:service>
END_XML
}

Search Discussions

Discussion Posts

Previous

Follow ups

Related Discussions

Discussion Navigation
viewthread | post
posts ‹ prev | 2 of 3 | next ›
Discussion Overview
groupxml-compile @
postedNov 13, '08 at 9:46a
activeNov 13, '08 at 10:47a
posts3
users2
websiteperl.overmeer.net...

2 users in discussion

Drew Taylor: 2 posts Zbigniew Lukasiak: 1 post

People

Translate

site design / logo © 2022 Grokbase