Список выбора PrimeFaces с OmniFaces validateAll приводит к исключению NullPointerException

На самом деле мне нужны два ПраймФейс <p:pickList>, которые проверяются с помощью компонента OmniFaces' <o:validateAll>. Обратите внимание, что при проверке списка выбора с помощью <o:validateAll> есть проблема, которую можно решить с помощью описано в выпуске 488 в системе отслеживания проблем OmniFaces.

Итак, очень простой пример моего требования выглядит так:

<h:form id = "form1">
  <p:messages id = "messages">
    <p:autoUpdate/>
  </p:messages>

  <p:pickList id = "pick1" value = "#{dummy.dualListModel}"
              var = "item" itemLabel = "#{item}" itemValue = "#{item}">
    <p:ajax event = "transfer"/>
  </p:pickList>

  <p:pickList id = "pick2" value = "#{dummy.dualListModel2}"
              var = "item" itemLabel = "#{item}" itemValue = "#{item}">
    <p:ajax event = "transfer"/>
  </p:pickList>

  <o:validateAll id = "validPicks" components = "pick1 pick2"
                 message = "all values required!" />

  <h:commandButton id = "done" value = "Done" action = "#{dummy.action1}"/>
</h:form>

<h:form id = "theOtherForm">
  <h:commandButton id = "otherFormAction" value = "Action in other form"
                   action = "#{dummy.action2}"/>
</h:form>

Компонент поддержки дурачок просто предоставляет геттеры/сеттеры для двух свойств dualListModel и методов действий, которые ничего не делают.

Когда я запускаю этот код и оставляю хотя бы один список выбора пустым, отправка кнопки Done приводит к ошибке проверки, как исключение. Однако нажатие кнопки в другой форме после неудачной проверки приводит к NullPointerException в PickListRenderer. Вот трассировка стека:

Caused by:java.lang.NullPointerException
    at org.primefaces.component.picklist.PickListRenderer.encodeMarkup(PickListRenderer.java:92)
    at org.primefaces.component.picklist.PickListRenderer.encodeEnd(PickListRenderer.java:59)
    at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:920)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1863)
    at javax.faces.render.Renderer.encodeChildren(Renderer.java:176)
    at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:890)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:456)
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:134)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
    at org.omnifaces.viewhandler.OmniViewHandler.renderView(OmniViewHandler.java:119)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
    [...]

Я использую OmniFaces 2.7 и PrimeFaces 6.2.

Пожалуйста, обрати внимание, что я использую пользовательский рендерер для PickList, который переопределяет getConvertedValue(), как описано в связанной проблеме выше. Однако это никоим образом не меняет поведение средства визуализации, которое должно повлиять на эту ошибку. Это просто заставляет <o:validateAll> признать, что список выбора пуст.

Мне это кажется ошибкой, но я не уверен, ошибка ли это в OmniFaces или в PrimeFaces. У кого-нибудь есть идеи?

Обходной путь

В качестве обходного пути можно добавить атрибут required = "true" ко всем спискам выбора.

Обновлять

Та же проблема существует и с PrimeFaces 7.0 (только номера строк немного отличаются).

Кроме того, я создал еще один NPE с приведенным выше кодом и PrimeFaces 7.0, когда подсчитывал пустые списки выбора через «готово», а затем переносил элемент в один из списков выбора в целевой список.

Другое исключение возникает здесь:

Caused by:java.lang.NullPointerException
    at org.primefaces.component.picklist.PickList.validateValue(PickList.java:140)
    at javax.faces.component.UIInput.validate(UIInput.java:982)
    at org.primefaces.component.picklist.PickList.validate(PickList.java:181)
    at javax.faces.component.UIInput.executeValidate(UIInput.java:1248)
    at javax.faces.component.UIInput.processValidators(UIInput.java:712)
    at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:575)
    at com.sun.faces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:183)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1689)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
    at javax.faces.component.UIForm.visitTree(UIForm.java:371)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
    at com.sun.faces.context.PartialViewContextImpl.processComponents(PartialViewContextImpl.java:403)
    at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:266)
    at org.primefaces.context.PrimePartialViewContext.processPartial(PrimePartialViewContext.java:63)
    at javax.faces.context.PartialViewContextWrapper.processPartial(PartialViewContextWrapper.java:219)
    at org.omnifaces.context.OmniPartialViewContext.processPartial(OmniPartialViewContext.java:124)
    at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1193)
    at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76)

В соответствующий код значение oldModel, которое инициализируется через getValue(), равно null.

Я подожду, пока @balusC не вмешается, поскольку он обычно знает, где на самом деле находится эта ошибка. У меня есть ощущение, что это может быть связано с тем, как работает PickList.

Melloware 22.02.2019 13:08

Я бы добавил код, в котором вы переопределяете рендерер, поскольку он играет роль мог бы...

Kukeltje 22.02.2019 13:26

Код пользовательского средства визуализации доступен в связанной проблеме OmniFaces. Как уже упоминалось, он просто переопределяет getConvertedValue() и изменяет только одну строку, которая создает экземпляр DualListModel.

Martin Höller 22.02.2019 13:51
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
3
417
3

Ответы 3

Проблема подтверждена и опубликована на GitHub: https://github.com/primefaces/primefaces/issues/4756.

Я отправил исправление, которое, надеюсь, будет включено в PF 7.0.2 и PF 7.1.

https://github.com/primefaces/primefaces/pull/4759

текущее исправление ИМХО только маскирует настоящую причину, которая до сих пор неясна. NPE в PickListRenderer (из исходного вопроса) все еще существует. Воспроизведение было обновлено, и проблема на github была вновь открыта.

Martin Höller 29.04.2019 11:39

Как писал Меллоуэр, о проблеме сообщили как Выпуск PrimeFaces #4756. Оказалось, что проблема существует только с Mojarra (проверено с 2.2.17, 2.2.18, 2.2.19 и 2.3.9), а не с MyFaces. Итак, была создана еще одна проблема: Мохарра #4398.

Если в вашем списке выбора используется FacesConverter, обратите внимание, что входное значение не должно быть экранировано при сравнении для извлечения исходного объекта. На самом деле, если входная строка похожа на «Курица и яйцо», конвертер получает 'Chicken&amp;Egg' Пример:

      @Override
  public YourObject getAsObject(FacesContext facesContext, UIComponent uiComponent, String name)
  {
    PickList pickList = (PickList) uiComponent;
    DualListModel<YourObject> dualListModel = (DualListModel<YourObject>) pickList.getValue();
    List<YourObject> all = dualListModel.getSource();
    all.addAll(dualListModel.getTarget());

    return all.stream().filter(element ->
      String.valueOf(element.getName()).equals(HtmlUtils.htmlUnescape(name)))
      .findFirst().get();
  }

Другие вопросы по теме