5

I have a system that is posting data to a streaming channel which works upon data changing and a trigger firing.

The a code snippet is shown below.

        string sessionId = UserInfo.getSessionId();    
        HttpRequest req = new HttpRequest();
        HttpResponse res = new HttpResponse();
        Http http = new Http();

        req.setEndpoint(uri);
        req.setMethod('POST');
        req.setHeader('Authorization', 'Bearer '+sessionId);


        string body = '{"pushEvents":[{"payload":"'+payload.escapeJava()+'", "userIds":[]}]}';


        req.setHeader('Content-Type', 'application/json');
        req.setBody(body);

        req.setCompressed(true); // otherwise we hit a limit of 32000

        try {
            res = http.send(req);                
        } catch(System.CalloutException e) {
            System.debug('Callout error: '+ e);
            System.debug(res.toString());

        } catch(System.Exception ex){
          System.debug(res.getStatusCode());
          System.debug(res.toString());
        }

I now need to call this code via scheduled apex and so now the sessionid is coming in null as its asynchronous.

What I can do is use OAuth to get an access token and use this for authentication. There is quite a lot of setup to this and storing usernames/passwords/securitytokens (and managing them) is something that doesn't appeal!

I have come across the Named Credentials functionality and wonder if this is something I can leverage? Anybody tried this?

I have tried

HttpRequest req = new HttpRequest();
req.setEndpoint('callout:Salesforce');
req.setMethod('POST');

Http http = new Http();
HTTPResponse res = http.send(req);


System.debug(res.getBody());

where Salesforce is the Named Credential with the following details:-

The result from Developer Console is

12:05:11.560 (560650534)|CALLOUT_RESPONSE|[6]|System.HttpResponse[Status=Bad Request, StatusCode=400]
12:05:11.560 (560668002)|HEAP_ALLOCATE|[6]|Bytes:96
12:05:11.560 (560819528)|VARIABLE_ASSIGNMENT|[6]|res|"System.HttpResponse[Status=Bad Request, StatusCode=400]"|0x319e2ef7
12:05:11.561 (561088589)|USER_DEBUG|[9]|DEBUG|{"error":"unsupported_grant_type","error_description":"grant type not supported"}

Any help appreciated.

5
  • whenever you call that class using scheduler, pass the current user session id in that class constructor and use that session id for callout
    – Ratan Paul
    Jan 27, 2016 at 12:10
  • @Ratan I am calling this from batch apex and so the session isn't guaranteed to be available. Sessions time out and expire due to user logout so I'm looking for a 'proper solution' here Jan 27, 2016 at 12:12
  • Try checking this question. Its in C#, not apex, but when I was having a similar error in apex, the question was helpful to determining the cause. Jan 27, 2016 at 19:19
  • Hi @RichardDurrant. Were you able to figure this out? I am stuck with the same thing.
    – AslamK
    Jul 25, 2016 at 13:14
  • Were you able to figure this out? I am stuck with the same thing.
    – user40703
    Mar 2, 2017 at 20:13

1 Answer 1

6

You can do this, but you'll need to do a bit more work to use it.

  • First, Create a connected app with oAuth, select refresh_token (at a min) for the oAuth scope
  • Second, Create an auth provider of the salesforce type. Give it the oauth consumer key and consumer secret that you got when you created the connected app.
  • Finally, create a Named Credential using oauth, and your auth provider. When you save the named credential, it will prompt you to log in to a SF org.

Once you've logged in there, the refresh token is saved and used by the named credential. From there, you can make callouts to access data. Note whatever user you login as there is the user your api calls will run as.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .