Skip to Content
Author's profile photo Thomas Nitschke

Conversions in SAP Gateway Foundation – Part 1

Many of us remember the ABAP dynpro programming model as the methodology to create user interfaces on top of business applications in a lot of SAP products. Furthermore, SAP GUI is still a widely used technology.

ABAP dynpro is tightly integrated with the ABAP Dictionary: the definition of domains, data elements, structures, and database tables influences the appearance of, the behavior of, and the content representation in an ABAP dynpro user interface.

Conversion Exits

Take domains, for example. Domains may reference conversion exits. These exits define a transformation between the representation in the ABAP runtime environment and the representation on the UI.

Let us take a look at the so-called alpha conversion routine (not to be confused with alpha conversion in lambda calculus):

The five-character conversion exit identification ALPHA is added to a character-like domain, VBELN in this case. As a result, for any purely numerical content of a corresponding field leading zeros are omitted during output on UI but added to numerical user input. Any non-numerical content stays as it is in both directions.

The left screenshot shows the representation of a sales document number (based on domain VBELN) in the famous transaction VA03 while the right screenshot displays the same sales document in SE16, that is, the representation in database table VBAK.

The transformation from the ABAP representation (with leading zeros in our example) to the representation on the UI is called outbound conversion while the other direction is called inbound conversion.

Please observe that these conversion exits have nothing to do with locale-dependent representations of dates, times, or amounts. Nevertheless, conversion exits may also take the logon language into account.

Technically, conversion exits are implemented as function modules that follow a certain naming convention: CONVERSION_EXIT_<exitID>_INPUT and CONVERSION_EXIT_<exitID>_OUTPUT. Their signature contains an importing parameter INPUT and an exporting parameter OUTPUT without type specification.

OData and SAP Gateway Foundation

Nowadays, SAP Fiori is the user experience paradigm. Its technological basis relies on SAPUI5 with OData as the protocol for data transfer between backend and UI client. SAP Gateway Foundation enables the usage of OData. In case of a typical ABAP backend SAP Gateway Foundation is the framework that allows you to develop, to expose, and to administer OData services.

When using SAP Gateway Foundation to create an OData service on top of an existing ABAP business application it can be assumed that conversion exits are taken into account as described above.

And yes, the framework provides features to automatically execute conversions such that the OData service exposes data in a way that is comparable to the former representation in SAP GUI.

But since OData defines a type system that is different from the type system in the ABAP runtime environment things get a little complicated. The conversion feature in SAP Gateway Foundation is very powerful and supports much more than just the conversion exits mentioned above.

In a small series of blog posts let us explore the secrets of conversions in SAP Gateway Foundation both for OData version 2.0 and OData version 4.0. We start with the above example of conversion exits in the context of OData version 2.0.

Starting Point – An Example

Let us stick to the sales document number. Suppose you want to create an OData service that provides sales document headers using a direct access to the database.

Your OData service will define an entity type, SD_HEADER for example. And, there will be an entity set SD_HEADER_SET. For the sake of simplicity we assume that the ABAP names are used in the OData metadata document.

The entity type SD_HEADER will get a key property VBELN to identify the sales document header through the sales document number.

If we would just expose the database content in the OData service a (JSON) response would look like this:

How do we achieve that the system automatically applies the ALPHA conversion as defined in the ABAP Dictionary such that the OData service returns the following result?

Dictionary Binding

The answer is simple: we provide the dictionary information to SAP Gateway Foundation. The mechanism to do this is called binding.

Option 1 – Structure Binding

After having created the entity type (storing the object in lo_entity_type) with its properties you implement the following call in the DEFINE method of the model provider class:

lo_entity_type->bind_structure(
  iv_structure_name   = 'VBAK'
  iv_bind_conversions = abap_true ).

Please observe the importing parameter IV_BIND_CONVERSIONS. If it would not be set to ABAP_TRUE then SAP Gateway Foundation would take over type information from the ABAP Dictionary but would not take the conversion information into account.

This code is also generated if you use transaction SEGW (SAP Gateway Service Builder) to build your service. In this design time tool you would just specify the name of the ABAP Dictionary structure when defining the entity type:

The generator will create the above method call with IV_BIND_CONVERSIONS = ABAP_TRUE automatically.

Option 2 – Element Binding

Similarly, if you create your properties independent of a structure and you just want to use ABAP Dictionary information for a single property you can call method BIND_DATA_ELEMENT at the respective property object (lo_property, for example) providing the name of a data element. Again, do not forget to set IV_BIND_CONVERSIONS.

lo_property->bind_element(
  iv_element_name     = 'DATA_ELEMENT_NAME'
  iv_bind_conversions = abap_true ).

The parameter IV_BIND_CONVERSIONS has been added to this method in SAP_GWFND 740 SP13 and higher. Hence, earlier releases do not support this function. You either need to use structure binding or the following feature.

Explicit Specifications

Independent of any ABAP Dictionary reference you are able to specify a conversion exit at the property using method SET_CONVERSION_EXIT. The method expects the 5-character identification of the conversion exit as it would have been entered in the domain.

lo_property->set_conversion_exit( 'ALPHA' ).

Be careful, the method does not check the existence of the conversion exit. It just adds the information to the property which implies that the method may also be used to override a conversion exit that has previously been determined using structure binding.

Tricky Switches

The last sentence may sound as if the method could also be used to remove a conversion exit. In principle, this is possible if an initial value is provided to the method.

A more appropriate way is the usage of method /IWBEP/IF_MGW_ODATA_PROPERTY~DISABLE_CONVERSION at the property class. It does not remove the conversion information from the property object but switches off its usage.

lo_entity_type = model->get_entity_type( 'SD_HEADER' ).
lo_entity_type->get_property( 'Vbeln' )->disable_conversion( ).

There is a corresponding method ENABLE_CONVERSION. But this method cannot be used to derive conversion exit information from the ABAP Dictionary retroactively. It just resets the switch that has been set with DISABLE_CONVERSION.

Another switch that allows to disable conversions is the method /IWBEP/IF_MGW_ODATA_MODEL~SET_NO_CONVERSION at the model itself. It disables all conversions for the complete model – we will discuss in subsequent blog posts why this is not advisable at all. Consider that you cannot re-enable a conversion for a property using ENABLE_CONVERSION if the conversion has been switched off for the complete model.

To summarize, the best way to work with the conversions is as follows: use structure binding with IV_BIND_CONVERSIONS = ABAP_TRUE and disable conversions at the individual property if needed.

Conversion Execution

Now, if a (primitive) property of an OData service “knows” about an assigned conversion exit SAP Gateway Foundation may execute an inbound conversion for content of a request payload and filter expressions or key predicates in the request URI. Outbound conversions are processed for the response payload.

In the next blog post we are going to discuss a bit more theoretical and technical background about how SAP Gateway Foundation transfers and serializes data, and when and where conversions are executed.

Assigned Tags

      14 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Andre Fischer
      Andre Fischer

      Very informative and wellexplained!

      Author's profile photo Mike Doyle
      Mike Doyle

      Interesting blog, Thomas, thank you.

      I think there is an interesting debate to be had about why it might be a good idea to do conversion in Gateway.

      To take your example, if Gateway returns the sales order number without any conversion I can easily write a formatter so that my UI5 app displays it without the leading zeroes.

      If instead we get Gateway to do the conversion then we must ensure that every time the app passes the sales order number back to the service the reverse conversion takes place.
       

      Author's profile photo Thomas Nitschke
      Thomas Nitschke
      Blog Post Author

       

      Hello Mike,
      Thanks for your comment. My answer would be twofold:

      1. The above example of an alpha conversion is quite simple and easy to implement in the UI5 app, too. But there are other conversion exits that rely on specific data in the backend and we will see further types of conversions / formatting options in the upcoming blog posts that may be more convincing.
      2. Once the property becomes relevant for conversion SAP Gateway Foundation will execute outbound AND inbound conversions. That is, the app gets the ID without leading zeros in the above example and needs to deliver it without leading zeros. There is no need to add leading zeros in the app.

      Thomas

      Author's profile photo Andre Fischer
      Andre Fischer

       

      Hi Mike,
      in addition to what Thomas said I would like to add that it is the goal of OData services provided by SAP Gateway to hide the SAP specifics on how we handle data ABAP internally from the UI5 developer so that live of UI developers gets easier.
      For the same reason OData services provided by SAP Gateway can exernally use property names like "MaterialNumber" which are much easier to understand than "MATNR" or "SalesOrder" that you can use instead of "VBELN" (which stems from German "Verkaufsbeleg") while the ABAP developer that implements the service can happily use MATNR and VBELN. 😉
      Andre

      Author's profile photo Former Member
      Former Member

      Good examples with SD tables VBAK and VBELN!

      Author's profile photo Former Member
      Former Member

      thanks a lot for share this information . very usefull

      Author's profile photo Sebastian Freilinger-Huber
      Sebastian Freilinger-Huber

      Hi Thomas,

      thanks a lot for these very useful information in Part 1 and 2 of your series. I am pretty sure, that my question does not really hit your main work area, nevertheless maybe you have an opinion about it 🙂 ?

      I am wondering about the question "How can I steer the behaviour of the conversions, when I implement the Auto-Exposure scenario with @OData.publish: true, where I do not have a SEGW project or model provider class?"

      Maybe I am wrong, but as far as I know, there is not really a CDS annotation, which I could use to steer this. Would you suggest to avoid the Auto-Exposure way and implement RDS (or the manual mapping)?

      Thanks in advance and best regards,

      Sebastian

       

      Author's profile photo Thomas Nitschke
      Thomas Nitschke
      Blog Post Author

      Hi Sebastian,

      Thanks for this question. Very good point. Difficult to answer in a short comment. Personally, I would prefer auto exposure. RDS or MDS might make sense if the additional flexibility outweighs the additional effort/complication.

      The auto exposure uses generic data and model provider classes. Hence, no possibility to influence conversions as described above. The auto exposure uses the default conversion derivation mechanism of SAP Gateway. This derivation is executed in the options 1 and 2 as described in the dictionary binding section of the blog post.

      Therefore, the only chance to influence the conversion behavior is to change the input. That is, the typing in the ABAP CDS View. You may use the cast( ) operator to manipulate the typing. For example, if the data source types field A with data element X that would lead to a certain conversion and you do not want to have it then try to cast to a data element Y with similar properties that does not lead to a conversion in the default derivation: cast(a as y)

      Thomas

      Author's profile photo Sebastian Freilinger-Huber
      Sebastian Freilinger-Huber

      Hi Thomas,

      thanks a lot for your quick reply - I think I got your point.

      Just a sidenote considering auto exposure: Our experience showed that this kind of flexibility is really necessary in more or loss all of our scenarios. I think this at least applies generally for customer projects, where you have to implement something dependent on the needs of the users or the business team. At some point in time they always show up with some fancy ideas, is you know what I mean ;-).

      Once again, thank you and best regards,

      Sebastian

       

      Author's profile photo Mark Van Reeth
      Mark Van Reeth

      Hi Thomas,

       

      Thank you for the great post. I am having some trouble with conversion routines that cause short dumps. I explain it all in this question, and I was hoping you could take a look at it and give me your thoughts on it.

      https://answers.sap.com/questions/13329761/gateway-conversions-cause-dumps.html

      Kind regards,

      Mark.

      Author's profile photo Martin Ceronio
      Martin Ceronio

      Hello Thomas,

      During processing of an OData request, I can see in the implementation of a GET_ENTITYSET  method that /IWBEP/IF_MGW_REQ_ENTITYSET=>GET_OSQL_WHERE_CLAUSE_CONVERT takes conversion exits into account, by converting external (output) to internal (input) values in the resulting values.

      However, in a GET_ENTITY method, /IWBEP/IF_MGW_REQ_ENTITY=>GET_CONVERTED_KEYS does not apply conversion exits. (You would think, because it has CONVERTED in the name, as opposed to GET_KEYS, that the system would apply conversion exits).

      Am I doing something wrong? Or is it the system that is not behaving consistently?

      Kind Regards,

      Martin

      Author's profile photo Thomas Nitschke
      Thomas Nitschke
      Blog Post Author

      Martin Ceronio - indeed, /IWBEP/IF_MGW_REQ_ENTITY=>GET_CONVERTED_KEYS is supposed to execute the (inbound) conversions. If it does not, a detailed analysis is required.

      Author's profile photo Martin Ceronio
      Martin Ceronio

      Thanks for the confirmation Thomas. It sounds like we should perhaps open an SAP incident for that.

      Author's profile photo Martin Ceronio
      Martin Ceronio

      Thomas Nitschke OK, never mind, I was being a doofus.

      I didn't realize that /IWBEP/IF_MGW_REQ_ENTITY=>GET_CONVERTED_KEYS exports a data structure, not a table like GET_KEYS, so simply passing the entity structure does in fact obtain a converted value in the correct field.

      Many thanks.