Почему представление jsf не обновляется после загрузки из базы данных новых данных в компоненте поддержки? - PullRequest
4 голосов
/ 09 апреля 2009

К сожалению, я работаю с jsf, и у меня возникла проблема. У меня есть страница jsf, которая отображает таблицу с некоторыми данными, используя компонент <h:dataTable>. В каждой строке этой таблицы есть <h:commandLink> с действием Удалить, чтобы удалить элемент из этой строки. Когда я выполняю это действие, метод в компоненте поддержки корректно вызывается, ArrayList , содержащий элементы таблицы, корректно обновляется, и метод навигации для возврата на ту же страницу, где находится таблица, правильно выполнен.

Но при перезагрузке страницы таблица не обновляется . Я вижу те же элементы, которые были в таблице перед действием удаления.

Если я снова перезагружу страницу, теперь таблица обновится.

Похоже, что представление визуализируется до того, как компонент поддержки завершит свои обновления.

Как я могу заставить рендеринг представления только после того, как компонент поддержки завершил свои обновления?

Вот код:

CommandLink на странице jsf внутри таблицы данных:

<h:column>
<f:facet name="header">
    <h:outputText value="Rimuovi" />
</f:facet>
<h:commandLink action="#{servicesListBean.removeServizio}" title="Rimuovi questo servizio" onclick="if(!confirm('Vuoi davvero rimuovere questo servizio?')) return false">
    <h:outputText value="Rimuovi" />
</h:commandLink>
</h:column>

А вот метод в бэк-бине:

public String removeServizio() {
        this.servizioToRemove = (Servizio) getDataTable().getRowData();
        try {
        ServiziDAO.removeServizio(this.servizioToRemove.getId());
        } catch (Exception e) {
            // ...
        }

        return userSessionBean.goToElencoServizi(); 
    }

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

Надеюсь, я был достаточно ясен. Спасибо всем заранее.


ОБНОВЛЕНИЕ ЭТОГО ВОПРОСА, КОТОРЫЕ ИЗМЕНЯЮТ ВСЕ

Спасибо всем. Как сказал Макдауэлл, проблема была не во время визуализации представления, и проблема вообще не была связана с JSF.

Случилось так, что когда я удалял элемент из БД, я не удалял строку, я просто устанавливал конечную дату для элемента. Это правильный способ сделать это в моем приложении, но в то время как в запросе, который установил конечную дату для элемента, я потратил время, используя System.currentTimiMillis(), в запросе, который перезагрузил обновленный список, я использовал sysdate из Сервер Oracle.

Между этими двумя датами есть доли секунды разницы, и поэтому я мог видеть обновленный список сразу после перезагрузки страницы: потому что прошла одна или две секунды!

Может быть, эта проблема может быть полезна кому-то еще.

Ответы [ 2 ]

4 голосов
/ 09 апреля 2009

Похоже, вид перед этим передается боб завершил свои обновления.

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

Я предполагаю, но это похоже на проблему логики в вашем бине. Ваш servicesListBean поддерживает состояние? То есть:

  1. HTTP POST
  2. Фаза жизненного цикла RESTORE VIEW приводит к созданию servicesListBean в области запроса (каждая фаза жизненного цикла должна повторяться для каждой строки)
  3. servicesListBean извлекает строки из постоянного хранилища, и они кэшируются в состоянии компонента
  4. Когда мы попадаем в фазу INVOKE APPLICATION , removeServizio () удаляет целевую строку из хранилища постоянных данных, но ничего не делает с состоянием кэшированного компонента
  5. Фаза RENDER RESPONSE отображает устаревшее состояние кэшированного компонента
  6. Если вы обновите сейчас, компонент будет воссоздан с новыми кэшированными значениями, и вы увидите правильное состояние

Этот компонент поддержки воссоздает проблему:

public class DeleteFromRowBean {

  private ListDataModel dataModel;

  public DataModel getList() {
    if (dataModel == null) {
      List<RowBean> list = PersistenceStore.fetch();
      dataModel = new ListDataModel(list);
    }
    return dataModel;
  }

  public String deleteCurrentRow() {
    if (dataModel == null) {
      throw new IllegalStateException();
    }
    RowBean row = (RowBean) dataModel.getRowData();
    PersistenceStore.delete(row.getId());
    return null; // no navigation required
  }

}

Изменение списка во время итерации таблицы данных не очень хорошая идея (вы получите одновременные исключения модификации). Самое простое решение в моем примере bean-компонента - просто освободить ссылку на кэшированные данные. Таблица данных уже имеет ссылку на это во время итерации в фазе INVOKE APPLICATION ; при запуске RENDER RESPONSE таблица данных снова вызовет getList () , вызывая выборку нового состояния из постоянного хранилища.

public class DeleteFromRowBean {

  private ListDataModel dataModel;

  public DataModel getList() {
    if (dataModel == null) {
      List<RowBean> list = PersistenceStore.fetch();
      dataModel = new ListDataModel(list);
    }
    return dataModel;
  }

  public String deleteCurrentRow() {
    if (dataModel == null) {
      throw new IllegalStateException();
    }
    RowBean row = (RowBean) dataModel.getRowData();
    PersistenceStore.delete(row.getId());
    // flush cached data
    dataModel = null;
    return null; // no navigation required
  }

}
1 голос
/ 09 апреля 2009

Если вы не будете явно перенаправлять на «другую» страницу (даже если это та же страница), вы получите старые данные. Это особенность. Попробуйте что-то вроде:

public String removeServizio() {
    .
    .
    .
    userSessionBean.goToElencoServizi(); // if this redirects to needed page
    return null;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...