BOPF-SADL Mapping – Demystifying Limitations
The series E2E: BOPF-SADL-GW-SAPUI5 describes how to create an SAP Gateway service based on the Business Object Processing Framework (BOPF) by leveraging the mapping features of the Service Adaptation Description Language (SADL). We are glad to receive feedback and questions about this technology.
With this article I explain the most important limitations of this approach. I will also explain where these limitations come from, so you may have a better idea of what you can expect (not) to work in general. I assume that you already had a look at the “Map to Data Source” feature of the SAP NetWeaver Gateway Service Builder as described in E2E: BOPF-SADL-GW-SAPUI5 – Mapping an Entity Set.
Interested in some “History”?
SADL started out with the ambition to remove all “heavy” framework overhead for read-only scenarios. By doing so, SADL is an ultra-fast query engine which makes it possible to access and interactively page through millions of records with very short round-trip times. For instance, SADL provides the run time engine behind ALV and FPM on SAP HANA.
SADL uses BOPF’s metadata information to bypass the BOPF runtime for read-only scenarios. This is only possible if there is a static mapping between the structures used by the BOPF service manager API and the underlying database.
Today, SADL is no longer limited to read-only use cases, but it also offers support for modifying operations. SADL does not try to directly update data on the database, but delegates any modifying request to BOPF. This ensures the consistency of business data.
Although SADL supports modifying operations by delegation, it is important to keep in mind that the full use of SADL is generally limited to scenarios where it is possible to establish a static mapping of business object data to the database.
So, what are the prerequisites for SADL to be able to map BOPF data directly to the database?
The node’s database table must be maintained. Transient nodes in particular cannot be mapped.
- No custom data access class (DAC) must be used. The following DAC classes are allowed: /BOBF/CL_DAC_TABLE and /BOBF/CL_DAC_LEGACY_TABLE (if available in your system). (Note that, if no DAC is maintained at the BO node, BOPF takes it from the BO header.)
- The node must have only one node category.
Node categories cannot be maintained in BOBX or in the Eclipse-based BOPF editor. If you created your BO with one of these tools, you only have one node category and you should not even bother about this concept as we discourage its use. The reason for the limitation is that SADL only supports static metadata for entities (here: BO nodes). BOPF’s node categories allow to model, for example, different associations per node category. From SADL’s perspective, this would mean that an entity’s metadata changes per entity instance.
If you need to expose a BOPF node which cannot be mapped by SADL, you will have to manually implement this in your service’s data provider class (DPC).
- The attribute must exist on the database table. Attributes of the transient structure cannot be mapped.
- In case your BO uses the DAC /BOBF/CL_DAC_LEGACY_TABLE, the standard BOPF key fields (KEY, PARENT_KEY, ROOT_KEY) are transient and cannot be mapped.
In this case, you cannot expose BOPF’s key fields in your service, but you have to use the key fields of the underlying database table. In my experience, this is what most applications do, anyway.
If you need to expose transient attributes you have to leave them unmapped. In addition, you have to redefine the entity set-specific implementation in your DPC. You can, for example, first call super (SADL’s generic implementation) and afterwards fill the missing values for the transient attributes. Take care not to flag such attributes as “sortable” or “filterable” in the property definition of the entity type.
- Compositions, TO_ROOT, and TO_PARENT can be used – provided that their target node can be mapped (see above).
- Other associations can be used if an attribute binding has been maintained for them. There is no check for the existence of an implementation class, but SADL assumes that the binding information is complete. If your association has binding information but the association is implemented in a way which deviates from the binding logic, wrong results may be returned by the SADL runtime.
If you need to map an association which cannot be handled by SADL, you will have to manually implement this in your DPC.
SADL translates all authority checks into the WHERE-condition of a generated SELECT statement. This is a necessary precondition for efficiently processing requests for arbitrary pages of a given result set. Therefore, it must be possible to derive a WHERE-condition from BOPF’s metadata. This means:
- The authority class must be able to return a SADL query condition provider. This is true if your BO uses /BOBF/CL_LIB_AUTHCHECK_W_QUERY or a subclass thereof. This class imposes certain constraints on how authorization checks can be implemented.
While SADL is being heavily used within new SAP applications, there are still scenarios which have not received much attention, so far.
- BOPF Dependent Objects have not been in focus, yet. Some scenarios may not work in all aspects with SADL. So if you use them, you should be aware that you are an early adopter in this area.
- Since BOPF offers a lot of flexibility, it is not always feasible to programmatically detect all situations where metadata in the BOPF configuration model might be misleading with regard to the BO’s actual run-time behavior. In addition, BOPF supports add-ons and plugins which can change pretty much every aspect of BOPF’s original behavior. SADL does not check for such extensions as it would not be practical to disable SADL mapping as soon as an extension is detected.
- If you use SADL’s feature of implicit view building as described in the example in E2E: BOPF-SADL-GW-SAPUI5 – Implicit View Building, you will not be able to update fields which have been joined from other BO nodes to the leading node. In the example, this is the case for the fields PRODUCTNAME and SUPPLIERNAME. If you need to update such a field, you will have to update it at its original entity.
- SADL reads data by bypassing BOPF’s buffer. Keep this in mind if you use BOPF’s service manager API in your service implementation. If you re-use SADL’s generic implementationfor reading data of an entity set after having made changes via BOPF, SADL might read outdated data.
BOPF vs. Stateless Services
There is a natural conflict between some BOPF BOs which have been optimized for traditional SAPGUI or WebDynpro applications on the one hand, and modern web-based applications using stateless services on the other hand. Some framework optimizations which have been introduced for traditional applications can turn into a bourdon for modern architectures.
In a stateless context, you would like to post only small updates with each service call. You might want to “activate” your object only after a series of modifications which would not make much sense each on their own. You would like to be able to save an incomplete version (“draft”) of your document and continue working on it later – knowing that the existence of your draft prevents the original document from being modified in the background.
On the other hand, a classic BOPF BO – if it has been developed with only session-based applications in mind – may refuse to save any business data as long as it is not in a “consistent state”. Inconsistencies are only temporarily allowed within the current ABAP session. For the time of the current session, BOPF locks instances against parallel changes.
A stateless service request is answered by an ABAP session. The next request creates a new session. Any locks acquired in the first session are lost as soon as it ends. In addition, some updates may fail because of save-preventing BOPF validations.
The cheap answer to this problem is: Only use a BOPF BO in a stateless service after you have verified that it is suitable for the scenarios you are targeting. Especially BOs with strict consistency checks or save-preventing validations are likely to cause issues.
However, at SAP we are working on a better solution to bridge the gap between classic applications and the world of stateless UIs. Stay tuned!