ABAP to the future – my version of the BOPF chapters – Part 6: Validations
In “ABAP to the future” (A2tF) it is being said that validations in BOPF are meant to check the consistency and prevent saving. This is only partially correct. Validations are those parts of the model which represent idempotent (repeatable without changing the state) checks. When a validation is being executed and what the effect of a failed validation is, depends on the validation’s configuration. In general, there are two types of validation configuration: Action validations and consistency validations. The implementation of both types is based on the same interface (/BOBF/IF_FRW_VALIDATION) and thus, the same implementation class can be used in multiple places. Therefore, I also recommend restricting the scope of a validation as much as possible in order to facilitate re-use.
We still don’t really know what an action is (this will be covered in the next chapter of the book), but we’ll start with action validations. An action validation is – surprise, surprise – registered to be executed before an action is being executed. If the validation fails, the action will not be invoked for the failed instances.
Actions can easily be invoked from the Test-UI, this includes the execution of the action validations. Or you can execute the core-service “check action” from the check-menu.
Figure 46 – Result of a failed action validation: You can see the error message and the highlighted origin location.
Not only modeled actions can be subject to validations, but also the so-called framework actions. For our purpose, it is now enough to know that for each node, a CREATE_<NODE>, UPDATE_<NODE>- and DELETE_<NODE> action exists and is being executed by the framework when performing a corresponding modification.
Figure 47 – Configuration of the alternative key validation: The framework actions are prevented if the alternative key is not unique
Let’s have a look at a sample which we foreshadowed some chapter ago: The business requirement reads that howling at the moon should only be possible for monsters with at least one head.
Figure 48 – Definition of an action validation. The really important part is the “trigger actions”
Figure 49 – Trigger actions: which actions are guarded by the validation
In addition, in future werewolves should be able to howl at the moon only if it’s full moon. The two aspects are semantically independent; therefore we create two validations which we both register for the action HOWL_AT_THE_MOON: HAS_AT_LEAST_ONE_HEAD and IS_FULL_MOON. If later on, we might for example add an action BITE, we could also register the HAS_AT_LEAST_ONE_HEAD for it, but not the full-moon-check (assuming that also human-bodied werewolves can bite). This additional configuration would not require a single line of code and makes our model more readable with respect to the pictured business.
The implementation of HAS_AT_LEAST_ONE_HEAD looks very similar to what we coded in the previous chapter’s property determination with one big difference: We now want to prevent the action execution and provide a meaningful error message. Remember: The property-determination was only executed on request of the consumer (the UI-layer).
DATA lt_root TYPE zmonster_t_root. “The combined table type of the node to be retrieved
CLEAR: et_failed_key, eo_message.
iv_node = zif_monster_c=>sc_node–root
it_key = it_key
it_requested_attributes = VALUE #( ( zif_monster_c=>sc_node_attribute–root–number_of_heads ) )
et_data = lt_root ).
LOOP AT lt_root ASSIGNING FIELD-SYMBOL(<ls_root>).
IF <ls_root>-number_of_heads = 0.
* Get a message container. Unfortunately, the message container is not injected as a handler,
* so we must instantiate it actively. #architectural_fail
IF eo_message IS INITIAL.
eo_message = /bobf/cl_frw_factory=>get_message( ).
* Create a message by instantiating the message-class. Don’t use the instantiation of /bobf/cm_frw_core as written in the book
* (this is bad style), but simply make your exception-message-class inherit from /bobf/cm_frw.
* There’s also a blog post about message-objects in BOPF on SCN ;). The constructor-expressions pay-off very well in this case!
eo_message->add_cm( NEW zcm_monster(
textid = zcm_monster=>no_head
severity = zcm_monster=>co_severity_error
symptom = /bobf/if_frw_message_symptoms=>co_bo_inconsistency
lifetime = /bobf/if_frw_c=>sc_lifetime_set_by_bopf
ms_origin_location = VALUE #(
bo_key = zif_monster_c=>sc_bo_key
node_key = zif_monster_c=>sc_node–root
key = <ls_root>-key ) ) ).
* The message just created is not meant to be interpreted at all,
* neither by the framework nor by a consumer. What really matters
* (and what makes the framework not execute the action in case of an action validation)
* is the indication of the instance as failed
INSERT VALUE #( key = <ls_root>-key ) INTO TABLE et_failed_key.
ENDIF. “monster has no head
The validation code will always be executed if the action to howl at the moon is about to being performed or if the core-service “check_action” is being executed by a consumer: In this case, all action validations configured for the requested action will be executed. In contrast to what’s been said in the book, there is no option to invoke a particular validation.
A consistency validation is a check which is being executed as a side-effect of an interaction with a business object changing the state of one or multiple instances (without a change of its state, the consistency of the instance cannot change anyway). As such, the configuration of a consistency validation is comparable to the configuration of a determination: You can select trigger nodes and modification (CUD). Additionally, all consistency validations which have been configured on “check” are being executed through the core-service check_consistency.
Figure 50 – Invoking the core-service “check consistency” on the test-UI (including the scope-options “local” and “substructure”)
While an action validation prevents the action if it fails, the consistency validation’s reaction on failure is defined by a so-called “consistency-group”: Either it can prevent saving or it can set a consistency-status (which is a dedicated node-attribute).
Figure 51 – A consistency check fails on update – but accepts the values give on update (creator) nevertheless. An action validation would have rejected the complete modification.
Figure 52 – Result of a failed consistency validation preventing the save.
Setting a status value is particularly interesting if you think about stateless-applications in which a save is effectively being requested after each round-trip: The framework will mark the instance as inconsistent if a consistency validation fails on save. With a new stateless request, this consistency-status can be interpreted in order to prevent a subsequent action which should only be possible for consistent instances.
In order to define a consistency validation, one needs to define the validation itself and assign it to a consistency group.
Figure 53 – Configured consistency validation
Figure 54 – The trigger of the validation is defined in the validation’s trigger conditions
Figure 55 – The consistency group defines the reaction on failure of one of the assigned consistency validations
With respect to implementation, there’s no difference compared to action validations (both implement the same interface). But as consistency-validations are being executed as a result of a modification (which – once again – the consistency validation will not prevent), there’s good reason to also implement the check and check_delta-methods, which don’t make much sense for action validations. I will not provide a complete implementation now (you can read one in A2tF), but I want to point out some of the major mistakes made (which you unfortunately can also find in the book):
- As all interface-methods,also the validation methods are mass-enabled! If you ever see a READ INDEX 1
- Most of the BOPF framework-classes (containg _frw_/bobf/cl_frw_factoryio_read and).
- For message-classes or libraries, inheritance is a common reuse-mechanism in BOPF.
- In addition, all the pitfalls mentioned in the chapter on determinations apply – including the lengthy “no need for a single model class”-pledge.
About raising exceptions
As you might have noticed, the signature also features an exception of type /BOBF/CX_FRW which can be raised and you may wonder whether it would not be suitable for failed validations. The short answer: No, it is not. The system will go for a (“controlled”) short-dump. I could also go for a long explanation why this is desired, but I fear no-one is really interested in reading it. If you would like to know more about it, please comment 😉
Superb Content !!
The whole series..
Would like to know more about the Associations. Can you please have part 7 on that!??
Keep up the good work! 🙂
thanks for the appreciation, it's nice to know someone read it 😉
However, I was not too happy with the quality, particularly I was missing screenshots. Now that I've got a dev. system again, I provided them and reviewed the content once more.
I also added a short blog on associations: ABAP to the future - my version of the BOPF chapters - Part 1 Addendum: Other associations
Feedback (also questions and criticism) highly appreciated!
just letting you know that the Link "find more alternative versions of other chapters on my blogs." at the very end does not work for me 🙁
"No results found."
thanks for notifying! It seems as if when moving to the new search-engine used in scn (find.sap.com), old links got broken. Just adjusted them again...
Hope you enjoy the posts. If not, I'd even more enjoy your response and proposal for change!
to be honest I didn't realy read your blog...
I'm just currenlty reading "ABAP to the Future", that's why I searched for that term on SCN and the found you blog.
I recoginzed it's a kind of blog-series and tried to find the first one (to start reading at the start), that's when I figured the serach-link was broken.
I'm new to BOPF and I find your blog very useful for me.
I have a question about action validations for framework (CRUD) operations. Maybe you can give me a link where I can find more information about this.
I have a subnode which can be instantiated only in case if root node has a certain status.
I created a validation for my subnode but if I test it in BOBT I get message that the root node has 'failed' status but I can save the instance anyway.
Thank you in advance for your help.
First of all sorry for the delay. Seems I lost notification about comments during the SCN upgrade ;(
With respect to your question: An action validation will prevent the execution of the action for all failed instances. It will not prevent the save.
The action you're looking to prevent is the framework-action CREATE_<subnode>. It's located on subnode, so your action validation should reside on subnode as well. Thus, you will get subnode's instances keys in IT_KEY.
As your business logic is interested in data residing on the root-node, your validation will do the following:
* As you're depending on the root-node-data, retrieve by association to_root (don't forget the iv_fill_data = abap_true 😉 )
* loop at it_key, find the corresponding root-data read table lt_root with key key = ls_subnode-root_key.
* if the root node's status is not appropriate, insert ls_key into table et_failed_key and create a message-object.
Hope this answered your question!
Thank you for your answer. I did it in the way you has written. It works 🙂
But I thought that the other solution is also possible. Anyway thank you for your help.
I continue to learn and use BOPF, so most likely other questions will raise 🙂
My question here is , how can i overwrite the existing save functionality for a particular BOPF. Currently on clicking the Save button in the fiori app , it saves the record in the database table. Instead of saving in the database table , I would like to call my exiting API and perform the logic present in it. Is there any way I can handle that.
Would really appreciate the help.
Hi, I know its a old question. But I will try to answer. I am no BOBF expert but you can create your own action and call your API inside the 'EXECUTE' method which is related to your action.
Nice explanation for action/consistency validations. I am looking forward to implement these concepts.
Thank you, Oliver. My consistency validation did not prevent saving. This chapter just saved my day.