FacesMessage не отображается в p:messages, когда пользователь отменяет загрузку файла

Когда я добавляю FacesMessage внутрь блока catch try-catch, он не отображается в компоненте p:messages. Если я добавлю FacesMessage в другое место, он отобразится. Почему?

Добавление FacesMessage:

try {
    ...
} catch (ServiceException | IOException e) {
    LOG.error("Failed to load content for download", e);
    MessageUtils.addErrorMessage(msgs, "msg.error.general", (Object[]) null);
}


public static void addErrorMessage(final MessagesProxy msgs, final String key, final Object... params)
{
    final FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, msgs.getText(key, params), null);
    final FacesContext fc = FacesContext.getCurrentInstance();
    fc.addMessage(null, msg);
    fc.validationFailed();
}

msgs — это доступ к пакету ресурсов.

Вот p:messages с autoUpdate=true:

<p:messages id="mainMessagesId" autoUpdate="true" />

Предыстория: пользовательский интерфейс обеспечивает загрузку файлов, которые обрабатываются в компоненте поддержки. Если пользователь выбирает большой файл и нажимает кнопку «Отмена» в диалоговом окне «Сохранить как» браузера, возникает исключение:

15:29:13,599 ERROR [xxx.web.bl.ContentBL] (http-/127.0.0.1:9090-1) Failed to load content for download: ClientAbortException:  java.net.SocketException: Connection reset by peer: socket write error
at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:403) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:450) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:351) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:426) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:415) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:89) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
at org.omnifaces.servlet.GzipHttpServletResponse$GzipThresholdOutputStream.write(GzipHttpServletResponse.java:204) [omnifaces-1.8.1.jar:1.8.1-20140603]
at org.omnifaces.io.ResettableBufferedOutputStream.write(ResettableBufferedOutputStream.java:77) [omnifaces-1.8.1.jar:1.8.1-20140603]
at org.omnifaces.io.ResettableBufferedOutputStream.write(ResettableBufferedOutputStream.java:56) [omnifaces-1.8.1.jar:1.8.1-20140603]
at org.omnifaces.servlet.HttpServletResponseOutputWrapper$1.write(HttpServletResponseOutputWrapper.java:92) [omnifaces-1.8.1.jar:1.8.1-20140603]
at java.io.OutputStream.write(OutputStream.java:116) [rt.jar:1.7.0_75]
at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1793) [commons-io-2.4.jar:2.4]
at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1769) [commons-io-2.4.jar:2.4]
at org.apache.commons.io.IOUtils.copy(IOUtils.java:1744) [commons-io-2.4.jar:2.4]
at xxx.web.bl.ContentBL.downloadContent(ContentBL.java:309) [classes:]
at xxx.web.bl.ContentBL$Proxy$_$$_WeldClientProxy.downloadContent(ContentBL$Proxy$_$$_WeldClientProxy.java) [classes:]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_75]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [rt.jar:1.7.0_75]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.7.0_75]
at java.lang.reflect.Method.invoke(Method.java:606) [rt.jar:1.7.0_75]
at javax.el.BeanELResolver.invokeMethod(BeanELResolver.java:735) [jboss-el-api_2.2_spec-1.0.2.Final-redhat-1.jar:1.0.2.Final-redhat-1]
at javax.el.BeanELResolver.invoke(BeanELResolver.java:467) [jboss-el-api_2.2_spec-1.0.2.Final-redhat-1.jar:1.0.2.Final-redhat-1]
at javax.el.CompositeELResolver.invoke(CompositeELResolver.java:246) [jboss-el-api_2.2_spec-1.0.2.Final-redhat-1.jar:1.0.2.Final-redhat-1]
at de.odysseus.el.tree.impl.ast.AstMethod.eval(AstMethod.java:91) [juel-impl-2.2.7.jar:2.2.7]
at de.odysseus.el.tree.impl.ast.AstMethod.invoke(AstMethod.java:104) [juel-impl-2.2.7.jar:2.2.7]
at de.odysseus.el.tree.impl.ast.AstEval.invoke(AstEval.java:71) [juel-impl-2.2.7.jar:2.2.7]
at de.odysseus.el.TreeMethodExpression.invoke(TreeMethodExpression.java:132) [juel-impl-2.2.7.jar:2.2.7]
at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40) [weld-core-1.1.16.Final-redhat-1.jar:1.1.16.Final-redhat-1]
at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50) [weld-core-1.1.16.Final-redhat-1.jar:1.1.16.Final-redhat-1]
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105) [jsf-impl-2.2.11.jar:2.2.11]
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87) [jsf-api-2.2.11.jar:2.2]
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102) [jsf-impl-2.2.11.jar:2.2.11]
at org.apache.myfaces.extensions.cdi.jsf.impl.security.SecurityViolationAwareActionListener.processAction(SecurityViolationAwareActionListener.java:56) [myfaces-extcdi-jsf20-module-impl-1.0.5.jar:1.0.5]
at org.apache.myfaces.extensions.cdi.jsf.impl.config.view.ViewControllerActionListener.processAction(ViewControllerActionListener.java:68) [myfaces-extcdi-jsf20-module-impl-1.0.5.jar:1.0.5]
at org.apache.myfaces.extensions.cdi.jsf.impl.listener.action.CodiActionListener.processAction(CodiActionListener.java:58) [myfaces-extcdi-jsf20-module-impl-1.0.5.jar:1.0.5]
at org.omnifaces.eventlistener.ResetInputAjaxActionListener.processAction(ResetInputAjaxActionListener.java:197) [omnifaces-1.8.1.jar:1.8.1-20140603]
at javax.faces.component.UICommand.broadcast(UICommand.java:315) [jsf-api-2.2.11.jar:2.2]

А то p:messages ничего не показывает. Я использую простые лица 5.2.6 и JSF 2.2.11.

С уважением Оливер


person opfau    schedule 18.06.2015    source источник


Ответы (1)


Большинство современных браузеров уже с готовностью загружают файл в фоновом режиме, даже если конечный пользователь еще не решил, сохранить ли файл в указанном месте или отменить загрузку файла. Отмена, очевидно, прервет текущий текущий запрос на загрузку. В случае, если файл загружается быстрее, чем конечный пользователь решит отменить его, он остается полностью незамеченным сервером, и браузер молча удалит его с (временного) диска вместо перемещения/переименования.

Этот вид исключений не может обрабатываться на стороне сервера в форме отображения сообщения конечному пользователю по той простой причине, что больше нет средств запроса/ответа. Клиент прервал запрос/ответ. Нигде нет ответа, чтобы написать сообщение. Лучшим вариантом будет push-соединение (например, веб-сокеты через PrimeFaces <p:socket>).

Просто отпустите исключение. У клиента все в руках. При необходимости отключите ведение журнала конкретно ClientAbortException, чтобы он не беспокоил вас в журналах сервера.

Смотрите также:


Не связано с конкретной проблемой, судя по трассировке стека, вы используете OmniFaces. Если вы еще этого не знали, у него есть Messages служебный класс, спасающий вас от этого MessageUtils шаблонный.

person BalusC    schedule 18.06.2015