Announcement Announcement Module
No announcement yet.
Domain Object Design Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Domain Object Design

    I'm deep in my first Spring/Hibernate project and have a question regarding domain object design.

    I first designed our datamodel, wrote the hibernate mappings, and then built a businesslogic front to a bunch of DAOs that could persist each domain object. This all works great, and up to this point, Spring handled the DAO/businesslogic DI and Hibernate sorta managed the domain model/persistence side of things.

    Enter the web layer. Today it took me quite a while to figure out why I couldn't add a new object to my database using a SimpleFormController: Spring thinks every one of my data objects is a simple JavaBean (they are), but it also assumes all getters and setters are public (they aren't).

    I was trying to avoid two things in my design:

    1. Anemic Domain Model: If I wanted complex logic in my code (aka children adding themselves to parents' collections, certain validation strict enough to belong in the model itself, etc.), I'd make a public setter for human use when creating detached domain objects, and a private setter which is stupid and just sets the property.

    2. Mutable objects: If I wanted certain properties to be immutable, I'd make the setters private and only allow the properties to be set through a public constructor... Hibernate could of course use a package constructor and the private setters.

    My problem with Spring MVC is that it can't use the private setters for my objects, so it seems that I should make them public, breaking the immutability of the fields.

    SO: What's the best design? Completely stupid objects with no logic at all? Just a bunch of getters and setters? This seems incredibly moronic.

    Should I ditch all my complicated logic (for use by humans) and just make all the stupid getters/setters (currently for use by Hibernate) public?

    Help is appreciated!

    Paralyzed by Design

  • #2
    I prefer using some kind of DTO/Command/Backing object that contains all data for a specific action (creation of new items, updates etc):

    class NewPersonCommand{
       String firstname,lastname;phoneNumber;
    The Controller can bind to this object because everything is exposed (maybe getters/setters or just public fields).

    In the Service you can do this:

    class NewPersonService{
         PersonDao personDao;
         Person create(NewPersonCommand command){
               Person person = new Person(command.getFirstname(),....)
               return person;
    Transactional boundaries are also 100% clear in this example, something that often is completely unclear when domain objects are exposed in the controller (also possible location for database isolation problems btw... lost update for example).

    Using such a command object also depends a little on the application: if there is almost no domain logic... I can imagine that it is a lot of stupid work.
    Last edited by Alarmnummer; Apr 7th, 2008, 02:30 AM.


    • #3
      Or you can tell spring to use reflection instead of getter/setters.

      Override the 'useDirectFieldAccess' method in your Controller and return true. That way spring will also use reflection on your objects to access fields.


      • #4

        This is pretty much exactly what I was looking for. I have a decent bit of domain logic, so I think implementing some other form backing object to transfer user-entered data back and forth isn't a terrible idea (it's as simple as making a bunch of beans and hitting "generate getters and setters", I suppose).

        Everything you stated applies: I'll be able to use my logic-enabled domain objects while at the same time having more clarity with regards to transactional boundaries.

        The second reply is also very helpful; this is something I was hoping I could do if I wanted to avoid the first solution. I'm worried that implementing a bunch of backing/control objects will result in object proliferation, so I was hunting for a solution like this. Thanks for the help.

        Does the second solution require CGLIB or anything weird, or does it rely on standard java reflections?


        • #5
          One more question

          Just thought of a related question.

          In the first case above, validators could be written to test the form-backing object for completeness: is every field there, are phone numbers really phone numbers, are emails really emails, etc.

          But then there's no real validator written for the actual domain objects.

          I sorta wanted to be able to write:

          (a) domain objects that are complicated enough that you can't create an invalid graph (and also have immutable properties to keep the equals() semantics sane when they're in a set), and:

          (b) domain object validators that (1) get called by interceptors by the DAO layer before any set*() command, (2) are exposed via some web interface for AJAX calls, and (3) can be used in the view layer by Spring MVC.

          But if I'm using a special value/DTO/backing object for carrying form data from the view, it seems like I'd only be able to prompt the user for corrections on that object, not on more complicated, domain-based errors.

          And I DO have some reservations about having a bunch of classes that essentially do nothing (the value/backing objects proposed for the forms).


          • #6
            How can I set 'useDirectFieldAccess' to 'true' by using @Controller?


            • #7
              Originally posted by Keiti View Post
              How can I set 'useDirectFieldAccess' to 'true' by using @Controller?
              I would like to know the answer to this too, please.


              • #8
                Domain Object Design

                I am also in the queue...Can anyone reply to this question? We are waiting.........!!!!!!!


                • #9
                  Here is the answer:

                  Originally posted by kevinkx7 View Post
                  I am also in the queue...Can anyone reply to this question? We are waiting.........!!!!!!!