Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
LaurensDeprost
Contributor

 

Why use local exception classes?


Although it is generally best practice to create global exception classes, they can seem a bit overkill for some applications. Think of PoCs, demo scenarios, BAdI implementations, etc. A handy but not so well-known option for these situations is to define a local exception class inside the global class. These allow internal exceptions (exceptions raised within the class itself) to be handled without the need for another global DDIC object. The SAP Help Portal describes local classes as follows:



Local definitions, especially local classes, can be useful as auxiliary classes for the global class. In local classes you can encapsulate implementation details that should not be visible from the outside (they should not even occur in the private section).

Class editor: source-code based or ADT ⚠️


Before you get coding, take into consideration that local exception classes do not play well with the classical Form-Based Class Builder. Use the Source Code-Based editor or Eclipse with ADT instead.


An overview of the editor choices available


 

Defining a local exception class


 

Source-code based Class Builder


To add a local exception class definition within a global class first open the global class in SE24 or SE80. Next, open the menu path Goto → Local Definitions/Implementations → Local Definitions/Implementations.


Opening the 'local definitions/implementations' section in the Class Builder


 

Alternatively, you can click the toolbar button labeled ‘Local Definitions/Implementations’. You can now enter the logic for the local exception class.


The button labeled 'Local definitions/Implementations' in the Class Builder


 

Eclipse with ADT


To add or edit a local class definition in the ABAP Development Tools in Eclipse, first open the global class. Do this via double-clicking the corresponding entry in the Project Explorer or via the ‘Open ABAP Development Object’ tool. Open the latter via its menu option Navigate → Open ABAP Development Object or its corresponding keyboard shortcut Ctrl + Shift + A.




The menu path 'Open ABAP Development Object' in the ABAP Development Tools in Eclipse


 

After opening the global class, define the local exception class in the tab ‘Class-relevant Local Types’. Next, open its local types section by clicking the tab labeled ‘Local Types’. You can now enter the definition and logic.

As noted by matthew.billingham in the comment section, usually, it's fine to just have the local class definition in the ‘Local Types’ tab. However, this can cause problems in some cases. Prevent potential issues by declaring the class separately using ‘DEFINITION DEFERRED’ in the ‘Class-relevant Local Types’ tab.




The tab named 'Local Types' in the ABAP Development Tools in Eclipse


 

Example


The example below showcases a basic exception class for handling exceptions in an ALV reporting class.
*"* use this source file for the definition and implementation of
*"* local helper classes, interface definitions and type
*"* declarations
CLASS lcx_ca_gen_report DEFINITION INHERITING FROM cx_dynamic_check.
PUBLIC SECTION.
INTERFACES if_t100_dyn_msg.
ALIASES msgty FOR if_t100_dyn_msg~msgty.
ENDCLASS.

 


Example local class definition in the Class Builder


 

We can now use this exception class in the internal methods of the global class.
"Program error in ALV-based output list, contact support
RAISE EXCEPTION TYPE lcx_ca_gen_report
MESSAGE e014(j_3rvatd).

 

Further reading



Conclusion



Local exception classes can provide distinct exceptions to internal class methods without creating a new global exception class. However, do they have added value in a particular situation? What is your opinion? Do you consider them a useful option for specific cases or a bad habit for lazy developers? Good practice or bad practice?
Share your feedback in the comments 👇




18 Comments
matt
Active Contributor
One point, is that you should declare the local exception class in the Class-relevant Local Types tab, and the definition in the Local Types tab.

Usually, it's fine to have the definition in the Local Types tab, but it can cause problems sometimes that would need to to put a DEFINITION DEFERRED in the Class-relevant Local Types tab anyway.

Good idea for prototyping though. Thanks.
LaurensDeprost
Contributor
Good remark concerning the declaration in the 'Class-relevant Local Types' tab.
Thanks matthew.billingham, I have amended the post.
wridgeu
Participant
I often find myself wondering when to (best) use those seperate class includes and in which scenarios - but thanks to your Blog I have a better Idea now!

Great and to the point Blog with all necessary information! Thanks for sharing!

BR,

Marco

 
LaurensDeprost
Contributor
Thanks marco.beier, great to hear you liked the post.

I agree. The decision as to whether code is better implemented in the local include class versus elsewhere is not always obvious.
JensSB
Participant
Hi dep

This is a nice blog at the right time for me. When I was ready with reading, I immediately intended to write. I like the idea of local exception classes because I use them in some rare cases as a possibility for coding control. As such, it is surely a better behaviour to define them as local objects. Just yesterday, I created a global exception class for exactly such a purpose. So I thought, 'Cool, that helps me avoid creating an object that nobody else needs!'.

You kindly provided the blog with some links. So I read these too, and now I am in trouble! In the CleanCode chapter for "Error handling" is written:
"Exceptions should be reserved for cases that you don't expect and that reflect error situations. Misusing exceptions misguides the reader into thinking something went wrong, when really everything is just fine." 

I wrote a method that recursively calls itself until it finds either a result (which is returned) or it fits a specific status (and no result is needed). Currently, I no idea how to solve this problem without using an exception excepting I export to values and check both.

To discuss this (using exceptions as a controlling instrument or not), I assume it needs another blog, isn't it?

To use local exception classes as intended in the mentioned Clean Code chapter seems a little strange to me.

I believe I'm a little confused now, or not? Could please someone help out?

Cheers, Jens
SuhaSaha
Advisor
Advisor

Hi Jens,

My 2 cents...

We had a scenario similar to yours. In our case both initial & non-initial "result" are valid. If "initial" result, then different callers would react in different ways. 

Our approach was to enhance the "result" as a structure with 2 fields:

  • Value: Both zero/non-zero values
  • Status: An enumeration detailing why the "value" is zero

The caller of the method can now use the status to control the program flow.

JensSB
Participant
0 Kudos
Thank yousuhassaha,

yes, this could also be a solution for me, as my result is structure anyway and I return the status. Good idea. Thank you.
pokrakam
Active Contributor

Local exception classes are great. However personally I rarely put them into class-relevant local types. You only need that if you need the local class to be part of the class definition (i.e. METHODS ... RAISING lcx_...). If this is the case, then there's possibly a good argument for making it a global exception.

If the exception is only used in code, not in the definition (e.g. dynamic or inherited exceptions), then local definitions are fine.

Inheriting global exceptions is very useful to make things more meaningful.

For example gateway methods have /iwbep/cx_mgw_busi_exception in their interface for business exceptions. You don't need to create an implementation of an inherited class, just:

CLASS lcx_order_not_found DEFINITION INHERITING FROM /iwbep/cx_mgw_busi_exception.
ENDCLASS.

and you have a more meaningful exception. One can raise any subclass exception in code if a superclass is defined in the method signature.

LaurensDeprost
Contributor
Thanks for your insights mike.pokraka.
I agree that most use cases are better off with either 'regular' local exception classes or global exception classes. Using class-relevant local types lends itself to very specific contexts (BAdIs, a demo scenario for which you don't want too many objects, etc.).

Fantastic tip on inheriting /iwbep/cx_mgw_busi_exception without having to create an implementation in gateway projects. Doing this never occured to me before while it's a quick and easy way to provide more meaningful exceptions indeed.
LaurensDeprost
Contributor

Hi jens.schmitt-bousska,

The use of exceptions as controlling instruments is indeed a discussion in itself.

The consensus to only use exceptions for error situations and not for flows that occur in 'normal' processing makes sense. That said, it seems justifiable to me specifically for recursive methods that are sufficiently encapsulated. Alternative methods to stop the chain after finding a result will be probably be significantly more verbose/less clear.


For your specific use case you can try to keep track of the result and/or status in a member variable and check/update its value in the recursively called method.
Jelena
Active Contributor
I fully agree that exceptions should be used for, well, exceptional situations, as the name suggests. However, on practice most things are not so black and white, so whether it should be 0 value returned or "no value found" should be an exception - that's for the developer to decide. An alternative (exporting 2 values, introducing statuses, etc.) might be not much "cleaner" than an exception that kind of isn't.

This is a good point to remind ourselves that development is as much Art as it is Science. 🙂
Jelena
Active Contributor
Love the blog, don't love the concept. 🙂 I have created global exception classes even for PoC and tests. It's super fast and convenient (especially if you use SE80 - exception classes are included in the pattern there). There are some caveats though.

  1. I suspect many developers get confused by when and how the exception classes should be created. This tends to end with either a ZCX_GENERIC that is [ab]used all over the place or hundreds of ZCXs for every obscure exception. As always, practical solution is somewhere in the middle.

  2. Who likes T100 interface? Let's see some hands. It "confuses and infuriates us", so I immediately outfit my ZCX with a couple of methods that I'll actually use to pass along messages in a more practical fashion.


I wouldn't say local exception is a bad idea but something about it feels off. If I was looking at the code that uses this, I'd be scratching my head and wondering what motivated the developer to do that.

Anyways, thanks for sharing!

 
SuhaSaha
Advisor
Advisor

Who likes T100 interface? Let's see some hands. It "confuses and infuriates us", so I immediately outfit my ZCX with a couple of methods that I'll actually use to pass along messages in a more practical fashion

✋🏽✋🏽✋🏽✋🏽✋🏽✋🏽

Why the hate? IMO, exception classes which implement IF_T100_DYN_MSG are quite easy to use. You don't need any bells & whistles to link the exception to a meaningful message. I especially like the USING MESSAGE addition which helps to convert classical exceptions into OO-exceptions.

 

LaurensDeprost
Contributor
Great feedback, jelena.perfiljeva2 Precisely the kind of discussion I was hoping for.
I suspect many developers get confused by when and how the exception classes should be created.

The difficulty in determining when to create a new global exception class or reuse an existing one is recognizable. I have struggled with this predicament since starting with ABAP development.
Who likes T100 interface?

I agree that the T100 interface can be confusing at times and can make code difficult to read. That said, I find that with recent releases, there have been significant improvements concerning passing messages to exceptions:
RAISE EXCEPTION TYPE cx_demo_dyn_t100
MESSAGE ID sy-msgid
TYPE sy-msgty
NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.

in ABAP 7.50 and 'USING MESSAGE' in 7.52 as mentioned by suhassaha.
I wouldn't say local exception is a bad idea but something about it feels off. If I was looking at the code that uses this, I'd be scratching my head and wondering what motivated the developer to do that.

I can certainly get that. Should I encounter local exception classes in productive code, I might find the code a bit off too. We should probably ask ourselves if we're not being a little bit too lazy when using them 🤔
Jelena
Active Contributor
0 Kudos
Yes, the DYN one is actually useful but it's implemented in a later release. We didn't have it in 7.31 system.
Jelena
Active Contributor
Thanks for a reply! I've just replied to Suhas that better interface is not available in earlier versions (as you've also noted, it's 7.52+). Well, even less reasons now to use a local exception class, I recon. 🙂
shais
Participant
0 Kudos
You may still the dynamic message in earlier releases,

but you'll have to do it manually:

Create a Z interface and set the value of T100 manually (the addition USING MESSAGE isn't available).
yunze-wang
Employee
Employee
0 Kudos

Hi Deprost,as per to the help documentation (https://help.sap.com/docs/SAP_NETWEAVER_AS_ABAP_752/bd833c8355f34e96a6e83096b38bf192/469ccf144e7d2c0...) of the latest version,the Local Definitions Referred by the Global Class SHOULDN'T be used anymore since Release 7.1 (SP4).

BR,

Yunze