The new Certification Class of Learn Spring Security is out:

>> CHECK OUT THE COURSE

1. Overview

In this quick article, we’re going to do something new. We’re going to evolve an existing REST Spring API and make it use Command Query Responsibility Segregation – CQRS.

The goal is to clearly separate both the service and the controller layers to deal with Reads – Queries and Writes – Commands coming into the system separately.

Keep in mind that this is just an early first step towards this kind of architecture, not “an arrival point”. That being said – I’m excited about this one.

Finally – the example API we’re going to be using is publishing User resources and is part of our ongoing Reddit app case study to exemplify how this works – but of course, any API will do.

2. The Service Layer

We’ll start simple – by just identifying the read and the write operations in our previous User service – and we’ll split that into 2 separate services – UserQueryService and UserCommandService:

public interface IUserQueryService {

    List<User> getUsersList(int page, int size, String sortDir, String sort);

    String checkPasswordResetToken(long userId, String token);

    String checkConfirmRegistrationToken(String token);

    long countAllUsers();

}
public interface IUserCommandService {

    void registerNewUser(String username, String email, String password, String appUrl);

    void updateUserPassword(User user, String password, String oldPassword);

    void changeUserPassword(User user, String password);

    void resetPassword(String email, String appUrl);

    void createVerificationTokenForUser(User user, String token);

    void updateUser(User user);

}

From reading this API you can clearly see how the query service is doing all the reading and the command service isn’t reading any data – all void returns.

3. The Controller Layer

Next up – the controller layer.

3.1. The Query Controller

Here is our UserQueryRestController:

@Controller
@RequestMapping(value = "/api/users")
public class UserQueryRestController {

    @Autowired
    private IUserQueryService userService;

    @Autowired
    private IScheduledPostQueryService scheduledPostService;

    @Autowired
    private ModelMapper modelMapper;

    @PreAuthorize("hasRole('USER_READ_PRIVILEGE')")
    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    public List<UserQueryDto> getUsersList(...) {
        PagingInfo pagingInfo = new PagingInfo(page, size, userService.countAllUsers());
        response.addHeader("PAGING_INFO", pagingInfo.toString());
        
        List<User> users = userService.getUsersList(page, size, sortDir, sort);
        return users.stream().map(
          user -> convertUserEntityToDto(user)).collect(Collectors.toList());
    }

    private UserQueryDto convertUserEntityToDto(User user) {
        UserQueryDto dto = modelMapper.map(user, UserQueryDto.class);
        dto.setScheduledPostsCount(scheduledPostService.countScheduledPostsByUser(user));
        return dto;
    }
}

What’s interesting here is that the query controller is only injecting query services.

What would be even more interesting is to cut off the access of this controller to the command services – by placing these in a separate module.

3.2. The Command Controller

Now, here’s our command controller implementation:

@Controller
@RequestMapping(value = "/api/users")
public class UserCommandRestController {

    @Autowired
    private IUserCommandService userService;

    @Autowired
    private ModelMapper modelMapper;

    @RequestMapping(value = "/registration", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    public void register(
      HttpServletRequest request, @RequestBody UserRegisterCommandDto userDto) {
        String appUrl = request.getRequestURL().toString().replace(request.getRequestURI(), "");
        
        userService.registerNewUser(
          userDto.getUsername(), userDto.getEmail(), userDto.getPassword(), appUrl);
    }

    @PreAuthorize("isAuthenticated()")
    @RequestMapping(value = "/password", method = RequestMethod.PUT)
    @ResponseStatus(HttpStatus.OK)
    public void updateUserPassword(@RequestBody UserUpdatePasswordCommandDto userDto) {
        userService.updateUserPassword(
          getCurrentUser(), userDto.getPassword(), userDto.getOldPassword());
    }

    @RequestMapping(value = "/passwordReset", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    public void createAResetPassword(
      HttpServletRequest request, 
      @RequestBody UserTriggerResetPasswordCommandDto userDto) 
    {
        String appUrl = request.getRequestURL().toString().replace(request.getRequestURI(), "");
        userService.resetPassword(userDto.getEmail(), appUrl);
    }

    @RequestMapping(value = "/password", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    public void changeUserPassword(@RequestBody UserchangePasswordCommandDto userDto) {
        userService.changeUserPassword(getCurrentUser(), userDto.getPassword());
    }

    @PreAuthorize("hasRole('USER_WRITE_PRIVILEGE')")
    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    @ResponseStatus(HttpStatus.OK)
    public void updateUser(@RequestBody UserUpdateCommandDto userDto) {
        userService.updateUser(convertToEntity(userDto));
    }

    private User convertToEntity(UserUpdateCommandDto userDto) {
        return modelMapper.map(userDto, User.class);
    }
}

A few interesting things are happening here. First – notice how each of these API implementations is using a different command. This is mainly to give us a good base for further improving the design of the API and extracting different resources as they emerge.

Another reason is that when we take the next step, towards Event Sourcing – we have a clean set of commands that we’re working with.

3.3. Separate Resource Representations

Let’s now quickly go over the different representations of our User resource, after this separation into commands and queries:

public class UserQueryDto {
    private Long id;

    private String username;

    private boolean enabled;

    private Set<Role> roles;

    private long scheduledPostsCount;
}

Here are our Command DTOs:

  • UserRegisterCommandDto used to represent user registration data:
public class UserRegisterCommandDto {
    private String username;
    private String email;
    private String password;
}
  •  UserUpdatePasswordCommandDto used to represent data to update current user password:
public class UserUpdatePasswordCommandDto {
    private String oldPassword;
    private String password;
}
  • UserTriggerResetPasswordCommandDto used to represent user’s email to trigger reset password by sending an email with reset password token:
public class UserTriggerResetPasswordCommandDto {
    private String email;
}
  • UserChangePasswordCommandDto used to represent new user password – this command is called after user use password reset token.
public class UserChangePasswordCommandDto {
    private String password;
}
  • UserUpdateCommandDto used to represent new user’s data after modifications:
public class UserUpdateCommandDto {
    private Long id;

    private boolean enabled;

    private Set<Role> roles;
}

4. Conclusion

In this tutorial, we laid the groundwork towards a clean CQRS implementation for a Spring REST API.

The next step will be to keep improving the API by identifying some separate responsibilities (and Resources) out into their own services so that we more closely align with a Resource-centric architecture.

Go deeper into Spring Security with the course:

>> LEARN SPRING SECURITY

  • SwapnilShah

    Hi, Instead of writing from the core the CQRS way of architecture, cannot spring itself has some internal librariy or we can us Axon from allard Buijze at Trifork. Does spring 5 M1 has inbuilt CQRS . Why we are now going to reinvent the wheel everytime some new architecture comes up. How can these be used in a distributed Event Sourcing?.

    • Hey Shah – that Axon talk is actually on my watch list this weekend.
      Spring 5 will come with very interesting primitives for doing a CQRS implementation, but I would say that it has build-in CQRS.
      As for reinventing the wheel, I would say that there are some interesting solutions (such as Axon) out there, but the space is certainly not mature yet, and so a simple manual implementation can still be quite powerful.
      Cheers,
      Eugen.

      • SwapnilShah

        Hi
        The point i am trying to make is why not make programming less miserable ,in java world its a chaos and requires lot more effort and pain.if we add in frameworks for each layers its a hell.
        Why cant spring make less complex and less verbose.
        See how others languages like python or perl makes working with streams, reactive breeze.

        Its less complicated to manage monitor debug in the end.

        If you add iot, AI NLP its lot more effort in java Scala JVM dependent world.

        • Again, I’m not saying – don’t use Axon. If it solves the problem, of course – use it.
          I’m just saying – it’s not the only way to go. Hope that makes sense.
          Cheers,
          Eugen.

          • SwapnilShah

            Hi
            Does cqrs events help in blockchain technology.
            Spring is great, but not fit for all approaches.
            But i am looking forward to your post on something on lines of axon.

          • That’s a very interesting question. CQRS specifically – no, but Event Sourcing, which is closely connected to CQRS is built on lots of the same principles as a blockchain.
            As for Axon – I do have it in mind for 2017.
            Hope that helps. Cheers,
            Eugen.

    • SwapnilShah

      Eugen,

      For making one own apps with an idea on Android and
      other platforms, does the whole spring stack justify. I have few
      SME{Small scale enterpreneurs} looking at starting their own firm with
      great SAAS products. In that parlence which will be good fit, Whole
      stack like METEOR or AngularJs+Node stack.?. Can we have some kind of Design Thinking with Drag and Drop options rather than codding with FW. Does Dropwizard and Play help.

      • Well Shah, that’s not an easy question to answer (and it’s also beyond the scope of this article here, so let’s take the conversation to email after this comment).
        There are certainly lots of good stacks out there, and – beyond a certain point – it stops becoming a question of what’s the right one.
        In my experience, once the top stacks in all ecosystems (Java, Ruby, whatever) do check all the right boxes, and the real question is – where do you or your team have the most experience, and how easy it is to find developers that understand that particular stack well.
        So, in this case, yes, Spring certainly is a good way to go – it’s both very mature but also very much actively developed and forward looking. And of course there’s a huge number of developers out there that are well-versed in Spring.
        Now – is it THE best way to go? As was saying before – that will depend on your experience or the experience of your team.
        Hope that helps. Cheers,
        Eugen.