Skip to Content

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 Moy  ‘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 tstcpgmna,

         _tcode   TYPE tstctcode,

         _variant TYPE rsvarvariant.

   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 tstctttext,

         _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: _inputparamsname  TO UPPER CASE,

                _inputparamsvalue TO UPPER CASE.

     MODIFY _it_inputparams FROM _inputparams.

   ENDLOOP.

   CLEAR _inputparams.

   READ TABLE _it_inputparams INTO _inputparams WITH KEY name = ‘TCODE’.

   _tcode = _inputparamsvalue.

   CLEAR _inputparams.

   READ TABLE _it_inputparams INTO _inputparams WITH KEY name = ‘CALLBACK’.

   _callback = _inputparamsvalue.

   CLEAR _inputparams.

   READ TABLE _it_inputparams INTO _inputparams WITH KEY name = ‘VARIANT’.

   _variant = _inputparamsvalue.

   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 SELECTIONSET _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 _metadatat_fcat INTO _fcat WHERE edit_mask IS NOT INITIAL

                                               AND inttype = ‘C’.

           CONCATENATE ‘<_WA_DATA>-‘

                       _fcatfieldname

                  INTO _datafield.

           ASSIGN (_datafield) TO <_datafield>.

           WRITE <_datafield> TO <_datafield> USING EDIT MASK _fcatedit_mask.

         ENDLOOP.

*       Modify currency amount

         LOOP AT _metadatat_fcat INTO _fcat WHERE datatype = ‘CURR’

                                               AND cfieldname IS NOT INITIAL.

           CONCATENATE ‘<_WA_DATA>-‘

                       _fcatcfieldname

                  INTO _waersfield.

           CONCATENATE ‘<_WA_DATA>-‘

                       _fcatfieldname

                  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 = _metadatat_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 = sylangu

     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

/wp-content/uploads/2012/09/attributes_139830.jpg/wp-content/uploads/2012/09/interface_139831.jpg/wp-content/uploads/2012/09/m_139844.jpg

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’)

/wp-content/uploads/2012/09/s_139845.jpg

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

/wp-content/uploads/2012/09/te_139865.jpg/wp-content/uploads/2012/09/ie_139866.jpg/wp-content/uploads/2012/09/js_139867.jpg

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 syrepid.

   _repid                             = syrepid.

   _layoutcolwidth_optimize = ‘X’.

   _layoutzebra                   = ‘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.


To report this post you need to login first.

22 Comments

You must be Logged on to comment or reply to a post.

  1. Jack Stewart

    Great use of cl_salv_bs_runtime_info to get the table data, it’s a really interesting approach. You’re right, the techniques you’ve employed here could work really well with zMob. The architecture you’ve used is not dissimilar to that of zMob’s either, so it may not be so complicated to integrate ๐Ÿ™‚

    Thanks for the heads up,

    (0) 
    1. Basar Ozgur Kahraman Post author

      Hi Lokeswar,

      i think it got this dump while submitting program. Please, check this sql statement result and be sure transaction code exist in your system.

         SELECT SINGLE pgmna

         INTO _pgmna

         FROM tstc

         WHERE tcode = _tcode.

      Regards,

      Basar Ozgur

      (0) 
      1. satya Gadde

        Hi,

        Actually i tried in another system, in that system SAP is not installed.

        some Error occurred .

        error.PNG

        Is it necessary to install SAP.

        (0) 
                1. Basar Ozgur Kahraman Post author

                  Hi Satya,

                  Are you sure about service is running and settings is OK? Follow me on scn so you can reach me with direct messages. i will help you in private and share results here..

                  Regards

                  (0) 
  2. Felipe Granda

    Hi Basar,

    I’m new in the SAP world and thanks for your article, it was really helpful and solve some issues with this kind of implementation.

    In the Test, Step 1, I got the tcode is missing, ok I put it on the url but now the message is:

    “Input Parameter “tcode” is not exists “

    tcode is not exist.png

    I know that I will need a transaction code: “zalvreport” but I don’t know how it’s the best way or option to create it, I see some blogs on internet that explain process in the tcode se93 but I don’t feel able to create all stuff.

    Could you explain me please how it’s the best way to create the transaction and how can I run the:

    SELECT SINGLE pgmna

       INTO _pgmna

       FROM tstc

       WHERE tcode = _tcode.

    Thanks before hand.

    F.G.

    (0) 
    1. Basar Ozgur Kahraman Post author

      Hi Felipe,

      This tool is using your EXISTING tcodes that creates ALV outputs so you don’t need to create a tcode. You pass any tcode that EXIST in your system. There isn’t any ‘zalvreport’ tcode in your system so you get this error.

      Regards

      Basar Ozgur

      (0) 
          1. Felipe Granda

            Hi Basar,

            I check your link and I implemented as a program into my SAP system on the SE80 with the name zprogramtest,

            Then I created a transaction code “zalvreport” in the: SE93, with short text, and with “Program and selection screen (Report Transaction)”,

            After that, I linked the zprogramtest on the new transaction zalvreport in the “program” input and save

            Restart my service and… It works! thank you so much, thumbs up!

            Return json.png

            So the last conclusion it’s we need to implement ALV report according with the need, so the create a tcode and launch in the webservice.

            Thanks again!

            F.G.

            (0) 

Leave a Reply