#jsf
#jsf
Вопрос:
Во время тестирования была выявлена слабость в том, как наше приложение создает f:selectItems
списки, в частности, ввод действительно длинных имен для некоторых наших объектов улучшает выравнивание страницы, делая действительно широкие выборки.
Многие из этих списков SelectItem дублируются в нескольких представлениях и вспомогательных компонентах, поэтому я хотел бы объединить их создание.
У нас уже есть компонент в области приложений, который предоставляет список<SelectItem> для перечислений, и моей первоначальной мыслью было разместить их там.
Однако у меня есть несколько вопросов. Мы используем jsf 1.2 (если это имеет значение)
1) Насколько я понимаю, компоненты в области приложений являются одноэлементными просто потому, что создается один экземпляр и помещается в контекст сеанса. Они не похожи на синглтоны EJB3 в том смысле, что только один поток может получить доступ к любому методу, поэтому множественные запросы не будут блокировать попытки доступа к разным методам. Это правильно?
2) Я подозреваю, что каждый метод должен быть синхронизирован, чтобы несколько потоков, вызывающих один и тот же метод, не загромождали друг друга. Так ли это, даже если единственным членом класса, к которому осуществляется доступ в методе, является потокобезопасный @EJB без состояния?
Ниже приведена реализация одного из них, который будет использоваться в 20 представлениях. Реализации для 10 других объектов будут аналогичными. Также зарегистрированы соответствующие преобразователи.
public synchronized List<SelectItem> getAccountSelect(){
List<Account> list = new ArrayList<Account>(pemEJB.list(Account.class));
Collections.sort(list, new AccountByActiveByName());
List<SelectItem> result=new ArrayList<SelectItem>(list.size());
for(Account row : list){
result.add(new SelectItem(row,
StringUtil.prefixTruncate(row.getName(), MAX_ACCT_LENGTH, row.isActive())));
}
return resu<
}
Приветствуются любые советы
Ответ №1:
Если действительно обязательно выполнять загрузку данных в геттере, а не в конструкторе / postconstruct, то определенно нет смысла делать это компонентом в области приложений. Просто сделайте это в области запроса, где вы выполняете задание загрузки данных в конструкторе / postconstruct.
Комментарии:
1. Спасибо, лампочка только что погасла. Я застрял в мышлении, основанном на обратных представлениях beans, и никогда не рассматривал простое использование отдельного компонента запроса из всех представлений
Ответ №2:
В приложениях на jsf, над которыми я работаю, мы загружаем почти все наши справочные данные (в первую очередь значения для selectonemen-ов) в компоненты области приложений и устанавливаем значения в конструкторе этих компонентов. Затем данные становятся доступными для других управляемых компонентов и представлений через средства получения, но глобализируются и централизовываются для приложения. Поскольку значения считываются только с помощью методов получения, нет необходимости в синхронизации.
Затем мы предоставляем beans в виде mbeans через jmx с методом перезагрузки, чтобы их можно было обновлять по мере необходимости. Методы перезагрузки синхронизированы таким образом, чтобы блокировать во время коротких перезагрузок.
В вашем примере выше кажется, что вы могли бы просто вернуть коллекцию SelectItems, поэтому, пока значения настроены заранее, вы можете использовать этот метод и по-прежнему отлично обслуживать несколько потоков:
public List<SelectItem> getAccountSelectItems() {
return this.accountSelectItems;
}
Просто добавьте этот закрытый элемент в свой компонент:
private List<SelectItem> accountSelectItems;
и настройте это в конструкторе:
public AccountBean() {
List<Account> list = new ArrayList<Account>(pemEJB.list(Account.class));
Collections.sort(list, new AccountByActiveByName());
this.accountSelectItems = new ArrayList<SelectItem>(list.size());
for(Account row : list) {
this.accountSelectItems.add(new SelectItem(row, StringUtil.prefixTruncate(row.getName(), MAX_ACCT_LENGTH, row.isActive())));
}
}
Если, с другой стороны, это данные, которые постоянно меняются и нуждаются в обновлении, возможно, было бы лучше просто загружать их за сеанс или за запрос, хотя вы можете периодически перезагружать их в области приложения, используя Quartz или какой-либо другой таймер, чтобы замедлить чтение данных из вашего источника данных, если реальное время не является существенным требованием для этих данных в вашем приложении. Если вы перезагружаете данные, то вам захочется синхронизировать эти операции, если вы используете область приложения.
Комментарии:
1. К сожалению, это требование для сборки по запросу. Я думаю, что отдельный компонент с ограниченной областью запроса — это правильный путь.