Where should business logic exist (and what is it?), And how to do it with Spring?

I just read this article:

http://www.tutorialized.com/view/tutorial/Spring-MVC-Application-Architecture/11986

which I find great. This explains the architecture of the layer beautifully, and I was glad that the architecture I work with is what it describes.

But there is one thing that I don't seem to get:

First: what is business logic and what is not? In the article, he says (and he’s not the only one) that business logic should go in the domain model. Therefore, the Account class must have an activate() method that knows how to activate an Account . In my opinion, this is likely to require some work of perseverance. But the domain model should not be dependent on the DAO. Only the service level should know about the DAO.

So this is business logic, what can the domain object itself do? Like the activate() method, the active property will be set to true , and also set the dateActivated property to new Date() , and then perform a utility task to call account.activate() and the second dao.saveAccount(account) ? And what is needed for external dependencies? This is what I have been doing so far mostly.

 public AccountServiceImpl implements AccountService { private AccountDAO dao; private MailSender mailSender; public void activateAccount(Account account) { account.setActive(true); account.setDateActivated(new Date()); dao.saveAccount(account); sendActivationEmail(account); } private void sendActivationEmail(Account account) { ... } } 

This is in contrast to what he says, I think not?

What I also don't get is an example of how to have Spring wired domain objects such as Account . What is required if the account sends its email on its own.

Given this code:

 import org.springframework.mail.MailSender; import org.springframework.mail.SimpleMailMessage; public class Account { private String email; private MailSender mailSender; private boolean active = false; public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public void setMailSender(MailSender mailSender) { this.mailSender = mailSender; } public void activate() { if (active) { throw new IllegalStateException("Already active"); } active = true; sendActivationEmail(); } private void sendActivationEmail() { SimpleMailMessage msg = new SimpleMailMessage(); msg.setTo(email); msg.setSubject("Congrats!"); msg.setText("You're the best."); mailSender.send(msg); } } 

If I use Hibernate, I could use DependencyInjectionInterceptorFactoryBean to connect mailSender . If I use JDBC instead, would I really write bulky code? In addition, also, when I create a new instance for the Account in the MVC, it can be said that it fills it with a model

  BeanFactory beanFactory = new XmlBeanFactory( new ClassPathResource("chapter3.xml")); Account account = new Account(); account.setEmail(" email@example.com "); ((AutowireCapableBeanFactory)beanFactory).applyBeanPropertyValues( account, "accountPrototype"); account.activate(); 

It is not reliable and very bulky, no? I had to ask myself where this object was created, whenever I see an instance of the Account. Plus, if I went with this approach: I do not have a single appContext.xml that I could pass, but several, one for perseverance, one for configuring the service. How can I do it? Plus, would this create a whole new context every time such an instance is created or am I missing something?

Is there a better solution for this?

Any help is greatly appreciated.

+4
source share
1 answer

I think that sending an activation email action is not part of the business layer here, your domain logic is an account activation action, this part of the logic should live in a DomainObject called Account ( activate() method). The email action to activate sending is part of the infrastructure or application layers.

A service is an object that processes an account activation request and connects the business layer and others. The service accepts this account, activates them and performs an email action to activate the activation of MailSenderService or something like that.

Short sample:

 public AccountServiceImpl implements AccountService { private AccountDAO dao; private MailSenderService mailSender; public void activateAccount(AccountID accountID) { Account account = dao.findAccount(accountID); .... account.activate(); dao.updateAccount(account); .... mailSender.sendActivationEmail(account); } } 

The next step I can offer is a complete separation of the business layer and the infrastructure layer. This can be obtained by entering a business event. The service should no longer perform an action to send e-mail, it creates an event that notifies other layers about account activation.

In Spring, we have two tools for working with the ApplicationEventPublisher and ApplicationListener events.

A quick example: a service that publishes domain events:

 public AccountActivationEvent extends ApplicationEvent { private Account account; AccountActivationEvent(Account account) { this.account = account; } public Account getActivatedAccount() { return account; } } public AccountServiceImpl implements AccountService, ApplicationEventPublisherAware { private AccountDAO dao; private ApplicationEventPublisher epublisher; public void setApplicationEventPublisher(ApplicationEventPublisher epublisher) { this.epublisher = epublisher; } public void activateAccount(AccountID accountID) { Account account = dao.findAccount(accountID); .... account.activate(); dao.updateAccount(account); .... epublisher.publishEvent(new AccountActivationEvent(account)); } } 

And a domain event listener, at the infrastructure level:

 public class SendAccountActivationEmailEventListener implements ApplicationListener<AccountActivationEvent> { private MailSenderService mailSender; .... public final void onApplicationEvent(final AccountActivationEvent event) { Account account = event.getActivatedAccount(): .... perform mail ... mailSender.sendEmail(email); } } 

Now you can add other types of activation, logging, other infrastructure support without changes and pollute your domain (business).

And, you can learn more about Spring events in the documentation .

+5
source

All Articles