5
votes

We have implemented a RESTful web service using the Spring Hateoas project. This project makes it easy to convert your domain classes to resources that provides "self" links etc.

What I find confusing with this approach is that you return resources classes when using GET, but when it comes to do a POST or a PUT you use the domain model. This means that any client using the RESTful API would need to have access to the domain classes + the resource classes (resulting in clients having to add the Hateoas project as a dependency). This approach can be seen in this blog entry.

What would be the correct approach here? To only work with resources classes (for POSTs and PUTs as well)?

Not each domain class has an matching resource. Take the case where the object graph is more complicated and a resource has a list of child object:

public class StoreResource {
    public String name;
    public List<Location> children;
}

The Location object wouldn't have any resource class.

For now it looks like we need to provide both the domain classes + existing resource classes to clients.

1

1 Answers

0
votes

In our project we use similar approach. Yes, in this case a client library does have Spring HATEOAS as dependency. For example, we share domain model as set of interfaces. Server entities and client resources both implement these interfaces for consistency.

Example of common interface:

package com.example.cookbook.model;

interface RecipeDetails {
  String getTitle();
  List<? extends IngredientExcerpt> getIngredients();
}

Example of server entity:

package com.example.cookbook.server.model;

@Entity
public class Recipe implements AbstractPersistable<Long> {

  /**
   * Recipe details projection.
   */
  @Projection(name="details", classes=RecipeEntity.class)
  public interface RecipeDetailsProjection extends RecipeDetails {
    @Override
    List<IngredientExcerptProjection> getIngredients();
  }

  private List<Ingredient> ingredients;
  private String title;
  ... // getters, setters
}

Example of client resource:

package com.example.cookbook.client.model;

public class RecipeDetailsResource extends ResourceSupport implements RecipeDetails {
  private List<IngredientExcerptResource> ingredients;
  private String title;
  ... // Getters, setters
}