Expose Your Apex Class as a Web Service
You can expose your Apex class methods as a REST or SOAP web service operation. By making your methods callable through the web, your external applications can integrate with Salesforce to perform all sorts of nifty operations.
For example, say your company’s call center is using an internal application to manage on-premises resources. Customer support representatives are expected to use the same application to perform their daily work, including managing case records in Salesforce. By using one interface, representatives can view and update case records and access internal resources. The application calls an Apex web service class to manage Salesforce case records.
Expose a Class as a REST Service
Making your Apex class available as a REST web service is straightforward. Define your class as global, and define methods as global static. Add annotations to the class and methods. For example, this sample Apex REST class uses one method. The getRecord method is a custom REST API call. It’s annotated with @HttpGet and is invoked for a GET request.
1 | @RestResource (urlMapping= '/Account/*' ) |
2 | global with sharing class MyRestResource { |
3 | @HttpGet |
4 | global static Account getRecord() { |
5 | // Add your code |
6 | } |
7 | } |
As you can see, the class is annotated with @RestResource(urlMapping='/Account/*). The base endpoint for Apex REST is https://yourInstance.salesforce.com/services/apexrest/. The URL mapping is appended to the base endpoint to form the endpoint for your REST service. For example, in the class example, the REST endpoint ishttps://yourInstance.salesforce.com/services/apexrest/Account/. For your org, it could look something like,https://yourInstance.salesforce.com/services/apexrest/Account/.
The URL mapping is case-sensitive and can contain a wildcard character (*).
Define each exposed method as global static and add an annotation to associate it with an HTTP method. The following annotations are available. You can use each annotation only once in each Apex class.
Annotation | Action | Details |
---|---|---|
@HttpGet | Read | Reads or retrieves records. |
@HttpPost | Create | Creates records. |
@HttpDelete | Delete | Deletes records. |
@HttpPut | Upsert | Typically used to update existing records or create records. |
@HttpPatch | Update | Typically used to update fields in existing records. |
Expose a Class as a SOAP Service
ReplyDeleteMaking your Apex class available as a SOAP web service is as easy as with REST. Define your class as global. Add thewebservice keyword and the static definition modifier to each method you want to expose. The webservice keyword provides global access to the method it is added to.
For example, here’s a sample class with one method. The getRecord method is a custom SOAP API call that returns an Account record.
1
global with sharing class MySOAPWebService {
2
webservice static Account getRecord(String id) {
3
// Add your code
4
}
5
}
The external application can call your custom Apex methods as web service operations by consuming the class WSDL file. Generate this WSDL for your class from the class detail page, accessed from the Apex Classes page in Setup. You typically send the WSDL file to third-party developers (or use it yourself) to write integrations for your web service.
Because platform security is a first-class Salesforce citizen, your web service requires authentication. In addition to the Apex class WSDL, external applications must use either the Enterprise WSDL or the Partner WSDL for login functionality.
Apex REST Walkthrough
Now the fun stuff. The next few steps walk you through the process of building an Apex REST service. First, you create the Apex class that is exposed as a REST service. Then you try calling a few methods from a client, and finally write unit tests. There’s quite a bit of code, but it will be worth the effort!
Your Apex class manages case records. The class contains five methods, and each method corresponds to an HTTP method. For example, when the client application invokes a REST call for the GET HTTP method, the getCaseByIdmethod is invoked.
Because the class is defined with a URL mapping of /Cases/*, the endpoint used to call this REST service is any URI that starts with https://yourInstance.salesforce.com/services/apexrest/Cases/.
We suggest that you also think about versioning your API endpoints so that you can provide upgrades in functionality without breaking existing code. You could create two classes specifying URL mappings of /Cases/v1/* and /Cases/v2/* to implement this functionality.
Let’s get started by creating an Apex REST class.
Open the Developer Console under Your Name or the quick access menu (Setup gear icon).
In the Developer Console, select File | New | Apex Class.
For the class name, enter CaseManager and then click OK.
Replace the autogenerated code with the following class definition.
@RestResource(urlMapping='/Cases/*')
ReplyDelete02
global with sharing class CaseManager {
03
04
@HttpGet
05
global static Case getCaseById() {
06
RestRequest request = RestContext.request;
07
// grab the caseId from the end of the URL
08
String caseId = request.requestURI.substring(
09
request.requestURI.lastIndexOf('/')+1);
10
Case result = [SELECT CaseNumber,Subject,Status,Origin,Priority
11
FROM Case
12
WHERE Id = :caseId];
13
return result;
14
}
15
16
@HttpPost
17
global static ID createCase(String subject, String status,
18
String origin, String priority) {
19
Case thisCase = new Case(
20
Subject=subject,
21
Status=status,
22
Origin=origin,
23
Priority=priority);
24
insert thisCase;
25
return thisCase.Id;
26
}
27
28
@HttpDelete
29
global static void deleteCase() {
30
RestRequest request = RestContext.request;
31
String caseId = request.requestURI.substring(
32
request.requestURI.lastIndexOf('/')+1);
33
Case thisCase = [SELECT Id FROM Case WHERE Id = :caseId];
34
delete thisCase;
35
}
36
37
@HttpPut
38
global static ID upsertCase(String subject, String status,
39
String origin, String priority, String id) {
40
Case thisCase = new Case(
41
Id=id,
42
Subject=subject,
43
Status=status,
44
Origin=origin,
45
Priority=priority);
46
// Match case by Id, if present.
47
// Otherwise, create new case.
48
upsert thisCase;
49
// Return the case ID.
50
return thisCase.Id;
51
}
52
53
@HttpPatch
54
global static ID updateCaseFields() {
55
RestRequest request = RestContext.request;
56
String caseId = request.requestURI.substring(
57
request.requestURI.lastIndexOf('/')+1);
58
Case thisCase = [SELECT Id FROM Case WHERE Id = :caseId];
59
// Deserialize the JSON string into name-value pairs
60
Map params = (Map)JSON.deserializeUntyped(request.requestbody.tostring());
61
// Iterate through each parameter field and value
62
for(String fieldName : params.keySet()) {
63
// Set the field and value on the Case sObject
64
thisCase.put(fieldName, params.get(fieldName));
65
}
66
update thisCase;
67
return thisCase.Id;
68
}
69
70
}
Press CTRL+S to save.
Create a Record with a POST Method
ReplyDeleteLet’s use the Apex REST class that you’ve just created and have some fun. First, we’ll call the POST method to create a case record.
To invoke your REST service, you need to use a… REST client! You can use almost any REST client, such as your own API client, the cURL command-line tool, or the curl library for PHP. We’ll use the Workbench tool as our REST client application, but we’ll take a peek at cURL later on.
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. Since JSON is easier to read and understand than XML, this unit uses JSON exclusively. In this step, you send a case record in JSON format.
Apex REST supports OAuth 2.0 and session authentication mechanisms. In simple terms, this means that we use industry standards to keep your application and data safe. Fortunately, you can use Workbench to make testing easier. Workbench is a powerful, web-based suite of tools for administrators and developers to interact with orgs via Force.com APIs. With Workbench, you use session authentication as you log in with your username and password to Salesforce. And you use the REST Explorer to call your REST service.
Navigate to https://workbench.developerforce.com/login.php.
For Environment, select Production.
Select the latest API version from the API Version drop-down.
Accept the terms of service, and click Login with Salesforce.
To allow Workbench to access your information, click Allow.
Enter your login credentials and then click Log in to Salesforce.
After logging in, select utilities | REST Explorer.
Select POST.
The URL path that REST Explorer accepts is relative to the instance URL of your org. Provide only the path that is appended to the instance URL. In the relative URI input field, replace the default URI with/services/apexrest/Cases/.
For the request body, insert the following JSON string representation of the object to insert.
1
{
2
"subject" : "Bigfoot Sighting!",
3
"status" : "New",
4
"origin" : "Phone",
5
"priority" : "Low"
6
}
Click Execute.
This invocation calls the method that is associated with the POST HTTP method, namely the createCase method.
To view the response returned, click Show Raw Response.
The returned response looks similar to this response. The response contains the ID of the new case record. Your ID value is likely different from 50061000000t7kYAAQ. Save your ID value to use in the next steps.
1
HTTP/1.1 200 OK
2
Date: Wed, 07 Oct 2015 14:18:20 GMT
3
Set-Cookie: BrowserId=F1wxIhHPQHCXp6wrvqToXA;Path=/;Domain=.salesforce.com;Expires=Sun, 06-Dec-2015 14:18:20 GMT
4
Expires: Thu, 01 Jan 1970 00:00:00 GMT
5
Content-Type: application/json;charset=UTF-8
6
Content-Encoding: gzip
7
Transfer-Encoding: chunked
8
9
"50061000000t7kYAAQ"
Retrieve Data with a Custom GET Method
By following similar steps as before, use Workbench to invoke the GET HTTP method.
In Workbench, select GET.
Enter the URI /services/apexrest/Cases/, replacing with the ID of the record you created in the previous step.
Click Execute.
This invocation calls the method associated with the GET HTTP method, namely the getCaseById method.
To view the response returned, click Show Raw Response.
The returned response looks similar to this response. The response contains the fields that the method queried for the new case record.
ReplyDelete01 HTTP/1.1 200 OK
02 Date: Wed, 07 Oct 2015 14:28:20 GMT
03 Set-Cookie: BrowserId=j5qAnPDdRxSu8eHGqaRVLQ;Path=/;Domain=.salesforce.com;Expires=Sun, 06-Dec-2015 14:28:20 GMT
04 Expires: Thu, 01 Jan 1970 00:00:00 GMT
05 Content-Type: application/json;charset=UTF-8
06 Content-Encoding: gzip
07 Transfer-Encoding: chunked
{
"attributes" : {
"type" : "Case",
"url" : "/services/data/v34.0/sobjects/Case/50061000000t7kYAAQ"
}
"CaseNumber" : "00001026",
"Subject" : "Bigfoot Sighting!",
"Status" : "New",
"Origin" : "Phone",
"Priority" : "Low",
"Id" : "50061000000t7kYAAQ"
} Retrieve Data Using cURL
Every good developer should know at least three things: 1) how to make an animated GIF of yourself eating ice cream; 2) the value of pi to 25 decimal places; and 3) how to use cURL. The first two are beyond the scope of this module, so we’ll concentrate on the last one.
cURL is a command-line tool for getting or sending files using URL syntax. It comes in quite handy when working with REST endpoints. Instead of using Workbench for your Apex REST service, you’ll use cURL to invoke the GET HTTP method. Each time you “cURL” your REST endpoint, you pass along the session ID for authorization. You were spoiled when working in Workbench because it passes the session ID for you, under the covers, after you log in.
You can obtain a session ID a few different ways, but the easiest—because you’re already in Workbench—is to grab the ID from there. In the top menu, select info | Session Information and then expand the Connection folder to find the session ID. Now open up terminal or the command prompt and enter your cURL command, which will be similar to the following.
ReplyDelete1curl https://yourInstance.salesforce.com/services/apexrest/Cases/ -H 'Authorization: Bearer ' -H 'X-PrettyPrint:1'
ReplyDeleteAfter pressing Enter, you see something similar to the following. Now that you are a command-line master, feel free to cURL, jq, sed, awk, and grep to your heart’s content. For more info on cURL, see the Resources section. cURL and response from the command line
Update Data with a Custom PUT or PATCH Method
You can update records with the PUT or PATCH HTTP methods. The PUT method either updates the entire resource, if it exists, or creates the resource if it doesn’t exist. PUT is essentially an upsert method. The PATCH method updates only the specified portions of an existing resource. In Apex, update operations update only the specified fields and don’t overwrite the entire record. We’ll write some Apex code to determine whether our methods update or upsert.
Update Data with the PUT Method: The upsertCase method that you added to the CaseManager class implements the PUT action. This method is included here for your reference. The method uses the built-in upsert Apex DML method to either create or overwrite case record fields by matching the ID value. If an ID is sent in the body of the request, the case sObject is populated with it. Otherwise, the case sObject is created without an ID. The upsert method is invoked with the populated case sObject, and the DML statement does the rest. Voila!
@HttpPut global static ID upsertCase(String subject, String status, String origin, String priority, String id) {
Case thisCase = new Case(Id=id, Subject=subject, Status=status, Origin=origin, Priority=priority);
// Match case by Id, if present.
// Otherwise, create new case.
upsert thisCase;
// Return the case ID.
return thisCase.Id; }
To invoke the PUT method:
In Workbench REST Explorer, select PUT.
For the URI, enter /services/apexrest/Cases/.The upsertCase method expects the field values to be passed in the request body. Add the following for the request body, and then replace with the ID of the case record you created earlier.{
"id": "",
"status" : "Working",
"subject" : "Bigfoot Sighting!",
"priority" : "Medium"}
Note:The ID field is optional. To create a case record, omit this field. In our example, you’re passing this field because you want to update the case record.Click Execute.This request invokes the upsertCase method from your REST service. The Status, Subject, and Priority fields are updated. The subject is updated, even though its value matches the old subject. Also, because the request body didn’t contain a value for the Case Origin field, the origin parameter in the upsertCase method is null. As a result, when the record is updated, the Origin field is cleared. To check these fields, view this record in Salesforce by navigating to https://yourInstance.salesforce.com/.
Update Data with the PATCH Method: As an alternative to the PUT method, use the PATCH method to update record fields. You can implement the PATCH method in different ways. One way is to specify parameters in the method for each field to update. For example, you can create a method to update the priority of a case with this signature: updateCasePriority(String priority). To update multiple fields, you can list all the desired fields as parameters.
Another approach that provides more flexibility is to pass the fields as JSON name/value pairs in the request body. That way the method can accept an arbitrary number of parameters, and the parameters aren’t fixed in the method’s signature. Another advantage of this approach is that no field is accidentally cleared because of being null. TheupdateCaseFields method that you added to the CaseManager class uses this second approach. This method deserialize the JSON string from the request body into a map of name/value pairs and uses the sObject PUT method to set the fields.
01@HttpPatch
ReplyDelete02
global static ID updateCaseFields() {
03
RestRequest request = RestContext.request;
04
String caseId = request.requestURI.substring(
05
request.requestURI.lastIndexOf('/')+1);
06
Case thisCase = [SELECT Id FROM Case WHERE Id = :caseId];
07
// Deserialize the JSON string into name-value pairs
08
Map params = (Map)JSON.deserializeUntyped(request.requestbody.tostring());
09
// Iterate through each parameter field and value
10
for(String fieldName : params.keySet()) {
11
// Set the field and value on the Case sObject
12
thisCase.put(fieldName, params.get(fieldName));
13
}
14
update thisCase;
15
return thisCase.Id;
16
}
To invoke the PATCH method:
In Workbench REST Explorer, click PATCH.
For the URI, enter /services/apexrest/Cases/. Replace with the ID of the case record created earlier. Enter the following JSON in the Request Body.
1
{
2
"status" : "Escalated",
3
"priority" : "High"
4
}
This JSON has two field values: status and priority. The updateCaseFields method retrieves these values from the submitted JSON and are used to specify the fields to update in the object.
Click Execute.
This request invokes the updateCaseFields method in your REST service. The Status and Priority fields of the case record are updated to new values. To check these fields, view this record in Salesforce by navigating tohttps://yourInstance.salesforce.com/.
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.
In general, here’s how you test Apex REST services. To simulate a REST request, create a RestRequest in the test method, and then set properties on the request as follows. You can also add params that you “pass” in the request to simulate URI parameters.
01
// Set up a test request
02
RestRequest request = new RestRequest();
03
04
// Set request properties
05
request.requestUri =
06
'https://yourInstance.salesforce.com/services/apexrest/Cases/'
07
+ recordId;
08
request.httpMethod = 'GET';
09
10
// Set other properties, such as parameters
11
request.params.put('status', 'Working');
12
13
// more awesome code here....
14
// Finally, assign the request to RestContext if used
15
RestContext.request = request;
If the method you’re testing accesses request values through RestContext, assign the request to RestContext to populate it (RestContext.request = request;).
Now, let’s save the entire class in the Developer Console and run the results.
In the Developer Console, select File | New | Apex Class.
For the class name, enter CaseManagerTest and then click OK.
Replace the autogenerated code with the following class definition.
01
ReplyDelete@IsTest
02
private class CaseManagerTest {
03
04
@isTest static void testGetCaseById() {
05
Id recordId = createTestRecord();
06
// Set up a test request
07
RestRequest request = new RestRequest();
08
request.requestUri =
09
'https://yourInstance.salesforce.com/services/apexrest/Cases/'
10
+ recordId;
11
request.httpMethod = 'GET';
12
RestContext.request = request;
13
// Call the method to test
14
Case thisCase = CaseManager.getCaseById();
15
// Verify results
16
System.assert(thisCase != null);
17
System.assertEquals('Test record', thisCase.Subject);
18
}
19
20
@isTest static void testCreateCase() {
21
// Call the method to test
22
ID thisCaseId = CaseManager.createCase(
23
'Ferocious chipmunk', 'New', 'Phone', 'Low');
24
// Verify results
25
System.assert(thisCaseId != null);
26
Case thisCase = [SELECT Id,Subject FROM Case WHERE Id=:thisCaseId];
27
System.assert(thisCase != null);
28
System.assertEquals(thisCase.Subject, 'Ferocious chipmunk');
29
}
30
31
@isTest static void testDeleteCase() {
32
Id recordId = createTestRecord();
33
// Set up a test request
34
RestRequest request = new RestRequest();
35
request.requestUri =
36
'https://yourInstance.salesforce.com/services/apexrest/Cases/'
37
+ recordId;
38
request.httpMethod = 'GET';
39
RestContext.request = request;
40
// Call the method to test
41
CaseManager.deleteCase();
42
// Verify record is deleted
43
List cases = [SELECT Id FROM Case WHERE Id=:recordId];
44
System.assert(cases.size() == 0);
45
}
46
47
@isTest static void testUpsertCase() {
48
// 1. Insert new record
49
ID case1Id = CaseManager.upsertCase(
50
'Ferocious chipmunk', 'New', 'Phone', 'Low', null);
51
// Verify new record was created
52
System.assert(Case1Id != null);
53
ReplyDeleteCase case1 = [SELECT Id,Subject FROM Case WHERE Id=:case1Id];
54
System.assert(case1 != null);
55
System.assertEquals(case1.Subject, 'Ferocious chipmunk');
56
// 2. Update status of existing record to Working
57
ID case2Id = CaseManager.upsertCase(
58
'Ferocious chipmunk', 'Working', 'Phone', 'Low', case1Id);
59
// Verify record was updated
60
System.assertEquals(case1Id, case2Id);
61
Case case2 = [SELECT Id,Status FROM Case WHERE Id=:case2Id];
62
System.assert(case2 != null);
63
System.assertEquals(case2.Status, 'Working');
64
}
65
66
@isTest static void testUpdateCaseFields() {
67
Id recordId = createTestRecord();
68
RestRequest request = new RestRequest();
69
request.requestUri =
70
'https://yourInstance.salesforce.com/services/apexrest/Cases/'
71
+ recordId;
72
request.httpMethod = 'PATCH';
73
request.addHeader('Content-Type', 'application/json');
74
request.requestBody = Blob.valueOf('{"status": "Working"}');
75
RestContext.request = request;
76
// Update status of existing record to Working
77
ID thisCaseId = CaseManager.updateCaseFields();
78
// Verify record was updated
79
System.assert(thisCaseId != null);
80
Case thisCase = [SELECT Id,Status FROM Case WHERE Id=:thisCaseId];
81
System.assert(thisCase != null);
82
System.assertEquals(thisCase.Status, 'Working');
83
}
84
85
// Helper method
86
static Id createTestRecord() {
87
// Create test record
88
Case caseTest = new Case(
89
Subject='Test record',
90
Status='New',
91
Origin='Phone',
92
Priority='Medium');
93
insert caseTest;
94
return caseTest.Id;
95
}
96
97
}
Press CTRL+S to save.
Run all the tests in your org by selecting Test | Run All.
The test results display in the Tests tab. After the test execution finishes, check the CaseManager row in the Overall Code Coverage pane. It’s at 100% coverage
Anusha Ak14 June 2016 at 02:58
ReplyDeleteCreate a Record with a POST Method
Is it callin service or call out service anusha gaaru.just we are dealing with cases create,update,delete and so on operation in salesforce.
could you please explain me.
Thanks in advance.