2013 Oct 19 3:33 AM
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_MATNR | Importing | Type | MATNR |
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_MATERIAL | Enter 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
2013 Oct 19 6:39 AM
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.
2013 Oct 19 6:39 AM
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.
2013 Oct 19 7:06 PM
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
2013 Oct 19 7:18 PM
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.
2013 Oct 19 9:47 PM
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
2013 Oct 20 11:08 AM
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.
2013 Oct 20 1:03 PM
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.
2013 Oct 21 8:58 AM
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".
2013 Oct 21 11:31 AM
I would rather say that the pattern only generates the exceptions defined in the method signature
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
2013 Oct 21 11:51 AM
It is good to know that method signature is the correct term to be used here.
2013 Oct 19 9:14 PM
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_MATERIAL | Enter 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:
| Exception | Handling |
|---|---|
| No user id | Create a new user id |
| Forgot password | Request for a new password |
| SCN site is down for maintenance | Take 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
2013 Oct 20 8:42 PM
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.
2013 Dec 15 12:47 PM
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
2013 Dec 15 8:01 PM
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
2013 Dec 16 6:31 AM
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