Когда форма обрабатывается в 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;
}
Другие вопросы по тегам