Почему реализация JSF вызвала response.getWriter() во время загрузки / выгрузки файла?

#jakarta-ee #servlets #download #jsf-2.2 #ajax4jsf

#джакарта-ee #сервлеты #Скачать #jsf-2.2 #ajax4jsf

Вопрос:

Это мой первый вопрос по SO.

Я хотел бы создать файл отчета сразу после импорта другого файла с некоторыми бизнес-элементами.

После выбора import file with h:inputFile я запускаю действие компонента с h:commandButton помощью и вложенный a4j:ajax :

 FacesContext facesContext = FacesContext.getCurrentInstance();

        try {
            HttpServletRequest req = (HttpServletRequest) facesContext.getExternalContext().getRequest();
            HttpServletResponse res = (HttpServletResponse) facesContext.getExternalContext().getResponse();
            byte[] byteSourceExcelFile = IOUtils.toByteArray(sourceExcelFile.getInputStream());
            req.setAttribute("excel", DatatypeConverter.printBase64Binary(byteSourceExcelFile));

            RequestDispatcher dispatcher = req.getRequestDispatcher("importReport.jsf");  
            dispatcher.forward(req, res);
        } catch (IOException e) {
            FacesUtils.createErrorMessage(e.getMessage(), null, msgs);
        } catch (ServletException e) {
            FacesUtils.createErrorMessage(e.getMessage(), null, msgs);
        } finally {
            facesContext.responseComplete();
            fileClear();    
        }
  

Запрос перенаправляется на сервлет, где импорт работает хорошо, но когда я пытаюсь получить объект, необходимый для вывода двоичных данных:

 ServletOutputStream outputStream = response.getOutputStream(); 
  

Я получаю сообщение об ошибке:

  org.apache.myfaces.view.facelets.el.ContextAwareELException: javax.el.ELException: java.lang.IllegalStateException: SRVE0209E: Writer already obtained
  

Я отладил код сервлета и заметил, что поле _gotWriter имеет значение true в объекте ответа. Это указывает на то, что:

 PrintWriter outputStream = response.getWriter();
  

. Ни один из моих фильтров этого не сделал. Кроме того, другие сервлеты, которые используются для получения данных, работают нормально.

Использование MyFaces 2.2.3 в качестве общей библиотеки в WebSphere 8.5.5.

Механизм, описанный выше, работает с реализацией Websphere 7 JSF (Sun-RI 1.2) и компонентом Richfaces (3.3.3) rich:FileUpload.

  1. Каковы возможные причины описанного состояния объекта ответа?
  2. Есть ли какой-нибудь способ заменить PrintWriter object на ServletOutputStream object ?

Я надеюсь, что это подходящий способ задать вопрос. Я буду признателен за любые предложения.

Комментарии:

1. Ваш код не вызывался response.getWriter() , но фреймворк реализации JSF вызвал.

2. @Isaac Почему это происходит в данном конкретном случае (а не в других)?

3. если бы я знал, я бы написал это как ответ… но ошибка, которую вы получаете, подразумевает, что что- то вызывается response.getWriter() , поэтому, если это не ваш код, тогда это должна быть реализация JSF. Я не эксперт по JSF, поэтому не могу комментировать дальше, извините.

Ответ №1:

Все дело a4j:ajax во вложенности h:commandButton . Оказывается, это было причиной вызова response.getWriter() в середине обработки запроса (я до сих пор не знаю, где и почему).

 <h:commandButton action="#{listBean['processImport']}" > 
    <a4j:ajax  oncomplete="js();" execute="fileUploadId" render="fileUploadId"/>
</h:commandButton>
  

Я удалил a4j:ajax , и загрузка файла работает так, как и предполагалось.

 <h:commandButton action="#{listBean['processImport']}" onclick="js();"> 
</h:commandButton>
  

Теперь мне нужно выяснить, как обновить желаемые элементы на странице jsf. Но это другая история…

Приложение: JSF 1.2

Стоит упомянуть, что перед переходом с WAS-7 (Sun-RI 1.2) на WAS-8.5.5 (MyFaces 2.2.3) вышеупомянутый механизм работает с комбинацией:

 <h:commandButton action="#{listBean['processImport']}" > 
    <a4j:support  oncomplete="js();" reRender="fileUploadId"/>
</h:commandButton>
  

но не сработало с:

 <a4j:commandButton action="#{listBean['processImport']}" oncomplete="js();" reRender="fileUploadId" />
  

РЕДАКТИРОВАТЬ: После последнего обновления безопасности IE 14-037 (KB2962872) файл принимается браузером, но больше не может быть открыт или сохранен.

Ответ №2:

response.getOutputStream() и response.getWriter() не должны вызываться одновременно. Вам нужно проверить, есть ли какие-либо выходные данные в importReport.jsf. Если да, удалите их или используйте отдельный класс для обработки логики импорта.

Комментарии:

1. Я бы ожидал, что это также сломается под WAS 7.0. В OP говорится, что код работает на WAS 7.