This is part three of the weblog series on the New Enhancement Framework. You get to know some more facts as to what a BAdI is and when to use it, and then, at last, we start with an example that shows you how to build the BAdI with the respective tools in the ABAP Workbench and how the code to instantiate and call the BAdI is integrated in the ABAP language.
In the last weblogs (Part 1: What the New Enhancement Framework Is For – Its Basic Structure and Elements For Beginn and The new Enhancement Framework Part 2 – What Else You Need to Know Before Building an Enhancement) you have learnt about the basic structure of an enhancement, the different enhancement technologies within the framework and the containers for enhancement options and enhancement implementation elements. You need to know them in order not to lose your bearings within the Enhancement Framework when we now start building a BAdI. If you have a mental map of the entities in the framework, you will find it really to easy to understand what is going on in the example. So I would recommend you should take your time to recapitulate theses basics, before proceeding to the practical part of this weblog.
Some Basics About the BAdI
Many of you know perhaps the classic BAdI. And there is some good news for them: The basic things about the BAdI itself have not changed a lot, though there are some major improvements, such as a gigantic step forward in performance. What will be totally new for those familiar with the classic BAdI is the way the new BAdI is embedded in the container-structure of the Enhancement Framework.
For those not acquainted with the classic BAdI, let me spend some words on what a BAdI is and what it is for:
The BAdI is an object-oriented enhancement option. The BAdI defines an interface that can be implemented by BAdI-implementations that are transport objects of their own. The new BAdI is fully integrated into the Enhancement Framework. Within the Enhancement Framework a BAdI is an enhancement option or an anchor point for an object plug-in.
A BAdI is to put it this way a controlled explicit enhancement option. It is an explicit enhancement option, which means: BAdIs are not provided by the framework, but they have to be defined explicitly by the developer. Why do I call it a controlled enhancement option. To understand what this means we have to go a bit deeper into the methodology of enhancing development objects. Why is it done, and who does it? What is the typical process of enhancing a development object like?
Providing and Implementing Enhancement Options – Two Different Roles
In this process there are two different roles: There is the so-called option-provider. He is the one who builds an enhancement option that is a hook where others can attach something to. And it is essential to have such a hook: Where there is no hook you cannot attach anything. This analogy means, that you can only insert an enhancement implementation where there is an enhancement option. Of course, there are implicit enhancement options, that are, so to speak, for free and always available. But there are not implicit BAdIs. If you need a BAdI, somebody has to define it explicitly. Let us call this role the (enhancement) option provider. In general, the option provider is identical with the developer of a development object that should offer an explicit enhancement option. Let us call this object the basic development object. Typically, the developer of the basic development object could be somebody working in the SAP core who anticipates that the customer or an industry solution might want to add some code at a particular point. In this case he creates both the development object to be enhanced at a later stage and defines an enhancement option.
An enhancement option that has no implementation does not do a lot when processed, in fact, it has no effect at all. To make something happen at an enhancement option, you need to implement it. The developer who implements an enhancement option, or to put it in the analogy, attaches something to the hook, is called the implementer. He need not care about the details of an enhancement option, but just know how he implements it. But, of course, he should have a sound knowledge of the way enhancement options function. You might compare this to somebody who uses a service class. He does not need to know the inside of this class, but just its public methods or maybe even only the respective interface he is interested in. In the same way, the implementer only needs a limited knowledge as to how to define an enhancement option.
In the strict sense, many of you are probably only interested in implementing a BAdI. They suppose that SAP provides the BAdI and calls the respective BAdI methods. All they want to know is what they have to take heed of when writing the BAdI implementation. But it is quite useful to know a bit more about defining a BAdI, and once you have understood what a powerful pattern a BAdI is, you might also be tempted to write your own BAdI definitions. Moreover, it would be a bit long-winded to write two different series of weblogs, one for the option provider and another one for the implementer, because there is a large overlap in the background knowledge. For all these reasons, I have decided to handle both topics in this one series. But still, I treat building the BAdI in this weblog and providing an BAdI implementation in the next one. And you should always keep in mind: Implementing and defining a BAdI are two different roles. And the same is true for source code enhancements.
The BAdI as a Controlled Enhancement Option
To fully grasp in which way a BAdI is a controlled enhancement option, let us first have look at source code plug-ins in contrast. This enhancement technology is not controlled at all. This means: The option provider inserts an enhancement point in the code thereby giving the possibility to attach a source code plug-in. The implementer can insert any code whatsoever at this enhancement point. The option provider has no control at all on the code that is written, because generally it is implemented at a later stage of development. Moreover the code of the source code plug-in has access to all the variables that are visible within the modularization unit that is enhanced. So the option provider cannot prevent the implementer from changing the value of some variables that should not be touched at all. In fact he cannot bar the implementer from anything at all.
With BAdIs, things are completely different. The option provider has a firm grip on what the implementer does insofar as he defines the interface and confines the implementer to the class that implements the BAdI. In detail this means: A BAdI defines the methods with their signature, that is, which parameters the respective method imports, exports, changes or returns. The BAdI implementer has to implement these methods defined in the BAdI interface. We could put it this way: With a BAdI the option provider defines what has to be done, but leaves it to the implementer how he implements the BAdI. Moreover, the BAdI implementer cannot fiddle with the basic program. It is assured that a BAdI implementation can only change the parameters handed over to BAdI. The implementation of a method has a context of its own and the variables of the development object using the BAdI are not even visible from inside the BAdI implementation.
BAdI Commands in ABAP
There are two ABAP commands for the new BAdI. GET BADI hugo returns a handle to all active instances of the implementations of the respective BAdI. For example hugo might refer to five active BAdI implementations.
You call a BAdI method with the command: CALL BADI hugo->method. If a method of the BAdI is called, all active implementations are selected. So this amounts to a loop with the different method calls in it.
When to Use a BAdI?
As a potential option provider you should use a BAdI if you already know that a particular procedure should be executed at a particular position in your program, but you want leave it to somebody else to specify the specific content of that procedure. This is typically the case if the details of the procedure vary among different potential implementers or are so specific that the developer of basic development object does not know them or want to give the possibility to add different implementations at a later stage.
So the developer of the basic development object just writes something like saying: subtract your fees and return the result. He does not care about what the different fees are and if there is a complex formula, percentages calculation or just a simple subtraction. To do this the option provider writes a BAdI which contains a method:
subtract_fees CHANGING costs.
This way, a BAdI can be used quite well to understand what enhancements are for from a semantic point of view. This is because the way BAdIs work is pretty much like our common sense concept of enhancing something. Usually we do not think: Just add any enhancement, but add something as a means to a particular end. You can decide yourself how you want to accomplish the end, but the end is defined. This is one analogy to explain a BAdI.
You might compare the usage of BAdIs also to the process when some company delivers the same car body to different manufactures of multi-purpose vehicles. They all build their specific vehicle on the same car body. The producer of the car body leaves the technical details to the different manufacturer, but of course it prescribes that the car suspension has to be build in here and the engine there. In this way, the engine has to be in a particular place and has to have particular properties, but all the other details are up to the manufacturer of the multipurpose vehicle.
This process can be compared to the process of multilevel software development I have already sketched: The program logic of a SAP core program needs some value at a certain point, but the developer of this program does not know how to calculate this value. So he inserts a method call that should provide this value, but leaves the actual implementation, that is the calculation to the developer of the next development level. In terms of this framework, the developer inserts an enhancement option that is a BAdI, providing the respective method in its interface, and also a call of a BAdI method.
Multiple and Single Use BAdIs
Concerning the programming model, there are two different BAdI types: Single- and multiple use BAdIs. They have a completely different semantics.
The use case with the calculation I have sketched above is a typical example of a single use BAdI. The basic program needs the result of a calculation. You leave the implementation details of the calculation to subsequent levels of development, for example the developers for the particular countries. The business logic requires a result of the calculation, and it must be exactly one result. The next steps in the program need this result, so you need at least one BAdI implementation. And there is no way to process many return values, so you need exactly one result. If you have a single use BAdI, the system takes care that there is exactly one active implementation. This way the call of the method of a single use BAdI functions like a method call.
Multiple use BAdIs are quite different in this respect. Such a BAdI is suitable for activities, that might be done or not and that might even be consecutively done in different ways in different implementations when a program is executed. Imagine you build a BAdI additional_output that might convert data for different additional output devices such as a Blackberry, handy, etc… Many different active implementations can coexist in the program simultaneously, but there might also be no active implementation. So the call of a method of a multiple use BAdI is in a way like sending a message: You do not know and do not care how many services react to the message. It corresponds to a publish and subscribe mechanism.
Building Our First BAdI
The Use Case
And now let us have a look at an example in detail. Imagine that the developer of the basic program needs the VAT of different book entries. These entries should be passed to a method that calculates and returns the VAT. As this developer does not know what the VAT in a specific country is, he defines a BAdI badi_vat with the method get_vat. This method should return the VAT for a particular value that is passed to the method get_vat.
Building the Enhancement Spot
The first thing you need when creating a BAdI is a container for the BAdI. Up to now we have no container, so we have to create a (simple) enhancement spot. This is the container in which we develop our BAdI.
We go to the ABAP workbench and navigate there to our local objects. We select:
from the context menu of the local objects folder.
This is what the dialog window looks like:
We enter a name for the enhancement spot and some short text. To name a composite enhancement spot is voluntary. We are content with our enhancement spot and need no higher level container for the example. In real life programming, you probably should take advantage of the structure the composite enhancement spots offer you and always work with these complex containers.
The BAdI Itself
Next we create a BAdI within the new enhancement spot. We select the CREATE icon on the left:
In the dialog window that appears we enter the BAdI name z_badi_calc_vat plus a short description and confirm. Now we have a BAdI in the list of our enhancement spot. We deselect the property “multiple use”, because for our calculation we need a single use BAdI:
The BAdI Interface
More important is the fact that up now we do not have much of BAdI. We need an interface. In fact, it is the interface where you define the methods that determine what use you can make of your BAdI. Understood this way, the interface makes up the identity of a BAdI to a large extent. After clicking the arrow in front of the BAdI name and after doubleclicking Interface in the tree below we can input the name of the interface. You can either choose the name of an interface that already exists or create a new one. There are no restrictions on the name of the interface enforced by the framework. But, of course, you should conform to the normal rules for choosing speaking names in a systematic manner.
Selecting the Change icon leads you to the class builder, where you can create the methods you need for your BAdI in the same way that you are used to if you are familiar with the class builder. We just type in the name of the method get_vat and enter the parameters we need.
A BAdI interface has to implement the interface if_badi_interface. But if we create a BAdI interface in the way just shown this marker interface is already integrated in the BAdI interface. Probably you know how to work with the class builder, but still I have inserted the following two screenshots to show you: Defining a BAdI interface is just normal ABAP Objects programming and as simple as could be for anyone familiar with the Class Builder. We define one BAdI method.
Next we determine the parameters of the method.
We save and activate the interface and the spot.
So let us now take a breath and consider what we have created so far:
We have created an enhancement spot and a BAdI with an interface. The interface has one method so far.
Of course, just building a BAdI does not suffice. It does not do anything. You need a BAdI instance, and this instance must be called somewhere in the code. This is the definition part of a BAdI. But as a BAdI only defines an interface, you need a class that implements this interface. Remember: A BAdI definition is the option to insert an object plug-in that does a job at runtime. You still need an object that is plugged in to get something done.
BAdI Commands in ABAP
So it is time to write some ABAP code to use the BAdI. We need a variable that can refer to the BAdI and some variables which are given as actual parameters to the BAdI method. Next we create a handle for that BAdI and call the BAdI method get_vat. The respective commands are GET BADI and CALL BADI.
DATA: handle TYPE REF TO z_badi_calc_vat, sum TYPE p, vat TYPE p, percent TYPE p. sum = 50. GET BADI handle. CALL BADI handle->get_vat EXPORTING im_amount = sum IMPORTING ex_amount_vat = vat ex_percent_vat = percent. WRITE: 'percentage:', percent, 'VAT:', vat.
If we run the program it dumps. Considering what I have told you before about the single use BAdI, this is no wonder. It is mandatory, that there is exactly one active implementation for a single use BAdI. Our BAdI is a single use BAdI. One way to handle this is to catch the respective exception cx_badi_not_implemented.
Using and Creating a Fallback Class
The other way is the better solution, namely to use a fallback class. A fallback class for a BAdI is used if there is no active BAdI implementation. This means: The GET BADI command returns a handle to an instance of the fallback class and the respective CALL BADI calls the methods of the fallback class instance. As soon as there is an active BAdI implementation, the fallback class is not used any longer at runtime. So using a fallback class serves two functions at once:
- The program runs with a single use BAdI without raising an exception.
- It is guaranteed that the fallback class is not used any more as soon as a BAdI implementation is supplied. So a fallback class is only selected conditionally. This is important, because the BAdI provider does usually not know the details of some process. This is why a BAdI is used.
We select the checkbox the bottom with the text: Call fallback class if no implementation is executed and insert a name for the class.
Clicking the change icon leads us to the class builder. Again the tools do a great job for you: The respective method of the BAdI interface is already defined. We only have to implement it:
DATA: percent TYPE p VALUE 20. ex_amount_vat = im_amount * percent / 100. ex_percent_vat = percent.
I skip this, because it is no news to anybody familiar with the Class Builder. Of course, we have to save and activate the class. Then we navigate back to the enhancement spot and activate it.
Running the program again leads to result:
percentage: 20 VAT: 10.
And this is the end of this weblog. Now, you know how to build an enhancement spot and a BAdI including the BAdI interface and a fallback class plus the ABAP commands to use the new BAdI. In the next weblog you learn how to create a BAdI implementation inside the respective container, that is the (simple) enhancement implementation and how to select among the different BAdI implementations using the addition FILTER to the GET BADI command.