Información general sobre desencadenadores de Apex
Objetivos de aprendizaje
Después de completar esta unidad, podrá:
- Escribir un desencadenador para un objeto de Salesforce.
- Utilizar variables de contexto de desencadenadores.
- Llamar a un método de clase desde un desencadenador.
- Usar el método
addError()
de sObject en un desencadenador para restringir las operaciones de guardado.
Antes de comenzar
Los desencadenadores de Apex son útiles, divertidos y estupendos. En este módulo aprenderá a empezar a utilizarlos, pero también haremos referencia a otras funciones de Salesforce para demostrar el poder de los desencadenadores de Apex. Para sacar el máximo partido de este módulo, le recomendamos encarecidamente que eche un vistazo a estos otros primero:
- Inicio rápido: Apex
- Fundamentos y base de datos de Apex
- SOQL para administradores
- Fundamentos de Developer Console
Escritura de desencadenadores de Apex
Los desencadenadores de Apex permiten realizar acciones personalizadas antes o después de eventos para registros en Salesforce, como inserciones, actualizaciones o eliminaciones. Del mismo modo que los sistemas de bases de datos admiten desencadenadores, Apex permite el uso de desencadenadores para la gestión de registros.
Normalmente, los desencadenadores se usan para realizar operaciones basadas en condiciones específicas, modificar registros relacionados o impedir determinadas operaciones. Puede usar desencadenadores para realizar cualquier operación admitida en Apex, lo que incluye la ejecución de SOQL y DML o la llamada a métodos Apex personalizados.
Use desencadenadores para realizar tareas que no se pueden realizar con herramientas interactivas (apuntar y hacer clic) en la interfaz de usuario de Salesforce. Por ejemplo, si va a validar un valor de campo o actualizar un campo de un registro, use reglas y flujos de validación. Utilice desencadenadores de Apex si el rendimiento y la escala son importantes, si su lógica es demasiado compleja para herramientas de apuntar y hacer clic o si está ejecutando operaciones que consumen mucho rendimiento de la CPU.
Se pueden definir desencadenadores para objetos estándar de nivel superior, como una cuenta o un contacto, objetos personalizados y determinados objetos secundarios estándar. Los desencadenadores se activan de forma predeterminada al crearlos. Salesforce activa automáticamente desencadenadores cuando se producen eventos de base de datos específicos.
Sintaxis de desencadenadores
La sintaxis de una definición de desencadenador es distinta de la sintaxis de una definición de clase. La definición de un desencadenador empieza por la palabra clave trigger
. A continuación, le siguen el nombre del desencadenador, el objeto de Salesforce con el que está asociado el desencadenador y las condiciones en las que este se activa. Un desencadenador tiene la siguiente sintaxis:
trigger TriggerName on ObjectName (trigger_events) { code_block }
Para ejecutar un desencadenador antes o después de operaciones de inserción, actualización, eliminación y recuperación, especifique varios eventos de desencadenador en una lista separada por comas. Los eventos que se pueden especificar son:
before insert
(antes de insertar)before update
(antes de actualizar)before delete
(antes de eliminar)after insert
(después de insertar)after update
(después de actualizar)after delete
(después de eliminar)after undelete
(después de recuperar)
Ejemplo de desencadenador
Este desencadenador sencillo se activa antes de insertar una cuenta y escribe un mensaje en el registro de depuración.
- En Developer Console, seleccione File (Archivo) | New (Nuevo) | Apex Trigger (Desencadenador de Apex).
- Escriba
HelloWorldTrigger
como nombre del desencadenador y, a continuación, seleccione la cuenta para sObject. Haga clic en Submit (Enviar). - Sustituya el código predeterminado por lo siguiente:
trigger HelloWorldTrigger on Account (before insert) { System.debug('Hello World!'); }
- Para guardar, pulse Ctrl+S.
- Para probar el desencadenador, cree una cuenta.
- Haga clic en Debug (Depurar) | Open Execute Anonymous Window (Abrir ventana de ejecución anónima).
- En la ventana nueva, agregue lo siguiente y, a continuación, haga clic en Execute (Ejecutar).
Account a = new Account(Name='Test Trigger'); insert a;
- En el registro de depuración, busque la declaración
Hello World!
. En el registro se muestra además que el desencadenador se ha ejecutado.
Tipos de desencadenadores
Hay dos tipos de desencadenadores.
- Los desencadenadores previos se usan para actualizar o validar valores de registro antes de guardarlos en la base de datos.
- Los desencadenadores posteriores se usan para acceder a los valores de campo establecidos por el sistema (por ejemplo, el campo
Id
oLastModifiedDate
de un registro) y aplicar cambios a otros registros. Los registros que activan el desencadenador posterior son de solo lectura.
Uso de variables de contexto
Para acceder a los registros que activan el desencadenador, use variables de contexto. Por ejemplo, Trigger.new
contiene todos los registros insertados en desencadenadores de tipo insert o update. Trigger.old
proporciona la versión anterior de sObjects antes de actualizarlos en desencadenadores update o una lista de sObjects eliminados en desencadenadores delete. Los desencadenadores se pueden activar cuando se inserta un registro o cuando se insertan numerosos registros de forma masiva mediante la API o Apex. Por consiguiente, las variables de contexto, como Trigger.new
, pueden contener solo un registro o varios registros. Puede iterar en Trigger.new
para obtener cada sObject individual.
Este ejemplo es una versión modificada del desencadenador de ejemplo HelloWorldTrigger
. Itera en cada cuenta mediante un bucle for y actualiza el campo Description
(Description) en cada caso.
trigger HelloWorldTrigger on Account (before insert) { for(Account a : Trigger.new) { a.Description = 'New description'; } }
Algunas otras variables de contexto devuelven un valor booleano para indicar si el desencadenador se ha activado debido a una actualización o a algún otro evento. Estas variables son de utilidad cuando un desencadenador combina varios eventos. Por ejemplo:
trigger ContextExampleTrigger on Account (before insert, after insert, after delete) { if (Trigger.isInsert) { if (Trigger.isBefore) { // Process before insert } else if (Trigger.isAfter) { // Process after insert } } else if (Trigger.isDelete) { // Process after delete } }
La tabla siguiente es una lista de todas las variables de contexto para desencadenadores.
Variable | Uso |
---|---|
isExecuting | Devuelve true si el contexto actual para el código Apex es un desencadenador, pero no una página de Visualforce, un servicio web o una llamada a API |
isInsert | Devuelve |
isUpdate | Devuelve |
isDelete | Devuelve |
isBefore | Devuelve |
isAfter | Devuelve |
isUndelete | Devuelve |
new | Devuelve una lista de versiones nuevas de registros de sObject. Esta lista de sObject solamente está disponible en desencadenadores |
newMap | Asignación de Id. a las versiones nuevas de los registros de sObject. Esta asignación solo está disponible en los desencadenadores |
old | Devuelve una lista de versiones anteriores de registros de sObject. Esta lista de sObjects solo está disponible en los desencadenadores |
oldMap | Asignación de Id. a las versiones anteriores de los registros de sObject. Esta asignación solo está disponible en los desencadenadores |
operationType | Devuelve una enumeración de tipo System.TriggerOperation correspondiente a la operación actual. Los posibles valores de la enumeración |
size | Número total de registros en una invocación de desencadenadores (tanto anteriores como nuevos). |
Llamada a un método de clase desde un desencadenador
Puede llamar a métodos de utilidad públicos desde un desencadenador. La llamada a métodos de otras clases permite la reutilización de código, reduce el tamaño de los desencadenadores y mejora el mantenimiento del código Apex. Además, permite el uso de programación orientada a los objetos.
En el siguiente ejemplo de desencadenador se muestra cómo llamar a un método estático desde un desencadenador. Si el desencadenador se ha activado debido a un evento de inserción, en el ejemplo se llama al método estático sendMail()
de la clase EmailManager
. Este método de utilidad envía un correo electrónico al destinatario especificado y contiene el número de registros de contacto insertados.
- En Developer Console, haga clic en File (Archivo) | New (Nuevo) | Apex Class (Clase de Apex).
- Introduzca
EmailManager
y, a continuación, haga clic en OK (Aceptar). - Sustituya el cuerpo de clase predeterminado por el ejemplo de clase
EmailManager
.public class EmailManager { // Public method public static void sendMail(String address, String subject, String body) { // Create an email message object Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); String[] toAddresses = new String[] {address}; mail.setToAddresses(toAddresses); mail.setSubject(subject); mail.setPlainTextBody(body); // Pass this email message to the built-in sendEmail method // of the Messaging class Messaging.SendEmailResult[] results = Messaging.sendEmail( new Messaging.SingleEmailMessage[] { mail }); // Call a helper method to inspect the returned results inspectResults(results); } // Helper method private static Boolean inspectResults(Messaging.SendEmailResult[] results) { Boolean sendResult = true; // sendEmail returns an array of result objects. // Iterate through the list to inspect results. // In this class, the methods send only one email, // so we should have only one result. for (Messaging.SendEmailResult res : results) { if (res.isSuccess()) { System.debug('Email sent successfully'); } else { sendResult = false; System.debug('The following errors occurred: ' + res.getErrors()); } } return sendResult; } }
- En Developer Console, seleccione File (Archivo) | New (Nuevo) | Apex Trigger (Desencadenador de Apex).
- Escriba
ExampleTrigger
como nombre del desencadenador y, a continuación, seleccione Contact (Contacto) para el sObject. Haga clic en Submit (Enviar). - Sustituya el código predeterminado por lo siguiente y, a continuación, modifique el texto del marcador de posición de correo electrónico en
sendMail()
con su dirección de correo electrónico.trigger ExampleTrigger on Contact (after insert, after delete) { if (Trigger.isInsert) { Integer recordCount = Trigger.new.size(); // Call a utility method from another class EmailManager.sendMail('Your email address', 'Trailhead Trigger Tutorial', recordCount + ' contact(s) were inserted.'); } else if (Trigger.isDelete) { // Process after delete } }
- Para guardar, pulse Ctrl+S.
- Para probar el desencadenador, cree un contacto.
- Haga clic en Debug (Depurar) | Open Execute Anonymous Window (Abrir ventana de ejecución anónima).
- En la ventana nueva, agregue lo siguiente y, a continuación, haga clic en Execute (Ejecutar).
Contact c = new Contact(LastName='Test Contact'); insert c;
- En el registro de depuración, compruebe si el desencadenador se ha activado. Al final del registro, busque el mensaje de depuración escrito mediante el método de utilidad:
DEBUG|Email sent successfully
(DEBUG|El correo electrónico se ha enviado correctamente) - A continuación, compruebe si ha recibido un correo electrónico con el texto de cuerpo
1 contact(s) were inserted
(Se ha insertado 1 contacto).
Con el nuevo desencadenador, recibirá un correo electrónico cada vez que agregue uno o varios contactos.
Adición de registros relacionados
Los desencadenadores se suelen usar para gestionar y acceder a registros relacionados con otros registros en el contexto del desencadenador (registros que activan el desencadenador).
Este desencadenador agrega una oportunidad relacionada para cada cuenta nueva o actualizada si no hay ninguna oportunidad asociada a la cuenta. El desencadenador realiza primero una consulta SOQL para obtener todas las oportunidades secundarias de las cuentas en las que se ha activado el desencadenador. A continuación, el desencadenador itera en la lista de sObjects en Trigger.new
para obtener el sObject de cada cuenta. Si la cuenta no tiene ningún sObject de oportunidad relacionado, el bucle (for) crea uno. Si el desencadenador ha creado oportunidades, la declaración final las inserta.
- Agregue el siguiente desencadenador desde Developer Console (realice los pasos del ejemplo de
HelloWorldTrigger
, pero useAddRelatedRecord
como nombre del desencadenador).trigger AddRelatedRecord on Account(after insert, after update) { List<Opportunity> oppList = new List<Opportunity>(); // Get the related opportunities for the accounts in this trigger Map<Id,Account> acctsWithOpps = new Map<Id,Account>( [SELECT Id,(SELECT Id FROM Opportunities) FROM Account WHERE Id IN :Trigger.new]); // Add an opportunity for each account if it doesn't already have one. // Iterate through each account. for(Account a : Trigger.new) { System.debug('acctsWithOpps.get(a.Id).Opportunities.size()=' + acctsWithOpps.get(a.Id).Opportunities.size()); // Check if the account already has a related opportunity. if (acctsWithOpps.get(a.Id).Opportunities.size() == 0) { // If it doesn't, add a default opportunity oppList.add(new Opportunity(Name=a.Name + ' Opportunity', StageName='Prospecting', CloseDate=System.today().addMonths(1), AccountId=a.Id)); } } if (oppList.size() > 0) { insert oppList; } }
- Para probar el desencadenador, cree una cuenta en la interfaz de usuario de Salesforce y asígnele el nombre
Apples & Oranges
. - En la lista relacionada de oportunidades de la página de la cuenta, busque la oportunidad nueva. El desencadenador ha agregado esta oportunidad automáticamente.
Uso de excepciones de desencadenadores
En ocasiones, es posible que necesite agregar restricciones para determinadas operaciones de base de datos, como impedir que los registros se guarden cuando se cumplen determinadas condiciones. Para evitar que los registros se guarden en un desencadenador, llame al método addError()
del sObject en cuestión. El método addError()
genera un error grave en el desencadenador. El mensaje de error se muestra en la interfaz de usuario y se registra.
El siguiente desencadenador impide la eliminación de una cuenta si esta tiene oportunidades relacionadas. De forma predeterminada, la eliminación de una cuenta provoca la eliminación en cascada de todos sus registros relacionados. Este desencadenador impide la eliminación en cascada de las oportunidades. Pruebe este desencadenador. Si ha ejecutado el ejemplo anterior, su organización tiene una cuenta llamada Apples & Oranges
con una oportunidad relacionada. En este ejemplo se usa dicha cuenta.
- Use Developer Console para agregar el siguiente desencadenador.
trigger AccountDeletion on Account (before delete) { // Prevent the deletion of accounts if they have related opportunities. for (Account a : [SELECT Id FROM Account WHERE Id IN (SELECT AccountId FROM Opportunity) AND Id IN :Trigger.old]) { Trigger.oldMap.get(a.Id).addError( 'Cannot delete account with related opportunities.'); } }
- En la interfaz de usuario de Salesforce, navegue hasta la página de la cuenta
Apples & Oranges
y haga clic en Delete (Eliminar). - En la ventana emergente de confirmación, haga clic en OK (Aceptar).
Busque el error de validación con el mensaje de error personalizadoCannot delete account with related opportunities
(No se pueden eliminar cuentas con oportunidades relacionadas).
- Desactive el desencadenador
AccountDeletion
. Si deja este desencadenador activado, no podrá revisar los aspectos complejos.
- En Setup (Configuración), busque
Apex Triggers
(Desencadenadores de Apex). - En la página Apex Triggers (Desencadenadores de Apex), haga clic en Edit (Modificar) junto al desencadenador
AccountDeletion
. - Anule la selección de Is Active (Está activo).
- Haga clic en Save (Guardar).
Desencadenadores y llamadas
Apex permite hacer llamadas e integrar el código Apex con servicios web externos. Estos contactos de Apex con servicios web externos se denominan llamadas. Por ejemplo, puede hacer una llamada a un servicio de cotización para conocer las últimas cotizaciones. Al hacer una llamada desde un desencadenador, dicha llamada se debe hacer de forma asíncrona para que el proceso del desencadenador no le impida trabajar mientras espera la respuesta del servicio externo. La llamada asíncrona se realiza mediante un proceso en segundo plano y la respuesta se recibe cuando el servicio externo la devuelve.
Para hacer una llamada desde un desencadenador, llame a un método de clase que se ejecute de forma asíncrona. Este método se llama método futuro y se anota con @future(callout=true)
. Esta clase de ejemplo contiene el método futuro que hace la llamada.
public class CalloutClass { @future(callout=true) public static void makeCallout() { HttpRequest request = new HttpRequest(); // Set the endpoint URL. String endpoint = 'http://yourHost/yourService'; request.setEndPoint(endpoint); // Set the HTTP verb to GET. request.setMethod('GET'); // Send the HTTP request and get the response. HttpResponse response = new HTTP().send(request); } }
En este ejemplo se muestra el desencadenador que llama al método en la clase para hacer una llamada asíncrona.
trigger CalloutTrigger on Account (before insert, before update) { CalloutClass.makeCallout(); }
Esta sección es solo una descripción general de las llamadas y el objetivo no es proporcionar información detallada. Para obtener más información, consulte Invocación de llamadas utilizando Apex en la Guía del desarrollador de Apex.
Recursos
- Guía del desarrollador de Apex: Triggers
- Guía del desarrollador de Apex: Invocar llamadas usando Apex
- Trailhead: Servicios de integración de Apex