Implement the UserServiceImpl class

Now, we have the tests ready. Let's implement the UserServiceImpl class itself. Here is how it looks:

...
@Service
@Transactional
public class UserServiceImpl implements UserService {

private RegistrationManagement registrationManagement;
private DomainEventPublisher domainEventPublisher;
private MailManager mailManager;

public UserServiceImpl(RegistrationManagement registrationManagement,
DomainEventPublisher domainEventPublisher,
MailManager mailManager) {
this.registrationManagement = registrationManagement;
this.domainEventPublisher = domainEventPublisher;
this.mailManager = mailManager;
}

@Override
public void register(RegistrationCommand command) throws
RegistrationException {
Assert.notNull(command, "Parameter `command` must not be null");
User newUser = registrationManagement.register(
command.getUsername(),
command.getEmailAddress(),
command.getPassword());

sendWelcomeMessage(newUser);
domainEventPublisher.publish(new UserRegisteredEvent(newUser));
}

private void sendWelcomeMessage(User user) {
mailManager.send(
user.getEmailAddress(),
"Welcome to TaskAgile",
"welcome.ftl",
MessageVariable.from("user", user)
);
}
}

As you can see, we apply the @Service annotation and the @Transactional annotation to this class. The name of the @Service annotation was originally defined in Eric Evans's book, Domain-Driven Design. It means that the class with this annotation applied only offers operations for its client. The UserServiceImpl class is stateless. It doesn't hold any internal state. In a DDD application, services are partitioned into three types—Application Services, Domain Services, and Infrastructure Services.

Let's talk a little bit more about these services.

First of all, for Application Services, the following applies:

  • They only coordinate tasks on the model
  • They do not house any business logic
  • They are sometimes designed to shield clients from accessing the domain model
  • They control transactions, in our case by using the @Transactional annotation

One example is our UserServiceImpl class. As you can see, it doesn't care about how to register a user. It replies on the Domain Service, RegistrationManagement, to take care of that. In Spring, the @Service annotation is usually applied to Application Services.

For Domain Services, the following applies:

  • They encapsulate business logic that doesn't naturally fit within a domain object and are not typical CRUD operations, which would belong to a repository

One example is our RegistrationManagement class, which we will discuss shortly.

For Infrastructure Services, the following applies:

  • They typically talk to the external resources, for example, mail servers, databases, messaging queues, cache servers, or third-party RESTful APIs
  • They are not part of the primary problem of the domain model

One example is the implementation of UserRepository and the mail service, which we will create in the next chapter, and which DefaultMailManager depends on.

Back to the code; in this service, we ask Spring to inject its three dependencies via the constructor. Inside the register() method, the first thing we do is to add an assertion to make sure the command parameter can never be null. If it is null, an IllegalArgumentException will be thrown from the Assert.notNull() method. Once the parameter is checked, we call the register() method of RegistrationManagement to register the user. Here, we do not pass the RegistrationCommand instance as the parameter anymore because RegistrationCommand is for clients of Application Services, such as Controller, to use. Inside the Application Core, we avoid using RegistrationCommand so that the internals of the Application Core won't be coupled with the outside.

Once the user has been registered, we send a welcome email and also publish the UserRegisteredEvent domain event so that others who are interested in (subscribed to) this event can take action accordingly. We will skip the details of the sendWelcomeMessage() method for now. You can check the details of the commit. We will talk about sending emails in a later section of this chapter.

For now, we still cannot make the test pass because we haven't created the RegistrationManagement class.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.128.105