Excepciones personalizadas
IllegalArgumentException dice «argumento no válido», pero no dice «problema de la importación». Crear tu propia excepción te deja separar los errores del negocio de los fallos técnicos, y capturar solo los tuyos.
✓ En esta sub-lección
- 01Declarar una excepción propia que extienda Exception.
- 02Envolver una excepción técnica en una de negocio sin perder la original (getCause).
- 03Capturar solo los errores del negocio y dejar que los fallos inesperados se vean.
La nutria: ¿Te acuerdas? · Repaso de la lección 3
parseAmount lanza una IllegalArgumentException y el bucle que la llama no tiene try. ¿Qué pasa?
Tu bucle de importación tiene ya dos catch, y en la tarea 6 serán más. Pero todos dicen lo mismo: «esta fila no se puede importar». Lo que el bucle necesita no es distinguir TypeException de IllegalArgumentException; necesita distinguir «fila rechazada por el negocio» de «algo se ha roto de verdad». Para eso creas tu propio tipo de excepción.
Una línea basta
Una es una clase que extiende Exception, igual que en el Módulo 5 TaskReminder extendía Notification. Solo hay una regla: su nombre tiene que terminar en Exception. No hace falta escribir nada dentro: al heredar de Exception, ya trae getMessage(), getCause(), getTypeName() y cuatro constructores listos para usar.
public class RenewalImportException extends Exception {}
// Los cuatro constructores que trae de serie:
new RenewalImportException(); // sin mensaje
new RenewalImportException('Cuenta desconocida: ERP-999'); // con mensaje
new RenewalImportException(e); // envolviendo otra excepción
new RenewalImportException('Importe no numérico', e); // mensaje + la originalLa nutria: Un valor de picklist propio en lugar de «Otro»
Envolver sin perder la original
El 'doce mil' sigue lanzando una TypeException dentro de parseAmount, porque la lanza Decimal.valueOf, no tú. Para que al bucle le llegue una RenewalImportException, la capturas justo ahí y lanzas la tuya pasándole la original como segundo argumento. Así el bucle solo ve errores del negocio, y quien depure después puede recuperar el fallo técnico con getCause().
Decimal amount;
try {
amount = Decimal.valueOf(raw);
} catch (TypeException e) {
throw new RenewalImportException('Importe no numérico: ' + raw, e);
}
// Más arriba, en el catch del bucle:
// e.getMessage() → 'Importe no numérico: doce mil'
// e.getCause().getTypeName() → 'System.TypeException'LANZA UN FALLO
Elige un fallo y mira qué catch lo recoge.
La nutria: ¿Y por qué no un Flow? Porque el fault path no tiene categorías