Как повторно использовать Primefaces с данными на разных вкладках браузера? - PullRequest
0 голосов
/ 04 января 2019

У моего приложения есть параметр запроса в URL, который используется для отображения различных данных с использованием одного и того же xhtml (всего динамического содержимого) в таблице данных.

Область действия bean-объекта - это область действия сеанса, таблица данных отображает все данные и имеет множество элементов ввода, которые открывают различные диалоговые окна.

Если я открою другую вкладку браузера и отправлю другой параметр запроса, таблица данных будет отображаться идеально, однако если я вернусь к первой вкладке, все командные ссылки не будут вызывать действия, и все приложение начнет работать очень хаотично.

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

<f:metadata>
  <f:viewParam name="param" value="#{moduleBean.param}"/>
  <f:viewAction action="#{moduleBean.setup}" />
</f:metadata>

<c:set var="module" value="#{moduleBean.param}" />

<p:dataTable id="#{module}-dataTable" value="#{moduleBean.model[module]}" var="data">

  <p:commandLink action="#{moduleBean.openModuleDetails}" update=":#{module}-searchDialog" oncomplete="PF('#{module}-searchWidget').show();">
    <f:param name="module" value="#{module}" />
    <f:param name="dataRow" value="#{data.dbKey}" />
  </p:commandLink>
</p:dataTable>


@Named
@javax.faces.view.ViewScoped
public class ModuleBean implements Serializable {

   private String param;

   public void setup() throws IOException {
      this.model.put(this.param, new LazyDataModel(this.param));
   }

    public Map<String, LazyDataModel> getModel() {
        return model;
    }
}

Это создает все ожидаемые HTML со всеми правильными идентификаторами на каждой вкладке, однако JSF все еще не обрабатывает действие внутри командной ссылки. Само собой разумеется, если я придерживаюсь только одной вкладки браузера, все работает отлично.

Иногда он начинает работать после двойного щелчка по ссылке, но переход назад и вперед между вкладками браузера в конечном итоге всегда приводит к сбою.

Добавление прослушивателя действий к командной ссылке также не исправило это.

Любые предложения о том, как заставить JSF обрабатывать один и тот же объект данных как разные сущности на одной странице, но с разными параметрами?

1 Ответ

0 голосов
/ 04 января 2019

Не зная больше о базовом бине - если вы поместите свой moduleBean в @SessionScoped, это будет ожидаемым поведением. Сеанс (и сессионные компоненты) разделяются между вкладками браузера. Поэтому нельзя полагаться на базовые значения из двух разных вкладок.

Попробуйте изменить значение на @RequestScoped/@ViewScoped для базовых значений данных таблицы.

Вот полное решение, которое работает, обратите внимание, что оно использует PrimeFaces 6.2, Apache Commons и Lombok;

@Data
@Named
@ViewScoped
public class TableTestBackingBean implements Serializable {
    private int param;

    @Inject
    private PersonsBean personsBean;

    public void onClicked() {
        System.out.println("Clicked fine!");
    }

    public List<Person> getPersons() {
        return personsBean.getPersons()[param];
    }
}
@Data
@ApplicationScoped
public class PersonsBean {
    @Data
    @AllArgsConstructor
    public class Person {
        private String firstName;
        private String lastName;
        private int age;
    }

    private List<Person> persons[];

    @PostConstruct void init() {
        persons = new List[4];

        for (int j = 0; j < 4; j++) {
            persons[j] = new ArrayList<>();

            for (int i = 0; i < 30; i++) {
                final String firstName =
                    RandomStringUtils.randomAlphanumeric(10);
                final String lastName = 
                    RandomStringUtils.randomAlphanumeric(10);
                final int age = RandomUtils.nextInt(0, 120);

                persons[j].add(new Person(firstName, lastName, age));
            }
        }
    }   
 }
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui" xmlns:f="http://java.sun.com/jsf/core">
    <f:metadata>
        <f:viewParam name="param" value="#{tableTestBackingBean.param}"/>
    </f:metadata>
    <h:head>
            <title>Test</title>
    </h:head>
    <h:body>
        <p:dataTable value="#{tableTestBackingBean.persons}" var="t">
            <p:column headerText="First Name"><h:outputText value="#{t.firstName}" /></p:column>
            <p:column headerText="Last Name"><h:outputText value="#{t.lastName}" /></p:column>
            <p:column headerText="Age"><h:outputText value="#{t.age}" /></p:column>
        </p:dataTable>
        <h:form>
            <p:commandButton action="#{tableTestBackingBean.onClicked}" value="Click Me!" />
        </h:form>
    </h:body>
</html>

При этом для данных таблицы используется бин области действия приложения, что делает его полностью статичным. Это работает без проблем, и таблица отображает данные по-разному в зависимости от параметра, переданного в param.

...