function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
John Lay 9John Lay 9 

Unable to validate AccountManager APEX Web Service Trailhead Challenge

I've completed the challenge, it has 100% coverage. I've checked all the method names. The URL is valid. I've used Work Bench and curl to test and even tested with multiple Accounts with and without contacts.

I know on other challenges, punctionation was important.  What about the defination of the return? Are there expected names?

I built a class to hold Account ID & Name along with a List of Contact names and IDs. Is this my issue?  Anyone else have a challenge with this challenge?


Any help or hints will be appreciated.

Here are snippets of my code:

@RestResource(urlMapping='/Accounts/*/contacts')
global with sharing class AccountManager {

....

global class APIAccount {
        public ID Id;
        public String Name;
        List<APIContact> Contacts;

...

@HttpGet
    global static APIAccount getAccount() {
        RestRequest request = RestContext.request;
...
 
Best Answer chosen by John Lay 9
Lei ShiLei Shi
You don't have to create a separate Class or a Map. 

Below please find my working code, and be careful with the lower case for contacts.
 
@RestResource(urlMapping='/Accounts/*/contacts')
global class AccountManager {
    @HttpGet
    global static Account getAccount() {
        RestRequest req = RestContext.request;
        String accId = req.requestURI.substringBetween('Accounts/', '/contacts');
        Account acc = [SELECT Id, Name, (SELECT Id, Name FROM Contacts) 
                       FROM Account WHERE Id = :accId];
		return acc;
    }
}

 

All Answers

SinanBunniSinanBunni
Hello,

I have a similar problem - Salesforce failed to validate my solution, as below:
 
@RestResource(urlMapping='/Account/*/contacts')
global class AccountManager {
	
	@HttpGet
	global static Map<String, String> getAccount() {
		RestRequest request = RestContext.request;
		System.debug(request);
		String accountId = request.requestURI.substringBetween('Account/', '/contacts');
		System.debug('AccountManager - accountId: ' + accountId);
		
		Map<String, String> IdToName = new Map<String, String>();
		Account account =  [SELECT Id, Name FROM Account WHERE Id = :accountId];
		List<Contact> contacts = [SELECT Id, Name FROM Contact WHERE AccountId = :account.Id];
		
		IdToName.put(account.Id, account.Name);
		
		for (Contact con : contacts) {
			IdToName.put(con.Id, con.Name);
		}
		
		return IdToName;
	} // end getAccount method 
}

any help is truely appreciated. Thanks you, Sinan
Lei ShiLei Shi
You don't have to create a separate Class or a Map. 

Below please find my working code, and be careful with the lower case for contacts.
 
@RestResource(urlMapping='/Accounts/*/contacts')
global class AccountManager {
    @HttpGet
    global static Account getAccount() {
        RestRequest req = RestContext.request;
        String accId = req.requestURI.substringBetween('Accounts/', '/contacts');
        Account acc = [SELECT Id, Name, (SELECT Id, Name FROM Contacts) 
                       FROM Account WHERE Id = :accId];
		return acc;
    }
}

 
This was selected as the best answer
SinanBunniSinanBunni
Thank you Lei Shi - initially was going with your approach but then the challenge specifically asked us to return Id and Name of Account and Contacts therefore was going with a Map collection.

Thanks for your insight,

Sinan
Esteve GraellsEsteve Graells
For the trailheaders with problemas getting validation on this exercise:
  • The result must be an account (its how I passed) as Lei Shi pointed it out
  • Be very very careful with no records returned from your query as could a nightmare as I faced. Solved by adding: @isTest(SeeAllData=true)
I think it is very woth, at least it was for me to read this article about this: Demystifying SeeAllData in Unit Tests http://opfocus.com/blog/demystifying-seealldata-in-unit-tests/.

All the best,
Esteve
 
Naveen ChoudharyNaveen Choudhary

AccountManager Apex Class


@RestResource(urlMapping='/Accounts/*/contacts')
global class AccountManager {
    @HttpGet
    global static Account getAccount() {
        RestRequest req = RestContext.request;
        String accId = req.requestURI.substringBetween('Accounts/', '/contacts');
        Account acc = [SELECT Id, Name, (SELECT Id, Name FROM Contacts) 
                       FROM Account WHERE Id = :accId];
        return acc;
    }
}


TEST CLASS

@isTest
private class AccountManagerTest {

    private static testMethod void getAccountTest1() {
        Id recordId = createTestRecord();
        // 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 thisAccount = AccountManager.getAccount();
        // Verify results
        System.assert(thisAccount != null);
        System.assertEquals('Test record', thisAccount.Name);

    }

    // Helper method
        static Id createTestRecord() {
        // Create test record
        Account TestAcc = new Account(
          Name='Test record');
        insert TestAcc;
        Contact TestCon= new Contact(
        LastName='Test', 
        AccountId = TestAcc.id);
        return TestAcc.Id;
    }      
}

After saving it "Run All" test from developer console. It'll help you to clear the challange.

Please choose it as best answer.
Mustafa GuldoganMustafa Guldogan
I spent ~ an hour to solve this mystery.
I looked at the developer console log after ruinning the challange and found '/contacts' (lower case) was passed by the engine.
replacing '/Contacts' --> '/contacts' in my code solved my problem.
I may help somebody.
 
George WilliamsGeorge Williams
Esteve,

Wouldn't it be more appropriate to use a @TestSetup method insead of SeeAllData=True to follow SF unit testing standards?
Kellan ScheiberKellan Scheiber
Unreal, Mustafa THANK YOU!

That was my issue has well, I could not get the List to populate with data and once I updated to Contacts from contacts my List populated and I passed the challenge.

 
Janakiraman ChandravadhanJanakiraman Chandravadhan
Thankyou Naveen, it helped!
tbaila tbailatbaila tbaila
Thanks Naveen !
Jayanth B 2Jayanth B 2
Optimized code, refer in case required.

@RestResource(urlMapping='/Accounts/*/contacts')
global class AccountManager {
 @HttpGet
    global static Account getAccount(){
       RestRequest request =  RestContext.request;
        return [Select id, name,(SELECT id,name from Contacts) from Account where id=:request.requestURI.substringBetween('Accounts/',                                  '/contacts')];
}
}


Test class

@isTest
public class AccountManagerTest {

    @isTest public static void executeGetAccount(){
        //making Data ready for Testing
        Account acc = new Account(Name='Jayanth B');
        insert acc;
        insert new Contact(LastName='Jayanth',FirstName='b',AccountId=acc.id);
        
        // Set up a test request
        RestRequest request = new RestRequest();
        request.requestURI = 'https://ap4.salesforce.com/services/apexrest/Accounts/'+(String)acc.id+'/contacts';
        request.httpMethod ='GET';
        //set up request Context 
        RestContext.request =  request;
        // call the method
        Account returnedAcc = AccountManager.getAccount();

    }
}
Charles ThompsonCharles Thompson
@jayanth B 2
Thanks for posting "optimised" code.  Next time, could you mark your code as a code block (in the WYSIWYG editor)?  That makes it easier for future generations to read.

For all who come in the future, the challenge requires the class to start with 
@RestResource(urlMapping='/Accounts/*/contacts')
Note the trailing "/contacts".  The challenge also requires you to specify /contacts on the end of your REST URI.

The class actually doesn't require this, but this unit doesn't make it clear.  You *can* use the urlMapping without '/contacts' and the resulting data is almost identical.  Unfortunately, the challenge doesn't mention this, nor does it test for this simpler (i.e. more easily maintained) usage.  In fact, the challenge should make it clear exactly what type the return result should be and what the URI construction should be.
 
Christopher D. EmersonChristopher D. Emerson
For anyone else who tries everything here but still gets this message ... 
Methods defined as TestMethod do not support Web service callouts
My problem was that I had a couple test triggers on my Account and Contact objects and for some reason those were causing my Test for this lesson to fail. Soon as I deactivated those triggers the Test passed. 
Sambhav Jain 19Sambhav Jain 19
For anyone who might get stuck:
Its not very clear in instructions, that you have to make a test record for account in your test as Test methods cannot read your Organization data.
So either you create some test resords in test class or enable see all data (@IsTest(SeeAllData=true)).  This will allow to read org data in your test method.
DivyanshD SinghDivyanshD Singh
Apex class

@RestResource(urlMapping='/Accounts/*/contacts')
 @isTest(SeeAllData=true)
global class AccountManager{
	@HttpGet
    global static Account getAccount(){
        RestRequest request=RestContext.request;
        String Accountid=request.requestURI.substringBetween('Accounts/*/contacts');
        Account result=[Select id,name,(Select id,name from contacts) from Account where id =:Accountid];
        return result;
    }
}

Test Class

@isTest
public class AccountManagerTest {
    @isTest static void testgetAccount(){
   //     ID recordId=createTestRecord();
        Account ant=new Account(Name = 'Integration Superbadge Challenge');
        insert ant;
        Contact con=new Contact(LastName='challenging Superbadge' ,Accountid=ant.id);
        insert con;
        RestRequest request=new RestRequest();
        request.requestURI='https://ap5.salesforce.com/services/apexrest/Accounts/' + ant.id + '/contacts';
        request.httpMethod='GET';
        restContext.request=request;
        Account acc=AccountManager.getAccount();
        System.assert(acc != null);
}
}

Challenge not yet complete... here's what's wrong:
There was an unexpected error in your org which is preventing this assessment check from completing: System.TypeException: Cannot call test methods in non-test context
Mark Z DeanMark Z Dean
For me it was @Charles Thompson's suggestion that worked. I was missing the 's' in contacts. Thanks Charles!
Charles ThompsonCharles Thompson
Glad I could help, Mark :-)
Best of luck with the rest of the trail.
hemanth pendyalahemanth pendyala
Use below line.
String Accountid = request.requestURI.substringBetween('Accounts/','/contacts');
Pardha MutyalaPardha Mutyala
FATAL_ERROR List has no rows  List has no rows for assignment to SObject.
When i execute the query in Query Editor it is returning a row.
Following is my AccountManager
@RestResource(urlMapping='/Accounts/*/Contacts')
@isTest(SeeAllData=true)
global  class AccountManager {
    
    @HttpGet
    global static Account getAccount(){
        RestRequest request = RestContext.request;
        String acctId = request.requestURI.substringBetween('Accounts/','/Contacts');
        System.debug('Account Id ' + acctId);
       
        Account result = [SELECT Id, Name, (SELECT Id, Name FROM Contacts) FROM Account WHERE Id=:acctId];
        System.debug('Account Id after query ' + acctId);
        System.debug('Acccount Name ' + result.Name);
        return result;
    }
}

and my Test Class
 
@IsTest
public class AccountManagerTest {
       
	@isTest static void testGetAccountById() {
        Id recordId = '0016g00000CxYuoAAF';
        RestRequest request = new RestRequest();
        request.requestUri = 'https://resourceful-raccoon-vwir1z-dev-ed.my.salesforce.com/services/apexrest/Accounts/' + recordId + '/Contacts';
        request.httpMethod = 'GET';
        RestContext.request = request;
        Account acct = AccountManager.getAccount();
        if(acct != null)
        	System.debug(acct.Id);
        else
            System.debug('No Account found');
        
        System.assert(acct != null);
        System.assertEquals('Edge Communications', acct.Name);
    }
}



Can someone help in figuring out the issue
David Roberts 4David Roberts 4
I also spent an extra hour because it wasn't clear about the '/contacts' at the end of the request. I found it by debugging and arrived at the same solution as Lei, Charles and Mustafa.
I used the following to extract the record Id:
Integer subend = request.requestURI.lastIndexOf('/');
Integer subst = 1 + request.requestURI.lastIndexOf('/',subend-1);
accntId = request.requestURI.substring(subst,subend);

but I much prefer Lei's simple solution:
accId = request.requestURI.substringBetween('Accounts/', '/contacts');

 
vidhya mukatividhya mukati
without validating package also you can complete the trailhead with below code i have completed my trailhead


@RestResource(urlMapping='/Accounts/*/contacts')
global class AccountManager {
    
    @HttpGet
    global static Account getAccount() {
         RestRequest request = RestContext.request;
        String accId = request.requestURI.substringBetween('Accounts/','/contacts');
       
     List<Account> acc = [SELECT Id, Name, (SELECT Id, Name FROM Contacts) FROM Account WHERE Id = :accId];
      
    return acc.get(0);
    }
}



@isTest
public class AccountManagerTest {
@isTest(SeeAllData=true)
    public static void getAccountTest(){
        //create Test Data
        Account acc=new Account(Name='testAccount1');
        Contact con=new Contact(Account=acc,AssistantName='vidhyaTest',LastName='mukmuk');
                  insert acc;
        Id recordId=acc.Id;
        insert con;
        
   
        RestRequest request = new RestRequest();
       
         request.requestUri = 'https://sadas-dev-ed.my.salesforce.com/services/apexrest/Accounts/'+recordId+'/mukmuk';
        request.httpMethod = 'GET';
         RestContext.request = request;
   
         // Call the method to test
       Account thisAccount = AccountManager.getAccount();
        // Verify results
        System.assert(thisAccount != null);
       
       
        
    }
 
}
David NuñezDavid Nuñez
Hi All!! I've tried my code, and every single code snipped you posted here but I'm still getting this error: 

Challenge not yet complete in PLAYGROUND
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.

What could it be??

My final class look like this: 
@RestResource(urlMapping='/Accounts/*/contacts')
global class AccountManager {
    
    @HttpGet
    global static Account getAccount() {
         RestRequest request = RestContext.request;
        String accId = request.requestURI.substringBetween('Accounts/','/contacts');
       
     List<Account> acc = [SELECT Id, Name, (SELECT Id, Name FROM Contacts) FROM Account WHERE Id = :accId];
      
    return acc.get(0);
    }
}

And the test like this: 
 
@isTest
public class AccountManagerTest {
@isTest(SeeAllData=true)
    public static void getAccountTest(){
        //create Test Data
        Account acc=new Account(Name='testAccount1');
        Contact con=new Contact(Account=acc,AssistantName='vidhyaTest',LastName='mukmuk');
                  insert acc;
        Id recordId=acc.Id;
        insert con;
        
   
        RestRequest request = new RestRequest();
       
         request.requestUri = 'https://sadas-dev-ed.my.salesforce.com/services/apexrest/Accounts/'+recordId+'/mukmuk';
        request.httpMethod = 'GET';
         RestContext.request = request;
   
         // Call the method to test
       Account thisAccount = AccountManager.getAccount();
        // Verify results
        System.assert(thisAccount != null);
       }
 }


 
Philippe SimoesPhilippe Simoes
Most of the errors in this challenge are related to the Url Mapping, it has to be called exaclty the same way it was defined.
urlMapping='/Accounts/*/contacts'
This is case sensitive, so '/accounts/1234/Contacts' will not work, etc.  
Good luck.
Shalini Priya 9Shalini Priya 9
@David, hope you would have got a solution by now . If not , then create a new Playground and copy the same code , and that should solve the problem . I literally spent 2 hours .. and when I saw no issue in my code .. creatyed the new Org .. and passed the challenge . Good Luck !
 
Shalini Priya 9Shalini Priya 9
Error was - Challenge not yet complete in PLAYGROUND
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.
Lukesh KarmoreLukesh Karmore
Hii , shalini
Have u pass the challenge by changing playground . I m facing the same error  help here thank you..
Lukesh KarmoreLukesh Karmore
Thank you shalini , below code worked for me , i simply create new playground and try it.

Test class
@isTest
private class AccountManagerTest {

    private static testMethod void getAccountTest1() {
        Id recordId = createTestRecord();
        // 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 thisAccount = AccountManager.getAccount();
        // Verify results
        System.assert(thisAccount != null);
        System.assertEquals('Test record', thisAccount.Name);

    }

    // Helper method
        static Id createTestRecord() {
        // Create test record
        Account TestAcc = new Account(
          Name='Test record');
        insert TestAcc;
        Contact TestCon= new Contact(
        LastName='Test', 
        AccountId = TestAcc.id);
        return TestAcc.Id;
    }      
}
 Accountmanager class

@RestResource(urlMapping='/Accounts/*/contacts') 
global class AccountManager {
@HttpGet 
global static Account getAccount() { 
RestRequest request = RestContext.request; 
String accId = request.requestURI.substringBetween('Accounts/','/contacts'); Account acc = [SELECT Id, Name, (SELECT Id, Name FROM Contacts) FROM Account WHERE Id = :accId]; 
return acc;
} }
Curt Grogan 4Curt Grogan 4

I beat my head against a rock on this one for a long time. Finally, I narrowed it down to an issue with the test and found Esteve's comment from 2015 with the answer to my problem. Adding (SeeAllData=True) to the method's @isTest annotation did the trick.

For quick reference here is a snippet of the code.
 

@IsTest 
private class AccountManagerTest {
    @isTest(SeeAllData=true)
    static void testGetAccount() {
        Id accountId = '0014x00000FIL8JAAX';
        String accountName = 'ABC Computing';
        //set up a test request
        RestRequest request = new RestRequest();
        request.requestUri = 
            'https://brave-raccoon-k2074x-dev-ed.my.salesforce.com/Accounts/'
            + accountId + '/contacts/';
        request.httpMethod = 'GET';
        RestContext.request = request;
        
        // method call to test
        Account thisAccount = AccountManager.getAccount();
        
        // verify results
        System.assert(thisAccount != null);
        System.assertEquals(thisAccount.name, accountName, 'Doh!');
    }
}


Esteve, it was a nightmare. The dawn arrived and I woke up when I found your comment.

Thanks, everyone!

Pieter SpoelstraPieter Spoelstra

I'm just a Salesforce noob. Trying in de last 6 weeks to get some development knowledge using Trailhead. But these challenges are too difficult to solve on my own. I continuously miss Salesforce background information. Because there are so many Units, Modules and Trails. Which makes it easy to get lost on the level of needed experiences. And I forgot also a lot. Needed knowledge is shattered. Difficult to say you know enough, to do a challenge. Even it's part of a trail.

I had a lot of problems to solve this on my own, I lack the skill set. Came on this page, to learn about the mistakes I've been made.

  • Module too complex, like the suddenly introduction of `cUrl`. I now what is, I use it sparingly. But I couldn't get it up and running with al these security codes, url's. I would say, explain it in a separate unit.Why explain it, if you don't really need it. It is handy, but it is distracting. Like, I'm using at home Win7, no curl. A small problem to solve, but it breaks the real focus of the lesson.
  • I missed the clue; "urlMapping='/Accounts/*/contacts'" ~ /Accounts/<id_account>/contacts'. It is REST Logic, but how to recognize this.
  • Never knew you can not access 'live' data or use the bad testdesign option @isTest(SeeAllData=true), Took me ages to understand why my account list was empty all the time.
And yes, I've learned a lot! but 50min took me a half day.
Maxim Zhukousky 6Maxim Zhukousky 6
Look out for the right urlMapping, it could've been explained nicer (Account or Accounts). Also, your test record should literally be 'Test Record'.
Ishan Gupta 9Ishan Gupta 9
I tried  Naveen Choudhary code but I'm getting "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."  Please help.
SHAHID IMAMSHAHID IMAM
Apex Class:
@RestResource(urlMapping='/Accounts/*/contacts')
global with sharing class AccountManager{
    @HttpGet
    global static Account getAccount(){
        RestRequest request = RestContext.request;
        String accountId = request.requestURI.substringBetween('Accounts/','/contacts');
        system.debug(accountId);
        Account objAccount = [SELECT Id,Name,(SELECT Id,Name FROM Contacts) FROM Account WHERE Id = :accountId LIMIT 1];
        return objAccount;
    }
}

Test Class:
@IsTest 
private class AccountManagerTest {
    @isTest(SeeAllData=true)
    static void testGetAccount() {
        Id accountId = '0015j00000XrVLlAAN';
        String accountName = 'PanCake';
        //set up a test request
        RestRequest request = new RestRequest();
        request.requestUri ='https://wise-goat-e0r2m4-dev-ed.my.salesforce.com/Accounts/'+ accountId + '/contacts/';
        request.httpMethod = 'GET';
        RestContext.request = request;
        
        // method call to test
        Account thisAccount = AccountManager.getAccount();
        
        // verify results
        System.assert(thisAccount != null);
        System.assertEquals(thisAccount.name, accountName, 'Company ABC');
    }
}

Hey Guys ,Try this one. It will definitely help you to pass the challenge.100% working. If you also passed the challenge hit the thumb.

 
Amar Kumar Das 5Amar Kumar Das 5
Hi All I have write below code but not able to pass I donot understand where is the issue 

So can any one tell me where I am doing wrong here

#Remote Site Setting
Remote Name - > SOAP
URL -> https://th-apex-soap-service.herokuapp.com

#Error
Challenge not yet complete in My Trailhead Playground 1
Executing the method 'getAccount' from the Apex class 'AccountManager' 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.

#Code
@RestResource(urlMapping='/Accounts/*/contacts')
global class AccountManager {
    @HttpGet
    global static Account getAccount() {
        RestRequest req = RestContext.request;
        String accId = req.requestURI.substringBetween('Accounts/', '/contacts');
        Account acc = [SELECT Id, Name, (SELECT Id, Name FROM Contacts) 
                       FROM Account WHERE Id = :accId];
        return acc;
    }
}

#Test Class
@isTest
private class AccountManagerTest {

    private static testMethod void getAccountTest1() {
        Id recordId = createTestRecord();
        // 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 thisAccount = AccountManager.getAccount();
        // Verify results
        System.assert(thisAccount != null);
        System.assertEquals('Test record', thisAccount.Name);

    }

    // Helper method
        static Id createTestRecord() {
        // Create test record
        Account TestAcc = new Account(
          Name='Test record');
        insert TestAcc;
        Contact TestCon= new Contact(
        LastName='Test', 
        AccountId = TestAcc.id);
        return TestAcc.Id;
    }      
}