Resource request from iOS applications

Overview

PMF applications can access resources using the WLResourceRequest REST API.
The REST API works with all adapters and external resources.

Prerequisites:

WLResourceRequest

The WLResourceRequest class handles resource requests to adapters or external resources.

Create a WLResourceRequest object and specify the path to the resource and the HTTP method.
Available methods are: WLHttpMethodGet, WLHttpMethodPost, WLHttpMethodPut and WLHttpMethodDelete.

Objective-C

WLResourceRequest *request = [WLResourceRequest requestWithURL:[NSURL URLWithString:@"/adapters/JavaAdapter/users/"] method:WLHttpMethodGet];

Swift

let request = WLResourceRequestSwift(
    URL: URL(string: "/adapters/JavaAdapter/users"),
    method: WLResourceRequestSwift.WLHttpMethodGet
)
  • For JavaScript adapters, use /adapters/{AdapterName}/{procedureName}
  • For Java adapters, use /adapters/{AdapterName}/{path}. The path depends on how you defined your @Path annotations in your Java code. This would also include any @PathParam you used.
  • To access resources outside of the project, use the full URL as per the requirements of the external server.
  • timeout: Optional, request timeout in milliseconds

Sending the request

Request the resource by using the sendWithCompletionHandler method.
Supply a completion handler to handle the retrieved data:

Objective-C

[request sendWithCompletionHandler:^(WLResponse *response, NSError *error) {
    if (error == nil){
        NSLog(@"%@", response.responseText);
    } else {
        NSLog(@"%@", error.description);
    }
}];

Swift

request.send() {(response, error) in
    if (error != nil){
        print("Failure: " , error!);
    }
    else if (response != nil){
        print("Success: " + response!.responseText);
    }
}

Alternatively, you can use sendWithDelegate and provide a delegate that conforms to both the NSURLConnectionDataDelegate and NSURLConnectionDelegate protocols. This will allow you to handle the response with more granularity, such as handling binary responses.

Parameters

Before sending your request, you may want to add parameters as needed.

Path parameters

As explained above, path parameters (/path/value1/value2) are set during the creation of the WLResourceRequest object.

Query parameters

To send query parameters (/path?param1=value1...) use the setQueryParameter method for each parameter:

Objective-C

[request setQueryParameterValue:@"value1" forName:@"param1"];
[request setQueryParameterValue:@"value2" forName:@"param2"];

Swift

request.setQueryParameterValue("value1", forName: "param1")
request.setQueryParameterValue("value2", forName: "param2")

JavaScript adapters

JavaScript adapters use ordered nameless parameters. To pass parameters to a Javascript adapter, set an array of parameters with the name params:

Objective-C

[request setQueryParameterValue:@"['value1', 'value2']" forName:@"params"];

Swift

request.setQueryParameterValue("['value1', 'value2']", forName: "params")

This should be used with WLHttpMethodGet.

Form parameters

To send form parameters in the body, use sendWithFormParameters instead of sendWithCompletionHandler:

Objective-C

//@FormParam("height")
NSDictionary *formParams = @{@"height":@"175"};

//Sending the request with Form parameters
[request sendWithFormParameters:formParams completionHandler:^(WLResponse *response, NSError *error) {
    if (error == nil){
        NSLog(@"%@", response.responseText);
    } else {
        NSLog(@"%@", error.description);
    }
}];

Swift

//@FormParam("height")
let formParams = ["height":"175"]

//Sending the request with Form parameters
request.send(withFormParameters: formParams) {(response, error) in
    if (error != nil){
        print("Failure: " , error!);
    }
    else if (response != nil){
        print("Success: " + response!.responseText);
    }
}

JavaScript adapters

JavaScript adapters use ordered nameless parameters. To pass parameters to a Javascript adapter, set an array of parameters with the name params:

Objective-C

NSDictionary *formParams = @{@"params":@"['value1', 'value2']"};

Swift

let formParams = ["params":"['value1', 'value2']"]

This should be used with WLHttpMethodPost.

Header parameters

To send a parameter as an HTTP header use the setHeaderValue API:

Objective-C

//@HeaderParam("Date")
[request setHeaderValue:@"2015-06-06" forName:@"birthdate"];

Swift

//@HeaderParam("Date")
request.setHeaderValue("2015-06-06", forName: "birthdate")

Other custom body parameters

  • sendWithBody allows you to set an arbitrary String in the body.
  • sendWithJSON allows you to set an arbitrary dictionary in the body.
  • sendWithData allows you to set an arbitrary NSData in the body.

Callback queue for completionHandler and delegate

In order to avoid blocking the UI while receiving responses, a private callback queue can be specified to execute completionHandler block or delegate for sendWithCompletionHandler and sendWithDelegate set of APIs.

Objective-C

//creating callback queue
dispatch_queue_t completionQueue = dispatch_queue_create("com.ibm.mfp.app.callbackQueue", DISPATCH_QUEUE_SERIAL);

//Sending the request with callback queue
[request sendWithCompletionHandler:completionQueue completionHandler:^(WLResponse *response, NSError *error) {
    if (error == nil){
        NSLog(@"%@", response.responseText);
    } else {
        NSLog(@"%@", error.description);
    }
}];

Swift

//creating callback queue
let completionQueue = DispatchQueue(label: "com.ibm.mfp.app.callbackQueue");

//Sending the request with callback queue
request.send(withQueue: queue){ (response, error) in
    if (error != nil){
        print("Failure: " , error!);
    }
    else if (response != nil){
        print("Success: " + response!.responseText);
    }
}

The response

The response object contains the response data and you can use its methods and properties to retrieve the required information. Commonly used properties are responseText (String), responseJSON (Dictionary) (if the response is in JSON) and status (Int) (the HTTP status of the response).

Use the response and error objects to get the data that is retrieved from the adapter.

Using WLResourceRequest to access external microservices

The WLResourceRequest API can be used to allow mobile apps access to microservices hosted outside of Persistent Mobile Foundation. PMF facilitates secure calls to microservice or enterprise backend service without involving adapters through PMF API Connector. The API Connector, like an adapter, ensures secure invocations based on Persistent Mobile Foundation’s OAuth 2.0 mechanism. With API Connector, PMF administrator can configure and deploy microservice or enterprise backend service details in PMF. The deployed configuration is used by PMF runtime to securely call microservice or backend service requests from the mobile app.

Learn how to configure Persistent Mobile Foundation API Connector.

To access a microservice URL such as http://mybluemix.net/resorts/cities and the PMF runtime backend service is configured as follows

{
  "service": "resorts",
  "baseUrl":"http://mybluemix.net/resorts"
}

WLResourceRequest can be defined as

Objective-C

WLResourceRequest *request = [WLResourceRequest requestWithURL:[NSURL URLWithString@"url"] method:WLHttpMethodGet backendServiceName timeout];

Swift

let request = WLResourceRequestSwift(
    url: URL(),
    method: WLResourceRequestSwift.WLHttpMethodGet,
    backendServiceName: ,
    timeout
)
  • url : Relative URL of the microservice endpoint. For example : cities
  • method : HTTP method to use. For example : WLResourceRequest.GET
  • backendServiceName : Name of the backend service configured on server to fetch data from. For example, resorts.
  • timeout : The timeout in milliseconds for this request.

Objective-C

WLResourceRequest* request = [WLResourceRequest requestWithURL:@"cities" method:WLHttpMethodGet backendServiceName:@"resorts" timeout:3000]

Swift

let request = WLResourceRequestSwift(
    url: URL(string: "/cities"),
    method: WLResourceRequestSwift.WLHttpMethodGet,
    backendServiceName: "resorts" ,
    timeout: 3000
)

For more information

For more information about WLResourceRequest, refer to the API Reference.

Image of the sample application

Sample application

The ResourceRequestSwift project contains an iOS application, implemented in Swift, that makes a resource request using a Java adapter.
The adapter Maven project contains the Java adapter used during the resource request call.

Click to download the iOS project.
Click to download the adapter Maven project.

Sample usage

Follow the sample’s README.md file for instructions.

Note about iOS 9:

Xcode 7 enables Application Transport Security (ATS) by default. To complete the tutorial disable ATS (read more).

  1. In Xcode, right-click the [project]/info.plist file → Open As → Source Code
  2. Paste the following:
     <key>NSAppTransportSecurity</key>
     <dict>
           <key>NSAllowsArbitraryLoads</key>
           <true/>
     </dict>
Last modified on