[[customizing-sdr.configuring-the-rest-url-path]]
= Configuring the REST URL path

Configuring the segments of the URL path under which the resources of a JPA repository are exported is simple. You just add an annotation at the class level and/or at the query method level.

By default, the exporter will expose your `CrudRepository` 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. So a repository defined as follows:

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

Will, by default, be exposed under the URL `http://localhost:8080/persons/`

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

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

Now the repository will be accessible under the URL: `http://localhost:8080/people/`

If you have query methods defined, those also default to be exposed by their name:

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

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

This would be exposed under the URL: `http://localhost:8080/persons/search/findByName`

NOTE: All query method resources are exposed under the resource `search`.

To change the segment of the URL under which this query method is exposed, use the `@RestResource` annotation again:

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

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

Now this query method will be exposed under the URL: `http://localhost:8080/people/search/names`

== Handling rels

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'll get back a list of links:

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

To change the rel value, use the `rel` property on the `@RestResource` annotation:

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

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

This would result in a link value of:

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

NOTE: These snippets of JSON assume you are using Spring Data REST's default format of http://stateless.co/hal_specification.html[HAL]. It's possible to turn off HAL, which would cause the output to look different. But your ability to override rel names is totally independent of the rendering format.


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

[source,javascript]
----
{
  "_links" : {
    "people" : {
      "href" : "http://localhost:8080/people"
    },
    …
  }
}
----

In the top level fragment above:

* `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 shown below:

[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`
* Being 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 or 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:

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

To skip exporting a query method:

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

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

Or to skip exporting a field:

[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, it's your responsiblity to NOT export the fields. See 

[[customizing-sdr.hiding-repository-crud-methods]]
== Hiding repository CRUD methods

If you don't 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 overriden version. For example, to prevent HTTP users from invoking the delete methods of `CrudRepository`, override all of them and add the annotation to the overriden methods.

[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 as the exporter currently uses a somewhat naive algorithm for determing which CRUD method to use in the interest of faster runtime performance. It's not currently possible to turn off the version of delete which takes an ID but leave exported 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, then just keep in mind you have to annotate both versions with `exported = false`.
