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: 
RonaldKonijnenb
Contributor

When I was reading excellent post about michael.hardenbol/blog/2010/12/07/android-and-restful-web-service-instead-of-soap by Michael Hardenbol I was wondering how to make some useful tool using presented techinques.

I decided to make some handy service for workflows based on standard User Decision step type (which is backed by DECISION object type). This service can be consumed by mobile - I've tested it with Android example application.

Of course you must consider all  security issues - presented approach uses no middleware, it depends of many factors when you can decide to use this kind of service.

The Service

ICF service concept is simple - allow to download list of decision workitems (http GET request) and send user's decision back (PUT request).

For testing purposes the current user is taken from request headers (sap-user etc.) and switched on as a simple http service.Of course in production environment enable some stronger security available in ICF's logon procedures. You can also make some additional layer for checking user credentials.

The service have one handler class, which supports GET and PUT. I present some basic version for just for showing idea - think about potential vulnerabilities  and implement suitable protection.

METHOD if_http_extension~handle_request.

   TYPES: BEGIN OF ty_wi_info,
           wi_id     TYPE swr_struct-workitemid,
           wi_title  TYPE swr_wihdr-wi_text,
           wi_text   TYPE STANDARD TABLE OF swr_txtlin WITH NON-UNIQUE DEFAULT KEY,
           wi_htext  TYPE STANDARD TABLE OF swr_txtlin WITH NON-UNIQUE DEFAULT KEY,
           decisions TYPE STANDARD TABLE OF swr_decialts WITH NON-UNIQUE DEFAULT KEY,
          END OF ty_wi_info.

   DATA: verb        TYPE string,
         path        TYPE string,
         rc          TYPE sy-subrc,
         split_tab   TYPE TABLE OF string,
         param1      TYPE string,
         param2      TYPE string,
         res_xml     TYPE xstring,
         dec_key     TYPE swr_decikey,
         dec_wiid    TYPE swr_struct-workitemid,
         wi_text     TYPE swr_wihdr-wi_text,
         nodes       TYPE TABLE OF swr_decialts,
         items       TYPE TABLE OF swr_wihdr,
         t_wi_info   TYPE TABLE OF ty_wi_info,
         wi_info     TYPE ty_wi_info.

   FIELD-SYMBOLS: <item> LIKE LINE OF items.

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

   IF verb <> 'GET' AND verb <> 'PUT'.
     CALL METHOD server->response->set_header_field(
       name = 'Allow' value = 'GET, PUT' ).
     CALL METHOD server->response->set_status( code = '405' reason = 'Method not allowed' ).
     EXIT.
   ENDIF.

   path = server->request->get_header_field( name = '~path_info' ).
   SHIFT path LEFT BY 1 PLACES.
   SPLIT path AT '/' INTO TABLE split_tab.

   CASE verb.  "Get user decisions to make...
     WHEN 'GET'.

       CALL FUNCTION 'SAP_WAPI_WORKITEMS_TO_OBJECT'
        EXPORTING
          objtype                        = 'DECISION'
          top_level_items                = ' '
*     SELECTION_STATUS_VARIANT       = 0001     "active items
        IMPORTING
          return_code                    = rc
         TABLES
*     TASK_FILTER                    =
           worklist                       = items
*     MESSAGE_LINES                  =
*     MESSAGE_STRUCT                 =.
.
       IF rc <> 0.
         CALL METHOD server->response->set_status( code = '500' reason = 'Error (RC <> 0' ).
         RETURN.
       ENDIF.

       LOOP AT items ASSIGNING <item> WHERE wi_aagent = sy-uname.

         "get details
         CLEAR: rc, wi_info, wi_text, nodes.
         CALL FUNCTION 'SAP_WAPI_DECISION_READ'
           EXPORTING
             workitem_id          = <item>-wi_id
          IMPORTING
            return_code          = rc
            decision_title       = wi_text
           TABLES
             alternatives         = nodes
*           MESSAGE_LINES        =
*           MESSAGE_STRUCT       =
                   .
         IF rc <> 0.
           CALL METHOD server->response->set_status( code = '500' reason = 'Error (RC <> 0' ).
           RETURN.
         ENDIF.

         wi_info-wi_id = <item>-wi_id.
         wi_info-wi_title = wi_text.
         wi_info-decisions = nodes.

         CLEAR rc.
         CALL FUNCTION 'SAP_WAPI_WORKITEM_DESCRIPTION'
           EXPORTING
             workitem_id     = <item>-wi_id
           IMPORTING
             return_code     = rc
           TABLES
             text_lines      = wi_info-wi_text
             html_text_lines = wi_info-wi_htext.

         APPEND wi_info TO t_wi_info.

       ENDLOOP.

       CALL TRANSFORMATION zwitoxml
         SOURCE root = t_wi_info
         RESULT XML res_xml.

       CALL METHOD server->response->set_header_field(
         name = 'Content-Type'
         value = 'text/xml; charset=utf-8' ).

       CALL METHOD server->response->set_data( data = res_xml ).
       CALL METHOD server->response->set_status( code = '200' reason = 'OK' ).

       RETURN.

     WHEN 'PUT'.

       READ TABLE split_tab INTO param1 INDEX 2.   ".../wi_id/NNNNNNNNN/decision/NNNN
       READ TABLE split_tab INTO param2 INDEX 4.

       dec_key = param2.
       dec_wiid = param1.

       CLEAR rc.
       CALL FUNCTION 'SAP_WAPI_DECISION_COMPLETE'
         EXPORTING
           workitem_id  = dec_wiid
           decision_key = dec_key
         IMPORTING
           return_code  = rc.

       IF rc <> 0.
         CALL METHOD server->response->set_status( code = '500' reason = 'Error (RC <> 0' ).
       ELSE.
         CALL METHOD server->response->set_status( code = '200' reason = 'OK' ).
       ENDIF.

   ENDCASE.

ENDMETHOD.

GET action returns XML with running decision tasks for calling user. It's using standard WAPI methods for getting list of tasks and all possible decisions.

XML is generated with Simple Transformation:

<?sap.transform simple?>

<tt:transform xmlns:tt="http://www.sap.com/transformation-templates">

  <tt:root name="ROOT"/>

  <tt:template>

    <workitems>

      <tt:loop name="line" ref=".ROOT">

        <workitem>

          <id>

            <tt:value ref="$line.wi_id"/>

          </id>

          <title>

            <tt:value ref="$line.wi_title"/>

          </title>

          <description>

            <tt:loop name="html" ref="$line.wi_text">

                 <tt:value ref="$html.TEXTLINE"/>

            </tt:loop>

          </description>

          <decisions>

            <tt:loop name="dec_line" ref="$line.decisions">

              <decision>

              <key>

                <tt:value ref="$dec_line.ALTKEY"/>

              </key>

              <text>

                <tt:value ref="$dec_line.ALTTEXT"/>

              </text>

              </decision>

            </tt:loop>

          </decisions>

        </workitem>

      </tt:loop>

    </workitems>

  </tt:template>

</tt:transform>

Each task has unique id, some title and description.

Each decision has four digit key (0001, 0002) and decribing text.

PUT action handles user decision sended in url: .../wi_id/NNNNNNNNN/decision/NNNN - after wi_id we have task id and after decision - decision number.

After parsing incoming data standard WAPI module is used for finishing decision task.

I made some example Android application to test. It connects to service via AsyncTask and downloads xml with awaiting decision tasks.

Business Workplace:

application:

Selecting one item shows work item details and possible decisions:

tapping button connects to service via PUT request and completes workitem.

Item is completed and removed from Business Workplace.

2 Comments
Labels in this area