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:

  1. 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

    ReplyDelete
  2. 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

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

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

    Andrejus

    ReplyDelete
  5. 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...

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

    ReplyDelete
  7. 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

    ReplyDelete
  8. 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...

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

    Andrejus

    ReplyDelete
  10. 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)

    ReplyDelete
  11. There is email in about blog section.

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

    Andrejus

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

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

    Andrejus

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

    Andrejus

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

    Andrejus

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

    ReplyDelete
  17. 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...

    ReplyDelete
  18. 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

    ReplyDelete
  19. 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..

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

    Andrejus

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

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

    Andrejus

    ReplyDelete
  23. 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..

    ReplyDelete
  24. 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

    ReplyDelete
  25. 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...

    ReplyDelete
  26. 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.

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

    Andrejus

    ReplyDelete
  28. 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

    ReplyDelete
  29. 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 ?

    ReplyDelete
  30. 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.

    ReplyDelete