简体   繁体   中英

CDI Injection in created objects

We have a large pre-JEE5 application that uses JPA but does not use CDI or EJB, so EntityManager does not get injected into DAOs, but rather is created using

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

, and then stored in ThreadLocal variable.This dirty work of getting entity manager is encapsulated in utility class EntityManagerUtil used by DAOs, so business logic does not deal with low level entiy manager stuff; also, this application uses aspectj and annotations to create transactional boundaries, and transaction aspects use same EntityManagerUtil class as DAOs to obtain entity manager to create transaction.

We need to migrate this application to wildfly 9 now. It does not work out of the box, as aspectj cannot be deployed in wildfly, so our aspects that create and commit transactions do not apply and nothing works. To make it work, we need to inject EntityManager into DAOs and use EJB or CDI transactional mechanism, but it seems that this also means that we need to inject DAOs into whatever classes use them, then inject these classes into the classes higher up on the call hierarchy, and so on (as if the class is created using "new" it is not managed by the container and nothing gets injected into it). As the application is big, and we have object instantiation all over the place this seems like impossible task.

So I wonder if it is possible to isolate injection usage in the DAO and lower levels, so caller code that use DAO would not change,and would still create DAOs using "new", but the DAO would use injected entity manager and CDI or EJB transactions ?

Any suggestions are welcome, thank you !

I would vote for IoC container like Spring or CDI , because EJB doesn't give you a custom dependency injection - only other EJBs and pre-defined server resources can be injected ( EDIT: of course if app is using CDI and EJB, then cdi beans also can be injected ).

I would try to wrap BeanManager (or ApplicationContext if using Spring) in some kind of a static utility class accessible from everywhere - especially within business logic ( static would be a temporary approach, alternative way is to use a WildFly server and its JNDI capabilities).

But it can be tricky, if application is using EAR archive and multiple class loaders (but I guess, if app is using now a ThreadLocal pattern, then it lives fine with multiple "singletons" already).

Transactional boundaries can be achieved by annotating all DAOs with @javax.transaction.Transactional . Later BeanManager / ApplicationContext itself can be used for creation of such DAOs inside business classes.


BTW: when migrating to WildFly 9 such pre-JEE5 application, perhaps these problems with transactions will be one of the smallest. You will also have to deal with a huge amount of new libraries (probably incompatible with already used ones) provided by the server, issues with class loaders and so on...

You certainly can do the sort of localized injection you're talking about, but it's a bit verbose without a cdi extension framework like Apache DeltaSpike.

With DeltaSpike you could simply say BeanProvider.getContextualInstance(MyInterface.class); to "inject" stuff into your self-constructed object.

Without DeltaSpike or equivalent you could still use a jndi lookup to get access to the BeanManager to "inject" your beans but the api is not as nice.

Regarding jndi you could also implement your data access using EJBs and encapsulate access to them in your old self-created DAOs via jndi lookups. Not so nice but that would at least get you access to container-managed transactions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM