java ee - Letting the presentation layer (JSF) handle business exceptions from service layer (EJB) -
the ejb method (using cmt) updates entity supplied :
@override @suppresswarnings("unchecked") public boolean update(entity entity) throws optimisticlockexception { // code merge entity. return true; } this throw javax.persistence.optimisticlockexception, if concurrent update detected handled precisely caller (a managed bean).
public void onrowedit(roweditevent event) { try { service.update((entity) event.getobject()) } catch(optimisticlockexception e) { // add user-friendly faces message. } } but doing makes additional dependency javax.persistence api on presentation layer compulsory design smell leading tight-coupling.
in exception should wrapped tight-coupling issue can omitted in entirely? or there standard way handle exception in turn not cause service layer dependencies enforced on presentation layer?
by way, found clumsy catch exception in ejb (on service layer itself) , return flag value client (jsf).
create custom service layer specific runtime exception annotated @applicationexception rollback=true.
@applicationexception(rollback=true) public abstract class serviceexception extends runtimeexception {} create concrete subclasses general business exceptions, such constraint violation, required entity, , of course optimistic lock.
public class duplicateentityexception extends serviceexception {} public class entitynotfoundexception extends serviceexception {} public class entityalreadymodifiedexception extends serviceexception {} some of them can thrown directly.
public void register(user user) { if (findbyemail(user.getemail()) != null) { throw new duplicateentityexception(); } // ... } public void addtoorder(orderitem item, long orderid) { order order = orderservice.getbyid(orderid); if (order == null) { throw new entitynotfoundexception(); } // ... } some of them need global interceptor.
@interceptor public class exceptioninterceptor implements serializable { @aroundinvoke public object handle(invocationcontext context) throws exception { try { return context.proceed(); } catch (javax.persistence.entitynotfoundexception e) { // can thrown query#getsingleresult(). throw new entitynotfoundexception(e); } catch (optimisticlockexception e) { throw new entityalreadymodifiedexception(e); } } } which registered default interceptor (on ejbs) below in ejb-jar.xml.
<interceptors> <interceptor> <interceptor-class>com.example.service.exceptioninterceptor</interceptor-class> </interceptor> </interceptors> <assembly-descriptor> <interceptor-binding> <ejb-name>*</ejb-name> <interceptor-class>com.example.service.exceptioninterceptor</interceptor-class> </interceptor-binding> </assembly-descriptor> as general hint, in jsf can have global exception handler adds faces message. when starting this kickoff example, in yourexceptionhandler#handle() method:
if (exception instanceof entityalreadymodifiedexception) { // unwrap if necessary. // add fatal faces message , return. } else { // continue usual. }
Comments
Post a Comment