加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

让表示层(JSF)处理来自服务层(EJB)的业务异常

发布时间:2020-12-15 04:28:41 所属栏目:Java 来源:网络整理
导读:更新提供的实体的EJB方法(使用CMT): @Override@SuppressWarnings("unchecked")public boolean update(Entity entity) throws OptimisticLockException { // Code to merge the entity. return true;} 如果检测到并发更新,则将抛出javax.persistence.Optimis
更新提供的实体的EJB方法(使用CMT):

@Override
@SuppressWarnings("unchecked")
public boolean update(Entity entity) throws OptimisticLockException {
    // Code to merge the entity.
    return true;
}

如果检测到并发更新,则将抛出javax.persistence.OptimisticLockException,该更新将由调用者(托管bean)精确处理.

public void onRowEdit(RowEditEvent event) {
    try {
        service.update((Entity) event.getObject())
    } catch(OptimisticLockException e) {
        // Add a user-friendly faces message.
    }
}

但这样做会对表示层上的javax.persistence API产生额外的依赖性,这是一种导致紧耦合的设计气味.

应该包装哪个例外,以便完全省略紧耦合问题?或者是否有一种标准方法来处理此异常,这反过来又不会导致在表示层上强制执行任何服务层依赖性?

顺便说一句,我发现在EJB中(在服务层本身上)捕获此异常然后向客户端(JSF)返回一个标志值是笨拙的.

解决方法

创建一个特定于自定义服务层的运行时异常,该异常使用带有rollback = true的 @ApplicationException进行批注.

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

为一般业务异常创建一些具体的子类,例如约束违规,必需实体,当然还有乐观锁.

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

其中一些可以直接抛出.

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();
    }

    // ...
}

其中一些需要全局拦截器.

@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);
        }
    }

}

在ejb-jar.xml中注册为默认拦截器(在所有EJB上),如下所示.

<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>

作为一般提示,在JSF中,您还可以拥有一个全局异常处理程序,它只添加一个faces消息.从this kickoff example开始,您可以在YourExceptionHandler#handle()方法中执行以下操作:

if (exception instanceof EntityAlreadyModifiedException) { // Unwrap if necessary.
    // Add FATAL faces message and return.
}
else {
    // Continue as usual.
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读