SWIG binary string caveat

If you have been working with Web services you might have heard the term MTOM. I was getting MTOM support to work on WSF/Perl and the image that was not getting saved properly. Only the first few bytes was written to the file. The magic numbers that were getting saved was enough for the file command to say it’s a JPEG image. From the C layer it was reading image data to a character pointer and returning it to the scripting language.

The C function reading the image had a char * return type. The code that was generated by SWIG was returning the pointer after running it through the following function,

SWIG_FromCharPtr(const char *cptr)
{
  return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0));
}

The rough English translation of the above is, “you’re screwed”. Why? The strlen doesn’t particularly like to go through binary strings. It’ll choke and die when it see a null byte. So, only the content before the null byte was returned.

The solution was to create a string using the API provided by the particular scripting language. For Perl it’s newSVpv and for Ruby it’s rb_str_new. Wrapped the functions inside an ifdef (thanks to the nice SWIG<lang> defines) and all is set for MTOM!

Comments (2)

Custom SOAP headers using WSF/Perl

SOAP headers are used to convey additional control information that complements the information in the payload. For example WS-Security is one such thing that use SOAP headers to say how integrity and confidentiality should be achieved. Apart from the specs that define standard SOAP headers you could also define your own custom headers which could then be processed as you wish from your application. Let’s see how we can generate custom SOAP headers using WSF/Perl. You’ll need to get the SVN head revision of WSF/Perl in order to get this working (as of this writing).

First, let’s see an example from “Processing XML with Java” (Amazon page) also available online here. I’m using the SOAP header example to show you how to generate the exact thing.

<Payment xmlns="http://namespaces.cafeconleche.org/xmljava/ch2/">
    <Name>Elliotte Harold</Name>
    <Issuer>VISA</Issuer>
    <Number>5125456787651230</Number>
    <Expires>2005-12</Expires>
</Payment>

Here’s how you can generate the above headers using WSF/Perl,

my $name = new WSO2::WSF::WSHeader( 
    {'name' => 'Name', 'data' => 'Elliotte Harold' } );
 
my $issuer = new WSO2::WSF::WSHeader( 
    {'name' => 'Issuer', 'data' => 'VISA' } );
 
my $number = new WSO2::WSF::WSHeader( 
    {'name' => 'Number', 'data' => '5125456787651230' } );
 
my $expires = new WSO2::WSF::WSHeader( 
    {'name' => 'Expires', 'data' => '2005-12' } );
 
my $payment = new WSO2::WSF::WSHeader( 
    {'name' => 'Payment',
      'ns' => 'http://namespaces.cafeconleche.org/xmljava/ch2/',
      'data' => [$name, $issuer, $number, $expires] } );
 
my $client = new WSO2::WSF::WSClient( 
    {...,
     'inputHeaders' => [$payment] } );

In the next example it shows the header with the mustUnderstand attribute set, this is how you set it,

my $client = new WSO2::WSF::WSClient( 
    {...,
     'mustUnderstand' => 'true',
     'inputHeaders' => [$payment] } );

Next, I’ll take an example from a developerWorks article that shows you how to manipulate SOAP headers in WebSphere. Consider the following header contents (Listing 4 in the article)

<MyPrefix:CallingApplication xmlns:MyPrefix="http://SOAPHeaderDemonstration">
    <name>ServiceRequester1</name>
    <version>1.0</version>
    <timeRequestMade>13:20:00</timeRequestMade>
</MyPrefix:CallingApplication>

The main difference in this is that it contains a custom prefix for the element CallingApplication. Here’s the WSF/Perl code to generate this header,

my $name = new WSO2::WSF::WSHeader( 
    {'name' => 'name', 'data' => 'ServiceRequester1' } );
 
my $version = new WSO2::WSF::WSHeader( 
    {'name' => 'version', 'data' => '1.0' } );
 
my $timereq = new WSO2::WSF::WSHeader( 
    {'name' => 'timeRequestMade', 'data' => '13:20:00' } );
 
my $capp = new WSO2::WSF::WSHeader( 
    {'name' => 'CallingApplication', 'ns' => 'http://SOAPHeaderDemonstration',
     'nsprefix' => 'MyPrefix',
     'data' => [$name, $version, $timereq] } );
 
my $client = new WSO2::WSF::WSClient( 
    {...,
     'inputHeaders' => [$capp] } );

As you saw in the examples, WSHeader class facilitate creating custom SOAP headers with WSF/Perl.

Comments (0)