A CRUD REST API architecture implemented in Spring Boot

Père, mari, développeur, geek, coffee lover, amateur dans beaucoup de domaines
Hello world!
I am currently working on an web application as a side-project for an association in which I am. This project is a redesign of an existing application written in PHP/HTML/CSS. The current source code is dirty and not maintainable due to a bad level of us when we did the V1 four years ago.
To be able to maintain the system, upgrade it with new features and upgrade its security, I decided to start a new web app which will be a client/server app written respectively in ReactJS and Spring Boot.
Because I don't like to stub HTTP requests when I am working on a website, I started by the back-end.
The back-end, it consists in a classical CRUD API. I want to go quite fast (but not dirty this time). To make it quickly, I decided to create and implement a small CRUD architecture which allows me to easily add a new path with its entity and its service.
After some reflection, I got this architecture:
It is small but it works well and do so without code duplication.
To reduce at the maximum the dependencies, I defined 2 main interfaces with their default abstract implementation and 1 abstract class representing the minimum structure for an entity.
With this 5 objects, I am able to define quickly (if there is no special behavior) a new API linked to an entity. AbstractCrudController and AbstractCrudService have default implementations that each final implementation take. For the CrudController case, the implementation only has to map each method to the right request path for SpringMVC.
Let's see an example of an implementation I did with this architecture:
Example
In my API, I have a notion of Articles which are defined like this:
public class Article extends AbstractEntity<Long> {
private Long id;
private String title;
private String content;
private String author;
private OffsetDateTime publicationDate;
private OffsetDateTime lastEditionDate;
private String summary;
private String tags;
}
Notes: To save some space, I removed here the lombok and JPA annotations.
The ArticleService is very simple:
@Service
public class ArticleService extends AbstractCrudService<Article, Long> {
@Autowired
public ArticleService(JpaRepository<Article, Long> repository) { super(repository); }
}
And the ArticleController is not very complex too:
@RestController
@RequestMapping("/api/v1/articles")
public class ArticleController extends AbstractCrudController<Article, Long> {
@Autowired
public ArticleController(CrudService<Article, Long> service) { super(service); }
@GetMapping("")
@Override
public ResponseEntity<List<Article>> findAll() {
return super.findAll();
}
@GetMapping("/{id}")
@Override
public ResponseEntity<Article> findById(@PathVariable("id") Long id) {
return super.findById(id);
}
@PostMapping("")
@Override
public ResponseEntity<Article> create(@RequestBody Article article) {
return super.create(article);
}
@PutMapping("/{id}")
@Override
public ResponseEntity<Article> update(@PathVariable("id") Long id, @RequestBody Article newArticle) {
return super.update(id, newArticle);
}
@DeleteMapping("/{id}")
@Override
public ResponseEntity<Article> deleteById(@PathVariable("id") Long id) {
return super.deleteById(id);
}
}
I think, one day, I will talk about this architecture in details to allow you to fork and reuse it easily. But, before, I prefer to finish this web application I have to do and I prefer to present to you the architecture when I have packaged it into a library you can use from my github packages or from maven central.
This was a quite messy article. But I hope you liked it. I think I will try to let you know some news about this website which is the first one I have to mount from scratch and alone. Let me know what you think about that in comment!
It was Macdrien for Macnews, Good bye world.


