[[customizing-sdr.configuring-the-rest-url-path]]
= 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 https://github.com/atteo/evo-inflector[Evo Inflector] to pluralize this word. Consider the following repository definition:

====
[source,java]
----
interface PersonRepository extends CrudRepository<Person, Long> {}
----
====

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

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

====
[source,java]
----
@RepositoryRestResource(path = "people")
interface PersonRepository extends CrudRepository<Person, Long> {}
----
====

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

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

====
[source,java]
----
interface PersonRepository extends CrudRepository<Person, Long> {

  List<Person> findByName(String name);
}
----
====

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

NOTE: 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:

====
[source,java]
----
@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 `http://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 `http://localhost:8080/persons/search` to find out what query methods are exposed, you get back a list of links similar to the following:

====
[source,javascript]
----
{
  "_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:

====
[source,java]
----
@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:

====
[source,javascript]
----
{
  "_links" : {
    "names" : {
      "href" : "http://localhost:8080/persons/search/names"
    }
  }
}
----
====

NOTE: These snippets of JSON assume you use Spring Data REST's default format of http://stateless.co/hal_specification.html[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:

====
[source,java]
----
@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:

====
[source,javascript]
----
{
  "_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:

====
[source,javascript]
----
{
  "_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`.

[[customizing-sdr.hiding-repositories]]
== 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:

====
[source,java]
----
@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:

====
[source,java]
----
@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:

====
[source,java]
----
@Entity
public class Person {

  @Id @GeneratedValue private Long id;

  @OneToMany
  @RestResource(exported = false)
  private Map<String, Profile> profiles;
}
----
====

WARNING: Projections provide the means to change what is exported and effectively <<projections-excerpts.hidden-data,side-step these settings>>. If you create any projections against the same domain object, be sure to NOT export the fields.

[[customizing-sdr.hiding-repository-crud-methods]]
== 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:

====
[source,java]
----
@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);
}
----
====

WARNING: 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`.
