An Idea for JPA Regarding Domain-Driven Design

May 14, 2011

JPA and domain-driven design don’t mix well. In fact, JPA “entities” are representatives of the anemic data model that Fowler warns against. I have already discussed DDD in the light of JPA and dependency injection, so I won’t go into much details here whether anemic data model is bad or not (for the record: I don’t think it’s bad).

But for the times you need to inject dependencies into entities standards don’t give you a hand. The only option is @Configurable, which requires aspectj weaving, which is “black magic” to me. So why you can’t inject dependencies into entities? Because they are created by you and not by a dependency injection framework.

Well, here’s a weird idea. What if JPA 3 had EntityManager.createEntity(Foo.class) so that your entities are managed all the time? Then you’ll be able to inject dependencies different than other entities (which is already handled by JPA through associations). How will it work?

  • JPA will require a DependencyManager which will provide the dependencies, handle their lifecycle, etc. CDI will be the default dependency manager of course, but any framework (spring, guice, etc) can plug-in their implementation
  • whenever you em.create(..) your entity it will have its dependencies set – as if the entity is created by your DI framework
  • this would mean that the “transient” state of entities will not exist (if you choose the create() method, that is)

But… detached entities, or the cases when you need to create the entities where you should not have access to the entity manager (in a controller for example) are the most important thing. And I can’t give a satisfactory suggestion to this one. You would either need to inject EntityCreator which, under the hood will either use the entity manager, or another mechanism (if you are likely to switch from JPA to something else). But this could be a “best practice” rather than a standard interface because if it is a JPA interface that’s still a direct dependency of the web layer on JPA. Another option is to propagate the creation through all layers, but that is boilerplate. A third option is to have detached entities automatically attached when they ‘enter’ the service layer (through AOP). And a downside to the idea is that people will be tempted to inject the EntityManager itself, which will violate layer boundaries. And another downside is that people may (rightfully) say – “what, I can’t use the new operator anymore?!”

So I’m just throwing an idea. I would be surprised if CDI and JPA designers didn’t think of something similar, so I’d like to hear some (more) cons.

6 Responses to “An Idea for JPA Regarding Domain-Driven Design”

  1. Long story short, I successfully implemented Spring DI, using @Configurable, with JPA entities. It worked fine when I created an entity with the ‘new’ keyword. DI did not work, however, when Hibernate reconstituted my entities. And that stands to reason. I suspect there’s a workaround for this issue. I just never bothered to look for it.

    I build my entities with DDD in mind. But I’ve never felt a strong need to use DI within my JPA entities. I only did it as an experiment for a client.

    Interesting post.

  2. I’m not quite understanding the issues you see with “detached entities in the contoller layer”? I presume the case is you create an entity there (using DI) and then want to persist it?

    Pete (CDI Spec lead)

  3. @Pete – yes, it is the case when you create an entity in the controller (or any front-end related component, that is. I use controller generically, but in case of JSF that would be the jsf managed bean). Since you usually don’t have an EnitityManager injected there, you can’t do em.createEntity(..). You’d have to use some other mechanism – either “new”, or some delegate (like the mentioned EntityCreator, which would not be JPA-dependent)

  4. Ok, so this is more an architectural concern/issue than a technical one (you don’t want to “pollute” your controller layer with EM references?

    Anyway, I would have thought the best to handle this would be to allow JPA to persist entities created using “regular” DI. To impl this, JPA would need to callback into the DI layer to “deproxy” the object just after calling em.persist(). Any other issues that I am missing about why you can’t just persist any old DI object.

    In CDI I guess you would do

    @Inject @New Person person;

    to get such an object. And in CDI only if it was non-dependent scoped would you need to deproxy it.

  5. @Pete yes, you can easily persist anything. But when you later call `em.find(..)` (or execute a query), you won’t have any dependencies injected in your object. That’s where the DI can be plugged in JPA.

  6. Very interresting post. Is there anything new one year later?
    I wonder what would be the cons of accessing the BeanManager (via jndi) in the entity constructor to access a local service provided that:
    1) the entities are not serialized and sended over the network
    2) I know this is not DI

    Thanks for this great post

Leave a Reply