This is a simple Springboot project for a REST API
In this application you can find examples of:
- A simple CRUD Rest Spring Controller
- Incapsulated business logic (a little anemic in this case) in service classes, decoupled from controllers using Inversion Of Control
- JPA Entities
- Springdata JPA Repositories
- Validation of request bodies using Hibernate Validator
- H2 on memory/file database for fast develop!
- A simple markdown file!
A controller is implemented (here, in this project) in 2 Java files:
- The interface
- The concrete class
In this project I used the interface only to define the paths of my API. It's really easy to start a new project just by shaping the endpoints of the API. Try to keep in mind that frequently you're not the only one consuming it! Keep it predictable and use conventional paths and http methods!
@RequestMapping("corsi")
public interface CorsoController {
@GetMapping
Collection<Corso> list();
@GetMapping("{id}")
ResponseEntity<Corso> findById(@PathVariable UUID id);
...
}
Map a rest controller using plural nouns of the entities you're going to expose and be coherent with HTTP methods. i.e.:
- GET - return a list or a single entity
- POST - create a new entity
- DELETE - delete an entity
- PUT - rewrite an existing entity
I usually use this tier of the application to:
- validate request bodies
- decouple services from controllers using dependency injection (I recommend using constructor injection... stop using @Autowire like 10 years ago)
- manipulate service results to produce a better output for the consumer of the service (eventually)
Services are java classes used to represent out business logic. Usually those classes could contain:
- complex checks
- calculations
- usages of repositories methods
Our data representation!
@Entity
@Data
public class Corso {
@Id
@Column(name = "cod_corso", length = 36)
private UUID id;
@Column(name = "nome_corso", nullable = false)
private String nome;
@Column(name = "des_corso", nullable = false)
private String descrizione;
@ManyToMany(mappedBy = "corsiFrequentati")
@JsonBackReference
private Collection<Soldato> soldatiCheHannoFrequentato;
@ManyToMany(mappedBy = "corsiInCorso")
@JsonBackReference
private Collection<Soldato> soldatiCheStannoFrequentando;
}
Did you ever have to write a DAO manually?? Well, forget about it!
Springdata will generate the implementation for you! All it needs is an interface with your DAO behaviour...
public interface CorsoRepository extends JpaRepository<Corso, UUID> {
List<Corso> findAllByNome(String nome);
}
Many times I've found snippet of entities with validations metadata. Why mix data layer and controller layer?
Keep you entities clean and create brand new POJOs for validation:
@Getter
@Setter
public class CorsoBody {
@NotBlank(message = "nome corso obbligatorio")
private String nome;
@NotBlank(message = "descrizione corso obbligatoria")
private String descrizione;
}