badi - good introduction
Post on 14-Oct-2015
Embed Size (px)
DESCRIPTIONBADI - Good Introduction
The time for me to have a BADi of my ownSergey KorolevBusiness CardCompany:self employedPosted on Mar. 14, 2005 01:27 PM inABAP
Step-by-step process of creating your own BADI definition
BADi is an object oriented version of SAP enhancement concept. Its main idea is that instead of filling special includes with ABAP code in some customer functionEXIT_SAPxxxxxxstyle='_nnnstyle=',you are to define some ABAP object class which implements a particular interface (BADi interface) a set of predefined method declarations.
What are the pros of the BADi concept besides the fact it is object-oriented (though I know some people think OO overweighs all others pros and cons)? At my recent project I was assigned a role of a development team leader and so I was aware of software engineering management. And from this point of view BADI is much better than customer exits. Sometimes more than one developer has different tasks which include programming of the same customer-exit. One of the possible consequences is a mixture of the code provoking errors, transport request locking problems, etc. On the contrary, a particular BADI can have several independent implementations, and so different tasks can be safely separated with no source code conflicts or request deadlocks.
And one more idea... There are still lots of questions on various SAP ABAP forums (including SDN) concerning ways of searching possible enhancements of one or another business transaction. BADi gives you one stable method of searching: just place a break-point inside the methodCL_EXITHANDLER=>GET_INSTANCEstyle=' and then execute the business transaction. After the program stops at the break-point you can easily obtain BADi name and browse the source code around the call point to get the most exact knowledge of terms and conditions of the BADi call.
In our project we had to implement HR functionality, and there were several development tasks including default value calculations for various infotypes (infotype is a time dependent chunk of a person attributes e.g. personal data, address data, etc., infotype has its unique four-digit code).
In transaction SMOD you can find a customer enhancement designed for this kind of task -PBAS0001. The enhancement contains function moduleEXIT_SAPFP50M_001, which is commonly used for setting infotype defaults, and EXIT_SAPFP50M_002for additional checks after a user has entered values into infotype fields. Both user-exits have their counterparts in BADiHRPAD00INFTY. These are corresponding methodsIF_EX_HRPAD00INFTY~BEFORE_OUTPUTandIF_EX_HRPAD00INFTY~AFTER_INPUTand they are called from nearly the same call-up points of the source code.
It would be nice to use them, but the matter is that those methods have only importing parameters and obviously they were not intended to change infotype values.
And after hard reflections and mental sweating on possible ways of the tasks separation I found a solution to create my own BADI and call it from theEXIT_SAPFP50M_001andEXIT_SAPFP50M_002.
So, lets start with transaction SE18. At the initial screen I entered the name ZPBAS0001_BADI_FLTand clicked the buttonCreate.
By checkingMultiple usecheckbox I allowed my BADI to have multiple implementations, and that is the main goal of the proceeding. Now each developer (informed of the BADI existence) can create his/her own fully independent implementation.
But here we can improve the BADI. As we make developments for HR functionality the infotype code will always be involved. Different infotypes have different structure and we cannot make universal code for calculating default values. What I am leading to is that every implementation of the newly created BADI will be essentially infotype dependent. In that case I bet the very first statement of every implementation would be
>CHECK> infty =some_infotype_number.
Thus infotype code is an ideal candidate to become a filter value for implementations. In theAttributestab of the BADI definition you can see a checkboxFilter-depend. The checkbox turns on filter capabilities of the BADI.
To finalize definition of filter dependent BADI we have to enter some data element name intoFilter typefield, and the data element has to accept infotype codes as a value.
There are special requirements for the data element to be used as aFilter type. It has to be associated with some Search help, and one of the import parameter of the search help must be of the same type as data element. So, I was not successful when tried hastily to enter INFTY data element into theFilter typefield as it has no associated Search help. I did not find proper SAP standard data element (maybe I did not search thoroughly) and had to create one of nameZINFTY_FLT.
Also I have created a Search helpZH_T582A_BADIwith export parameter of typeZINFTY_FLT.
Finally, I associated previously created Search help with new Data element.
After that I could successfully enter the name of my Data element as the Filter type of the BADI.
To be honest, the requirement looks odd. At least, I do not clearly understand the reason for an idea of obligatory Search help connection. Certainly defining filter values with Search help is convenient but whats wrong if one can enter values manually?
Why use Filtering? One can think that all the mess is about getting rid of oneCHECKstatement. But do not forget that without filtering every time the BADI fires it creates class instances for all implementations defined and that costs.
Now its time to define methods of the BADI interface. It is done in theInterfacetab of BADI definition. Here I can enter method names. Being not much eccentric I called themGET_DEFAULT_VALUESandCHECK_BEFORE_UPDATE.
By double clicking at the method name we are driven into a common class/interface designer (SE24). And here we define all the method parameters. Note that each method has one predefined import parameter FLT_VAL of type ZINFTY_FLT for we defined the BADI as filter dependent.
Now the definition of the BADI seems to be completed and we can click the buttonSave. As a result the BADI interface will be activated and a special proxy class will be generated and also activated.
At the call-up point
The BADI now is almost ready for an implementation. The final stroke is to call it up somewhere. At the beginning ofEXIT_SAPFP50M_001function module we insert a special aided fragment of code. First, by calling methodCL_EXITHANDLER=>GET_INSTANCEstyle=' we obtain an instance of the proxy class, implementing BADI interface, and examine whether or not any implementation exists.
If it does, then we call appropriate method of the interface instance which does the rest. Note that before the call we calculate proper filter value, and in this case it is an infotype code. At the first glance it seems slightly odd that we place a single call to the BADI method while it was defined asMultiple use. No internal tables, no loop. Actually the interface instance is the instance of the proxy class which was generated after saving BADI definition. Each proxy class method contains a standard code snippet which finds and calls all the implementations complying with filter value.
Global data declarations:
DATA: act_imp_existingTYPEsxrt_boolean, pbas0001_badi_instanceTYPEREFTOzif_ex_pbas0001_badi.CONSTANTS: c_exit_nameTYPEexit_defVALUE'ZPBAS0001_BADI'.
>*&---------------------------------------------------------------------**& Include ZXPADU01 **&---------------------------------------------------------------------**"----------------------------------------------------------------------*"*"Lokale Schnittstelle:*" IMPORTING*" VALUE(TCLAS) LIKE PSPAR-TCLAS*" VALUE(INNNN) LIKE PRELP STRUCTURE PRELP*" VALUE(IPSYST) LIKE PSYST STRUCTURE PSYST*" VALUE(I001P) LIKE T001P STRUCTURE T001P*" VALUE(I503) LIKE T503 STRUCTURE T503*" EXPORTING*" VALUE(INNNN) LIKE PRELP STRUCTURE PRELP*" CHANGING*" REFERENCE(IPREF) LIKE PREF STRUCTURE PREF*"----------------------------------------------------------------------
IFpbas0001_badi_instanceISINITIAL.CALLMETHODcl_exithandler=> get_instanceEXPORTING exit_name = c_exit_nameIMPORTING act_imp_existing = act_imp_existingCHANGING instance = pbas0001_badi_instanceEXCEPTIONS no_reference = 1 no_interface_reference = 2 no_exit_interface = 3 class_not_implement_interface = 4 single_exit_multiply_active = 5 cast_error = 6 exit_not_existing = 7 data_incons_in_exit_managem = 8 OTHERS = 9.
IFsy-subrc 0.MESSAGEIDsy-msgidTYPEsy-msgtyNUMBERsy-msgnoWITHsy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.ENDIF.ENDIF.
IFNOTact_imp_existingISINITIAL.CALLMETHODpbas0001_badi_instance-> get_default_valuesEXPORTING tclas = tclas ipsyst = ipsyst i001p = i001p i503 = i503 flt_val = innnn-inftyCHANGING innnn = innnn ipref = ipref.ENDIF.
To create a BADI implementation we start SE19 transaction. After entering implementation name and BADI definition name you also can manually enter the name of the class already existent which will implement the BADI, or the system can generate it automatically.
Strange enough, for some reason or another a single class cannot be used for implementing more than one BADI, in spite the fact that a class can implement arbitrary number of interfaces. There could be circumstances when it is convenient to use a single class to implement more than one BADI. Lets treat it as an item to a wish list for coming versions of ABA