Thursday, 6 June 2019

Using long string in function imports

Motivation


So I created a SEGW project in both the latest stack as well as in 740 (the latest SP though) to check whether I would be able to reproduce the issue.

I wasn’t able to do so but wanted to share in detail how it worked for me.

I will work on publishing this and other code on Github but for the time being I just post screen shots and source code

SEGW Project


I created a project ZAF_SAMPLE_001 with an entity type SalesOrderDescription and an EntitySet SalesOrderDescription as follows:

soid is of type Edm.String , length 10

description is of type Edm.String, length 1000

Both field names were chosen automatically since the entity type is not bound to a DDIC structure.

SAP ABAP Study Materials, SAP ABAP Materials, SAP ABAP Tutorials and Materials

Then I created a function import SetDescription with two parameters Salesorder (Edm.String with a length of 10) and Description (Edm.String with a length 1000).

The ABAP Field Names ZAF_SAMPLE_001_DESCRIPTION and ZAF_SAMPLE_001_SALESORDER are NOT existing DDIC types but the names were just chosen randomly when creating the function import parameters.

SAP ABAP Study Materials, SAP ABAP Materials, SAP ABAP Tutorials and Materials

Table


The data was stored in a simple table whose fields are using the ABAP internal types CHAR(30) and CHAR(1000).

@EndUserText.label : 'long descriptions'
@AbapCatalog.enhancementCategory : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #LIMITED
define table zaf_sample_001 {
  key client  : abap.clnt not null;
  key soid    : abap.char(10) not null;
  description : abap.char(1000);

}

Result


When posting the following URI I got a response where all characters (more than 400 are being returned)

/sap/opu/odata/SAP/ZAF_SAMPLE_001_SRV/SetDescription?Salesorder='29'&Description='100 characters: '0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789 200 characters: '0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789 300 characters: '0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789 400 characters: '0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'0123456789'

SAP ABAP Study Materials, SAP ABAP Materials, SAP ABAP Tutorials and Materials

DPC_EXT class (740)


Here is the code of the DPC_EXT class for 740 where no inline declaration of variables is allowed an no “@” must be used to mark parameters in SQL statements as host variables.

class ZCL_ZAF_SAMPLE_001_DPC_EXT definition
  public
  inheriting from ZCL_ZAF_SAMPLE_001_DPC
  create public .

  PUBLIC SECTION.
    METHODS /iwbep/if_mgw_appl_srv_runtime~execute_action
        REDEFINITION .
  PROTECTED SECTION.
    METHODS salesorderdescri_get_entity REDEFINITION.
    METHODS salesorderdescri_get_entityset REDEFINITION.
private section.
ENDCLASS.

CLASS ZCL_ZAF_SAMPLE_001_DPC_EXT IMPLEMENTATION.
  METHOD salesorderdescri_get_entityset.
    DATA: lv_osql_where_clause TYPE string,
          lv_top               TYPE i,
          lv_skip              TYPE i,
          lv_max_index         TYPE i,
          n                    TYPE i.
*- get number of records requested
    lv_top = io_tech_request_context->get_top( ).
*- get number of lines that should be skipped
    lv_skip = io_tech_request_context->get_skip( ).
*- value for maxrows must only be calculated if the request also contains a $top
    IF lv_top IS NOT INITIAL.
      lv_max_index = lv_top + lv_skip.
    ENDIF.
    lv_osql_where_clause = io_tech_request_context->get_osql_where_clause( ).

    SELECT * FROM zaf_sample_001
      INTO CORRESPONDING FIELDS OF TABLE et_entityset
      UP TO lv_max_index ROWS
      WHERE (lv_osql_where_clause).
*- skipping entries specified by $skip
    IF lv_skip IS NOT INITIAL.
      DELETE et_entityset TO lv_skip.
    ENDIF.
*-  Inlinecount - get the total numbers of entries that fit to the where clause
    IF io_tech_request_context->has_inlinecount( ) = abap_true.
      SELECT COUNT(*)  FROM   zaf_sample_001 WHERE (lv_osql_where_clause) .
      es_response_context-inlinecount = sy-dbcnt.
    ELSE.
      CLEAR es_response_context-inlinecount.
    ENDIF.

  ENDMETHOD.

  METHOD salesorderdescri_get_entity.
    DATA: lt_keys       TYPE /iwbep/t_mgw_tech_pairs,
          ls_key        TYPE /iwbep/s_mgw_tech_pair,
          ls_bp_key     TYPE zcl_zaf_sample_001_mpc=>ts_salesorderdescription-soid,
          ls_headerdata TYPE zcl_zaf_sample_001_mpc=>ts_salesorderdescription.

    CALL METHOD io_tech_request_context->get_converted_keys
      IMPORTING
        es_key_values = ls_headerdata.

    ls_bp_key = ls_headerdata-soid.

    SELECT SINGLE *
      INTO CORRESPONDING FIELDS OF er_entity
      FROM zaf_sample_001
      WHERE soid = ls_headerdata-soid.
  ENDMETHOD.

  METHOD /iwbep/if_mgw_appl_srv_runtime~execute_action.

    DATA: ls_message           TYPE          scx_t100key.

    TYPES: BEGIN OF lty_import_parameter,
             ZAF_SAMPLE_001_SALESORDER  TYPE zaf_sample_001-soid,
             ZAF_SAMPLE_001_DESCRIPTION TYPE zaf_sample_001-description,
           END OF lty_import_parameter.
    DATA: ls_parameter_values     TYPE lty_import_parameter,

          lv_function_import_name TYPE /iwbep/mgw_tech_name.
    DATA ls_sales_description TYPE  zaf_sample_001.  " zcl_zaf_sample_001_mpc=>ts_salesorderdescription.
    DATA lt_sales_description TYPE STANDARD TABLE OF zaf_sample_001. "zcl_zaf_sample_001_mpc=>tt_salesorderdescription.

    lv_function_import_name = io_tech_request_context->get_function_import_name( ).

    io_tech_request_context->get_converted_parameters(
      IMPORTING
        es_parameter_values = ls_parameter_values ).

    CASE lv_function_import_name.

      WHEN 'SetDescription'.

        ls_sales_description-description = ls_parameter_values-ZAF_SAMPLE_001_description.
        ls_sales_description-soid = ls_parameter_values-ZAF_SAMPLE_001_salesorder.
        APPEND ls_sales_description TO lt_sales_description.
*
        INSERT zaf_sample_001 FROM TABLE lt_sales_description.
"        INSERT zaf_sample_001 FROM @ls_sales_description.
        " add check whether salesorder exist or not
        IF sy-subrc <> 0.
          " implement suitable error handling here
          ls_message-msgid = 'SY'.
          ls_message-msgno = '002'.
          CONCATENATE 'Update for ' ls_parameter_values-ZAF_SAMPLE_001_SalesOrder ' failed' INTO ls_message-attr1.

          RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception
            EXPORTING
              textid = ls_message.
*        ELSE.
*          ls_snwd_lock-node_key = ls_so-node_key.
        ENDIF.

data ls_entity type zcl_zaf_sample_001_mpc=>ts_salesorderdescription.

        SELECT SINGLE * FROM zaf_sample_001 INTO CORRESPONDING FIELDS OF ls_entity WHERE soid = ls_parameter_values-ZAF_SAMPLE_001_salesorder.

        IF ls_entity IS INITIAL.
          ls_message-msgid = 'SY'.
          ls_message-msgno = '002'.
          ls_message-attr1 = 'sales order not found'.

          RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception
            EXPORTING
              textid = ls_message.
        ENDIF.

        copy_data_to_ref( EXPORTING
        is_data = ls_entity CHANGING
        cr_data = er_data
        ).

    ENDCASE.
  ENDMETHOD.
ENDCLASS.

MPC code


Extract from the definition part of the MPC class

class ZCL_ZAF_SAMPLE_001_MPC definition
  public
  inheriting from /IWBEP/CL_MGW_PUSH_ABS_MODEL
  create public .

public section.

  types:
    begin of TS_SETDESCRIPTION,
        ZAF_SAMPLE_001_DESCRIPTION type C length 1000,
        ZAF_SAMPLE_001_SALESORDER type C length 10,
    end of TS_SETDESCRIPTION .

DEFINE_ACTIONS

  method DEFINE_ACTIONS.
*&---------------------------------------------------------------------*
*&           Generated code for the MODEL PROVIDER BASE CLASS         &*
*&                                                                     &*
*&  !!!NEVER MODIFY THIS CLASS. IN CASE YOU WANT TO CHANGE THE MODEL  &*
*&        DO THIS IN THE MODEL PROVIDER SUBCLASS!!!                   &*
*&                                                                     &*
*&---------------------------------------------------------------------*

data:
lo_action         type ref to /iwbep/if_mgw_odata_action,                 "#EC NEEDED
lo_parameter      type ref to /iwbep/if_mgw_odata_parameter.              "#EC NEEDED

********************************************************
*   ACTION - SetDescription
********************************************************

lo_action = model->create_action( 'SetDescription' ).  "#EC NOTEXT
*Set return entity type
lo_action->set_return_entity_type( 'SalesOrderDescription' ). "#EC NOTEXT
*Set HTTP method GET or POST
lo_action->set_http_method( 'POST' ). "#EC NOTEXT
*Set the action for entity
lo_action->set_action_for( 'SalesOrderDescription' ).        "#EC NOTEXT
* Set return type multiplicity
lo_action->set_return_multiplicity( '1' ). "#EC NOTEXT
********************************************************
* Parameters
********************************************************

lo_parameter = lo_action->create_input_parameter( iv_parameter_name = 'Description'    iv_abap_fieldname = 'ZAF_SAMPLE_001_DESCRIPTION' ). "#EC NOTEXT
lo_parameter->/iwbep/if_mgw_odata_property~set_type_edm_string( ).
lo_parameter->set_maxlength( iv_max_length = 1000 ). "#EC NOTEXT
lo_parameter = lo_action->create_input_parameter( iv_parameter_name = 'Salesorder'    iv_abap_fieldname = 'ZAF_SAMPLE_001_SALESORDER' ). "#EC NOTEXT
lo_parameter->/iwbep/if_mgw_odata_property~set_type_edm_string( ).
lo_parameter->set_maxlength( iv_max_length = 10 ). "#EC NOTEXT
lo_action->bind_input_structure( iv_structure_name  = 'ZCL_ZAF_SAMPLE_001_MPC=>TS_SETDESCRIPTION' ). "#EC NOTEXT
  endmethod.

No comments:

Post a Comment