Handling Exceptions in 2 Tier vs. 3 Tier
Question
I created a class that implements oracle.jbo.JboExceptionHandler and I used the method setExceptionHandler to bind it to my ApplicationModule. But the exceptions that occur in the BC4J are never caught by the JboExceptionHandler (the method handleException is never called). In opposition, the handleWarning works when I call the addWarning method of the ApplicationModule. In the documentation of JDeveloper I read that the handleException only works in three-tier application. What does it exactly mean? How should I deploy my application to make it work. How should I throw the Exception to make them catch by the ExceptionHandler?
Answer
In BC4J, a part of your application may run as a part of the middle tier (MT) app and another part may run asclient code that uses this middle tier app.
Even for the client code, the client code (depending on the deployment mode) may run in the same JVM as the middle tier app or in a separate JVM. In the latter case, the MT part needs to be deployed as EJB Session Bean.
If a part of you app is running in the same JVM as MT, when an exception is thrown from BC4J app-server code, the exception is thrown as a normal Java exception. This means that JVM will throw that back to you and your code needs to catch that exception if you want to process it.
If the client part of the app is running in a separate JVM (we refer to this as 3 tier), an exception (obviously) cannot be thrown across JVMs. Hence, in this configuration, we (BC4) package up the exceptions in the app-server and carry them to the client side.
Also, in this 3 tier configuration, more than one exception may have been thrown and packaged. When the exception info reaches CLI, we cannot simply throw the exception because there may be more than one.
This is where JboExceptionHandler comes in. In this case (3 tier), we call handleException method of JboExceptionHandler, notifying the client app with each exception.
Thus,
- When the code runs in the same JVM as the MT code that throws the exception, you simply catch the exception in the normal Java way and process it.
- When the code runs in a different JVM (client code in 3 tier), you need to process exception through JboExceptionHandler and handleException.
For warnings, there is no throw-catch mechanism supported by JVM. Hence, JboExceptionHandler's handleWarning is called in all cases (regardless of the JVM configuration or 2 tier vs. 3 tier).
There are times when you would write a client app code that can run in either 2 tier (same JVM as MT) or 3 tier. If you want your app to run equivalently in both configs, you need to do both: catch block for the 2 tier case, and JboExceptionHandler for the 3 tier case. ================================ Sample code below. First define a class that implements oracle.jbo.JboExceptionHandler. For example, public class myClass implements oracle.jbo.JboExceptionHandler This class must implement the following methods as declared in the interface.
void handleException(Exception ex, boolean lastEntryInPiggyback); void handleWarning(JboWarning warn); void finishedProcessingPiggyback(Exception[] exArray);
Get the Application Module on which you want to install this exception handler. For example, ApplicationModule myAM; ... initialize myAM ... myAM.setExceptionHandler(this);
In your client code, suppose you want to handle exception raised when you call myMethod(). Then, you would write code like: try { ... myMethod(); } catch(Exception ex) { ... error handling code ... } If you want to catch specific exception class, you may specify that in your catch declaration. When the application is running in 2 tier, if an exception is thrown while myMethod() is being serviced, then the catch block is reached and your exception handling as written in the catch block will execute. In 3 tier execution, here is what happens. Suppose some action in CLI causes a visit to middle tier app-server (MT). It services the request. This may result in multiple exceptions. A "record" of things that happened in MT is sent back to CLI in one network packet. This packet may contain many method calls and exceptions. When the packet comes to CLI, it is unpacked and each method call/exception is played back in CLI. While doing so, if an exception entry is found, BC4J's CLI library will call void handleException(Exception ex, boolean lastEntryInPiggyback); The 'lastEntryInPiggyback' is a flag indicating whether the exception entry is the last one in the packet. When done with processing all entries in the packet, void finishedProcessingPiggyback(Exception[] exArray);
is called to give the user code a chance to handle exceptions in mass. What if you don't install any JboExceptionHandler and run the app in 3 tier? In this case, BC4J handles exception entries in the packet in the following way. After the packet is completely processed, it looks at the array of exceptions (just as if finishedProcessingPiggyback() was called on your custom JboExceptionHandler). Then, it throws the last exception of the array. For uniform handling of exceptions, I would recommend the following: Put your exception handling logic in a separate helper method. For 2 tier, add a call to this helper method in your catch block. For 3 tier, install your JboExceptionHandler. You have a choice to handle exceptions as they occur (one by one). For this, you would add code to call the helper method in handleException(). Or, you can handle them all at once. For this, you would put the handling logic in finishedProcessingPiggyback(). If you go with the handleException() approach, however, you must remember not to throw any exception from within handleException(). If you do that it may short-circuit processing of the packet and the CLI side state may no longer be in sync with MT. In contrast, finishedProcessingPiggyback() may throw an exception.
9:42:15 AM
|