0

I have an EJB3 application which consists of some EJB's for accessing a DB, and exposed via a Session Bean as a web service.

Now there are two things I need to find out:

1) Is there any way I can stop SQL exceptions from causing the web service from throwing a SOAP Fault? The transactions are handled by the container, and currently sql exceptions cause a RollBackException to be thrown, and consequently the transaction to be rolled back (desired behaviour) and the web service to throw a fault (not desired).

2) I wish to extend the webservice to be able to take in a list of entities, and the session bean to persist each. However, I want each entity to be executed in its own transaction, so that if one fails the others are not affected (and again the web service should not fault).

For (1) I have tried to catch the RollBackException, but I assume this is thrown somewhere on another thread, as the catch block is never reached. I assume for (2) I will need to look into User Transactions, but firstly would prefer the container to manage this, and secondly do not know how to force the use of user transactions.

Thanks.

Anthony Roy
  • 1,835
  • 3
  • 15
  • 16

2 Answers2

2

no, you can do all this with container managed transactions (and this is definitely preferable, as managing transactions is a pain).

the gist of the solution is to create a second EJB with a local interface only and the transaction semantics you desire. then your "public" ejb, which the web-service is calling directly, calls into this second ejb via its local interface to do the actual work.

something along the lines of:

public class MyPublicEjb {
  @EJB
  private MyPrivateImpl impl;

  public void doSomething() {
    try {
      impl.doSomething();
    } catch(TXRolledBack) {
      // handle rollback ...
    }
  }
}

I know this looks sort of ugly, but trust me, this is far preferable to directly manipulating transactions.

james
  • 1,379
  • 7
  • 6
  • With the caveat that the private EJB required a @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) annotation (otherwise we have the same situation as before as the transaction is scoped on the calling EJB) this worked. Thanks. – Anthony Roy Mar 24 '09 at 10:58
0

For (1): Debug your code to find out where the exception is being thrown and what is causing it. Then handle the exception there.

For (2): Wrap each instance with beginTransaction() and commit().

for(each Entity){
    try{
        //begin transaction
        //save entity
        //commit
    } catch(Exception e) {
         //handle Exception, but continue on
    }
}
Kevin Crowell
  • 10,082
  • 4
  • 35
  • 51
  • As I said - the exception seems to be being thrown from a separate thread - or at least after my code has finiished what it is doing. Specifically, my code has returned control to the App server by the time the exception is thrown - i.e. it is not possible to catch it. – Anthony Roy Mar 23 '09 at 15:12
  • On the second point, I am quite aware of the general solution to this sort of problem - just not the specifics of how to do it in EJB3. How do I begin and commit transactions using the EntityManager? How do I get hold of an EntityManager which isn't bound to a container managed transaction? – Anthony Roy Mar 23 '09 at 15:17