Throwing Application exceptions from EJB Callbacks...


EJB design: Throwing Application exceptions from EJB Callbacks...

  1. Hello All,
       Our application uses BMP entity beans. We would like to build custom validations to our database tables using triggers and handle them in our beans.

       The current implementation of our beans throw an EJBException when we receive an error from Oracle. This results in the container throwing a TransactionRolledBack exception . Some application servers do not provide the cause of the actual exception and hence the client code is unable to see the actual reason for the exception...

       Here's what we want to do :-

       public void ejbStore()
          try {
          } catch (SQLException e)
       // If Validation exception from Oracle Error code > 2000
            throw ApplicationException(e);
       This would require that the call back methods like ejbStore to throw Custom Application exceptions.
       However, this is not supported as the ejbStore cannot throw arbitrary application exceptions..
      Any pointers on how to use triggers to validate data and use them in beans...


  2. Just a quick pointer. You should never check the error code contained within an SQLException against vendor-specific codes, such as Oracle. By doing so, your beans are NOT portable. If your company decided to change database for some reason (and dont think for a moment that something like that would never occur), then your beans would no longer function properly since a new vendor likely uses a different set of error codes. If checking errors codes is a must, then I would create another layer of abstraction which decouples the EBJ from any vendor-specific feature.

  3. Hi SAF,
      Thanks for the pointer...We intend to write database triggers to perform custom validations. This gives us the flexibility to choose our own custom error codes for any database. Therefore, we do not foresee this as a problem - we will be not be checking for the non-user defined codes..
       We need a way to handle the custom error message from the trigger within the bean ..
  4. Maybe you should "pack" your application exceptions in an EJBException. Since it's a call-back method, it's quite common to let the implementation throw some pre-defined, nested exception. Or how could the container providers implement the mechanisms to invoke these call-back methods? :)
  5. Hello Dright,
       Wrapping the pre-defined exception within an EJBException is fine for some app. servers... App. servers like Weblogic recognize this and provide the whole nested trace to the client. However, app servers like IPlanet discards the nested exception in the EJBException and throws an instance of javax.transaction.TransactionRolledBack exception with no trace of the root cause exception.
       We do not want to necessarily throw an Application exception from ejbstore. We only want to find out a possible way to support validation errors raised from DB triggers using the raise_application_error methods...
  6. Hi Sunil,
      I don't think detecting application exceptions in those container call-backs is appropriate. Those call-backs, like ejbStore or ejbLoad, are not activated by any client. This means the clients are not supposed to catch the exceptions raised from those methods. You are only able to access those business operations you designed for an EJB, and that are the only places you may raise application exceptions. You cannot predict when ejbLoad or ejbStore will be invoked.

      I think maybe you should move the validations out of the DB server. Implement these validations in your business methods so that you may have more control on what is going wrong in the validation.
  7. Hi Sunil,

    The solution I am trying to provide is certainly not an easy solution. And I am also not sure if this is a good design.

    In the ejbStore() catch block try to capture your custom exception code and record it somewhere so that it is accessible to your business method(s). If the ejbStore() finishes calmly record zeros as Custom Exception code(or soemthing else if zeros is not ok with your scenario).

    And this is the lengthy part, in each of your business methods which might trigger the app server to call ejbStore(), check to see if your custom exception code is still zeros or not. If it is not, throw appropriate Application Exception based on the value.

    I would like to know how you solve this problem, if this solution doesn't suit/interest you.

    Ramana Yalamanchili.
  8. Hi Ramana,

    Your solution seems to fit in some situations. However, not all ejbStore invocations are initiated from the business methods. If you do check the "exception stores" in all your business methods, it's quite possible that the exception is not caused by the same method.

    And I think doing so will make the program get in a mess sooner :) If you write more than 20 session beans, you will get a headache :p
  9. Hello Ramana and Dright,
      Thanks for your suggestions. Ramana, your suggestion, though cumbersome to implement, may be fine in certain situations. I'm inclined to agree with Dright on his opinion on this..
       We already have our session beans built and modifying the code to check for this new error code may be a nightmare...
       I believe this might be possible if you were starting a fresh development project...
       As of now, i'm leaning towards moving the validations from the database to the bean...This reduces the flexibility of our system, as clients could have written their own custom triggers to add extra validations to our application...
       Well, as long as J2EE does not mandate that the container preserves the actual root cause of the exception all through the trace, this might very well be impossible...
  10. Just an interesting note: EJB actually mandates that containers must not pass the exception wrapped inside an EJBException to the client. Passing only the trace data is possible, but not mandated.

    The reason why EJB server must not pass the exception to the client is somewhat complex. I had allready participated in a rather lengthly discussion about this topic. If anyone is interested, it's at: