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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With