Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

COMMIT CL_BCS e-mail in BACKGROUND TASK

Tomas_Buryanek
Product and Topic Expert
Product and Topic Expert
7,539

Hello,

I am building custom wrapper class to send e-mails. Inside it uses CL_BCS.

Problem is, that there is need to COMMIT after cl_bcs->send( ). But direct COMMIT is not possible in most user exits and BADIs.

Usually this is solved by RFC module which contains whole sending part of code and called IN BACKGROUND TASK. But now I want to create simple and reusable way to do this.

I was thinking about simple RFC module with input of TYPE REF TO cl_bcs. Inside just call ->send, commit and return result. But RFC module can not have TYPE REF TO parameter.

My question:

Is there any elegant method how to commit CL_BCS SEND to not interfere with user exits/BADI update task? Any tips, ideas..? 🙂

-- Tomas --
1 ACCEPTED SOLUTION
Read only

Tomas_Buryanek
Product and Topic Expert
Product and Topic Expert
0 Likes
5,892

So far only discovered option to encapsulate cl_bcs e-mail logic in different LUW is RFC (and calling it in destination 'NONE', background etc..). 😞

Some examples I found in standard code:

CRM_EMAIL_SEND_EMAIL - RFC


* -> call mail sending via RFC to create a new 'comittable' LUW

   CALL FUNCTION 'CRM_EMAIL_SEND_EMAIL' DESTINATION 'NONE'

---

* logic in an RFC module as a commit work needs to be carried out in order

* to send a send request from BCS. The RFC creates a new LUW which ensures

* - no interference with application data which is waiting to be commited

* - no interference with 'object pool' applications like the one order, where

*   commit logic is changed

BCS_TEST23 - demo program, but it uses "old" SO function:


"Sending on-commit through RFC"


CALL FUNCTION 'SO_NEW_DOCUMENT_ATT_SEND_API1'

     DESTINATION 'NONE'

-- Tomas --
22 REPLIES 22
Read only

Former Member
0 Likes
5,892

This message was moderated.

Read only

Tomas_Buryanek
Product and Topic Expert
Product and Topic Expert
0 Likes
5,892

Thanks, but there is no helpful info for me.

-- Tomas --
Read only

LukaszPegiel
SAP Champion
SAP Champion
0 Likes
5,892

Hi Tomas,

try with this:

   try.

        data: transaction_mgr type ref to if_os_transaction_manager.

        data: transaction type ref to if_os_transaction.

        transaction_mgr = cl_os_system=>get_transaction_manager( ).

        transaction = transaction_mgr->get_current_transaction( ).

        transaction->set_mode_update( oscon_dmode_direct ).

      catch cx_root.

    endtry.

    set update task local.

    your code

    commit work.

I use this in some user exits

Read only

Tomas_Buryanek
Product and Topic Expert
Product and Topic Expert
0 Likes
5,892

Thanks! This is new to me and very interesting. And probably will do the job 🙂 Let me try it...

Here is SAP HELP for this if anybody also interested:

Components of the Transaction Service - ABAP - Object Services - SAP Library

-- Tomas --
Read only

SuhaSaha
Product and Topic Expert
Product and Topic Expert
0 Likes
5,892

Hi Lukas,

Nice idea to use Transaction OS

I always had this idea to use them, but never quite got a chance to!

Shouldn't the SET_MODE_UPDATE method be OSCON_DMODE_LOCAL.

BR,

Suhas

Read only

0 Likes
5,892

In my cases because of compatibility mode I could not use OSCON_DMODE_LOCAL, but the output is the same.

Read only

Tomas_Buryanek
Product and Topic Expert
Product and Topic Expert
0 Likes
5,892

I will have to study this little bit more. Having problem with compatibility mode.

Getting exception: "You cannot set the update mode to "local" in compatibility mode".

Trying this (steps as time goes):

lets say in user exit/BAdI

- UPDATE ztab. "not commited

- call ZCL_EMAIL send method

     Inside:

     - set OSCON_DMODE_LOCAL throws exception

     - CL_BCS mail

     - COMMIT WORK.

- end of call ZCL_EMAIL send method

- here ztab should not be updated yet

-- Tomas --
Read only

0 Likes
5,892

use direct mode when you go to the code of cl_os_transaction method IF_OS_TRANSACTION~SET_MODE_UPDATE then you'll notice that when you'll choose direct mode then it will work same as local.

Read only

Tomas_Buryanek
Product and Topic Expert
Product and Topic Expert
0 Likes
5,892

Not it does not throw exception with OSCON_DMODE_DIRECT. But does not help with commit (ztab update is commited with ZCL_MAIL inner commit).

-- Tomas --
Read only

0 Likes
5,892

Then I need to do some test, I'll try to do it in the evening.

Read only

Tomas_Buryanek
Product and Topic Expert
Product and Topic Expert
0 Likes
5,892

OK, thanks a lot. I am testing too.

Tried logic which is in DEMO_TRANSACTION_SERVICE program: create_transaction(), start(), end(), but no success...

One new thing I found: add_attachment method of bcs_document also commits.

So whole e-mail construction from start to send needs to be separated.

-- Tomas --
Read only

0 Likes
5,892

I've tried several times and it seems it was working for me as I have only one update/delete/insert statement, so in fact I could only call simply 'set update task local' in this case without using transaction manager.

I've read cl_os_transaction documentation few times now and it seem that 'commit work' commits changes of all level of transaction manager, means top level + subtransactions so it will not help in your case.

At the moment I think there is no other case but running the RFC module in background task or update task as has mentioned , so your wrapper class would need to have some FG to call FM with specified parameters to be able to recreate the cl_bcs object after FM call. I know it's quite annoying, but at the moment seems the only way.

But anyway I'll keep on trying....

Read only

Tomas_Buryanek
Product and Topic Expert
Product and Topic Expert
0 Likes
5,892

Thank you for effort! Yea it seems bad. I searched prior starting this topic, and found only RFC way 😞

It means to pack whole thing into RFC, all interfaces (subject,recipients,attachment table, etc.) 😞 Since whole cl_bcs e-mail creating needs to be separated (not only last COMMIT after ->send() ).

-- Tomas --
Read only

SuhaSaha
Product and Topic Expert
Product and Topic Expert
0 Likes
5,892

Usually this is solved by RFC module which contains whole sending part of code and called IN BACKGROUND TASK.

IMHO, this is a better solution! You are decoupling (SoC) the sending Email functionality from the BAdI.

What do you think?

Read only

Tomas_Buryanek
Product and Topic Expert
Product and Topic Expert
0 Likes
5,892

Sending e-mail functionality can be in separate BAdi implementation (if supported). And in separate new BAdi method. Or in some other Z*class. Is not it enought for "SoC"?

The problem is separation of LUW/update, so my e-mail commit will not interfere with place where is e-mail called.

-- Tomas --
Read only

rosenberg_eitan
Active Contributor
0 Likes
5,892

Hi,

I am quite sure that all CL_BCS supporters are following this thread with much interests.

At the end of it IMHO it would be very helpful if a blog post or a document will be posted with working sample code.

Maybe this will help to promote the use of CL_BCS instead of using SO_NEW_DOCUMENT_ATT_SEND_API1...

Regards.

Read only

Tomas_Buryanek
Product and Topic Expert
Product and Topic Expert
0 Likes
5,893

So far only discovered option to encapsulate cl_bcs e-mail logic in different LUW is RFC (and calling it in destination 'NONE', background etc..). 😞

Some examples I found in standard code:

CRM_EMAIL_SEND_EMAIL - RFC


* -> call mail sending via RFC to create a new 'comittable' LUW

   CALL FUNCTION 'CRM_EMAIL_SEND_EMAIL' DESTINATION 'NONE'

---

* logic in an RFC module as a commit work needs to be carried out in order

* to send a send request from BCS. The RFC creates a new LUW which ensures

* - no interference with application data which is waiting to be commited

* - no interference with 'object pool' applications like the one order, where

*   commit logic is changed

BCS_TEST23 - demo program, but it uses "old" SO function:


"Sending on-commit through RFC"


CALL FUNCTION 'SO_NEW_DOCUMENT_ATT_SEND_API1'

     DESTINATION 'NONE'

-- Tomas --
Read only

0 Likes
5,892

Hi,

Maybe a combination of using "ABAP Objects Share Memory Enable (SHMA)" as the carrier of the pay load (email content + local cl_bcs to do the actual sending) and a very simple update function that will call a method for the send will do the trick .

I have not try it .

Regards.

Read only

0 Likes
5,892

I have found that cl_document_bcs-add_attachment( ) commits LUW too (in FM SDOK_COMMIT). And maybe some other methods... So there goes simple function 😞

-- Tomas --
Read only

0 Likes
5,892

Hi,

I was thinking more of a way of just storing the data in the shared object .

I do not know if behind the scene SAP is doing a commit in this case.

Regards.

Read only

0 Likes
5,892

Tomas,

I think I found it.... instead of cl_bcs use CL_BCS_MESSAGE. This does not commit nothing until you call send method and you have choice if you want to do it in update task (method SET_UPDATE_TASK). During save method it checks if you want update task or not and then it calls FM SBCS_SEND or SBCS_SEND_UPDATE. Seems like no wrapper function is needed for that (as long you don't want to pimp this class).

Example of usage can be found in program RSBCS_EXAMPLE_EMAIL.

Read only

0 Likes
5,892

Wow thats great Łukasz

I don't have time for bigger testing now. But It looks like it is it.

All methods like add_attachment etc. are just setting private atribute data of main class object.

And both SBCS_SEND* functions are actually wrappers we were talking about (the only solution of calling RFC in DESTINATION NONE or IN UPDATE TASK with all email data).

-- Tomas --