Database update committed despite BAPI_TRANSACTION_ROLLBACK - abap

I have a Modify statement to update a custom table after which I am calling BAPI_CONTRACT_CHANGE. When BAPI failed to change the document it's calling BAPI_TRANSACTION_ROLLBACK. However, it's not changing the data back in my custom table which was updated by Modify statement.
IF gt_return[] IS NOT INITIAL.
READ TABLE gt_return INTO gwa_return WITH KEY type = 'E'.
IF sy-subrc EQ 0.
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
MESSAGE i021(zxx).
ELSE.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
EXPORTING
wait = abap_true.
ENDIF.
ENDIF.
Appreciate your response.
Modify statement is present somewhere before the bapi call.and also this program can be run from external portal . The behaviour is as expected when I run it from the portal i.e, BAPI_TRANSACTION_ROLLBACK works and data doesn't get updated in the custom table. It fails only when I run it from ECC.

You get an implicit commit on each PBO screen interaction.
So any user interaction after the Insert/modify/update DB will be committed without code needing to issuing a commit work.
if you want to rollback , it must be done before the next PBO cycle.

Related

VA01 BDC_OKCODE /00 not working as expected

In my report I am calling the transaction VA01 with BDC data, and everything works as expected, the data is being filled correctly, but bdc_okcode /00 does not work.
I simply add the ok-code to the internal table:
gs_bdcdata-fnam = 'BDC_OKCODE'.
gs_bdcdata-fval = '/00'.
APPEND gs_bdcdata TO gt_bdcdata.
...
CALL TRANSACTION 'VA01' USING gt_bdcdata.
I get a popup that shows the ok code.
My expectation is that it should navigate to the next dynpro.
Also I tried to record the transaction through the transaction SHDB to see if I have to do something differently but the BDC data is basically the same. Playing back the recording shows the same popup with the code.
How can I solve that?
The MODE addition is not used by the CALL TRANSACTION.
If one of the additions MODE or OPTIONS FROM is not used, the effect is the same as if mode had the content "A". Which means the call transaction stops by each screen.
It has to be called like this:
DATA lv_mode TYPE char1 VALUE 'N'. "N - BI won't stop, E - will stop by error, A - will stop at every screen
CALL TRANSACTION 'VA01'
USING gt_bdcdata
MODE lv_mode.
A better option is to use the OPTIONS FROM addition, this gives you more opportunities:
DATA: ls_options TYPE ctu_params.
ls_options-dismode = 'N'. "see explanation above
CALL TRANSACTION 'VA01'
USING gt_bdcdata
OPTIONS FROM ls_options.

Clone a program which uses a logical database, programmatically

I have a report, let's call it REPORT_A, and I'd like to clone it to REPORT_B, execute REPORT_B, and then come back.
I'm doing the following:
DATA: lv_report_name TYPE c LENGTH 30 VALUE `DEMO_LIST_OUTPUT`,
lv_new_report_name TYPE c LENGTH 30 VALUE `ZZ_DEMO_LIST_OUTPUT`,
lt_report_code TYPE abaptxt255_tab,
lv_message TYPE abaptxt255,
lv_line TYPE i,
lv_word TYPE abaptxt255.
READ REPORT lv_report_name INTO lt_report_code.
SYNTAX-CHECK FOR lt_report_code
MESSAGE lv_message
LINE lv_line
WORD lv_word.
IF sy-subrc = 0.
INSERT REPORT lv_new_report_name FROM lt_report_code STATE 'A'.
GENERATE REPORT lv_new_report_name.
SUBMIT (lv_new_report_name) VIA SELECTION-SCREEN AND RETURN.
ENDIF.
The syntax-check statement is returning sy-subrc = 4, and lv_message contains:
PERNR is not defined for the current logical database
This is the issue -> REPORT_A uses PNP logical database and has a get pernrstatement, so it fails the syntax-check.
Detail: REPORT_A is working just fine, tables pernr is declared in it. If I run it alone in SE38, it executes perfectly.
But, due to this weird error, I am always failing to generate REPORT_B.
Even if I skip the IF condition, it will then DUMP in the submit line, pointing a syntax error referring to the same error, "pernr is not defined for the current logical database".
Is there a way around it?
Can I call get pernr dynamically, so it doesn't fail the syntax check?
First of all, be careful, INSERT REPORT and GENERATE REPORT are statements for internal use (reserved to SAP).
If you still want to use the internal statements, see the rest of my answer.
Otherwise the workaround is to use GENERATE SUBROUTINE POOL. But it won't work for a logical database. If you copy a standard program maybe it's not a good idea of copying it (no note assistant to help you in case of patch/upgrade), so the classic workarounds are to add implicit enhancement options, or use eventual user exits proposed by SAP in this particular program (if any). There might be other options, but it depends on your exact goal, which you didn't share (yet).
The statement INSERT REPORT creates a source code module with a program entry (in table TRDIR) which by default corresponds to an Executable program (A.K.A. "report"), and so can be executed with SUBMIT.
But in your case, the program you want to generate is a program using a Logical Database, so you must assign the program attribute Logical database (TRDIR-LDBNAME).
The program attributes are to be passed via the words DIRECTORY ENTRY in the following statements:
SYNTAX-CHECK ... DIRECTORY ENTRY ls_trdir
INSERT REPORT ... DIRECTORY ENTRY ls_trdir
An easy solution for copying an existing program is to read its program attributes from the table TRDIR, change the name of the program (TRDIR-NAME) that you are creating, and pass them after the words DIRECTORY ENTRY.
Additional comments:
COMMIT WORK should be placed after GENERATE REPORT as explained in the documentation.
SY-SUBRC should be checked after INSERT REPORT and GENERATE REPORT.
Consequently, the following code will work:
DATA: lv_report_name TYPE c LENGTH 30 VALUE `DEMO_LIST_OUTPUT`,
lv_new_report_name TYPE c LENGTH 30 VALUE `ZZ_DEMO_LIST_OUTPUT`,
lt_report_code TYPE abaptxt255_tab,
lv_message TYPE abaptxt255,
lv_line TYPE i,
lv_word TYPE abaptxt255,
ls_trdir TYPE trdir.
READ REPORT lv_report_name INTO lt_report_code.
SELECT SINGLE * FROM trdir INTO ls_trdir WHERE name = lv_report_name.
ls_trdir-name = lv_new_report_name.
SYNTAX-CHECK FOR lt_report_code
MESSAGE lv_message
LINE lv_line
WORD lv_word
DIRECTORY ENTRY ls_trdir.
IF sy-subrc = 0.
INSERT REPORT lv_new_report_name FROM lt_report_code STATE 'A' DIRECTORY ENTRY ls_trdir.
IF sy-subrc = 0.
GENERATE REPORT lv_new_report_name.
IF sy-subrc = 0.
COMMIT WORK.
SUBMIT (lv_new_report_name) VIA SELECTION-SCREEN AND RETURN.
ELSE.
* Handle the error + rollback
ENDIF.
ELSE.
* Handle the error + rollback
ENDIF.
ELSE.
* Handle the error
ENDIF.

Best practice for BAPI commit and rollback?

I am using C# to call BAPI to communicate with SAP. I am new to this topic so I want to clarify some of the concept.
Q1: If I call BAPI_GOODSMVT_CREATE, should I check RETURN table or MAT_DOC field of items table to see whether it is succeed or failed?
Q2: If it is failed, need I call BAPI_TRANSACTION_ROLLBACK, or just ignore it(because without BAPI_TRANSACTION_COMMIT, data will not be saved)?
Q3: I found sometimes, even if there is error message, if I continue call BAPI_TRANSACTION_COMMIT, the data will be saved. But sometimes it won't.
Thanks in advance.
Check RETURN table. If it's OK, issue a BAPI_TRANSACTION_COMMIT with the WAIT flag. If it's not OK, issue a BAPI_TRANSACTION_ROLLBACK.
Check RETURN from BAPI_TRANSACTION_COMMIT as there may be errors there as well (for example a database update issue).
Ad Q1 In that particular case I'd rather check if material document number is returned in MAT_DOC. This way you don't rely on return messages. If a material document is returned, it means BAPI call was successful irrespective of messages. I find BAPIs implementation of handling return message quite inconsistent. Some BAPIs return a success message, some don't.
Ad Q2, Q3 Always call BAPI_TRANSACTION_COMMIT or BAPI_TRANSACTION_ROLLBACK after a BAPI call depending on result. BAPI_TRANSACTION_COMMIT and BAPI_TRANSACTION_ROLLBACK not only execute commit / rollback work but also call BUFFER_REFRESH_ALL function.

Variable is cleared on PostExecute event SSIS 2008

I am trying to pass Package variable: packno from Execute SQL Task to Data flow.
Variable is filled with needed value on OnProgress event. The value is:20717.
But on OnPostExecute event this value is cleared and assigned: -1.
So SQL command is executed with -1 value.
Any idea why this is happening?
There is a problem with the server. Everything worked fine on different one.

Best way to detect a "data loss" publish action when calling SSDT's SQLPackage.exe

When calling SQLPackage.exe (syntax described here) with publish action /a:Publish, there are cases when data loss occurs and the execution will be halted; this is specified by setting the parameter /p:BlockOnDataLoss (default to be 'true').
I need to know whether my publish action has succeeded or has failed due to 'data loss'.
Currently when succeeded, the returned exit code will be 0. And when failed, we just have the returned exit code to be 1. We cannot say whether a fail was caused by the data loss or not. How can we identify this?
Somewhere in the console output, we see the line that contain "... is being dropped, data loss could occur." So I intend to scan for every output line is printed but I guess there should be some other better way to do this.
Hope to hear what you think.