Skip to main content

Usar métodos futuros

Objetivos de aprendizagem

Após concluir esta unidade, você saberá:

  • Quando usar métodos futuros.
  • As limitações para o uso de métodos futuros.
  • Como usar métodos futuros para callouts.
  • Melhores práticas para método futuro.
Nota

Nota

O desafio prático para esse emblema está traduzido para japonês, espanhol (América Latina) e português (Brasil). Para definir o idioma do seu Trailhead Playground, siga essas instruções. A tradução pode estar desatualizada. Se você não conseguir passar no desafio usando as instruções traduzidas, defina o idioma para inglês e a localidade para Estados Unidos. Em seguida, tente novamente.

Consulte o emblema Trailhead no seu idioma para saber mais sobre como aproveitar a experiência de Trailhead em outros idiomas.

Acompanhar com o Trail Together

Deseja acompanhar um instrutor enquanto trabalha nesta etapa? Veja este vídeo que faz parte da série Trail Together no Trailhead Live.

(Este clipe começa na marca dos 09:39 minutos, caso você queira retroceder e ver o início da etapa novamente.) 

Apex futuro

O Apex futuro é usado para executar processos em um thread separado, mais tarde, quando os recursos do sistema se tornarem disponíveis.

Nota: Tecnicamente, você usa a anotação @future para identificar métodos que são executados de forma assíncrona. Porém, como os “métodos identificados com a anotação @future” são trabalhosos, eles normalmente são citados como “métodos futuros” e é assim que nos referiremos a eles daqui em diante.

Ao usar o processamento sincronizado, todas as chamadas de método são feitas a partir do mesmo thread que está executando o código do Apex e nenhum processamento adicional pode ocorrer até que o processo seja concluído. Você pode usar métodos futuros para qualquer operação que quiser para executar de forma assíncrona em seu próprio thread. Isso oferece os benefícios de não impedir que o usuário realize outras operações e ofereça limites de administrador e de execução maiores para o processo. Todos saem vencedores com o processamento assíncrono.

Métodos futuros normalmente são utilizados para:
  • Fazer callouts para serviços da Web externos. Se você estiver fazendo callouts a partir de um acionador ou após realizar uma operação DML, tem que usar um método futuro ou que permita a execução em fila. Um callout em um acionador manteria a conexão com o banco de dados aberta pela duração do callout e isso é inaceitável em um ambiente multilocatário.
  • Operações que você deseja executar em seu próprio thread, quando o tempo permitir, como um tipo de cálculo ou processamento de registros com consumo intenso de recursos.
  • Isolar operações DML em diferentes tipos de sObject para evitar o erro de DML combinada. Isto é um caso extremo, mas você pode passar por este problema. Consulte sObjects que não podem ser usados juntos em operações DML para obter mais detalhes.

Sintaxe do método futuro

Os métodos futuros têm de ser métodos estáticos e só podem retornar um tipo void. Os parâmetros especificados precisam ser tipos de dados primitivos, matrizes de tipos de dados primitivos ou coleções de tipos de dados primitivos. Em especial, métodos futuros não podem lidar com objetos padrão ou personalizados como argumentos. Um padrão comum é passar ao método uma Lista de IDs de registros que você deseja processar de forma assíncrona.

public class SomeClass {
  @future
  public static void someFutureMethod(List<Id> recordIds) {
    List<Account> accounts = [Select Id, Name from Account Where Id IN :recordIds];
    // process account records to do awesome stuff
  }
}
Nota

O motivo de os objetos não poderem ser passados como argumentos para métodos futuros é que o objeto pode mudar entre o momento em que o método é chamado e o momento em que ele é realmente executado. Lembre-se: métodos futuros são executados quando os recursos do sistema se tornam disponíveis. Neste caso, o método futuro pode ter um valor de objeto antigo quando for realmente executado, o que pode causar todo tipo de problema.

É importante notar que não é garantido que os métodos futuros são executados na mesma sequência em que foram chamados. Vamos repetir porque é crucial que você se lembre: não é garantido que métodos futuros sejam executados na mesma sequência em que foram chamados. Ao usar métodos futuros, também é possível que dois métodos futuros possam ser executados simultaneamente, o que poderia resultar em bloqueio de registro e em um desagradável erro de tempo de execução se os dois métodos estiverem atualizando o mesmo registro.

Amostra de código de callout

Para fazer um callout de um serviço da Web para um serviço ou API, crie uma classe de Apex com um método futuro marcado com (callout=true). A classe abaixo tem métodos para fazer callout de forma síncrona e assíncrona onde callouts não são permitidos. Inserimos um registro em um objeto de registro personalizado para monitorar o status do callout simplesmente porque sempre é divertido fazer o registro! 

Observação

A classe SmsMessage e o sObject SMS_Log__c no exemplo são hipotéticos e mostrados apenas para demonstrar o padrão de callout.

public class SMSUtils {
    // Call async from triggers, etc, where callouts are not permitted.
    @future(callout=true)
    public static void sendSMSAsync(String fromNbr, String toNbr, String m) {
        String results = sendSMS(fromNbr, toNbr, m);
        System.debug(results);
    }
    // Call from controllers, etc, for immediate processing
    public static String sendSMS(String fromNbr, String toNbr, String m) {
        // Calling 'send' will result in a callout
        String results = SmsMessage.send(fromNbr, toNbr, m);
        insert new SMS_Log__c(to__c=toNbr, from__c=fromNbr, msg__c=results);
        return results;
    }
}

Classes de teste

Testar métodos futuros é um pouco diferente do teste de Apex típico. Para testar métodos futuros, inclua seu código de teste entre os métodos de teste startTest() e stopTest(). O sistema coleta todas as chamadas assíncronas feitas após o startTest(). Quando o método stopTest() é executado, todos estes processos assíncronos coletados são executados de forma síncrona. Então é possível afirmar se a chamada assíncrona operou corretamente.

Nota

O código de teste não pode efetivamente enviar callouts para sistemas externos, assim, você terá de “simular” o callout para a cobertura do teste. Confira o módulo Serviços de integração do Apex para obter todos os detalhes sobre callouts simulados para o teste.

Aqui está nossa classe de callout simulado usado para o teste. A estrutura de teste do Apex usa essa resposta “simulada” em vez de fazer o callout real para o ponto de extremidade da API REST.

@isTest
public class SMSCalloutMock implements HttpCalloutMock {
    public HttpResponse respond(HttpRequest req) {
        // Create a fake response
        HttpResponse res = new HttpResponse();
        res.setHeader('Content-Type', 'application/json');
        res.setBody('{"status":"success"}');
        res.setStatusCode(200);
        return res;
    }
}

O teste de classe contém apenas um método de teste (testSendSms() neste exemplo), que testa ambos os métodos assíncrono e síncrono à medida que o primeiro chama este último.

@IsTest
private class Test_SMSUtils {
  @IsTest
  private static void testSendSms() {
    Test.setMock(HttpCalloutMock.class, new SMSCalloutMock());
    Test.startTest();
      SMSUtils.sendSMSAsync('111', '222', 'Greetings!');
    Test.stopTest();
    // runs callout and check results
    List<SMS_Log__c> logs = [select msg__c from SMS_Log__c];
    System.assertEquals(1, logs.size());
    System.assertEquals('success', logs[0].msg__c);
  }
}

Melhores práticas

Como toda invocação de método futuro adiciona uma solicitação à fila assíncrona, evite projetar padrões que adicionem grandes números de solicitações futuras em um curto período de tempo. Se seu projeto tem o potencial de adicionar 2.000 ou mais solicitações de uma vez, as solicitações podem ser atrasadas devido ao controle de fluxo. Aqui estão algumas das melhores práticas que você deve manter em mente:
  • Verifique se os métodos futuros estão sendo executados o mais rápido possível.
  • Se você estiver usando callouts de serviço da Web, tente agrupar todos os callouts do mesmo método futuro, em vez de usar um método futuro separado para cada callout.
  • Realize testes completos na escala. Teste se um acionador que coloca na fila as chamadas @future é capaz de lidar com uma coleção de acionadores de 200 registros. Isto ajuda a determinar se podem ocorrer atrasos devido ao projeto nos volumes atuais e futuros.
  • Considere usar o Apex de lote em vez de métodos futuros para processar um grande número de registros de forma assíncrona. Isto é mais eficiente que criar uma solicitação de futuro para cada registro.

Coisas a serem lembradas

Métodos futuros são uma ótima ferramenta, mas com grandes poderes vêm também grandes responsabilidades. Aqui estão algumas coisas para manter em mente ao usá-los:
  • Métodos com a anotação @future têm de ser métodos estáticos e só podem retornar um tipo void.
  • Os parâmetros especificados têm de ser tipos de dados primitivos, matrizes de tipos de dados primitivos ou coleções de tipos de dados primitivos. Métodos futuros não podem ter objetos como argumentos.
  • Métodos futuros não são executados necessariamente na mesma ordem em que são chamados. Além disso, é possível que dois métodos futuros sejam executados simultaneamente, o que poderia resultar em bloqueio de registro se os dois métodos estivessem atualizando o mesmo registro.
  • Os métodos futuros não podem ser usados com controladores Visualforce em getMethodName(), setMethodName() nem no construtor.
  • Não é possível chamar um método futuro a partir de um método futuro. Também não é possível invocar um acionador que chame um método futuro enquanto executa um método futuro. Veja o link em Recursos para evitar chamadas recursivas de método futuro.
  • Os métodos getContent() e getContentAsPDF() não podem ser usados em métodos com anotação @future.
  • Há uma limitação de 50 chamadas futuras por invocação Apex e um limite adicional no número de chamadas em um período de 24 horas. Para mais informações sobre limites, acesse o link abaixo.
Continue a aprender de graça!
Inscreva-se em uma conta para continuar.
O que você ganha com isso?
  • Receba recomendações personalizadas para suas metas de carreira
  • Pratique suas habilidades com desafios práticos e testes
  • Monitore e compartilhe seu progresso com os empregadores
  • Conecte-se a orientação e oportunidades de carreira