cancel
Showing results for 
Search instead for 
Did you mean: 

Function Imports - USE

Former Member
0 Kudos

Hi !!

I have been developing OData Services in SEGW and came across Function imports. I went through

https://help.sap.com/saphelp_nw74/helpdata/en/c5/dc22512c312314e10000000a44176d/content.htm

and I still am not clear about it. Could anyone please help me with this ?

Could anyone explain -

  • The use of function imports ?
  • Why use function imports , when we can implement CRUD operations through entities.
  • some scenarios where function imports are used ?
  • When to use function imports and when to implement CRUD through entities.

Accepted Solutions (1)

Accepted Solutions (1)

ChandraMahajan
Active Contributor
0 Kudos

Hi,

Please refer my blog and check the last section on function import.

Regards,

Chandra

Former Member
0 Kudos

Hi !

Thanks for the information. I have already been through your blog, and i found the procedure for creating of function imports, useful . I still am missing clarity on the above mentioned points.

Regards,

Manvitha.

ChandraMahajan
Active Contributor
0 Kudos

Hi,

I guess all your question can be answered based on below information.


The Open Data Protocol (OData) includes standard CRUD (Create, Retrieve, Update, and Delete) operations that map to the HTTP methods POST, GET, PUT/MERGE, and DELETE.

In addition, OData supports further service operations (function imports) that can be invoked by the HTTP methods GET or POST for anything that cannot be mapped to the standard CRUD operations. You can implement such additional service operations in the Service Builder by creating function imports within your data model.

For example, you could create function imports for the following custom operations:

  • Confirm Work Item
  • Check Flight Availability

While it is simple to create new function imports to invoke custom operations, if the operation you want to use can be invoked using a standard CRUD operation, you should not create a function import. That is, you should only create function imports for custom operations that cannot be invoked using a standard operation.

Most important point is, you can go for function import operation for anything that cannot be mapped to the standard CRUD operations.

and the examples are Check flight availability (This will be GET operation) and Confirm Work Item (This will be POST)

Regards,

Chandra

Former Member
0 Kudos

Hi Chandrashekhar ,

I have been referring your blog and found it to be extremely good .

I am trying to use Function imports , however when I try to edit

/IWBEP/IF_MGW_APPL_SRV_RUNTIME~EXECUTE_ACTION , it is asking for an Access key .

Do I need to create an enhancement spot for the same ? (However , this enhancement creation is no where mentioned in your blog )

Please guide me in this .

Also , my scenario is I will be accepting an employee number from the portal and send out relavant details of that employee back to the portal . Is this right approach to be followed ?

Thanks

Supriya

ChandraMahajan
Active Contributor
0 Kudos

1) You need to redefine the method.

2) for your scenario, no need of function import. you can implement get_entity.

Regards,

Chandra

Former Member
0 Kudos

Hi Supriya,

With regard to the scenario, it really depends on the usage context.

1) If this is self-service, then the person will be logging into SAP-HR and SAP-HR can determine their personnel ID from GW login.

In that case you could either have a function import such as 'MyPersonnelID' or preferably, a "Persons" entityset. The latter would actually only return the current person details because the login would be linked to the person.

2) If this is an open query where any person can enter anyone else's person ID then it would be different. That would be a GET on a Person entity with a personnel ID as key. However this should probably be subject to authorisation of the current user if there is any confidentiality or security concern! The service would therefore need to validate the current user role before allowing a response. It's very doubtful that the login would go as far as being anonymous either

Regards

Ron.

Former Member
0 Kudos

Hi Chandrashekhar ,

Will GET_ENTITY work for multiple returning records ?
i.e. all possible Actions againsts that employee ?

Also , how will I pass the PERNR which will come from the portal in this class method ?

Does the signature support this ?

Regards

Supriya

AshwinDutt
Active Contributor
0 Kudos

Hello Supriya,

The READ/Get_Entity response can hold only single entry as part of response.

For READ we need to pass KEY's as input. In your case may be its PERNR which is to be passed as KEY.

The QUERY/Get_Entity_Set response can hold multiple entries as part of response.

It works on FILTER parameters. Pass PERNR as a filter parameter.

Since ur UI5 application will be embedded inside your portal, u need to capture the PERNR from portal and send it to GW as KEY / FILTER based on the approach u decide to implement your scenario.

Regrads,

Ashwin

Former Member
0 Kudos

Hi Ashwin ,

Thanks .. That helped !

Now I have another query .

Basically from the UI5 app , the user might request infotype 0008 record or infotype 0014 record .

I created 2 different data models for the same , 1 importing PA0008 and other importing PA0014 .

however , when I try to right my code pass 0014 values to er_entityset  in DPC_EXT class/GET_ENTITY_SET , I am getting syntax error , since the er_entity set internal table refers to 0008 structure .

can you please tell how to implement this functionality .

I am basically differentiating which table to query on based on the parameter which I get in KEY .

REgards

Supriya

AshwinDutt
Active Contributor
0 Kudos

Hello Supriya,

Since u have created 2 different data models for handling PA0008 & PA0014 infotypes, model properties would be different when its PA0008 & PA0014 infotypes. Correct ?

In that case have u created 2 different implementation ?

i mean to say have u created different Get_EntitySet method for PA0008 and different Get_EntitySet method for PA0014 ?

As per my understanding from the problem statement, u have two models but single implementation and hence the syntax error is encountered when u try to send back the response. Correct?

Correct me if my understanding is wrong

The error which u r getting is a valid one.

So to fix ur existing problem Basically u need to have 2 different Get_EntitySet implementation to handle PA0008 & PA0014 infotypes as ur model properties would be different ( to be specific the structure of the table which u would be returning as part of response would be different ).

So Different implementation and mapping back the correct response table structure for the respective info-type should resolve the error.

If at all u think for all the info-types has the same properties/fields but has to be read from different tables then U can do everything using a single model and single implementation.

But Since your info-types will be having different properties, its gud to have different models and their respective implementations.


Regards,

Ashwin

former_member184247
Participant
0 Kudos

Hi Supriya,

Infotype 0008 record(Basic Pay) and Infotype 0014 record(Recur. Payments/Deds.) contain same Key fields and different infotype fields.

So I suggest to create two different entity and entity set for the same.

Depending on the data required i.e, Infotype 0008 record or Infotype 0014 record, call the appropriate service.

I think this may help you.

Regards,

Sumeet Shahapeti

Former Member
0 Kudos

Hi Ashwin ,

I have created 2 data models and they created 2 entity sets as well . However problem I am facing here is that the underlying DPC and MPC classes (basically the entire runtime artifacts segment) is common for both . Hence , I am not able to create different implementation for the same . and hence I am not able to write different logic for the different entity sets .

Is there a different procesdure to be followed when we have 2 different data models than that mentioned in the blog by Chandrashekhar Mahajan ?

AshwinDutt
Active Contributor
0 Kudos

Hello Supriya,

If u can use SEGW service builder u can create ur service in no-time with less efforts.

This will take care of all ur coding and error handling as well

So i suggest u to use that if u r not using Gateway Service Builder

However, Yes the underlying DPC and MPC would be common for any number of entity u create and implement.

But still U can create different implementation for different entity as below.

for example

Say u have the below entities.

a.

Entity - Get_PA0008

EntitySet - Get_PA0008Set


b.

Entity - Get_PA0014

EntitySet - Get_PA0014Set

1. Go to ur DPC_EXT class.

2. Go to ur /IWBEP/IF_MGW_APPL_SRV_RUNTIME~GET_ENTITYSET method.

3. U need to call the appropriate logic to fetch data related to PA0008 & PA0014 Inside a CASE statement based on entity/entityset name as below.

Sample ->

CASE IV_ENTITY_SET_NAME.

WHEN 'Get_PA0008Set'.

" call the logic which will get data for PA0008

" send back response as below.

copy_data_to_ref(

         EXPORTING

           is_data = lt_PA0008

         CHANGING

           cr_data = er_entityset

       ).

" where lt_PA0008 is your internal table whose structure is similar as that of entity ' Get_PA0008 '

WHEN 'Get_PA0014Set'.

" call the logic which will get data for PA0014

" send back response as below.

copy_data_to_ref(

         EXPORTING

           is_data = lt_PA0014

         CHANGING

           cr_data = er_entityset

       ).

" where lt_PA0014 is your internal table whose structure is similar as that of entity ' Get_PA0014 '


WHEN OTHERS.


ENDCASE.


Like this u can create different implementation for different entities and map back the response correctly as shown above.



Regards,

Ashwin


Former Member
0 Kudos

HI Ashwin ,

I tried to implement code as above with copy_data_to_ref .

Its giving me syntax error 'ET_ENTITYSET is not type compatible with formal parameter' when I am using with change parameter .

can you let me know the proper syntax for the same ?

Regards

Supriya

Former Member
0 Kudos

Just to make it more clear , we are working on MRS module and the table which 'ET_ENTITYSET' refers to is not PA0008 , but is /MRSS/D_BAS_ASG .

AshwinDutt
Active Contributor
0 Kudos

Hello Supriya,

Are u using SEGW to build services ?

If yes then below details will help u resolving error.

However even if u r not using segw t-code to build services and if u r using Code based Implementation ( se80 ) technique, then also we its good to code the below way.

U get that error because there is a structure mismatch.

So Please check again and send back the appropriate structure as response.

Please refer this which will help u resolving the issue.

When u go to ur /IWBEP/IF_MGW_APPL_SRV_RUNTIME~GET_ENTITYSET in DPC_EXT class

the code and the method signature would be like this ( care fully observe the text highlighted )

method /IWBEP/IF_MGW_APPL_SRV_RUNTIME~GET_ENTITYSET.

DATA get_empset_get_entityset TYPE zcl_zash_test_user_01_mpc=>tt_get_emp.

  DATA testset_get_entityset TYPE zcl_zash_test_user_01_mpc=>tt_test.

  DATA lv_entityset_name TYPE string.

lv_entityset_name = io_tech_request_context->get_entity_set_name( ).

CASE lv_entityset_name.

*-------------------------------------------------------------------------*

*             EntitySet -  get_empSet

*-------------------------------------------------------------------------*

    WHEN 'get_empSet'.

*     Call the entity set generated method

       get_empset_get_entityset(

         EXPORTING

          iv_entity_name = iv_entity_name

          iv_entity_set_name = iv_entity_set_name

          iv_source_name = iv_source_name

          it_filter_select_options = it_filter_select_options

          it_order = it_order

          is_paging = is_paging

          it_navigation_path = it_navigation_path

          it_key_tab = it_key_tab

          iv_filter_string = iv_filter_string

          iv_search_string = iv_search_string

          io_tech_request_context = io_tech_request_context

        IMPORTING

          et_entityset = get_empset_get_entityset

          es_response_context = es_response_context

        ).

*     Send specific entity data to the caller interface

       copy_data_to_ref(

         EXPORTING

           is_data = get_empset_get_entityset

         CHANGING

           cr_data = er_entityset

       ).

*-------------------------------------------------------------------------*

*             EntitySet -  testSet

*-------------------------------------------------------------------------*

    WHEN 'testSet'.

*     Call the entity set generated method

       testset_get_entityset(

         EXPORTING

          iv_entity_name = iv_entity_name

          iv_entity_set_name = iv_entity_set_name

          iv_source_name = iv_source_name

          it_filter_select_options = it_filter_select_options

          it_order = it_order

          is_paging = is_paging

          it_navigation_path = it_navigation_path

          it_key_tab = it_key_tab

          iv_filter_string = iv_filter_string

          iv_search_string = iv_search_string

          io_tech_request_context = io_tech_request_context

        IMPORTING

          et_entityset = testset_get_entityset

          es_response_context = es_response_context

        ).

*     Send specific entity data to the caller interface

       copy_data_to_ref(

         EXPORTING

           is_data = testset_get_entityset

         CHANGING

           cr_data = er_entityset

       ).

     WHEN OTHERS.

       super->/iwbep/if_mgw_appl_srv_runtime~get_entityset(

         EXPORTING

           iv_entity_name = iv_entity_name

           iv_entity_set_name = iv_entity_set_name

           iv_source_name = iv_source_name

           it_filter_select_options = it_filter_select_options

           it_order = it_order

           is_paging = is_paging

           it_navigation_path = it_navigation_path

           it_key_tab = it_key_tab

           iv_filter_string = iv_filter_string

           iv_search_string = iv_search_string

           io_tech_request_context = io_tech_request_context

        IMPORTING

          er_entityset = er_entityset ).

  ENDCASE.

   endmethod.

If u go inside the method GET_EMPSET_GET_ENTITYSET

Signature ->

Here when u return the response the response shud be of the type which is highlighted in red.

If u go inside the method TESTSET_GET_ENTITYSET

Signature->

Here when u return the response the response shud be of the type which is highlighted in red.

The copy_data_to_ref method is a standard method and u need to call that which is correct.

Hope this will help u in resolving the error.

Regards,

Ashwin

Answers (5)

Answers (5)

former_member633146
Discoverer
0 Kudos

We go for Function Import when the operations or business scenario are not achievable by CRUD operations. For Example, Say we have same field in 2 tables(Different Entitysets) which doesn't have any relationships, If we want to fetch the data based on one table to another then we will write this code in Function Import . Remember Function Imports are independent of Entitysets.

Thank you and correct me if I am wrong.

AbhijeetK
Active Participant
0 Kudos

Function Import is used when we dont want to send any payload data in request body, but passing some data(key like order) in URL or just calling that specific action(Function Import) that specific action is executed. Example in SAP EWM is like Picking, Packing or in SD and MM confirmation of any order where in only action need to execute with parameter, no need to payload in request.

So in SD, MM, PP for confirmation of any order just sending order number in url , confirmation action will be executed(where underneath method or function doesn't require any data except order).

Same for in EWM picking and packing, just need to pass order and corresponding function import will be executed.

Former Member
0 Kudos

Hi,

Interesting thread to me... I had this confusion earlier, but only until I find a use case.

I worked on a sample which requires that form be approved/rejected from browser. And, I did not find the need to use POST operating to do this as this has nothing to do with any of the entities and associated data. All I need is to trigger the workflow with some inputs to the same.

I used a function import with defined parameters and the job is done...

Also, one more use case where I have to pre-load the employee details along with his line manager details. I don't know the employee number to perform a query from form, so I used a function import with no parameters at all, that just reads the data and the result is the entities with information I required.

Now that the discussion is going good, can someone suggest me with a better approach..

Best regards,

Nadh

kammaje_cis
Active Contributor
0 Kudos

Performing a "Approve/Reject" is a change operations, hence it has to be a POST as per OData. Also, doing POST will provide extra security using XSRF Token. So definitely POST is the way to go.

Second use case is a 'READ', with $expand navigating to manager. This navigation property will need to use an association pairing EMPLOYEE with EMPLOYEE. (Self pointing). If employee number is the key and you do not have it, I would suggest a $filter with $expand.

Former Member
0 Kudos

Thanks Krishna Koshore,

I have used Function Import with a POST Operation. As there is no update on data, I thought straining the request with Entities would be of no use. Data I added to POST are the Task ID, and two fields required for workflow container. This reduced the effort to build a POST on entities, and reduced size of request.

Can you elaborate your suggestions on READ... $filter with $expand. Do you mean that I can just pass a space in filter and perform a read query instead of function import?

Also, the concept of Self Pointing is interesting, but how is it beneficial?

Employee here is the initiator, say who launches the form from a URL. And only input I have is his SY-UNAME to extract other details like his org details and approving manager details (who here is his line manager). This information must be available on form when it is launched. Second thing, all this information forms the header, so is contained in single entity, and requires no association. READ operation with out a parameter? I have not tried it, but if that is possible, I wrongly used the function import here.

From your inputs, it looks like everything can be fairly accomplished with out having to use Function Import. So, now I feel that more appropriate use cases should be given by GW team at SAP.

kammaje_cis
Active Contributor
0 Kudos

I think you misunderstood my comments. Few pointers.

- Approval/Rejection is an ideal use case of Function import.

- READ always requires complete specification of the key.

- If you have all the data available in the entity you do not require a $expand

About $filter, I meant you can pass user name as the filter, and handle it within the implementation. Other option is to use SY-UNAME and get rid of the filter. (depending on purpose of your entityset)

Former Member
0 Kudos

Thank you Krishna Kishore

Contextual discussion like this is a better way to understand the concept with ease. Your inputs are really valuable.

Former Member
0 Kudos

Hi Manvitha,

As stated in other responses, function imports can be used where CRUD doesn't fit, however there are some drawbacks.

Overuse can start to make the ODATA protocol more SOAP-like with a focus on business functions rather than the data.

They aren't currently associated with a particular entity, they float around in the service definition. If I understand the Odata 4 spec properly, this is going to change.

Most operations that are turned into a function import can be implemented under CRUD with the right design, such as using "aliased" entities (I'm not sure if there is an official term for this technique).

An example of aliasing would be a set of entities based on the "sales order" business object. You could have Orders, UnconfirmedOrders and ConfirmedOrders.

A full query on Orders would result in a union of all three possible sets, but a full query on the other two would result in two mutually exclusive sets. If I wish to confirm an order under CRUD, I simply get it from UnconfirmedOrders and PUT it to ConfirmedOrders. The source and target entities indicate to the backend what is happening so the logic can run the confirmation process. After the PUT, I will find that the 'location' of the order has changed; it is still in Orders, but is now in ConfirmedOrders instead of UnconfirmedOrders.

I actually prefer this design pattern as it fits in with REST principles of using URI's and navigating. By "moving" the URI to a navigable point, I have managed to alter the business object state.

The main difficulty, with a function import or an aliased entity, is conveying the usage pattern to a consumer. Assume that the consumer doesn't know all the little wrinkles in your service. Yes, you are porbaly writing it for your won app, but OData is about published services that might need to be exposed to the global community, they should not be anachronistic!

I would try to use whichever one requires the simplest form of URI and is easiest to convey usage.

Regards

Ron.

kammaje_cis
Active Contributor
0 Kudos

Very interesting Ron..

Definitely would need explanation understanding this and implementation.

 If I wish to confirm an order under CRUD, I simply get it from UnconfirmedOrders and PUT it to ConfirmedOrders. The source and target entities indicate to the backend what is happening so the logic can run the confirmation process

May be you can I request you to write a blog on this design pattern? Also interested to understand how do you design 'Search Helps'.

Thanks

Krishna

AshwinDutt
Active Contributor
0 Kudos

Hello Manvitha,

We go for Function_Import or Custom_Action when the operation/business-scenario which we would like to do/implement will not fall under standard CRUD operations.

Apart from what Chandra has explained, i would like to quote one more example where we go or Function_Import/Custom_Action.

Lets say we have a scenario -

1. Say we have ordered a an ITEM with ID 'IT-001'

2. User can also cancel that order correct ?!

3. Now question is how to implement this Business_Case ?!

a. This can be implemented using Update/Delete operations as Cancelling your Order can be treated as Update as well as a Delete operation.

b. This can also be implemented as Function_Import/Custom_Action as the above business case will not fall under standard Update/Delete operation.

Technically we can fit the above scenario in Update/Delete operation and also in Custom-Action/Function-Import as well as the code written would be the same for the above case irrespective of whether we are calling Delete or Update or some Custom_Action.

But GW provides some standard ways to handle the above kind of business-cases. So we go for Function-Import.

Regards,

Ashwin

Former Member
0 Kudos

Hi Ashwin,

Thanks for the information. so, as per my understanding-

We can choose between the two options for implementing CRUD operations and it would be ideal to implement it through execute_action using function imports for scenarios like the one you mentioned.

Regards,

Manvitha