简体   繁体   English

@PostConstruct中抛出的异常会导致JSF 2.1中出现IllegalStateException

[英]Exception thrown in @PostConstruct causes IllegalStateException in JSF 2.1

I have an init method on my @ViewScoped mananged bean. 我的@ViewScoped mananged bean上有一个init方法。 In the post construct i load data from the db. 在post构造中,我从db加载数据。 I have a custom ExceptionHandlerWrapper to catch all excptions and send to an error pages. 我有一个自定义ExceptionHandlerWrapper来捕获所有的排除并发送到错误页面。 However when @PostConstuct throws an exception i recieve an IllegalStateException and am not redirected to the error page. 但是当@PostConstuct抛出异常时,我收到IllegalStateException并且没有重定向到错误页面。 I have tried many combinations..... 我尝试了很多组合......

Ive tried this inside my ExcpetionHandler 我在我的ExcpetionHandler中尝试过这个

externalContext.getRequestMap().put(ERROR_BEAN_ID, ERROR_TEXT);
externalContext.dispatch(ERROR_PAGE);
fc.responseComplete();

This line below is what i originally had. 这一行是我原来的。 It also doent work 它也很有用

externalContext.getFlash().put(ERROR_BEAN_ID, ERROR_TEXT);
nav.handleNavigation(fc, null, ERROR_PAGE);
fc.renderResponse();

These all cause IllegalStateExceptions. 这些都会导致IllegalStateExceptions。 I also called redirect with the same result. 我也称为重定向具有相同的结果。

Can you globally catch errors thrown from @PostConstruct? 你可以全局捕获从@PostConstruct抛出的错误吗?

These all cause IllegalStateExceptions. 这些都会导致IllegalStateExceptions。

With the message "Response already committed", I assume? 有了消息“响应已经提交”,我假设? Well, that's a point of no return. 嗯,这是一个不归路的点。 A part of the response has already been sent to the client (the webbrowser). 响应的一部分已经发送到客户端(webbrowser)。 It's not possible to take the already sent bytes back. 无法取回已发送的字节。 The server will end up with this exception in the logs and the client will end up with a halfbaked response. 服务器最终会在日志中出现此异常,客户端将以半熟响应结束。

What can you do? 你能做什么?

Most straightforward way would be to enlarge the response buffer size to the size of the largest page. 最直接的方法是将响应缓冲区大小扩大到最大页面的大小。 For example, 64KB: 例如,64KB:

<context-param>
    <param-name>javax.faces.FACELETS_BUFFER_SIZE</param-name>
    <param-value>65536</param-value>
</context-param>

It defaults to ~2KB depending on the server configuration. 默认值为~2KB,具体取决于服务器配置。 You only need to keep in mind that this may be memory hogging when your server has to process relatively a lot of requests/responses. 您只需要记住,当您的服务器必须处理相对大量的请求/响应时,这可能会占用内存。 Profile and measure properly. 正确地描述和测量。

Another way is to reference the bean before the response is to be rendered/committed so that it's (post)construction is triggered before that point. 另一种方法是在呈现/提交响应之前引用bean 以便在该点之前触发它(post)构造。 Perhaps the bean in question is referenced for the first time at the very bottom of the view, long beyond the ~2KB response size border. 也许有问题的bean第一次被引用到视图的最底部,远远超过~2KB的响应大小边界。 You could take over the job of @PostConstruct with a <f:event type="preRenderView"> somewhere in the top of the view. 您可以在视图顶部的某处使用<f:event type="preRenderView">接管@PostConstruct的工作。 Eg 例如

<f:event type="preRenderView" listener="#{bean.init}" />

with

public void init() {
    if (!FacesContext.getCurrentInstance().isPostback()) {
        // Do here your original @PostConstruct job.
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM