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: 
johannes_konings
Participant
0 Kudos

Normally for the SAP Business Workflow with the transaction SBWP classic Dynpros are used for user interaction. Now I had the requirement to combine SAP Business Workflow with WebDynpro (WDA) to substitute the classical Dynpro.

The reason was the WebDynpro advantage over classical Dynpro.


For that i had first to create two classes:


1. WF-Class (Z_WD_WF_CLASS)


Create a class which is used in the wf task (In this case Z_WD_WF_CLASS).This class requires the interface IF_WORKFLOW, but an implementation is not required.

This class starts the WebDynpro application using the WF-task (Step 4.).

On the method OPEN_WD of class Z_WD_WF_CLASS the WebDynpro application is started. The WI_ID is passed as a URL parameter.





class Z_WD_WF_CLASS definition
  public
  final
  create public .
public section.
  interfaces BI_OBJECT .
  interfaces BI_PERSISTENT .
  interfaces IF_WORKFLOW .
  class-methods OPEN_WD
    importing
      !_WORKITEM type SIBFLPOR
    returning
      value(_WI_OBJECT_ID) type ref to Z_WD_WF_CLASS .
protected section.
private section.
ENDCLASS.
CLASS Z_WD_WF_CLASS IMPLEMENTATION.
METHOD open_wd.
  DATA lt_parameters TYPE tihttpnvp.
  DATA ls_parameters LIKE LINE OF lt_parameters.
  ls_parameters-name = 'WI_ID'.
  ls_parameters-value = _workitem-instid+20.    "Name muss so sein
  APPEND ls_parameters TO lt_parameters.
  CALL FUNCTION 'WDY_EXECUTE_IN_BROWSER'
    EXPORTING
*     PROTOCOL                =
      application             = 'Z_WD_WF_FORM'
      parameters              = lt_parameters
*     TRY_TO_USE_SAPGUI_THEME = ''
    EXCEPTIONS
      invalid_application     = 1
      browser_not_started     = 2
      action_cancelled        = 3
      OTHERS                  = 4.
  IF sy-subrc <> 0.
* Implement suitable error handling here
  ENDIF.
ENDMETHOD.
ENDCLASS.





2. WF-Event-Class (Z_WD_WF_EVENT_CLASS)


This class also requires the interface IF_WORKFLOW and has two events (APPROVE and REJECT), which can be fired on the WebDynpro application. The link to the WF-task is a GUID.

The static method GET_EVENT_OBJECT creates an object of class Z_WD_WF_EVENT_CLASS with a GUID, which will be passed to the WF-task data binding (Step 4). The other methods are necessary to the use of the WF task with the class.



class Z_WD_WF_EVENT_CLASS definition
  public
  final
  create public .
public section.
  interfaces BI_OBJECT .
  interfaces BI_PERSISTENT .
  interfaces IF_WORKFLOW .
  events APPROVE .
  events REJECT .
  methods CONSTRUCTOR
    importing
      !I_GUID_16 type GUID_16 .
  class-methods GET_EVENT_OBJECT
    returning
      value(RO_EVENT_OBJECT) type ref to Z_WD_WF_EVENT_CLASS .
protected section.
private section.
  data M_GUID_16 type GUID_16 .
  data M_SIBFLPOR type SIBFLPOR .
ENDCLASS.
CLASS Z_WD_WF_EVENT_CLASS IMPLEMENTATION.
method BI_OBJECT~DEFAULT_ATTRIBUTE_VALUE.
endmethod.
method BI_OBJECT~EXECUTE_DEFAULT_METHOD.
endmethod.
method BI_OBJECT~RELEASE.
endmethod.
METHOD bi_persistent~find_by_lpor.
  DATA lo_wd_wf_event TYPE REF TO z_wd_wf_event_class.
  DATA l_guid_16 TYPE guid_16.
  l_guid_16 = lpor-instid.
  IF l_guid_16 IS INITIAL.
    RETURN.
  ENDIF.
  CREATE OBJECT lo_wd_wf_event
    EXPORTING
      i_guid_16 = l_guid_16.
  .
  result = lo_wd_wf_event.
ENDMETHOD.
METHOD bi_persistent~lpor.
  result = m_sibflpor.
ENDMETHOD.
method BI_PERSISTENT~REFRESH.
endmethod.
METHOD constructor.
  m_sibflpor-catid = 'CL'.
  m_sibflpor-typeid = 'Z_WD_WF_EVENT_CLASS'.
  m_sibflpor-instid = i_guid_16.
  m_guid_16 = i_guid_16.
ENDMETHOD.
METHOD get_event_object.
  DATA lo_system_uuid TYPE REF TO if_system_uuid.
  DATA l_guid_16 LIKE m_guid_16.
  lo_system_uuid = cl_uuid_factory=>create_system_uuid( ).
  l_guid_16 = lo_system_uuid->create_uuid_x16( ).
  CREATE OBJECT ro_event_object
    EXPORTING
      i_guid_16 = l_guid_16.
ENDMETHOD.
ENDCLASS.





Now I can use the classes in the workflow:

3. Workflow

Create any workflow. For this example, I created the following workflow.

4. asynchronous task

The class Z_WD_WF_CLASS with the OPEN_WD method is used for object method of the WF task. These WF-task must be asynchronous because the WF task is terminated by an event.

A container must be created for the Event class Z_WD_WF_EVENT_CLASS.

This allows the two events APPROVE and REJECT are entered in the tab "Terminating events".

Data binding passes the Object Class XX passed with the GUID.


Furthermore, the Web Dynpro application is required:

5. WebDynpro




WDDOINIT in the Componentencontroller:

In WDDOINIT is the ID of the workitem that has been passed through the URL parameters queried.


The workitem ID is passed to the Fuba SAP_WAPI_READ_CONTAINER. Thus, the container contents of Z_WD_WF_EVENT_CLASS of the workitem can be determined.

The object of the container is passed to the WebDynpro.


METHOD wddoinit .

   DATA lo_nd_wf_info TYPE REF TO if_wd_context_node.

   DATA lo_el_wf_info TYPE REF TO if_wd_context_element.
   DATA ls_wf_info TYPE wd_this->element_wf_info.

   ls_wf_info-wi_id = cl_wd_runtime_services=>get_url_parameter( name = 'WI_ID' ).
*
   lo_nd_wf_info = wd_context->get_child_node( name = wd_this->wdctx_wf_info ).
   lo_el_wf_info = lo_nd_wf_info->get_element( ).

   lo_el_wf_info->set_static_attributes(
      static_attributes = ls_wf_info ).

*********************************************************
*  GET EVENT
*************************************************************

   DATA l_workitem_id TYPE swr_struct-workitemid.

   DATA l_return_code TYPE  sy-subrc.
   DATA l_ifs_xml_container TYPE  xstring.
   DATA l_ifs_xml_container_schema  TYPE  xstring.
   DATA l_task_id TYPE swr_struct-task.
   DATA lo_container          TYPE REF TO if_swf_cnt_container.

   DATA lt_simple_container TYPE STANDARD TABLE OF swr_cont.
   DATA lt_message_lines TYPE STANDARD TABLE OF swr_messag.
   DATA lt_message_struct TYPE STANDARD TABLE OF swr_mstruc.
   DATA lt_subcontainer_bor_objects TYPE STANDARD TABLE OF swr_cont.
   DATA lt_subcontainer_all_objects TYPE STANDARD TABLE OF swr_cont.

*  DATA lo_wf_event TYPE REF TO /kibf/nacl_wf_event.
   DATA ls_sibflpor TYPE sibflpor.
   DATA l_guid_16 TYPE guid_16.

   l_workitem_id = ls_wf_info-wi_id.


   CALL FUNCTION 'SAP_WAPI_READ_CONTAINER'
     EXPORTING
       workitem_id              = l_workitem_id
       language                 = sy-langu
       user                     = sy-uname
       buffered_access          = 'X'
     IMPORTING
       return_code              = l_return_code
       ifs_xml_container        = l_ifs_xml_container
       ifs_xml_container_schema = l_ifs_xml_container_schema
     TABLES
       simple_container         = lt_simple_container
       message_lines            = lt_message_lines
       message_struct           = lt_message_struct
       subcontainer_bor_objects = lt_subcontainer_bor_objects
       subcontainer_all_objects = lt_subcontainer_all_objects.


   cl_swf_cnt_factory=>create_task_container(
  EXPORTING
    im_task_id        = 'TSXXXXXXXXX' "ID of the WF task
  IMPORTING
    ex_task_container = lo_container
    ).


   TRY.
     CALL METHOD cl_swf_ifs_conversion_base=>if_swf_ifs_conversion~import_from_ifs_xml
     EXPORTING
       ifs_xml_stream        = l_ifs_xml_container
       target_container      = lo_container
*    import_param          = 'X'
*    export_param          = 'X'
*    local_elements        = 'X'
*    no_system_elements    = SPACE
*  IMPORTING
*    num_elements_imported =
*    error_handle          =
       .
   ENDTRY.

   TRY.

       CALL METHOD lo_container->if_swf_ifs_parameter_container~get
         EXPORTING
           name       = 'Z_WD_WF_EVENT_CLASS'
         IMPORTING
           value      = ls_sibflpor
*         unit       = <fs_unit>
           returncode = l_return_code.


       l_guid_16 = ls_sibflpor-instid.

       CREATE OBJECT wd_this->mo_wd_wf_event_class
         EXPORTING
           i_guid_16 = l_guid_16.


     CATCH cx_swf_cnt_elem_not_found .
     CATCH cx_swf_cnt_elem_type_conflict .
     CATCH cx_swf_cnt_unit_type_conflict .
     CATCH cx_swf_cnt_container .
   ENDTRY.


ENDMETHOD.








V_MAIN->ONACTIONAPPROVE

When the user selects an action, the event object is used and fires the appropriate event (in this example APPROVE).


METHOD onactionapprove .

   DATA ls_sibflpor TYPE sibflpor.

   ls_sibflpor = wd_comp_controller->mo_wd_wf_event_class->bi_persistent~lpor( ).

   TRY.
       cl_swf_evt_event=>raise(
          EXPORTING
            im_objcateg = ls_sibflpor-catid
            im_objtype  = ls_sibflpor-typeid
            im_event    = 'APPROVE'
            im_objkey   = ls_sibflpor-instid
*    im_event_container =
       ).
     CATCH cx_swf_evt_invalid_objtype .
     CATCH cx_swf_evt_invalid_event .
   ENDTRY.

   COMMIT WORK.


ENDMETHOD.










In the instance linkages (transaction SWEINST) you can see the link between GUID (Object Key) and workitem ID (Receiver Key)


Result


By clicking on the button "APPROVE" the event "APPROVE" is fired, thereby terminating the WF task.


Thereafter, the entry in the instance linkages is no longer included.

Other suggestions?

6 Comments
Labels in this area