I'm building a REST API for performing CRUD operations on a database. My tentative stack is Jersey, Spring, Spring Data, JPA and Hibernate. I'm also using jersey-spring to supply instances of the resource class so Spring can autowire them.
The API will support CRUD operations on dozens of tables, with concomitant JPA Entities and DAOs backed by Spring Data repositories. The family of DAO interfaces and related DTOs looks something like this:
public interface CrudService<T extends PersistedObject> { /* ... */ }
public interface PersonService extends CrudService<Person> { /* ... */ }
public class PersistedObject { /* ... */ }
public class Person extends PersistedObject { /* ... */ }
Here's a simplified version of a JAX-RS resource class:
@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();
}
}
The problem is that remainder of the dozens of resource classes look almost identical, the only difference being they operate on a different PersistedObject subclass and its corresponding DAO. I'd like to stay DRY by having one resource class that can support the CRUD operations on all entity types, presumably via polymoprhism and clever injection of the DAO. It might look something like this:
@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();
}
}
The issues I need to solve:
- If resource methods accept and return PersistedObject, how will Jersey/Jackson know how to serialize/deserialize? The
resourceType
variable in the path parameter indicates the concrete type the user is requesting, but I don't know how to wield this to any advantage. - When Spring supplies the resource class instance, how will it know which DAO to inject?
Overall, I'm not sure that I'm on the right path. Is it possible to implement this in a generic way?