Let's be honest - no matter how developer friendly and stable validation rules support would be in ADF BC, there will be always use cases when validation logic will be executed directly in DB, by check constraints for example. There is one problem in ADF, when validation logic is executed by DB check constraints. As there will be error received in doDML, while posting row and violating check constraint - transaction will stop and no other edited rows will be verified, until currently failed row data will be fixed. I will explain in this post, how to bypass such behaviour and have to report failed rows to ADF UI.
Key part to understand - there are two transient attributes defined on VO level. These two should be defined on VO level, if you would define them on EO level, transient attributes from EO level would not be included into passivation and values would be lost. One attribute is used as a flag to indicate DB constraint error for current row and other attribute keeps error text:
Both attributes are set to be included into passivation cycle. This would not be possible for transient attributes defined on EO level:
Method doDML is overriden on EO level to catch error from DB check constraint. In this example, I'm processing only Salary > 0 DB check constraint. In case of error from DB, error text is saved into ErrorText transient attribute from current row. ErrorIndicator is set to be 1, if error happened, and 0 otherwise. I'm getting current VO row for the current EO, by accessing it from root AM:
On UI side, we add Partial Trigger to the surrounding Panel Collection from Save/Cancel buttons. This will ensure error code and error text for the affected rows will be updated:
There are client and server listeners defined for the table to enable row double click support, this is how error message will be displayed to the user (instead of annoying popup showing up constantly):
Error message from currently selected row is retrieved and displayed through Faces message. I'm checking if error exists for the current row and only then display it - quite straightforward:
Here is example, where user was trying to submit changes in three rows, all set with negative salary. Of course DB check constraint for positive salary failed and we can see failed rows highlighted in red. You can double click on row highlighted in red and then error text popup will be displayed:
Let's fix salary in the second failed row to be positive and press Save again. Two rows will remain in failed state, but data from the fixed row will be saved to DB successfully:
We can double click on the first failed row to see the error message:
Fix salary to be positive in the first row and commit again - only one row with error will remain in pending state:
Download sample application - DoDMLExceptionProcessingApp.zip.
Key part to understand - there are two transient attributes defined on VO level. These two should be defined on VO level, if you would define them on EO level, transient attributes from EO level would not be included into passivation and values would be lost. One attribute is used as a flag to indicate DB constraint error for current row and other attribute keeps error text:
Both attributes are set to be included into passivation cycle. This would not be possible for transient attributes defined on EO level:
Method doDML is overriden on EO level to catch error from DB check constraint. In this example, I'm processing only Salary > 0 DB check constraint. In case of error from DB, error text is saved into ErrorText transient attribute from current row. ErrorIndicator is set to be 1, if error happened, and 0 otherwise. I'm getting current VO row for the current EO, by accessing it from root AM:
On UI side, we add Partial Trigger to the surrounding Panel Collection from Save/Cancel buttons. This will ensure error code and error text for the affected rows will be updated:
There are client and server listeners defined for the table to enable row double click support, this is how error message will be displayed to the user (instead of annoying popup showing up constantly):
Error message from currently selected row is retrieved and displayed through Faces message. I'm checking if error exists for the current row and only then display it - quite straightforward:
Here is example, where user was trying to submit changes in three rows, all set with negative salary. Of course DB check constraint for positive salary failed and we can see failed rows highlighted in red. You can double click on row highlighted in red and then error text popup will be displayed:
Let's fix salary in the second failed row to be positive and press Save again. Two rows will remain in failed state, but data from the fixed row will be saved to DB successfully:
We can double click on the first failed row to see the error message:
Fix salary to be positive in the first row and commit again - only one row with error will remain in pending state:
Download sample application - DoDMLExceptionProcessingApp.zip.