2016 Jan 12 9:45 AM
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..? 🙂
2016 Jan 19 9:28 AM
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'
2016 Jan 12 10:14 AM
2016 Jan 12 11:42 AM
2016 Jan 12 10:56 AM
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
2016 Jan 12 11:39 AM
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
2016 Jan 12 12:20 PM
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
2016 Jan 12 12:41 PM
In my cases because of compatibility mode I could not use OSCON_DMODE_LOCAL, but the output is the same.
2016 Jan 12 3:11 PM
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
2016 Jan 12 3:25 PM
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.
2016 Jan 13 7:22 AM
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).
2016 Jan 13 8:35 AM
Then I need to do some test, I'll try to do it in the evening.
2016 Jan 13 8:49 AM
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.
2016 Jan 13 8:28 PM
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....
2016 Jan 14 7:58 AM
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() ).
2016 Jan 12 12:15 PM
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?
2016 Jan 12 2:42 PM
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.
2016 Jan 13 7:36 AM
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.
2016 Jan 19 9:28 AM
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'
2016 Jan 19 10:07 AM
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.
2016 Jan 19 12:17 PM
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 😞
2016 Jan 19 12:24 PM
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.
2016 Feb 06 4:05 PM
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.
2016 Feb 09 6:59 AM
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).