1 2 3 4 Previous Next 59 Replies Latest reply on Jun 11, 2009 1:35 PM by luxspes Go to original post
      • 15. Re: Injection into entity beans
        hajdi

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


        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).


        But in most cases they do depend on things that can be obtained only from the container: lazy initialized fields. We can think of external services similar to them. It is application specific, if you need transportable entities then don't use dependencies that may cause problems.

        • 16. Re: Injection into entity beans
          hajdi

          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).


          I want to handle use cases where request/seesion/application scoped object is accessed by entity. Great example provided by Clint is Logger.



          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.


          Is that really a requirement for DI / scoping? It is just current state of things in JSR-299. We can come up with injection point that for example takes entity ID as parameter and injects Entity instance. Or even query in order to access collection of entities. This could work similar to Any in JSR-299.



          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.


          I am talking about second case here. Don't want to store it in database.



          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.


          This flexibility is not always required. This is application specific I think. If you want transportable objects you just don't expose not initialized persistent fields and external objects/services.



          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.


          Does something have to singleton-ish in order to support injection? Well I just see EntityManger as just another context that I can access programmatically. As mentioned above we can also use query or entity id for injection point to support enity injection into other objects.



          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?


          It doesn't. If you create objects manually you have to do it on you own.



          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.


          Why is it semantically weak?

          • 17. Re: Injection into entity beans
            hajdi

            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...


            How about Logger injection into entities?

            • 18. Re: Injection into entity beans
              cpopetz

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


              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).


              That's a perfectly legitimate requirement, and a good reason to be very careful about creating dependencies in the model layer if you have it. I've never had that requirement, nor do I see it as a natural endpoint for the types of problems we solve.


              I think our difference on this issue may be due to our definition of entity.  To me, the only connotation inferred from the @Entity annotation is persistence.  By designating an class an entity I am agreeing to obey the rules of JPA in order to make use of a JPA provider to map my object to a table.  If (for example) one uses an entity in RMI situations, then that imposes  additional requirements, but that's orthogonal to the question of what's good or bad for entities.  That's why I accept the argument that the entity lifecycle complicates injection, because that argument is based on a characteristic that entities share by definition.



              • 19. Re: Injection into entity beans
                hajdi


                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.

                Does something have to singleton-ish in order to support injection? Well I just see EntityManger as just another context that I can access programmatically. As mentioned above we can also use query or entity id for injection point to support enity injection into other objects.


                Gavin, but WebBeans's Logger is also not singleton-ish and yet you consider it a good candidate for injection. There are many instances of it from which only one is selected and injected using injection point metadata as id source. Entities can be handled in a similar way. The one thing that is different as Clint mentioned is more complicated life cycle of entities. But really is there anything in it that is a deal breaker for supporting injection?

                • 20. Re: Injection into entity beans
                  cpopetz

                  I want to clarify that I am not advocating adding injection of entities to JCDI.  That level of modification of the existing specification at this point in its lifecycle wouldn't be advisable or even feasible, and the semantics of entity injection needs a lot more thought in any case.


                  I am however advocating the investigation of a webbeans extension, either in Seam3 or otherwise, that would support this. 


                  • 21. Re: Injection into entity beans
                    hajdi

                    I want to clarify that I am not advocating adding injection of entities to JCDI.  That level of modification of the existing specification at this point in its lifecycle wouldn't be advisable or even feasible, and the semantics of entity injection needs a lot more thought in any case.


                    I am also not advocating it. In fact I am strongly against for doing it now. I am only arguing that considering persistence as just another context that can be handled by DI is feasible in general. But of course there are probably lots of issues hidden in JPA-JCDI integration in order to achieve it in an elegant way.


                    My point of mentioning this idea is to support general perspective that it is sensible to think about DI-managed and EM-managed objects as just domain objects that can access each other and that reasons for not doing so comes from other requirements/use cases that are not related to standard domain logic design.



                    I am however advocating the investigation of a webbeans extension, either in Seam3 or otherwise, that would support this. 


                    Agree. This was my initial point starting this thread.

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

                      Rafal Hajdacki wrote on Jun 01, 2009 12:58:



                      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...


                      How about Logger injection into entities?


                      Seriously, if logging is the best usecase you can come up with...

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

                        Rafal Hajdacki wrote on Jun 01, 2009 10:44:



                        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).


                        I want to handle use cases where request/seesion/application scoped object is accessed by entity. Great example provided by Clint is Logger.


                        seems like a kinda lame example to me :-)




                        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.


                        Is that really a requirement for DI / scoping? It is just current state of things in JSR-299. We can come up with injection point that for example takes entity ID as parameter and injects Entity instance. Or even query in order to access collection of entities. This could work similar to Any in JSR-299.


                        This is a case of injecting entities into other things, not a case of injecting other things into entities. This can be handled today with magical things like producer methods and InjectionPoint.




                        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?


                        It doesn't. If you create objects manually you have to do it on you own.


                        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.


                        Why is it semantically weak?


                        Because its a field that is sometimes injected and so sometimes has the semantics specified by the annotations declared at the injection point.

                        • 24. Re: Injection into entity beans
                          gonorrhea

                          Gavin King wrote on Jun 01, 2009 18:24:



                          Rafal Hajdacki wrote on Jun 01, 2009 12:58:



                          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...


                          How about Logger injection into entities?


                          Seriously, if logging is the best usecase you can come up with...


                          I don't think logging by itself (one use case) qualifies as a solid case for allowing DI in entity classes.  Although it may be more convenient to have access to DI in an entity class, you can still use JNDI lookup, no?


                          It really comes down to whether or not business logic belongs in an entity class.  If it does (in some cases), then perhaps DI should be under consideration.


                          I mean do you really need to do some calculation, for example, in an entity class?  Why can't that logic happen in a DAO, for example?


                          The only advantage I see with having the biz logic embedded in an entity class (as a public method), is you don't have to factor that method into an auxiliary helper class that is injected into a SFSB or DAO class everytime it is needed.  So essentially it would cut down on coding.  Especially in the case where you have an interface (e.g., Vehicle) which is implemented by Car, Truck, and SUV entity classes.  That biz logic (calculation, etc.) may be common to all the entities and may belong in the interface or perhaps an abstract class with implementation.


                          So let's say you have a valid case and need to embed the public calculation method in the entity class, do we need access to EntityManager interface directly at this point for CRUD ops?  I hope not.  I think it's better to maintain separation of concerns, but at the same time minimize layering if possible.


                          This is one thing I agree on with GKing and one main reason I liked Seam from the beginning (no forced layering and patterns like Struts/EJB2.x!)

                          • 25. Re: Injection into entity beans
                            hajdi

                            Seriously, if logging is the best usecase you can come up with...


                            Seriously, if you don't consider logging a valid use case ... ;-) Why you have added injected logger to Seam and WebBeans extensions then? And who said it is the best use case? How about application scoped FileManager that abstracts access to files which we don't want to store in blobs? How about use cases provided by Clint?

                            • 26. Re: Injection into entity beans
                              hajdi


                              I want to handle use cases where request/seesion/application scoped object is accessed by entity. Great example provided by Clint is Logger.

                              seems like a kinda lame example to me :-)


                              That's for sure the ultimate argument Gavin. :-) Agree that logging seems trivial but it is still very frequent and valid use case. Let's make it less trivial then. How about audit logging that is common in financial/payment applications. You better make sure every financial operation is reported. And database is not always target storage for such audit traces. So injected AuditLogger would be very handy in entity beans. If this is lame use case then tell it to our customers. I would love to see their faces. ;-)



                              This is a case of injecting entities into other things, not a case of injecting other things into entities. This can be handled today with magical things like producer methods and InjectionPoint.


                              Please keep context of the discussion. I have provided ideas regarding injecting of entities into other things as example that the analogy of persistence to other context holds. And that injecting other things into entities is similar to injecting request scoped objects into session scoped objects. As arguments against that you first mentioned that things in the database are not uniquely identifiable by type/bindings which I showed is not requirement for DI. Second you argued that entities are not singleton-ish which I refuted by mentioning Logger which is also not really singleton-ish and yet fits DI (heck, you seem to have introduced InjectionPoint mostly to support such non singleton-ish cases). Third argument was that entities need to be transportable across container boundaries. But as me and Clint answered this requirement is really orthogonal to DI and also is not present in many applications.


                              Any other arguments against that analogy?


                              As for magical things provided by JSR-299, I am well aware of them as I follow spec changes and your blog since the beginning. As I mentioned in previous comment I don't argue here for adding support for alternative ways of entity injection into other things. This was just for the sake of argument.




                              Why is it semantically weak?

                              Because its a field that is sometimes injected and so sometimes has the semantics specified by the annotations declared at the ijection point.


                              Agree, such a injection is really semantically weak. You have to use Instance<Order>.get() to avoid that.
                              But really when you create entity manually you are on your own to provide dependencies.

                              • 27. Re: Injection into entity beans
                                gonorrhea

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


                                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.



                                And Fowler most likely doesn't care about Seam or Web Beans as is evidenced by the fact that his blog entries are dated back to 2003, pre-EJB3, which is kinda lame.  Nevertheless...



                                I don't know why this anti-pattern is so common. I suspect it's due to many people who haven't really worked with a proper domain model, particularly if they come from a data background. Some technologies encourage it; such as J2EE's Entity Beans which is one of the reasons I prefer POJO domain models.

                                In general, the more behavior you find in the services, the more likely you are to be robbing yourself of the benefits of a domain model. If all your logic is in services, you've robbed yourself blind.

                                Why does he say you're robbing yourself?



                                The logic that should be in a domain object is domain logic - validations, calculations, business rules - whatever you like to call it.

                                Validations is (mostly) solved by Hibernate validators.  How often do we need calculations in CRUD apps in the domain model?  And don't business rules belong in the business logic tier?


                                source: http://martinfowler.com/bliki/AnemicDomainModel.html

                                • 28. Re: Injection into entity beans
                                  gonorrhea

                                  Rafal Hajdacki wrote on Jun 01, 2009 22:08:


                                  That's for sure the ultimate argument Gavin. :-) Agree that logging seems trivial but it is still very frequent and valid use case. Let's make it less trivial then. How about audit logging that is common in financial/payment applications. You better make sure every financial operation is reported. And database is not always target storage for such audit traces. So injected AuditLogger would be very handy in entity beans. If this is lame use case then tell it to our customers. I would love to see their faces. ;-)



                                  CBauer presented an auditing solution IIRC in Bauer/King book.  Also........



                                  The Envers project aims to enable easy auditing/versioning of persistent classes. All that you have to do is annotate your persistent class or some of its properties, that you want to audit, with @Audited. For each audited entity, a table will be created, which will hold the history of changes made to the entity. You can then retrieve and query historical data without much effort.

                                  source: http://www.jboss.org/envers/


                                  So what is it about one of these two solutions that is insufficient for your logging/auditing use case?


                                  Do you need one audit table for all entities or one audit table for each entity?


                                  • 29. Re: Injection into entity beans
                                    hajdi

                                    Arbi Sookazian wrote on Jun 01, 2009 20:39:


                                    I don't think logging by itself (one use case) qualifies as a solid case for allowing DI in entity classes.


                                    Agree. But sure it would be nice to have it. Don't you think? There are other cases. See my and Clint's previous entries.



                                    Although it may be more convenient to have access to DI in an entity class, you can still use JNDI lookup, no?


                                    Sure I can. But we have DI to handle this better. Right? Why don't you use JNDI lookup in services?



                                    It really comes down to whether or not business logic belongs in an entity class.  If it does (in some cases), then perhaps DI should be under consideration.


                                    Even Gavin agrees that that it belongs in some cases. I would argue that it belongs in additional cases. OO is all about it, right?



                                    I mean do you really need to do some calculation, for example, in an entity class?  Why can't that logic happen in a DAO, for example?


                                    Sure it can. But for OO-geeks it seems nice to have method that operates on data located in the same object as data. :-)



                                    The only advantage I see with having the biz logic embedded in an entity class (as a public method), is you don't have to factor that method into an auxiliary helper class that is injected into a SFSB or DAO class everytime it is needed.


                                    That's huge advantage. There are other benefits of OO design though. The are also drawbacks.



                                    So let's say you have a valid case and need to embed the public calculation method in the entity class, do we need access to EntityManager interface directly at this point for CRUD ops?  I hope not. 


                                    In most cases you just access local persistent fields like collections to do that. So no need to access EntityManager.



                                    I think it's better to maintain separation of concerns, but at the same time minimize layering if possible.


                                    What are these concerns that should be separated?



                                    This is one thing I agree on with GKing and one main reason I liked Seam from the beginning (no forced layering and patterns like Struts/EJB2.x!)


                                    Me too. But from my point of view Gavin is insisting on this last artificial layer. :-)