Diving for Perls with WSIF

Talking to Perl from BPEL

or WSIF HTTP Bindings

Earlier this week I was asked how to call Perl from BPEL.  My first inclination was to use a <bpelx:exec> to embed some Java and then in Java use Runtime.getRuntime().exec() to invoke a Perl script.  A little more thought came up with a better solution.  Perl is usually used as part of a cgi solution so why not us WSIF to create an HTTP binding.  Lets look at this solution.

The Perl Script

Not being a Perl guru I created a tremendously unsophisticated Perl script
#!/usr/bin/perl
use strict;
use CGI;
my $cgi = CGI::new();
print $cgi->header(-type => "text/xml; charset=utf-8");
print <<XML;
<?xml version= '1.0' encoding= 'UTF-8' ?>
<response xmlns="http://perl.antony.blog">
XML
print "  <name>Hello " . $cgi->param('name') . "</name>";
print <<XML
</response>
XML
This just takes the parameter "name" passed into the script and creates an XML document response that conforms to the following schema
<?xml version="1.0" encoding="windows-1252" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns="http://perl.antony.blog"
            targetNamespace="http://perl.antony.blog"
            elementFormDefault="qualified">
      <xsd:element name="name" nillable="true" type="xsd:string" />
      <xsd:element name="response">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="name"/>
            </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
</xsd:schema>
To deploy the Perl script I dropped it into the $ORACLE_HOME/Apache/Apache/cgi-bin directory of Oracle App server which by default will run Perl scripts in this directory.
A sample query may be "http://localhost/perl/helloParamXML.pl?name=Jackson%20Franklin"  This produces the following XML document
<?xml version= '1.0' encoding= 'UTF-8' ?>
<response xmlns="http://perl.antony.blog">
  <name>Hello Jackson Franklin</name>
</response>
So now I had a sample Perl script.  The next step was to create a WSIF wrapper for the Perl service.

Wrapping Up an HTTP GET in WSIF

WSIF enables us to create a WSDL description with non-SOAP bindings.  In this case I wanted to create a HTTP GET binding.  There just happens to be an example of this in the BPEL Process manager samples at $ORACLE_HOME/bpel/samples/tutorials/702.Bindings/HTTPBinding/HTTPBindingSample/bpel/QuoteService.wsdl.
I used this a a template to create my own WSIF.  Here is the WSIF I created.
<?xml version="1.0" encoding="utf-8"?>
<definitions
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://perl.antony.blog"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:plnk="http://schemas.xmlsoap.org/ws/2003/05/partner-link/"
targetNamespace="http://perl.antony.blog"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:perl="http://perl.antony.blog">
I didn't check all the definitions to see if they were all needed.  The changes I made from the sample are highlighted.
    <types>
        <schema xmlns="http://www.w3.org/2001/XMLSchema">
    <xsd:import schemaLocation="PerlSchema.xsd"
                namespace="http://perl.antony.blog"/>
        </schema>
    </types>
Message types are imported from a seperate XSD, I find this makes it cleaner and easier to modify the schema because the same schema can be used in multiple places.
  <message name="CallPerlRequest">
    <part name="name" type="xsd:string" />
  </message>
This is the input message and will later be bound onto a HTTP GET request.   It consists of a single string.  Multiple parameters would be entered as multiple parts.  If a complex XML type or document is the input then it would be better to map onto a POST request and enter the XML document as the value of a an input parameter.
  <message name="CallPerlResponse">
    <part name="Body" element="perl:response" />
  </message>
This is the response message and is the XML document returned by the Perl service.
  <portType name="PerlHttpGet">
    <operation name="CallPerl">
      <input message="tns:CallPerlRequest" />
      <output message="tns:CallPerlResponse" />
    </operation>
  </portType>
Having set up the Port Type now need to bind the service onto an HTTP GET Request
  <binding name="PerlHttpGet" type="tns:PerlHttpGet">
    <http:binding verb="GET" />
    <operation name="CallPerl">
      <http:operation location="/perl/helloParamXML.pl" />
      <input>
        <http:urlEncoded />
      </input>
      <output>
        <mime:mimeXml part="Body" />
      </output>
    </operation>
  </binding>
The binding maps the operation onto a URL path and species that the input message is mapped onto HTTP URL encoded parameters and the response is an XML document.
  <service name="HelloPerl">
    <port name="PerlHttpGet" binding="tns:PerlHttpGet">
      <http:address location="http://localhost" />
    </port>
  </service>
  The service binding identifies the server providing this service.
  <plnk:partnerLinkType name="HelloPerlService">
    <plnk:role name="HelloPerlServiceProvider">
      <plnk:portType name="tns:PerlHttpGet"/>
    </plnk:role>
  </plnk:partnerLinkType> 
</definitions>
The WSIF descriptor is finished off by adding a partner link for use by BPEL.

Putting it to Work

We can now use our new Perl service directly from BPEL, just as we would any other web service.  As you can see from the above the process to create an HTTP WSIF is pretty straightforward.  It would be nice if the Designer could do that for you ut it doesn't, although it can create WSIF for Java services.  Obviously this approach is not limited to Perl but can be used with any service that takes HTTP requests and returns an XML document as the response.

Comments:

Hi Antony, nice post and example of WSIF with HTTP binding. Personally though, my first inclination for invoking perl in a SOA/Web Services context would be to simply implement a SOAP interface usign SOAP::Lite. Great information is available in the book Programming Web Services With Perl

Posted by Paul on June 06, 2007 at 02:23 PM MDT #

hi Antony, fyi to expand the discussion I got a little derivative ;) and just posted Diving for SOAP Perls which describes the approach of wrapping your perl with a SOAP interface.
Paul Gallagher

Posted by Antony Reynolds on June 14, 2007 at 11:49 AM MDT #

Hello Antony, I am writeing my degree with name WSIF. I found your examples very useful. But i have problem with example JMS (message bean) with WSIF. In my message bean is method methodName(BigDecimal x, BigDecimal y). I don't know how to call this method with WSIF. If you can help me i will be verrrrrry thankful.

Posted by Primoz on June 18, 2007 at 10:38 PM MDT #

Post a Comment:
Comments are closed for this entry.
About

Musings on Fusion Middleware and SOA Picture of Antony Antony works with customers across the US and Canada in implementing SOA and other Fusion Middleware solutions. Antony is the co-author of the SOA Suite 11g Developers Cookbook, the SOA Suite 11g Developers Guide and the SOA Suite Developers Guide.

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today