Tipos de excepción en Apex
No todos los fallos son iguales: no es lo mismo que una cuenta no exista que un guardado rechazado. Cada tipo de excepción dice qué pasó, y cada catch se ocupa del suyo.
✓ En esta sub-lección
- 01Reconocer las excepciones más habituales y qué situación provoca cada una.
- 02Encadenar varios catch, del tipo más concreto al más general.
- 03Explicar por qué LimitException no se puede capturar.
La nutria: ¿Te acuerdas? · Repaso de la lección 1
Quieres que un importe mal escrito no pare el resto de filas. ¿Dónde va el try?
En la tarea 1 el fallo era siempre el mismo: un texto que no era un número. Pero en el puente con el ERP pueden fallar cosas muy distintas, y no todas se tratan igual. Si la cuenta no existe, hay que avisar al ERP de que el código es incorrecto. Si Salesforce rechaza el guardado, hay que decir por qué. El tipo de la excepción es lo que te permite distinguirlas.
Las excepciones que más te vas a encontrar
| Excepción | Cuándo salta | Ejemplo |
|---|---|---|
| DmlException | Un insert, update o delete rechazado: una regla de validación, un campo obligatorio, un propietario inactivo. | insert opp; con un OwnerId de un usuario inactivo |
| QueryException | Asignas a un solo registro una consulta que no devuelve ninguno (o que devuelve más de uno). | Account a = [SELECT … WHERE ERP_Code__c = 'ERP-404']; |
| NullPointerException | Usas algo que es null como si tuviera valor. | acc.Name cuando acc es null |
| TypeException | Una conversión imposible entre tipos. | Decimal.valueOf('12.500,00') |
| ListException | Pides una posición que la lista no tiene. | rows[5] en una lista de 3 |
| SObjectException | Lees un campo que no pediste en la consulta. | a.Industry si el SELECT solo traía Id |
| LimitException | Superas un governor limit. No se puede capturar. | La consulta número 101 |
La nutria: Los códigos de error que ya has visto
Varios catch, del más concreto al más general
Un try puede llevar varios catch seguidos. Cuando salta una excepción, Apex los prueba de arriba abajo y usa el primero cuyo tipo encaja. Todas las excepciones son hijas de Exception, así que un catch (Exception e) encaja con cualquiera: si lo pones, que sea el último, como red de seguridad para lo que no esperabas. Si lo pusieras el primero, se quedaría con todo y los catch concretos no llegarían a usarse nunca.
try {
Account acc = [SELECT Id, OwnerId FROM Account WHERE ERP_Code__c = :erpCode LIMIT 1];
insert new Opportunity(Name = erpCode, AccountId = acc.Id, OwnerId = acc.OwnerId,
StageName = 'Prospecting', CloseDate = Date.today());
} catch (QueryException e) {
System.debug('Código de cuenta desconocido: ' + erpCode); // avisar al ERP
} catch (DmlException e) {
System.debug(e.getDmlType(0) + ': ' + e.getDmlMessage(0)); // el motivo exacto
} catch (Exception e) {
System.debug('Inesperado: ' + e.getTypeName() + ' en la línea ' + e.getLineNumber());
}¿QUÉ EXCEPCIÓN SALTA? ·aciertos 0/0
Account a = [SELECT Id FROM Account WHERE ERP_Code__c = 'ERP-404'];
Paso 1 de 7
Elige la excepción que lanza esta línea.
La nutria: ¿Y por qué no un Flow? Porque el fault path solo recibe un texto