Ces instructions sont utilisees pour signaler activement une situation d’exception (Exception) dans le deroulement du programme. Vous faites cela typiquement quand :
- Une erreur survient que l’unite de programme actuelle (methode, module fonction, routine Form) ne peut pas resoudre elle-meme.
- Un etat inattendu ou invalide est atteint.
- Une regle metier specifique est violee.
Lever une exception interrompt le flux normal du programme a cet endroit et passe le controle a un bloc de gestion des erreurs special (bloc CATCH pour les exceptions basees sur classes) ou a l’appelant (qui verifie alors sy-subrc pour les exceptions non-basees sur classes). Cela permet une gestion structuree des erreurs.
Il existe deux types principaux d’exceptions et donc deux variantes de RAISE :
1. Exceptions basees sur classes (Moderne, Recommande !)
C’est la methode standard dans l’ABAP moderne oriente objet. Les exceptions sont ici des objets de classes d’exception speciales (qui heritent de CX_ROOT).
Syntaxe
" 1. Lever une nouvelle exception d'une classe :RAISE EXCEPTION TYPE <ClasseException> [EXPORTING p1 = v1 p2 = v2 ...] " Passer des parametres au constructeur [MESSAGE { <msg> " Message depuis objet/interface | ID <id> TYPE <t> NUMBER <n> [WITH v1 v2 v3 v4] " Message depuis T100 | oref->if_t100_message } ] " Message depuis autre objet [USING MESSAGE]. " Utiliser le message depuis TEXTID
" 2. Relever un objet exception existant (ex. dans CATCH) :RAISE EXCEPTION <objet_exception>.Fonctionnement
- Un objet de la
<ClasseException>specifiee est cree. Des valeurs peuvent etre passees au constructeur de la classe viaEXPORTINGpour donner des details sur l’erreur (ex. la valeur erronee, un ID). - Optionnellement, un message de la gestion des messages (
SE91) ou d’un autre objet peut etre associe a l’exception via l’ajoutMESSAGE(de nombreuses classes d’exception implementent l’interfaceIF_T100_MESSAGEpour cela). - Le flux normal du programme est arrete.
- Le systeme recherche vers le haut dans la pile d’appels un bloc
TRY...CATCHqui peut gerer cette classe d’exception (ou l’une de ses superclasses). - Si un bloc
CATCHest trouve, son code est execute. - Si aucun bloc
CATCHcorrespondant n’est trouve, cela conduit a une erreur d’execution (dump court).
Classes d’exception : Sont creees dans SE24 et heritent typiquement de
CX_STATIC_CHECK: Erreurs qui pourraient potentiellement etre detectees des le developpement par la verification de syntaxe (mais pas necessairement). Doivent normalement etre gerees.CX_DYNAMIC_CHECK: Erreurs qui ne surviennent qu’a l’execution, mais que le programme devrait anticiper et gerer.CX_NO_CHECK: Erreurs graves et inattendues pour lesquelles une gestion n’est pas necessairement prevue (conduit souvent au dump si non explicitement interceptee).- Gestion des erreurs : L’appelant intercepte ces exceptions avec
TRY. ... CATCH cx_... INTO DATA(lo_exc). ... ENDTRY.
2. Exceptions non-basees sur classes (Obsolete)
C’est l’ancienne methode, utilisee principalement dans les modules fonction et les anciennes methodes.
Contexte : N’a de sens que dans les procedures (modules fonction, methodes, FORMs) qui declarent de telles exceptions dans l’ajout EXCEPTIONS de leur interface.
Syntaxe
RAISE <nom_exception>.Fonctionnement
- L’execution de la procedure est immediatement terminee.
- Le systeme definit le champ systeme
sy-subrca une valeur associee a ce<nom_exception>dans l’ajoutEXCEPTIONSde l’appelant (CALL FUNCTION ... EXCEPTIONS <nom_exception> = valeur ...). - L’appelant doit verifier
sy-subrcapres l’appel pour determiner si cette exception s’est produite.
- Statut : Considere comme obsolete pour les nouveaux developpements, en particulier dans le contexte oriente objet. Ne devrait etre utilise que lorsque d’anciens modules fonction l’exigent.
Exemples
1 : Lever et intercepter une exception basee sur classe
" Classe d'exception personnalisee (simplifiee)CLASS zcx_division_by_zero DEFINITION INHERITING FROM cx_static_check.ENDCLASS.CLASS zcx_division_by_zero IMPLEMENTATION.ENDCLASS.
START-OF-SELECTION. DATA dividend TYPE i VALUE 10. DATA divisor TYPE i VALUE 0. DATA result TYPE f. DATA lo_error TYPE REF TO zcx_division_by_zero.
TRY. IF divisor = 0. " Lever notre propre exception RAISE EXCEPTION TYPE zcx_division_by_zero. ELSE. result = dividend / divisor. WRITE: / 'Resultat:', result. ENDIF.
CATCH zcx_division_by_zero INTO lo_error. MESSAGE 'Erreur : Division par zero !' TYPE 'E'. " Optionnel : Acceder aux attributs/methodes de lo_error ENDTRY.
WRITE / 'Le programme continue apres le bloc TRY.'.2 : Exception basee sur classe avec message
" Hypothese : Message 010 dans classe ZMSG : 'Le materiel &1 n''est pas actif."" Hypothese : ZCX_MATERIAL_INACTIVE implemente IF_T100_MESSAGEDATA lv_matnr TYPE matnr VALUE 'M-INACTIVE'.DATA lo_mat_error TYPE REF TO zcx_material_inactive.
TRY. " ... La verification montre que le materiel est inactif ... RAISE EXCEPTION TYPE zcx_material_inactive MESSAGE ID 'ZMSG' TYPE 'E' NUMBER '010' WITH lv_matnr.
CATCH zcx_material_inactive INTO lo_mat_error. MESSAGE lo_mat_error->get_text( ) TYPE 'E'. " Recuperer le message de l'exception ENDTRY.3 : Exception non-basee sur classe (concept dans module fonction)
FUNCTION Z_DO_SOMETHING.*"----------------------------------------------------------------------*"*"Interface locale :*" IMPORTING*" VALUE(INPUT) TYPE I*" EXPORTING*" VALUE(OUTPUT) TYPE I*" EXCEPTIONS*" INPUT_IS_ZERO " Exception declaree*"---------------------------------------------------------------------- IF input = 0. RAISE input_is_zero. " leve l'exception -> sy-subrc est defini chez l'appelant ELSE. output = 100 / input. ENDIF.ENDFUNCTION.
" Programme appelant :DATA result TYPE i.CALL FUNCTION 'Z_DO_SOMETHING" EXPORTING input = 0 IMPORTING OUTPUT = result EXCEPTIONS input_is_zero = 1 " Mappe l'exception a sy-subrc = 1 OTHERS = 2.
IF sy-subrc = 1. MESSAGE 'L''entree pour Z_DO_SOMETHING etait zero !' TYPE 'W'.ELSEIF sy-subrc = 0. WRITE: / 'Resultat:', result.ENDIF.Remarques importantes / Bonnes pratiques
- Utilisez les exceptions basees sur classes (
RAISE EXCEPTION TYPE ...) pour tous les nouveaux developpements. - Definissez des classes d’exception personnalisees parlantes pour les cas d’erreur specifiques de votre application. Derivez-les de
CX_STATIC_CHECKouCX_DYNAMIC_CHECK. - Implementez l’interface
IF_T100_MESSAGEdans vos classes d’exception pour les associer facilement aux classes de messages (SE91). - Passez les informations de contexte pertinentes via l’ajout
EXPORTINGau constructeur de la classe d’exception. - Interceptez les exceptions de maniere ciblee avec
TRY...CATCH...ENDTRYla ou elles peuvent etre traitees de maniere sensee. Laissez les exceptions non-gerables conduire consciemment a un dump (en particulier celles basees surCX_NO_CHECK). - Evitez
RAISE <nom_exception>dans le nouveau code, sauf pour interagir avec de tres anciens modules fonction.