Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

Catch CX_ROOT vs Specific Exception

Former Member
0 Likes
44,702

Hi All

I'm learning SAP ABAP Objects basics , Please no links. I would appreciate if some one could explain..

I have a class ZCL_TEST with a method  GET_DATA

with

IM_MATNRImportingTypeMATNR

EX_MARA   Exporting Type MARA

and en exception  ZCX_MATERIAL

method get_data.

SELECT SINGLE * INTO EX_MARA FROM MARA WHERE MATNR = IM_MATNR.

IF SY-SUBRC NE 0.

RAISE ZCX_MATERIAL.

endmethod.

Again ZCX_MATERIAL is an Exception Class with Super class CX_STATIC_CHECK

Now my Exception Class Text Says


ZCX_MATERIAL

Now with in Method DEFAULT of ZCL_MAIN Class i have something like this

METHOD DEFAULT.

DATA : LC_TEST TYPE REF TO ZCL_TEST.

DATA : WA_MARA TYPE MARA.

DATA:   gr_err TYPE REF TO ZCX_MATERIAL.

CREATE OBJECT LC_TEST.

TRY.

LC_TEST->GET_DATA ( IMPORTING IM_MATNR = 'ABC'

                                       EXPORTING IM_MARA  = WA_MARA ).

CATCH ZCX_MATERIAL INTO GR_ERR.   "Orginal One

gs_msg = gr_err->get_text( ).

WRITE : GS_MSG. 

ENDMETHOD.

Output is  " An Exception Occured "  ( This is the Value of GS_MSG.

Instead i change it to

METHOD DEFAULT.

DATA : LC_TEST TYPE REF TO ZCL_TEST.

DATA : WA_MARA TYPE MARA.

DATA:

   gr_err TYPE REF TO cx_root.

CREATE OBJECT LC_TEST.

TRY.

LC_TEST->GET_DATA ( IMPORTING IM_MATNR = 'ABC'

                                      EXPORTING IM_MARA  = WA_MARA ).

CATCH CX_ROOT INTO GR_ERR.  "Changed One

gs_msg = gr_err->get_text( ).

WRITE : GS_MSG. 

ENDMETHOD.

Output is  " An Exception Occured "  ( This is the Value of GS_MSG. )

My questions are

1)Either way i'm getting Same Message " An Exception Occured " , so whats the point in Catching Specific CATCH ZCX_MATERIAL INTO GR_ERR.

excepton class ...we can always use CATCH CX_ROOT INTO GR_ERR.

2)Lets Say i want a more specific message then i have to attach a message text

Now my Exception Class Text Says


ZCX_MATERIALEnter a valid value

If i run the pgm both ways my Output is "Enter a Valid value "

So when i have to use   CATCH ZCX_MATERIAL INTO GR_ERR.  or when i have to use CATCH CX_ROOT INTO GR_ERR

Thanks in advance

1 ACCEPTED SOLUTION
Read only

Former Member
0 Likes
15,972

For a known exception, you can take specific action.

For remaining exceptions, cx_root can be used the catch exception, and show associated text.

Take a look at this snippet.

DATA lv TYPE i.
DATA lv_message TYPE string.
DATA lr_exc TYPE REF TO cx_root.
TRY .
    lv 100 / 0.
  CATCH cx_root INTO lr_exc.
    lv_message = lr_exc->get_text( ).
    WRITE:/ lv_message.
ENDTRY.

Here, output will be 'Division by zero'. It could have been 'Overflow during operation' if you multiply 99999 by 99999.

By catching specific exception, you can give tailored message like 'Number 100 can't be divided by 0'.

According to links, the associated text can be hardcoded or linked to SE91 message class.

You are getting general message 'An Exception Occurred' because the exception object is not having an associated text.

14 REPLIES 14
Read only

Former Member
0 Likes
15,973

For a known exception, you can take specific action.

For remaining exceptions, cx_root can be used the catch exception, and show associated text.

Take a look at this snippet.

DATA lv TYPE i.
DATA lv_message TYPE string.
DATA lr_exc TYPE REF TO cx_root.
TRY .
    lv 100 / 0.
  CATCH cx_root INTO lr_exc.
    lv_message = lr_exc->get_text( ).
    WRITE:/ lv_message.
ENDTRY.

Here, output will be 'Division by zero'. It could have been 'Overflow during operation' if you multiply 99999 by 99999.

By catching specific exception, you can give tailored message like 'Number 100 can't be divided by 0'.

According to links, the associated text can be hardcoded or linked to SE91 message class.

You are getting general message 'An Exception Occurred' because the exception object is not having an associated text.

Read only

0 Likes
15,972

Thanks Manish Kumar.

Now i have a better understanding

So as per my understanding

TRY

----

----

CATCH  SPECIFIC EXCEPTIONS LIKE CX_SY_ZERODIVIDE OR CX_SY_ARTHIMETIC ERROR

CATCH CX_ROOT   " At the end to be on safer side if i missed any specific exceptions that can occur because of above statements

ENDTRY.

If i'm right i have one last question how to identify the SPECIFIC Exceptions that can occur

ex :

try.

CALL METHOD cl_salv_table=>factory

           EXPORTING

             r_container  = gr_container

           IMPORTING

             r_salv_table = gr_alv

           CHANGING

             t_table      = i_table.

       CATCH cx_salv_msg.  " how do i identify this particular exception

       catch cx_root.

endtry.

I see that its in the signature of the Method Factory is thats how you identify what exceptions can occur

But i see for some methods there are no exceptions does it mean no exceptions can occur ?

Thanks in advance

Read only

0 Likes
15,972

Code is generated automatically for the exceptions that can be raised by method. (when Call Pattern is used).

To check manually, RAISE statement can be searched in the method or class.

  if r_container is bound and list_display eq abap_true.
    raise exception type cx_salv_msg
        exporting msgid = 'SALV_EXCEPTION'
                  msgno = 015.
  endif.

  if is_offline( ) eq if_salv_c_bool_sap=>true and
     r_container is bound.
    raise exception type cx_salv_msg
        exporting msgid = 'SALV_EXCEPTION'
                  msgno = 025.
  endif.

The factory method has 2 RAISE statement, both for exception class cx_salv_msg.

Even if a method is not raising exception, exception can still occur in methods or FMs called by method.

Read only

SuhaSaha
Product and Topic Expert
Product and Topic Expert
0 Likes
15,972

I see that its in the signature of the Method Factory is that's how you identify what exceptions can occur

But i see for some methods there are no exceptions does it mean no exceptions can occur ?

All exception classes which are inherited from CX_STATIC_CHECK should be either handled in the procedure(FORM, FUNCTION, METHOD etc) or propagated through the interface (read: signature). (Ref. - http://help.sap.com/abapdocu_740/en/abenexception_categories.htm)

In order to see which exception the procedure propagates i always refer to the signature & IMO that's the most trusted place to look for.

To check manually, RAISE statement can be searched in the method or class

- Checking for the RAISE statement manually might help, but i won't suggest it to anyone. E.g., i have a method div_raise_excp( ) defined as:

    div_raise_excp

IMPORTING
       numerator TYPE i denominator TYPE i
     RETURNING value(quotient) TYPE i
     RAISING cx_sy_zerodivide.

and implemented as

METHOD div_raise_excp.
     quotient = numerator / denominator.

ENDMETHOD.

There is no RAISE statement in the method/class, so should i leave the method call as

   lcl_main=>div_raise_excp( numerator = 1 denominator = 0 ).

Or should i put it in a TRY-CATCH block

TRY .
       lcl_main=>div_raise_excp( numerator = 1 denominator = 0 ).
     CATCH cx_sy_zerodivide ##no_handler.

ENDTRY.

BR,

Suhas

Read only

0 Likes
15,972

Checking for the RAISE statement manually might help, but i won't suggest it to anyone.

I am not suggesting that either. It is to know how Call Pattern suggests list of exceptions.

Read only

SuhaSaha
Product and Topic Expert
Product and Topic Expert
0 Likes
15,972

It is to know how Call Pattern suggests list of exceptions.

I'm sorry; but i don't get that either. So you were trying to tell the OP how the "Insert Pattern" suggests the list of exceptions. And (if i understand your response correctly) it does that by -

checking manually RAISE statement can be searched in the method or class.

Read only

0 Likes
15,972

It is an observation based on code generated by Call Pattern.

*TRY.
CALL METHOD cl_salv_table=>factory
*  EXPORTING
*    list_display   = IF_SALV_C_BOOL_SAP=>FALSE
*    r_container    =
*    container_name =
*  IMPORTING
*    r_salv_table   =
  CHANGING
    t_table        =
    .
* CATCH cx_salv_msg .
*ENDTRY.

The method implementation has statement "raise exception type cx_salv_msg", and Call Pattern has "Catch cx_salv_msg".

On the other hand, Call Pattern for cl_gui_alv_grid->refresh_table_display is:

CALL METHOD lr_grid->refresh_table_display
*  EXPORTING
*    is_stable      =
*    i_soft_refresh =
*  EXCEPTIONS
*    finished       = 1
*    others         = 2
        .

The method implementation has statement "raise finished".

Read only

SuhaSaha
Product and Topic Expert
Product and Topic Expert
0 Likes
15,972

I would rather say that the pattern only generates the exceptions defined in the method signature

  1. CL_SALV_TABLE=>FACTORY( ); exception class CX_SALV_MSG. Hence the TRY-CATCH block.
  2. CL_GUI_ALV_GRID->REFRESH_TABLE_DISPLAY( ); classical exception FINISHED. Hence the classical exception handling using SY-SUBRC.

class ZCL_CALCULATOR definition
   public
   final
   create public .

public section.

   constants ADD type I value 1. "#EC NOTEXT
   constants SUB type I value 2. "#EC NOTEXT
   constants MULT type I value 3. "#EC NOTEXT
   constants DIV type I value 4. "#EC NOTEXT

   class-methods CALCULATOR
     importing
       !OPERATION type I
       !IV1 type I
       !IV2 type I
     returning
       value(RES) type I
     raising
       CX_SY_ARITHMETIC_OVERFLOW
       CX_SY_ZERODIVIDE .
protected section.
private section.

   class-data X type I .
   class-data Y type I .
ENDCLASS.



CLASS ZCL_CALCULATOR IMPLEMENTATION.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_CALCULATOR=>CALCULATOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] OPERATION                      TYPE        I
* | [--->] IV1                            TYPE        I
* | [--->] IV2                            TYPE        I
* | [<-()] RES                            TYPE        I
* | [!CX!] CX_SY_ARITHMETIC_OVERFLOW
* | [!CX!] CX_SY_ZERODIVIDE
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD calculator.

   CASE operation.
     WHEN add.
       res = iv1 + iv2.
     WHEN sub.
       res = abs( iv1 - iv2 ).
     WHEN mult.
       res = iv1 * iv2.
     WHEN div.
       res = iv1 / iv2.
   ENDCASE.

ENDMETHOD.
ENDCLASS.

Create a global class(using the code above) & call the method ZCL_CALCULATOR=>CALCULATOR( ) in your program. You'll see that the exceptions are raised in a TRY-CATCH block.

BR,

Suhas

Read only

0 Likes
15,972

It is good to know that method signature is the correct term to be used here.

Read only

SuhaSaha
Product and Topic Expert
Product and Topic Expert
0 Likes
15,972

Hello Satyam,

I think you should close your previous thread - . I can see that the responders have provided quite a few valuable responses which tell you why you should not use CX_ROOT to catch the exceptions.

1)Either way i'm getting Same Message " An Exception Occured " , so whats the point in Catching Specific CATCH ZCX_MATERIAL INTO GR_ERR.

excepton class ...we can always use CATCH CX_ROOT INTO GR_ERR.

2)Lets Say i want a more specific message then i have to attach a message text

Now my Exception Class Text Says


ZCX_MATERIALEnter a valid value

If i run the pgm both ways my Output is "Enter a Valid value "

So when i have to use   CATCH ZCX_MATERIAL INTO GR_ERR.  or when i have to use CATCH CX_ROOT INTO GR_ERR

Let's take a simple example, you are trying to post a question on SCN. There are 3 types of exceptions which may occur:

ExceptionHandling
No user idCreate a new user id
Forgot passwordRequest for a new password
SCN site is down for maintenanceTake a break & come back later

TRY .
     post_a_question_on_scn( ).
   CATCH no_user_id.
     create_user_id( ).
   CATCH forgot_password.
     request_new_password( ).
   CATCH site_maintenance.
     sip_coffee_and_come_back_later( ).
ENDTRY.

If you use the the generic exception CX_ROOT, can you handle the specific exceptions? So the answer to your question is - "depends on how you want to handle the exception".

BR,

Suhas

Read only

matt
Active Contributor
0 Likes
15,972

Agreed

The correct pattern is to define the exception object that you catch into with reference to cx_root, but catch specific exceptions.

Never catch cx_root. ...of course there may be some exceptions to this, but as a general rule it stands.

Read only

former_member182680
Active Participant
0 Likes
15,972

As Matthew explained, catching cx_root is generally a no-go. Please keep in mind, that implicitly raised exceptions like CX_SY_REF_IS_INITIAL (when accessing an unbound object) are also catched and you won't receive a dump explaining what went wrong..

So unless you don't know exactly what you are doing, catch specific exceptions. If you catch CX_ROOT, you need to write additional logic, which helps you in the following aspects:

-re-raising certain exceptions, that should lead to a program exit (dump)

-output of the exact stack trace

-switching off stack trace output for end users

Read only

nishantbansal91
Active Contributor
0 Likes
15,972

Hi Satyam,

For this you can use the Multiple catch block for the simple try Block. Class CX_root is the top most class of all the exception class.

You can handle your exception in this class because if you know that you want to show the oone common message for each Exception or You are not sure that what type of exception is coming while dynamic time.

SO CX_ROOT class is used for to handle any type of exception either is Airthemetic or Object type.

Regard,

Nishant Bansal

Read only

0 Likes
15,972

As a wise man, just one post above yours said:

...catching cx_root is generally a no-go. Please keep in mind, that implicitly raised exceptions like CX_SY_REF_IS_INITIAL (when accessing an unbound object) are also catched and you won't receive a dump explaining what went wrong..

So unless you don't know exactly what you are doing, catch specific exceptions. If you catch CX_ROOT, you need to write additional logic, which helps you in the following aspects:

-re-raising certain exceptions, that should lead to a program exit (dump)

-output of the exact stack trace

-switching off stack trace output for end users