Configuring the REST URL Path

You can configure the segments of the URL path under which the resources of a JPA repository are exported. To do so, add an annotation at the class level or at the query method level.

By default, the exporter exposes your CrudRepository by using the name of the domain class. Spring Data REST also applies the Evo Inflector to pluralize this word. Consider the following repository definition:

interface PersonRepository extends CrudRepository<Person, Long> {}

The repository defined by the preceding example is exposed at localhost:8080/persons/.

To change how the repository is exported, add a @RestResource annotation at the class level, as the following example shows:

@RepositoryRestResource(path = "people")
interface PersonRepository extends CrudRepository<Person, Long> {}

The repository defined by the preceding example is accessible at localhost:8080/people/.

If you have query methods defined, those also default to being exposed by their name, as the following example shows:

interface PersonRepository extends CrudRepository<Person, Long> {

  List<Person> findByName(String name);
}

The method in the preceding example is exposed at localhost:8080/persons/search/findByName.

All query method resources are exposed under the search resource.

To change the segment of the URL under which this query method is exposed, you can use the @RestResource annotation again, as the following example shows:

@RepositoryRestResource(path = "people")
interface PersonRepository extends CrudRepository<Person, Long> {

  @RestResource(path = "names")
  List<Person> findByName(String name);
}

Now the query method in the preceding example is exposed at localhost:8080/people/search/names.

Handling rel Attributes

Since these resources are all discoverable, you can also affect how the rel attribute is displayed in the links sent out by the exporter.

For instance, in the default configuration, if you issue a request to localhost:8080/persons/search to find out what query methods are exposed, you get back a list of links similar to the following:

{
  "_links" : {
    "findByName" : {
      "href" : "http://localhost:8080/persons/search/findByName"
    }
  }
}

To change the rel value, use the rel property on the @RestResource annotation, as the following example shows:

@RepositoryRestResource(path = "people")
interface PersonRepository extends CrudRepository<Person, Long> {

  @RestResource(path = "names", rel = "names")
  List<Person> findByName(String name);
}

The preceding example results in the following link value:

{
  "_links" : {
    "names" : {
      "href" : "http://localhost:8080/persons/search/names"
    }
  }
}
These snippets of JSON assume you use Spring Data REST’s default format of HAL. You can turn off HAL, which would cause the output to look different. However, your ability to override rel names is totally independent of the rendering format.

You can change the rel of a repository, as the following example shows:

@RepositoryRestResource(path = "people", rel = "people")
interface PersonRepository extends CrudRepository<Person, Long> {

  @RestResource(path = "names", rel = "names")
  List<Person> findByName(String name);
}

Altering the rel of a repository changes the top-level name, as the following example output shows:

{
  "_links" : {
    "people" : {
      "href" : "http://localhost:8080/people"
    },
    …
  }
}

In the top level fragment shown in the preceding output:

  • path = "people" changed the value in href from /persons to /people.

  • rel = "people" changed the name of that link from persons to people.

When you navigate to the search resource of this repository, the finder method’s @RestResource annotation has altered the path, as follows:

{
  "_links" : {
    "names" : {
      "href" : "http://localhost:8080/people/search/names"
    }
  }
}

This collection of annotations in your repository definition has caused the following changes:

  • The Repository-level annotation’s path = "people" is reflected in the base URI with /people.

  • The inclusion of a finder method provides you with /people/search.

  • path = "names" creates a URI of /people/search/names.

  • rel = "names" changes the name of that link from findByNames to names.

Hiding Certain Repositories, Query Methods, or Fields

You may not want a certain repository, a query method on a repository, or a field of your entity to be exported at all. Examples include hiding fields like password on a User object and similar sensitive data. To tell the exporter to not export these items, annotate them with @RestResource and set exported = false.

For example, to skip exporting a repository, you could create a repository definition similar to the following example:

@RepositoryRestResource(exported = false)
interface PersonRepository extends CrudRepository<Person, Long> {}

To skip exporting a query method, you can annotate the query method with @RestResource(exported = false), as follows:

@RepositoryRestResource(path = "people", rel = "people")
interface PersonRepository extends CrudRepository<Person, Long> {

  @RestResource(exported = false)
  List<Person> findByName(String name);
}

Similarly, to skip exporting a field, you can annotate the field with @RestResource(exported = false), as follows:

@Entity
public class Person {

  @Id @GeneratedValue private Long id;

  @OneToMany
  @RestResource(exported = false)
  private Map<String, Profile> profiles;
}
Projections provide the means to change what is exported and effectively side-step these settings. If you create any projections against the same domain object, be sure to NOT export the fields.

Hiding Repository CRUD Methods

If you do not want to expose a save or delete method on your CrudRepository, you can use the @RestResource(exported = false) setting by overriding the method you want to turn off and placing the annotation on the overridden version. For example, to prevent HTTP users from invoking the delete methods of CrudRepository, override all of them and add the annotation to the overridden methods, as follows:

@RepositoryRestResource(path = "people", rel = "people")
interface PersonRepository extends CrudRepository<Person, Long> {

  @Override
  @RestResource(exported = false)
  void delete(Long id);

  @Override
  @RestResource(exported = false)
  void delete(Person entity);
}
It is important that you override both delete methods. In the interest of faster runtime performance, the exporter currently uses a somewhat naive algorithm for determining which CRUD method to use. You cannot currently turn off the version of delete that takes an ID but export the version that takes an entity instance. For the time being, you can either export the delete methods or not. If you want turn them off, keep in mind that you have to annotate both versions with exported = false.