3

简短:(Portlet-)Container 吞下支持 bean 中 @PostConstruct 方法抛出的异常。

这种行为是故意的,是错误还是容器特定?

Long:我在 WebSphere Portal 7 上运行一个 portlet,我在 PhaseListener 中强制构建托管 bean,以便当系统在 Bean 构建/构建后遇到不可恢复的问题时,它可以将用户发送回起始页面。

我正在使用以下代码来“强制”构造:

@SuppressWarnings("unchecked")
public static <T> T getManagedBean(final String beanName)
{
    final FacesContext context = getFacesContext();
    return (T)context.getApplication().evaluateExpressionGet(context, "#{" + beanName + "}", Object.class);
}

我测试了从 @PostConstruct 方法抛出 RuntimeException

@PostConstruct
public void initialize()
{
    throw new RuntimeException("test");
}

堆栈跟踪最终出现在 RAD(Eclipse) 日志中:

com.ibm.ws.webcontainer.annotation.WASAnnotationHelper doInvoke unable to invoke method --> [initialize] on class --> [foo.bar.UpdateAddress]
                             java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:611)
at com.ibm.ws.webcontainer.annotation.WASAnnotationHelper.doInvokeSingle(WASAnnotationHelper.java:432)
at com.ibm.ws.webcontainer.annotation.WASAnnotationHelper.doInvokeChain(WASAnnotationHelper.java:400)
at com.ibm.ws.webcontainer.annotation.WASAnnotationHelper.doPostConstruct(WASAnnotationHelper.java:220)
at com.sun.faces.vendor.WebSphereInjectionProvider.invokePostConstruct(WebSphereInjectionProvider.java:86)
at com.sun.faces.mgbean.BeanBuilder.invokePostConstruct(BeanBuilder.java:225)
...
Caused by: java.lang.RuntimeException: test
    at foo.bar.UpdateAddress.initialize(UpdateAddress.java:119)
    ... 121 more

但是在我的 PhaseListener 中没有异常可以捕获,并且在 @PostConstruct 期间它会愉快地继续,而不会意识到异常。

这种行为是故意的,是错误还是容器特定?

看起来至少 JBoss 有类似的处理方式:http: //www.coderanch.com/t/499013/JSF/java/PostConstruct-exception-handling

4

1 回答 1

3

根据 Servlet 3.0 规范的第 15.5.9 节:

所有支持依赖注入的类都必须支持 @PostConstruct 注解,并且即使该类不请求注入任何资源,也必须调用该注解。如果方法抛出未经检查的异常,则不得将类投入使用,并且不能调用该实例上的任何方法。

如果您看到不同的行为,那么这看起来像是产品缺陷。如果 servlet 没有投入使用但异常被吞下,这听起来像是一个可服务性缺陷。无论哪种情况,我都建议与 IBM 建立 PMR。请注意,您的服务条款不太可能允许反编译 WebSphere Application Server 类,即使是出于调试目的。

于 2012-06-25T13:53:18.977 回答