Sto costruendo un'API REST per eseguire operazioni CRUD su un database. Il mio stack provvisorio è Jersey, Spring, Spring Data, JPA e Hibernate. Sto anche usando jersey-spring per fornire istanze della classe di risorse in modo che Spring possa autoprodurle.Come posso implementare questa API REST e rimanere DRY?
L'API supporterà operazioni CRUD su dozzine di tabelle, con le entità JPA concomitanti e DAO supportate dagli archivi Spring Data. La famiglia di interfacce DAO e DTOs relativi simile a questa:
public interface CrudService<T extends PersistedObject> { /* ... */ }
public interface PersonService extends CrudService<Person> { /* ... */ }
public class PersistedObject { /* ... */ }
public class Person extends PersistedObject { /* ... */ }
Ecco una versione semplificata di una classe di risorse JAX-RS:
@Component
@Path("/people")
public class PersonResource {
@Autowired
private PersonService personService;
@Path("/{id}")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Person get(@PathParam("id") String id) {
return personService.findOne(Long.valueOf(id));
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response post(Person person) {
personService.save(person);
return Response.created().build();
}
}
Il problema è che resto delle decine di classi di risorse sembrano quasi identici, con la sola differenza che operano su una diversa sottoclasse PersistedObject e sul relativo DAO corrispondente. Mi piacerebbe rimanere DRY avendo una classe di risorse in grado di supportare le operazioni CRUD su tutti i tipi di entità, presumibilmente attraverso il polimoprismo e l'iniezione intelligente del DAO. Potrebbe sembrare qualcosa di simile:
@Component
@Path("/{resourceType}")
public class CrudResource {
@Autowired
private CrudService crudService;
@Path("/{id}")
@GET
@Produces(MediaType.APPLICATION_JSON)
public PersistedObject get(@PathParam("id") String id) {
return crudService.findOne(Long.valueOf(id));
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response post(PersistedObject entity) {
crudService.save(entity);
return Response.created().build();
}
}
Le questioni di cui ho bisogno per risolvere:
- Se i metodi di risorse accettare e tornare PersistedObject, come sarà Jersey/Jackson sapere come serializzare/deserializzare? La variabile
resourceType
nel parametro path indica il tipo concreto che l'utente sta richiedendo, ma non so come maneggiarlo a vantaggio. - Quando Spring fornisce l'istanza della classe di risorse, in che modo saprà quale DAO deve essere iniettato?
Nel complesso, non sono sicuro di essere sulla strada giusta. È possibile implementarlo in modo generico?