| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Java EE (J2EE) и Spring > Spring + Hibernate + JSF 2.0 |
| Автор: 4epT 13.4.2011, 21:13 | ||||||
| Добрый вечер! Пытаюсь соединить эти три фреймверка =) Расскажу по порядку: 1) Сделал для всех таблиц в БД, отображение на сущности (Entity) 2) Написал Dao классы ... Dao написаны таким образом что есть один базовый Dao:
От этого класса унаследовано все остальные Dao. 3) Сделал класс userManager, который пока что просто дублирует методы userDao. 4) В настройках спринга все описал ... но поле userDao в классе userManager не инициализируется, и при вызове методы валится NullPointerException. Вот настройка настройка бинов:
А вот класс userManager:
Подскажите пожалуйста где я ошибся ? Если что то не привел, скажите, допишу ... вроде все упомянул. Заранее спасибо! |
| Автор: 4epT 13.4.2011, 22:13 | ||
И еще хотел спросить, стоит ли связывать эти три вещи ? До этого начинал писать без спринга, но приходилось самому следить за транзакциями и использовать самописный HibernateUtil
|
| Автор: 4epT 13.4.2011, 22:45 | ||
А можно насчет этого поподробнее ?) В web.xml спринг не прописан ( Пытался прописать там listener, но проект после этого не собирается ... |
| Автор: emmanuil 13.4.2011, 22:59 | ||||||
Причина? Не просто так же. Чего-то не хватает значит. Если не пропишите, то он сам не догадается. ;)
Начните пожалуй с этого. Это с грэйлса, но в жсф где-то тоже такое видел. А что тут подробнее... Обычный java ee стек. JPA, ejb там всякие, транзакции. В jsf 2.0 думаю можно обойтись без спринга. Но смотря что нужно. JSF это отображение в EE. Сейчас java ee стал проще, навешал аннотаций и работай себе. Добавлено через 10 минут и 10 секунд Вот еще:
Добавлено через 11 минут и 23 секунды для примера - http://code.google.com/p/mesir/source/browse/#svn%2Ftrunk%2Fmesir%2Fsrc%2Fmain%2Fwebapp%2FWEB-INF |
| Автор: 4epT 13.4.2011, 23:30 | ||||
Когда в web.xml прописываешь:
проект перестает собираться ... в консоли видно вот такое:
p.s. у меня работало без спринга, но у меня у проекта была такая архитектура что из jsf бина (ManagedBean) дергался метод какого либо менеджера (в данном примере UserManager). Все менеджеры создавались jsf бине, с областью жизни сессия ... что не очень красиво (менеджеров ожидается порядка 40 штук ... в сессия будет очень много хлама). |
| Автор: emmanuil 13.4.2011, 23:40 | ||
Больше похоже на попытку запуска. В логах сервера смотри доп. инфу.
А спринг тут чем поможет? Измени видимость. Есть даже conversation. Определись, какие действия нужны с менеджерами. Тот выполняет только логин, его в request. Добавлено через 2 минуты и 15 секунд Есть CDI бины. weld подключи и юзай DI. @Injected нравится? Тогда бины нужно Named помечать. |
| Автор: 4epT 14.4.2011, 09:32 | ||||
В логах томкэта видно вот такое:
и такое:
|
| Автор: 4epT 15.4.2011, 14:51 | ||
| В общем я разобрался ) вкратце опишу как все сделал, может кому то пригодится. faces-config в итоге у меня пустой. В applicationContext (контекст спринга), описываю все spring bean, dataSource (Sessionfactory), transactionManager и настройки хибера. В web.xml прописываю путь к applicationContext, и вешая два листенера:
помимо этого еще нужно повесить RequestLoaderListener (пишу по памяти, но вроде похоже ...), этот листенер нужен для работы с jsf. Ну и в applicationContext, я не прописываю jsf manadeg beans, я просто из управлямых бинов (managed bean), достаю бины спринга и с ними работаю ) |
| Автор: MisterCleric 15.4.2011, 14:59 | ||
| Привет. Вообще по своему опыту могу сказать такое: JSF-бины, в принципе, и не нужны. Достаточно все описать в Spring и использовать их напрямую. Для это в faces-config.xml добавить такое:
|
| Автор: 4epT 15.4.2011, 16:12 |
| Использовать их напрямую откуда ? Я например хочу использовать jsf контролы наподобие рич или прайм фейсес ... |
| Автор: MisterCleric 15.4.2011, 17:23 |
| JSF-контролы - это не Managed-бины. Это визуальные компоненты. Такие себе HTML-темплейты с некоторым JavaScript кодом. |
| Автор: 4epT 15.4.2011, 17:47 |
| то есть в атрибут action можно повесить метод/поле spring bean ? Если да, то чем такая связка лучше чем через managed bean ? =) |
| Автор: MisterCleric 18.4.2011, 11:15 | ||
Тем, что у тебя всего лишь одно место конфигурации бинов. И только один контейнер - Spring. А еще у тебя все получается в одном стиле - спринговском. Spring со всеми своими фреймворками более мощней, чем JSF сам по себе. И вполне возможно, что решая задачи на JSF ты однажды придешь, к тому, что у Spring уже есть готовое решение. Ты его подключаешь к своему проекту - и начинает разрастаться у тебя конфигурация как JSF, так и Spring. Как по мне так лучше все в одном месте иметь. Но это сугубо мое личное мнение. Просто однажды начав проект JSF+Spring я всю конфигурацию вынес в Spring и был доволен. |
| Автор: 4epT 18.4.2011, 20:11 | ||
А тогда такой вопрос =) Если я отказываюсь от JSF, то логично использовать Controller из Spring MVC ... да ? а как будет обстоять дело с шаблонами ? К примеру в JSF это facelets. |
| Автор: MisterCleric 19.4.2011, 08:10 | ||||
| Привет. Нет от JSF ты не отказываешь. Ты просто делаешь конфигурацию backend для JSF в Spring. JSF у тебя остается - он просто делает делегирование в Spring. MVC тебе здесь не нужно: у тебя же есть FacesServlet, который и решает, какой backingBean вызываеть, а тот уже в свою очередь является SpringBean. Для них обоих их взаимодействие остается прозрачным. 1. В web.xml ты прописываешь как конфигурацию JSF, так и конфигурацию Spring. Главное не забыть это:
Чтобы можно было пользоваться request & session Scope при конфигурации Spring/ 2. В faces-config.xml добавляешь такое:
Все остальное - navigation-rules, converters, validators может остаться без изменения, хотя я тоже последние конфигурю в Spring 3. И того: у тебя получается приложение на JSF, просто его бины сконфигурены в другом контейнере. |
| Автор: isabsent 1.5.2011, 11:08 | ||||||||||||||||
Пробую реализовать вашу программу на основе референсного примера из пакета Spring Web Flow 2.3 http://static.springframework.org/spring-webflow/resources/samples/swf-booking-faces.war В нем разбирается Spring-centric интеграция Spring, Hibernate с JSF2.0. Столкнулся с необходимостью написания своего собственного конвертера WalletConverter.java, преобразующего строку списка referenceData.wallets в объект Wallet, чтобы вставить его в поле referenceData.wallets при обработке .xhtml страницы с элементом выбора из выпадающего списка:
В референсном примере такой конвертации нет - только "строки <-> числа", поэтому и проблемы такой нет. На сколько я понял и мануалов, я должен добавить объявление конвертора в faces-config.xml
В WalletConverter.java мне необходим доступ к объекту walletService из контекста Spring
Проблема в том, что Spring почему-то никак не хочет инжектировать walletService в предназначенное ему аннотацией @Autowired место. Под дебагом я вижу, что перед моментом конвертации вместо walletService стоит ссылка на null. Получать этот бин напрямую из контекста Spring мне не хочется по некоторым причинам. Поэтому возникает вопрос - Как инжектировать бин в JSF-конвертор? Чем тут может помочь добавление
в faces-config.xml ? Поясните плз, почему в web.xml вы говорите, что нужно использовать
Если возможно - выложите plz, исходники вашего приложения или хотя бы конфигурационные файлы web.xml, web-mvc.xml, web-flow.xml и faces-config.xml |
| Автор: RageSteel 1.5.2011, 12:06 | ||
| Тебе не нужен JSF-конвертор для твоего случая. В JSF2 можно просто написать:
Что-же касается конверторов, то их тожно определять с помощью аннотаций. А что касается того, как получить экземпляр сервиса в конверторе. Самое простое — это получить спринговый контекст и запросить у него. Либо нужно как-то встраиваться в процесс создания конверторов в JSF2. |
| Автор: isabsent 1.5.2011, 12:13 | ||||||
Спасибо, попробую осмыслить сейчас. Дадите ссылочку на то где это написано? Два дня гуглил - не попадалось ничего похожего... P.S. Проверил вашу подсказку - Exception такой же как и был до того как я понял, что нужно писать конвертер
|
| Автор: RageSteel 1.5.2011, 13:52 | ||||
http://javaserverfaces.java.net/nonav/docs/2.0/pdldocs/facelets/f/selectItems.html Может у тебя твой конвертор мешается? Я активно пользуюсь этим синтаксисом и у меня с ним проблем не было. У тебя точно JSF 2.0? |
| Автор: isabsent 1.5.2011, 14:03 | ||
| Судя по jsf-api-2.0.3.jar и jsf-impl-2.0.3.jar в Libraries проекта - надеюсь что JSF2.0... Или еще надо какие-то либы смотреть? Я делаю это под Tomcat 6 - в нем не может быть проблемы? Может есть какая-то демо-версия или хотя бы основные конфиги - сравнить? Видимо я что-то не так делаю. По прежнему пытается найти конверторы - 'null Converter' в Exception... P.S. Никак не пойму как указание параметров itemValue и itemLabel на .xhtml-странице поможет мне вытащить нужный объект wallet из ArrayList<SelectItem> и поместить его поместить в поле newOutcome.wallet.
Может у вас там что-то типа http://balusc.blogspot.com/2007/09/objects-in-hselectonemenu.html#UsingABackingMap организовано и поэтому всё работает? |
| Автор: RageSteel 1.5.2011, 17:14 |
| Для использования itemLabel и itemValue метод getWallets должен возвращать не список SelectItem'ов, а просто список объектов Wallet, без преобразования. |
| Автор: isabsent 1.5.2011, 17:50 | ||||||
| Точно! Невнимательно прочёл jsf-доку... Переписал
И всё равно -
|
| Автор: RageSteel 1.5.2011, 18:42 |
| То что оно пишет в консоль Debug, может это от того, что у тебя на странице нет <h:messages />? Конверторов больше никаких нет, ни в faces-config ни в классах с аннотациями? Тип newOutcome.wallet точно принимает значение типа Wallet? Почему в логах пишет Wallet(Cash), откуда берётся Cash? В какой момент возникает сообщение? При отображении страницы или при осуществлении действия? |
| Автор: isabsent 1.5.2011, 19:06 | ||||||||||||||
У меня нет странице <h:messages />. А для чего оно там нужно? В логах пишет Wallet(Cash) потому что берет мой переопределенный wallet.toString() и выводит его в консоль.
Его же выводит и в выпадающих списках на веб-странице. Cash - это ID одного из Wallet - того, которого я выбрал из выпадающего списка перед тем как нажать на кнопку чтобы сохранить объект newOutcome в базу. Все упоминания о конверторах выкинул ОТОВСЮДУ и сами классы конверторов удалил из проекта. В main-flow.xml
Сообщение возникает при выполнении действия. До этого всё отрабатывается без ошибок.
Полный лог того что происходит после нажатия на кнопку:
А как должен быть аннотирован тот класс, в котором я делаю
У меня просто @Service стоит. Может надо @Scope(request) какой-нибудь? |
| Автор: RageSteel 1.5.2011, 20:10 |
| Ух. А можешь проект куда-нибудь выложить? А то у меня остаются только мысли вроде: «может что-то не так с развёртыванием и где-то остались старые файлы». <h:messages /> нужно для отображения сообщения JSF'а. В частности туда бы у тебя вывелись сообщения о необходимости конвертации. Что-же касается аннотаций @Service. Я знаю что там у Spring'а по умолчанию, но то что у тебя правильно выводит списки означает, что оно работает. |
| Автор: isabsent 1.5.2011, 20:28 |
| Попробовал на Гугл выложить - что-то по ссылке архив не загружается... Сейчас подумаю - куда еще можно. Может проще на мыло выслать? А! Вот - догадался и сюда выложил |
| Автор: RageSteel 1.5.2011, 20:38 |
| http://narod.yandex.ru |
| Автор: isabsent 1.5.2011, 20:50 |
| Перевыложил архив - замените плз. Там была версия с вариантом backing Map и кое-какие мелочи поправил. На первой странице в левом верхнем углу нажать на login На второй странице выбрать из предложенного списка login/password и нажать Login На третьей ничего не вводить - только нажать Find Outcomes На четвертой выбрать что-нибудь из выпадающих списков, в третье поле вставить 120.00, по четвертому щелкнуть и выбрать дату, в пятое вставить любой текст и нажать кнопку Save справа от строки ввода. После этого в логе появятся DEBUG'и с error'ами на тему Conversion Error setting value 'Wallet(Cash)' for 'null Converter |
| Автор: isabsent 2.5.2011, 07:04 |
| Сейчас выкину всё лишнее - две страницы, две таблицы, скрипт для их создания - и выложу. На первой странице - перейти по ссылке "Start your Spring Travel experience" На второй странице выбрать что-нибудь из выпадающего списка, во второе поле вставить 120.00, по третьему щелкнуть и выбрать дату, в пятое вставить любой текст и нажать кнопку "Save". |
| Автор: isabsent 2.5.2011, 15:11 |
| Похоже, что вы имели ввиду вывод данных из бина в выпадающий список на странице. С этим у меня проблем не было с самого начала. А я спрашивал о конвертации в обратном направлении - из выпадающего списка на странице в поле объекта (а не просто в строку или число как в примере из SWF). |
| Автор: RageSteel 2.5.2011, 19:08 |
| Да, был не прав. Если просто вставить itemValue=#{w} то в html в значении option будет значение Wallet.toString(), что не верно. Моё предложение, чтобы не связываться с конверторами: поместить в itemValue значение индентификатора Wallet. Тогда во время сохранения можно будет его восстановить. Собственно я сделал ещё более «лёгкую» версию, только JSF2.0, безо всякого Spring'а. Недеюсь принцип понятен. |
| Автор: isabsent 2.5.2011, 19:20 |
| Спасибо - разберу ваш пример. Для тех кто нас прочтёт Если кто-то знает как внедрить Spring-бины в JSF-конвертер - очень хотелось бы услышать. (Только не через вытаскивание посредством Spring-контекста). |
| Автор: RageSteel 2.5.2011, 21:02 |
| http://stackoverflow.com/questions/5069991/how-to-inject-a-spring-3-bean-into-a-jsf-2-converter — вот ещё один вариант. Если посмотреть со стороны JSF — то правильный способ — Spring должен предоставлять реализацию JSF ApplicationFactory, которая в методе createConvertor возвращала бы экземпляр с внедрёнными зависимостями. Но…, почему ты так хочешь воспользоваться именно конвертором? |
| Автор: isabsent 3.5.2011, 05:47 | ||||
Понять будет ли то что тут предложено работать и как http://stackoverflow.com/questions/5069991/how-to-inject-a-spring-3-bean-into-a-jsf-2-converter мне пока не хватает опыта. Вот если бы там рабочий пример был... JSF ApplicationFactory - она уже есть в Spring или подразумевается, что я сам её напишу? Потому что конвертор - это стандартный подход в JSF. Не нужно реализовывать подпорки типа той, что описана у BalusC. И вроде всё для него есть - одна только проблема - заставить JSF увидеть бин walletService...
|
| Автор: RageSteel 3.5.2011, 20:44 |
| В Spring'е я такого не обнаружил, хотя он вполне там и мог бы быть. Самому писать лениво — Spring мне не особо интересен но общий принцип простой. Реализуем ApplicationFactory, где все методы кроме создания Application переправляем в оригинальную ApplicationFactory. В методе создания Application оборачиваем созданный Application с помощью ApplicationWrapper, где в свою очередь переопределяем метод возвращения конвертора. Вместо него пишем получаем Bean конвертора из Spring'а. Как-то так. Может способ, приведённый на stackoverflow всех устраивает (@Component("myConverter")). |
| Автор: MisterCleric 4.5.2011, 10:45 | ||
| Насчет конвертеров и валидаторов. Зачем их определять в faces-config.xml, если у тебя есть Spring? Просто берешь их и определяешь как Spring бины, разве что имплементишь нужные интерфейсы. И будет тебе счастье с @Autowired. Разве что нужно быть аккуратным со scope, чтобы они не оказались у тебя на все приложение, да и чтобы не получился scope impedans. И насчет RequestContextListener. Такова рекомендация интеграции JSF+Spring. Он нужен для того, чтобы мокжно было работать со scopes session & request. а также в его исходниках так и написано:
|
| Автор: isabsent 8.5.2011, 21:55 | ||
Золотые слова! Жаль, что сразу не доходят - только после того как на всех граблях постоишь... Не забывайте переопределять equals() и hashCode() у бина, для которого пишется свой пользовательский Converter - иначе долгий и упорный "Validation Error: Value is not valid" в элементах типа selectOneMenu... Странно, почему конвертер в JSF так выделен среди других классов? Ведь можно же инжектировать Spring-бины в другие JSF-бины (вот, например, http://technology-for-human.blogspot.com/2010/12/jsf-2-with-spring-3-basics-part-1-of-2.html), а как только класс implements Converter, так всё это благолепие рушится и остаётся один грубый FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance()).getBean("yourServiceBean")! Почему так?! |
| Автор: RageSteel 9.5.2011, 06:11 | ||
В приведённой ссылкы injectируется результат выполнения Expression Language выражение, а так как используется Spring EL Resolver, то там работает подключение Spring-Bean'ов. Жизненный цикл конвертора управляется JSF'ом, который ничего про Spring не знает. |
| Автор: isabsent 9.5.2011, 09:05 | ||
В приведённой ссылке жизненный цикл бина BikeDetails, в который легко и непринуждённо инжектируется Spring-бин bikeDataProvider, находится под управлением JSF IoC. Однако в JSF Converter, точно так же находящийся под управлением JSF IoC, невозможно инжектировать ничего, что находится под управлением Spring IoC - даже с помощью EL-Resolver. Поэтому я не совсем понимаю ваш ответ - ведь ситуация одна и та же, а spring-бин не инжектируется во втором случае... |
| Автор: RageSteel 9.5.2011, 10:22 |
| Не совсем так. В BikeDetails inject'ируется не Spring Bean, а результат выполнения ExpressionLanguage выражения! И Spring представляет реализацию ELResolver'а, который может получать доступ к Spring'овым Bean'ам. |
| Автор: isabsent 9.5.2011, 11:37 | ||
Всё равно непонятно - почему тот же самый результат выполнения ExpressionLanguage выражения не может инжектироваться в Converter!? Чем Converter принципиально отличается от любого другого JSF-бина с точки зрения Spring'a или EL-Resolvera? |
| Автор: RageSteel 9.5.2011, 12:13 |
| Конвертор не поддерживает @ManagedProperty, если я правильно помню. |
| Автор: isabsent 9.5.2011, 15:09 | ||
Да - я в этом на собственной шкуре убедился |