java - In JSF, a custom exception thrown by called EJB is seen as EJBTransactionRolledBackException or NullPointerException or ServletException -
here's problem: ejb throws exception (from glassfish logs):
severe: attempting confirm confirmed login using confirmation uuid: b90b33ca-dc69-41c1-9c60-99152810c89b com.extremelatitudesoftware.els_commons.exceptions.loginpreviouslyconfirmedexception: attempting confirm confirmed login using confirmation uuid: b90b33ca-dc69-41c1-9c60-99152810c89b @ com.extremelatitudesoftware.security.auth.credentialscontroller.checkforpreviousconfirmation(credentialscontroller.java:244)
and on client side of exception stack (down @ bottom) see this:
warning: standardwrappervalve[faces servlet]: pwc1406: servlet.service() servlet faces servlet threw exception java.lang.nullpointerexception @ com.extremelatitudesoftware.accesscontrol.registration.registrationconfirmationbean.setchallengequestion(registrationconfirmationbean.java:61) @ com.extremelatitudesoftware.accesscontrol.registration.registrationconfirmationbean.fetchchallengeresponse(registrationconfirmationbean.java:51)
and of course in browser generic 500 exception error says there null pointer exception.
i want have custom error page detects "com.extremelatitudesoftware.els_commons.exceptions.loginpreviouslyconfirmedexception" , "oops confirmed this!"
can point me in right direction getting client/jsf layer correctly "see" exception may done.
this use case problem:
have method in ejb layer checks see if user has confirmed login account. if haven't processes request confirm new account. if have gone old email , said, hmmmmm let's click on again, end detect that, throw exception intent of being picked jsf/client layer , user advised account confirmed.
adding example code:
method checking condition , throwing exception if necessary. note majority of time won't happen want use mechanism instead of making unnecessary calls every time confirms account.
... private void checkforpreviousconfirmation(credentials cr) throws loginpreviouslyconfirmedexception { if (!(credentialsstatustype.pending.equals(cr.getstatus())) || !(credentialsdispositiontype.waiting.equals(cr.getdisposition()))) { string msg = "attempting confirm confirmed login using " + "confirmation uuid: " + cr.getconfirmationuuid(); logger.getlogger(credentialscontroller.class.getname()).log(level.info, msg); throw new loginpreviouslyconfirmedexception(msg); } }
the custom exception:
public class loginpreviouslyconfirmedexception extends runtimeexception { public loginpreviouslyconfirmedexception(string msg, throwable cause) { super(msg, cause); } public loginpreviouslyconfirmedexception(string msg) { super(msg); } }
this in managedbean in jsf tier. called via: prerenderview
... public void fetchchallengeresponse() { try { cresplist = regfacade.fetchchallengeresponse(confirmuuid); } catch (loginpreviouslyconfirmedexception ex) { string msg = "attempting confirm confirmed login using " + "confirmation uuid: " + getconfirmuuid(); logger.getlogger(registrationconfirmationbean.class.getname()).log(level.severe, msg, ex); facescontext facescontext = facescontext.getcurrentinstance(); application application = facescontext.getapplication(); navigationhandler navigationhandler = application.getnavigationhandler(); navigationhandler.handlenavigation(facescontext, null, "faces/errorpages/already_confirmed.xhtml"); facescontext.renderresponse(); }catch (exception ex){ string msg = "including see if confirmed exception skipped over"; logger.getlogger(registrationconfirmationbean.class.getname()).log(level.severe, msg, ex); } this.setchallengequestion(); }
this log shows:
info: attempting confirm confirmed login using confirmation uuid: b90b33ca-dc69-41c1-9c60-99152810c89b warning: ejb5184:a system exception occurred during invocation on ejb credentialscontroller, method: public java.util.arraylist com.extremelatitudesoftware.security.auth.credentialscontroller.fetchchallengeresponsebycredentialuuid(java.lang.string) throws com.extremelatitudesoftware.els_commons.exceptions.loginpreviouslyconfirmedexception warning: javax.ejb.transactionrolledbacklocalexception: exception thrown bean
then couple traces down:
severe: including see if confirmed exception skipped on javax.ejb.ejbtransactionrolledbackexception
per balusc's suggestion changed code in managedbean this:
public void fetchchallengeresponse() throws loginpreviouslyconfirmedexception{ cresplist = regfacade.fetchchallengeresponse(confirmuuid); this.setchallengequestion(); }
this in web.xml
<error-page> <exception-type>com.extremelatitudesoftware.els_commons.exceptions.loginpreviouslyconfirmedexception</exception-type> <location>/errorpages/already_confirmed.xhtml</location> </error-page>
here simplest , best answer have found through researching today: decorate custom exception @applicationexception(rollback=true) annotation.
e.g.
@applicationexception(rollback=true) public class loginpreviouslyconfirmedexception extends exception {...
the fundamental problem before passing exception client, ejb container wraps @ least exceptions in "ejbtransactionrolledbackexception" wrapper. i'm not sure seems similar way jsf wants wrap exceptions in "servletexception" raised there. seems me pretty flawed thinking hide real application errors are. in case prevents client "seeing" kind of special case exception might throw reason being or user can correct without aborting whole operation. is, see ejbtransactionrolledbackexception used wrap multitude of exceptions. doing makes impossible debug or handle exceptions. fortunately in latest issues of jee included @applicationexception annotation counteract behaviour. although don't see why don't stop wrapping exceptions altogether.
in case, @applicationexception(rollback=true) tells server not wrap exception in ejbtransactionrolledbackexception , pass it, is, client. allows client see real exception have chance of handling gracefully. specifying "rollback=true" tells server roll current transaction. if don't, defaults false , drop right there. ending @ whatever state things in.
if custom exception inherits exception, , method in ejb session bean throws it, method doing calling in jsf managedbean have throw too. if inherits runtimeexception, not.
in case exception not wrapped ejbtransactionrolledbackexception, when gets jsf layer exception page defined in web.xml custom exception called. no need catch exception in managed bean. no filtering required. no special navigation rules required. if want catch it, can caught. without @applicationexception, won't (because wrapped).
info found here (among other places):
http://docs.oracle.com/javaee/5/api/javax/ejb/applicationexception.html
http://openejb.apache.org/examples-trunk/applicationexception/
how use custom exception in session beans?
anyway works. wished figured out right search terms on google sooner.
Comments
Post a Comment