Skip to Content

Basic (and possibly stupid) SAP Gateway OData service questions

Some background: no one in our team has previous experience with Gateway or OData but we are trying to learn as fast as we can because of the looming project deadlines. I've been going through the SCN blogs (special thanks to the authors, very helpful) and with the help from new "ABAP to the Future" book so far I've been able to create a simple service that runs.

At this point I have some general questions that may seem stupid but I can take "you're way off track here" for an answer if that's the case. We're on EHP6, Gateway 2.0 SP 12 if I'm reading it correctly.

1. What if the service can only accept one value, like PARAMETER? I read this blog on implementing a filter and understand it well but it looks like filter, essentially, is the equivalent of select options. Is there a way to change that or do something different? Or are we fundamentally wrong in our ways of "parameter thinking"?

2. Related to p. 1 - is there any easy option to implement something like OBLIGATORY? I.e. the service requires certain value to be supplied, otherwise it won't work.

3. What is a good practice for returning success / error messages to the service consumer? In what scenarios should a service throw an exception instead of just returning an error message? (I'm not sure how these options would work for the service consumer.) And what exactly is the best way to return the messages? Some string table? BAPIRET2 seems way too heavy for this... I found some existing Q&As regarding messages and exceptions (exhibit A) but they pertain to very specific scenarios and I'm looking for general guidance.

Thank you!

Add comment
10|10000 characters needed characters exceeded

  • Thank you, everyone, for the replies! To clarify some points - we plan to expose these Gateway services as, essentially, an interface.

    For example, one of the simplest APIs on my list is to generate a "container ID" for a delivery. A business partner (e.g. a subcontractor) would use an API to send us document number and we would send them back "container ID" that the partner should use for shipping. There are some business rules involved in the container ID determination.

    In this case the document can be a selection option but, as a "parameter", we want the API consumer (= our business partner) to provide their "partner ID". It can only have one value, naturally. This ID is not tied to any SAP standard master data like vendor or customer. It's a completely custom ID (referenced in a Z table) and it's just needed to drive some business rules within APIs. This partner ID needs to be a single and required value, hence my questions.

6 Answers

  • Best Answer
    Posted on Mar 26, 2019 at 09:32 PM

    Hi Jelena,

    1. If you want to just accept one parameter you have to define a key in your segw/project and just redefine the get_entity method. This will import only one line of the entityset, but you can also just return one. If you want more you need to work with $filter and develop your own checks. There you need to redefine get_entityset.

    2. This can be done via the redefine too, just make your things obligatory inside and throw a exception if something is not like you expect.

    3. depends on what you want to return. I use both, depends on the case. Right now I developed some rest-services for a webshop and here I have used the return-structures of the bapi's I used inside. Before I have developed some services to update tables and on that case I just used the exceptions. So really depends on whats on the other end of the line.

    If you want more information on that topic I also can share some of my code on github.

    ~Florian

    Add comment
    10|10000 characters needed characters exceeded

  • Posted on Mar 27, 2019 at 04:51 AM

    For point 1:

    The answer depends on what you expect the parameter to do. If the parameter is the key of the record, then as @Florian Henninger said you can use the get_entity method of your entity to return the single record it identifies. But if you expect to get multiple records like the where conditions of a select statement you can continue to use the $filter odata option and the Get_entitySet would be managing the filter. ( using Odata generated through CDS's would automatically handle this without the need for you having to code this ) .

    Alternatively, use function Import if your requirement is completely custom ( i don't think it's a good fit here).

    For Point 2 :

    This may be one option in addition to what's already been suggested. https://blogs.sap.com/2017/04/06/cds-view-with-input-parameters-consumption-via-odata/

    For Point 3 :

    Bapiret2 is the way to go, SAP offers very complete options to deal with these using the standard code provided using the /IWBEP/CX_MGW_BUSI_EXCEPTION or /IWBEP/CX_MGW_TECH_EXCEPTIONexceptions, The way I see it the Technical exception is a fatal error that you don't expect ( or is technical in nature e.g. a part of config/customizing not being available etc.. ) to get and the business exception is the error you get because of business scenarios for example from a BAPI return.

    Here's the link to the complete documentation for the same. https://help.sap.com/viewer/68bf513362174d54b58cddec28794093/7.4.19/en-US/01a226519eff236ee10000000a445394.html

    Basically, this adds all the BAPI error and a custom header for the response and best of all, SAP standard UI5 views play very well with this and work out of the box with it. eg: https://sapui5.hana.ondemand.com/#/topic/52824a6c316a413dbd7bd5f29522dce2

    I'm not very good with going into too much detail in my replies to please do let me know if you have further questions, I'll add as much as I can.

    Hope this helps.

    Add comment
    10|10000 characters needed characters exceeded

    • Thanks for a reply! I've just added a comment to the question with a specific example I'm dealing with. The confusing part for me is that in our scenario the "parameter" is actually not used directly in the data retrieval. It's a value used in the business logic. All examples I've seen are like "oh, I put this value in the filter and then it's used in SELECT". But in our case it doesn't. This is also why I have a feeling this is a wrong approach and there could be some feature I'm missing. Perhaps it should not even be a "parameter" but something built into a service call itself. But I did not see anything else in SEGW so far.

  • Posted on Mar 26, 2019 at 10:51 PM

    Hi Jelena,

    This won't be the answer you can mark as your answer but here's some info to hopefully help:

    First point is to understand who the consumer of the OData Service is and to define your entities and interactions that are required. e.g. No need to implement all methods if you are simply doing a search for a PO. e.g. Assuming you are providing an OData service for a freestyle Fiori UI, and that UI needs to do search on PO's, you could have an entityset called PurchaseOrders, with an Entity called PurchaseOrder. Now if you want to search by PO Number, Name, Vendor, etc; you could make it really easy for the UI developer and tell them to just use the Name field, and in the back-end you'll use that to search for PO Number, Name and Vendor regardless (e.g. It's an agreement between the UI developer and the back-end developer remembering the UI part is the hardest part to get right).

    Once you've done this, this will require you to implement just the POsGetEntitySet method - the others may not be necessary. Plus you can decide how you want to build the search in this routine. e.g. You can use select option style, you can dice up the string so that you can make it a google like search. For example, searching for an employee called *P Jel* should actually be searchong on *P* and *Jel* so that the order doesn't matter.

    Note - There is also a query option that could also serve this purpose but that can be harder for the UI developer to implement.

    TL;DR for this bit: Design your API's based on the User Interface requirements in order to make the UI developer's life as easy as possible. Reuse is not the focus of Gateway Services. This also applies even if just doing an extension to an existing Fiori app.

    Of course - this all goes out the window when you start talking about CDS so I'm assuming you are talking about SEGW defined OData Services.

    For Obligatory, In the above example, you could simply return no entities if no search parameter is provided. Sometimes this makes sense if getting the first 20 entities in order without a filter takes too long.

    Only rule I would say is that you should only throw business exceptions for create/update/delete type of changes unless something is catastrophically wrong.

    Last recommendation is for your next message would be (if you are allowed of course) to put more specific example and details into your question as there are lots of varying programming models now days, and variation of features between different versions.

    Hope that is of some help,

    Matt

    ps. Make sure you know about some of the utility methods to do paging, filtering and sorting - Very useful when you can just go and get all entities because there aren't too many and then use these to do the heavy lifting for you.

    Add comment
    10|10000 characters needed characters exceeded

    • Thanks, Matt! All fair points. I'll add more details to the question. In our case there is no UI, we just need to create some APIs that would be exposed to our business partners (e.g. a subcontractor), so that they can interact with our SAP system. We don't want to do anymore file interfaces, IDoc is not suitable here, so a choice was made to use Gateway services.

      I completely agree with you that it's important to understand what the consumer actually requires but for a variety of non-technical reasons we are creating these services rather proactively. I.e. we don't know for sure yet how and who will consume them but we are required to make them available.

  • Posted on Mar 27, 2019 at 09:29 AM

    Hi Jelena,

    since you already received lots of correct and helpful answers I will just add a few comments here:

    1.

    As Amarpreet Singh mentioned a function Import could be a solution for you if you do not want to use $filter=myproperty eq <somevalue> since function Imports accept parameters like …/employeedforhowmanyyears?empid=12345.

    In addition there is the option to use a search string.

    searchstring = io_tech_request_context->get_search_string( ).			

    2 a)

    By default parameters of function Imports are mandatory.
    You would have to perform custom code as described here to make them optional / nullable :-).

    2b)

    If it is about having a field being mandatory for CDS views you can use the annotation

    @ObjectModel.mandatory: true

    But this will probably won't help you since you said that you are working on SAP Gateway 2.0 SP12 and thus not on SAP NetWeaver 750 or higher.

    The above mentioned Annotation results in the following Annotation:

    <Annotations xmlns="http://docs.oasis-open.org/odata/ns/edm" Target="Z_INVENT_TP_50_SRV.ZC_Inventory_Tp_50Type/Quantity">
    <Annotation Term="Common.FieldControl" EnumMember="Common.FieldControlType/Mandatory"/>
    </Annotations>

    Book:

    There is also a book available that is covering SAP Gateway starting from SAP Gateway 2.0 up to the ABAP RESTful Programming Model available in SAP Cloud Platform ABAP Environment.

    3rd Edition of SAP Gateway and OData

    Best Regards,

    Andre

    Add comment
    10|10000 characters needed characters exceeded

    • Thanks for a reply, Andre! I googled "function import" and found this blog, it seems way more than we need, so in this particular simple scenario I'm just going with what Florian suggested.

      I do have the book, not the most recent edition but the old one is perfectly fine for our version. It's a fine book but there is just so much information and I need to "hit the ground running", so this does not leave much time for academic literature, unfortunately.

      By the way, for some reason only the old book edition is included in the SAP Press Developer subscription online. After reading your reply, I was trying to add new edition to my online library but could not find it.

  • Posted on Mar 27, 2019 at 10:08 AM

    People gave you already a lot of great inputs.

    Now, since i was there, here some selfish self promotion of my blogs i wrote when I approached UI5/OData 4 years ago.

    I discovered way more things and evolved a lot in the past months into structuring the code, but maybe you can find some hints.

    Add comment
    10|10000 characters needed characters exceeded

  • Posted on Mar 26, 2019 at 11:32 PM

    I don't have any experience personally with items #1-2 but for #3 I have successfully done something similar to the post you have linked - using /IWBEP/CX_MGW_BUSI_EXCEPTION. I would add however that the use case I was prototyping didn't have a need for BAPIRET_T (1:n) messages in the response so it may not match up with what you need to provide for a solution.

    P.S. - as far as #1-2 from what I recall you may have to look at overriding default behavior to see if can suit your needs.


    Regards,

    Ryan Crosby

    Add comment
    10|10000 characters needed characters exceeded

    • Hmmm, here is a screen shot of the help for that exception class which indicates it's specifically for the return of business exceptions and most importantly provides notes on how to add messages from BAPIs. Guess I would have a different opinion on the use here as the type isn't what I'm looking at to provide context to a user when an issue occurs with an OData service - the messages give the answer in this case.