Abstraction Builder

Building simple and elegant programming abstractions

Pico Tutorial 3 - Hello eBay Finding

| Comments

This is the third tutorial of Pico tutorial series, in first and second tutorials, I showed you how to use Pico with simple web serivces like StockQuote and CurrencyConverter. These services are quite simple, only support one or two calls, and the request/response structures are fairly simple, supporting these simple services only can’t show the full power of Pico, so in this and later tutorials, I will show you how to use Pico with industrial grade services, let’s start with eBay Finding service, please reivew its official site if you are not familiar with this service, bastially, it lets you search items on eBay. eBay Finding service supports SOAP 1.2, so I will also show you how to configure Pico to support SOAP 1.2 protocol, also I will show how to set service required HTTP headers on Pico client.

The source of this tutorial is here

Step 0 - Prerequisite

I suppose you have already read Pico tutorial 1 and 2, and basically you should know:

  • The wsdl driven development process supported by Pico.
  • How to reference Pico as a static library in your project.
  • Or How to reference Pico Source directly in your project.

Step 1 - Generate Objective-C Proxy from WSDL

Download mwsc and run following command in terminal to generate the proxy:

1
bin/mwsc -pico -d generated -prefix Finding_ -ebaysoa http://developer.ebay.com/webservices/Finding/latest/FindingService.wsdl

Depends on the network speed, you may need to wait a few moments to let the code generator download the wsdl and generate code, you may also download the wsdl and run the code generator with a local wsdl.

A few comments about the codegen options:

  • I have added a prefix Finding_ as codegen option, such that all interfaces/types generated will be prefixed. Adding prefix to Objective-C types is a recommended best practice to avoid possible type name conflict with code generated from other services, for example, eBay has a couple of SOA services, and they share a few commons types, without prefixing, you may get conflict if you use two or more eBay SOA services in one application.
  • I have added a special -ebaysoa codegen option, this is because eBay Finding service needs a per-call operation name HTTP header, I added this special flag in the code generator to let it generate the header for me, since I don’t want to add this header everytime I call an eBay Finding service, so this is just a special flag for eBay SOA services and for demo, or a hidden feature, not a generic codegen option.

Step 2 - Create New iOS Project, Add Pico Library and Generated Proxy into Your Project

Create a new simple iOS single view application named “HelloeBayFinding”, don’t choose ARC since Pico does not support ARC yet.

In this tutorial, we will reference Pico as a static library, suppose you have downloaded Pico source project from github site, then:

  1. Drag the Pico xcodeproj into your project,
  2. In the Build Phases of the target, add libPico.a and libxml2.dylib to “Link Binary With Libraries” section.
  3. In the Build Setting of the target, add [your path to Pico source] to “User Header Search Paths” setting, choose “recursive” seach path.

Build the project to ensure that it can build successfully.

Now drag the proxy generated in step 1 into the project, choose “Copy items to destination group’s folder” and “add to targets” when prompted.

Build the project again to ensure that it can build successfully.

You may now review the eBay Finding service SOAP interface generated from wsdl, to learn what kinds of functions are provided by eBay Finding service, and what kinds of parameters are needed to call the serivce, the interface is posted below:

FindingServicePortType_SOAPClient.h source
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Generated by wsdl compiler for ios/objective-c
// DO NOT CHANGE!


#import <Foundation/Foundation.h>
#import "PicoSOAPClient.h"
#import "Finding_GetVersionResponse.h"
#import "Finding_FindItemsAdvancedRequest.h"
#import "Finding_FindItemsAdvancedResponse.h"
#import "Finding_FindItemsForFavoriteSearchResponse.h"
#import "Finding_FindCompletedItemsRequest.h"
#import "Finding_GetSearchKeywordsRecommendationResponse.h"
#import "Finding_FindCompletedItemsResponse.h"
#import "Finding_FindItemsByImageResponse.h"
#import "Finding_FindItemsByProductRequest.h"
#import "Finding_FindItemsByImageRequest.h"
#import "Finding_FindItemsByKeywordsRequest.h"
#import "Finding_FindItemsByProductResponse.h"
#import "Finding_FindItemsIneBayStoresRequest.h"
#import "Finding_FindItemsByCategoryRequest.h"
#import "Finding_GetHistogramsRequest.h"
#import "Finding_GetSearchKeywordsRecommendationRequest.h"
#import "Finding_FindItemsIneBayStoresResponse.h"
#import "Finding_GetVersionRequest.h"
#import "Finding_FindItemsByCategoryResponse.h"
#import "Finding_FindItemsByKeywordsResponse.h"
#import "Finding_FindItemsForFavoriteSearchRequest.h"
#import "Finding_GetHistogramsResponse.h"


/**
 This class is the SOAP client to the FindingServicePortType Web Service.
*/
@interface FindingServicePortType_SOAPClient : PicoSOAPClient {

}

/**
 public method
*/
-(void)getSearchKeywordsRecommendation:(Finding_GetSearchKeywordsRecommendationRequest *) requestObject
      success:(void (^)(Finding_GetSearchKeywordsRecommendationResponse *responseObject))success
      failure:(void (^)(NSError *error, id<PicoBindable> soapFault))failure;

/**
 public method
*/
-(void)findItemsByKeywords:(Finding_FindItemsByKeywordsRequest *) requestObject
      success:(void (^)(Finding_FindItemsByKeywordsResponse *responseObject))success
      failure:(void (^)(NSError *error, id<PicoBindable> soapFault))failure;

/**
 public method
*/
-(void)findItemsByCategory:(Finding_FindItemsByCategoryRequest *) requestObject
      success:(void (^)(Finding_FindItemsByCategoryResponse *responseObject))success
      failure:(void (^)(NSError *error, id<PicoBindable> soapFault))failure;

/**
 public method
*/
-(void)findItemsAdvanced:(Finding_FindItemsAdvancedRequest *) requestObject
      success:(void (^)(Finding_FindItemsAdvancedResponse *responseObject))success
      failure:(void (^)(NSError *error, id<PicoBindable> soapFault))failure;

/**
 public method
*/
-(void)findItemsByProduct:(Finding_FindItemsByProductRequest *) requestObject
      success:(void (^)(Finding_FindItemsByProductResponse *responseObject))success
      failure:(void (^)(NSError *error, id<PicoBindable> soapFault))failure;

/**
 public method
*/
-(void)findItemsIneBayStores:(Finding_FindItemsIneBayStoresRequest *) requestObject
      success:(void (^)(Finding_FindItemsIneBayStoresResponse *responseObject))success
      failure:(void (^)(NSError *error, id<PicoBindable> soapFault))failure;

/**
 public method
*/
-(void)findItemsByImage:(Finding_FindItemsByImageRequest *) requestObject
      success:(void (^)(Finding_FindItemsByImageResponse *responseObject))success
      failure:(void (^)(NSError *error, id<PicoBindable> soapFault))failure;

/**
 public method
*/
-(void)getHistograms:(Finding_GetHistogramsRequest *) requestObject
      success:(void (^)(Finding_GetHistogramsResponse *responseObject))success
      failure:(void (^)(NSError *error, id<PicoBindable> soapFault))failure;

/**
 public method
*/
-(void)findCompletedItems:(Finding_FindCompletedItemsRequest *) requestObject
      success:(void (^)(Finding_FindCompletedItemsResponse *responseObject))success
      failure:(void (^)(NSError *error, id<PicoBindable> soapFault))failure;

/**
 public method
*/
-(void)getVersion:(Finding_GetVersionRequest *) requestObject
      success:(void (^)(Finding_GetVersionResponse *responseObject))success
      failure:(void (^)(NSError *error, id<PicoBindable> soapFault))failure;

/**
 public method
*/
-(void)findItemsForFavoriteSearch:(Finding_FindItemsForFavoriteSearchRequest *) requestObject
      success:(void (^)(Finding_FindItemsForFavoriteSearchResponse *responseObject))success
      failure:(void (^)(NSError *error, id<PicoBindable> soapFault))failure;


@end

All the methods in the interface follow same calling paradigm - you call the service with required request object and register success callback(for success handling logic) and failure callback(for error handling logic) using Objective-C block.

Step 3 - Implement Appliction Logic and UI, Call Proxy to Invoke Web Service as Needed.

First, create a shared service client as below:

EBayFindingServiceClient.h source
1
2
3
4
5
6
7
#import "FindingServicePortType_SOAPClient.h"

@interface EBayFindingServiceClient : FindingServicePortType_SOAPClient

+ (EBayFindingServiceClient *)sharedClient;

@end
EBayFindingServiceClient.m source
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
31
32
33
34
35
36
37
38
39
40
41
#import "EBayFindingServiceClient.h"

static NSString *const eBayAppId = @"YOUR APPID HERE";

// production
static NSString *const eBayFindingServiceURLString = @"http://svcs.ebay.com/services/search/FindingService/v1";

// sandbox
//static NSString *const eBayFindingServiceURLString = @"http://svcs.sandbox.ebay.com/services/search/FindingService/v1";

@implementation EBayFindingServiceClient

+ (EBayFindingServiceClient *)sharedClient {
    static EBayFindingServiceClient *_sharedClient = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedClient = [[EBayFindingServiceClient alloc] initWithEndpointURL:[NSURL URLWithString:eBayFindingServiceURLString]];
    });

    return _sharedClient;
}

- (id)initWithEndpointURL:(NSURL *)URL {

    self = [super initWithEndpointURL:URL];
    if (!self) {
        return nil;
    }

    self.soapVersion = SOAP12; // eBay finding service supports SOAP 12
    [self setDefaultHeader:@"Accept" value:@"application/soap+xml"];
    [self setDefaultHeader:@"Content-Type" value:@"application/soap+xml"];

    [super setDefaultHeader:@"X-EBAY-SOA-SECURITY-APPNAME" value:eBayAppId];
    [super setDefaultHeader:@"X-EBAY-SOA-MESSAGE-PROTOCOL" value:@"SOAP12"];
    [super setDefaultHeader:@"X-EBAY-SOA-REQUEST-DATA-FORMAT" value:@"SOAP"];

    return self;
}

@end

The shared client for eBay Finding service is a little more complex than the simple serivce client in tutorial 1 and 2, this is because that eBay Finding service needs a few HTTP headers set to work, let me give more comments:

  1. eBay Finding service support SOAP12, so we set the client to use SOAP12 protocol, this is not necessary since eBay Finding service also supports SOAP11(which is Pico default), we use SOAP12 here just for demo and to show the capability of Pico.
  2. eBay Finding service needs to set a few HTTP headers to work, for a list of required headers, please refer to doc here.
  3. One mandatory header for eBay Finding service is eBayAppId, you need to register on eBay developer site as an eBay developer then get this id, before your can run this demo, you must fill in your own eBayAppId in the shared client.

Now the UI part, for this hello world like sample, we just need a UITextField for keyword input and UIButton to trigger eBay search by invoking method searchButtonPressed which will indirectly call eBay Finding service through the proxy, fairly simple, see definition in header file ViewController.h and instantiation in implementation file ViewController.m.

Now implement the searchButtonPressed method by invoking service as below:

ViewController.m source
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#import "ViewController.h"
#import "EBayFindingServiceClient.h"
#import "Finding_CommonTypes.h"
#import "SOAP12Fault.h"
#import "SOAP12Faultreason.h"
#import "SOAP12Detail.h"
#import "SOAP12Reasontext.h"

#import "Toast+UIView.h"


- (void)searchButtonPressed:(id)sender
{
    // Hide the keyboard.
    [_searchText resignFirstResponder];

    if (_searchText.text.length > 0) {

        // start progress activity
        [self.view makeToastActivity];

        // Get shared service client
        EBayFindingServiceClient *findingClient = [EBayFindingServiceClient sharedClient];
        findingClient.debug = YES; // enable request/response message logging

        // Build request object
        Finding_FindItemsByKeywordsRequest *request = [[[Finding_FindItemsByKeywordsRequest alloc] init] autorelease];
        request.keywords = _searchText.text;
        // only need one item for demo
        Finding_PaginationInput *pagination = [[Finding_PaginationInput alloc] init];
        pagination.pageNumber = [NSNumber numberWithInt:1];
        pagination.entriesPerPage = [NSNumber numberWithInt:1];
        request.paginationInput = pagination;
        [pagination release];

        // make API call and register callbacks
        [findingClient findItemsByKeywords:request success:^(Finding_FindItemsByKeywordsResponse *responseObject) {

            // stop progress activity
            [self.view hideToastActivity];

            if ([Finding_AckValue_SUCCESS isEqualToString:responseObject.ack]) {
                if (responseObject.searchResult.count > 0) {
                    // show the title of the first found item
                    Finding_SearchItem *item = [responseObject.searchResult.item objectAtIndex:0];

                    // start image downloading progress activity
                    [self.view makeToastActivity];
                    // get gallery image
                    NSURL *imageURL = [NSURL URLWithString:item.galleryURL];
                    NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
                    // stop progress activity
                    [self.view hideToastActivity];

                    UIImage *image = [UIImage imageWithData:imageData];
                    [self.view makeToast:item.title duration:3.0 position:@"center" title:@"Success" image:image];
                } else {
                    // no result
                    [self.view makeToast:@"No result" duration:3.0 position:@"center"];
                }
            } else { // response residenet error
                Finding_ErrorData *errorData = [responseObject.errorMessage.error objectAtIndex:0];
                [self.view makeToast:errorData.message duration:3.0 position:@"center" title:@"Error"];
            }
        } failure:^(NSError *error, id<PicoBindable> soapFault) {

            // stop progress activity
            [self.view hideToastActivity];

            if (error) {
                [self.view makeToast:[error localizedDescription] duration:3.0 position:@"center" title:@"Error"];
            } else if (soapFault) {
                SOAP12Fault *soap12Fault = (SOAP12Fault *)soapFault;
                SOAP12Reasontext *reasonText = [soap12Fault.reason.text objectAtIndex:0];
                [self.view makeToast:reasonText.value duration:3.0 position:@"center" title:@"SOAP Fault"];
            }
        }];

    }
}

More comments to the serivce call code:

  1. I’ve added comments in the code so the whole service call flow should be easy to understand.
  2. We used the eBay Finding FindItemsByKeywords call, which takes a keyword as input, and will return a list of matched items, for demo, we just need one item to display, so we set entries per page to 1.
  3. In the success handling logic, we show the title and the image of the returned item, for demo, the image is downloaded synchronously, but in practice, you should download image asynchronously in order not to block main UI.
  4. Since we set the client to use SOAP12 protocol, in the error handling logic, we need to cast the soapFault variable to type SOAP12Fault and handle it accordingly.
  5. eBay Finding service support response resident error(RRE), so even we get a success response, we still need to check the response for resident error and handle it accordingly.
  6. We used a thrid party library called “Toast” for producing toast like message, this is just for the convenience of demo, not necessary in your real project.

Regarding type hint:

The pageNumber property of Finding_PaginationInput is of type NSNumber, you may get confused what kind of number should be put in PageNumber, short, int or long? Please just consult the source of Finding_PaginationInput.h, it provides type hint as code comments, see sample below. Indeed, every type generated from wsdl has sufficient type hint to assist your development. Xsd annotations in wsdl/schema are also generated into corresponding interfaces/types, further facilitating your development

Finding_PaginationInput.h source
1
2
3
4
5
6
7
8
9
10
11
/**
Specifies which subset of data (or "page") to return in the call
response. The number of data pages is determined by the total number of
items matching the request search criteria (returned in
paginationOutput.totalEntries) divided by the number of entries to
display in each response (entriesPerPage). You can return up to the first
100 pages of the result set by issuing multiple requests and specifying,
in sequence, the pages to return.
type : NSNumber, wrapper for primitive int
*/
@property (nonatomic, retain) NSNumber *pageNumber;

In response handling, the item property of Finding_SearchResult is of type NSMutableArray, you may get confused what is the actual entry type? please just consult the source of Finding_SearchResult.h for type hint, see sample below:

Finding_SearchResult.h source
1
2
3
4
5
6
7
8
9
/**
 
 Container for the data of a single item that matches the search criteria.
 
 
 entry type : class Finding_SearchItem
*/

@property (nonatomic, retain) NSMutableArray *item;

Xsd enumeration is mapped to Objective-C NSString in Pico framework, for example, the ack property of Finding_FindItemsByKeywordsResponse is of type NSString, in wsdl, it’s an xsd enumeration of type AckValue, the type hint in Finding_BaseServiceResponse.h(from which Finding_FindItemsByKeywordsResponse.h extends) will tell you where to find the enum constants allowed by ack property, in this case, the allowed enum constants are in Finding_AckValue.h, see sample below :

Finding_BaseServiceResponse.hsource
1
2
3
4
5
6
7
8
9
/**
 
 Indicates whether or not errors or warnings were generated during the
 processing of the request.
 
 
 type: string constant in Finding_AckValue.h
*/
@property (nonatomic, retain) NSString *ack;

At last, please don’t forget to include the shared client and SOAP12 related header files, it’s a best practice to include the generated Finding_CommonTypes.h file which can free you from writing many import statements required by request building and response handling.

Final Step - Run the Demo

This time let’s run the demo on a real iPod Touch 4 device with iOS 4.3.3, see a screen shot below:

and the debug output:

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
2013-03-29 12:21:53.963 HelloeBayFinding[180:607] Sending request to : http://svcs.ebay.com/services/search/FindingService/v1
2013-03-29 12:21:53.979 HelloeBayFinding[180:607] Request message:
2013-03-29 12:21:53.981 HelloeBayFinding[180:607] <?xml version="1.0" encoding="UTF-8" ?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.ebay.com/marketplace/search/v1/services">
  <soapenv:Body>
      <findItemsByKeywordsRequest>
          <paginationInput>
              <pageNumber>1</pageNumber>
              <entriesPerPage>1</entriesPerPage>
          </paginationInput>
          <keywords>iPad 3</keywords>
      </findItemsByKeywordsRequest>
  </soapenv:Body>
</soapenv:Envelope>
2013-03-29 12:21:53.989 HelloeBayFinding[180:607] Request HTTP Headers : 
{
    Accept = "application/soap+xml";
    "Accept-Language" = "zh-Hans, en, fr, de, ja, nl, it, es, pt, pt-PT, da, fi, nb, sv, ko, zh-Hant, ru, pl, tr, uk, ar, hr, cs, el, he, ro, sk, th, id, ms, en-GB, ca, hu, vi, en-us;q=0.8";
    "Content-Type" = "application/soap+xml";
    "User-Agent" = "HelloeBayFinding/1.0 (iPod touch; iOS 4.3.3; Scale/2.00)";
    "X-Ebay-Soa-Message-Protocol" = SOAP12;
    "X-Ebay-Soa-Operation-Name" = findItemsByKeywords;
    "X-Ebay-Soa-Request-Data-Format" = SOAP;
    "X-Ebay-Soa-Security-Appname" = ************;
}
2013-03-29 12:21:55.446 HelloeBayFinding[180:1a03] Response HTTP status : 
200
2013-03-29 12:21:55.452 HelloeBayFinding[180:1a03] Response HTTP headers : 
{
    Connection = "keep-alive";
    "Content-Encoding" = gzip;
    "Content-Type" = "application/soap+xml;charset=UTF-8";
    Date = "Fri, 29 Mar 2013 04:21:59 GMT";
    Server = "Apache-Coyote/1.1";
    "Transfer-Encoding" = Identity;
    "X-Ebay-Esb-Endpointurl" = "/Root/ESBFunctions/Services/Ports/7002/profile/search/v1/FindingService/destination_default/address_synapse";
    "X-Ebay-Esb-Guid" = "urn:uuid:E626354F8F2A3156CE1365170887318";
    "X-Ebay-Soa-Locale-List" = "en-US_US";
    "X-Ebay-Soa-Message-Protocol" = SOAP12;
    "X-Ebay-Soa-Operation-Name" = findItemsByKeywords;
    "X-Ebay-Soa-Request-Id" = "13db4617-6bd0-a0a2-2d44-7514ffcfbc4b!FindingService!10.10.34.212!v3apifindingcore[!FindItemServiceNextGen!10.10.34.212!v3apifindingcore[!MetadataDependencyService!10.86.122.59!v3mddscore[]]]";
    "X-Ebay-Soa-Response-Data-Format" = XML;
    "X-Ebay-Soa-Service-Metrics" = 266275234;
    "X-Ebay-Soa-Service-Name" = "{http://www.ebay.com/marketplace/search/v1/services}FindingService";
    "X-Ebay-Soa-Service-Version" = "1.12.0";
}
2013-03-29 12:21:55.460 HelloeBayFinding[180:650f] Response message : 
2013-03-29 12:21:55.467 HelloeBayFinding[180:650f] <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"><soapenv:Header/><soapenv:Body><findItemsByKeywordsResponse xmlns="http://www.ebay.com/marketplace/search/v1/services"><ack>Success</ack><version>1.12.0</version><timestamp>2013-03-29T04:21:59.429Z</timestamp><searchResult count="1"><item><itemId>200910323546</itemId><title>Apple iPad 3rd Generation 16GB, Wi-Fi, 9.7in - White Grade B</title><globalId>EBAY-US</globalId><primaryCategory><categoryId>171485</categoryId><categoryName>iPads, Tablets & eBook Readers</categoryName></primaryCategory><galleryURL>http://thumbs3.ebaystatic.com/m/mdIP8tQ1uohjPjsWmhz9q8w/140.jpg</galleryURL><viewItemURL>http://www.ebay.com/itm/Apple-iPad-3rd-Generation-16GB-Wi-Fi-9-7in-White-Grade-B-/200910323546?pt=US_Tablets</viewItemURL><productId type="ReferenceID">109304845</productId><paymentMethod>CashOnPickup</paymentMethod><paymentMethod>PayPal</paymentMethod><autoPay>false</autoPay><postalCode>08753</postalCode><location>Toms River,NJ,USA</location><country>US</country><shippingInfo><shippingServiceCost currencyId="USD">0.0</shippingServiceCost><shippingType>Free</shippingType><shipToLocations>US</shipToLocations><expeditedShipping>false</expeditedShipping><oneDayShippingAvailable>false</oneDayShippingAvailable><handlingTime>1</handlingTime></shippingInfo><sellingStatus><currentPrice currencyId="USD">402.99</currentPrice><convertedCurrentPrice currencyId="USD">402.99</convertedCurrentPrice><sellingState>Active</sellingState><timeLeft>P29DT10H4M7S</timeLeft></sellingStatus><listingInfo><bestOfferEnabled>false</bestOfferEnabled><buyItNowAvailable>false</buyItNowAvailable><startTime>2013-03-28T14:21:06.000Z</startTime><endTime>2013-04-27T14:26:06.000Z</endTime><listingType>FixedPrice</listingType><gift>false</gift></listingInfo><returnsAccepted>true</returnsAccepted><condition><conditionId>2500</conditionId><conditionDisplayName>Seller refurbished</conditionDisplayName></condition><isMultiVariationListing>false</isMultiVariationListing><topRatedListing>true</topRatedListing></item></searchResult><paginationOutput><pageNumber>1</pageNumber><entriesPerPage>1</entriesPerPage><totalPages>113843</totalPages><totalEntries>113843</totalEntries></paginationOutput><itemSearchURL>http://www.ebay.com/sch/i.html?_nkw=iPad+3&_ddo=1&_ipg=1&_pgn=1</itemSearchURL></findItemsByKeywordsResponse></soapenv:Body></soapenv:Envelope>

let’s also try a soap fault case, for example, if you forget to fill in your eBayAppId in the shared client, then you will get:

This is just a bare minimum eBay Finding service based application, for a demo with more functions, please see the eBayDemoApp sample in the Examples folder of Pico source, eBayDemoApp is a composite app which calls two eBay serivces behind, this app searches eBay by calling eBay Fining service, showes a list of matched items on UI, when an item is clicked, it will show item details by calling eBay Shopping service, see a screen shot below.

Now it’s your turn to create iOS applications based on eBay Finding web service, see your next great service based app.

Update 1

The eBay Finding Service Proxy has been extracted as a standalone project, hosted here, and the corresponding appledoc is hosted here, the appledoc is a useful programming reference. By the way, the doc annotations in wsdl are not only generted into the proxy code, but into the appledoc, assisting your development.

Comments