В моем приложении JSF 2.0 есть 2 экрана.Экран 1 выполняет поиск студентов и перечисляет студентов в таблице.Имя ученика в таблице результатов - это ссылка на страницу сведений о ученике (экран 2).
Мой управляемый компонент:
@SessionScoped
public class TestController {
private Student studentOnUI; // Student being viewed on the UI
// synchronized public getters and setters
public String viewStudentAction(String studentId) {
this.studentOnUI = getStudentFromDB( studentId );
return "studentDetailedPage";
}
public synchronized String clearSearchAction() {
this.studentOnUI = null;
return "studentSearchPage";
}
screen 1 фрагмент xhtml
<!-- search fields -->
<h:commandButton
value="Clear Search"
action="#{testController.clearSearchAction()}"/>
<!-- Search button -->
<!-- search results table -->
Screen 2 фрагмент xhtml
<h:outputText value="#{testController.studentOnUI.name}" />
<h:dataTable
value="#{testController.studentOnUI.subjects}"
var="subject">
<h:outputText value="#{subject.score}"/>
</h:dataTable>
У меня возникла следующая проблема:
- После запуска поиска пользователь нажимает на имя студента (чтобы перейти к экрану 2)
- Когда выполняется фаза ответа рендеринга экрана 2 (который содержит ссылки на ELtestController.studentOnUI), он нажимает кнопку очистки (не дожидаясь завершения первого запроса).Теперь поток, обрабатывающий запрос очистки, устанавливает для testController.studentOnUI значение null, и первый поток, находящийся в фазе ответа рендеринга, генерирует исключение NullPointerException при оценке
{testController.studentOnUI. *}.
Хотя управляемый компонент обрабатывает синхронизацию (правильно?), Он не решает проблему параллелизма, потому что может произойти следующее
- Поток 1 (обработка запроса для перехода к экрану 2) - оценивает # {testController.studentOnUI.name} и счастливо отображает значение.И затем выходит из синхронизированного метода testController.getStudentOnUI ().Таким образом, поток 1 больше не имеет блокировки на экземпляре контроллера (в области сеанса).происходит переключение контекста.
- Поток 2 (обработка запроса для очистки результатов поиска) - делает testController.studentOnUI = null в clearSearchAction ().происходит переключение контекста.
- Поток 1 - оценивает следующий EL на странице (# {testController.studentOnUI.subjects}) и выдает исключение NullPointerException (поскольку testController.studentOnUI теперь имеет значение null).
Цените любые указания на то, что я делаю неправильно с этим подходом, или если здесь требуется другой подход.