问题描述
我维护一个具有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扩展异常{
// ..
}
总结:
-
RuntimeException
从事务EJB方法抛出将执行完全回滚,但异常将被包裹在EJBException
。 -
RuntimeException
与事务EJB方法中的@ApplicationException
将仅在rollback = true
被明确设置时执行完全回滚。 >
-
事务EJB方法中的异常
将不会执行完全回滚。 -
异常
与事件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:
RuntimeException
thrown from transactional EJB method will perform full rollback, but exception will be wrapped inEJBException
.RuntimeException
with@ApplicationException
from transactional EJB method will only perform full rollback whenrollback=true
is explicitly set.Exception
from transactional EJB method will not perform full rollback.Exception
with@ApplicationException
from transactional EJB method will only perform full rollback whenrollback=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前端方法中处理服务层异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!