Когда форма обрабатывается в JSF, все ли это происходит в одном потоке?
Скажи, у меня есть этот кусок кода
<p:dataTable styleClass="scheduleTable" value="#{todaySchedule.hours}" var="hour">
<p:column headerText="Hour" styleClass="hourColumn" >
#{hour.time}
</p:column>
</p:dataTable>
и в классе под названием todaySchedule, есть метод
public List<Hour> getHours() {
final List<Hour> hours = IntStream.range(0, Hour.TIME.values().length)
.mapToObj($ -> new Hour()).collect(Collectors.toList());
for (int i = 0; i < 5; i++) {
hours.get(i).setHour(1);
}
return hours;
}
и вот класс час
public class Hour {
private int time;
public int getTime() {
return time;
}
public void setTime(int time) {
this.time = time;
}
}
Теперь я не уверен, что JSF делает за кулисами, чтобы сделать эту динамическую итерацию данных dataTable через Список часов возможной, но я предполагаю, что если это происходит все в одном потоке, то это нормально. Однако что, если за кулисами getHours используется в другом потоке, который фактически генерирует столбцы и видит Hour в плохом состоянии? Этого можно избежать, если метод getHours()
public List<Hour> getHours() {
final List<Hour> hours = new ArrayList<>();
for (int i = 0; i < 5; i++) {
hours.add(new Hour(i + ""));
}
return hours;
}
with the corresponding Hour class being
public class Hour {
private final int time;
public Hour(int time) {
this.time = time;
}
public int getTime() {
return time;
}
}
Однако мой вопрос заключается в том, что, если он не был изменен на последний дизайн, могут ли что-то пойти не так при использовании базового динамического рендеринга JSF dataTable из-за проблем с видимостью в Java при публикации экземпляров Hour?
1 ответ
JSF работает поверх Servlet API, который обслуживает один запрос в одном потоке, поэтому, если вы сами не введете больше потоков, вы можете ожидать, что ваш код будет выполняться в одном потоке.
С другой стороны, вы должны познакомиться с основами жизненного цикла JSF и с тем, как осуществляется доступ к свойствам bean-компонентов, так как это может вызвать массу проблем, если вы этого не понимаете.
Например, если ваш Java-код останется прежним, добавление еще одной ссылки на todaySchedule.hours в ваш JSF вызовет вызов метода получения дважды, что приведет к генерации содержимого дважды. Это может очень быстро запутаться, поэтому хорошо бы заняться "кэшированием". Я лично использую этот подход:
private List<Hour> hours = null;
private void initHours() {
this.hours = new LinkedList<>();
// Fill hours here
}
public List<Hour> getHours() {
if (this.hours == null) {
initHours();
}
return this.hours;
}
Вы должны быть осторожны, хотя на какой стадии жизненного цикла JSF вы делаете это. Если вы, например, в методе обработки формы измените данные, влияющие на генерацию списка, список, вероятно, будет уже "кэширован" с фазы восстановления представления, и изменение не будет отражено, когда начнется фаза просмотра представления. В таком случае вы должны быть осведомлены о кешировании и очистить список, когда вам нужно его перезагрузить.
public void saveHours() {
// Save the data, do whatever you need to do
// This will ensure re-initializing the list on the next call
this.hours = null;
}