Skip to Content

This document is part 5 of what builds on my other example:  “Part 4: basic HCM Process and Forms scenario (Include a DropDown List for Country Selection)” which can be accessed at: http://scn.sap.com/docs/DOC-35588

Backend Services are important components of HCM Processes and Forms.  Let’s create one to validate that the form user only selects country code “USA”. This example uses the configuration and form development we was completed in the prior example:  “Part 4”.

Note:  You normally want to call a Backend Service when a user presses the “Check and Send” button on your form.  This is a common scenario to validate what was entered.  However, there are instances when you want to call a Backend Service to be called when the form is loading.  For example, you might have a position ID being sent to the form.  For this position, you wish to also display the position holder name and employee number, you can also use a BE service for that too.  However, there is a slight difference.  When you want to call a Backend Service on form load, you use the Initialize Method of the Backend Service.  For a normal “Check and Send” Scenario, you use the Do Operations method of the Backend Service.

Follow this path:

/wp-content/uploads/2013/01/pic__180282.jpg

Go into this node and you will see something similar to the following:

/wp-content/uploads/2013/01/pic__180282.jpg

Select “New Entries” at the top and put in your Backend Service Key and Backend Service Name, like:

/wp-content/uploads/2013/01/pic__180282.jpg

I used “ZGS_COUNTRY_VALIDATION” for the Backend Service Key Name.  Save your entries.  At this point you have defined a generic service.  Now we need to “implement” code for the service.

Follow this path:

/wp-content/uploads/2013/01/pic__180282.jpg

When you execute this node, you will get a pop-up window showing all existing “generic services”.

Click the “Create Implementation” icon and you will be prompted with the following:

/wp-content/uploads/2013/01/pic__180282.jpg

Select the green check and complete the implementation properties information like the following:

/wp-content/uploads/2013/01/pic__180282.jpg

You will then be prompted to supply the properties information for the Badi Implementation and Implementing Class:

/wp-content/uploads/2013/01/pic__180282.jpg

Use the following naming format:

•             BAdI Implementation:  ZHRASR_(service key without prefix for ZGS or ZAS)

•             Implementation class:  ZCL_HRASR_(service key without prefix for ZGS or ZAS)

So for our service key of “ZGS_COUNTRY_VALIDATION “, the entries would be:

ZHRASR_COUNTRY_VALIDATION

ZCL_HRASR_COUNTRY_VALIDATION

Results:

/wp-content/uploads/2013/01/pic__180282.jpg

Continue and Save your implementation – you will see the following screen:

/wp-content/uploads/2013/01/pic__180282.jpg

Now we need to give this implementation a unique Service ID by which HCM Process & Forms can call it.

Double Click on the “Filter Val.” as shown in the screen shot below:

/wp-content/uploads/2013/01/pic__180282.jpg

Click the “Create Filter Combination” button.  Your screen now looks like:

/wp-content/uploads/2013/01/pic__180282.jpg

Double-click the “????” under “Value 1” and complete the filter for your service ID:

/wp-content/uploads/2013/01/pic__180282.jpg

Select Continue and save and activate your work.

You have now created a definition and implementation for your backend service.  You have not put any logic into theservice.  That comes next.  Click on the “Technical Details” tab and find the class name for your implementation:

/wp-content/uploads/2013/01/pic__180282.jpg

The class name in this example is: ZCL_HRASR_COUNTRY_VALIDATION and you can edit the class in transaction SE24 directly.

The first item to take care of is defining attributes of the class.  Every BE Service should have an attribute which stores the name of the BE Service.  There should also be an attribute which stores the name of the operation being performed.  There could be more than one operation defined in a single backend service.  Lastly, for each form field being passed to the BE Service both the field name and field data type need to be defined in the attributes.   Define the following attributes:

C_GENERIC_SERVICE_NAME    Type: ASR_FORM_SCENARIO_SERVICE    Value: ‘ZGS_COUNTRY_VALIDATION’

C_OPER_CHECK_STATE    Type: ASR_BACKEND_OPERATION    Value: ‘CHECK_COUNTRY’

C_FLD_COUNTRY    Type: FIELDNAME    Value: ‘LAND1’

C_DTEL_ COUNTRY    Type: ASR_FIELD_DATA_ELEMENT_NAME    Value: ‘LAND1’

Results:

/wp-content/uploads/2013/01/pic__180282.jpg

So basically, you have defined the unique name of you BE service in your attributes.  You have also defined one operation: “CHECK_COUNTRY”.  Remember, you can have more than one operation.  Also, you defined the field name and field data type.  These are definitions of all the fields that you expect to pass between the form and the BE Service.

Now you can go to the methods tab and start implementing them.  There are some method definitions already defined:

/wp-content/uploads/2013/01/pic__180282.jpg

*Note: if you ever want to see how SAP defines some of their own BE Services, you can do a search in SE24 for “CL_HRASR00_GS*”.

First: create a new method in your class as follows:

Name:  GET_FIELDS_OF_OPERATION

Level:  Instance Method

Visibility:  Private

Description:  Determine Fields/Parameters of Operation

/wp-content/uploads/2013/01/pic__180282.jpg

Define the following parameters for this method:

OPERATION    Importing  Type  ASR_BACKEND_OPERATION

FIELDNAMES  Returning  Type  HRBAS_FIELDLIST_TAB

/wp-content/uploads/2013/01/pic__180282.jpg

Add the following code to the method:

  clear fieldnames.
 
case operation.
   
when c_oper_check_state.
     
append c_fld_country to fieldnames.
   
when others.
     
assert 1 = 0. “called for an operation that is not supported
 
endcase.

Now create a new method as follows:

Name:  EXTRACT_RELEVANT_DATASETS

Level:  Instance Method

Visibility:  Private

Description:  Extract Data Records Relevant for Field Group

/wp-content/uploads/2013/01/pic__180282.jpg

Define the following parameters for this method:

FIELDGROUP  Importing  Type  ASR_FIELD_GROUP

OPERATION  Importing  Type  ASR_BACKEND_OPERATION

SERVICE_DATASETS  Importing  Type  HRASR00GENSRV_DATASET_TAB

HELP_DATASETS  Importing  Type  HRASR00GS_HELP_DATASET_TAB

RELEVANT_SERVICE_DATASETS  Exporting  Type  HRASR00GENSRV_DATASET_TAB

RELEVANT_HELP_DATASETS  Exporting  Type  HRASR00GS_HELP_DATASET_TAB

/wp-content/uploads/2013/01/pic__180282.jpg

Add the following code to this method:

  data relevant_help_dataset_wa type hrasr00gs_help_dataset.
 
data current_index type i.

  clear relevant_service_datasets.
 
clear relevant_help_datasets.

  data operation_fieldnames type hrbas_fieldlist_tab.

  operation_fieldnames = get_fields_of_operation( operation ).
  relevant_service_datasets
= service_datasets.

  delete relevant_service_datasets where fieldgroup <> fieldgroup.

  relevant_help_datasets = help_datasets.

  loop at relevant_help_datasets into relevant_help_dataset_wa.
    current_index
= sytabix.
   
read table operation_fieldnames transporting no fields

           with key table_line = relevant_help_dataset_wafieldname.
   
if sysubrc <> 0. “field is not relevant
     
delete relevant_help_datasets index current_index.
   
endif.
  endloop.

Now create a new method as follows:

Name:  RESTORE_RELEVANT_DATASETS

Level:  Instance Method

Visibility:  Private

Description:  Return Data Records Relevant for Field Group

/wp-content/uploads/2013/01/pic__180282.jpg

Define the following parameters for this method:

FIELDGROUP  Importing  Type  ASR_FIELD_GROUP

OPERATION  Importing  Type  ASR_BACKEND_OPERATION

RELEVANT_SERVICE_DATASETS  Importing  Type  HRASR00GENSRV_DATASET_TAB

RELEVANT_HELP_DATASETS  Importing  Type  HRASR00GS_HELP_DATASET_TAB

SERVICE_DATASETS  Changing  Type  HRASR00GENSRV_DATASET_TAB

HELP_DATASETS  Changing  Type  HRASR00GS_HELP_DATASET_TAB

/wp-content/uploads/2013/01/pic__180282.jpg

Add the following code to this method:

  data relevant_service_dataset_wa type hrasr00gensrv_dataset.
 
data service_dataset_wa type hrasr00gensrv_dataset.
 
data relevant_help_dataset_wa type hrasr00gs_help_dataset.

  field-symbols <service_dataset_wa> type hrasr00gensrv_dataset.
 
field-symbols <relevant_service_dataset_wa> type hrasr00gensrv_dataset.
 
field-symbols <help_dataset_wa> type hrasr00gs_help_dataset.

  data operation_fieldnames type hrbas_fieldlist_tab.

  operation_fieldnames = get_fields_of_operation( operation ).

 
loop at relevant_service_datasets assigning <relevant_service_dataset_wa> where fieldgroup = fieldgroup.
   
read table service_datasets into service_dataset_wa
              
with key fieldgroup = <relevant_service_dataset_wa>fieldgroup
                        fieldname
= <relevant_service_dataset_wa>fieldname
                        fieldindex
= <relevant_service_dataset_wa>fieldindex.
   
if sysubrc = 0.
      service_dataset_wa
= <relevant_service_dataset_wa>.
     
modify service_datasets index sytabix from service_dataset_wa.
   
else.
      service_dataset_wa
= <relevant_service_dataset_wa>.
     
append service_dataset_wa to service_datasets.
   
endif.
 
endloop.

 
loop at service_datasets into service_dataset_wa
where fieldgroup = fieldgroup and fieldindex > 1.
   
read table relevant_service_datasets into relevant_service_dataset_wa
              
with key fieldgroup = service_dataset_wafieldgroup
                        fieldname
= service_dataset_wafieldname
                        fieldindex
= service_dataset_wafieldindex.
   
if sysubrc <> 0.
     
delete service_datasets.
   
endif.
 
endloop.

 
loop at help_datasets assigning <help_dataset_wa>.
   
read table operation_fieldnames transporting no fields
              
with key table_line = <help_dataset_wa>fieldname.
   
if sysubrc <> 0.
     
continue.
   
endif.

    read table relevant_help_datasets into relevant_help_dataset_wa
              
with key fieldname = <help_dataset_wa>fieldname
                        fieldindex
= <help_dataset_wa>fieldindex.
   
if sysubrc = 0.
      <help_dataset_wa>
= relevant_help_dataset_wa.
   
endif.
 
endloop.

Now insert the following code into method GET_FIELD_INFO:

  data field_info type hrasr00gs_field_info.
 
data service_field type fieldname.
 
clear field_infos.

  loop at service_fields into service_field.
   
case service_field.
     
when c_fld_country.
       
clear field_info.
        field_info
fieldname = c_fld_country.
        field_info
field_data_element_name = c_dtel_country.
        field_info
supports_value_help = space.
        field_info
supports_default_value = space.
       
append field_info to field_infos.
   
endcase.
 
endloop.

Now insert the following code into method GET_OPERATIONS:

  data operation type hrasr00gs_operation.
 
clear operations.
 
clear operation.

  operationoperation = c_oper_check_state.
  operation
fieldnames = get_fields_of_operation( operationoperation ).
 
append operation to operations.

Now create a new method as follows:

Name:  DO_OPERA_CHECK_COUNTRY

Level:  Instance Method

Visibility:  Private

Description:  Check Valid Country

/wp-content/uploads/2013/01/pic__180282.jpg

Define the following parameters for this method:

SPECIAL_FIELDS  Importing  Type  HRASR00VALUE_OF_FIELD_TAB

NO_AUTH_CHECK  Importing  Type  BOOLE_D

MESSAGE_HANDLER  Importing  Type Ref To  IF_HRBAS_MESSAGE_HANDLER

HELP_DATASETS  Changing  Type  HRASR00GS_HELP_DATASET_TAB

SERVICE_DATASETS  Changing  Type  HRASR00GENSRV_DATASET_TAB

/wp-content/uploads/2013/01/pic__180282.jpg

Add the following code to the method:

  data message type symsg.
 
data message_dummy type string.
 
field-symbols <service_dataset_fs> type hrasr00gensrv_dataset.
 
data: address_country type land1.
 
read table service_datasets assigning <service_dataset_fs>

with key fieldname = c_fld_country.
 
if sysubrc = 0.
    address_country
= <service_dataset_fs>fieldvalue.
 
endif.

  if ( address_country ne ‘US’ ).
   
messagemsgty = ‘E’.
   
messagemsgno = ‘009’.
   
messagemsgv1 = ‘Please Enter a US Address’.
    message_handler
->add_message( exporting message = message ).
   
exit.
 
endif.

Now insert the following code into method DO_OPERATIONS:

  data service_operation_wa type hrasr00genserv_operation.
 
data help_dataset type hrasr00gs_help_dataset.
 
data relevant_help_datasets type hrasr00gs_help_dataset_tab.
 
data relevant_service_datasets type hrasr00gensrv_dataset_tab.
 
data message_dummy type string.
 
data message type symsg.

  loop at service_operations into service_operation_wa.
    call method me->extract_relevant_datasets
     
exporting
        fieldgroup               
= service_operation_wafieldgroup
        operation                
= service_operation_waoperation
        service_datasets         
= service_datasets
        help_datasets            
= help_datasets
     
importing
        relevant_service_datasets
= relevant_service_datasets
        relevant_help_datasets   
= relevant_help_datasets.

    case service_operation_waoperation.
     
when c_oper_check_state.
       
call method me->do_opera_check_country
         
exporting
            special_fields  
= special_fields
            no_auth_check   
= no_auth_check
            message_handler 
= message_handler
         
changing
            help_datasets   
= relevant_help_datasets
            service_datasets
= relevant_service_datasets.
     
when others.
       
message e102(hrasr00_genserv) with service_operation_waoperation c_generic_service_name
                                     
into message_dummy.
       
move-corresponding sy to message.
        message_handler
->add_message( exporting message = message ).
       
return.
   
endcase.

   
call method me->restore_relevant_datasets
     
exporting
        fieldgroup               
= service_operation_wafieldgroup
        operation                
= service_operation_waoperation
        relevant_service_datasets
= relevant_service_datasets
        relevant_help_datasets   
= relevant_help_datasets
     
changing
        service_datasets         
= service_datasets
        help_datasets            
= help_datasets.
 
endloop.

Now your method for the Backend Service is complete.  Yes, there is a lot of code added to methods in your class.  The good news is that once you have done this once, any other Backend Services you create, will model the same code.  So, you might want to create a template that you can always use.  The only thing left is to map the Backend Service to the fields in your process configuration.

Call Up Transaction: HRASR_DT and select your process from the drop down.  Under Form Scenarios, double click Back-End Services:

/wp-content/uploads/2013/01/pic__180282.jpg

Insert an entry for your newly created Backend Service:

/wp-content/uploads/2013/01/pic__180282.jpg

Expand “Field Groups and Operations”:

/wp-content/uploads/2013/01/pic__180282.jpg

Create the Field Group: FG1 and Choose Your Operation: CHECK_COUNTRY

/wp-content/uploads/2013/01/pic__180282.jpg

Expand “Fields”:

/wp-content/uploads/2013/01/pic__180282.jpg

Define the following field:

/wp-content/uploads/2013/01/pic__180282.jpg

Now is a good time to test.  You can either logon to the portal and select your process or launch directly using:

http://yourserver.com/sap/bc/webdynpro/sap/asr_process_execute?sap-client=<yourclient #>&sap-language=EN

   

Result (choosing country other than US):

/wp-content/uploads/2013/01/pic__180282.jpg

As you can see, the logic in the Backend Service was executed and threw an error when a country other than “US” was selected..

To report this post you need to login first.

8 Comments

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

  1. Gaurang Gujar

    Hi Philip,

    Excellent and Exceptional Document,infact the Best I found on SDN.

    Yes there is actually a lot of code in Part 5 Basic HCM Process and Scenario was little tiresome job understanding the code would have been great if you can put some inline comments in the code. 🙂

    Regards,

    Gaurang

    (0) 
      1. kalikinkar lahiri

        Hi Philip,

        Great Post !! After reading this, I have few doubts on Field transferring –

        Back end Service is using a Field LAND1. In the Form we have field defined on Same name. Is this necessary to have same name as Form Scenario field as defined in Service field of the back end service ?

        Regards,

        Kalikinkar

        (0) 
      2. Bashir Ahmad

        Hi Philip,

        Nice documents, but this part is bit tricky as i am very new in Process & Forms area and have such commend over programming i am trying to paste same code as it is but facing one problem in specially where you define

        GET_FIELDS_INFO

        DO_OPERATIONS

        GET_OPERATIONS

        Where should i paste your code for these methods because it troughs me errors.

        and i also did not define anywhere as you ask to define 

        Name:  DO_OPERA_CHECK_COUNTRY

        Level:  Instance Method

        Visibility:  Private

        Description:  Check Valid Country

        /wp-content/uploads/2015/05/pic__703869.jpg

        Define the following parameters for this method:

        SPECIAL_FIELDS  Importing  Type  HRASR00VALUE_OF_FIELD_TAB

        NO_AUTH_CHECK  Importing  Type  BOOLE_D

        MESSAGE_HANDLER  Importing  Type Ref To  IF_HRBAS_MESSAGE_HANDLER

        HELP_DATASETS  Changing  Type  HRASR00GS_HELP_DATASET_TAB

        SERVICE_DATASETS  Changing  Type  HRASR00GENSRV_DATASET_TAB

        Kindly do help me out, thanks in advance for your help.

        Regards;

        Bashir

        (0) 
  2. Prashanth Ledehlla

    Hi,

    I have a small doubt. Why you have added other methods? As SAP is providing standard methods like Initialize, Do Operations, Get_Operations etc. we can write the code here right? Please correct me if I am wrong.

    (0) 
    1. Christopher Solomon

      “Initialize” and “do operations” are the “public” methods that come from the “interface” that you base your generic service on. There is nothing stopping you from adding additional methods….and in fact, it is VERY common as you modularize your own work into reusable code. It helps to understand the interface methods (when/where they are used) and then design your own class accordingly.

      (0) 

Leave a Reply