An Oracle blog about Java Technology

Better CDI Alignment in JPA 2.1/Java EE 7

Guest Author

A long standing open debate within the Domain-Driven Design (DDD) community is whether entities should be able to access application services (roughly business facades in J2EE patterns parlance) and repositories (roughly DAOs in J2EE patterns parlance). If we think it's OK for entities to access these parts of the application, it poses a problem in JPA and other mainstream data access technologies - how do you inject objects into an entity? The answer today in JPA is that you can't do that. There are good technical reasons why it's difficult to allow CDI injection directly into JPA entities - it becomes very difficult to figure out how to manage the entity life-cycle if it is managed by both the CDI and JPA runtimes at the same time.

So is there a solution to this problem? The good news in JPA 2.1 and Java EE 7 is that there is a clever workaround. While you can't use CDI injection in entities, entity listeners now fully support injection. If needed you can then pass in an appropriately scoped injected object (probably an application scoped bean) into the entity or anything else that you need from the entity listener. This is exactly the technique demonstrated by Hantsy Bai in explaining CDI support in JPA 2.1 entity listeners. Besides entity access to services and repositories, being able to use injection in entity listeners is generally very helpful for more complex cross-cutting concern like requirements at the JPA layer. Prior to JPA 2.1 both Apache CODI and Seam 3 enabled injection into JPA entity listeners.

If you happen to need a basic introduction to JPA entity listeners, Alexandre Gama has one of the best compact write-ups I've seen so far.

For the record, I do think accessing application services and repositories in entities violates the separation of concerns principle and should be done very sparingly :-).

Please note that any views expressed here are my own only and certainly does not reflect the position of Oracle as a company.

Join the discussion

Comments ( 8 )
  • guest Friday, January 23, 2015

    Thank you, I thought that only I have such problems...

  • guest Friday, January 23, 2015

    "accessing application services and repositories in entities violates the separation of concerns principle"

    Why would you ever call a DAO/Repository from an JPA entity ??

  • Reza Rahman Friday, January 23, 2015

    The typical example given (which I do not agree with) is implementing something like MyEntity.save(), MyEntity.delete(), etc.

  • guest Wednesday, January 28, 2015

    This is not for calling DAO/Repository, but for eg sending ("domain") events. So in @Pre/@PostXXX you can inject eg CDI event launcher, and later fire it in any bussiness method of entity. Anyway you always need to somehow inject it or provide manually for new (not yet persisted) entity. On persisted one you can inject on @PostPersist. It would allow you then to send email or JMS event from observer. Badum tss ;)

  • Veit Weber Friday, February 13, 2015

    It would be nice if GF 4.1 supports that feature. I'm not able to inject a CDI Bean into an EntityListener

  • Reza Rahman Friday, February 13, 2015

    Hmm, perhaps file a bug? It is supposed to be working and did in GF 4.0 last I checked...

  • Veit Weber Monday, February 23, 2015

    It works with GF 4.0. I filed a bug for Payara. In GF 4 there is already one: https://java.net/jira/browse/GLASSFISH-21195

  • Reza Rahman Tuesday, February 24, 2015

    Thanks. The Paraya guys are awesome :-).

Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.