Defining Your Own Exception Classes

Objective

After completing this lesson, you will be able to Define your own exception classes.

Definition of Your Own Exception Classes

There are lots of predefined system exception classes whose names all begin with cx_sy. However, these classes describe technical errors and do not reflect the semantics of your application.

In a flight application, a class may need an exception that describes a situation where a particular combination of an airline and flight number does not exist.

To define an exception class of your own, create a new class that inherits from the class cx_static_check.

In this video, you will see how to create, prepare, attach, and raise an exception.

Try It Out: Definition of Your Own Exception Classes

Create an exception class ZSD4D01_EXCEPTIONS as follows:

  1. Press Ctrl + Shift + N to create a new ABAP Repository Object.
  2. Enter the filter text MESSAGE and double-click the entry Message Class in the hit list.
  3. Assign the message class to a valid package. Enter the name ZS4D401_EXCEPTIONS and a description, and then press Next.
  4. Select an appropriate transport request and choose Finish.
  5. Enter the message number 001 and the text Connection &1 &2 does not exist.
  6. Save the message class.
  7. Create a new class that implements the interface IF_OO_ADT_CLASSRUN.
  8. Switch to the Local Types tab and paste the following code snippet into the editor:
    Code Snippet
    Copy code
    Switch to dark mode
    123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
    CLASS lcx_no_connection DEFINITION INHERITING FROM cx_static_Check. PUBLIC SECTION. interfaces if_t100_message. METHODS constructor IMPORTING textid LIKE if_t100_message=>t100key OPTIONAL previous LIKE previous OPTIONAL airlineid TYPE /DMO/CARRIER_ID OPTIONAL connectionnumber TYPE /DMO/CONNECTION_ID OPTIONAL. CONSTANTS: BEGIN OF lcx_no_connection, msgid TYPE symsgid VALUE 'ZS4D401_EXCEPTIONS', msgno TYPE symsgno VALUE '001', attr1 TYPE scx_attrname VALUE 'AIRLINEID', attr2 TYPE scx_attrname VALUE 'CONNECTIONNUMBER', attr3 TYPE scx_attrname VALUE 'attr3', attr4 TYPE scx_attrname VALUE 'attr4', END OF lcx_no_connection. DATA airlineid TYPE /dmo/carrier_id READ-ONLY. DATA connectionnumber TYPE /dmo/connection_id READ-ONLY. ENDCLASS. CLASS lcx_no_Connection IMPLEMENTATION. METHOD constructor. super->constructor( previous = previous ). me->airlineid = airlineid. me->connectionnumber = connectionnumber. CLEAR me->textid. IF textid IS INITIAL. if_t100_message~t100key = lcx_no_connection. ELSE. if_t100_message~t100key = textid. ENDIF. ENDMETHOD. ENDCLASS. CLASS lcl_connection DEFINITION. PUBLIC SECTION. METHODS constructor IMPORTING i_airlineid TYPE /dmo/carrier_id i_connectionnumber TYPE /dmo/connection_id RAISING lcx_no_connection. PRIVATE SECTION. DATA AirlineId TYPE /dmo/carrier_id. DATA ConnectionNumber TYPE /dmo/connection_id. DATA fromAirport TYPE /dmo/airport_from_id. DATA toAirport TYPE /dmo/airport_to_id. ENDCLASS. CLASS lcl_Connection IMPLEMENTATION. METHOD constructor. DATA fromairport TYPE /dmo/airport_from_Id. DATA toairport TYPE /dmo/airport_to_id. SELECT SINGLE FROM /dmo/connection FIELDS airport_from_id, airport_to_id WHERE carrier_id = @i_airlineid AND connection_id = @i_connectionnumber INTO ( @fromairport, @toairport ). IF sy-subrc <> 0. RAISE EXCEPTION TYPE lcx_no_connection EXPORTING airlineid = i_airlineid connectionnumber = i_connectionnumber. ELSE. me->connectionnumber = i_connectionnumber. me->fromairport = fromairport. me->toairport = toairport. ENDIF. ENDMETHOD. ENDCLASS.
  9. Switch to the Global Class tab and paste the following code snippet into the implementation of the main( ) method:
    Code Snippet
    Copy code
    Switch to dark mode
    123456789
    DATA connection TYPE REF TO lcl_connection. DATA exception TYPE REF TO lcx_no_connection. TRY. connection = NEW #( i_airlineid = 'XX' i_connectionnumber = '0000' ). CATCH lcx_no_connection into exception. out->write( exception->get_text( ) ). ENDTRY.
  10. Activate the class by pressing Ctrl + F3.
  11. Execute the class by pressing F9. Play around with the source code to familiarize yourself with it.

Define and use an Exception Class

You realize that the exception texts are not specific enough for your application. Therefore, you define your own exception classes and use them in your code.

Template:

  • /LRN/CL_S4D401_EXS_HANDLING (Global Class)

Solution:

  • /LRN/CL_S4D401_EXS_CLASS (Global Class)
  • /LRN/S4D401_EXS_MESS (Message Class)
  • /LRN/CX_S4D401_EXS_FAILED (Global Exception Class)

Task 1: Copy Template (Optional)

Copy the template class. If you finished the previous exercise, you can skip this task and continue editing your class ZCL_##_SOLUTION.

Steps

  1. Copy class /LRN/CL_S4D401_EXS_HANDLING to a class in your own package (suggested name: ZCL_##_SOLUTION, where ## stands for your group number).

    1. In the Project Explorer view, right-click class /LRN/CL_S4D401_EXS_HANDLING to open the context menu.

    2. From the context menu, choose Duplicate ....

    3. Enter the name of your package in the Package field. In the Name field, enter the name ZCL_##_SOLUTION, where ## stands for your group number.

    4. Adjust the description and choose Next.

    5. Confirm the transport request and choose Finish.

  2. Activate the copy.

    1. Press Ctrl + F3 to activate the class.

Task 2: Create a Message Class

Create a new message class (suggested name: Z##_MESSAGES, where ## is your group number). Define two message texts, one to report a non-existent carrier, the other to report a missing read authorization. In both messages, use a placeholder for the carrier ID.

Steps

  1. Create a new message class (suggested name: Z##_MESSAGES, where ## is your group number).

    1. In the Project Explorer view on the left, right-click your package and choose NewOther ABAP Repository Object.

    2. In the search field, enter mess.

    3. From the search result, choose TextsMessage Class and choose Next.

    4. Ensure that the Package field contains the name of your package.

    5. In the Name field, enter the name Z##_MESSAGES, where ## stands for your group number.

    6. In the Description field, enter Messages for Exception Class.

    7. Choose Next.

    8. Confirm your transport request and choose Finish.

  2. Define a message to report that a carrier does not exist (suggested number: 010). Use a placeholder for the carrier ID.

    1. In the first row, in column Number, choose <Enter new value> and enter 010.

    2. In the same row, in column Short Text, enter Carrier &1 does not exist.

  3. Define a message to report that the user is not authorized to display a certain carrier (suggested number: 020). Use a placeholder for the carrier ID.

    1. In the second row, in column Number, choose <Enter new value> and enter 020.

    2. In the same row, in column Short Text, enter You are not authorized to display carrier &1.

  4. Save the message class.

    Note

    It is not neither necessary nor possible to activate message classes. For message classes, we do not distinguish between active and inactive versions.
    1. Press Ctrl + s to save the message class.

Task 3: Create Exception Class

Create a new global exception class (suggested name: ZCX_##_FAILED, where ## is your group number) that inherits from superclass CX_STATIC_CHECK. Define two text ID constants that refer to the message texts you just created. Declare a public, read-only instance attribute (suggested name: CARRIER_ID) and make sure that at runtime, the placeholders in the messages are replaced with the value of this attribute. Finally, extend the CONSTRUCTOR method with an optional import parameter to set the new attribute.

Steps

  1. Create a new global class that inherits from superclass CX_STATIC_CHECK (suggested name: ZCX_##_FAILED, where ## is your group number) .

    1. In the Project Explorer view on the left, expand your package.

    2. Right-click Source Code Library and choose NewABAP Class.

    3. Ensure that the Package field contains the name of your package.

    4. In the Name field, enter the name ZCX_##_FAILED, where ## stands for your group number.

    5. In the Description field, enter Instantiation Failed.

    6. In the Superclass field, enter CX_STATIC_CHECK.

    7. Choose Next.

    8. Confirm your transport request and choose Finish.

  2. Use code completion, to define a new text id constant, that is, a public structured constant.

    1. In the public section of your exception class, after the INTERFACES statements, enter text and press Ctrl + Space to invoke the code-completion.

    2. From the suggestion list, choose textIDExceptionClass - Default textid for exception class.

    3. The code-completion should adjust the code as follows:

      Code Snippet
      Copy code
      Switch to dark mode
      123456
      PUBLIC SECTION. INTERFACES if_t100_message . INTERFACES if_t100_dyn_msg .
  3. Use a quickfix to rename the constant (suggested new name: carrier_not_exist).

    1. After BEGIN OF, place the cursor on zcx_##_failed, where ## is your group number and press Ctrl + 1 to invoke the quickfix.

    2. From the list of available quickfixes, choose Rename zcx_##_failed.

    3. While the name of the constant is still highlighted, enter the new name.

  4. Adjust the component values of the constant. Use the name of your message class, and the number of the first message as values.

    1. Adjust the code as follows:

      Code Snippet
      Copy code
      Switch to dark mode
      1234567891011
      CONSTANTS: BEGIN OF carrier_not_found, msgid TYPE symsgid VALUE '', msgno TYPE symsgno VALUE '', attr1 TYPE scx_attrname VALUE 'attr1', attr2 TYPE scx_attrname VALUE 'attr2', attr3 TYPE scx_attrname VALUE 'attr3', attr4 TYPE scx_attrname VALUE 'attr4', END OF carrier_not_found.
  5. Use the same code template and quickfix to define another text ID constant for your second message text (suggested name: carrier_no_read_auth).

    1. Add the following code:

      Code snippet
      Expand
  6. Define a public, read-only instance attribute of type /DMO/CARRIER_ID (suggested name: CARRIER_ID).

    1. In the public section of your exception class, add the following code:

      Code snippet
      Expand
  7. Adjust the text ID constants. Use the name of your new attribute as the value for component attr1.

    1. Adjust the code as follows:

      Code Snippet
      Copy code
      Switch to dark mode
      123456789101112131415161718192021
      CONSTANTS: BEGIN OF carrier_not_exist, msgid TYPE symsgid VALUE '/LRN/S4D401_EXS_MESS', msgno TYPE symsgno VALUE '010', attr1 TYPE scx_attrname VALUE '', attr2 TYPE scx_attrname VALUE 'attr2', attr3 TYPE scx_attrname VALUE 'attr3', attr4 TYPE scx_attrname VALUE 'attr4', END OF carrier_not_exist. CONSTANTS: BEGIN OF carrier_no_read_auth, msgid TYPE symsgid VALUE '/LRN/S4D401_EXS_MESS', msgno TYPE symsgno VALUE '020', attr1 TYPE scx_attrname VALUE '', attr2 TYPE scx_attrname VALUE 'attr2', attr3 TYPE scx_attrname VALUE 'attr3', attr4 TYPE scx_attrname VALUE 'attr4', END OF carrier_no_read_auth.
  8. Extend the signature of the CONSTRUCTOR method. Add an optional import parameter that can be used to set the value of attribute carrier_id (suggested name: carrier_id).

    1. Adjust the code as follows:

      Code Snippet
      Copy code
      Switch to dark mode
      123456
      METHODS constructor IMPORTING !textid LIKE if_t100_message=>t100key OPTIONAL !previous LIKE previous OPTIONAL.

      Note

      You can ignore or remove the exclamation marks (!) in front of the existing parameter names. They are optional as long as the parameter names are distinguishable from ABAP key words. In global classes, the tool inserts them by default.
  9. Adjust the implementation of the CONSTRUCTOR method. At the end of the method check whether optional parameter carrier_id is initial. If it is not initial, store its value in instance attribute carrier_id.

    Note

    If you choose the same name for the importing parameter and the attribute you have to address the attribute using self-reference me-> .
    1. Adjust the code as follows:

      Code Snippet
      Copy code
      Switch to dark mode
      12345678
      IF textid IS INITIAL. if_t100_message~t100key = if_t100_message=>default_textid. ELSE. if_t100_message~t100key = textid. ENDIF. ENDMETHOD.
  10. Activate your exception class.

    1. Press Ctrl + F3 to activate the code.

Task 4: Use the Exception Class

In method GET_INSTANCE of local class LCL_CARRIER, replace the exception classes CX_ABAP_INVALID_VALUE and CX_ABAP_AUTH_CHECK_EXCEPTION with your own exception class. Follow the warnings to adjust the RAISING clause of the method definition and the exception handling in method IF_OO_ADT_CLASSRUN~MAIN.

Steps

  1. Navigate to the implementation of method GET_INSTANCE of local class LCL_CARRIER.

    1. For example, expand LCL_CARRIERGET_INSTANCE in the Outline view on the bottom left.

  2. Remove or comment the RAISE EXCEPTION statement that uses exception class CX_ABAP_INVALID_VALUE.

    1. Select the RAISE EXCPETION statement, including the parameter passing, and press Ctrl + < to add a comment sign in front of the selected rows.

  3. Implement a RAISE EXCEPTION statement with your own exception class. Use code completion to insert the full signature of the CONSTRUCTOR.

    1. Place the cursor after the commented code and enter raise exception type ZCX_##, where ## is your group number.

    2. Press Ctrl + Space to invoke the code-completion.

    3. Press Shift + Enter to insert full signature.

    4. Make sure the code completion added the following code:

      Code snippet
      Expand
  4. Supply optional parameter textid with the first of your text ID constants and optional parameter carrier_id with the value of i_carrier_id.

    1. Adjust the code as follows:

      Code Snippet
      Copy code
      Switch to dark mode
      1234567
      RAISE EXCEPTION TYPE zcx_##_failed EXPORTING textid = * previous = carrier_id = .
  5. Similarly, use your own exception class in the second RAISE EXCEPTION statement. This time, use the other text ID constant as input for parameter textid.

    1. Adjust the code as follows:

      Code Snippet
      Copy code
      Switch to dark mode
      12345
      * RAISE EXCEPTION TYPE cx_abap_auth_check_exception * EXPORTING * textid = cx_abap_auth_check_exception=>missing_authorization.
  6. Use a quickfix to add your own exception class to the RAISING clause of method GET_INSTANCE.

    1. Go to the code row with either of the two RAISE EXCEPTION statements and choose the warning icon with the light bulb on the left-hand side to invoke the quickfix.

    2. From the list of available quickfixes, choose Add raising declaration.

  7. Remove or comment the redundant exceptions from the raising clause of method GET_INSTANCE.

    1. Adjust the code as follows:

      Code Snippet
      Copy code
      Switch to dark mode
      1234567891011
      CLASS-METHODS get_instance IMPORTING i_carrier_id TYPE /dmo/carrier_id RETURNING VALUE(r_result) TYPE REF TO lcl_carrier RAISING cx_abap_invalid_value cx_abap_auth_check_exception /lrn/cx_s4d401_exs_failed.
  8. Adjust the exception handling in method IF_OO_ADT_CLASSRUN~MAIN. Replace the two CATCH blocks with one CATCH block for your own exception class.

    1. Adjust the code as follows:

    Code Snippet
    Copy code
    Switch to dark mode
    12345678910111213
    TRY. DATA(carrier) = lcl_carrier=>get_instance( i_carrier_id = c_carrier_id ). out->write( name = `Carrier Overview` data = carrier->get_output( ) ). * CATCH cx_abap_invalid_value INTO DATA(exc_val). * out->write( exc_val->get_text( ) ). * CATCH cx_abap_auth_check_exception INTO DATA(exc_auth). * out->write( exc_auth->get_text( ) ). ENDTRY.
  9. Activate and test your code. Adjust the value of constant c_carrier_id to provoke the different exceptions.

    1. Press Ctrl + F3 to activate the code.

    2. Press F9 to execute the code as console app.

    3. Set the value of constant c_carrier_id to XX to provoke the exception for invalid value.

    4. Set the value of constant c_carrier_id to UA to provoke the exception for missing authorization.

Log in to track your progress & complete quizzes