Letting the presentation layer (JSF) handle business exceptions from service layer (EJB)

后端 未结 1 1733
無奈伤痛
無奈伤痛 2020-12-01 22:54

The EJB method (using CMT) that updates an entity supplied :

@Override
@SuppressWarnings(\"unchecked\")
public boolean update(Entity entity) throws Optimisti         


        
相关标签:
1条回答
  • 2020-12-01 23:13

    Create a custom service layer specific runtime exception which is annotated with @ApplicationException with rollback=true.

    @ApplicationException(rollback=true)
    public abstract class ServiceException extends RuntimeException {}
    

    Create some concrete subclasses for general business exceptions, such as constraint violation, required entity, and of course optimistic lock.

    public class DuplicateEntityException extends ServiceException {}
    
    public class EntityNotFoundException extends ServiceException {}
    
    public class EntityAlreadyModifiedException extends ServiceException {}
    

    Some of them can be 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 a 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 be thrown by Query#getSingleResult().
                throw new EntityNotFoundException(e);
            }
            catch (OptimisticLockException e) {
                throw new EntityAlreadyModifiedException(e);
            }
        }
    
    }
    

    Which is registered as default interceptor (on all EJBs) as 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 a general hint, in JSF you can also have a global exception handler which just adds a faces message. When starting with this kickoff example, you could do something like this in YourExceptionHandler#handle() method:

    if (exception instanceof EntityAlreadyModifiedException) { // Unwrap if necessary.
        // Add FATAL faces message and return.
    }
    else {
        // Continue as usual.
    }
    
    0 讨论(0)
提交回复
热议问题