очерёдность запуска managed beans

victorhalf

Green Team
29.05.2007
79
3
BIT
0
Всем привет
Пытаюсь научиться пользоваться managed beans, да и явой заодно. Если кто этим добром пользуется подскажите как правильно всё организовать.
Ситуация такая - создал два бина: bean1 (session scope) и bean2 (view scope), в первом хранится всё что касается пользователя, во втором - собственно логика документа.

Хочется чтобы данные из bean1 можно было получить в bean2.
Что то типа bean2.setCreator(bean1.getUserName());

Покопался в инете, люди советуют использовать <managed-property></managed-property>. Мне это в общем то подходит, но не могу побороть проблему очерёдности загрузки бинов. Понятно что сессионный бин1 должен быть загружен раньше бин2, но почему то bean2 грузиться раньше bean1.

Bean2 у меня инициируется как DataSources в createObject, а вот где грузить Bean1 не могу понять. Делал и из передЗагрузкойСтраницы и послеЗагрузкиСтраницы и на контроле где у меня ApplicationLayout (в который обёрнуты все страницы), но всё равно вначале грузиться бин2, а потом бин1.

Может кто подскажет как правильно организовывать логику загрузки бинов, а то ведь ещё хочется
сделать application scope bean.
[doublepost=1507529230,1507193309][/doublepost]Как оказалось <managed-property> не очень то и нужно, можно просто через ExtLibUtil.resolveVariable() проверять наличие бина, при этом в первый раз он создастся автоматом, а потом просто будет его использовать.
Единственно что смущает , что эту проверку нужно вставлять в конструктор каждого бина где будет использоваться сессионный бин.
 
C

cLif

Довольно странно. По идее IoC должен корректно делать загрузку бинов и зависимостей. Можете кинуть фрагмент объявления бинов?
 

victorhalf

Green Team
29.05.2007
79
3
BIT
0
Довольно странно. По идее IoC должен корректно делать загрузку бинов и зависимостей. Можете кинуть фрагмент объявления бинов?
Да загружает то он их, наверное, корректно, но вот только я не знаю как правильно организовать их загрузку. Видовой бин объявляю в разделе xp:this.data
Код:
<xp:this.data>
       <xe:objectData
           var="adsDoc"
           saveObject="#{_javascript:adsDoc.save();}">
           <xe:this.createObject><![CDATA[#{_javascript:return new dpgas.zayavki.beans.Ads;}]]></xe:this.createObject>
       </xe:objectData>
   </xp:this.data>
а вот где объявить сессионный бин, чтобы он однозначно загрузился раньше видового я не знаю.
 
R

romych2004

Вариантов несколько:
1) Попробовать оба бина объявить в Faces-cofig и использовать менеджет-проперти(я так понимаю этот вариант не подходит)
2) Оба бина объявить в Обджект Дата, создадутся они скорее всего в том порядке, в каком ты их объявишь(я так понимаю этот вариант тоже не подходит)
3) Bean1 объявить в фейсес конфиг. Заменить
Код:
<xe:this.createObject><![CDATA[#{_javascript:return new dpgas.zayavki.beans.Ads;}]]></xe:this.createObject>
на
Код:
<xe:this.createObject><![CDATA[#{_javascript:var a = return new dpgas.zayavki.beans.Ads();
a.setCreator(bean1.getUserName());
return a;}]]></xe:this.createObject>
4) Bean1 объявить в фейсес конфиг. Добавить конструктор для Ads, туда передавать нужные данные. Но не забыть объявить пустой конструктор для сериализации
5) Для бин1 добавить код:
Код:
private static String BEAN_NAME = "bean1";
public static Bean1 get() {
return (Bean1) ExtLibUtil.resolveVariable(BEAN_NAME);
}

И в Bean2 добавить метод:
Код:
private String creator = nunll;
public String getCreator() {
if(creator == null) creator = Bean1.get().getUserName();
return creator;
}

Не совсем понимаю что именно нужно :) Может есть еще какие-то варианты.. это первое что в голову пришло
 
  • Нравится
Реакции: cLif
C

cLif

Я бы пошел по пути 1 и объявил оба бина в faces-config. Прелесть в том, что без надобности бин не будет инстанцироваться. А надобность - первое обращение в коде.

объявление в objectData - не совсем managedBean получается. Кстати, если правильно помню, то в objectData, createObject можно указать имя managedBean. А какая задача? Создать контроллер страницы или обертку объекта?
 

victorhalf

Green Team
29.05.2007
79
3
BIT
0
А какая задача? Создать контроллер страницы или обертку объекта?
Наверное, обертку объекта. Вместо document1. У меня просто уже есть работающая страница которая использует документ в качестве источника и библиотеку ssjs для логики. Хочу подучить и яву и переписать всё под неё, чтобы работать с объектом явы, а в реальный документ только записывать/читать. Вот и учусь как это делать.
Посмотрел видео NotesIn9, там именно рассказывали про objectData, мне понравилось.
1) Попробовать оба бина объявить в Faces-cofig и использовать менеджет-проперти(я так понимаю этот вариант не подходит)
Дело не в "не подходит", а в то м что при этом всё равно вначале грузиться конструктор видового бина, а потом сессионного.

например так я делал в faces-config
<managed-bean>
<description>Data for whole applacation</description>
<managed-bean-name>appData</managed-bean-name>
<managed-bean-class>dpgas.ApplicationData</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>

<managed-bean>
<description>user Session Data</description>
<managed-bean-name>userData</managed-bean-name>
<managed-bean-class>dpgas.SessionData</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>aplData</property-name>
<value>#{appData}</value>
</managed-property>
</managed-bean>

<managed-bean>
<description>Ads document Bean</description>
<managed-bean-name>myBean</managed-bean-name>
<managed-bean-class>dpgas.zayavki.beans.Ads</managed-bean-class>
<managed-bean-scope>view</managed-bean-scope>
<managed-property>
<property-name>usd</property-name>
<value>#{userData}</value>
</managed-property>
</managed-bean>
public class Ads implements Serializable {
public Ads() throws NotesException {
...
setCreator(SessionData.getUserPib());
...​
}
}
возможно здесь нужно както по другому, но...
при этом по дебагеру видно что вначале отрабатывает конструктор Ads, а уже потом SessionData.

сейчас остановился на таком конструкторе
public class Ads implements Serializable {
public Ads() throws NotesException {
{ //проверяю есть ли такой бин в памяти, если нет он создаеётся
SessionData usrData = (SessionData)ExtLibUtil.resolveVariable(FacesContext.getCurrentInstance(), "userData"); }
setCreator(SessionData.getUserPib());
...​
}
}
но при этом в managed-property необходимости нет.
2) Оба бина объявить в Обджект Дата, создадутся они скорее всего в том порядке, в каком ты их объявишь(я так понимаю этот вариант тоже не подходит)
Это то как раз было самое очевидное, но как по мне, прописывать на каждой странице инициализацию обоих бина - слишком топорно. Хотелось как то поизящнее.
 
R

romych2004

А при чем здесь конструктор? Конструкторы, как мне кажется - больше служебные, для десереализации. Я всегда его пустым оставляю.

Вызывай через события. Либо у документа postOpen, либо у пейджа на beforePageLoad
 
  • Нравится
Реакции: alexas1

victorhalf

Green Team
29.05.2007
79
3
BIT
0
А при чем здесь конструктор? Конструкторы, как мне кажется - больше служебные, для десереализации. Я всегда его пустым оставляю.
Вызывай через события. Либо у документа postOpen, либо у пейджа на beforePageLoad
да какая разница где я буду инициализировать внутренности объекта, хоть в конструкторе хоть через процедуру. Конструктор объекта, как я понял, вызывается при создании объекта через new.Пока меня это устраивает, потом может перенесу загрузку в отдельную процедуру.
На очерёдность это не повлияет. А сессионный бин я пытался грузить в beforePageLoad и самой страници и applicationLayout, но всё равно createObject для objectData срабатывает раньше, уж не знаю почему.
 
C

cLif

Таки понятно (ну вроде как).
property - это же свойство. А вы говорите о конструкторе. В этом случае действительно view-scope bean используется раньше сессионного, поэтому в setCreator(), небось, вылетает NullPointerException.

В Ads у вас, наверно, есть setter наподобие: setSessionData(SessionData data).
Попробуйте для него еще сделать getter и в конструкторе setCreator(getSessionData().getUserPib()).

Если не прокатит то, что написал вышел - ваш способ более чем нормальный для подобной ситуации. На мой взгляд, использование конструктора не противоречит религии, поскольку использовать метод с @PostConstruct в JSF1.2 возможности нет. Для удобства можно вынести получение бина из контекста в утильный метод, что-нибудь типа:

public enum JSFUtil {
;
public static <T> T getBean(String beanName) {
return (T)ExtLibUtil.resolveVariable(FacesContext.getCurrentInstance(), beanName);​
}​
}

тогда писанины будет еще меньше и ваш конструктор примет совсем простой вид:
SessionData userData = JSFUtil.getBean("userData");
setCreator(userData.getUserPib());
 

victorhalf

Green Team
29.05.2007
79
3
BIT
0
В Ads у вас, наверно, есть setter наподобие: setSessionData(SessionData data).
Попробуйте для него еще сделать getter и в конструкторе setCreator(getSessionData().getUserPib()).
Нет, сеттера/геттера нет, только проверка на наличие присутствия бина, как написано выше.
А вообще, всем спасибо за ответы. Я только пытаюсь яву и бины раскурить.
Понял что мой вариант не самый бестолковый.
Вопрос именно был в корректной загрузке цепочки бинов: видовой, сессионный, апликационный. Надеялся, что установка managed-property для видового бина в фейсес конфиг автоматически создаст сессионный бин, но нетс.
Просто не хотетелось в дальнейшем наступить на непонятные грабли.
 
C

cLif

А вообще, всем спасибо за ответы. Я только пытаюсь яву и бины раскурить.
Понял что мой вариант не самый бестолковый.
Вопрос именно был в корректной загрузке цепочки бинов: видовой, сессионный, апликационный. Надеялся, что установка managed-property для видового бина в фейсес конфиг автоматически создаст сессионный бин, но нетс.
Просто не хотетелось в дальнейшем наступить на непонятные грабли.

Scope бина не влияет на цепочку загрузки как таковую. Влияет использование бинов. Суть - первое обращение к бину инициирует его загрузку. А scope - это область жизни бина. Таким образом:
1. application - один и только 1 объект данного класса на все приложение (т.е. для всех пользователей)
2. session - один и только 1 объект класса в рамках сессии. У каждого пользователя - свой экземпляр
3. view - новый бин инстанцируется каждый раз, когда происходит загрузка страницы
4. request - бин каждый раз инстанцируется и живет в рамках запроса.
5. flash - искусственный scope (т.е. нельзя писать в faces-config scope=flash) для передачи параметров при переходе между страницами (на основе view + request).

Нет, сеттера/геттера нет, только проверка на наличие присутствия бина, как написано выше.

Вы выше писали, что в faces-config у вас такое описание бина. Тогда в классе должен быть setter/getter (getUsd(), setUsd())
<managed-property>
<property-name>usd</property-name>
<value>#{userData}</value>
</managed-property>
Дословно эта конструкция читается так: при инстанцировании бина, положи в его поле (usd) через setter (setUsd) значение. Значение - другой бин, который называется userData.
Ошибка у вас не возникает по одной простой причине: вы не обращаетесь к объявленному бину myBean из кода, а просто говорите new Ads(). Отсюда и причина, почему ваш сессионный бин не инстанцируется.

Если правильно помню, то для objectData можно просто передать название бина из faces-config, а не писать new ...
 
  • Нравится
Реакции: victorhalf

victorhalf

Green Team
29.05.2007
79
3
BIT
0
Тогда в классе должен быть setter/getter (getUsd(), setUsd())
Спасибо, не знал.
Если правильно помню, то для objectData можно просто передать название бина из faces-config, а не писать new ...
надо будет попробовать,на видео у Дэвида Лиди было так
 
C

cLif

надо будет попробовать,на видео у Дэвида Лиди было так
Посмотрите в описании свойства, там должно быть написано так это или нет.
NotesIn9 очень хороший ресурс. Если будете углубляться в java для xpages очень советую так же обратить внимание на Jessy Gallagher и его "философию" контроллеров. Основывал свой движок для xsp приложений (в части контроллеров) именно на его идее.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!