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.