Salesforce Apex Integration Services Part 2
Contents
[NOTE] Updated March 18, 2020. This article may have outdated content or subject matter.
Learning Objectives
After completing this article, you’ll be able to:
Prologue
Ahoy, today’s topic will be on exposing your Apex classes and methods so that external applications can access your application. By making your methods callable through the web, your external applications can integrate with Salesforce to perform all sorts of nifty operations.
Expose a Class as a REST Service
Making APEX classes REST exposable is very straightforward. Simply define your class as global, and define methods as global static. The next step is to annotate each method conforming to a HTTP verb (GET, POST, etc). For example, the code illustrates the correct way to retrieve a Case resource. it’s annotated with @HttpGet and is invoked for a GET request.
|
|
The above code snippet wasn’t too hard to understand right? he base endpoint for Apex REST is https://yourInstance.salesforce.com/services/apexrest/
. he URL mapping is appended to the base endpoint to form the endpoint for your REST service https://yourInstance.salesforce.com/services/apexrest/Case
.
Apex REST Annotations
Annotation | Action | Info |
---|---|---|
@HttpGet | Read | Read records |
@HttpPost | Create | Create records |
@HttpPut | Upsert | Update if existing else create records |
@HttpDelete | Delete | Delete records |
@HttpPatch | Update | Update exiting records |
Governor Limits
Calls to Apex REST classes count against the organization’s API governor limits. the maximum request or response size is 6 MB for synchronous Apex or 12 MB for asynchronous Apex.
Methods annotated with @HttpGet or @HttpDelete should have no parameters. This is because GET and DELETE requests have no request body, so there’s nothing to deserialize.
Apex REST Methods Versioning
it is recommended to implement an versioning strategy for your API endpoints so that you can provide upgrades in functionality without breaking existing code. For example, /Account/v1/* and /Lead/v2/*
.
Apex REST Methods
Apex REST supports two formats for representations of resources: JSON and XML. JSON representations are passed by default in the body of a request or response, and the format is indicated by the Content-Type property in the HTTP header.
A single Apex class annotated with @RestResource can’t have multiple methods annotated with the same HTTP request method. For example, the same class can’t have two methods annotated with @HttpGet.
Apex REST Methods Parameters
You can retrieve the body as a Blob from the HttpRequest object if there are no parameters to the Apex method. If parameters are defined in the Apex method, an attempt is made to deserialize the request body into those parameters. If the Apex method has a non-void return type, the resource representation is serialized into the response body. The following return and parameter types are allowed:
- Apex primitives (excluding sObject and Blob)
- sObjects
- Lists or maps of Apex primitives or sObjects (only maps with String keys are supported)
- User-defined types that contain member variables of the types listed above
Apex REST currently doesn’t support requests of Content-Type multipart/form-data. RestRequest and RestResponse objects are available by default in your Apex methods through the static RestContext object. This example shows how to access these objects through RestContext:
|
|
Apex REST Method Considerations
Here are a few points to consider when you define Apex REST methods:
- If a login call is made from the API for a user with an expired or temporary password, subsequent API calls to custom Apex REST Web service methods aren’t supported and result in the MUTUAL_AUTHENTICATION_FAILED error
- When calling Apex REST methods that are contained in a managed package, you need to include the managed package namespace in the REST call URL
- An Apex method with a non-void return type will have the return value serialized into RestResponse.responseBody
- If the Apex method has no parameters, Apex REST copies the HTTP request body into the RestRequest.requestBody property. If the method has parameters, then Apex REST attempts to deserialize the data into those parameters and the data won’t be deserialized into the RestRequest.requestBody property
REST Parameter User-Defined Types
You can use user-defined types for parameters in your Apex REST methods. Apex REST deserializes request data into public, private, or global class member variables of the user-defined type, unless the variable is declared as static or transient. Also please remember members variables must types allowed by APEX rest as described above, Example below: \*
is used to escape the * for demonstration purposes, not needed in actual APEX.
|
|
Valid JSON request data for this method would look like:
|
|
Request and Response Data Considerations
- The URL patterns testPattern and testPattern/* match the same URL. An REST request for this URL pattern resolves to the class that was saved first
- For request data in either JSON or XML, valid values for Boolean parameters are: true, false (both of these are treated as case-insensitive), 1 and 0 (the numeric values, not strings of “1” or “0”). Any other values for Boolean parameters result in an error
- If the JSON or XML request data contains multiple parameters of the same name, this results in an HTTP 400 status code error response
- Some parameter and return types can’t be used with XML as the Content-Type for the request or as the accepted format for the response, and hence, methods with these parameter or return types can’t be used with XML
- Lists, maps, or collections of collections, for example, List
- > aren’t supported ( not applicable to JSON)
- If the parameter list includes a type that’s invalid for XML and XML is sent, an HTTP 415 status code is returned
- If the return type is a type that’s invalid for XML and XML is the requested response format, an HTTP 406 status code is returned
- Lists, maps, or collections of collections, for example, List
Security Considerations
Invoking a custom Apex REST Web service method always uses system context. Consequently, the current user’s credentials are not used, and any user who has access to these methods can use their full power, regardless of permissions, field-level security, or sharing rules. Developers who expose methods using the Apex REST annotations should therefore take care that they are not inadvertently exposing any sensitive data. Apex class methods that are exposed through the Apex REST API don’t enforce object permissions and field-level security by default. Use the following to align with best practices:
- To enforce object or field-level security while using SOQL SELECT statements in Apex, use the
WITH SECURITY_ENFORCED
clause - You can strip user-inaccessible fields from query and subquery results, or remove inaccessible sObject fields before DML operations, by using the
Security.stripInaccessible
method - Declare classes with the
with sharing
keyword, this in turns enables record-level access enforcement
Apex REST Guidance
To invoke your APEX REST service, you need to use a REST client. You can use almost any REST client, such as your own API client, the examples going forward will utilize the cURL command-line tool. Each time you invoke a request, you should pass along the session ID for authorization. To obtain a session ID, you first create a connected app in your Salesforce organization and enable OAuth. Your client application, cURL in this case, uses the connected app to connect to Salesforce. Follow these instructions to create a connected app that provides you with the consumer key and consumer secret that you need to get your session ID.
Session ID Retrieval
To get your sessionId, use the following command. A SOAP API login() call returns the session ID. You can also have the session ID. The password actually is an combination from login password and Salesforce security token. To retrieve your security, that’s if you have stored somewhere place 😃 read up here
- Navigate to My Personal Information
- Reset My Security Token
- Reset your token (sent by email)
- Use your token
curl -v https://login.salesforce.com/services/oauth2/token -d "grant_type=password" -d "client_id=<your_consumer_key>" -d "client_secret=<your_consumer_secret>" -d "username=<your_username>" -d "password=<your_password_and_security_token>" -H 'X-PrettyPrint:1'
After you’ve successfully authenticated you should see text resembling the following. The result includes an access_token, which is your session ID and instance_url for your organization.
Sample Example
|
|
The interesting section is finally about to start, we will not try executing each of the rest endpoints created earlier using cURL. Use the following commands to access your endpoints accordingly.
Create Data (POST)
The following snippet create a new Case record with the following information, the newly created case id should be in the response:
1 2 3 4 | curl https://salesforceinstance.com/services/apexrest/Cases -X POST -d '{"subject":"Testing", "status":"New","origin":"Phone","priority":"low"}' -H 'Authorization: Bearer <access-token>' -H 'X-PrettyPrint:1' -H "Content-Type: application/json" |
Retrieve Data (GET)
Use the returned id to query the created case record:
curl https://salesforceinstance.com/services/apexrest/Cases/<record_id> -H 'Authorization: Bearer <access_token>' -H 'X-PrettyPrint:1'
Test Your Apex REST Class
Testing your Apex REST class is similar to testing any other Apex class—just call the class methods by passing in parameter values and then verify the results. For methods that don’t take parameters or that rely on information in the REST request, create a test REST request.
|
|
Epilogue
Phew 😆, that was quite the restful journey, we learned quite a lot, starting with Rest Resources in APEX. This includes the various different Http verbs used to create, update and delete resources. We also explored best practices, security considerations, general considerations and sample code samples to get your feet wet. Thanks for stopping by and I hope you were able to learn or reinforce your knowledge regarding Rest Resources on the Salesforce platform 😃
Author Remario Richards
Modified March 18, 2020