📢✨Boas Práticas e Estrutura de Código para Integração de Callouts no Salesforce✨📢
Neste tutorial, exploraremos as boas práticas e a estrutura de código para integração de callouts no Salesforce.
Ao trabalhar com chamadas de callouts externos no Apex, é importante seguir algumas melhores práticas para garantir um código eficiente e seguro. Aqui estão algumas diretrizes que você pode considerar:
- Use a classe “Http” do Apex: O Salesforce fornece a classe “Http” para fazer chamadas de callouts externos. Ela possui métodos convenientes para enviar solicitações HTTP, como GET, POST, PUT, DELETE, etc. Certifique-se de usá-la em vez de implementar sua própria lógica de chamada HTTP.
- Implemente mecanismos de tratamento de erros: Ao fazer uma chamada de callout externo, sempre trate possíveis erros e exceções. Verifique o status da resposta HTTP para garantir que a solicitação tenha sido concluída com êxito. Lembre-se de lidar com situações de tempo limite, erros de rede ou respostas inválidas.
- Considere limites de chamadas de callouts: O Salesforce possui limites para chamadas de callouts externos, como o limite diário de 100 chamadas por organização e os limites de tempo de execução. Certifique-se de monitorar e respeitar esses limites para evitar interrupções no funcionamento do seu código.
- Faça uso de autenticação adequada: Se a chamada de callout externo exigir autenticação, verifique os requisitos de autenticação e utilize as práticas recomendadas para proteger suas credenciais, como o uso de tokens de acesso ou autenticação OAuth.
- Considere o uso de cache: Se possível, implemente um mecanismo de cache para armazenar respostas de chamadas de callouts externos. Isso pode melhorar o desempenho e reduzir a dependência de chamadas externas, especialmente se os dados retornados forem estáticos ou atualizados com pouca frequência.
- Teste suas chamadas de callouts: Certifique-se de incluir testes adequados para suas chamadas de callouts externos. Isso pode ser feito usando testes de unidade ou criando mocks para simular as respostas externas. Testar esses cenários ajudará a identificar problemas antes de implantar seu código em produção.
Em seguida vou abordar um exemplo básico de chamada de callout externo:
GitHubApiClient
Neste exemplo a seguir, a classe GitHubApiClient
possui um método getUserInfo
que recebe o nome de usuário do GitHub como parâmetro. Ele constrói a URL da API com base no nome de usuário fornecido, configura a solicitação HTTP GET e envia a solicitação usando a classe Http
. Em seguida, retorna a resposta da chamada.
//GitHubApiClient
public class GitHubApiClient {
public static HttpResponse getUserInfo(String username) {
String apiUrl = 'https://api.github.com/users/' + username;
HttpRequest request = new HttpRequest();
request.setEndpoint(apiUrl);
request.setMethod('GET');
HttpResponse response = new Http().send(request);
System.debug('response : ' + response);
return response;
}
}
/*
GitHubApiClient.getUserInfo('salesforce');
Response:
{
"login": "salesforce",
"id": 453694,
"avatar_url": "https://avatars.githubusercontent.com/u/453694?v=4",
"created_at": "2010-10-25T21:15:24Z",
"updated_at": "2023-05-04T18:33:36Z"
}*/
GitHubApiMock
A classe GitHubApiMock
implementa o método respond
da interface HttpCalloutMock
e retorna a resposta simulada que foi passada no construtor.
public class GitHubApiMock implements HttpCalloutMock {
private HttpResponse mockResponse;
public GitHubApiMock(HttpResponse response) {
mockResponse = response;
}
public HttpResponse respond(HttpRequest request) {
return mockResponse;
}
}
GitHubApiClientTest
No próximo exemplo criamos uma classe de teste, contendo um método de teste chamado testGetUserInfo
para verificar se a chamada de callout externo está funcionando corretamente. Primeiro, criamos um objeto de resposta simulado e configuramos um mock de callout usando a classe GitHubApiMock
, que implementa a interface HttpCalloutMock
fornecida pelo Salesforce.
Dentro do método de teste, chamamos o método getUserInfo
da classe GitHubApiClient
, que deveria fazer a chamada de callout externo. Em seguida, verificamos se a resposta recebida é a esperada, comparando o status do código e o corpo da resposta.
@isTest
public class GitHubApiClientTest {
@isTest
static void testGetUserInfo() {
// Mock de resposta da API
HttpResponse mockResponse = new HttpResponse();
mockResponse.setStatusCode(200);
mockResponse.setBody('{"login": "salesforce", "name": "Salesforce", "public_repos": 369}');
// Configurar o mock do callout
Test.setMock(HttpCalloutMock.class, new GitHubApiMock(mockResponse));
// Executar o método a ser testado
HttpResponse actualResponse = GitHubApiClient.getUserInfo('salesforce');
// Verificar se a resposta é a esperada
System.assertEquals(200, actualResponse.getStatusCode());
System.assertEquals('{"login": "salesforce", "name": "Salesforce", "public_repos": 369}', actualResponse.getBody());
}
}
Abordaremos a seguir as classes CalloutIntegration
, JSONPlaceholderPostCalloutClient
, JSONPlaceholderAlbumCalloutClient
e JSONPlaceholderService
. Essas classes serão usadas como exemplo para mostrar como implementar chamadas a APIs externas de forma eficiente e organizada.
Nota Importante:
Antes de prosseguir com o teste dos exemplos fornecidos neste tutorial, certifique-se de adicionar a URL do serviço nas Configurações do Site Remoto do Salesforce. Isso é necessário para permitir que o Salesforce se comunique com o serviço externo. Consulte a documentação do Salesforce para obter mais informações sobre como configurar sites remotos.
CalloutIntegration
A classe CalloutIntegration
é uma classe abstrata que fornece métodos e atributos comuns para realizar callouts HTTP. Esta classe serve como uma base para outras classes de integração de callouts.
public abstract with sharing class CalloutIntegration {
protected final String HEADER_CONTENT_TYPE = 'Content-Type';
protected final String HEADER_CONTENT_TYPE_APPLICATION_JSON = 'application/json';
protected final String HEADER_AUTHORIZATION = 'Authorization';
protected final String HEADER_BEARER_AUTHORIZATION = 'Bearer';
protected final String HTTP_METHOD_GET = 'GET';
protected final String HTTP_METHOD_POST = 'POST';
protected final Integer DEFAULT_TIMEOUT = 120000;
protected HttpRequest request;
protected HttpResponse response;
protected void doCallout() {
Http http = new Http();
this.response = http.send(request);
}
protected Boolean isStatusCodeOk() {
return response.getStatusCode() == 200;
}
protected Integer getResponseStatusCode() {
return response.getStatusCode();
}
protected String getResponseBody() {
return response.getBody();
}
protected HttpRequest createRequest(String method) {
request = new HttpRequest();
request.setMethod(method);
return request;
}
protected abstract Object getResponseObject();
public class CalloutIntegrationException extends Exception {}
}
JSONPlaceholderPostCalloutClient
Esta classe é um exemplo de cliente de callout para a API JSONPlaceholder e fornece um método para realizar chamadas específicas para o endpoint de postagens da API.
public with sharing class JSONPlaceholderPostCalloutClient extends CalloutIntegration {
private static final String BASE_ENDPOINT = 'https://jsonplaceholder.typicode.com';
private static final String ENDPOINT = '/posts';
public JSONPlaceholderPostCalloutClient() {}
public List<PostResponse> getPosts() {
createRequest();
doCallout();
return handleResponse();
}
public override Object getResponseObject() {
try {
return (List<PostResponse>) JSON.deserialize(getResponseBody(), List<PostResponse>.class);
} catch (JSONException ex) {
throw new CalloutIntegrationException('Response deserialization has failed.');
}
}
private void createRequest() {
request = super.createRequest(HTTP_METHOD_GET);
request.setEndpoint(BASE_ENDPOINT + ENDPOINT);
}
private List<PostResponse> handleResponse() {
if (isStatusCodeOk()) {
return (List<PostResponse>) getResponseObject();
} else {
throw new CalloutIntegrationException('Invalid status code: ' + getResponseStatusCode());
}
}
public class PostResponse {
public Integer userId;
public Integer id;
public String title;
public String body;
}
}
JSONPlaceholderAlbumCalloutClient
Esta classe é um exemplo de cliente de callout para a API JSONPlaceholder e fornece um método para realizar chamadas específicas para o endpoint de álbuns da API.
public with sharing class JSONPlaceholderAlbumCalloutClient extends CalloutIntegration {
private static final String BASE_ENDPOINT = 'https://jsonplaceholder.typicode.com';
private static final String ENDPOINT = '/albums';
public JSONPlaceholderAlbumCalloutClient() {}
public List<AlbumResponse> getAlbums() {
createRequest();
doCallout();
return handleResponse();
}
public override Object getResponseObject() {
try {
return (List<AlbumResponse>) JSON.deserialize(getResponseBody(), List<AlbumResponse>.class);
} catch (JSONException ex) {
throw new CalloutIntegrationException('Response deserialization has failed.');
}
}
private void createRequest() {
request = super.createRequest(HTTP_METHOD_GET);
request.setEndpoint(BASE_ENDPOINT + ENDPOINT);
}
private List<AlbumResponse> handleResponse() {
if (isStatusCodeOk()) {
return (List<AlbumResponse>) getResponseObject();
} else {
throw new CalloutIntegrationException('Invalid status code: ' + getResponseStatusCode());
}
}
public class AlbumResponse {
public Integer userId;
public Integer id;
public String title;
}
}
JSONPlaceholderService
A classe JSONPlaceholderService
atua como um serviço intermediário entre os clientes de callouts e os controladores ou outras classes de negócios. Ele encapsula a lógica de chamada de callout e fornece métodos convenientes para acessar os dados da API JSONPlaceholder.
public with sharing class JSONPlaceholderService {
public static List<JSONPlaceholderPostCalloutClient.PostResponse> getPosts() {
JSONPlaceholderPostCalloutClient client = new JSONPlaceholderPostCalloutClient();
return client.getPosts();
}
public static List<JSONPlaceholderAlbumCalloutClient.AlbumResponse> getAlbums() {
JSONPlaceholderAlbumCalloutClient client = new JSONPlaceholderAlbumCalloutClient();
return client.getAlbums();
}
}
Neste tutorial, exploramos as classes GitHubApiClient
, GitHubApiMock
e GitHubApiClientTest
depois em seguida abordamos as boas práticas e a estrutura de código para integração de callouts no Salesforce. As classes CalloutIntegration
, JSONPlaceholderPostCalloutClient
, JSONPlaceholderAlbumCalloutClient
e JSONPlaceholderService
fornecem uma base sólida para a implementação de chamadas a APIs externas de forma eficiente e organizada.
Ao seguir essas práticas, você estará construindo integrações robustas e escaláveis no Salesforce. Lembre-se de adicionar a URL do serviço nas Configurações do Site Remoto do Salesforce antes de testar os exemplos fornecidos.
Esperamos que este tutorial tenha sido útil para você. Aplique esses conceitos em seus projetos de integração e aproveite todos os benefícios de uma integração bem estruturada no Salesforce.