Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

oracle - catch DB exception in JSF+EJB application

I'm using Glassfish 3.1 with JSF2 and EJB stateless to query and write an Oracle DB. The table the user wants to populate in this web application has a primary key. When the user tries to add a new record the ejb method invoking em.persist is called. Now, if the user tries to add a record that has an already used primary key value, I got an exception in the EJB. I would like to pop up a message to the user indicating that an error in the database occurred but I can't figure out how the JSF managed bean could catch the EJB exception. Is there any way?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

EJB has the concept of system exceptions and application exceptions.

Runtime exceptions, like EntityExistsException are system exceptions. These will among others cause any transaction to be rolled-ed back and cause the EJB instance bean to be discarded (destroyed). Most importantly for your problem, they will be wrapped in an EJBException.

There is no magic surrounding catching these exceptions. Adjusting the code from Petr above,
the following will just work:

Backing bean:

@EJB
private DAOBean daoBean;

public void savePerson(Entity e) {
     try {
         daoBean.save(e);
     } catch (EJBException e) {         
         FacesMessage message = new FacesMessage("entity is already exists.");
         FacesContext.getCurrentInstance.addMessage(null, message);
     }         
}

EJB:

private EntityManager em;

public void save(Entity e) {    
    em.persist(e);    
}

Note that you can retrieve the cause of the exception to see if was an EntityExistsException or not (omitted above for brevity).

Since you probably have no need to destroy your EJB instance for this case, a better pattern is to define your own exception that inherits from a RuntimeException and is annotated with the @ApplicationException with the rollback attribute set to true.

E.g.

@ApplicationException(rollback = true)
public class MyException extends RuntimeException {

    public MyException(Throwable cause) {
        super(cause);
    }
}

Wrap your EntityExistsException in your EJB into this exception and throw and catch it.

I strongly advise you NOT to use error codes or boolean success/failure as a result. This is a well-known anti pattern and makes your code incredible error prone.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...