Hot answers tagged

6

Typically, if I want to verify the callout is made and there may be asynchronous processing involve, I just track it on my mock. class MyMock implements HttpCalloutMock { Integer calls = 0; public HttpResponse respond(HttpRequest request) { calls++; // mock implementation here } } Then, in your test, you just cache your mock ...


6

No, that's nor quite right. Imagine callout as animal and Http as cat, it's a subclass, not the actual class. What I mean is you have 2 types of callouts in Apex: Http http = new Http(); http.send(/*...*/); and WebServiceCallout.invoke(/*...*/); Here is the documentation link.


5

If possible, use Named Credentials. You don't need to manage the Access Tokens or Refresh Tokens at all, as the platform does it for you, and securely stores the tokens in a way that's non-trivial to retrieve, even for administrators. Also, feel free to read Secure Coding: Storing Secrets for other alternatives. Custom Metadata Types is also a viable ...


5

This line is not needed when using named credentials as callout endpoints: req.setHeader('Authorization','Bearer {!$D365Credential.access_token}'); From the example HttpRequest req = new HttpRequest(); req.setEndpoint('callout:My_Named_Credential/some_path'); req.setMethod('GET'); Http http = new Http(); HTTPResponse res = http.send(req); System.debug(res....


4

For callouts that need to implement mutual auth in SSL (aka 2-way SSL) with your own, self-signed cert: Drop your cert + private key into a JKS keystore and import it via Certificate and Key Management admin UI. Even though JKS supports a cert-only entry, that won't work here. SF will only import a JKS with one or more entry of type PrivateKeyEntry. The ...


4

You have a trigger looking like you are making an asynchronous (@future) to method getAPIAsyn but in fact, this method is never called. Furthermore, even if the trigger did call this method, it executes asynchronously and the bottom of the trigger that loops through Trigger.new will execute BEFORE the @future method even starts - hence why no value in the ...


4

The main difference between the two techniques is that with future methods, you can't make any future calls, but with Queueable, you're allowed one more Queueable call. Regardless, you can't call more than one Queueable per asynchronous call. If you choose to call an InvocableMethod, you must remember to check if you're in asynchronous code or not: if(!...


4

Enqueuing Asynchronous Apex, including future methods, for execution is a "DML-equivalent" operation. It counts just like DML for purposes of causing an exception in proximity to callouts. You must call your future method after performing the callout. You can then execute DML in the future method, which executes in a separate transaction context.


4

This happens because cacheable=true. When you do this, the platform notices that there's already a cached response and uses that instead of waiting. It will then callback again later, but the promise will have already resolved (and they can't resolve multiple times!). Set cacheable=false to make sure that it waits until the process is finished. Or, if ...


4

A GET request to that URL is returning HTML not just the JSON body. HttpRequest req = new HttpRequest(); req.setHeader('Content-Type','application/json;charset=UTF-8'); req.setEndpoint('https://swapi.dev/api/people/1/'); req.setMethod('GET'); HTTPResponse res = new Http().send(req); system.debug(res.getBody()); Produces this: Update: HttpRequest req = ...


4

This is a classic problem with testing multi-layer Asynchronous Apex. The trick is that Test.startTest() and Test.stopTest() only force synchronous execution of the first layer - in this case, the future method - of asynchronous code. Any asynchronous functionality enqueued by that layer will ultimately execute, and may in fact be visible in your debug ...


4

The Lightning Session ID doesn't include REST API privileges, except for a few UI-API calls. You should be able to use the ConnectApi classes to get the information you want for Chatter, or you can use a Named Credential to allow Apex access to the API.


4

Yes, you need to use the namespace (see this question, basically, callout:myNameSpace__myCalloutName).


3

That is a possible way to bypass SF limits: 1) Make a callout to your server (do not wait for result). 2) On your server, after all calculations and any other actions make a callout to SF @RestResource with the actual answer. 3) Process answer on SF side. Also sfdcfox is right, you can move logic dealing with duplicates to SF side by creating duplicate ...


3

It should be as simple as using a Queueable with Database.AllowsCallouts instead of using a future method. See the product documentation for details. There are lots of alternatives you could consider in terms of the over-all approach, such as generating platform events with the JSON (as text) in them, but this approach does keep it clean and simple.


3

Future methods only accept Apex primitive values and collections of primitives as parameters. They do not support sObject parameters or complex parameters including sObjects. The easiest way to correct this is to break your code into a synchronous piece and pass only the serialized JSON to your @future method: public static void AfterUpdate(Map<Id, ...


3

You can use SSL mutual authentication, where the endpoint can verify the certificate used, or you could use an IP address white list using the published IP address ranges for Salesforce. Both of threat techniques can be used to verify that a request is authentic.


3

I know this is quite old, but in case someone else is looking for guidance here, I'm doing something similar and it works for me without having to implement a while loop. I think the main issue you had is calling boxToolkit.commitChanges(); in your for loop. I suggest waiting to commit any changes to Box until after your loop, but before your DML ...


3

Interfaces such as Database.AllowsCallouts or Database.Stateful can be considered as Marker Interfaces. They do not bring any overhead to the implementing classes but it's a marker to the runtime virtual machine to treat any implementing classes in a special way. Although not specifically stated in Apex Developer Guide, but you can find a reference of Marker ...


3

Try adding xero-tenant-id header in you apex code. For this you may need to check "Allow merge fields in HTTP Header" or else it wont allow. HttpRequest req = new HttpRequest(); req.setEndpoint('callout:XeroDev/api.xro/2.0/Accounts'); req.setMethod('GET'); /* tenant id is different for different organization */ req.setHeader('xero-tenant-id', 'd5ae8ed7-be06-...


3

For anyone looking at this in the future, this post has solved my issue: StackExchange Post. You need to set your site name as your as the user name and it will show up in debug logs (without setting a cookie).


3

You can go by what Rahul has suggested, its called as Promise chaining. Modern javascript has new concepts that allow you to handle these complex requirements without making you go in promise chaining callback hell. Welcome Async and Await :) await - > The keyword await makes JavaScript wait until that promise settles and returns its result. ...


3

This guard: if(!Test.isRunningTest()){ HttpResponse res = http.send(req); } and the use of Test.setMock(HttpCalloutMock.class, new FindAnApprenticeshipCalloutsMock()); are mutually incompatible. Your Mock class will never be called if you gate the HTTP call in your production code; remove the gate if you plan to use a Mock. ...


3

To say "Salesforce does not have limits for callouts" is completely incorrect. From the very document you linked to: A single Apex transaction can make a maximum of 100 callouts to an HTTP request or an API call. This per-transaction governor can be checked at any time in Apex by calling Limits.getCallouts(). The maximum cumulative timeout ...


3

I don't believe that syntax is supported. Instead, you could use Basic authentication: Http http = new Http(); HttpRequest request = new HttpRequest(); String endpoint = 'https://mycURL'; request.setEndpoint(endpoint); request.setMethod('GET'); request.setHeader( 'Authorization', 'Basic '+EncodingUtil.base64Encode(Blob.valueOf('username:password')) ); ...


3

Disclaimer: I work for Salesforce. I'll talk about architecture only. I won't discuss costs. I'll start by putting Platform Events (PE) and Change Data Capture (CDC) in the same Streaming APIs basket as they both rely on the same underlying technology (CometD). Here are two main things to take into consideration when comparing Callouts with the Streaming ...


3

I have faced similar dilemma a few months back, here are the points that made me consider the architecture. 1) Callouts from Trigger: You would basically do it in Future, Queueabale or if you run periodically in batch/scheduler. You will consume AsyncApexLimits then. Am not sure how many do you have in your org, you can't buy them directly, you have to buy ...


3

This isn't valid JSON: { animal: { id: 0, name: "", eats: "", says: "", } } and the error actually says exactly what's wrong: Unexpected character ('a' (code 97)): was expecting double-quote to start field name at [line:1, column:3] JSON keys are required to be quoted strings. You must quote "animal", "id", "name", "eats", and "says"...


3

If you are not building a Managed package solution, there are a couple of ways you can secure the keys. Use custom objects with a Private Sharing model. Keep OWD Private, this way no one will have access to it except System admin and owner of the record. You can further secure it using the encrypted fields (Note this will not need a shield license). Using ...


2

These are nested objects. As such, you have to follow each object in the path. For InternalID: Map<String, Object> dataNode = (Map<String, Object>)arr[0].get('Data'); Map<String, Object> dataHeaderNode = (Map<String, Object>)dataNode.get('DataHeader'); String internalId = (String)dataHeaderNode.get('InternalID'); Each time you ...


Only top voted, non community-wiki answers of a minimum length are eligible