0

I am working on an assignment where I need to setup a webservice in Salesforce. The other system will have a search screen on their side and they should be able to search Salesforce for list of accounts given a partial account name. As a POC, I developed a simple REST webservice. The code is below.

/*******************************************************************************

    Description - Sample Apex REST service with GET and POST methods

    Service EndPoint : https://test.salesforce.com/services/apexrest/v1/accounts/

    {
    "accountName" : "TEST",

    "accountPhone" : "",

    "accountWebsite" : "http://www.abc.com/"
    }

    *******************************************************************************/

    @RestResource(urlMapping='/v1/accounts/*')
    global with sharing class REST_AccountService {


    @HttpPost

    global static AccountWrapper doPost(String accountName, String accountPhone, String accountWebsite) {

    RestRequest req = RestContext.request;

    RestResponse res = RestContext.response;

    AccountWrapper response = new AccountWrapper();

    System.debug('Request = ' + req.requestBody);
    String acctName = '%' + accountName + '%';
    String acctPhone = accountPhone;
    String acctWebsite = accountWebsite;
    System.debug('Request parameters = ' + acctName + ' \t ' + acctPhone + ' \t ' + acctWebsite);

    List<Account> accLst = new List<Account>();
    //Account acc = null;
    try {
        accLst = [Select Id, Name from Account where Name LIKE :acctName];
    } catch(Exception ex) {
        System.debug('Hit Exception. ' + ex);
    }

    System.debug(accLst);

    for (Account acc : accLst) {
        response.acctList.add(acc);
        response.status = 'Success';
        response.message = 'Your Accounts ware fetched successfully.';
    }
    System.debug('Response = ' + response);
    return response;
}

global class AccountWrapper {
    public List<Account> acctList;
    public String status;
    public String message;

    public AccountWrapper(){
        acctList = new List<Account>();
    }
}

}

The above service is working fine from workbench when I call with EndPoint URL /services/apexrest/v1/accounts and with the request message.

{
"accountName" : "Test",
"accountPhone" : "",
"accountWebsite" : "http://cumobileapps.com/"
}

However, when I call the same service with the same request message from SoapUI, I am getting a null response as shown below.

{
   "status": null,
   "message": null,
   "acctList": []
}

Below is the screenshot of the response from Salesforce workbench.

enter image description here

I am stumbled as to why this is happening. Has anyone faced this issue before? Any help is appreciated.

Debug logs when calling from soap ui is below.

enter image description here

Debug logs when calling from workbench is below. enter image description here

  • What do your debug statements show? That looks like it would be the expected outcome if no Accounts are returned by the query. – David Reed Nov 19 '18 at 21:50
  • 1
    It sounds like your payload is incorrectly configured and all the values are null. Check the method, Content-Type, Accept headers. – sfdcfox Nov 19 '18 at 21:53
  • I have edited my original comment to include the debug logs. As you can see from the screenshot, the request params are there, but the SOQL doesn't seem to be returning any values when the service is called via SoapUI. – Balaji Pooruli Nov 19 '18 at 21:57
  • 2
    @BalajiPooruli Are you authenticating as the same user in both situations? – David Reed Nov 19 '18 at 22:10
  • No. For workbench, I am running as myself (System Administrator profile) and for SoapUI, I am using a service account which has access to Accounts and Contacts object. It is a API Only user account with limited access in Salesforce. – Balaji Pooruli Nov 19 '18 at 22:19
0

This appears to be a record-level visibility issue.

Your web service class is running with sharing, which is good. The authenticated context user's record-level visibility will be applied to query results.

Your class creates a new AccountWrapper regardless of the results it finds:

AccountWrapper response = new AccountWrapper();

But it only populates any of its elements if at least one Account is found:

for (Account acc : accLst) {
    response.acctList.add(acc);
    response.status = 'Success';
    response.message = 'Your Accounts ware fetched successfully.';
}

The response you are receiving

{
   "status": null,
   "message": null,
   "acctList": []
}

is consistent with your code returning a newly-initialized, empty AccountWrapper - which is exactly what we should expect it to do if accLst is empty. Since you note that for SoapUI you are using

service account which has access to Accounts and Contacts object. It is a API Only user account with limited access in Salesforce

I am confident that that's our culprit: the SoapUI user does not have record-level visibility to the test Accounts you are using.

Easy fix to prove this is true: give that user the View All permission on Account and see what happens.

  • 1
    Hi David, Thanks for your help. The API User profile had the "View All" permission on the Accounts checked. However, it appears that some other developer has changed the profile of the service account from 'API User' to 'Basic API User' for which the permissions are not given (Multiple developers are working on the same project). Once I switched the profile of the service account to 'API User', it is working fine. – Balaji Pooruli Nov 20 '18 at 2:37

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.