Skip to content

Best Practises for data driven REST Applications

Peter edited this page Apr 9, 2014 · 3 revisions

The following is a set of best-practises recommendations for building data-driven RESTful applications in the framework. It is designed to be read alongside the Your First RESTful Application guide.

Database Entities and DAOs

  • Database entities as beans with annotations on private fields and auto-generated getters/setters, named with the suffix "Entity", for example UserEntity - Using Long as a numeric id, String as a string id - Avoiding composite primary keys for the sake of simplicity of hibernate operation - @Column annotations assigning db-style names (e.g. email_address rather than emailAddress)
  • Database access object with an interface (e.g. UserDao), extending Dao<UserEntity, PrimaryKeyType>
    • Queries expressed as methods on this dao (e.g. getByEmailAddress(String email)).
  • Database access object impleentation for Hibernate (e.g. UserDaoImpl), extending HibernateDao<UserEntity, PrimaryKeyType>
    • Methods implemented with @Transactional to act as a last resort boundary for starting a db transaction

API Services

See an example of a simple service as part of the Your First RESTful Application guide

  • REST service to expose the data via API. UserRestService interface
    • Resources structured as:
      • GET /user/{id} - retrieve single user document (return 404 if not exist)
      • PUT /user/{id} - update (post a user document here), returns the same as GET
      • DELETE /user/{id} - delete a user (may mark as inactive)
      • POST /users/create - create a new user (by posting a user document or, in more complicated cases, a user creation request document). Returns the same as GETting the newly-created user
      • GET /users - execute a query (expressed on the query string - [a dynamic query, for instance](WebQuery API)) across all users. Designed for web UI and developer use
      • POST /users - execute a query (expressed in a query document) across all users. Designed for other services. Same return type as GET /users above usually
      • POST /user/{id}/action/{action-name} - perform some action (often POSTing a document or some form parameters)
    • Use of @Doc annotation on interface, methods and parameters to help improve quality of auto-generated service docs exposed via /list resource
    • Access Control via @AuthConstraint annotations
  • JAXB document classes for REST service inputs/outputs, implemented as POJOs (no getters/setters, public fields with annotations).
    • Named as Entity classname without Entity suffix (e.g. simply User for a user document).
    • @XmlRootElement(name="User") and @XmlType(name="UserType") annotations
    • Request/Response documents with Request or Response suffix (e.g. MigrateUserRequest)
  • Internal service class, UserService, where both API and others will need to make changes in a managed way (e.g. state transitions)
  • REST service implementation named as "UserRestServiceImpl", talking to DAO or, where appropriate, an internal service
    • @Transactional or @Transactional(readOnly=true) annotations on REST method boundaries
  • Converter class to convert the database entity bean to JAXB documents. Depending on use this may be a UserConverter or a single Converter for the whole service (e.g. where converting a graph of objects and their relations)
    • Two main methods, marshal to convert an Entity -> JAXB type and unmarshal to convert a JAXB type -> partially filled in Entity
    • Converter usually not DAO aware
    • Complex relationship expansion may be controlled by a flag (to allow entities to return lots of data on their related objects, but without creating circular references loop or ending up with the whole db in a single xml entity response as more and more relationships are expanded)

REST UI Services

  • UI service to expose the data to users. UserUIService interface (in service project, usually annotated with @ImplementedBy(UserUIServiceImpl.class) for less guice module wiring)
    • Similar (or identical) endpoints to the API Service, with the exception of search which doesn't require a POSTed XML document approach and can survive on the query string approach.
    • Use Accept header negotiation to return UI method instead of API method (e.g. @Provides("text/html") vs @Provides("application/xml"))
    • Create/Modify resources redirect to GET /user/{id} page on success rather than returning the getter as with RestServices
  • UI service implementation, UserUIServiceImpl
    • java @Transactional or @Transactional(readOnly=true) annotations on REST method boundaries
    • Calls DAOs or, where appropriate, custom services (UserService, for example)
    • Uses a templater to present database entities, emitting String documents via JAX-RS (done at this point so the template can be generated while the hibernate template is still valid, since it may be needed to expand lazy relationships used in the template)
    • Access Control via @AuthConstraint annotations