+ Start a Discussion
EmilienGuichardEmilienGuichard 

Trailhead Apex Integration Services - Apex SOAP Callouts - The Apex class 'ParkLocator' does not appear to be calling the SOAP endpoint.

Hi all,

I'm stuck in the Apex Integration Services - Apex SOAP Callouts challenge with the following message "The Apex class 'ParkLocator' does not appear to be calling the SOAP endpoint.".

Could you please advise ?
Best Answer chosen by EmilienGuichard
Jeff DouglasJeff Douglas
Try changing line #3 in ParkLocator to: 
ParkService.ParksImplPort park = new ParkService.ParksImplPort();
Sorry... it's case sensitive.  :(

If you had entered ParkService originally it would have generated this code in this manner. Not sure if it didn't overwrite these classes or something.

Jeff Douglas
Trailhead Developer Advocate

All Answers

James LoghryJames Loghry
I ran into this issue too.  You have to pay close attention to the challenge.  When you import the WSDL, it defaults your Apex Class name to "parksServices".  (Note the pluralization and the lower case p).  Instead of accepting the default after you click the import WSDL button, you'll want to change it to "ParkService".

You can try refactoring your Apex to work with this class, but it's easier to delete the Apex class(es) and start the challenge from scratch with this in mind.

 
EmilienGuichardEmilienGuichard
Hi James and thanks for your anwser.

I have deleted my classes and imported again the wsdl paying attention to the name but I still into the same issue.

All the classes are compiling fine.

here are my classes :
public class ParkLocator {
    public static string[] country(String country) {
        parkService.parksImplPort park = new parkService.parksImplPort();
        return park.byCountry(country);
    }
}
//Generated by wsdl2apex

public class ParkService {
    public class byCountryResponse {
        public String[] return_x;
        private String[] return_x_type_info = new String[]{'return','http://parks.services/',null,'0','-1','false'};
        private String[] apex_schema_type_info = new String[]{'http://parks.services/','false','false'};
        private String[] field_order_type_info = new String[]{'return_x'};
    }
    public class byCountry {
        public String arg0;
        private String[] arg0_type_info = new String[]{'arg0','http://parks.services/',null,'0','1','false'};
        private String[] apex_schema_type_info = new String[]{'http://parks.services/','false','false'};
        private String[] field_order_type_info = new String[]{'arg0'};
    }
    public class ParksImplPort {
        public String endpoint_x = 'https://th-apex-soap-service.herokuapp.com/service/parks';
        public Map<String,String> inputHttpHeaders_x;
        public Map<String,String> outputHttpHeaders_x;
        public String clientCertName_x;
        public String clientCert_x;
        public String clientCertPasswd_x;
        public Integer timeout_x;
        private String[] ns_map_type_info = new String[]{'http://parks.services/', 'ParkService'};
        public String[] byCountry(String arg0) {
            ParkService.byCountry request_x = new ParkService.byCountry();
            request_x.arg0 = arg0;
            ParkService.byCountryResponse response_x;
            Map<String, ParkService.byCountryResponse> response_map_x = new Map<String, ParkService.byCountryResponse>();
            response_map_x.put('response_x', response_x);
            WebServiceCallout.invoke(
              this,
              request_x,
              response_map_x,
              new String[]{endpoint_x,
              '',
              'http://parks.services/',
              'byCountry',
              'http://parks.services/',
              'byCountryResponse',
              'ParkService.byCountryResponse'}
            );
            response_x = response_map_x.get('response_x');
            return response_x.return_x;
        }
    }
}
@isTest
private class ParkLocatorTest {
    @isTest static void testCallout() {              
        // This causes a fake response to be generated
        Test.setMock(WebServiceMock.class, new ParkServiceMock());
        // Call the method that invokes a callout
        //Double x = 1.0;
        //Double result = AwesomeCalculator.add(x, y);
        
        String country = 'Germany';
        String[] result = ParkLocator.Country(country);
        
        
        // Verify that a fake result is returned
        System.assertEquals(new List<String>{'Hamburg Wadden Sea National Park', 'Hainich National Park', 'Bavarian Forest National Park'}, result); 
    }
}
@isTest
global class ParkServiceMock implements WebServiceMock {
   global void doInvoke(
           Object stub,
           Object request,
           Map<String, Object> response,
           String endpoint,
           String soapAction,
           String requestName,
           String responseNS,
           String responseName,
           String responseType) {
        // start - specify the response you want to send
        parkService.byCountryResponse response_x = new parkService.byCountryResponse();
        response_x.return_x = new List<String>{'Hamburg Wadden Sea National Park', 'Hainich National Park', 'Bavarian Forest National Park'};
        
        //calculatorServices.doAddResponse response_x = new calculatorServices.doAddResponse();
        //response_x.return_x = 3.0;
        // end
        response.put('response_x', response_x); 
   }
}




 
Jeff DouglasJeff Douglas
Try changing line #3 in ParkLocator to: 
ParkService.ParksImplPort park = new ParkService.ParksImplPort();
Sorry... it's case sensitive.  :(

If you had entered ParkService originally it would have generated this code in this manner. Not sure if it didn't overwrite these classes or something.

Jeff Douglas
Trailhead Developer Advocate
This was selected as the best answer
EmilienGuichardEmilienGuichard
Well spotted !

I'm definitely not used to pay attention to the case when writting apex.

Thanks a lot.
James LoghryJames Loghry
Jeff Douglas,

There's been a lot of confusion around importing the WSDL file and getting the naming convention correct.  Could we get an updated WSDL with the correct Schema, so that the name is correct off the bat, and avoid further issues? Or is the intent to have the challenge taker realize the difference, and adjust their Apex accordingly?

If the latter, then I'd suggest strongly hinting at the fact you need to change the name of your Apex class when importing the WSDL.
Jeff DouglasJeff Douglas
Good idea James. I'll make the instruction more prominent. It's currently:

Use WSDL2Apex to generate a class called 'ParkService' in public scope using this WSDL file.

I'll change it to:

Use WSDL2Apex to generate a class called 'ParkService' in public scope using this WSDL file. After you click the 'Parse WSDL' button don't forget to change the name of the Apex Class Name from 'parksServices' to 'ParkService'.

 Thanks James!

Jeff Douglas
Trailhead Developer Advocate
Ajay Ghuge 6Ajay Ghuge 6
Hi Folks ,

I have followed all the steps mentioned above but still getting the error :

Following are my classes : 
 
public without sharing class ParkLocator
{

  public static List<string> country(string strCountryName)
  {
     ParkService.ParksImplPort objParkService = new ParkService.ParksImplPort ();
     //objParkService.ParksImplPort  objInner = new ParksImplPort.ParksImplPort();
     List<string> lstCountry = objParkService.byCountry(strCountryName);
     return lstCountry ;
  }
    
}
 
//Generated by wsdl2apex

public class ParkService {
    public class byCountryResponse {
        public String[] return_x;
        private String[] return_x_type_info = new String[]{'return','http://parks.services/',null,'0','-1','false'};
        private String[] apex_schema_type_info = new String[]{'http://parks.services/','false','false'};
        private String[] field_order_type_info = new String[]{'return_x'};
    }
    public class byCountry {
        public String arg0;
        private String[] arg0_type_info = new String[]{'arg0','http://parks.services/',null,'0','1','false'};
        private String[] apex_schema_type_info = new String[]{'http://parks.services/','false','false'};
        private String[] field_order_type_info = new String[]{'arg0'};
    }
    public class ParksImplPort {
        public String endpoint_x = 'https://th-apex-soap-service.herokuapp.com/service/parks';
        public Map<String,String> inputHttpHeaders_x;
        public Map<String,String> outputHttpHeaders_x;
        public String clientCertName_x;
        public String clientCert_x;
        public String clientCertPasswd_x;
        public Integer timeout_x;
        private String[] ns_map_type_info = new String[]{'http://parks.services/', 'ParkService'};
        public String[] byCountry(String arg0) {
            ParkService.byCountry request_x = new ParkService.byCountry();
            request_x.arg0 = arg0;
            ParkService.byCountryResponse response_x;
            Map<String, ParkService.byCountryResponse> response_map_x = new Map<String, ParkService.byCountryResponse>();
            response_map_x.put('response_x', response_x);
            WebServiceCallout.invoke(
              this,
              request_x,
              response_map_x,
              new String[]{endpoint_x,
              '',
              'http://parks.services/',
              'byCountry',
              'http://parks.services/',
              'byCountryResponse',
              'ParkService.byCountryResponse'}
            );
            response_x = response_map_x.get('response_x');
            return response_x.return_x;
        }
    }
}
Test class is also working correctly and giving expected coverage.

What is going wrong in this ?

Regards,
Ajay
Uvais KomathUvais Komath

I used following code and everything went fine for me :

ParkLocator
 

public class ParkLocator {
    public  static string[] country(String country) {
        ParkService.ParksImplPort prk = new ParkService.ParksImplPort();
        return prk.byCountry(country);
    }
}
 

ParkLocatorTest
 

@isTest
private class ParkLocatorTest {
    @isTest static void testCallout() {              
        // This causes a fake response to be generated
        Test.setMock(WebServiceMock.class, new ParkServiceMock());
        // Call the method that invokes a callout
  
        
        String country = 'India';
    
        
        
        
        System.assertEquals(new List<String>{'Lal Bhag', 'Cubbon Park', 'Pazhassi Dam'},     ParkLocator.country(country)); 
    }
}
 

ParkServiceMock
 

@isTest
global class ParkServiceMock implements WebServiceMock {
   global void doInvoke(
           Object stub,
           Object request,
           Map<String, Object> response,
           String endpoint,
           String soapAction,
           String requestName,
           String responseNS,
           String responseName,
           String responseType) {
        // start - specify the response you want to send
        parkService.byCountryResponse response_x = new parkService.byCountryResponse();
        response_x.return_x = new List<String>{'Lal Bhag', 'Cubbon Park', 'Pazhassi Dam'};
               // end
        response.put('response_x', response_x); 
   }
}
 

ParkService (Default from WSDL2Apex)

 

I queued Run All and checked challenge after a while

Ajay Ghuge 6Ajay Ghuge 6
Thanks Uvais !!

I cleared the challenge. Not sure what is the reason. I had not run the Run All in my previous steps today I run that and it worked.

Regards,
Ajay
 
EmilienGuichardEmilienGuichard
Sometimes, to get the right code coverage calculation, you need to clear all test data and then launch all the tests.
snehsneh
Hi All,

I ve bee trying to check my challenge after writing these 3 classes require to complete it, I am getting below error.

Challenge Not yet complete... here's what's wrong: 
The Apex class 'ParkLocator' does not appear to be calling the SOAP endpoint.
 
public class ParkLocator {
    public static string[] country(string c){
        parkService.ParksImplPort parks = new parkService.ParksImplPort();
        return parks.byCountry(c);
    }

}

This is my ParkLocator class. 
Jeff DouglasJeff Douglas
Sneh,

Look at the best answer (in green) for this thread. It should do the trick.

Jeff Douglas
Trailhead Developer Advocate
snehsneh
Jeff, Thank you for the quick response, It worked. But when I stil check my apex class which was parsed from WSDL it says "parkService" with small "p". Never thought it would be case sensitive.

I really appreciate your help. Thank you.
Jeff DouglasJeff Douglas
Sorry, I'm trying to get the change into the next release.

Jeff Douglas
Trailhead Developer Advocate
Aalokkumar Gupta07834984641251669Aalokkumar Gupta07834984641251669
thank you  @Jeff Douglas !!!! it works for me... 
Puneeth KumarPuneeth Kumar
Hello everyone !

Been working on this challenge. Unknowingly I had named test class as "ParkServiceTest"  instead of  "ParkLocatorTest". Now I created new class with the required name and did necessary changes. After running all test I am still Unable to find "ParkLocatorTest" in my code coverage panel. When I checked in for challenge it prompted
"Challenge Not yet complete... here's what's wrong: No Apex test class named 'ParkLocatorTest' was found."
Even though I can still see that class in Apex classes through setup. Can anyone help me out please. 
 
Jeff DouglasJeff Douglas
Puneeth,

If you want to email me (jdouglas at salesforce) your login credentials I can take a peek for you. Please also send me the URL to the unit of the module you are having problems with.

Jeff Douglas
Trailhead Developer Advocate
Puneeth KumarPuneeth Kumar
Sure J. Douglas I will mail you my credentials. Thanks for your reply and help.
Jeff DouglasJeff Douglas
Puneeth,

Very strange issue! Your class definitely exists but for some reason the Tooling API couldn't find it. Maybe some type of special characters in the name of the class or something? Not sure. Anyway, I deleted your class and recreated it and it works fine now. Go ahead and check the challenge test again.

Jeff Douglas
Trailhead Developer Advocate
Puneeth KumarPuneeth Kumar
J Douglas,

Yeah! I accept that, able to see the same class with old name in my recent item too but now its different though. Anyways done with my challenge. Appriciate your help. Thank you.
 
Eric KintzerEric Kintzer
I get same error The Apex class 'ParkLocator' does not appear to be calling the SOAP endpoint. , no issue on capitalization per above thread
 
public class ParkLocator {    
    public static String[] country(String country) {
        ParkService.ParksImplPort  parkSvc = new  ParkService.ParksImplPort ();
		return parkSvc.byCountry(country);
    }	
}

Class generated by WSDL:
//Generated by wsdl2apex

public class ParkService {
    public class byCountryResponse {
        // snip
    }
    public class byCountry {
        // snip
    }
    public class ParksImplPort {
        // snip
        public String[] byCountry(String arg0) {
          // snip
          return response_x.return_x;
        }
    }
}

Execute anonymous results of ParkLocator.country('Germany'); yields below so I know it calls the webservice:
 
12:01:07:298 CALLOUT_RESPONSE [31]|
 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
  <ns2:byCountryResponse xmlns:ns2="http://parks.services/">
   <return>Hamburg Wadden Sea National Park</return>
   <return>Hainich National Park</return>
   <return>Bavarian Forest National Park</return>
  </ns2:byCountryResponse>
  </soap:Body>
  </soap:Envelope>

Mystified
 
Jeff DouglasJeff Douglas
Eric,

Stupid thing but change line #3 in ParkLocator to the following:
 
ParkService.ParksImplPort  parkSvc = new  ParkService.ParksImplPort(); // remove space

I've change this test but it won't go into effect till our next release. Sorry for the inconvenience!

Jeff Douglas
Trailhead Developer Advocate

 
Eric KintzerEric Kintzer
Jeff:

First of all, thank you for looking into this and suggesting a workaround.  However, with the revised class code (space removed), I get the same error: The Apex class 'ParkLocator' does not appear to be calling the SOAP endpoint.​
 
public class ParkLocator {    
    public static String[] country(String country) {
        ParkService.ParksImplPort parkSvc = new ParkService.ParksImplPort();
		return parkSvc.byCountry(country);
    }	
}
Still mystified.
Eric
 
Jeff DouglasJeff Douglas
Eric,

Send me your credentials to jdouglas at salesforce and I'll take a peek.

Jeff Douglas
Trailhead Developer Advocate
Eric KintzerEric Kintzer
Jeff, now that I know I have to second guess your compliance parser, I tried the following and it worked:
 
public class ParkLocator {    
    public static String[] country(String theCountry) {
        ParkService.ParksImplPort parkSvc = new ParkService.ParksImplPort();
		return parkSvc.byCountry(theCountry);
    }	
}

Specifically, the argument to method country() has to have a different value than "country". You can see I changed it to "theCountry" and it passed.

As an aside, a future Apex Trailhead challenge could be to write a parser in Apex looking for compliance in coded Apex :-)
Jeff DouglasJeff Douglas
Excellent! Glad you got it to work. However, I have no idea why your change would have made a difference. That portion is not involved in the assessments. However... great work!! ;)

Jeff Douglas
Trailhead Developer Advocate
William Rogers 10William Rogers 10
Create a class called 'ParkLocator' that has a 'country' method that uses the 'ParkService' class and returns an array of available park names for a particular country passed to the web service.

You could also inlcude in the Test Spec that you need to use ParksImplPort(), that woud go along way for people trying to guess what you
exposed.  
Joe VJoe V
Piggybacking on this thread since it deals with the same Trailhead unit (please let me know if I should post this question as a new thread).
As required by this challenge - I created the ParkLocator.apxc, ParkLocatorTest.apxc, ParkLocatorMock.apxc.
Testing the code shows 100% coverage and I also successfully executed the code below, in the 'Execute Anonymous' Window:
ParkLocator park = new ParkLocator();
String c = 'Germany';
List<String> result = park.country(c);
System.debug(result);
and the logs shows the list of parks fine. However when I click on the 'Check Challenge' button, it throws this error:

Challenge Not yet complete... here's what's wrong:
No Apex class named 'ParkLocator' was found.


ParkLocator:
public class ParkLocator {
    public static String[] country (String countryName) {
        ParkService.ParksImplPort park = 
            new ParkService.ParksImplPort();
        return park.byCountry(countryName);
    }
}
Can someone tell me what I might be missing? I am able to open this file on my 'Developer Console' too, so not sure why the Trailhead challenge does not see this file. I have also tried closing my browser completely and logging back afresh with no avail.

Thanks,
Joe
 
James LoghryJames Loghry
Joe, as others have seen, try removing the spaces between ParkLocator and the curly brace and the country method and curly brace, and change String[] to List<String> to see if that helps.
 
public class ParkLocator{
    public static List<String> country(String countryName){
        ParkService.ParksImplPort park = new ParkService.ParksImplPort();
        return (List<String>)park.byCountry(countryName);
    }
}

 
Joe VJoe V

Thank you James, but that did not help much, still getting the same error.


User-added image
User-added image

Joe VJoe V
When originally creating the ParkLocator, ParkLocatorTest files I had copy-pasted these filenames from the Challenge itself (more so to avoid misspelling the names) and I guess that might have introduced some invisible characters or something? I deleted and re-created the ParkLocator and ParkLocatorTest files and this time, manually typed the filenames in and I was able to complete the challenge.
Lesson learned :).

 
Jeremy Kissoon-CantaveJeremy Kissoon-Cantave
I had alot of trouble trying to find the expected return value of the country Method in ParkLocator Class.

Thanks to Uvais Komath, I found when the method recieved 'India' as a parameter the output was the following list of strings: ['Lal Bhag', 'Cubbon Park', 'Pazhassi Dam']...

Where could i have found this information??

Thanks :)
Rafa GoldaracenaRafa Goldaracena
I had lots of problems with the ' The Apex class 'ParkLocator' does not appear to be calling the SOAP endpoint ', and It was because the 'P' and 'p'. With all 'P', it worked.
Akhil MehraAkhil Mehra
Please Go through this code It work Fine 
1 ParkLocator Class 
public class ParkLocator {
    //public string[] gt{get;set;}
    
   public  static string[] country(String theCountry) {
       ParkService.ParksImplPort park = new ParkService.ParksImplPort();
    // parkService.ParksImplPort park = new parkService.ParksImplPort();
   system.debug(theCountry);
         return park.byCountry(theCountry);
        
    }
 public void did()
 {
    string theCountry='India';
   //  gt=theCountry;
     parkService.ParksImplPort park = new parkService.ParksImplPort();
     park.byCountry(theCountry);
 ParkService.byCountryResponse response_x= new ParkService.byCountryResponse(); 

   
       
 }

2 ParkLocator Class 
@isTest
private class ParkLocatorTest {
    @isTest static void testCallout() {              
        // This causes a fake response to be generated
        Test.setMock(WebServiceMock.class, new ParkServiceMock());
        // Call the method that invokes a callout
  
        
        String country = 'India';
        
        System.assertEquals(new List<String>{'Lal Bhag', 'Cubbon Park', 'Pazhassi Dam'},     ParkLocator.country(country)); 
        ParkLocator bc = new  ParkLocator();
        bc.did();
    }
}

 
MarcFogMarcFog
All, I have been struggling with this on and off for days.  It turns out that Joe V had the solution for me.  Cutting and pasting the class names seems to have introduced some invisible characters, causing the challenge to not recognize the classes.  I saved the code to paste it into new classes I created with the names manually typed.  That was all it took.  Thanks Joe V!
cbrcbr
I faced a different issue while playing around the country method. I tried adding a simple logic that validates the input string argument to the country method for valid countries. Just by adding this extra logic the Trail Challenge failed. Note:- The Unit testing passed with 100% with this extra logic. Then the error shown was totally irrelavent (something like country method is missing in the ParkLocator class and check if its public and static).  Trying to understand what kind of validation the Trail Challenge is doing behind the scenes. Any ideas on checking that logic? 

Failed code:
public static String[] country(String theCountry){
		
               // Validation block:

		Set<String> ValidCountrySet = new Set<String>();
		ValidCountrySet.add('Germany'); //, 'India', 'Japan', 'United States');
		ValidCountrySet.add('India');
		ValidCountrySet.add('Japan');
		ValidCountrySet.add('United States');
		
		Integer matched = 0;
		for (String validCountry: ValidCountrySet){
			System.debug(theCountry);
			System.debug(validCountry);
			if(theCountry.compareTo(validCountry) ==0){
				matched = 1;
				break;
			}
		}
			
		System.assert(matched>0);	
		
		ParkService.ParksImplPort pserv = new	ParkService.ParksImplPort();
		return pserv.byCountry(theCountry);
}


Passed code:
public static String[] country(String theCountry){
		
                // Comment out the validation block
               /*

		Set<String> ValidCountrySet = new Set<String>();
		ValidCountrySet.add('Germany'); //, 'India', 'Japan', 'United States');
		ValidCountrySet.add('India');
		ValidCountrySet.add('Japan');
		ValidCountrySet.add('United States');
		
		Integer matched = 0;
		for (String validCountry: ValidCountrySet){
			System.debug(theCountry);
			System.debug(validCountry);
			if(theCountry.compareTo(validCountry) ==0){
				matched = 1;
				break;
			}
		}
			
		System.assert(matched>0);	
		
               */

		ParkService.ParksImplPort pserv = new	ParkService.ParksImplPort();
		return pserv.byCountry(theCountry);
}


 
Khera, SumeetKhera, Sumeet
To Jeremy's question 

I had alot of trouble trying to find the expected return value of the country Method in ParkLocator Class.

Thanks to Uvais Komath, I found when the method recieved 'India' as a parameter the output was the following list of strings: ['Lal Bhag', 'Cubbon Park', 'Pazhassi Dam']...

Where could i have found this information??





You can probably do something like this to the above code and check the results while running it via "Open Execute Anonoymous Window" and set the mock responses accordingly.

So here is what you gonna run in the execute window  ParkLocator.country('India'); 

Check the logs and set the mock responses..

public class ParkLocator {
    public  static string[] country(String country) {
        ParkService.ParksImplPort prk = new ParkService.ParksImplPort();
        String[] result = prk.byCountry(country);
        system.debug(result);
        return prk.byCountry(country);     
    }

}

thanks hope this helps and answer your query.
thienthangthienthang
I got an error as following. 
There was an unexpected error in your org which is preventing this assessment check from completing: System.CalloutException: Web service callout failed: Unexpected element. Parser was expecting element 'http://schemas.xmlsoap.org/soap/envelope/:Envelope' but found ':html'
looking around I got this:
User-added image
Would you please tell me how to fix this issue? Thank you.
 
Guy_KeshetGuy_Keshet
I am getting the same error - either when running my class from 'execute anonymouse' or when validating my exercise
Johan Chr SaaremJohan Chr Saarem
I think there is an error in the example wsdl file. When you open the link, the soap adress location gives the wrong url. it says https://simple-salesforce-soap-server.herokuapp.com/service/parks, but really should be https://th-apex-soap-service.herokuapp.com/service/parks. I changed the endpoint in the apex class and everything worked. 
thienthangthienthang
Thank you very much Johan Chr Saarem! I's worked like a charm.
Guy_KeshetGuy_Keshet
Thanks Johan, that solved my problem as well. Initially I changed the remote site defintions to simple-salesforce settings ... Jeff- any idea how can we ask SFDC to fix the wsdl file?
Gerard Braat 3Gerard Braat 3
I think we (SF) need to do two things:
  • make clear what is case sensitive and what not
  • update the WSDL file to contain the correct end-point as Johan pointed out correctly
Let me check with Jeff Douglas internally.

Best Regards
Gerard Braat, Program Architect
Ch. Szandor KnappCh. Szandor Knapp
Thx for addressing this stuff as quickly. Just stumbled over exactly the same issues
Alain CabonAlain Cabon
Thank you very much Johan Chr Saarem!
Jeff DouglasJeff Douglas
Sorry everyone! It looks like a commit overwrote some code. I'm rolled back to the correct version from a year ago. Can you try now?

Jeff Douglas
Trailhead Developer Advocate
Don AndersonDon Anderson
I got different results for parks in India:  Anamudi Shola National Park, Anshi National Park, Bandipur National Park.  To verify parks for a particular country, run code similar to this in an Execute Anonyous window and check the debug log for the results.
ParkService.ParksImplPort prk = new ParkService.ParksImplPort();
        String[] result = prk.byCountry('India');
        system.debug(result);
        return prk.byCountry('India');

 
Gbolahan JolapamoGbolahan Jolapamo
Hi All,

I called my parklocator.country(). according to my code below its not returning the same result as compiles but result printed on the debug log as expected.

Can anyone help with this

public class ParkLocator {
    public static List<string> Country(string countryname){
        List<string> result =new List<string>();
        List<string> Availablecountrynames = new List<string>{'India', 'Germany', 'Japan', 'United States'};
            for (string i: availablecountrynames){
                if (i == countryname){
        ParkService.ParksImplPort parknames = new parkService.ParksImplPort();
                  result = parknames.bycountry(countryname);
                system.debug(result);}
                else {break;}
                //{system.debug('select an apropriate country');}
            }
    return result;}
}
Varun SinghVarun Singh
Hi All ,There are some problem in WSDl file
Please Upadte the Code of Parkservice Class then it will work fine
 
public class ParkService {
    public class byCountryResponse {
        public String[] return_x;
        private String[] return_x_type_info = new String[]{'return','http://parks.services/',null,'0','-1','false'};
        private String[] apex_schema_type_info = new String[]{'http://parks.services/','false','false'};
        private String[] field_order_type_info = new String[]{'return_x'};
    }
    public class byCountry {
        public String arg0;
        private String[] arg0_type_info = new String[]{'arg0','http://parks.services/',null,'0','1','false'};
        private String[] apex_schema_type_info = new String[]{'http://parks.services/','false','false'};
        private String[] field_order_type_info = new String[]{'arg0'};
    }
    public class ParksImplPort {
        public String endpoint_x = 'https://th-apex-soap-service.herokuapp.com/service/parks';
        public Map<String,String> inputHttpHeaders_x;
        public Map<String,String> outputHttpHeaders_x;
        public String clientCertName_x;
        public String clientCert_x;
        public String clientCertPasswd_x;
        public Integer timeout_x;
        private String[] ns_map_type_info = new String[]{'http://parks.services/', 'ParkService'};
        public String[] byCountry(String arg0) {
            ParkService.byCountry request_x = new ParkService.byCountry();
            request_x.arg0 = arg0;
            ParkService.byCountryResponse response_x;
            Map<String, ParkService.byCountryResponse> response_map_x = new Map<String, ParkService.byCountryResponse>();
            response_map_x.put('response_x', response_x);
            WebServiceCallout.invoke(
              this,
              request_x,
              response_map_x,
              new String[]{endpoint_x,
              '',
              'http://parks.services/',
              'byCountry',
              'http://parks.services/',
              'byCountryResponse',
              'ParkService.byCountryResponse'}
            );
            response_x = response_map_x.get('response_x');
            return response_x.return_x;
        }
    }
}

ParkLoacater Class
 
public class ParkLocator {
    public static List < String > country(String Country) {
        ParkService.ParksImplPort obj = 
            new ParkService.ParksImplPort();
        return obj.byCountry(Country);
    }
}

Mock for test class
 
@isTest
global class ParkServiceMock implements WebServiceMock {
   global void doInvoke(
           Object stub,
           Object request,
           Map<String, Object> response,
           String endpoint,
           String soapAction,
           String requestName,
           String responseNS,
           String responseName,
           String responseType) {
        ParkService.byCountryResponse response_x = 
            new ParkService.byCountryResponse();
        response_x.return_x = new List < String > {'a', 'b'};
        response.put('response_x', response_x); 
   }
}

Test Class
@isTest
private class ParkLocatorTest {
    @isTest static void testCallout() {              
        Test.setMock(WebServiceMock.class, new ParkServiceMock());
        List < String > result = ParkLocator.country('Test');
    }
}

Code coverage
set the remote site setting
Remote site setting
check Setup->Security->Remote site settings. endpoint = https://th-apex-soap-service.herokuapp.com/service/parks


Cheers Enjoy !​

Don't Forget to choose the best annser ;)
shailendra singhaishailendra singhai
Awsome varun, it work.
Varun SinghVarun Singh
Welcome  shailendra singhai
Kaushik Muhuri 9Kaushik Muhuri 9
I got this message during completing the trailhead Apex SOAP callout
"Challenge Not yet complete... here's what's wrong: 
This challenge has already been completed"
Can somebody tell me its meaning please
Varun SinghVarun Singh
HI @ Kaushik Muhuri 9
Have  you tried  my  solution.

It is  working  fine.....
Tomasz JurekTomasz Jurek
Hi this is so frustrating I have 100% code coverage for ParkLocator and it doesn't work. HELP!!!!!!!!!!!!!
@isTest
global class ParkServiceMock implements WebServiceMock {
    global void doInvoke(
        Object stub,
        Object request,
        Map<String, Object> response,
        String endpoint,
        String soapAction,
        String requestName,
        String responseNS,
        String responseName,
        String responseType) {
            
            ParkService.byCountryResponse odp = new ParkService.byCountryResponse ();
            odp.return_x = new String[]{'Shiretoko National Park', 'Oze National Park', 'Hakusan National Park'};
            // Create response element from the autogenerated class.
            // Populate response element.
            // Add response element to the response parameter, as follows:
            response.put('response_x', odp); 
        }
}
 
public class ParkLocator {
    public static String[] country(String kraje){
        //ParkService.byCountry parking = new ParkService.byCountry();
        ParkService.parksImplPort parking = new ParkService.parksImplPort();
        return parking.byCountry(kraje);
            }
}
 
@isTest
private class ParkLocatorTest {
    @isTest static void testParking() {              
        // This causes a fake response to be generated
        Test.setMock(WebServiceMock.class, new ParkServiceMock());
        
        // Call the method that invokes a callout
        String[] parkingKraj = ParkLocator.country('Japan');
        
        // Verify that a fake result is returned
        System.assertEquals(new String[]{'Shiretoko National Park', 'Oze National Park', 'Hakusan National Park'}, parkingKraj); 
    }
}
User-added image
User-added image

 
Tomasz JurekTomasz Jurek
Okay apologies everyone I was convinced I had line
ParkService.ParksImplPort park = new ParkService.ParksImplPort();
already with capital P - but obviously I didn't. Sorry for trouble!
Jyotie NavaleJyotie Navale

I am getting same error

"The Apex class 'ParkLocator' does not appear to be calling the SOAP endpoint."

And I tried all the solutions provided here, rerun the test, but still getting same error.

 

Here are my mock  n Test classes

public class ParkLocator {
    public static String[] country(String c) {
        parkService.ParksImplPort parkContry = new parkService.ParksImplPort();
        String[] contryName = parkContry.byCountry(c);
        return contryName;
    }
}
 
@isTest
global class ParkServiceMock implements WebServiceMock {
   global void doInvoke(
           Object stub,
           Object request,
           Map<String, Object> response,
           String endpoint,
           String soapAction,
           String requestName,
           String responseNS,
           String responseName,
           String responseType) {
        // start - specify the response you want to send
		 parkService.byCountryResponse response_x = new parkService.byCountryResponse();
       
	   // Germany, India, Japan and United States
               List<String> x = new List<String>{'Germany', 'India', 'Japan', 'United States'};
        response_x.return_x = x;
		
        // end
        response.put('response_x', response_x); 
   }
}
 
@isTest
private class ParkLocatorTest {
    @isTest static void testCallout() {              
        // This causes a fake response to be generated
        Test.setMock(WebServiceMock.class, new ParkServiceMock());
        // Call the method that invokes a callout
        List<String> x = new List<String>{'Germany', 'India', 'Japan', 'United States'};
        List<String> result = ParkLocator.country(x[1]);
        // Verify that a fake result is returned
        System.assertEquals(x, result); 
    }
}


What is wrong?

I have set remote site url as

User-added image