Friday, March 25, 2011

Customizing Business Components Error Messages

Customization of business components error messages are well documented in Fusion Developer's Guide 37.8 Customizing Business Components Error Messages. I would like to add a couple of points more here :)

If you want to customize the display of DB level errors such as unique constraint violation, foreign key constraint violation etc by providing your own meaningful messages, then along with the steps mentioned in the Developer's Guide you may need to touch one more guy who is responsible for displaying the classic error messages. I'm talking about the ErrorHandler class (DCErrorHandlerImpl) provided by the binding layer.

To get a clear picture, let us take a step back and see the role of ErrorHandler class at run time. When your business method throws error, binding layer intercepts that and puts the 'configured' ErrorHandler(default is DCErrorHandlerImpl) class in to action. The ErrorHandlerClass is responsible for formatting the exception in a human readable format. During this exercise, DCErrorHandlerImpl (default error handler) class will skip the top level JboException as this is a wrapper over other business exception and doesn't have any business significance. This is OK in most of the scenarios. Unfortunately this default behavior may skip/swallow the custom message you set for replacing SQLExceptions.

Hmm..What next?

The solution is to override the default behavior using a Custom Error Handler. You can follow the chapter 28.10 Customizing Error Handling to learn more on this topic. ( Please note that there is no method called DCErrorHandlerImpl::processMessage(), so you can happily skip that part given in Developer's Guide ). Now the real story starts...While displaying each item in a nested exception, the error handling logic would invoke DCErrorHandlerImpl::skipException(Exception ex) to decide whether to display the corresponding Exception in the final list or not. Here you can check for specifics exception types and take a call based on the business scenario. For example the below given code snippet will skip the SQLIntegrityConstraintViolationException from displaying in the final list.

   @Override  
   protected boolean skipException(Exception ex) {  
     if (ex instanceof DMLConstraintException) {  
       return false;  
     } else if (ex instanceof SQLIntegrityConstraintViolationException) {  
       return true;  
     }  
     return super.skipException(ex);  
   }  

Download

You can download the sample workspace from here.
[Runs with Oracle JDeveloper 11g R1 PS3 + HR Schema]

A glance at the implementation

This sample displays employee entity and displays custom error message for violating unique key constraint defined on the email column. The implementation uses the custom message bundle (model.msg.CustomMessageBundle) for the Model project to override the error message displayed for the data base constraint EMP_EMAIL_UK (default HR schema has unique key constraint 'EMP_EMAIL_UK' defined on Email column). To display this custom messages from the web page, a custom error handler has been introduces as discussed above - view.CustomErrorHandler


How to run this sample?

1. Run test.jspx
2. Copy the email of first employee, navigate to next record
3. Update the email of second record with the copied value
4. Click on Commit. You may notice a more user friendly error message instead of classic ORA-00001: unique constraint error.


Learn More ...

There are a lot more points like this. If  you are curious to learn the internals of the ADF Business Components and ADF Binding Layer,  the following book is for you - Oracle ADF Real World Developer’s Guide.
More details about this book can be found in this post- http://jobinesh.blogspot.in/2012/07/pre-order-your-copy-of-oracle-adf-real.html

7 comments:

Anonymous said...

Hi,
How to do the Customization in the DCErrorHandlerImpl in order to display error pointing to the validated input field (like in general ADF UI popup) instead of the pop up window displayed in the center?
Thanks,
Kayal.

tshifhiwa said...

hi i have follow your sample but is not working is still showing database error i have created the two class and call the class hear <Application xmlns="http://xmlns.oracle.com/adfm/application"
version="11.1.1.59.23" id="DataBindings" SeparateXMLFiles="false"
Package="view" ClientType="Generic"
ErrorHandlerClass="view.CustomErrorHandler" what else must i do

Anonymous said...

Hi,
What if we customize DCErrorHandlerImpl to display custom error but for same error we want to show different msg according to different page. How can we achieve this for jsff page in dynamic region ? For example, duplicate empno or itemno, both are candidate for "too many object.." exception. If both error arise in different page, we want to send custom msg for each page.

JoeTheJet said...

So, I have a weird situation, The first time this happens, I get the ugly Oracle Error, but the second and subsequent times, the skipException method gets called.

Why would it not call it the first time. I have "debug" turned on so I know that the method doesn't get call at all.

Hosein Zare said...
This comment has been removed by the author.
viraj vekariya said...

hi all,
i want to change that error notification to informational warning.I tried from failure handling , but it didn't work.
please give me some other ideas,or can any one tell me that why it is happening..?

Jobinesh Purushothaman said...

Viraj
You cannot do it from the Error Handler, it's late in the cycle.