2008 Apr 08 9:36 AM
Hi experts,
I want to determine what method is currently running.
Backgourd:
I have one implementaton of a BAdI method. In this method I want to call other methods of other classes that implement the BAdIs interface. This call must be dynamic.
For that reason I need to know what method of what class/interface is currently running. So that I can call the same method, but in another class.
Thanks for your help.
Best regards
Lars
2008 Apr 08 8:23 PM
Hello Lars
Did not read your question carefully enough. Below you see another sample coding which might do the trick.
*&---------------------------------------------------------------------*
*& Report ZUS_SDN_GET_CLASS_METHOD
*&
*&---------------------------------------------------------------------*
*& Thread: How to determine current method / interface method that is running?
*& <a class="jive_macro jive_macro_thread" href="" __jive_macro_name="thread" modifiedtitle="true" __default_attr="813014"></a>
*&---------------------------------------------------------------------*
REPORT ZUS_SDN_GET_CLASS_METHOD.
" BAdI ME_PROCESS_PO_CUST
DATA: go_badi type ref to IF_EX_ME_PROCESS_PO_CUST.
START-OF-SELECTION.
" Simulate instantiation of BAdI and calling of interface method
create object go_badi type ('ZCL_EX_ME_PROCESS_PO_CUST').
go_badi->initialize( ).
END-OF-SELECTION.
And here is the coding of the interface method:
METHOD if_ex_me_process_po_cust~initialize.
* define local data
DATA: lo_badi TYPE REF TO if_ex_me_process_po_cust,
lo_typedescr TYPE REF TO cl_abap_typedescr,
lo_classdescr TYPE REF TO cl_abap_classdescr,
ld_clsname TYPE string,
ld_msg TYPE bapi_msg.
data: lt_callstack type ABAP_CALLSTACK,
ls_callstack type ABAP_CALLSTACK_LINE.
CALL METHOD cl_abap_classdescr=>describe_by_object_ref
EXPORTING
p_object_ref = me
RECEIVING
p_descr_ref = lo_typedescr
EXCEPTIONS
reference_is_initial = 1
OTHERS = 2.
IF sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
CHECK ( lo_typedescr IS BOUND ).
** lo_classdescr ?= lo_typedescr.
ld_clsname = lo_typedescr->get_relative_name( ).
CONCATENATE 'Class' ld_clsname
INTO ld_msg SEPARATED BY ' = '.
MESSAGE ld_msg TYPE 'I'.
CALL FUNCTION 'SYSTEM_CALLSTACK'
* EXPORTING
* MAX_LEVEL = 0
IMPORTING
CALLSTACK = lt_callstack
* ET_CALLSTACK =
.
read table lt_callstack into ls_callstack index 1. " current block
message ls_callstack-blockname type 'I'.
ENDMETHOD.
Obviously, it does not make sense to use this coding in every interface method you are interested in. Instead place the coding into a static method and check which entry of the callstack (probably index = 2) you have to read.
Regards
Uwe
2008 Apr 08 12:48 PM
Hi,
Sorry I don't have an answer to your question, but this might solve your problem:
Did you try to set Multiple Use flag of your Enhancement Spot associated to your BAdI? Doing so, you will be able to call the relevant method of all active classes implementing the BAdI interface.
Regards,
Tanguy
2008 Apr 08 2:06 PM
Hi Tanguy,
I don't want to use multiple implementations, because the sequence the implementations are called can not be forced. So I want to use only one implementation and then call the other implementations via cunstomizing table.
The other reason is, that consultants often can not program ABAP and are not able to activate or deactivate such implementations. In customizing this is very easy for any consultant.
Best regards
Lars
2008 Apr 08 1:56 PM
Hello Lars
Here is a simple piece of coding which could be useful to you (assuming you have the RTTI classes available on your system):
*&---------------------------------------------------------------------*
*& Report ZUS_SDN_GET_CLSNAME
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zus_sdn_get_clsname.
DATA: gif_msglist TYPE REF TO if_reca_message_list,
go_typedescr TYPE REF TO cl_abap_typedescr,
go_classdescr TYPE REF TO cl_abap_classdescr,
gd_clsname TYPE string.
START-OF-SELECTION.
gif_msglist = cf_reca_message_list=>create( ).
CALL METHOD cl_abap_classdescr=>describe_by_object_ref
EXPORTING
p_object_ref = gif_msglist
RECEIVING
p_descr_ref = go_typedescr
EXCEPTIONS
reference_is_initial = 1
OTHERS = 2.
IF sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
CHECK ( go_typedescr IS BOUND ).
go_classdescr ?= go_typedescr.
gd_clsname = go_typedescr->get_relative_name( ).
WRITE: / 'Class =', gd_clsname.
END-OF-SELECTION.
Regards
Uwe
2008 Apr 08 2:08 PM
Hi Uwe,
I already use cl_abap_classdescr, but it will only return the name of the class. I need the name of the method, that I am currently running. Something like sy-repid, but this variable only contains the class name at this specific time.
Best regards
Lars
2008 Apr 08 8:36 PM
Lars,
wouldn't it just be better to deactivate all the other implementations and move everything over to ONE active implementation and then use a customizing table. In this way (customizing) you can also control the order in which the 'implementations' are called.
The other methods will be called anyway, and this way, they will be called twice. I'm not sure if this is what you want.
Sorry if this isn't really the answer you were looking for, but in my opinion it would be 'cleaner' coding.
2008 Apr 11 11:04 AM
Hi Micky,
this would perhaps be the usual way. But we have our own namespace for customer developments. And if I transport our "one and only" active implementation to the customer, the implementation can not be changed anymore (only as modification), if some new logic has to be developed.
I am looking for some lines of code, that I can put in any BAdI method. These lines of code should be able to call other methods of inactive BAdI implementations or classes that implement the BAdI's interface. All these calls should be dynamic.
So I have only one active BAdI implementation withing our own namespace active at the customer. All other BAdI methods should be called via customizing tables. This enables the customer to call methods of own Z-implementations of BAdIs or classes also via customizing, without modifying our code.
Best regards
Lars
2008 Apr 08 8:23 PM
Hello Lars
Did not read your question carefully enough. Below you see another sample coding which might do the trick.
*&---------------------------------------------------------------------*
*& Report ZUS_SDN_GET_CLASS_METHOD
*&
*&---------------------------------------------------------------------*
*& Thread: How to determine current method / interface method that is running?
*& <a class="jive_macro jive_macro_thread" href="" __jive_macro_name="thread" modifiedtitle="true" __default_attr="813014"></a>
*&---------------------------------------------------------------------*
REPORT ZUS_SDN_GET_CLASS_METHOD.
" BAdI ME_PROCESS_PO_CUST
DATA: go_badi type ref to IF_EX_ME_PROCESS_PO_CUST.
START-OF-SELECTION.
" Simulate instantiation of BAdI and calling of interface method
create object go_badi type ('ZCL_EX_ME_PROCESS_PO_CUST').
go_badi->initialize( ).
END-OF-SELECTION.
And here is the coding of the interface method:
METHOD if_ex_me_process_po_cust~initialize.
* define local data
DATA: lo_badi TYPE REF TO if_ex_me_process_po_cust,
lo_typedescr TYPE REF TO cl_abap_typedescr,
lo_classdescr TYPE REF TO cl_abap_classdescr,
ld_clsname TYPE string,
ld_msg TYPE bapi_msg.
data: lt_callstack type ABAP_CALLSTACK,
ls_callstack type ABAP_CALLSTACK_LINE.
CALL METHOD cl_abap_classdescr=>describe_by_object_ref
EXPORTING
p_object_ref = me
RECEIVING
p_descr_ref = lo_typedescr
EXCEPTIONS
reference_is_initial = 1
OTHERS = 2.
IF sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
CHECK ( lo_typedescr IS BOUND ).
** lo_classdescr ?= lo_typedescr.
ld_clsname = lo_typedescr->get_relative_name( ).
CONCATENATE 'Class' ld_clsname
INTO ld_msg SEPARATED BY ' = '.
MESSAGE ld_msg TYPE 'I'.
CALL FUNCTION 'SYSTEM_CALLSTACK'
* EXPORTING
* MAX_LEVEL = 0
IMPORTING
CALLSTACK = lt_callstack
* ET_CALLSTACK =
.
read table lt_callstack into ls_callstack index 1. " current block
message ls_callstack-blockname type 'I'.
ENDMETHOD.
Obviously, it does not make sense to use this coding in every interface method you are interested in. Instead place the coding into a static method and check which entry of the callstack (probably index = 2) you have to read.
Regards
Uwe
2008 Apr 11 11:05 AM
Hi Uwe,
your idea with the SYSTEM_CALLSTACK function module looks good. I will try this next week and then give you feedback.
Thanks.
Best regards
Lars
2008 Apr 14 10:12 AM
Hi Uwe,
I tested the function module SYSTEM_CALLSTACK. With the current call stack I can always determine which method is running.
Great idea !
Thanks.
Best regards
Lars