Tuesday, May 18, 2010

Differences of Handling JboException in Oracle ADF

Today I will talk more about best practices, not about technical problems. From what I saw, especially new ADF developers, frequently are experiencing problems with handling JboExceptions. Its not about how to throw JboException, but about how to invoke method that throws it.

Download sample application - JboExceptionPropagation.zip. This sample implements two approaches about how to call custom method from the Model layer. Custom method is simple, it just throws JboException in both cases:


Method that I'm calling from managed bean, is implemented and exposed through Application Module client interface:


It simply throws JboException:


This custom method is declared in Page Definition Bindings, to make it available for the client:


Now most important part of this blog - how we invoke custom method defined in Application Module implementation class:


First function calls custom method correctly - through bindings. In case of JboException in that custom method, framework will raise error popup automatically.

Second function is accessing Application Module Implementation class directly, bypassing bindings layer. In this case, if developer forgets to catch thrown JboException - server error will appear and application will be broken.

So, always call custom methods from Application Module interface through bindings layer.

32 comments:

Karim Hasan Abdellatif said...

Hello Andrejus,
All your posts are useful, great effort.

I have question
which better calling custom method through binding layer or by bypassing it and create instance of Application module in backing bean?

Regards
Karim

Andrej Baranovskij said...

Hi Karim,

As per blog entry, it is better to call custom method through binding layer.

First, it is wrong ADF practice to bypass binding layer and create instance of Application Module in backing bean.

Second, JboExceptions are not catched automatically, if you bypass binding layer.

Regards,
Andrejus

Maniesh Sailoz (sid) said...

This is a nice little demonstration.

Ankit said...

Hi....First button click is generating stack trace error message on the console....I want to handle that..Please let me know about it....

Andrej Baranovskij said...

You can handle it with ADF error handling inside DCErrorHandler class. What is specific issue?

Andrejus

Ankit said...

Hi
I have just downloaded your application and try it to run on my machine....then of course it is generating pop-up alert but it is also generating stack trace message on the console.....I want to handle that stack trace message...Can you please provide with that type of working application...

Ankit said...

I tried to do it with DCError handler class...but it is not getting handled...

Andrej Baranovskij said...

Try those posts:

http://andrejusb.blogspot.com/2011/03/exception-handler-for-method-calls_19.html

http://andrejusb.blogspot.com/2011/03/exception-handler-for-method-calls.html

Andrejus

Ankit said...

Hi already have tried these two examples....and facing same issue ...that is not able to handle stack trace....please you try it at your end...

Andrej Baranovskij said...

Please send me detail screenshots and steps to reproduce your problem. I can't help you on so abstract question.

Andrejus

Ankit said...

Hi
How I can send the screen shot....I am not able to find any option on this site to send the image..
I sending the details of the exception that I am getting on the console....



racle.jbo.JboException: Data Processing Failed
at com.redsamurai.model.HrModuleImpl.processData(HrModuleImpl.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at oracle.adf.model.binding.DCInvokeMethod.invokeMethod(DCInvokeMethod.java:638)
at oracle.adf.model.binding.DCDataControl.invokeMethod(DCDataControl.java:2136)
at oracle.adf.model.bc4j.DCJboDataControl.invokeMethod(DCJboDataControl.java:3063)
at oracle.adf.model.binding.DCInvokeMethod.callMethod(DCInvokeMethod.java:261)
at oracle.jbo.uicli.binding.JUCtrlActionBinding.doIt(JUCtrlActionBinding.java:1635)
at oracle.adf.model.binding.DCDataControl.invokeOperation(DCDataControl.java:2143)
at oracle.jbo.uicli.binding.JUCtrlActionBinding.invoke(JUCtrlActionBinding.java:740)
at oracle.adf.controller.v2.lifecycle.PageLifecycleImpl.executeEvent(PageLifecycleImpl.java:394)
at oracle.adfinternal.view.faces.model.binding.FacesCtrlActionBinding._execute(FacesCtrlActionBinding.java:252)
at oracle.adfinternal.view.faces.model.binding.FacesCtrlActionBinding.execute(FacesCtrlActionBinding.java:210)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.el.parser.AstValue.invoke(Unknown Source)
at com.sun.el.MethodExpressionImpl.invoke(Unknown Source)
at oracle.adf.controller.internal.util.ELInterfaceImpl.invokeMethod(ELInterfaceImpl.java:168)
at oracle.adfinternal.controller.activity.MethodCallActivityLogic.execute(MethodCallActivityLogic.java:160)
at oracle.adfinternal.controller.engine.ControlFlowEngine.executeActivity(ControlFlowEngine.java:989)
at oracle.adfinternal.controller.engine.ControlFlowEngine.doRouting(ControlFlowEngine.java:878)
at oracle.adfinternal.controller.engine.ControlFlowEngine.doRouting(ControlFlowEngine.java:777)
at oracle.adfinternal.controller.engine.ControlFlowEngine.routeFromActivity(ControlFlowEngine.java:551)
at oracle.adfinternal.controller.engine.ControlFlowEngine.performControlFlow(ControlFlowEngine.java:147)
at oracle.adfinternal.controller.application.NavigationHandlerImpl.handleAdfcNavigation(NavigationHandlerImpl.java:109)
at oracle.adfinternal.controller.application.NavigationHandlerImpl.handleNavigation(NavigationHandlerImpl.java:78)
at org.apache.myfaces.trinidadinternal.application.NavigationHandlerImpl.handleNavigation(NavigationHandlerImpl.java:43)
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:130)
at org.apache.myfaces.trinidad.component.UIXCommand.broadcast(UIXCommand.java:190)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:475)

Andrej Baranovskij said...

There is email in about blog section.

Which sample you are running - one with pages, or one with fragments?

Andrejus

Ankit said...

One with pages....Although...one with fragment is also generating the same stack trace ...

Andrej Baranovskij said...

Stack trace will be generated always, only in addition you can intercept error in DCErrorHandler. But you cant hide stack trace.

Andrejus

Andrej Baranovskij said...

Of course, unless you will do try/catch in Java code.

Andrejus

Andrej Baranovskij said...

Here is code where exception is catched, in case of pages: https://lh5.googleusercontent.com/-Ev7aqW3NaKM/TYUPEwJ0lGI/AAAAAAAAE6k/_T9n3Uy27Kw/s1600/6.png

Andrejus

Ankit said...

But if we are using try catch in application module then also ...it is generating stack trace.....

Andrej Baranovskij said...

What I can say, if you say so :-)

Ankit said...

public void processData() {
try{
int a=10/0;
}catch(Exception e){
throw new JboException("Data Processing Failed");
}
}

The code is generating stack trace....now please let me know....

But if I remove line throw new JboException("Data Processing Failed"); then no exception is generated...

Andrej Baranovskij said...

Yes, thats how it works. Because we are doing throw new JboException("Data Processing Failed"); then ADF reports stack trace. From ADF Model layer we are throwing to ViewController. Thats normal behavior.

If you dont want to throw exception, you can just log it in catch block and not re-throw.

Andrejus

Ankit said...

Then how we will let the user know that the what kind of exception has occurred...??
I want the use to navigate to different screen on occurence of exception..

Andrej Baranovskij said...

Just define Error Handler activity (page) on ADF Task Flow, and you are done.

Andrejus

Ankit said...

please explain it in detail....I am able to navigate to different screen but not able to hide the stack trace...

Andrej Baranovskij said...

You will not hide stack trace, I already explained it.

Andrejus

Ankit said...

Thanks a lot for your co-operation......means there is no way to hide stack trace...

But I am able to do it when I am writting my own custom functions .....in managed bean....
public void arthException(ActionEvent actionEvent) {
try {
int a = 10 / 0;
}
catch (ArithmeticException e) {
System.out.println("Exception thrown..." + e);
throw new JboException("Arithmetic Exception", "ARTH", null);
}
}


and is able to navigate to appropriate screen by passing ARTH object error code in adf-config. with out stack trace message..

Andrej Baranovskij said...

Thats because in your example JboException is thrown from ViewController itself, framework is not registering it. However when you throw from Model, then its different.

Its common practice to show stack trace error.

Andrejus

Ankit said...

Ther exception which is generated is not able to reach the following code in my application....please let me know what I can be missing..??


public TaskFlowId getDynamicTaskFlowId() {
ControllerContext context = ControllerContext.getInstance();
ViewPortContext currentRootViewPort = context.getCurrentRootViewPort();
Exception exceptionData = currentRootViewPort.getExceptionData();

if (currentRootViewPort.isExceptionPresent()) {
exceptionData.printStackTrace();

currentRootViewPort.clearException();

TabContext.getCurrentInstance().removeCurrentTab();
List tabs = TabContext.getCurrentInstance().getTabs();
for (int i = 0; i < tabs.size(); i++) {
TabContext.getCurrentInstance().removeTab(i);
}

return TaskFlowId.parse(taskFlowIdError);
}

return TaskFlowId.parse(activeTaskFlowID);
}


if (currentRootViewPort.isExceptionPresent())


this statement is returning false on presence of exception also....

I am trying for fragments case...

Jacob said...

What is the best practice, if I want to commit the transaction after invoking the operation. I want that the transaction i committed or rolled back depending on whether the operation was successfully called.

Andrej Baranovskij said...

You can implement your custom method in AM impl class with try/catch. Rollback in catch block.

Andrejus

Anonymous said...

Hi,Andrejus.

I have used listofcombobox we enter wrong data error come from frame work like error is : Invalid values: sssss . my case i want override error message its possible.

kindly help me.....

Thanks

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 ?

swath said...

Hello Andrejus,

I have implemented database commit as AMImpl client interface and doing rollback in bean catch block if JBO error is thrown.
If any JBO error occurs, the page becomes invalid and I need to rerun the page to perform other operations. Can you please let me know how can I completely rollback the changes and continue with the current transaction.