Wednesday, 24 September 2025

Consuming EUDR Webservices from SAP ECC

  • There are number of us who're still stuck in the old SAP ECC or S/4 Hana on Premise and yet to move into Private or Public Cloud. A recent regulation in Europe requires us to implement tracebility on products produced by our plants. A requirement requires us to automatically submit the Due Diligent Statement (DDS) to EUDR website to compliance with the EUDR. For this, APIs have been developed to do just that, submitting DDS and getting the reference number and verification number. The APIs are available via Webservices, and to implement this, it is not that hard since SAP has automate the generation of consumer proxy and all required objects based on the WSDL available from EUDR. During first few Conformance Test (CF) that I've tested so far, there are few that probably will be helpful to point out: 
  • After you've loaded and generate the WSDL, using SOAMANAGER, you need to configure logical port. This is where you specified the end point, the username/password etc. In the first CF, this is the easiest one to just ping the server, sending hello in the payload with the correct cridential and header. However, for me, this is not a straight forward thing. 
    1. In SOAMANAGER, while creating logical port, you need to create logical port with "WSDL based configuration with template", and for the template, you need to use the "WSSE_USERNAMETOKEN". This will make the username/password appear in the next step. You need to use your username and authentication key you've created in the system (for testing, we need to get it from acceptance system). Finish the rest and save/activate the logical port. 
    2. While testing the generated class and sending the "hello" in the payload for CF1, I found out that SAP is sending a password and not a password digest as required by EUDR server. From my almost full day of debugging and trying so many options, I finally said that there will be no way that we could configure SAP to send a password digest, so at the end, I do what most of us trying not to do... implicit enhancement! 
    3. The implicit enhancement to Class CL_WSSE_FT_OUT_CFG and method GET_ST_CFG_711. At the end of the method, I put the following codes (this will trigger the passworddigest).   
     IF lf_supp_tk_type = co_t_type_unt.
     DATA(lv_soapaction) = to_upper( get_cfg_value( name = tsrtp_f_bdg_action ) ).            IF lv_soapaction CS 'EUDR' AND unt_st_cfg-digest_type IS INITIAL.                      unt_st_cfg-digest_type = abap_true.
     ENDIF.

          ENDIF.

  • I'm using the SOAPAction field since it has EUDR defined there in the WSDL and I don't want the enhancement gets triggered by other consumer proxy that doesn't have the same requirement for the authentication method. 2. There is also a requirement in the API for us to send a custom tag in the SOAP header. We need to add <v4:WebServiceClientId>eudr-test</v4:WebServiceClientId>  in the SOAP header. The only way to do this is in ABAP, when you call your proxy, you need to inject this custom tag to the header. I managed to do this using the following codes:
            DATA: lr_xml_document TYPE REF TO if_ixml_document,

          lr_xml_element  TYPE REF TO if_ixml_element.

    TRY.
        DATA(lo_ws_header) = CAST if_wsprotocol_ws_header( mr_interface->get_protocol( if_wsprotocol=>ws_header ) ).
      CATCH cx_ai_system_fault.
        RETURN.
      CATCH cx_ai_application_fault.
        RETURN.
    ENDTRY.

    CONCATENATE
      '<env:Header>'
      '<v4:WebServiceClientId xmlns:v4="http://ec.europa.eu/sanco/tracesnt/base/v4">'
      client_id
      '</v4:WebServiceClientId>'
      '</env:Header>' INTO DATA(lv_header).

    DATA(lv_xheader) = cl_proxy_service=>cstring2xstring( lv_header ).

    CALL FUNCTION 'SDIXML_XML_TO_DOM'
      EXPORTING
        xml      = lv_xheader
      IMPORTING
        document = lr_xml_document
      EXCEPTIONS
        OTHERS   = 0.

    DATA(lr_xml_root) = lr_xml_document->get_root_element( ).
    lr_xml_element ?= lr_xml_root->get_first_child( ).

    WHILE NOT lr_xml_element IS INITIAL.
      DATA(l_name) = lr_xml_element->get_name( ).
      DATA(l_namespace) = lr_xml_element->get_namespace_uri( ).
      lo_ws_header->set_request_header(
                  name      = l_name
                  namespace = l_namespace
                  dom       = lr_xml_element ).
      lr_xml_element ?= lr_xml_element->get_next( ).
    ENDWHILE.


  • The next that I found during the CF2 is, I need to send the geojson and this needs to be in base64 and since the xsd refered as base64Binary, the geojson code needs only be converted from the JSON to xstring. No further process needed, SAP will convert it to base64 automatically during the XML creation. 

I will update the blog as and when I find new things. Till then have fun!!!

Thursday, 30 May 2024

TOUCHTAB report, regenerate all ABAPs related to changed/modified structure

I was working on S4HANA OnPremis and tried to do an enhancement to BP's additional info structure by appending fields, but decided that it doesn't work that way. Revert the changes and everyone now getting ABAP dump with LOAD_TYPE_VERSION_MISMATCH. Found on SAP Notes, Note 1542682 which should fix this. Run report TOUCHTAB with the structure mentioned in the ABAP dump to regenerate all related programs.

Monday, 28 February 2022

Calling MS SQL Stored Procedure from ABAP

One of the few things sometime coming up in your ticket request. Calling stored procedure from ABAP to remote SQL server. 

How do we send the NULL value? It seems sending the ind_ref with -1 solve this.


TYPES: BEGIN OF ty_input,
         orderid(50),
         materialid(50),
         description(80),
         user1(50),
         user2(50),
       END OF ty_input,
       BEGIN OF ty_output,
         orderid(50),
       END OF ty_output.

DATA: ls_input          TYPE ty_input,
      ls_output         TYPE ty_output.

CONSTANTS: gc_null      TYPE int2 VALUE '-1'.

* Create db connection
DATA(lr_sql_connection) = cl_sql_connection=>get_connection( 'MSSQL' ).
DATA(lr_statement) = lr_sql_connection->create_statement( ).
DATA(lo_struct) = CAST cl_abap_structdescr( cl_abap_typedescr=>describe_by_data( ls_input ) ).
DATA(lt_comp) = lo_struct->get_components( ).
CLEAR: ls_input.
ls_input-orderid    = 'ABC123'.
ls_input-materialid = 'MAT01'.
ls_input-description = 'Order for MAT01'.

* Input fields
LOOP AT lt_comp INTO DATA(ls_comp).
  ASSIGN COMPONENT ls_comp-name OF STRUCTURE ls_input TO FIELD-SYMBOL(<cell>).
  IF <cell> IS INITIAL.
    lr_statement->set_param( data_ref = REF #( <cell> )
                             ind_ref  = REF #( gc_null )    "Send NULL if field has no value
                             inout    = cl_sql_statement=>c_param_in ).
  ELSE.
    lr_statement->set_param( data_ref = REF #( <cell> )
                             inout    = cl_sql_statement=>c_param_in ).
  ENDIF.
ENDLOOP.
* Output fields
lr_statement->set_param( data_ref = REF #( ls_output-orderid )
                         inout    = cl_sql_statement=>c_param_out ).

TRY.
    lr_statement->execute_procedure( proc_name = 'ST_ADDORDER' ).
    WRITE: / 'OrderID: ', ls_output-orderid.
  CATCH cx_sql_exception INTO DATA(lx_00).
    DATA(lv_exception) = | An exception occurred with SQL_MESSAGE = { lx_00->sql_message }|.
    WRITE: / lv_exception.
ENDTRY.

* Close db connection
lr_sql_connection->close( ). 

Sunday, 24 January 2021

Reviving my WX station, now with RTL-SDR.

 I've setup my WX station (Maplin version of WH1080) for quite sometime now but since last year, it went down due to few reasons. One of it, because the problem with the intermediary software between the WX base station and aprs server. Anyway, the outdoor unit still out there, transmitting it data over 433.920Mhz freq. 

Had a bit of time yesterday, and I've received the BNC to SMA jumper cables that I ordered through Shoppe few days back, so no reason not to go ahead with this. My Raspberry 4 mini-server is under-load anyway, and the RX only multi-coupler given by Weerut has been laying down collecting dust for quite sometime. 

What needed to get the SDR to receive the WX data from WH1080 is a software called rtl_433. This software runs on my Raspbian without a problem and it could actually receive many other devices that use 433MHz frequency. 

To get started, I was using the instructions found in :

GitHub - matthewwall/weewx-sdr: weewx driver for software-defined radio

Few things needed to be changed since the rtl_433 has been updated, WH1080 support has changed too. The weewx-sdr won't work out of box. The following changes still not available in the final code. 

Resolve #79 - new model name and wind fields in RTL-433 V20 by mitchins · Pull Request #88 · matthewwall/weewx-sdr · GitHub

To be able to send the output into aprs, I'm using the setup that I've had since 2015. This extension is a modified code, not written by me but it works great my setup. My write up on the weewx2aprx can be found here.

9M2TPT / KT2O / M0HIK: Getting your WX station out to RF using weewx + aprx

My current setup as below ( yes, I'm using multi-coupler for my setup which is connected to Diamond D190).


Oh am going to redo the power into the multi-coupler, it kind of dangerous using the croc-clip for it for sure :)


Friday, 17 July 2020

SAP Smartforms - Add T&C Pages

Some of you might have come across this requirement in your years of doing ABAP. T&C page might be easy in most cases, just set a COMMAND from PAGE main window but if we've some other stuff like printing a secondary window at end of page, we might missed that.

Since many developers overlapped their final windows to save some empty spaces rather than wasted it for reserving the last footer, this becomes a problem when trying to jump to a T&C page.

To achieve this, we need to do the following:

  1. Create two global variables (flags), e.g. GV_FLAG1 and GV_FLAG2.
  2. In the main window, after you've done all the processing, you need to create a program lines, here we set the first flag, GV_FLAG1 = 'X'. No conditions need to be added or ticked.
  3. After the above program lines, create a COMMAND and this is to be set to jump to the T&C page.
  4. In your secondary window (e.g. footer printed at last page), under the conditions tab, do a check on GV_FLAG1 EQ 'X' and GV_FLAG2 NE 'X'. Do not set any additional event/condition.
  5. Create a program line in the secondary window, make it the last one after all other processing, here you set the second flag, GV_FLAG2 = 'X'. Important, no condition needed and any event should be unticked. 
The above should print the last footer window and jump to your T&C page. Good luck!

 

Thursday, 25 June 2020

Debugging error from VF01

Ever wonder what the easiest way to debug error coming out from VF01? Well, you could try creating watchpoint by checking SYS-MSGID = 'VF' but the easiest is to place a session breakpoint in subroutine VBFS_HINZUFUEGEN which can be found in INCLUDE LV60AA98.




All errors found in the log will need to go through the above routine. Hope this helps! I've been enjoying doing this stuff for more than 20 years! Hope you too! :)

Wednesday, 12 June 2019

Debugging SAP ERMS rules

There probably many CRM implementations which use ERMS, I've come through few requests on how to debug the auto response given by ERMS when CRM receives an inbound email.

SAP provides a tool which you could use to debug this auto response rules. The transaction CRM_ERMS_LOGGING is very helpful. But before we could use this transaction, we need to know the work item ID.

Anyway, here are the steps I used in my debugging:

1. Use SOST, find the response that was sent out, note the date/time
2. Use SWIA, this will return you with work item ID, fill in the time period based on (1) and the task = TS00207915 (ERMS service manager)
3. Put a break point at your auto response implementation
4. Use CRM_ERMS_LOGGING, enter the work item ID and un-tick "Do not execute actions"
5. Execute and you'll be brought to the break point you left in (3)



Consuming EUDR Webservices from SAP ECC

There are number of us who're still stuck in the old SAP ECC or S/4 Hana on Premise and yet to move into Private or Public Cloud. A rece...