Announcement Announcement Module
Collapse
No announcement yet.
Use Hibernate Entities in the web layer? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Use Hibernate Entities in the web layer?

    Hello,

    I wonder how to handle my entities in a complete Spring application (persistence, logic, web layer).

    I have Hibernate generating entities and corresponding mapping files for me. Now the web layer will work with JSF and managed beans. Should I create DTOs out of the entities to be given to the JSF pages? Otherwise I would have to share the entities with the web layer.

    Would this be a good approach since entities are nothing less than POJOs? But changing entities means changing the web layer because it is coupled.

    Any suggestions please?

  • #2
    I just found an interesting thread about this ... seems as if there would be no reason to create DTOs anymore, when we do not use layers that run on different machines.

    http://forum.springframework.org/sho...ransfer+object

    Comment


    • #3
      To DTO or not to DTO ...

      This is a long-running and on-going debate with zealots on both sides of the camp. The forum mentioned in the previous post is pretty representative of the various opinions out there, which range from "Use DTOs or die!" to "DTOs are the work of Satan".

      I'm an advocate of "use the approach that solves your needs". Largely this depends on whether you have a single, web-only client or if you have a distributed application (e.g. a desktop application that makes remote calls to the middle tier by RMI/Hessian/Burlap/etc).

      From a purity view, the 'correct' approach is to use DTO's as it completely decouples your middle tier from your presentation tier. Those that argue that the use of DTOs 'has no conceivable benefit' have missed two fundamental consequence of exposing your Hibernate entities to the presentation layer:

      1. Security is now partially external to your business layer. The presentation layer now has the responsibility of deciding whether a certain attribute (an Employee's email address or birthday for example) should be displayed to the user or not. With a DTO you can restrict this information from ever reaching the presentation tier and so security is absolutely enforced by the middle-tier as it 'should' be.

      2. Transactions are now external to your business layer. Since the presentation tier is now potentially triggering database calls, you need to keep your transaction (or database session at least) open. Commits/rollbacks are now outside of the middle-tier. (Generally you only do reads in your presentation layer so this is not a big deal - definitely avoid doing 'writes'!)

      From a practical point of view however, both of these factors are generally not a problem for a standard, well-thought-out web-app. Since the presentation layer is server side, it's not really such a problem to let transactions and security seep into the controllers and JSPs.

      There is a reasonable amount of extra work and code (though an IDE like JetBrains IDEA significantly helps here!) and even some minor performance/memory considerations involved with DTOs, so if you know you're only going to have a standard web interface go with the exposed Hibernate entities and the OpenSessionInView approach.

      If you have a remote client (Swing, mobile phone, non-Java) or some distributed services (B2B) then consider using DTOs. The use of ORM object graphs (i.e. hibernate objects and their links to other objects) causes nothing but trouble when you try to serialize beans down the wire.

      Hope that helps,
      zonski

      Comment


      • #4
        When adopting a Domain Driven Design approach, domain objects should not be exposed to web tier, as argued in the following blog post:
        http://ozgwei.blogspot.com/2007/06/d...passed-to.html

        Comment


        • #5
          Thanks both of you.

          Very interesting aspects. I did not come to an end yet. I will thouroughly think about the points mentioned. For me it is just a web application without remote calls. Still I have to think about it carefully.

          Comment


          • #6
            Originally posted by zonski View Post
            I'm an advocate of "use the approach that solves your needs".
            I like that camp a lot more

            Originally posted by zonski View Post
            1. Security is now partially external to your business layer.
            I agree. Other implementation technique to restrict access is the usage of special presentation layer interfaces together with proxies, so cast won't work.

            Originally posted by zonski View Post
            2. Transactions are now external to your business layer. Since the presentation tier is now potentially triggering database calls, you need to keep your transaction (or database session at least) open. Commits/rollbacks are now outside of the middle-tier.
            Here I don't agree. What you describe is Open Session In View. Nobody forces you to use it. I restrict my transactions to the business layer. There are no database calls from the presentation layer. I don't say this solution has other flaws: I need to either eager load some associations or provide some initializeAssociation() methods on my service. At least I prefer this solution much more than OSIV since it's more controllable.

            Jörg

            Comment


            • #7
              Quote:
              Originally Posted by zonski
              2. Transactions are now external to your business layer. Since the presentation tier is now potentially triggering database calls, you need to keep your transaction (or database session at least) open. Commits/rollbacks are now outside of the middle-tier.

              Here I don't agree. What you describe is Open Session In View. Nobody forces you to use it. I restrict my transactions to the business layer. There are no database calls from the presentation layer. I don't say this solution has other flaws: I need to either eager load some associations or provide some initializeAssociation() methods on my service. At least I prefer this solution much more than OSIV since it's more controllable.
              Yep, that's definitely a good third option - use some form of eager loading to populate only those fields that you are going to use and then close the transaction before handing the Entity out to the presentation layer. This solves the issue of security, transactions and business rules seeping into your presentation layer.

              It does come at the price of a weaker service API and compiler support (i.e. if you forget to eager load Person.emailAddress and you try to use it you won't find out until runtime). With OSIV you avoid this problem but have the other transaction problems mentioned. With DTO you can avoid both these problems but with the hassle of extra code.

              Unfortunately there's no single solution that wins out. It comes down to weighing off the benefits and hassles of each against your specific requirements.

              Comment


              • #8
                I think I will use DTOs instead of entities in the presentation layer. The other approaches somehow smell. If it is only the extra code to maintain which makes this solution "worse" I will however take this approach since I am generating my entities. I think I'll find a way to generate the DTOs as well.

                Thank you!

                Comment


                • #9
                  Keep an eye on the ROO (Real Object Oriented) project created by Ben Alex, the creator of Acegi Security.

                  In a ROO application, DTOs are generated (and maintained in the lifecycle) according to the domain model.

                  Comment


                  • #10
                    Originally posted by Rapthor View Post
                    I think I will use DTOs instead of entities in the presentation layer. The other approaches somehow smell. If it is only the extra code to maintain which makes this solution "worse" I will however take this approach since I am generating my entities. I think I'll find a way to generate the DTOs as well.
                    Why do you feel that other approaches somehow smell ? I am all for using domain entities in the presentation layer. If you read the Expert Spring MVC book or the Hibernate book, both of them encourage using smart domain models and reusing domain objects in the presentation layer. The Spring MVC book recommends using domain objects as command objects and the Hibernate book recommends doing away with the behviorless JSF backing beans in favor of smart POJOs in SEAM.

                    Unless of course, you have a remoting scenario - still there u can use EJBs and container managed remoting. Unless there is a forceful enough reason, I would not go the DTO way. Too much boilerplates .. objects without behavior .. :-(

                    My 2 cents.
                    - Debasish

                    Comment


                    • #11
                      Debasish, I have plenty of respects for you. However, I have to disagree on this.

                      One thing that I have kept in mind is that Spring MVC and Hibernate's development started in the dark age of EJB 2.0, which forced developers to build enterprise applications with anaemic domain models using transaction scripts. At that time, many people equalled Java Beans to POJOs and domain classes. Unfortunately that was misleading... In a rich domain model, typically entity classes are NOT Java beans, because providing setter methods can easily break invariants of a domain class. Since then, Domain Driven Design has gained wider adoption and recognition.

                      In a recent presentation "Are We There Yet?", Rod Johnson, the founder of Spring, asked the attendees a question: when working with Hibernate, who use property access and who use field access? Those who use property access are persisting DTOs, or, using an anaemic domain model. I cannot recall the exact words, but that's basically what he said and meant.

                      I would like to add: that those who use domain classes as command objects in the web layer are working with an anaemic domain model.

                      For example, in one of the projects I have worked on, there is a Fraud class, which has three fields: fraudPaymentDate, fraudPaymentAmount, amountRecovered and dateRecovered. The invariants regarding these three fields are:
                      1) amountRecovered must not exceed fraudPaymentAmount.
                      2) When amountRecovered is $0.00, dateRecovered must be null.
                      3) When amount Recovered is greater than $0.00, dateRecovered must be present, in the past and must not predate fraudPaymentDate.

                      If this class provides setter methods for all these fields and is directly used as a command object, there is no way not to break invariants in the binding phase of Spring MVC:
                      If setAmountRecovered() is invoked with a non-zero amount before setDateRecovered(), then invariant no. 3 is broken.
                      If setDateRecovered() is invoked before setAmountRecovered(), then invariant no. 2 is broken.

                      Therefore, a command object typically does not maintain data integrity. Usually a validate() method is provided to the client to ensure data integrity AFTER the binding.

                      There is one big drawback with using validate() method: the domain object relies on its client to call its validate() method to check data integrity or on a trigger from an event such as save(). However, when using Hibernate, domain objects can be persisted transparently without the domain object being persisted beware of the fact that it's being persisted. Thus, a corrupted domain object can easily be persisted to database.

                      When using a rich domain model with DTO, this problem is solved:
                      The DTO can be used as a command object in the web layer and passed to the service tier. The UpdateService can construct two value objects fraudPaymentInfo, which contains both fraudPaymentDate and fraudPaymentAmount, and recoveryInfo, which contains both amountRecovered and dateRecovered, according to the data in the DTO and invoke the Fraud object's updatePaymentInfo() and updateRecoveryInfo(). Invariants are always maintained in the process.

                      http://ozgwei.blogspot.com/2007/06/i...tities-in.html

                      Comment


                      • #12
                        Originally posted by ozgwei View Post
                        If this class provides setter methods for all these fields and is directly used as a command object, there is no way not to break invariants in the binding phase of Spring MVC:
                        If setAmountRecovered() is invoked with a non-zero amount before setDateRecovered(), then invariant no. 3 is broken.
                        If setDateRecovered() is invoked before setAmountRecovered(), then invariant no. 2 is broken.

                        Therefore, a command object typically does not maintain data integrity. Usually a validate() method is provided to the client to ensure data integrity AFTER the binding.
                        Let me try to address one of your concerns : setter methods in domain objects break invariants, if used from the presentation layer.

                        Typically for a domain object, there is a top level contract (Java interface or abstract class) and there is an implementation. The setter methods are part of the implementation only and are NOT present in the contract. Expose the domain contract to the presentation layer in general - by this the presentation layer will have access to the *domain* methods only. Using the domain methods no one will be able to violate any contract. Expose the implementation class *only* to the MVC component. Use aspects to prevent usage of the implementation class by anyone other than the MVC framework. This way, you basically give the domain object a two-faced role - the implementation setters are only for the MVC framework.

                        Maybe I should blog more about this :-)

                        Cheers.
                        - Debasish

                        Comment


                        • #13
                          This has been a long documented debate. The presentation of ROO from Ben Alex at SpringONE showed a DTO approach, but it seemed really nice! The conversion was all done for you so there was zero effort. There were also some compelling reasons for going this way.
                          Last edited by karldmoore; Aug 29th, 2007, 11:10 AM.

                          Comment


                          • #14
                            Originally posted by karldmoore View Post
                            This has been a long documented debate. The presentation of ROO from Ben Alex at SpringONE showed a DTO approach, but it seemed really nice! The conversion was all done for you so there was zero effort. There were also some compelling reasons for going this way.
                            Karl -

                            Is there any pointer / documentation available on ROO ? I would like to see more of this. As a first impression, I think, irrespective of whether DTOs are being generated or hand-written, we have more classes. And most importantly dumb data holders as DTOs. But I really should not be commenting without having a look at ROO.

                            Cheers.
                            - Debasish

                            Comment


                            • #15
                              Originally posted by ozgwei View Post
                              Debasish, I have plenty of respects for you. However, I have to disagree on this.
                              Hi Alex,

                              I agree with Debasish.
                              As already commented in your blog, I also use setters/getters only in implementation classes (so the code using interfaces will never see them), and when needed I use specialized view interfaces introduced into domain objects via AOP by using Spring Modules XT Introductors.

                              Why do you think that such an approach still force to use an anemic model?

                              Cheers,

                              Sergio B.

                              Comment

                              Working...
                              X