+ Start a Discussion
Michael McCormickMichael McCormick 

Apex Web Services Challenge - unclear on return format

The instructions state:

"The method must return the ID and Name for the requested record and all associated contacts with their ID and Name."

I am returning a List<sObject> where the first object is the Account and the remaining objects are the Contacts.

The error message is:

"Executing the 'AccountManager' method failed. Either the service isn't configured with the correct urlMapping, is not global, does not have the proper method name or does not return the requested account and all of its contacts."

I assume it is looking for a different structure to be returned by getAccount() besides List<sObject> but since Account doesn't have a field to store associated Contacts, I'm not sure what to return.

Anyone able to clarify for me what type & structure the return value should have?
Best Answer chosen by Michael McCormick
James LoghryJames Loghry
It should return an Account (singular), but when you query the account, you'll use a relationship query to return the related children contact records.

All Answers

James LoghryJames Loghry
It should return an Account (singular), but when you query the account, you'll use a relationship query to return the related children contact records.
This was selected as the best answer
Michael McCormickMichael McCormick
I was doing this query to get the Contacts, and pulled the Account out of the Contact.
 
[SELECT Id, Name, Account.Id, Account.Name 
                                FROM Contact 
                                WHERE Account.Id = :accountId];

Based on your reply, I see I need a relationship query on Account instead, and now it works. Thanks!
Ajay Ghuge 6Ajay Ghuge 6
Hi ,

This worked for me !!!

@RestResource(urlMapping='/Accounts/*')

global with sharing class AccountManager
{
    @HttpGet
    global static Account getAccount() 
    {
        RestRequest request = RestContext.request;
        List<String> lst = request.requestURI.split('/');                
        String strAccId = lst[lst.size() - 2];
        ResponseWrapper objResp = new ResponseWrapper();
        Account obj = [select Id,Name ,(select Id,Name from Contacts) from Account where Id=:strAccId limit 1];
        return obj ;
    }
}

Regards,
Ajay 
Naveen ChoudharyNaveen Choudhary
What should be the test class for the same as I am getting error whle running the test
Ajay Ghuge 6Ajay Ghuge 6
@IsTest
private class AccountManagerTest{

    @isTest static void testAccountManager() {
        Id recordId = createTestRecord();
        
        Contact objCont = new Contact();
        objCont.LastName = 'Test1';
        objCont.AccountId = recordId ;
        insert objCont ;
        
        Contact objCont2 = new Contact();
        objCont2 .LastName = 'Test2';
        objCont2 .AccountId = recordId ;
        insert objCont2 ;
        
        // Set up a test request
        RestRequest request = new RestRequest();
        request.requestUri =
            'https://na1.salesforce.com/services/apexrest/Accounts/'+recordId+'/contacts';
        request.httpMethod = 'GET';
        RestContext.request = request;
        // Call the method to test
       Account lst = AccountManager.getAccount();
      //Add assert to check the list of size
    }

    // Helper method
    static Id createTestRecord() {
        // Create test record
        Account accTest = new Account(Name='Test Record');
        insert accTest ;
        return accTest.Id;
    }          

}
Bill KratochvilBill Kratochvil
Ajay's AccountManagerTest class worked for me, however I am curious as to why my unit test failed with an error indicating no records returned (System.QueryException: List has no rows for assignment to SObject).  The only difference is I used an "existing" record ID which works when I perform a GET using the same request.requestUri (reference code below) within the Workbench.  

Does the test environment have access to existing records?  The following excerpt from "Getting Started with Apex Unit Tests" is ambiguous - does a "copy" mean a copy of the data or a copy of the org's metadata so it has knowlege of the schema, meaning we always have to create our data within the test?   If so, what is the scope of the data, i.e., only limited to a unit test or to a class?

"Maintaining the security of your data is our highest priority. We don't view or modify any data in your org, and all testing is done in a copy that runs in a secure data center."
@IsTest
private class AccountManagerTest {
    
    @isTest static void testGetCaseById() {
        // Set up a test request
        RestRequest request = new RestRequest();
        
        // The following url works from workbench / Unit test fails
        request.requestUri = '/services/apexrest/Accounts/0015000001BlqjsAAB/contacts';
        request.httpMethod = 'GET';
        RestContext.request = request;
        
        // Call the method to test
        Account thisAccount = AccountManager.getAccount();
        System.assert(thisAccount != null);
    }
}

For reference I use the following method to retrieve data:
@RestResource(urlMapping='/Accounts/*/contacts')
global with sharing class AccountManager {

    @HttpGet
    global static Account getAccount() {
        RestRequest request = RestContext.request;

        // Grab the caseId from the wildcard
		String caseId = request.requestURI.substringBetween('Accounts/','/contacts');        

        System.debug('Using caseId = '+caseId);

        // Return results
        Account result= [SELECT Id, Name, (Select Id, Name From Contacts) 
                        FROM Account
                        WHERE Id = :caseId];
        return result;
    }
}

 
David GranadosDavid Granados
Hello,

I keep getting the following error message eventhough I do "Run All", please help :)

Challenge not yet complete... here's what's wrong:
The 'AccountManager' class did not achieve 100% code coverage via your test methods. Make sure that you chose 'Run All' tests in the Developer Console at least once before attempting to verify this challenge.
suresh bashettysuresh bashetty
Hi David,
Seems your 'AccountManager' class didn't covered 100% of code coverage. We have to click on 'Run Test' button in that 'AccountManagerTest' class and check whether you covered the class 100% or not.
Feisal IbrahimFeisal Ibrahim
@David use the @Ajay Ghuge test for test only. that worked for me.