Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
basarozgur_kahraman
Contributor

Today's mobility is one of the hot topics in SAP world. Companies are developing new reports and dashboards for mobile environment. Until now lots of custom ALV reports were created and most of their functionality is needed in mobile environment. Rather than new developments for mobile, How can we make this reports mobile enable without modifications?

In this blog series, We will create a Restful service to submit ALV reports and a jquerymobile client to show & visualize report data in mobile.

Before begin, i strongly recommend you to read john.moy3  's blog .

Part 2 - Create JQueryMobile Web Application with Datatables plugin

Part 3 - Visualize ALV Data with Highcharts for iPad

Creating JSON Restful Service to Submit ALV Reports:


Pre-requisites:

  1. Go to transaction SE24, copy CL_TREX_JSON_SERIALIZER object to ZCL_TREX_JSON_SERIALIZER and make modifications according to my previous blog post .


Steps:

  1. Via transaction SE24, create a public class ZCL_SUBMIT_ALV
  2. Assign interface IF_HTTP_EXTENSION to this class.  This should introduce an instance method 'HANDLE_REQUEST' to our class.
  3. For our implementation of HANDLE_REQUEST, paste the following code:

METHOD if_http_extension~handle_request.

   TYPE-POOLS: abap,

               kkblo.

   DATA: lo_json_data    TYPE REF TO zcl_trex_json_serializer,

         lo_json_metadata TYPE REF TO zcl_trex_json_serializer.

* Data definition

   DATA: _path_info     TYPE string,

         _verb          TYPE string,

         _callback      TYPE string,

         _json_string           TYPE string,

         _json_string_data      TYPE string,

         _json_string_metadata  TYPE string.

   DATA: _it_inputparams  TYPE tihttpnvp,

         _inputparams     TYPE LINE OF tihttpnvp.

   DATA: _pgmna   TYPE tstc-pgmna,

         _tcode   TYPE tstc-tcode,

         _variant TYPE rsvar-variant.

   DATA: _data            TYPE REF TO data,

         _data_line       TYPE REF TO data,

         _data_descr      TYPE REF TO cl_abap_datadescr,

         _data_line_descr TYPE REF TO cl_abap_datadescr.

   DATA: _datafield(40).

   FIELD-SYMBOLS: <_datafield> TYPE ANY.

   DATA: BEGIN OF _metadata,

           is_hierseq   TYPE abap_bool,

           tabname      TYPE string,

           tabname_line TYPE string,

           s_keyinfo    TYPE kkblo_keyinfo,

           s_layout     TYPE lvc_s_layo,

           t_fcat       TYPE lvc_t_fcat,

           t_filter     TYPE lvc_t_filt,

           t_sort       TYPE lvc_t_sort,

         END OF _metadata.

   FIELD-SYMBOLS: <_data>        TYPE ANY TABLE,

                  <_wa_data>     TYPE ANY,

                  <_wa_metadata> TYPE ANY.

   DATA: _fcat TYPE lvc_s_fcat.

   DATA: _amount(40),

         _waersfield(40),

         _currfield(40).

   DATA: _ttext TYPE tstct-ttext,

         _description TYPE char120.

   FIELD-SYMBOLS: <_waers> TYPE ANY,

                  <_currency> TYPE ANY.

* Process request

   _path_info = server->request->get_header_field( name = '~path_info' ).

   _verb = server->request->get_header_field( name = '~request_method' ).

* Determine if method is get.

   IF _verb NE 'GET'.

     CALL METHOD server->response->set_header_field( name = 'Allow' value = 'GET' ).

     CALL METHOD server->response->set_status( code = '405' reason = 'Method not allowed' ).

     EXIT.

   ENDIF.

* Get passed parameters

   CALL METHOD server->request->get_form_fields

     CHANGING

       fields = _it_inputparams.

   LOOP AT _it_inputparams INTO _inputparams.

     TRANSLATE: _inputparams-name  TO UPPER CASE,

                _inputparams-value TO UPPER CASE.

     MODIFY _it_inputparams FROM _inputparams.

   ENDLOOP.

   CLEAR _inputparams.

   READ TABLE _it_inputparams INTO _inputparams WITH KEY name = 'TCODE'.

   _tcode = _inputparams-value.

   CLEAR _inputparams.

   READ TABLE _it_inputparams INTO _inputparams WITH KEY name = 'CALLBACK'.

   _callback = _inputparams-value.

   CLEAR _inputparams.

   READ TABLE _it_inputparams INTO _inputparams WITH KEY name = 'VARIANT'.

   _variant = _inputparams-value.

   IF _tcode IS INITIAL. 

     CALL METHOD server->response->set_status( code = '404' reason = 'Parameter missing' ).

     CALL METHOD server->response->set_cdata( data = 'Input Paramater "tcode" is missing' ).

     EXIT.

   ENDIF.

* progname of tcode

   SELECT SINGLE pgmna

   INTO _pgmna

   FROM tstc

   WHERE tcode = _tcode.

   IF sy-subrc IS NOT INITIAL. 

     CALL METHOD server->response->set_status( code = '404' reason = 'Tcode not exist' ).

     CALL METHOD server->response->set_cdata( data = 'Input Paramater "tcode" is not exist' ).

     EXIT.

   ENDIF.

   cl_salv_bs_runtime_info=>set( EXPORTING display  = abap_false

                                           metadata = abap_true

                                           data     = abap_true ).

   IF _variant IS INITIAL.

     SUBMIT (_pgmna) AND RETURN.

   ELSE.

     DATA: _it_valutab TYPE STANDARD TABLE OF rsparams.

     CALL FUNCTION 'RS_VARIANT_CONTENTS'

       EXPORTING

         report               = _pgmna

         variant              = _variant

       TABLES

         valutab              = _it_valutab

       EXCEPTIONS

         variant_non_existent = 1

         variant_obsolete     = 2

         OTHERS               = 3.

     IF _it_valutab[] IS INITIAL.

       SUBMIT (_pgmna) AND RETURN.

     ELSE.

*       SUBMIT (_pgmna) WITH SELECTION-TABLE _it_valutab AND RETURN.

       SUBMIT (_pgmna) USING SELECTION-SET _variant AND RETURN.

     ENDIF.

   ENDIF.

   TRY.

       cl_salv_bs_runtime_info=>get_data_ref( IMPORTING

                                                r_data            = _data

                                                "r_data_line       = _data_line

                                                r_data_descr     = _data_descr

                                                r_data_line_descr = _data_line_descr ).

       cl_salv_bs_runtime_info=>get_metadata( RECEIVING value = _metadata ).

       ASSIGN _data->* TO <_data>.

*     Modify data for output

       LOOP AT <_data> ASSIGNING <_wa_data>.

*       Modify data with conversion routines

         LOOP AT _metadata-t_fcat INTO _fcat WHERE edit_mask IS NOT INITIAL

                                               AND inttype = 'C'.

           CONCATENATE '<_WA_DATA>-'

                       _fcat-fieldname

                  INTO _datafield.

           ASSIGN (_datafield) TO <_datafield>.

           WRITE <_datafield> TO <_datafield> USING EDIT MASK _fcat-edit_mask.

         ENDLOOP.

*       Modify currency amount

         LOOP AT _metadata-t_fcat INTO _fcat WHERE datatype = 'CURR'

                                               AND cfieldname IS NOT INITIAL.

           CONCATENATE '<_WA_DATA>-'

                       _fcat-cfieldname

                  INTO _waersfield.

           CONCATENATE '<_WA_DATA>-'

                       _fcat-fieldname

                  INTO _currfield.

           ASSIGN: (_waersfield) TO <_waers>,

                   (_currfieldTO <_currency>.

           CALL FUNCTION 'CURRENCY_AMOUNT_SAP_TO_IDOC'

             EXPORTING

               currency    = <_waers>

               sap_amount  = <_currency>

             IMPORTING

               idoc_amount = _amount.

           CONDENSE _amount.

           <_currency> = _amount.

         ENDLOOP.

       ENDLOOP.

     CATCH cx_salv_bs_sc_runtime_info.

*     If error detected then abort

       CALL METHOD server->response->set_status( code = '404' reason = 'Unable to retrieve ALV data' ).

       CALL METHOD server->response->set_cdata( data = _json_string ).

       EXIT.

   ENDTRY.

   cl_salv_bs_runtime_info=>clear_all( ).

* create instance of json serialiser

   CREATE OBJECT lo_json_data

     EXPORTING

       DATA = <_data>.

* serialize data

   lo_json_data->serialize( ).

* get serialized json data string

   _json_string_data = lo_json_data->get_data( ).

* create instance of json serialiser

   CREATE OBJECT lo_json_metadata

     EXPORTING

       DATA = _metadata-t_fcat.

* serialize metadata

   lo_json_metadata->serialize( ).

* get serialized json metadata string

   _json_string_metadata = lo_json_metadata->get_data( ).

   IF _json_string_metadata IS NOT INITIAL.

     CONCATENATE '"alvMetadata":' _json_string_metadata INTO _json_string_metadata SEPARATED BY space.

   ENDIF.

   IF _json_string_data IS NOT INITIAL.

     CONCATENATE '"alvData":' _json_string_data INTO _json_string_data SEPARATED BY space.

   ENDIF.

* Tcode description

   SELECT SINGLE ttext

   INTO _ttext

   FROM tstct

   WHERE sprsl = sy-langu

     AND tcode = _tcode.

   CONCATENATE '"description":"'

               _ttext

               '"'

          INTO _description.

* JSON

   CONCATENATE '{'

               _description

               ','

               _json_string_metadata

               ','

               _json_string_data

               '}'

          INTO _json_string

   SEPARATED BY space.

* to support JSONP

   CONCATENATE _callback

               '('

               _json_string

               ')'

          INTO _json_string.

*

* set the response mimetype to json

* Set the content type

   CALL METHOD server->response->set_header_field(

     name = 'Content-Type'

     value = 'application/json; charset=utf-8' "for JSON

     ).

* Set CORS access control to avoid browser policy restrictions around

* Cross Domain communication

   CALL METHOD server->response->set_header_field( name = 'Access-Control-Allow-Origin' value = '*' ).

** set Allow methods

*  CALL METHOD server->response->set_header_field( name = 'Access-Control-Allow-Methods' value = 'GET' ).

* set the cdata response to the json string

   CALL METHOD server->response->set_cdata( data = _json_string ).

ENDMETHOD.                    "if_http_extension~handle_request

Publish Service:

Steps:

  1. Via transaction SICF, create a new service 'zsubmitalv' under the path /default_host/sap/bc/
  2. For the service, add a description, then go to the 'Handler List' tab and add "ZCL_SUBMIT_ALV" into the handler list.
  3. Activate the service (from the SICF tree, right-click on the service and select 'Activate Service')


Test Service:

Steps:

  1. From the SICF tree, right-click on the service and select 'Test Service' , you will see service respond: 'Input Paramater "tcode" is missing'
  2. Take url from browser and pass your transaction code as parameter like http://yoursapurl:8000/sap/bc/zsubmitalv?tcode=ZALVREPORT  .Via this url you will get alv metadata and data in JSON format.

          You can also pass variant as parameter:

          Ex: http://yoursapurl:8000/sap/bc/zsubmitalv?tcode=ZALVREPORT&variant=MYVARIANT

Note:

In ALV, maybe there is "CNTL_ERROR" dump because of the background execution.

To avoid this problem;

1- For reports that was created with REUSE_ALV_GRID_DISPLAY, You have to pass IT_SORT paramater to function.(it can be initial)

DATA_it_field_catalog TYPE slis_t_fieldcat_alv,

           _it_sort_catalog  TYPE slis_t_sortinfo_alv ,

           _layout              TYPE slis_layout_alv,

           _title                 TYPE lvc_title,

           _repid                LIKE sy-repid.

   _repid                             = sy-repid.

   _layout-colwidth_optimize = 'X'.

   _layout-zebra                   = 'X'.

CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'

     EXPORTING

       i_callback_program = _repid

       i_grid_title              = _title

       i_save                    = 'A'

       is_layout                = _layout

       it_fieldcat               = _it_field_catalog

      it_sort                    = _it_sort_catalog

     TABLES

       t_outtab                 = p_it_output[]

     EXCEPTIONS

       program_error         = 1

       OTHERS                = 2.

2- In OO ALV add offline mode control before creation of custom container in pbo of alv screen

     IF cl_gui_alv_grid=>offline( ) IS INITIAL. "Offline mode control

          CREATE OBJECT g_custom_container

               EXPORTING

                     container_name = g_container.

     ENDIF.


     CREATE OBJECT g_grid

       EXPORTING

         i_parent = g_custom_container.


22 Comments
Labels in this area