• iti-comms
  • NEWBIE
  • 0 Points
  • Member since 2004

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 2
    Questions
  • 10
    Replies
Using version 7.0 of the API, when I try to set a batchSize limitation of 5 on my query, I still get 200 results.  Is there something wrong with my XML here that anyone sees?  The formatting here has been done by hand for readability purposes only.

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
>
    <soap:Header>
        <sforce:QueryOptions xmlns:sforce="urn:partner.soap.sforce.com">
            <batchSize xsi:type="xsd:int">5</batchSize>
        </sforce:QueryOptions>
        <sforce:SessionHeader xmlns:sforce="urn:partner.soap.sforce.com">
            <sessionId xsi:type="xsd:string">MoWWXx7_shortened_</sessionId>
        </sforce:SessionHeader>
    </soap:Header>
    <soap:Body>
        <query xmlns="urn:partner.soap.sforce.com">
            <queryString xsi:type="xsd:string">select id, firstname, lastname from lead</queryString>
        </query>
    </soap:Body>
</soap:Envelope>

One of the many annoying "features" of SOAP::Lite (I promise to try not to rant) is that it adds in attributes to tags that you do not tell it to.

<sforce:getServerTimestamp xmlns:sforce="urn:partner.soap.sforce.com" xmlns:sfons="urn:sobject.partner.soap.sforce.com">
    <c-gensym8 xsi:nil="true" />
</sforce:getServerTimestamp>
or
<sforce:getServerTimestamp xsi:nil="true" xmlns:sforce="urn:partner.soap.sforce.com" />
or
<getServerTimestamp xsi:nil="true" xmlns="urn:partner.soap.sforce.com" />

The xsi:nil="true" attribute of this tag is not being overlooked by the SOAP server for version 7.0 of the API.  Version 6.0 properly overlooked this.

Should "invalid" attributes actually cause an error or should they be overlooked?

I am adapting Tony Stubblebine's example to do a simple update of a Lead record.
I can query the database, and insert new records.  When I attempt to update a
record that's there already, I get the message

  Expected a hash with key 'type' as first argument at soaptest6.pl line 49

from the statement
    $sfresult = $sforce->update(%lead);

I dumped out the hash: it has a key "type" which I inserted first, but it's a hash, right, the keys come back in random order, and PostalCode comes back first. 

I must be missing something simple.  Clue please.

  • March 20, 2007
  • Like
  • 0
One of the many annoying "features" of SOAP::Lite (I promise to try not to rant) is that it adds in attributes to tags that you do not tell it to.

<sforce:getServerTimestamp xmlns:sforce="urn:partner.soap.sforce.com" xmlns:sfons="urn:sobject.partner.soap.sforce.com">
    <c-gensym8 xsi:nil="true" />
</sforce:getServerTimestamp>
or
<sforce:getServerTimestamp xsi:nil="true" xmlns:sforce="urn:partner.soap.sforce.com" />
or
<getServerTimestamp xsi:nil="true" xmlns="urn:partner.soap.sforce.com" />

The xsi:nil="true" attribute of this tag is not being overlooked by the SOAP server for version 7.0 of the API.  Version 6.0 properly overlooked this.

Should "invalid" attributes actually cause an error or should they be overlooked?

I am not sure if any of you have experienced the same problems that I did, but just in case any of you have.

I could not find any defininative anwsers on this in any of the forums, so I am posting it here for everyone elses benefit.

When using the salesforce.cgi example script that comes with the Salesforce-0.54.tar.gz package off of sforce.sourceforge.net I was getting the following error:

UNKNOWN_EXCEPTION: Destination URL not reset. The URL returned from login must be set in the SforceService

I looked for this error on the forums and found a couple of places that talked about this problem with PHP and with the Excel Connector, but none dealing with the perl Salesforce module.

It would appear that the API requirements have changed since the module was written, as now you have to save the 'serverUrl' and 'address' along with the sessionId in order to be able to use that sessionId in a subsequent API call.

I modified the salesforce.cgi script to create another cookie to store the serverUrl value for later use.

I modified the  'submit eq Login' 'if' statement as follows:

} elsif (param('submit') eq 'Login') {
    my $result = $port->login('username' => param('username'),
                              'password' => param('password'));
    my $cookie = cookie( -NAME  => 'sf_session',
                         -VALUE => $port->{'sessionId'});
    my $cookie1 = cookie( -NAME  => 'sf_serverurl',
                          -VALUE => $port->{'serverUrl'});
    print header( -COOKIE => [$cookie,$cookie1],
        -LOCATION => "http://$ENV{HTTP_HOST}$ENV{SCRIPT_NAME}?action=list");
    exit;
}


this allows the storing of the serverUrl in a cookie for later use.

I added:

my $SERVURL  = cookie('sf_serverurl');

at the top of the script to grab the data out of the cookie.

then I added:

$port->{'address'} = $SERVURL;

right after the setting of $port->{'sessionId'}.

Hopefully this will help someone one else who is struggling trying to get the saleforce.cgi example script ( and thereby other code using Salesforce.pm API sessions ) working.

While I was at it I also threw in a proper <form> tag and submit button so that you could actually use the dropdown for 'Results per Page'.

I just want to say thanks to the author of the Salesforce.pm module.  It will save me a great amount of time in writing code not having to deal with the foibles of SOAP::Lite and the salesforce wsdl.

A full 'diff -Naur' ( which will allow you to patch the file ) is included below.


--- salesforce.cgi      Tue Dec 16 11:47:40 2003
+++ salesforceM.cgi     Thu Jun  8 02:39:06 2006
@@ -13,6 +13,7 @@
 my $LIMIT    = param('per') || 10;
 my $ACTION   = param('action') || 'list';
 my $SESSION  = cookie('sf_session');
+my $SERVURL  = cookie('sf_serverurl');
 
 my $service = new Salesforce::SforceService;
 my $port = $service->get_port_binding('Soap');
@@ -27,20 +28,25 @@
     my $cookie = cookie( -NAME => 'sf_columns',
                         -VALUE => join(',',param('col')));
     print header( -COOKIE => $cookie,
-                 -LOCATION => "http://$ENV{HTTP_HOST}$ENV{SCRIPT_NAME}?action=list");
+                 -LOCATION => "https://clink.colltech.com$ENV{SCRIPT_NAME}?action=list");
     exit;
 } elsif (param('submit') eq 'Login') {
     my $result = $port->login('username' => param('username'),
                              'password' => param('password'));
     my $cookie = cookie( -NAME => 'sf_session',
                         -VALUE => $port->{'sessionId'});
-    print header( -COOKIE => $cookie,
-       -LOCATION => "http://$ENV{HTTP_HOST}$ENV{SCRIPT_NAME}?action=list");
+    my $cookie1 = cookie( -NAME => 'sf_serverurl',
+                        -VALUE => $port->{'serverUrl'});
+    print header( -COOKIE => [$cookie,$cookie1],
+       -LOCATION => "http://$ENV{HTTP_HOST}$ENV{SCRIPT_NAME}?action=list");
     exit;
 }
 my $COLUMNS  = cookie('sf_columns') || 'Id,FirstName,LastName';
 
 $port->{'sessionId'} = $SESSION;
+#$port->{'serverUrl'} = $SERVURL;
+$port->{'address'} = $SERVURL;
+
 
 print header( -TYPE => 'text/html' );
 print_header();
@@ -82,6 +88,7 @@
 sub list {
     print <<END_HTML;
 <p>
+<form>
 Results per page:
 <select name="per">
   <option>10</option>
@@ -110,12 +117,12 @@
        print "<tr".($i % 2 == 0 ? " bgcolor=\"#EEEEEE\"" : "").">";
        printf "<td>%d.</td>",++$i;
        foreach my $col (split(',',$COLUMNS)) {
-           printf "<td>%s</td>",$elem->{$col};
+           printf "<td>%s</td>",$elem->{$col}[0] ? $elem->{$col}[0] : $elem->{$col};
        }
        print "</tr>\n";
     }
 }
-print '</table>'."\n";
+print '</table><input type=submit name="submit"></form>'."\n";
 
 print <<END_HTML;
 <br />




Good day.

New to Sales Force and this board.

I'm wondering about the maintenance status of the Perl API. Looks like it was last updated in Nov 2004. Is it still being maintained? Anyone on this list working on it? Anyone know if it still matches the SF API?

Thanks.
I've been having some trouble wrapping my head around this one. Hope someone can help. I'd really appreciate the help.

I want to reliably iterate ove the responses from my queries. Not sure how I'd do that when the URL for the results are different for query (//queryResponse/result/records') and querymore (//queryMoreResponse/result/records').

Can someone help me out with some sample code? I've been trying to translate the c++ code provided in the API doc to perl without any luck. This one doesnt work.

$r = $sf->query('query' => "select Id from Case" );
$numrecords = $r->valueof('//queryResponse/result')->{size};
my $done = "false";
if ( $numrecords > 0 ) {
        while ( uc($done) eq "FALSE" ) {
                foreach $elem ( $r->valueof('//queryResponse/result/records') ) {
                        print $elem->{Id}[0]."\n";
                }
                $done = $r->valueof('//queryResponse/result')->{done};
                if ( uc($done) eq "FALSE" ) {
                        $r = $sf->queryMore( 'queryLocator' => $r->valueof('//queryResponse/result')->{queryLocator} );
                        $numrecords = $r->valueof('//queryMoreResponse/result')->{size};
                        foreach $elem ( $r->valueof('//queryMoreResponse/result/records') ) {
                                print $elem->{Id}[0]."\n";
                        }
                } else {
                        $done = $r->valueof('//queryResponse/result')->{done};
                }
        }
} else {
        print "No records match criteria\n";
}

Message Edited by sk2006 on 05-23-2006 06:04 AM

I am trying to  create an attachment using perl and the API. I am base64 encoding the string using MIME::Base64's encode_base64 method. Here's my create call:

        my $r = $sf->create( type=>'Attachment',
                    Body => "$filedata",
                    Name => "$uploaded_filename",
                    ParentId => "$caseid"
                    );

Here's what I get back:

$VAR1 = { 'success' => 'false', 'errors' => { 'fields' => undef, 'statusCode' => 'INVALID_TYPE_ON_FIELD_IN_RECORD', 'message' => 'Body: value not of required type: VGhpcyBpcyBhIHRlc3QgZm9yIHRoZSBhdHRhY2htZW50IGZlYXR1cmUuIE5vdCBjb21wcmVzc2lu ZyBiZWZvcmUgaW5zZXJ0IHlldC4=' }, 'id' => undef };

Can someone help please?
  • April 07, 2006
  • Like
  • 0
Hello.

I had installed WWW::Salesforce, and I tried to call delete api, but some error occurred.
Please give me a hint to resolve this problem.

This is test code.

#!/usr/bin/perl

package SFDCCleaner;

use strict;
use warnings;
use WWW::Salesforce;
use Data:: Dumper;

sub sforce_login {
    my $self = shift;
    my $user = shift;
    my $pass = shift;
    my $port = WWW::Salesforce->new(
        'username' => $user,
        'password' => $pass) || die "could not login to salesforce.com";
    return $port;
}

sub delete_object_multi {
    my($self, $port, $result) = @_;
    my @ids;
    foreach my $obj ($result->valueof('//queryResponse/result/records')) {
        printf("removing %s at %s ...\n", $obj->{'Id'}, $obj->{'type'});
        push(@ids, $obj->{'Id'});
    }
    my $res = $port->delete(@ids);
    print Dumper $res;
}

sub sforce_clear_leads {
    my($self, $port) = @_;

    my $result = $port->query(query => 'select id from Lead', limit => 1);
    my $size = $result->valueof('//queryResponse/result')->{'size'};
    for (my $i = 0; $i < ($size / 100); $i++) {
        $result = $port->query(query => 'select id from Lead', limit => 100);
        $self->delete_object_multi($port, $result);
    }
    $result = $port->query(query => 'select id from Lead', limit => ($size % 100));
    $self->delete_object_multi($port, $result);
}

1;

package main;

my $port = SFDCCleaner->sforce_login('foo@bar', 'foobar');
SFDCCleaner->sforce_clear_leads($port);

ErrorMessage:

$VAR1 = bless( {
   '_content' => [
     'soapenv:Envelope',
     {
       'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
       'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
       'xmlns:soapenv' => 'http://schemas.xmlsoap.org/soap/envelope/'
     },
     [
       [
         'soapenv:Body',
         {},
         [
           [
      'soapenv:Fault',
      {},
      [
        [
          'faultcode',
          {
            'xmlns:ns1' => 'http://xml.apache.org/axis/'
          },
          'ns1:Server.NoService',
          undef,
          'ns1:Server.NoService',
          'faultcode',
          {}
        ],
        [
          'faultstring',
          {},
          'The AXIS engine could not find a target service to invoke!  targetService is u/6.0',
          undef,
          'The AXIS engine could not find a target service to invoke!  targetService is u/6.0',
          'faultstring',
          {}
        ],
        [
          'detail',
          {},
          '',
          undef,
          '',
          'detail',
          {}
        ]
      ],
      undef,
      {
        'detail' => '',
        'faultcode' => 'ns1:Server.NoService',
        'faultstring' => 'The AXIS engine could not find a target service to invoke!  targetService is u/6.0'
      },
      '{http://schemas.xmlsoap.org/soap/envelope/}Fault',
      {}
           ]
         ],
         undef,
         {
           'Fault' => $VAR1->{'_content'}[2][0][2][0][4]
         },
         '{http://schemas.xmlsoap.org/soap/envelope/}Body',
         {}
       ]
     ],
     undef,
     {
       'Body' => $VAR1->{'_content'}[2][0][4]
     },
     '{http://schemas.xmlsoap.org/soap/envelope/}Envelope',
     {}
          ],
   '_current' => [
     $VAR1->{'_content'}
          ]
        }, 'SOAP::SOM' );

Thanks.

Message Edited by bayside on 03-30-2006 01:48 AM

I have taken it upon myself to make some updates to the Salesforce module and publish thim to CPAN so that Perl users have an easier time finding and using said module. A new root level namespace is not feasible for this module, so it is instead called WWW::Salesforce.

I have updated it to work with all Salesforce API v6.0 methods and am going to slowly update it to make it work with all API v7.0 methods. If you take a look at the code and see any bugs or places to make an enhancement, please don't hesitate to drop me an Email with the suggested change. If you already have a PAUSE account and wish to help out with the development process, drop me an Email and I'll be very appreciative of any help.

Also, as an addition, I've added a WWW::Salesforce::Simple module which is, as you could guess, a little simpler to use. I haven't gone crazy with functionality in the Simple module yet, but I am guessing it's functionality will grow a lot as I do more things with Perl and Salesforce.com.

Again, any feedback, be it positive or negative, is appreciated.

Thanks.
http://search.cpan.org/~capoeirab/WWW-Salesforce-0.05/lib/WWW/Salesforce.pm