Get the deepest text of chained exceptions

If you’re not already using ABAP Objects you’re chicken.
If you use them, I do hope you’re following the best practice of using class exceptions.
And if you’re using class exceptions you better understand the best way of using them, particularly the advantages of chaining them.
This said, here’s what brings us here today. In the post about chained exceptions I showed a way to get the text of the deepest exception in the chain by using a WHILE loop:
DATA: text TYPE string,
o_exp TYPE REF TO cx_root.
(…)
CATCH cx_fruit INTO o_exp.
WHILE o_exp->previous IS BOUND.
o_exp = o_exp->previous.
ENDWHILE.
text = o_exp->get_text( ).
ENDTRY.
But in a scenario of an application with many exceptions, all deriving from the same, you can do something much more interesting:
- Create a root exception for the application: ZCX_FRUIT
- All the application’s exceptions should inherit from this one: ZCX_FRUIT_BANANA, ZCX_FRUIT_PINEAPPLE, etc.)
- In the root exception ZCX_FRUIT
override method GET_TEXT() and add there the logic which was previously done outside, in the CATCH statement
The ZCX_FRUIT->GET_TEXT() code should be something like this:
METHOD GET_TEXT.
if me->previous is bound.
result = me->previous->get_text( ).
else.
result = super->if_message~get_text( ).
endif.
ENDMETHOD.
You may consider doing the same to method GET_LONG_TEXT() if you’re planning on using it.
The code is ever nicer because it’s recursive.
And now you no longer need to worry about the WHILE loop when you handle the exceptions. They now know how to take care of themselves. You just need to call GET_TEXT() on a chained exception and you’ll always be sure to get the text of the deepest one, which is usually the one better describing what happened.
Note 1: This just makes sense when you don’t care for the rest of the exceptions in the chain, which should be the most common scenario. I’ve needed them for logging purposes in the past. If that’s the case, this approach will not work.
Note 2: Unfortunately this technique is not compatible with the command MESSAGE o_exp TYPE ‘E’. For some reason, it will always give you the text of the top expression. It’s a shame.
Photo via JanDix via Visualhunt
Greetings from Abapinho.
18 de January de 2017 às 11:18 PM
Excelente post!!!!
19 de January de 2017 às 08:18 AM
Obrigado Erick! Gostando tanto de ler os teus posts é bom saber que também posso dar algo em troca! :)
6 de February de 2017 às 07:51 AM
Excelente ideia!
Para o exemplo funcionar falta fazer o downcast quanto se assigna a o_exp->previous a o_exp no while, isto porque a previous é do tipo cx_root, e a o_exp é uma excepção mais especifica.
6 de February de 2017 às 09:27 AM
Olá Sérgio, Tinha-me esquceido de declarar o O_EXP mas este também deverá ser CX_ROOT. Assim não é preciso downcast.
6 de February de 2017 às 09:32 AM
Olá Nuno,
Eu como sou um afortunado, e tenho à minha disposição o Netweaver 7.4, posso fazer:
(…)
CATCH cx_fruta INTO DATA(o_exp).
WHILE o_exp->previous IS BOUND.
o_exp ?= o_exp->previous.
ENDWHILE.
DATA(text) = o_exp->get_text( ).
ENDTRY.
Portanto para o caso de quem programa com a versão mais recente do ABAP, utilizando inline declarations, o downcast é mesmo necessário :)
6 de February de 2017 às 09:33 AM
Entendido :) obrigado sortudo :)