1 2 3 4 Previous Next 59 Replies Latest reply on Jun 11, 2009 1:35 PM by luxspes

    Injection into entity beans

    hajdi

      In order to achieve Rich Domain Model it is often (very often in fact) necessary to inject objects managed by DI framework to entity beans. Current JSR-299 spec doesn't seem to support this in an easy way. You can of course access these objects programitcally but by doing this you lose DI benefits. Is there a way in JSR-299 to handle such a scenario? Maybe some Seam 3 extension is planned that uses Hibernate Interceptor, JSR-299 SPI or something else? What is WebBeans team view on solving this use case?


      Regards,
      Rafał Hajdacki

        • 1. Re: Injection into entity beans
          cpopetz

          It should be possible to use the JSR-299 SPI's BeanManager.createInjectionTarget() and the resulting InjectionTarget.inject(...) method to inject dependencies into an entity bean via a @PostConstruct callback of the entity bean.  I don't know if a Seam3 extension is planned along those lines, but if not, I plan on rolling my own and sharing it, because I too dislike anemic models.

          • 2. Re: Injection into entity beans
            gavin.king

            In my opinion, this is a horrible thing to do architecturally. Your domain model is the re-usable representation of your business. It should not be polluted by access to application-specific services.


            Seriously, I'm a super-skeptic on architectural complexity, and I feel like I've spent my whole career advocating less layers, but even I don't advocate mixing your domain model, your infrastructural services, and your application-specific transaction logic into one big ball of dirty skanky nastiness.

            • 3. Re: Injection into entity beans
              gavin.king

              Not to mention the fact that entities may be instantiated using new, even in a different physical tier of the application. An entity is not always a container-managed object. That's why it has the whole new-persistent-detached lifecycle model.


              Do you really want to have to call Instance<Order>.get() to instantiate an Order?

              • 4. Re: Injection into entity beans
                hajdi

                In my opinion, this is a horrible thing to do architecturally. Your domain model is the re-usable representation of your business. It should not be polluted by access to application-specific services.

                Seriously, I'm a super-skeptic on architectural complexity, and I feel like I've spent my whole career advocating less layers, but even I don't advocate mixing your domain model, your infrastructural services, and your application-specific transaction logic into one big ball of dirty skanky nastiness.


                Agree but what if one of my domain objects is not persistent but session scoped instead? For example session scoped Cart in online shop. I may be wrong but from high level perspective persistence can be considered as just another scope that is wider than @ApplicationScoped. We can come up with examples where nice OO design requires injection of session scoped domain object into persistent scoped domain object (similar to request scoped into session scoped injection). Gavin you wrote once that the power of Seam is that it doesn't enforce application structure on you. You just create classes the way it fits domain, Seam handles their lifecycle and you can use them directly from view (JSF) with very little or no plumbing code at all. I would extend that flexibility to persistent classes. What do you think?


                BTW If you need some non-domain service layer then I agree that domain model shouldn't access it.



                Not to mention the fact that entities may be instantiated using new

                This would have to be solved by proper constructor I believe. In fact in nice OO design if object requires something it should be provided in constructor or method parameter. From this perspective no-argument constructor requirement in JPA spec can be considered a drawback but there are reason for that.



                even in a different physical tier of the application. An entity is not always a container-managed object. That's why it has the whole new-persistent-detached lifecycle model.

                Completely agree, if you need entities that should travel across physical tiers then you shouldn't access external objects from them. But the same is true for lazy initialized fields that were not initialized. Accessing them requires external persistence service which is similar to accessing external service object.



                Do you really want to have to call Instance Order .get() to instantiate an Order?

                Not really, I would like to use constructor injection in entities when they are created by EnitityManager and normal constructor instantiation in case of manual creation.


                Regards,
                Rafał

                • 5. Re: Injection into entity beans
                  gavin.king

                  Agree but what if one of my domain objects is not persistent but session scoped instead? For example session scoped Cart in online shop

                  Even if the Cart is persistent, you can easily put the Cart in the session scope using a producer method. You just would not be able to directly inject things into it (though you can inject into the producer method and pass the injected objects to the Cart constructor).


                  Or, if the point it is not persistent, what is the problem? You are trying to inject other things into it? Go ahead. Even if those other things



                  I may be wrong but from high level perspective persistence can be considered as just another scope that is wider than @ApplicationScoped.

                  No, things in the database are not uniquely identifiable by type/bindings. You need to look them up explicitly using a query API.



                  We can come up with examples where nice OO design requires injection of session scoped domain object into persistent scoped domain object (similar to request scoped into session scoped injection).

                  I'm certain that whatever usecase you come up with can be easily and more elegantly expressed using producer methods.


                  I'm also unclear on whether you are talking about an injection that happens once when you first instantiate the entity, and is thereafter stored persistently in the database as an association, or an injection that happens every time the entity is loaded. Two very different possible semantics.



                  You just create classes the way it fits domain, Seam handles their lifecycle and you can use them directly from view (JSF) with very little or no plumbing code at all. I would extend that flexibility to persistent classes. What do you think?

                  I don't think the analogy holds. There is an additional level of flexibility that is necessary in the case of entities: the flexibility to pass them around the system and use them in the absence of any container management. Secondly, in the case of entities, only very rarely do you encounter an entity that is singleton-ish. Normally, entities must be retrieved using queries, they can't just be injected without writing some code that specifies which one you're interested in. That code goes in the producer method.



                  This would have to be solved by proper constructor I believe. In fact in nice OO design if object requires something it should be provided in constructor or method parameter.

                  Right. And if I directly instantiate an object using its constructor, how does the container get an opportunity to inject dependencies of the object?



                  Not really, I would like to use constructor injection in entities when they are created by EnitityManager and normal constructor instantiation in case of manual creation.

                  Well, that would certainly be possible, and as Clint mentions, a portable extension could even provide that. But to me it seems like a very semantically weak kind of injection.

                  • 6. Re: Injection into entity beans
                    cpopetz

                    Gavin King wrote on May 31, 2009 21:53:


                    In my opinion, this is a horrible thing to do architecturally. Your domain model is the re-usable representation of your business. It should not be polluted by access to application-specific services.

                    Seriously, I'm a super-skeptic on architectural complexity, and I feel like I've spent my whole career advocating less layers, but even I don't advocate mixing your domain model, your infrastructural services, and your application-specific transaction logic into one big ball of dirty skanky nastiness.


                    All of my comments below are only my $.02, with the implicit acknowledgement that you can create good and bad code regardless of your architectural approach, and hence my suggestions (and yours) can be misused by others, but that this misuse does not constitute a refutation of the worth of the approach in question.  I also have a great deal of respect for your knowledge of architecture, in particular with regard to entities and dependency injection, Gavin. 


                    If entities are containers of data, and only that, an argument against IoC in entities makes sense.  However, when entities are true model objects, i.e. data and behavior representing a domain model, then they need to interact with other layers in order to accomplish the business logic they contain without resorting  to skankiness. Interacting with other layers doesn't make you skanky.  You do however need a clean way to do that.  Injection is one such way.


                    The standard way to avoid adding IoC to model/entity classes is to leave them behaviorless (except for trivial validations that need no dependencies) and to shove all the logic into a DAO layer.  That ends up creating horrible parallel graphs of Foo.java and FooManager.java, where the latter knows exactly how to hook a Foo to everything a Foo needs or that needs a Foo.  Blech.  A Foo at that point is essentially a C struct. 


                    The repeated argument I've heard against adding dependencies to entities is simply that it's hard because sometimes the ORM creates entities and sometimes the application logic does, but that seems like an argument for creating a mechanism for handling that, rather than punting on making entities real objects.


                    I could go on, but it's better summarized here .






                    -Clint

                    • 7. Re: Injection into entity beans
                      gavin.king

                      I really think you're setting up a false dichotomy here. I've heard this same argument before from other people. It is claimed that:



                      1. it is very much more OO to put business behavior with data, and

                      2. our entities hold most of the interesting data, so

                      3. therefore, we need dependency injection in our entities.



                      But this argument is missing a couple of steps. First, you need to show that:



                      • the kind of interesting business behavior that makes sense to package with the persistent data is the same logic that we usually want to implement in injectable beans, and

                      • there is no other natural way to get injectable beans into an entity other than injecting them directly.



                      But I'm simply incredibly skeptical on both of these points. IMO, the kind of business logic that really belongs on your entities is the stuff that uses the entity, and other entities that are related to it by graph traversal, and not random other stuff that you get by injection. And if you really can find me some cases where you need to use the random other stuff in an operation that truly does belong on an entity, I don't see why you can't just pass that stuff as method parameters from something else that you can inject into.

                      • 8. Re: Injection into entity beans
                        gavin.king

                        And by the way, I'm not at all in favor of an anemic domain model, and so the only thing about that Fowler article that I don't agree with is the idea that EJB somehow encourages it. Indeed, the original EJB entity beans were conceived as rather heavyweight components with method-level transaction and security demarcation that were responsible for implementing rather non-trivial transaction processing! So it seems like Fowler has things exactly backward on that point: it is the POJO (meaningless term) model that does more to encourage the need for a service layer, since the service layer is absolutely needed for transaction and security management.


                        I think what happened here is the following chain of reasoning:





                        • Anemic domain is Bad and

                        • EJB is Bad,

                        • therefore EJB forces you to use anemic domain.





                        Whatever, note that the Fowler article has nothing to say on the subject of injection, and so we don't know (or even especially care) what he would think about the topic we're discussing.

                        • 9. Re: Injection into entity beans
                          gavin.king

                          Actually, on the contrary, those folks who do want to inject into entities should perhaps take another look at entity beans in EJB2. That architecture does seem to be more like what you're looking for. Combine the EJB2 Entity Bean component model with a decent persistence mapping layer, and EJB 3.1-style annotations, and dependency injection via 299, and away you go... :-)

                          • 10. Re: Injection into entity beans
                            cpopetz

                            Gavin King wrote on Jun 01, 2009 02:53:


                            But this argument is missing a couple of steps. First, you need to show that:


                            • the kind of interesting business behavior that makes sense to package with the persistent data is the same logic that we usually want to implement in injectable beans, and






                            I guess you'll need to tell me what the same logic that we usually want to implement in injectable beans is, because I see no canonical definition of this type of logic.  To me, for example, the following things are useful things to be injected:



                            1. Things that might change based on deployment type

                            2. Things that are optional, but which, if present, we want to make use of

                            3. Things that our client code does not what to lookup manually

                            4. Things that have a pluggable implementation, such that we wish to inject the interface but have no idea what the implementation will resemble or who will provide it.



                            I can think of a wealth of use cases for models to need each of those.  Some examples:



                            1. Almost all my entities want logging, but I need that logging to be implemented differently based on deployment type.

                            2. My entities may want to provide an audit trail in @PreUpdate, but the audit interface is pluggable and may be a no-op, and the entity should not know about when or why that auditing mechanism changes, exists or doesn't, nor how to find it.

                            3. My entity may, in response to a method invoked by application code, need to lookup references to newly-dependent entities. It would rather not embed the query in itself, because several other entity types also need to do something similar with this type of dependency, and the query should not be duplicated.  So the query is abstracted to a DAO.  But the client invoking the update method on my entity has no reason to know about the DAO, so it should not pass it as parameter to the entity, and the DAO has no useful state, so it should not be an entity to which my entity has a reference.  The DAO is a dependency of some set of entities, and not of the business logic code that uses those entities.






                            • there is no other natural way to get injectable beans into an entity other than injecting them directly.





                            Why on earth would that be required to make client code worthy of injection?  In every case where you use injection there are other natural ways to get the injectable beans into the client code.  We used these mechanisms for decades before injection arrived.  Injection is simply cleaner, so we use it.



                            But I'm simply incredibly skeptical on both of these points. IMO, the kind of business logic that really belongs on your entities is the stuff that uses the entity, and other entities that are related to it by graph traversal, and not random other stuff that you get by injection.


                            I'm trying to understand what motivates this preferenced distinction between things I can reach by traversing my existing entity graph and things I can obtain by injection.  Why is behavior I can find in my referenced entities ok to use, but behavior I can find via injection (or without injection, via static methods) random other stuff?  From my  entity's perspective, the things I can reach by traversing my set of references are injected.  They're just injected by the ORM.  And what you're really saying here is that only the ORM can inject things into an entity, because it knows what references an entity needs.  But I told the ORM what things the entity needs, and I only told it things I needed to store in the database, because that's the role of the ORM.  But there are other logical forms of dependencies that don't relate to object persistence, which are still dependencies my entity needs to do its job. 




                            And if you really can find me some cases where you need to use the random other stuff in an operation that truly does belong on an entity, I don't see why you can't just pass that stuff as method parameters from something else that you can inject into.


                            I can say the same of any object that uses injection.  That's a straw man.



                            As an aside, did you never write:


                            @Logger Log log;



                            in an entity (post-Seam), and absolutely love it?  Why are we stopping there?

                            • 11. Re: Injection into entity beans
                              gavin.king

                              The point is that I have a good reason for thinking that entities should not depend upon things that they can only obtain from the container: the reason is that we often want to be able to serialize them around the system and use them in execution contexts where there is no container (or a logically different container).

                              • 12. Re: Injection into entity beans
                                gonorrhea

                                Active record is the pattern that applies to the anemic domain model situation (there is actually some coverage of this in the SiA book when DAllen is covering the Seam Application Framework).  I don't have experience with RoR or Active Record, but...



                                Active Record attempts to provide a coherent wrapper as a solution for the inconvenience that is object-relational mapping. The prime directive for this mapping has been to minimize the amount of code needed to build a real-world domain model. This is made possible by relying on a number of conventions that make it easy for Active Record to infer complex relations and structures from a minimal amount of explicit direction.



                                Convention over Configuration:



                                    - No XML-files!
                                    - Lots of reflection and run-time extension
                                    - Magic is not inherently a bad word



                                Admit the Database:



                                    - Lets you drop down to SQL for odd cases and performance
                                    - Doesn‘t attempt to duplicate or replace data definitions

                                source: http://ar.rubyonrails.org


                                I'm not sure if I'd refer to ORM as inconvenient, at least we have HibernateTools (hbm2java specifically) and 1st and 2nd level caches; if you have that mind-set then use OODBMS like db4o, InterSystems Cache, etc.


                                I really think that application tx (aka atomic conversation) using SMPC and Hibernate MANUAL flushMode extension is a very useful tool in Seam apps.


                                Transaction support in ActiveRecord::Transactions::ClassMethods module is weak at best (e.g. no distributed tx support).


                                But if you really dislike anemic models, then use RoR or similar.  Or find a way to integrate that into your JEE apps.  Hey, at least the DTO pattern is now an anti-pattern in EJB3...


                                My concern is not so much the anemic domain problem as much as when will OODBMS and JEE integration become a JSR so we don't need to use ORM anymore.  RDBMS has been around since the 70's, no?  I know a lot of corporations are using RDBMS but finally they will be phased out with new technology like OODBMS.  Ted Neward has blogged about the OODBMS topic a lot.

                                • 13. Re: Injection into entity beans
                                  matt.drees

                                  Gavin King wrote on Jun 01, 2009 03:48:

                                  we often want to be able to serialize them around the system and use them in execution contexts where there is no container (or a logically different container).


                                  Is that the common case?  I've never needed to do that.  Maybe that's just me.


                                  And even if it is the common case, entity injection availability doesn't require entities to necessarily use it; the author of an entity will know whether the it will need to be serialized to a different (container-less) execution context, and can code accordingly.

                                  • 14. Re: Injection into entity beans
                                    gonorrhea

                                    so it sounds like you guys are saying why can't DI be available/optional in entity classes?  if it's available and you don't use it, then GKing's concerns are irrelevant in those cases (e.g. unit testing).  JavaBean Seam components can have injections and implement java.io.Serializable, no?  So if they can, why can't entity classes as well?


                                    PEAA by Fowler does not cover DI at all.


                                    I looked at the Active Record pattern in that book and the examples showed static CRUD methods in the entity class.  Also business logic methods are in the entity class.



                                    Their primary problem is that they would work well only if the Active Record objects correspond directly to the database tables: an isomorphic schema.

                                    If your business logic is complex (relations, inheritance, etc), it's better to use Data Mapper.


                                    I prefer not to have business logic in my entity classes.


                                    But I guess the argument is, if for some reason we need to add business logic to entity class, then we may need injections?


                                    But why do you need to have the biz logic in the entity class in the first place?  What's wrong with separation of concerns and doing the biz logic in a JavaBean or EJB?


                                    Or what about allowing DI in entity classes only via XML, not annotations?


                                    How much do you really gain by adding biz logic methods to entity class?  Perhaps you won't have to repeat code in multiple business components (DRY principle) if it's already a method in the entity class...


                                    Overall, I'm siding with GKing on this one until somebody provides a concrete example of why/when you'd need DI in entity classes and what the gain/advantage is...

                                    1 2 3 4 Previous Next