Technology Blog Posts by Members
cancel
Showing results for 
Search instead for 
Did you mean: 
Ilayda_Ymlhgl
Explorer
3,336

Greetings to everyone,

I recently took part in my first public cloud project. I did a lot of research and development in this process. I would like to share with you a case that happened to me and the steps I applied in this case.

Used Api: Journal Entry - Clearing (Asynchronous) 

( https://api.sap.com/api/JOURNALENTRYBULKCLEARINGREQUES/overview )

Tutorial on the use of SOAP Services:

https://developers.sap.com/tutorials/abap-environment-soap-web-services..html

Case: Journal Entry - Clearing (Asynchronous) api is called with a button behind a screen made using RAP. In this case, when we start with the approach in the tutorial link above, dump is taken on the screen caused by the modify statement in the automatically generated class.

Ilayda_Ymlhgl_13-1739180905880.png

Ilayda_Ymlhgl_1-1739180719289.png

Ilayda_Ymlhgl_2-1739180719290.png

Ilayda_Ymlhgl_3-1739180719290.png

https://help.sap.com/docs/abap-cloud/abap-rap/rap-transactional-model-and-sap-luw )

Approach: In this case, we can run the xml of the soap service by embedding it into the body as if we call ODATA service. However, ws-a addressing and generate message id ticks must be checked in order to run Asynchronous Soap services. The aim is to make these ticks behave as if they are checked in postman and to provide the same situation in the code.

In order to run the Asynchronous SOAP service via SOAPUI, the following two ticks must be checked ( https://www.soapui.org/docs/soap-and-wsdl/supported-standards/using-ws-addressing/ )

Ilayda_Ymlhgl_14-1739180928235.png

In order for Postman to correspond to this, we need to put the ws-a addressing link that we view in the wsdl file into the header and then fill in the action and message id parts.

Action: We can get the action link on SoapUI.

Ilayda_Ymlhgl_5-1739180719292.png

WS-A: We can get the link on WSDL.

Ilayda_Ymlhgl_6-1739180719292.jpeg

MessageID: urn:uuid:{{{$randomUUUID}}} should be used to structure that generate random uuid with every time we do a post operation.

Ilayda_Ymlhgl_16-1739181002688.png

We can embed this structure into our transform object when calling the api from our Behavior class. We can use cl_system_uuid=>create_uuid_c36_static( ) method to provide the same format as urn:uuid:{{$randomUUUID}}.

Ilayda_Ymlhgl_8-1739180719295.png

Ilayda_Ymlhgl_9-1739180719298.png

Ilayda_Ymlhgl_10-1739180719298.png

Ilayda_Ymlhgl_11-1739180719298.png

Ilayda_Ymlhgl_0-1739181866309.png

The code of the Behavior Class Method where the Asynchronous Soap API is called:

 

TRY.
DATA(lo_http_destination) = cl_http_destination_provider=>create_by_url( 'https://host-api.s4hana.cloud.sap/sap/bc/srt/scs_ext/sap/journalentrybulkclearingreques' ).
  CATCH cx_http_dest_provider_error INTO DATA(lo_http_dest_provider_error).
ENDTRY.

  TRY.
        DATA(lo_web_http_client) = cl_web_http_client_manager=>create_by_http_destination( lo_http_destination ) .
      CATCH  cx_web_http_client_error INTO DATA(lo_client_error).
        DATA(lv_client) = lo_client_error->get_text( ).
    ENDTRY.

    DATA(lo_web_http_request) = lo_web_http_client->get_http_request( ).
    lo_web_http_request->set_authorization_basic(  EXPORTING  i_username = Communication User
                                                              i_password = Communication User Password ).


    lo_web_http_request->set_header_fields( VALUE #( (  name = 'Content-Type' value = 'text/xml; charset=UTF-8' )
                                                     (  name = 'SOAPAction'    value = 'http://sap.com/xi/SAPSCORE/SFIN/JournalEntryBulkClearingRequest_In/JournalEntryBulkClearingRequest_InRequest' ) )   ).
TRY.
        DATA(lv_uuid) = cl_system_uuid=>create_uuid_c36_static( ).
      CATCH cx_uuid_error INTO DATA(lx_uuid).
    ENDTRY.
    lv_uuid_s = lv_uuid.


*--->fill the body


  DATA(lv_body) = xco_cp_json=>data->from_abap( ls_body )->apply( VALUE #(  ( xco_cp_json=>transformation->underscore_to_pascal_case ) ) )->to_string( ).

        TRY.
            CALL TRANSFORMATION zfi_ac_api_to
           SOURCE data = ls_body
            RESULT XML lv_body.
          CATCH cx_root INTO DATA(lo_root).
            DATA(lv_mes_tr) = lo_root->get_text( ).
        ENDTRY.


        REPLACE ALL OCCURRENCES OF 'uuid:{UUID}' IN lv_body WITH lv_uuid_s.
        REPLACE ALL OCCURRENCES OF '<?xml version="1.0" encoding="utf-16"?>' IN lv_body WITH ''.
        REPLACE ALL OCCURRENCES OF '&lt;' IN lv_body WITH '<'.
        REPLACE ALL OCCURRENCES OF '&gt;' IN lv_body WITH '>'.

        lo_web_http_request->set_text( lv_body ).
        TRY.
            DATA(lo_web_http_response) = lo_web_http_client->execute( if_web_http_client=>post ).
          CATCH cx_web_http_client_error INTO lo_client_error.
            lv_client = lo_client_error->get_text( ).
        ENDTRY.
        DATA(lv_response)      = lo_web_http_response->get_text( ).
        DATA(ls_response_stat) = lo_web_http_response->get_status( ).

 

The code of the Transformation Object:

 

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sap="http://www.sap.com/sapxsl" version="1.0">
  <xsl:strip-space elements="*"/>

  <xsl:output encoding="UTF-8" indent="yes" method="xml"/>

  <xsl:template match="DATA">
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sfin="http://sap.com/xi/SAPSCORE/SFIN">
      <soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
        <wsa:Action soapenv:mustUnderstand="1">http://sap.com/xi/SAPSCORE/SFIN/JournalEntryBulkClearingRequest_In/JournalEntryBulkClearingRequest_InRequest</wsa:Action>
        <wsa:MessageID soapenv:mustUnderstand="1">uuid:{UUID}</wsa:MessageID>

      </soapenv:Header>
      <soapenv:Body>
        <sfin:JournalEntryBulkClearingRequest>
          <xsl:element name="MessageHeader">
            <xsl:element name="ID">
              <xsl:value-of select="JOURNAL_ENTRY_BULK_CLEARING_RE/MESSAGE_HEADER/I_D"/>
            </xsl:element>
            <xsl:element name="CreationDateTime">
              <xsl:value-of select="JOURNAL_ENTRY_BULK_CLEARING_RE/MESSAGE_HEADER/CREATION_DATE_TIME"/>
            </xsl:element>
            <TestDataIndicator>
              <xsl:value-of select="JOURNAL_ENTRY_BULK_CLEARING_RE/MESSAGE_HEADER/TEST_DATA_INDICATOR"/>
            </TestDataIndicator>
          </xsl:element>
          <JournalEntryClearingRequest>
            <xsl:element name="MessageHeader">
              <ID>
                <xsl:value-of select="JOURNAL_ENTRY_BULK_CLEARING_RE/JOURNAL_ENTRY_CLEARING_REQUEST/MESSAGE_HEADER/I_D"/>
              </ID>
              <xsl:element name="CreationDateTime">
                <xsl:value-of select="JOURNAL_ENTRY_BULK_CLEARING_RE/JOURNAL_ENTRY_CLEARING_REQUEST/MESSAGE_HEADER/CREATION_DATE_TIME"/>
              </xsl:element>
            </xsl:element>
            
            <JournalEntry>
              <CompanyCode>
                <xsl:value-of select="JOURNAL_ENTRY_BULK_CLEARING_RE/JOURNAL_ENTRY_CLEARING_REQUEST/JOURNAL_ENTRY/COMPANY_CODE"/>
              </CompanyCode>
              <AccountingDocumentType>
                <xsl:value-of select="JOURNAL_ENTRY_BULK_CLEARING_RE/JOURNAL_ENTRY_CLEARING_REQUEST/JOURNAL_ENTRY/ACCOUNTING_DOCUMENT_TYPE"/>
              </AccountingDocumentType>
              <DocumentDate>
                <xsl:value-of select="JOURNAL_ENTRY_BULK_CLEARING_RE/JOURNAL_ENTRY_CLEARING_REQUEST/JOURNAL_ENTRY/DOCUMENT_DATE"/>
              </DocumentDate>
              <PostingDate>
                <xsl:value-of select="JOURNAL_ENTRY_BULK_CLEARING_RE/JOURNAL_ENTRY_CLEARING_REQUEST/JOURNAL_ENTRY/POSTING_DATE"/>
              </PostingDate>
              <CurrencyCode>
                <xsl:value-of select="JOURNAL_ENTRY_BULK_CLEARING_RE/JOURNAL_ENTRY_CLEARING_REQUEST/JOURNAL_ENTRY/CURRENCY_CODE"/>
              </CurrencyCode>
              <DocumentHeaderText>
                <xsl:value-of select="JOURNAL_ENTRY_BULK_CLEARING_RE/JOURNAL_ENTRY_CLEARING_REQUEST/JOURNAL_ENTRY/DOCUMENT_HEADER_TEXT"/>
              </DocumentHeaderText>
              <CreatedByUser>
                <xsl:value-of select="JOURNAL_ENTRY_BULK_CLEARING_RE/JOURNAL_ENTRY_CLEARING_REQUEST/JOURNAL_ENTRY/CREATED_BY_USER"/>
              </CreatedByUser>
              
              <xsl:for-each select="JOURNAL_ENTRY_BULK_CLEARING_RE/JOURNAL_ENTRY_CLEARING_REQUEST/JOURNAL_ENTRY/APARITEMS/item">
                <APARItems>
                  <ReferenceDocumentItem>
                    <xsl:value-of select="REFERENCE_DOCUMENT_ITEM"/>
                  </ReferenceDocumentItem>
                  <CompanyCode>
                    <xsl:value-of select="COMPANY_CODE"/>
                  </CompanyCode>
                  <AccountType>
                    <xsl:value-of select="ACCOUNT_TYPE"/>
                  </AccountType>
                  <APARAccount>
                    <xsl:value-of select="APARACCOUNT"/>
                  </APARAccount>
                  <FiscalYear>
                    <xsl:value-of select="FISCAL_YEAR"/>
                  </FiscalYear>
                  <AccountingDocument>
                    <xsl:value-of select="ACCOUNTING_DOCUMENT"/>
                  </AccountingDocument>
                  <AccountingDocumentItem>
                    <xsl:value-of select="ACCOUNTING_DOCUMENT_ITEM"/>
                  </AccountingDocumentItem>
                  <xsl:value-of select="OTHER_DEDUCTION_AMOUNT_IN_DSP"/>
                </APARItems>

              </xsl:for-each>
            </JournalEntry>
          </JournalEntryClearingRequest>
        </sfin:JournalEntryBulkClearingRequest>
      </soapenv:Body>
    </soapenv:Envelope>
  </xsl:template>
</xsl:transform>

 

I hope this blog post has been helpful. 

Have a great day!