本文介绍了在Java EE前端方法中处理服务层异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我维护一个具有JSF标签< f:event 的页面的Web应用程序。我重写了一个服务类中的方法来抛出一个业务异常。但是,当抛出业务异常时,它不会被托管在bean中,并且异常显示在页面上。似乎我的代码 try / catch 不起作用。



在XHTML中:

 < f:event listener =#{resourceBean.init(enrollment)}type =preRenderView/> 

托管Bean中的监听器方法:

  private boolean canCreateResource; 

public void init(注册注册){
(...)

try {
canCreateResource = resourceService.canCreateResource(enrollment);
} catch(BusinessException e){
canCreateResource = false;
}
}

服务类中的方法:

  public boolean canCreateResource(注册注册){
if(...){
if(authorizedService.isCoordinator(user,course )){
return true;
} else {
抛出新的BusinessException(未定义的业务规则);
}
}

return false;
}

从我在其他网站上阅读的内容,我想我必须实现一些JSF处理程序类。但是哪些和如何?






EDITED



OBS 1: BusinessException class extends RuntimeException class。



OBS 2 :创建属性 canCreateResource 来控制按钮的渲染。

解决方案

p>这是因为你投了一个。



当这样的 RuntimeException 没有用,那么EJB容器将它包装成 javax.ejb.EJBException 并重新抛出。这样做是因为运行时异常通常仅用于指示代码逻辑中的错误,即程序员的错误,而不是终端用户的错误。你知道, NullPointerException IllegalArgumentException IndexOutOfBoundsException NumberFormatException 和朋友。这允许EJB客户端对于这样的运行时异常有一个全部的要点,例如 catch(EJBException e){在服务层有一个错误或者我们如何使用它!如果你尝试过 catch(Exception e)并检查了实际的异常那么你会注意到。



相应地修改你的 BusinessException 类以添加该注释,然后被认为是真正的应用程序异常,而不是包裹在一个 EJBException 中:

  @ApplicationException(rollback = true)
public class BusinessException扩展RuntimeException {
// ...
}

请注意,如果您抛出一个非 RuntimeException ,那么您仍然需要保留注释,明确地 rollback = true ,因为默认情况下它不会执行回滚,而与$ code> RuntimeException 相反,没有注释

  @ApplicationException(rollback = true)
public class BusinessException扩展异常{
// ..
}

总结:


  1. RuntimeException 从事务EJB方法抛出将执行完全回滚,但异常将被包裹在 EJBException

  2. RuntimeException 与事务EJB方法中的 @ApplicationException 将仅在 rollback = true 被明确设置时执行完全回滚。 >
  3. 事务EJB方法中的异常将不会执行完全回滚。

  4. 异常与事件EJB方法中的 @ApplicationException 将仅在 rollback = true 时执行完全回滚明确设置。

请注意, @ApplicationException 继承于所有子类自定义异常,所以你不需要重复它们。最好是把它作为抽象类。另请参见下面相关问题的例子。



另见:






I maintain a web application that have a page with the JSF tag <f:event. I have rewrote a method in a service class for it to throw a business exception. However, when the business exception is thrown, it isn't caught in managed bean and the exception is showed on the page. Seems that my code try/catch doesn't work.

In XHTML:

<f:event listener="#{resourceBean.init(enrollment)}" type="preRenderView" />

Listener method in Managed Bean:

private boolean canCreateResource;

public void init(Enrollment enrollment) {
    (...)

    try {
        canCreateResource = resourceService.canCreateResource(enrollment);
    } catch (BusinessException e) {
        canCreateResource = false;
    }
}

Method in service class:

public boolean canCreateResource(Enrollment enrollment) {
    if (...) {
        if (mandateService.isCoordinator(user, course)) {
            return true;
        } else {
            throw new BusinessException("Undefined business rule.");
        }
    }

    return false;
}

From what I read on other sites, I suppose I have to implement some JSF's handler class. But which and how?


EDITED

OBS 1: The BusinessException class extends RuntimeException class.

OBS 2: The attribute canCreateResource was created to control the render of a button.

解决方案

It's because you threw a RuntimeException from an EJB.

When such RuntimeException is not annotated with @ApplicationException, then the EJB container will wrap it in an javax.ejb.EJBException and rethrow it. This is done so because runtime exceptions are usually only used to indicate bugs in code logic, i.e. programmer's mistakes and not enduser's mistakes. You know, NullPointerException, IllegalArgumentException, IndexOutOfBoundsException, NumberFormatException and friends. This allows the EJB client to have one catch-all point for such runtime exceptions, like catch (EJBException e) { There's a bug in the service layer or in the way how we are using it! }

If you had tried catch (Exception e) and inspected the actual exception, then you'd have noticed that.

Fix your BusinessException class accordingly to add that annotation, it will then be recognized as a real application exception and not be wrapped in an EJBException:

@ApplicationException(rollback=true)
public class BusinessException extends RuntimeException {
    // ...
}

Do note that in case you throw an non-RuntimeException, then you still need to keep the annotation on that, explicitly with rollback=true, because by default it wouldn't perform a rollback, on the contrary to a RuntimeException without the annotation.

@ApplicationException(rollback=true)
public class BusinessException extends Exception {
    // ...
}

Summarized:

  1. RuntimeException thrown from transactional EJB method will perform full rollback, but exception will be wrapped in EJBException.
  2. RuntimeException with @ApplicationException from transactional EJB method will only perform full rollback when rollback=true is explicitly set.
  3. Exception from transactional EJB method will not perform full rollback.
  4. Exception with @ApplicationException from transactional EJB method will only perform full rollback when rollback=true is explicitly set.

Note that @ApplicationException is inherited over all subclasses of the custom exception, so you don't need to repeat it over all of them. Best would be to have it as an abstract class. See also the examples in the related question linked below.

See also:

这篇关于在Java EE前端方法中处理服务层异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 09:19