Exception Handling in ADF
Since Exception handling is very
vital part of any web based application and technique of exception handling implementation is depend on from where it is throwing.
The exception will occurred on
following part of the application
1-Model
2-View Controller
It may be Model layer or may be View
layer
Moreover the Exception handling
approach is base on the layer from where it's thrown .If it is
throwing through Model layer then the way of handling is difference compare to
if it thrown on the View Controller .
As you all know we are accessing model
layer through the binding container. Internally If any exception has
thrown by model layer ,then by default the DCErrorHandlerImpl class going to catch
the exception and show the error message to user.(this is default features
of ADF).
In some case we do not want to show the exception because as end user they want more specify message.So in this case we need to override default exception .
So
first i would like to explain exception handling approach in model
layer
Following step will explain the way of exception in model.
1-Create the class and extends
with DCErrorHandlerImpl
2-Override the public void reportException(DCBindingContainer bc, Exception ex) .
According your requirement report the exception on DCErrorHandlerImpl.
2-Override the public void reportException(DCBindingContainer bc, Exception ex) .
According your requirement report the exception on DCErrorHandlerImpl.
package com.prateek.blog.view.exception;
import oracle.adf.model.binding.DCBindingContainer;
import oracle.adf.model.binding.DCErrorHandlerImpl;
import oracle.jbo.JboException;
public class CustomExceptionHandler extends DCErrorHandlerImpl {
public CustomExceptionHandler() {
super(true);
}
@Override
public void reportException(DCBindingContainer dCBindingContainer,
Exception exception) {
if (exception instanceof JboException) {
//By default all exception which are coming from Model layer all are instance of JboException
//here just i am try to skip the exception to report to super class which is DCErrorHandlerInpl
//we can write our own logic
// if the exception came of model then it always go through this if condition
} else {
super.reportException(dCBindingContainer, exception);
}
}
private void disableAppendCodes(Exception ex) {
if (ex instanceof JboException) {
JboException jboEx = (JboException)ex;
jboEx.setAppendCodes(false);
Object[] detailExceptions = jboEx.getDetails();
if ((detailExceptions != null) && (detailExceptions.length > 0)) {
for (int z = 0, numEx = detailExceptions.length; z < numEx;
z++) {
disableAppendCodes((Exception)detailExceptions[z]);
}
}
}
}
@Override
public DCErrorMessage getDetailedDisplayMessage(BindingContext bindingContext,
RegionBinding regionBinding,
Exception exception) {
return super.getDetailedDisplayMessage(bindingContext, regionBinding,
exception);
}
@Override
public String getDisplayMessage(BindingContext bindingContext,
Exception exception) {
return super.getDisplayMessage(bindingContext, exception);
}
@Override
protected boolean skipException(Exception exception) {
return super.skipException(exception);
}
}
import oracle.adf.model.binding.DCBindingContainer;
import oracle.adf.model.binding.DCErrorHandlerImpl;
import oracle.jbo.JboException;
public class CustomExceptionHandler extends DCErrorHandlerImpl {
public CustomExceptionHandler() {
super(true);
}
@Override
public void reportException(DCBindingContainer dCBindingContainer,
Exception exception) {
if (exception instanceof JboException) {
//By default all exception which are coming from Model layer all are instance of JboException
//here just i am try to skip the exception to report to super class which is DCErrorHandlerInpl
//we can write our own logic
// if the exception came of model then it always go through this if condition
} else {
super.reportException(dCBindingContainer, exception);
}
}
private void disableAppendCodes(Exception ex) {
if (ex instanceof JboException) {
JboException jboEx = (JboException)ex;
jboEx.setAppendCodes(false);
Object[] detailExceptions = jboEx.getDetails();
if ((detailExceptions != null) && (detailExceptions.length > 0)) {
for (int z = 0, numEx = detailExceptions.length; z < numEx;
z++) {
disableAppendCodes((Exception)detailExceptions[z]);
}
}
}
}
@Override
public DCErrorMessage getDetailedDisplayMessage(BindingContext bindingContext,
RegionBinding regionBinding,
Exception exception) {
return super.getDetailedDisplayMessage(bindingContext, regionBinding,
exception);
}
@Override
public String getDisplayMessage(BindingContext bindingContext,
Exception exception) {
return super.getDisplayMessage(bindingContext, exception);
}
@Override
protected boolean skipException(Exception exception) {
return super.skipException(exception);
}
}
*This is just a example to just skip the exception.Please see the following link for more information.
1-http://docs.oracle.com/cd/B31017_01/web.1013/b25947/web_val008.htm
3-After Creating our own custom exception handler we need to write this class in DataBinding.cpx as ErrorHandlerClass
<application clienttype="Generic" errorhandlerclass="com.prateek.blog.view.exception.CustomExceptionHandler" id="DataBindings" package="com.prateek.blog.view" separatexmlfiles="false" version="11.1.1.59.23" xmlns="http://xmlns.oracle.com/adfm/application">
<pagemap>
<page path="/exceptionPage.jspx" usageid="com_prateek_blog_view_exceptionPagePageDef">
</page></pagemap>
<pagedefinitionusages>
<page id="com_prateek_blog_view_exceptionPagePageDef" path="com.prateek.blog.view.pageDefs.exceptionPagePageDef">
</page></pagedefinitionusages>
<datacontrolusages>
<bc4jdatacontrol configuration="AppModuleLocal" factoryclass="oracle.adf.model.bc4j.DataControlFactoryImpl" id="AppModuleDataControl" package="com.prateek.blog.model" supportsfindmode="true" supportsrangesize="true" supportsresetstate="true" supportssortcollection="true" supportstransactions="true" syncmode="Immediate" xmlns="http://xmlns.oracle.com/adfm/datacontrol">
</bc4jdatacontrol></datacontrolusages>
</application>
<pagemap>
<page path="/exceptionPage.jspx" usageid="com_prateek_blog_view_exceptionPagePageDef">
</page></pagemap>
<pagedefinitionusages>
<page id="com_prateek_blog_view_exceptionPagePageDef" path="com.prateek.blog.view.pageDefs.exceptionPagePageDef">
</page></pagedefinitionusages>
<datacontrolusages>
<bc4jdatacontrol configuration="AppModuleLocal" factoryclass="oracle.adf.model.bc4j.DataControlFactoryImpl" id="AppModuleDataControl" package="com.prateek.blog.model" supportsfindmode="true" supportsrangesize="true" supportsresetstate="true" supportssortcollection="true" supportstransactions="true" syncmode="Immediate" xmlns="http://xmlns.oracle.com/adfm/datacontrol">
</bc4jdatacontrol></datacontrolusages>
</application>
4-The following code which i have written in to backing bean to show our custom message on UI.
public void jboException(ActionEvent actionEvent) {
BindingContainer bindings =
BindingContext.getCurrent().getCurrentBindingsEntry();
OperationBinding opeartionBinding =
bindings.getOperationBinding("throwNewException");
opeartionBinding.execute();
if (opeartionBinding.getErrors().size() > 0) {
FacesContext context = FacesContext.getCurrentInstance();
FacesMessage message = new FacesMessage("Error message here");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
context.addMessage(null, message);
}
}
public void numberPointerException(ActionEvent actionEvent) {
BindingContainer bindings =
BindingContext.getCurrent().getCurrentBindingsEntry();
OperationBinding opeartionBinding =
bindings.getOperationBinding("throwNewException1");
opeartionBinding.execute();
if (opeartionBinding.getErrors().size() > 0) {
FacesContext context = FacesContext.getCurrentInstance();
FacesMessage message = new FacesMessage("Error message here");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
context.addMessage(null, message);
}
}
BindingContainer bindings =
BindingContext.getCurrent().getCurrentBindingsEntry();
OperationBinding opeartionBinding =
bindings.getOperationBinding("throwNewException");
opeartionBinding.execute();
if (opeartionBinding.getErrors().size() > 0) {
FacesContext context = FacesContext.getCurrentInstance();
FacesMessage message = new FacesMessage("Error message here");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
context.addMessage(null, message);
}
}
public void numberPointerException(ActionEvent actionEvent) {
BindingContainer bindings =
BindingContext.getCurrent().getCurrentBindingsEntry();
OperationBinding opeartionBinding =
bindings.getOperationBinding("throwNewException1");
opeartionBinding.execute();
if (opeartionBinding.getErrors().size() > 0) {
FacesContext context = FacesContext.getCurrentInstance();
FacesMessage message = new FacesMessage("Error message here");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
context.addMessage(null, message);
}
}
And upcoming blog i will explain exception handling on task flow and exception handling as global.
This exception handling approach is not going to catch any exception which is thrown from UI
Thanks
Prateek Shaw
Nice explanation dude!
ReplyDeleteKeep it Up..
When we work on multi project env, where all (I mean which projects) above classes are to be created? Is it to be a Model project (where we create View and entity objects including app modules) or in UI project (where we create jsff/jspx/backing beans).
ReplyDeleteFor eg:
"CustomlExceptionHandler extends DCErrorHandlerImpl", "FacesPageLifecycleBean extends FacesPageLifecycle", and "ADFPhaseListenerBean extends ADFPhaseListener" - where (projects) will these go?