Technical Articles
Objectify: ABAP Objects Model for BDC
Update 6 May 2014: Updated method parameters following Objectify’s naming convention. Updated Github repository link to Project Objectify
This is my first contribution to Project Objectify which is being “revived” by Bruno Esperança.
This an Object-Oriented approach for BDC processing. I’m aware that there is already a model published here but this is my own attempt at the design which includes the functionality to process the BDC via Call Transaction or Batch Input Session.
I develop in ABAP Objects wherever I can, so this is one of the classes where I bring along to every new project I start on as it is highly reusable. I am aware of the never-ending debate between developing ABAP in OO vs. procedural in SCN, but I will not get into that here. Please feel free to reuse this model and/or leave any comments if it can be improved any further.
Source Code
The corresponding objects and code for this article can be found in the following public repository on Github.
GitHub repository for BDC Model
Class Design
The design of the class is based on the Singleton pattern whereby there can be only 1 active instance of the class in a single session.
Methods
The screenshot below displays the methods available in the class.
Methods Explanation
1) Instantiation
Instantiation of the class is via static method S_INSTANTIATE, whereby the type of processing (CT = Call Transaction, BI = Batch Input) and related T-Code are mandatory inputs.
Additionally, other parameters are available for finer control of the BDC processing. All the input values are stored into the instance’s private attributes.
2) Construct BDC table
Once the class is instantiated, instance methods ADD_FIELD and ADD_SCREEN are used to construct the BDC table.
3) BDC Processing
After the BDC table has been fully populated, instance method PROCESS is used to process that data. Depending on the processing type (CT/BI), private methods CALL_TRANSACTION or CREATE_BATCH_INPUT_SESS will be executed.
4) Reset BDC table
If there is a need to execute the same BDC T-Code multiple times (i.e. in a loop), instance method CLEAR_BDC_DATA can be used to clear the BDC table so that it can be reconstructed again.
5) Garbage collection
Finally, if the BDC instance is no longer required during an internal session, static method S_FREE_INSTANCE can be used to free the instance of the singleton, which then allows the memory to be freed during the next run of the garbage collector.
Usage Example
Below is an example of a simple report program to illustrate the usage of the class. It shows both processing by Call Transaction and Batch Input Session.
*&———————————————————————*
*& Report ZESY_CALL_OO_BDC
*&
*&———————————————————————*
REPORT zesy_call_oo_bdc.
*———————————————————————-*
* Selection Screen
*———————————————————————-*
PARAMETER:
p_kunnr TYPE kna1-kunnr DEFAULT ‘2400’,
p_vkorg TYPE knvv-vkorg DEFAULT ‘1000’,
p_vtweg TYPE knvv-vtweg DEFAULT ’10’,
p_spart TYPE knvv-spart DEFAULT ’00’.
SELECTION-SCREEN SKIP 1.
PARAMETER:
p_delblk TYPE kna1-lifsd DEFAULT ’01’,
p_bilblk TYPE kna1-faksd DEFAULT ’01’.
SELECTION-SCREEN SKIP 1.
PARAMETER:
p_tran RADIOBUTTON GROUP r1 DEFAULT ‘X’,
p_sess RADIOBUTTON GROUP r1.
*———————————————————————-*
* Data Declarations
*———————————————————————-*
DATA:
g_bdc TYPE REF TO zcl_bc_bdc,
g_messages TYPE tab_bdcmsgcoll,
g_message LIKE LINE OF g_messages,
g_subrc TYPE sy-subrc,
g_exception TYPE REF TO zcx_batch_input_error,
g_error TYPE string.
*———————————————————————-*
* Initialization
*———————————————————————-*
*INITIALIZATION.
*———————————————————————-*
* Start of Selection
*———————————————————————-*
START-OF-SELECTION.
* Create an object for BDC
IF p_tran = ‘X’.
g_bdc = zcl_bc_bdc=>s_instantiate( im_bdc_type = ‘CT’
im_tcode = ‘VD05’ ).
ELSEIF p_sess = ‘X’.
g_bdc = zcl_bc_bdc=>s_instantiate( im_bdc_type = ‘BI’
im_tcode = ‘VD05’
im_group = ‘MY_SESSION’
im_keep = ‘X’
im_holddate = ‘20140528’ ).
ENDIF.
* Populate first screen
g_bdc->add_screen( im_repid = ‘SAPMF02D’ im_dynnr = ‘0507’).
g_bdc->add_field( im_fld = ‘BDC_OKCODE’ im_val = ‘/00’).
g_bdc->add_field( im_fld = ‘RF02D-KUNNR’ im_val = p_kunnr ).
g_bdc->add_field( im_fld = ‘RF02D-VKORG’ im_val = p_vkorg ).
g_bdc->add_field( im_fld = ‘RF02D-VTWEG’ im_val = p_vtweg ).
g_bdc->add_field( im_fld = ‘RF02D-SPART’ im_val = p_spart ).
* Populate second screen
g_bdc->add_screen( im_repid = ‘SAPMF02D’ im_dynnr = ‘0510’).
g_bdc->add_field( im_fld = ‘BDC_OKCODE’ im_val = ‘=UPDA’).
g_bdc->add_field( im_fld = ‘KNA1-LIFSD’ im_val = p_delblk ).
g_bdc->add_field( im_fld = ‘KNA1-FAKSD’ im_val = p_bilblk ).
*———————————————————————-*
* End of Selection
*———————————————————————-*
END-OF-SELECTION.
IF p_tran = ‘X’.
g_bdc->process( IMPORTING ex_subrc = g_subrc
ex_messages = g_messages ).
* Display processing status
IF g_subrc = 0.
WRITE:/ ‘Success:’.
ELSE.
WRITE:/ ‘Error:’.
* Display messages in list
LOOP AT g_messages INTO g_message.
MESSAGE ID g_message-msgid
TYPE g_message-msgtyp
NUMBER g_message-msgnr
WITH g_message-msgv1
g_message-msgv2
g_message-msgv3
g_message-msgv4
INTO g_error.
WRITE:/ g_error.
ENDLOOP.
ENDIF.
ELSEIF p_sess = ‘X’.
TRY.
g_bdc->process( ).
WRITE: ‘Success: Check session in SM35’.
CATCH zcx_batch_input_error INTO g_exception.
WRITE:/ ‘Error creating batch input session:’.
MESSAGE ID g_exception->msgid
TYPE ‘E’
NUMBER g_exception->msgno
WITH g_exception->msgv1
g_exception->msgv2
g_exception->msgv3
g_exception->msgv4
INTO g_error.
WRITE:/ g_error.
ENDTRY.
ENDIF.
Hello,
First-of-all, kudos for your submission to project Objectify 🙂
Would it not have been flexible to have a FACTORY method & return the instance based on whether the developer wanted to use BDC/Call Transaction?
The method PROCESS( ) had to be in the BDC & Call Transaction classes accordingly. I think that would make the solution more flexible to use.
What is your opinion?
BR,
Suhas
PS - Sorry for being critical, ol' habits die hard 😛
Hi Suhas
Thanks for your feedback - don't worry, constructive criticisms are always welcome, it is these that help oneself grow 🙂
When I modelled this in the past, my idea was to have a simple class that is able to handle both Call Transaction and Batch Input, hence it was all in one class. The PROCESS( ) method can then be invoked independent of whether it was CT or BI.
I'm interested to understand how having having a factory method and separate classes would make it more flexible. Can you elaborate with maybe a use-case?
Thanks!
Eng Swee
Hello Eng Swee,
This is what i meant -
Just an idea. Not sure if it can be applied to this specific use case.
BR,
Suhas
Hi Suhas
Thanks for the info. I think I get you now - I think you are suggesting modelling it with the Strategy Pattern, which is also similar to the IDoc framework model that I posted previously, right?
I agree with you that the strategy pattern is definitely more flexible especially for extending the behaviours of the class in the future. However, for this specific case, I can't foresee there being more than the 2 behaviours (Call transaction and Batch Input.)
Anyway, it is definitely a point to ponder! When I get some time in my hands, I might redesign this to make it a more robust model 🙂
Rgds
Eng Swee
Strategy pattern it is, indeed! I should have mentioned it, my bad 😳
I see how design patterns help developers think on identical terms.
Cheers,
Suhas
Fantastic 🙂
I wonder if it's possible to "fork" this and add this class in a folder in the project object github 😕
Or, alternatively, if you would contemplate being a contributor to project object and adding it there directly!
Thanks 🙂
Best,
Bruno
Also, as I have discussed with Florian Henninger, would be great if contributions to the project followed *at least* the naming conventions mentioned here:
Naming Conventions in ABAP Objects - ABAP Workbench Tools - SAP Library
Just to try and make it something as consistent as possible. I'm not asking you to change what you've done already, but maybe in the future you could think about it ^_^
Thanks!!
Best,
Bruno
Hi Bruno
Can you add me as a contributor to your existing Project Object repository? I will then move the codes there. I'm not that familiar of how the fork function works in Github yet...
Thanks for the naming convention link.
For method parameters, this other Help SAP document suggests the following instead of IM, EX, CH, RE. Any thoughts on which one to stick to?
ABAP Keyword Documentation
Rgds
Eng Swee
Hi again!
I have now added you as a contributor 🙂 You should have full access, let me know if you haven't. I'm not sure how this works either! Hopefully someday we will understand better how github works 🙂 I'm guessing I have to block some time to look into it properly.
Regarding the naming convention on parameters, I was using the one you shared. Then I found out the one I shared above. Apparently one is for OO and the other is for reports. So I think it makes more sense if we use the one for OO, with IM, EX, etc.
(If you look at the classes in the repository at the moment they have the same naming convention you used... but in the future I'll be using the IM, EX naming convention, if "everyone" in the project agrees!
Thanks!!
Best,
Bruno
Hi Bruno
Thanks for sorting out the Github access. I have now moved the codes over.
I'm fine with the IM, EX convention, so I've also updated the codes with that too, it was just a quick tweak.
Thanks again!
Eng Swee
Great!
Welcome to the team 🙂
I guess I'll change the "signature" in the readme file to "The Project Object Team" 😛
Best regards,
Bruno
can you show me the source code of ZCX_BATCH_INPUT_ERROR,ths
Hi Weiqiong,
That is an exception class with attributes MSGID, MSGNO, MSGV1-4. There is no other source code for it as it is auto generated by the system when the class is created.
Rgds
Eng Swee
i get it ,thank you!
Hi Eng Swee,
I extracted the ZCX_BATCH_INPUT_ERROR class from the NUGG_BDC_MODEL.nugg file.
It would be nice if you would include the ZCX_BATCH_INPUT_ERROR as .txt file (in the objectify project, too).
Regards
Guido
In the method called add_field you have a rutine to handle the date conversion from internal to external.
You should also have a routine that can handle the same for an amount/quantity field depending on how the user is configured with decimal point ( . or , ) and at the same time left justify the field to aviod the error "A screen field was supplied with longer field contents by batch input."
Hi,
FM MOVE_CHAR_TO_NUM can be used for this.
Kim, maybe you could work on it? 🙂
Cheers,
Bruno
Thanks for the feedback Kim.
Unfortunately in my current project, I am not involved in ABAP developments so I won't be getting around to enhancing that for a while.
As suggested by Bruno, in the spirit of the community and Project Objectify, maybe you can help to enhance it?
Rgds
Eng Swee
Hi. Good job. But I had little to add support to convert defsize. 🙂
Hi i tried this code but it isnt working for me.
I get the error:
But i copied the whole code. And i created the second exception class with following attributes.
Hello, I need to use this approach, but for a lot of register in a batch input session, how can I do it ?, because the example is for one record. how can the program separate the transactions.
Thanks in advance.