so the problem is pretty simple:
We are using JSF 2.0 with Primefaces and EJB to handle our application and we have encountered a problem. We have a single @SessionScoped bean in which we store all ours @Stateful Session Beans.
In one case, (when we didn’t handle some exceptions from JPA) and there is an exception:
javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "webuser_idwebuser_pk"
Detail: Key (idwebuser)=(6) already exists.
It leads to destruction of one of our @Stateful Session Bean.
So after refreshing the website, when JSF is still working correctly, after filling the form and trying to submit it, by invoking a method from that Bean there is an exception:
javax.ejb.NoSuchObjectLocalException: The EJB does not exist. session-key: 22900a4d007e1f-6dcc714a-0
What is the most problematic, we have to restart and redeploy the application to make it work on the same computer (or web browser) because the JSF’s @SessionScoped Bean is somehow kept through cookies or something.
So the solution I guess would be to force the destuction of that @SessionScoped or refresh the session somehow, but actually I have no idea how to do so.
Or what would be a better approach.
Thanks!
To remedy this, you need to be aware about the difference between application- and system exceptions in EJB.
Those roughly correspond to checked and runtime exceptions respectively.
Application exceptions are supposed to be handled by your own code, and will not cause a transaction rollback or the destruction of a bean. System exceptions have the opposite effect and will cause a rollback and the destruction of the EJB bean.
The latter effect is what you are seeing. JPA throws unchecked exceptions, which thus become system exceptions, which thus cause your SFSB to be destroyed. JSF nor CDI managed beans participate in this “system exception” thing, so they will just propagate the exception and will stay alive.
What you probably want is to define a new Exception that you annotate with @ApplicationException and then set its rollback attribute to true. Catch the JPA exception within your SFSB and wrap and rethrow it with your custom exception.