2015-11-05 3 views
0

У нас есть большое приложение, предварительно JEE5, который использует JPA, но не использует CDI или EJB, так EntityManager не получает впрыскивается в DAO,, а создается с помощьюCDI Инъекция в созданных объектов

Persistence.createEntityManagerFactory(...).createEntityManager() 

, и затем сохраняется в переменной ThreadLocal. Эта грязная работа по созданию диспетчера сущностей инкапсулируется в класс утилиты EntityManagerUtil, используемый DAO, поэтому бизнес-логика не имеет дело с менеджером низкого уровня; Кроме того, это приложение использует aspectj и аннотации для создания границ транзакций, а в аспектах транзакции используется тот же класс EntityManagerUtil, что и DAO, чтобы получить диспетчер сущности для создания транзакции.

Мы должны перенести это приложение на wildfly 9 сейчас. Это не работает из коробки, так как aspectj не может быть развернута в wildfly, поэтому наши аспекты, которые создают и фиксируют транзакции, не применяются, и ничего не работает. Чтобы заставить его работать, нам нужно ввести EntityManager в DAO и использовать транзакционный механизм EJB или CDI, но, похоже, это также означает, что нам нужно вводить DAO в любые классы, используя их, а затем вводить эти классы в классы выше на иерархии вызовов и т. д. (как будто класс создается с использованием «нового», он не управляется контейнером, и в него ничего не вводится). Поскольку приложение является большим, и у нас есть экземпляр объекта повсюду, это кажется невыполнимой задачей.

Так что мне интересно, можно ли изолировать использование инъекций в DAO и более низких уровнях, поэтому код вызывающего абонента, который использует DAO, не изменится и все равно создаст DAO с использованием «нового», но DAO будет использовать диспетчер инъецируемых сущностей и CDI или EJB?

Любые предложения приветствуются, спасибо!

+0

на более высоком уровне, когда ящик впрыскивается, можете ли вы сохранить его в локальной сети? Позже, новые DAO могут искать его из локальной сети. – ZhongYu

+0

Не могли бы вы немного рассказать о том, как используется ваш 'EntityManagerUtil'? Вам, скорее всего, придется либо полностью управлять (сервером), либо вам придется покинуть контейнер из него. –

ответ

1

я проголосовал бы за IoC контейнер как Spring или CDI, поскольку EJB не дает вам инъекцию пользовательских зависимостей - только другому EJBs и предопределенные ресурсы сервера может быть введен (EDIT: Конечно, если приложение использует CDI и EJB, то также можно вводить cdi beans).

Я хотел бы попробовать обернуть BeanManager (или ApplicationContext при использовании Spring) в каком-то статический служебном классе доступного отовсюду - особенно в бизнес-логике (static будет временный подходом, альтернативный способ заключается в использовании WildFly сервера и его возможности JNDI).

Но это может быть сложно, если приложение использует архив EAR и несколько загрузчиков классов (но, я думаю, если приложение использует теперь шаблон ThreadLocal, то он отлично работает с несколькими «синглетонами» уже).

Транзакционные границы могут быть достигнуты путем аннотации всех DAO с помощью @javax.transaction.Transactional. Позже BeanManager/ApplicationContext сам может быть использован для создания таких DAO внутри бизнес-классов.


КСТАТИ: при переходе на WildFly 9 таких приложений до JEE5, возможно, эти проблемы с транзакций будет один из самых маленьких. Вам также придется иметь дело с огромным количеством новых библиотек (возможно, несовместимыми с уже использованными), предоставляемыми сервером, проблемами с загрузчиками классов и т. Д. ...

+0

Вы можете определенно управлять управляемыми ресурсами '@ Inject' CDI в EJB. В большинстве случаев вы можете даже '@ Inject' сам EJB. –

+0

@ JamesR.Perkins кажется бессмысленным комментарием. Тем не менее EJB не дает вам возможности IoC. Мы все знаем, что можно объединить EJB и CDI, но почему автор захочет погрузиться в еще большие проблемы с EJB? –

+0

Я предполагаю, что неправильно понял ваш «только другие EJB и заданные серверные ресурсы». Мои извинения. –

0

Вы, безусловно, можете сделать своего рода локализованную инъекцию 're talk about, но это немного многословный без рамки расширения cdi, такой как Apache DeltaSpike.

С помощью DeltaSpike вы можете просто сказать BeanProvider.getContextualInstance(MyInterface.class);, чтобы «ввести» материал в свой самостроенный объект.

Без DeltaSpike или эквивалента вы все равно можете использовать поиск jndi, чтобы получить доступ к BeanManager, чтобы «ввести» ваши компоненты, но api не так хорош.

Что касается jndi, вы также можете реализовать свой доступ к данным с помощью EJB и инкапсулировать доступ к ним в своих старых самоподготовленных DAO через jndi-запросы. Не так приятно, но это, по крайней мере, даст вам доступ к транзакциям, управляемым контейнерами.

Смежные вопросы