1

I'm trying to call an APEX REST service from another system. The other system is not capable of JSON, it can pass data in XML only for PUT or POST, or in the querystring for GET.

So far, all of my attempts to retrieve the querystring have failed - containsKey() returns false.

Is there a way to make my REST service work using a querystring, and make the test class prove that it does? I'd rather not have to hack my way through the XML using string functions.

Here is a portion of the REST service...

@RestResource(urlMapping='/SubscriptionEventNew')
global with sharing class SubscriptionEventNew {
global class SubscriptionException extends Exception {}
@HttpGet
global static GatewayLog__c NewSubscription() {
    GatewayInfo gwInfo = new GatewayInfo();
    GatewayLog__c gwLogResponse = new GatewayLog__c();
    try 
    {
        if (!ApexPages.currentPage().getParameters().containsKey('SubscriptionID')) {
            System.debug('Hey argument missing');
            throw new SubscriptionException('SubscriptionID must be passed in querystring');
        }

And here is a testmethod that fails to pass the querystring:

@isTest
public with sharing class SubscriptionEventsTest {
public static testmethod void SubscriptionEventNewTestValid() {
    RestRequest req = new RestRequest();
    RestResponse res = new RestResponse();
    req.requestURI = '/SubscriptionEventNew';
    req.addParameter('SubscriptionID','4948C4C7-74EB-4467-BF72-B201A804B800'); 
    req.httpMethod = 'GET';
    RestContext.request = req;
    RestContext.response = res;
    GatewayLog__c log = SubscriptionEventNew.NewSubscription();
//      TestProcess.AnalyzeLog(log);
}
  • You are looking for the URL parms in the wrong place. They won't be in apexPages, see developer.salesforce.com/docs/atlas.en-us.apexcode.meta/… for example – cropredy Aug 4 '15 at 18:23
  • The external system can't send the parameter as a node on the URL, they can only send ?label=value&label=value&... – aging hippie Aug 4 '15 at 18:30
  • I'm confused; these should be available to your GET REST method in the params property of the RestContext.Request object – cropredy Aug 4 '15 at 19:28
  • Update: was able to get the parameters from the test class to the service and get test coverage to 91%. Remains to be seen whether this will work when actually called by the external system with its /service?label=name style request. – aging hippie Aug 4 '15 at 20:42
2

An @HttpGet request, by design (generally) passes its parameters in the URL. They'll be in the form that you've got noted in your question: url?key1=value&key2=value etc.

Your service class is looking for its parameters in the wrong class. A REST request is not an ApexPage and so the parameters won't be in the map of params on the ApexPages class reference. Instead, you'll need to get the parameters from the RestContext class.

Your unit test is fine as written, but your class needs to be modified with the RestContext class.

@RestResource(urlMapping='/SubscriptionEventNew')
global with sharing class SubscriptionEventNew {

    global class SubscriptionException extends Exception {}

    @HttpGet
    global static GatewayLog__c NewSubscription() {
        GatewayInfo gwInfo = new GatewayInfo();
        GatewayLog__c gwLogResponse = new GatewayLog__c();

        // RestContext is swapped in for ApexPages
        Map<String, String> requestParameterMap = RestContext.request.params;

        try 
        {
            if (requestParameterMap.get('SubscriptionID') == null) {
                System.debug('Hey argument missing');
                throw new SubscriptionException('SubscriptionID must be passed in querystring');
            }

@isTest
public with sharing class SubscriptionEventsTest {

    public static testmethod void SubscriptionEventNewTestValid() {

        RestRequest req = new RestRequest();
        RestResponse res = new RestResponse();

        req.requestURI = '/SubscriptionEventNew';
        req.addParameter('SubscriptionID','4948C4C7-74EB-4467-BF72-B201A804B800'); 
        req.httpMethod = 'GET';

        RestContext.request = req;
        RestContext.response = res;

        GatewayLog__c log = SubscriptionEventNew.NewSubscription();
        // TestProcess.AnalyzeLog(log);
    }
}

One thing to note, a Map in Apex can't contain duplicate keys so your parameter names in the request must be unique. i.e. this won't work: url?items=item1&items=item2&items=item3 which in vanilla HTML, might represent multiple items in a collection named items.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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