Analyse et test du code
Utilisation correcte des types de données et des conversions de types
Traitement des zones de caractères
Utilisation du Pushdown de code dans ABAP SQL
Amélioration de la performance des tables internes
Implémentation des contrôles des autorisations
Conception d'un code orienté objet efficace
Définition et utilisation des classes d'exception
Ajout de documentation au code ABAP

Utilisation des classes d'exception

Objective

After completing this lesson, you will be able to utilisez des classes d'exception.

Gestion des exceptions

Plus tôt dans ce cours, nous avons examiné la gestion des erreurs à l'aide des instructions TRY, CATCH et ENDTRY. Après l'instruction TRY est fournie l'instruction qui peut entraîner une erreur. Si l'erreur survient, le système passe à l'instruction CATCH et traite son contenu. Quoi qu'il arrive, la méthode poursuit le traitement après l'instruction ENDTRY.

Dans un bloc TRY…ENDTRY, vous pouvez inclure plusieurs instructions CATCH. Cela vous permet de traiter différentes exceptions différemment.

Vous pouvez répertorier plusieurs exceptions dans une seule instruction CATCH. Dans cet exemple, le même bloc CATCH sera traité si le système déclenche cx_sy_arithmetic_error ou cx_sy_zerodivide.

Lorsque vous répertoriez une classe dans une instruction CATCH, le système traite le bloc correspondant si une exception avec cette classe ou l'une de ses sous-classes est déclenchée. Dans cet exemple, cx_sy_arithmetic_error est une surclasse de cx_sy_arithmetic_overflow et cx_sy_zerodivide. En conséquence, le bloc sera traité si une exception de type de l'une des sous-classes est déclenchée.

Toutes les classes d'exception font partie d'une hiérarchie d'héritage dont la surclasse la plus élevée est la classe cx_root. Comme nous l'avons déjà vu, si vous utilisez une surclasse dans une instruction CATCH, le système y accède si une exception avec le type de l'une de ses sous-classes est déclenchée. Comme toutes les classes d'exception sont des sous-classes de cx_root, l'instruction CATCH cx_root est suffisante pour intercepter une exception.

Séquence des instructions CATCH

Lorsque vous écrivez des instructions CATCH, vous devez placer la ou les classes les plus spécifiques en premier et les plus génériques en dernier. Si vous placez une surclasse au-dessus de l'une de ses sous-classes, vous provoquerez une erreur de syntaxe. En effet, le système n'a pas pu traiter le bloc CATCH spécifique car il est éclipsé par le bloc plus générique.

L'ajout INTO

Chaque exception est représentée par un objet. Vous pouvez placer cet objet dans une variable de référence et l'utiliser - par exemple, pour récupérer le texte d'erreur de la classe d'exception à l'aide de la méthode get_text( ) comme illustré dans l'exemple ici.

Vous pouvez utiliser une déclaration en ligne dans l'instruction CATCH pour vous assurer que la variable de référence est déclarée avec le type correct.

La chose la plus courante à faire avec l'objet d'exception est d'appeler sa méthode get_text( ). Cependant, les objets d'exception peuvent posséder d'autres attributs et méthodes pour vous aider à traiter l'erreur.

Les classes d'exception peuvent avoir des attributs qui décrivent plus précisément ce qui s'est mal passé. Ces attributs sont souvent utilisés pour renseigner les caractères génériques des messages. Vous définissez un attribut dans la section publique de la classe d'exception avec son nom et son type appropriés.

Pour renseigner un attribut lorsque l'exception est déclenchée, vous avez besoin d'un paramètre d'import correspondant du constructeur de la classe d'exception. Vous pouvez générer ce paramètre d'importation à l'aide d'un correctif rapide. Positionnez le curseur sur le nom de méthode constructor et appuyez sur Ctrl + 1. Sélectionnez le correctif rapide Régénérer le constructeur.

Propagation des exceptions

Une méthode peut propager une exception tout au long de la chaîne d'appel. Au lieu d'utiliser l'instruction CATCH pour traiter l'exception, la méthode inclut la clause RAISING dans sa définition. Cela indique aux appelants de la méthode que l'exception peut leur être transmise.

Si l'exception n'est interceptée nulle part dans la chaîne d'appel, une erreur d'exécution se produit.

Attribut previous

Parfois, dans une chaîne d'appels, une méthode intercepte une exception et, en réponse, elle déclenche une exception différente pour son propre appelant à intercepter. Cela peut se produire, par exemple, si une structure déclenche une exception trop orientée techniquement pour que l'application puisse être traitée. La méthode qui déclenche sa propre exception peut transmettre la première exception. Pour ce faire, il utilise l'attribut previous de la classe d'exception.

Lorsque vous déclenchez une exception, vous pouvez transférer une instance d'une classe d'exception au paramètre d'importation previous. L'objet d'exception est alors attaché à la nouvelle exception. Une méthode qui intercepte la deuxième exception peut accéder au premier objet d'exception à l'aide de l'attribut public en lecture seule previous.

Comme previous est implémenté dans la surclasse cx_root, il est disponible dans toutes les classes d'exception.

Essayer : classes d'exception

  1. Créez une nouvelle classe qui implémente l'interface IF_OO_ADT_CLASSRUN.
  2. Copiez l'extrait de code suivant dans la partie implémentation de la méthode if_oo_adt_classrun~main( ).
    Code Snippet
    12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
    DATA number1 TYPE i VALUE 2000000000. DATA number2 TYPE p LENGTH 2 DECIMALS 1 VALUE '0.5'. DATA result TYPE i. TRY. result = number1 / number2. CATCH cx_sy_arithmetic_overflow. out->write( 'Arithmetic Overflow' ). CATCH cx_sy_zerodivide. out->write( 'Division by zero' ). ENDTRY. number2 = 0. TRY. result = number1 / number2. CATCH cx_sy_arithmetic_overflow. out->write( 'Arithmetic Overflow' ). CATCH cx_sy_zerodivide. out->write( 'Division by zero' ). ENDTRY. TRY. result = number1 / number2. CATCH cx_sy_arithmetic_overflow cx_sy_zerodivide. out->write( 'Arithmetic overflow or division by zero' ). ENDTRY. TRY. result = number1 / number2. CATCH cx_sy_arithmetic_error. out->write( 'Caught both exceptions using their common superclass' ). ENDTRY. TRY. result = number1 / number2. CATCH cx_root. out->write( 'Caught any exception using CX_ROOT' ). ENDTRY. TRY. result = number1 / number2. CATCH cx_root into data(Exception). out->write( 'Used INTO to intercept the exception object' ). out->write( 'The get_Text( ) method returns the following error text: ' ). out->write( Exception->get_text( ) ). ENDTRY.
  3. Activez la classe avec Ctrl + F3.
  4. Jouez avec le codage pour vous familiariser avec lui.

Utilisation des objets d'exception

Vous améliorez votre code en accédant à des objets d'exception, c'est-à-dire des instances de classes d'exception. Vous utilisez les paramètres du constructeur pour définir les valeurs d'attribut des objets d'exception.

Modèle :

  • /LRN/CL_S4D401_OOS_FACTORY (classe globale)

Solution :

  • /LRN/CL_S4D401_EXS_HANDLING (classe globale)

Tâche 1: Copier modèle (facultatif)

Copiez la classe de modèle /LRN/CL_S4D401_OOS_FACTORY. Si vous avez terminé l'exercice précédent, vous pouvez ignorer cette tâche et continuer à modifier votre classe ZCL_##_SOLUTION.

Étapes

  1. Copiez la classe /LRN/CL_S4D401_OOS_FACTORY dans une classe de votre propre package (nom proposé : ZCL_##_SOLUTION, ## correspondant à votre numéro de groupe).

    1. Dans l'explorateur de projet, cliquez avec le bouton droit de la souris sur la classe /LRN/CL_S4D401_OOS_FACTORY pour ouvrir le menu contextuel.

    2. Dans le menu contextuel, sélectionnez Dupliquer....

    3. Saisissez le nom de votre package dans la zone Package. Dans la zone Nom, saisissez ZCL_##_SOLUTION, où ## représente votre numéro de groupe.

    4. Cliquez sur Next.

    5. Confirmez l'ordre de transport et cliquez sur Terminer.

  2. Activez la copie.

    1. Appuyez sur Ctrl + F3 pour activer la classe.

Tâche 2: Accéder aux objets d'exception

Dans votre classe globale, ajustez l'implémentation de la méthode IF_OO_ADT_CLASSRUN~MAIN. Étendez le traitement des exceptions lors de l'appel de la méthode Factory GET_INSTANCE. Dans les deux blocs CATCH, reçoit une référence à l'objet d'exception et extrait le texte d'exception. Remplacez le texte littéral pour l'édition de la console par les textes d'exception.

Étapes

  1. Naviguez vers l'implémentation de la méthode IF_OO_ADT_CLASSRUN~MAIN de votre classe globale.

    1. Ouvrez la classe globale et passez à l'onglet Classe globale.

  2. Dans la première instruction CATCH, laissez un point de variable de référence au niveau de l'objet d'exception, c'est-à-dire l'instance de la classe d'exception CX_ABAP_INVALID_VALUE (nom suggéré pour la variable : exc_inv).

    Astuce

    Vous pouvez utiliser une déclaration en ligne pour déclarer la variable de référence avec le type correct.
    1. Adaptez le code comme suit :

      ABAP
      1
      CATCH cx_abap_invalid_value INTO DATA(exc_inv).
    2. Pour afficher le type de variable exc_inv, placez le curseur sur exc_inv et appuyez sur F2.

  3. Dans le bloc CX_ABAP_INVALID_VALUE CATCH, commentez l'appel de la méthode out->write. Récupérez le texte de l'exception à partir de l'objet d'exception et utilisez-le dans un nouvel appel de la méthode out->write.

    1. Adaptez le code comme suit :

      ABAP
      123
      CATCH cx_abap_invalid_value INTO DATA(exc_inv). * out->write( |Carrier { c_carrier_id } does not exist| ). out->write( exc_inv->get_text( ) ).
  4. Procédez de la même manière avec la deuxième instruction CATCH et le bloc CATCH (nom proposé pour la variable de référence : exc_auth).

    1. Adaptez le code comme suit :

      ABAP
      123
      CATCH cx_abap_auth_check_exception INTO DATA(exc_auth). * out->write( |No authorization to display carrier { c_carrier_id }| ). out->write( exc_auth->get_text( ) ).
  5. Activez et testez votre code. Ajustez la valeur de la constante c_carrier_id pour provoquer les différentes exceptions.

    1. Appuyez sur Ctrl + F3 pour activer le code.

    2. Appuyez sur F9 pour exécuter le code en tant qu'application de console.

    3. Définissez la valeur de la constante c_carrier_id sur XX pour provoquer l'exception pour une valeur non valide.

    4. Définissez la valeur de la constante c_carrier_id sur UA pour provoquer l'exception en cas d'autorisation manquante.

Tâche 3: Gérer les groupes d'exceptions

Dans la classe de test locale LTCL_FIND_FLIGHTS, ajustez l'implémentation de la méthode CLASS_SETUP. Lors de l'appel de la méthode Factory GET_INSTANCE, traitez toutes les exceptions possibles dans un seul bloc CATCH. En cas d'exception, indiquez la méthode d'échec avec le texte d'exception de l'objet d'exception au lieu du message d'erreur générique "Impossible d'instancier lcl_Carrier".

Étapes

  1. Naviguez vers l'implémentation de la méthode CLASS_SETUP de la classe de test locale LTCL_FIND_FLIGHTS.

    1. Passez à l'onglet Classes de test.

    2. Faites défiler jusqu'à l'instruction METHOD class_setup.

  2. Après l'appel de la méthode GET_INSTANCE, ajustez le traitement des exceptions. Commentez le bloc Catch pour la classe d'exceptions CX_ABAP_INVALID_VALUE et remplacez la classe d'exception CX_ABAP_AUTH_CHECK_EXCEPTION par CX_ROOT.

    1. Adaptez le code comme suit :

      ABAP
      1234567
      TRY. the_carrier = lcl_carrier=>get_instance( i_carrier_id = some_flight_data-carrier_id ). * CATCH cx_abap_invalid_value. * cl_abap_unit_assert=>fail( `Unable to instantiate lcl_carrier` ). CATCH cx_root. cl_abap_unit_assert=>fail( `Unable to instantiate lcl_carrier` ). ENDTRY.
  3. Ajoutez une clause INTO à l'instruction CATCH avec une variable de référence déclarée en ligne (nom suggéré pour la variable : exc_root).

    1. Adaptez le code comme suit :

      ABAP
      1
      CATCH cx_root INTO DATA(exc_root).
    2. Pour afficher le type de variable exc_root, placez le curseur sur exc_root et appuyez sur F2.

  4. Dans le bloc CX_ROOT CATCH, utilisez le texte d'exception comme entrée pour la méthode CL_ABAP_UNIT_ASSERT=>fail.

    1. Adaptez le code comme suit :

      ABAP
      12
      CATCH cx_root INTO DATA(exc_root). cl_abap_unit_assert=>fail( exc_root->get_text( ) ).
  5. Activez votre code.

    1. Appuyez sur Ctrl + F3.

Tâche 4: Définir les attributs des objets d'exception

Adaptez le déclenchement des exceptions dans la méthode Factory GET_INSTANCE. Lorsque vous déclenchez l'exception CX_ABAP_INVALID_VALUE, utilisez un paramètre de constructeur approprié pour inclure l'ID de transporteur non valide dans le texte d'exception. Lorsque vous déclenchez l'exception CX_ABAP_AUTH_CHECK_EXCEPTION, utilisez un paramètre de constructeur approprié pour sélectionner un texte d'exception plus approprié.

Étapes

  1. Naviguez vers l'implémentation de la méthode GET_INSTANCE de la classe locale LCL_CARRIER.

    1. Par exemple, dans la méthode IF_OO_ADT_CLASSRUN~MAIN, placez le curseur sur get_instance et appuyez sur F3.

  2. Analysez la signature de la méthode CONSTRUCTOR de la classe d'exceptions CX_ABAP_INVALID_VALUE.

    1. Dans l'instruction RAISE EXCEPTION, placez le curseur sur CX_ABAP_INVALID_VALUE et appuyez sur F2 pour afficher les informations sur l'élément ABAP pour la classe d'exception.

    2. Dans la boîte de dialogue, sélectionnez Constructeur pour afficher les informations d'élément pour la méthode CONSTRUCTOR.

  3. Adaptez l'instruction RAISE EXCEPTION pour la classe d'exception CX_ABAP_INVALID_VALUE. Fournissez la valeur de paramètre du constructeur avec l'ID de transporteur non valide.

    Remarque

    Vous devez effectuer une conversion de type car la valeur et i_carrier_id n'ont pas un type identique.
    1. Adaptez le code comme suit :

      ABAP
      123
      RAISE EXCEPTION TYPE cx_abap_invalid_value EXPORTING value = CONV #( i_carrier_id ).
  4. Adaptez l'instruction RAISE EXCEPTION pour la classe d'exception CX_ABAP_AUTH_CHECK_EXCEPTION. Fournissez au paramètre de constructeur textid la constante publique missing_Authorization de cette classe d'exception.

    1. Adaptez le code comme suit :

      ABAP
      1234
      RAISE EXCEPTION TYPE cx_abap_auth_check_exception EXPORTING textid = cx_abap_auth_check_exception=>missing_authorization.
  5. Activez et testez votre code. Ajustez la valeur de la constante c_carrier_id pour provoquer les différentes exceptions.

    1. Appuyez sur Ctrl + F3 pour activer le code.

    2. Appuyez sur F9 pour exécuter le code en tant qu'application de console.

    3. Définissez la valeur de la constante c_carrier_id sur XX pour provoquer l'exception pour une valeur non valide.

    4. Définissez la valeur de la constante c_carrier_id sur UA pour provoquer l'exception en cas d'autorisation manquante.