views:

264

answers:

2

In a web server project with a rich domain model (application logic is in the model, not in the services) how do you handle injecting the dependencies into the model objects? What are your experiences?

Do you use some form of AOP? Like Springs @Configurable annotation? Load time or build time weawing? Problems you encountered?

Do you use manual injection? Then how do you handle different instantiation scenarios (creating of the objects through an library [like Hibernate], creating objects with "new" ...)?

Or do you use some other way of injecting the dependencies?

+1  A: 

To keep my domain objects clean I avoid using injection on the entities/aggregates/value objects and rather put those in the services or repositories if needed.

For this we used normal Spring constructor injection to ease testing.

If you need to inject something into your entities one suggestion could be to write a builder or factory and inject what you needed there instead.

PålOliver
+1  A: 

We use Spring's @Configurable (along with regular new operator) which works like a charm. No more anemic domain models. Finally, this is much more object oriented design, isn't it:

Person person = new Person(firstname, lastname);
// weird
peopleService.save(person);
// good (save is @Transactional)
person.save();

Mail mail = new Mail(to, subject, body);
// weird
mailService.send(mail);
// good (send is @Transactional)
mail.send();

We haven't done any performance comparison though. So far, we simply haven't felt the need to do so.

EDIT: that's how the person class would look like:

@Configurable("person")
public class Person {
    private IPersonDAO _personDAO;
    private String _firstname;
    private String _lastname;

    // SNIP: some constructors, getters and setters

    @Transactional(rollbackFor = DataAccessException.class)
    public void save() {
        _personDAO.save(this);
    }

    @Transactional(readOnly = true)
    public List<Role> searchRoles(Company company) void{
        return _personDAO.searchRoles(this, company);
    }

    // it's getting more interesting for more complex methods
    @Transactional(rollbackFor = DataAccessException.class)
    public void resignAllRoles(Company company) {
        for (Role role : searchRoles(company)) {
            role.resign();
        }
    }
}

// the implementation now looks like this
personService.getPerson(id).resignAllRoles(company);

// instead of this
roleService.resignAll(personService.searchRoles(personService.getPerson(id), company));

And that's the Spring config:

<context:spring-configured />
<bean id="person" class="org.example.model.Person" lazy-init="true">
  <property name="personDAO" ref="personDAO" />
</bean>

Note: as you see, there are still services around, e.g. to search for objects (personService.getPerson(id)) but all methods that operate on a passed object (e.g. a person) are moved to that class itself (i.e. person.save() instead of personService.save(person)). The method itself stays the same and works with any underlying data access layer (pure JDBC, Hibernate, JPA, ...). It has simply moved where it belongs.

sfussenegger
How do you persist your entities? Plain JDBC? Because this strategy would not work if you use hibernate!?
Arne
@Arne of course it would. see my edit for an example. the idea is that you simply inject the DAO into the domain objects. Methods are then moved from services to the class (typically all methods that take an object of this class as argument). Everything else stays the same.
sfussenegger