Skip to Content

HCM Processes & Forms: validations with Generic Services

I will continue with my previous blog HCM Processes & Forms: default fields with Generic Serivices, where I explained how to default fields using Generic Services. In this blog I will explain how to perform validations using Generic Services, keep in mind that for simplicity’s sake, I created an example which makes no sense in real life, my intention is creating a step by step as basic and as easy to follow as possible, so you can use this idea to start building real things.

First off I recommend you reading this excellent blog about “required fields” by P&F Guru Chris Solomon HCM Processes & Forms: Required fields aren’t what they use to be!, it contains a theorical background about what I will show here, with very usefull tips and warnings.


We will use the same example that we used in the previous blog;  we have a very basic process form that creates a record for Infotype 0022 “education”, it will display the employees name and let the user enter data for Institute, Certificate, Education establishment, Final Grade and  Branches:


If we test it In the portal:


This form has already the standard validations offered by end service SAP_PA or BADIs for decoupled infotypes, but if we have validations in user exits or old PBO BAdIs they won’t get triggered, so we should implement them using Generic Services


The first step is creating the definition of the generic service, for that, in transaction HRASR_DT press “Definition”


 Then give a name to the new generic service:


After that, you have to create the BAdI that will contain all the logic for your generic service, press “Functionality by BAdI”:


 Press “Create”


Give a name to the enhancement implementation:


And then give a name to the BAdI and Implementation Class. We will use the BAdI definition “HRASR00GEN_SERVICE_BASIC” as the BAdI Definition:


After that, you can go to SE19 to continue the BAdIs creation.


The first step will be creating the Filter Value, if you don’t do so, you will receive a message in the workbench saying that you have created more than 1 implementation for the generic service.


The Filters name must be the same as the name of the Generic Service, here is where you link the BAdI with the Generic Service:


Then go to your class implementation, the first thing you have to do is indicate the operations that this Class is going to support, for our example, we are going to use this Class to perform 2 operations:

1) Validate that a field is not empty

2) Validate that a field has a value bigger than 1


We have to indicate our operations in the method GET_OPERATIONS, this method exports a table with these fields:


In this table you indicate the operations and the fields that this operation needs to work properly.

For the two operations that we are going to create, we only need a parameter for each one, if you need more parameters to perform an operation, for example a validation like this “if field x is bigger than 10 then field y must be bigger than 100″ you can add both fields x and y to the same operation.



  DATA operation TYPE hrasr00gs_operation.
  CLEAR operations.
  CLEAR operation.

  operation-operation = ‘OP_NO_EMPTY’.
  APPEND ‘field1’ TO operation-fieldnames.
*  APPEND ‘field2’ TO operation-fieldnames. “if I needed more than a field for my operation…
  APPEND operation TO operations.

  CLEAR operation.
  operation-operation = ‘OP_BIGGER_1’.
  APPEND ‘field1’ TO operation-fieldnames.
  APPEND operation TO operations.

  CLEAR operation.



In the previous code we created these operations

  • OP_NO_EMPTY: will receive a parameter called field1
  • OP_BIGGER_1: Will receive a parameter called field1


Keep in mind that this method wont execute at runtime but in design time, so that when you add this Generic Service in the HRASR_DT workbench it will read this method to show you which operations it provides, later on you will see this more clearly.


After this we have to go to method DO_OPERATIONS, this method does will execute a runtime, and will be called every time you press the button “Check” in your form. Within this method you have to develop the operations that we created in the method GET_OPERATIONS.


This method receives 2 important tables:


1)   service_operations: This table will have the operations that this Generic Service supports and the field groups assigned to the operations.

We already know the supported operations, because we created them in the GET_OPERATIONS method, but we don’t know the field groups, because they will be assigned to the operations at design time in the workbench HRASR_DT.


2)   service_dataset: Thia table will contain the field groups, the fields assigned to the field groups, and the fields values.



The logic that we should use to perform our validations should be the following:


1)       Search in table service_operations what are the field groups assigned to our operations

2)       With the field groups of step 1, retrieve the fields assigned to this field groups

3)       Perform the ‘operation’ to step 2 fields. In our example, it would mean validate that they are not empty and bigger than 1 (we have 2 operations).


Finally the code for this method would look like this:



  DATA service_operation TYPE hrasr00genserv_operation.
  DATA service_dataset TYPE hrasr00gensrv_dataset.
  DATA message_dummy TYPE string.
  DATA message TYPE symsg.

*  Operation to check that a field is not empty (error message otherwise)
   read table service_operations INTO service_operation with key operation = ‘OP_NO_EMPTY’.

   loop at service_datasets into service_dataset where FIELDGROUP = service_operation-FIELDGROUP.

    if service_dataset-FIELDVALUE is initial.

      MESSAGE ID ‘HRASR00_PROC_CONTENT’ TYPE ‘E’ NUMBER ‘013’ INTO message_dummy with ‘Field cant be empty’.
      MOVE-CORRESPONDING sy TO message.
      message_handler->add_message( EXPORTING message = message ).



*  Operation to check that a field is bigger than 1 (error message otherwise)
   read table service_operations INTO service_operation with key operation = ‘OP_BIGGER_1’.

   loop at service_datasets into service_dataset where FIELDGROUP = service_operation-FIELDGROUP.

    if service_dataset-FIELDVALUE <= 1.

      MESSAGE ID ‘HRASR00_PROC_CONTENT’ TYPE ‘E’ NUMBER ‘013’ INTO message_dummy with ‘Field must be bigger than 1’.
      MOVE-CORRESPONDING sy TO message.
      message_handler->add_message( EXPORTING message = message ).





After activating everything, we can go back to the P&F workbench.


First thing we have to do is assigning the Generic Service to our Form Scenario: 



After that, double click in node “Field groups and operations” of our Generic Service.


Here we have to create the field groups, we will create 2 fields groups, in the drop down combo the Generic Service will provide the operations created in the method GET_OPERATIONS:


Then we have to go to node “Fields” of our Generic Service, there we will map the fields that we want to be validated to the corresponding field group:



In our example, we will validate the following:


Fields that cant be empty (will be mapped to field group GR_NO_EMP):

  • Branch of study 1
  • Branch of study 2

Fields that must have values bigger than 1 (will be mapped to field group GR_BIGG_1):

  • Final Grade



As you see, we never map the fields to the Generic Service operation, rather we use the field group, this would act as an interface with the Class that we developed before.


If we test the form, and enter a Final grade smaller than 1, and we leave empty one of the two branches the Generic Service triggers the validations correctly:


The validation works, but it is really too generic, it cant show anything else rather than a generic message, it does not even tell which field in the form is validating.


A solution for this would be of course develop a Generic Service not that Generic, so you would create it specifically for your Form, this Generic Service would trigger messages and perform validations very specific to the fields of your form. The drawback here would be that this Generic Service might not be reusable in other Forms.


It also might happen that you want to perform validation for some Scenario steps only, for example in a payment you want a validation for a maximum amount for all Scenario steps except the one assigned to the manager, to achieve that you could use variable FORM_SCENARIO_STAGE which has the value of the current scenario step, for this you should add this field with the method GET_SPECIAL_FIELDS, the procedure to add this kind of “special fields” was explained in my previous blog HCM Processes & Forms: default fields with Generic Serivices


I hope this information was useful to you, I tried to explain it in the way I had wanted it to be explained to me, if you have any question in this subject please leave a message, I will try to go on with blogs about this topic.

You must be Logged on to comment or reply to a post.
  • First off, thanks for the "shout out" in your blog. haha I don't think of myself as the "P&F guru"....just more as "one of the people who stumbled upon it early on and shared with others so they didn't have as painful as an experience in learning it". hahaha

    Second...well, done. It's not really an easy thing to cover (which is why I never bothered before). You did it quite well in a simple way that folks will hopefully understand the underlying steps involved and then expand to fit their needs.

    Looking forward to more!

  • I spent a lot of time trying to understand generic services when initially working with HCM P&F back in '08 (EhP2). Pretty much zero info from SAP on the subject so it was pretty much a case of work it out for yourself - and read the many excellent blogs by Mr Solomon of course!

    This blog plugs a very necessary gap and is well articulated - well done.

    Although I no longer work in this area, I remain keenly interested in the evolution of HCM P&F. I look forward to reading more of your blogs.

  • I know the post is too old but we do have a requirement with some old object here.

    Can you tell me what decides how the field will be presented on screen? As in, how do we set a field as BUTTON in my specific case. In the tutorial above you have explained how an input field can be manipulated/validated using generic service. So, how an object is represented in output, is that also defined somewhere in the service itself? Any help would be highly appreciated.