First thing you should do - never implement validation logic in beforeCommit() method, this is especially true for beforeCommit() in VO Implementation class. Why? Because beforeCommit() method will be invoked even if data will not be changed, it is enough just to open VO instance and query data. We can have many VO instances for the same EO and all of them will trigger beforeCommit() methods implemented in VO Implementation. You could open one page, close it without changes and open another page. Once you invoke Commit operation in second page, beforeCommit() method from the VO's involved into first page will be called as well. This means it would trigger validation for the page which is currently closed. On other hand, it is understandable why developers try to code validation logic in beforeCommit(), standard ADF BC validation lifecycle is unpredictable sometimes, it fires validation rules too early. But it still not a good excuse to use beforeCommit() - I will show you why.
Download sample application - BeforeCommitVOApp.zip. This application contains two View Objects based on two different Entity Objects, each View Object is mapped with Implementation class:
First VO - Departments, contains overridden beforeCommit() method, where developer implemented validation rule to check department name text length:
Second VO - Employees, contains overridden beforeCommit() method, where validation rule to check salary amount is implemented:
Open Departments VO in ADF BC tester and close it without any change:
Open Employees VO in ADF BC tester, change data now and try to save it by committing transaction - you will get validation error from the first (already closed) Departments VO, fired from beforeCommit() method:
We can see it in the log - ADF BC tries to update Employees record, but just before completing transaction commit, it calls beforeCommit() from previously opened VO and it fails there. Entire transaction is interrupted:
Download sample application - BeforeCommitVOApp.zip. This application contains two View Objects based on two different Entity Objects, each View Object is mapped with Implementation class:
First VO - Departments, contains overridden beforeCommit() method, where developer implemented validation rule to check department name text length:
Second VO - Employees, contains overridden beforeCommit() method, where validation rule to check salary amount is implemented:
Open Departments VO in ADF BC tester and close it without any change:
Open Employees VO in ADF BC tester, change data now and try to save it by committing transaction - you will get validation error from the first (already closed) Departments VO, fired from beforeCommit() method:
We can see it in the log - ADF BC tries to update Employees record, but just before completing transaction commit, it calls beforeCommit() from previously opened VO and it fails there. Entire transaction is interrupted:
Hi,
ReplyDeleteThis is a good clarification, but if I need to validate the data of a View Object, can I only do it from a Managed Bean? Or BC provide another method to do this.
Thanks!
Marcos.
I would suggest to write your own custom method in View Object Impl and expose it through Client Interface, then you can call it from managed bean listener.
ReplyDeleteAndrejus
Suppose if i have a programmatic entity in which all the attributes are transient then what is the solution
ReplyDeleteYou can implement Entity validation rules in standard way.
ReplyDeleteAndrejus
Can I override beforeCommit(TransactionEvent transactionEvent) for any custom validation in EOImpl ? Or will this have the similar multiple invocation as you discussed here.
ReplyDeleteI saw your other post http://andrejusb.blogspot.in/2014/07/adf-bc-12c-new-feature-entity-level.html regarding Triggers. If my ADF is in older version which is the efficient way ?
Then I would recommend to update to newer version :)
ReplyDeleteAndrejus
I have a requirement that i can't change the EO, is there any way to add the validation for the attribute in VO, except the method beforeCommit?
ReplyDeleteThanks