diff --git a/src/main/asciidoc/adding-sdr-to-spring-mvc-app.adoc b/src/main/asciidoc/adding-sdr-to-spring-mvc-app.adoc
index 019719881..9a9384895 100644
--- a/src/main/asciidoc/adding-sdr-to-spring-mvc-app.adoc
+++ b/src/main/asciidoc/adding-sdr-to-spring-mvc-app.adoc
@@ -1,14 +1,13 @@
[[customizing-sdr.adding-sdr-to-spring-mvc-app]]
-= Adding Spring Data REST to an existing Spring MVC Application
+= Adding Spring Data REST to an Existing Spring MVC Application
-NOTE: The following steps are unnecessary if you are using Spring Boot. Adding *spring-boot-starter-data-rest* will cause it to automatically to get added to your application.
+NOTE: The following steps are unnecessary if you use Spring Boot. For Boot applications, adding `spring-boot-starter-data-rest` automatically adds Spring Data REST to your application.
-If you have an existing Spring MVC application and you'd like to integrate Spring Data REST, it's actually very easy.
-
-Somewhere in your Spring MVC configuration (most likely where you configure your MVC resources) add a bean reference to the JavaConfig class that is responsible for configuring the `RepositoryRestController`. The class name is `org.springframework.data.rest.webmvc.RepositoryRestMvcConfiguration`.
+You can integrate Spring Data REST with an existing Spring MVC application. In your Spring MVC configuration (most likely where you configure your MVC resources), add a bean reference to the Java configuration class that is responsible for configuring the `RepositoryRestController`. The class name is `org.springframework.data.rest.webmvc.RepositoryRestMvcConfiguration`. The following example shows how to use an `@Import` annotation to add the proper reference:
In Java, this would look like:
+====
[source,java]
----
import org.springframework.context.annotation.Import;
@@ -21,24 +20,27 @@ public class MyApplicationConfiguration {
…
}
----
+====
-In XML this would look like:
+The following example shows the corresponding XML configuration:
+====
[source,xml]
----
----
+====
-When your ApplicationContext comes across this bean definition it will bootstrap the necessary Spring MVC resources to fully-configure the controller for exporting the repositories it finds in that `ApplicationContext` and any parent contexts.
+When your ApplicationContext comes across this bean definition, it bootstraps the necessary Spring MVC resources to fully configure the controller for exporting the repositories it finds in that `ApplicationContext` and any parent contexts.
-== More on required configuration
+== More on Required Configuration
-There are a couple Spring MVC resources that Spring Data REST depends on that must be configured correctly for it to work inside an existing Spring MVC application. We've tried to isolate those resources from whatever similar resources already exist within your application, but it may be that you want to customize some of the behavior of Spring Data REST by modifying these MVC components.
+Spring Data REST depends on a couple Spring MVC resources that must be configured correctly for it to work inside an existing Spring MVC application. We tried to isolate those resources from whatever similar resources already exist within your application, but it may be that you want to customize some of the behavior of Spring Data REST by modifying these MVC components.
-The most important things that we configure especially for use by Spring Data REST include:
+You should pay special attention to configuring `RepositoryRestHandlerMapping`, covered in the next section.
-=== RepositoryRestHandlerMapping
+=== `RepositoryRestHandlerMapping`
-We register a custom `HandlerMapping` instance that responds only to the `RepositoryRestController` and only if a path is meant to be handled by Spring Data REST. In order to keep paths that are meant to be handled by your application separate from those handled by Spring Data REST, this custom `HandlerMapping` inspects the URL path and checks to see if a Repository has been exported under that name. If it has, it allows the request to be handled by Spring Data REST. If there is no Repository exported under that name, it returns `null`, which just means "let other `HandlerMapping` instances try to service this request".
+We register a custom `HandlerMapping` instance that responds only to the `RepositoryRestController` and only if a path is meant to be handled by Spring Data REST. In order to keep paths that are meant to be handled by your application separate from those handled by Spring Data REST, this custom `HandlerMapping` class inspects the URL path and checks to see if a repository has been exported under that name. If it has, the custom `HandlerMapping` class lets the request be handled by Spring Data REST. If there is no Repository exported under that name, it returns `null`, which means "`let other `HandlerMapping` instances try to service this request`".
-The Spring Data REST `HandlerMapping` is configured with `order=(Ordered.LOWEST_PRECEDENCE - 100)` which means it will usually be first in line when it comes time to map a URL path. Your existing application will never get a chance to service a request that is meant for a repository. For example, if you have a repository exported under the name "person", then all requests to your application that start with `/person` will be handled by Spring Data REST and your application will never see that request. If your repository is exported under a different name, however (like "people"), then requests to `/people` will go to Spring Data REST and requests to "/person" will be handled by your application.
+The Spring Data REST `HandlerMapping` is configured with `order=(Ordered.LOWEST_PRECEDENCE - 100)`, which means it is usually first in line when it comes time to map a URL path. Your existing application never gets a chance to service a request that is meant for a repository. For example, if you have a repository exported under the name of `person`, then all requests to your application that start with `/person` are handled by Spring Data REST, and your application never sees that request. If your repository is exported under a different name (such as `people`), however, then requests to `/people` go to Spring Data REST and requests to `/person` are handled by your application.
diff --git a/src/main/asciidoc/configuring-cors.adoc b/src/main/asciidoc/configuring-cors.adoc
index 2b4d8c88f..936dadd3f 100644
--- a/src/main/asciidoc/configuring-cors.adoc
+++ b/src/main/asciidoc/configuring-cors.adoc
@@ -1,23 +1,26 @@
[[customizing-sdr.configuring-cors]]
= Configuring CORS
-For security reasons, browsers prohibit AJAX calls to resources residing outside the current origin. When working with client-side HTTP requests issued by a browser you want to enable specific HTTP resources to be accessible.
+For security reasons, browsers prohibit AJAX calls to resources residing outside the current origin. When working with client-side HTTP requests issued by a browser, you want to enable specific HTTP resources to be accessible.
-Spring Data REST supports as of 2.6 http://en.wikipedia.org/wiki/Cross-origin_resource_sharing[Cross-origin resource sharing] (CORS) through http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/web.html#mvc-cors[Spring's CORS] support.
+Spring Data REST, as of 2.6, supports http://en.wikipedia.org/wiki/Cross-origin_resource_sharing[Cross-Origin Resource Sharing] (CORS) through http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/web.html#mvc-cors[Spring's CORS] support.
-== Repository interface CORS configuration
+== Repository Interface CORS Configuration
-You can add a `@CrossOrigin` annotation to your repository interfaces to enable CORS for the whole repository. By default `@CrossOrigin` allows all origins and HTTP methods:
+You can add a `@CrossOrigin` annotation to your repository interfaces to enable CORS for the whole repository. By default, `@CrossOrigin` allows all origins and HTTP methods. The following example shows a cross-origin repository interface definition:
+====
[source, java]
----
@CrossOrigin
interface PersonRepository extends CrudRepository {}
----
+====
-In the above example CORS support is enabled for the whole `PersonRepository`. `@CrossOrigin` provides attributes to configure CORS support.
+In the preceding example, CORS support is enabled for the whole `PersonRepository`. `@CrossOrigin` provides attributes to configure CORS support, as the following example shows:
+====
[source, java]
----
@CrossOrigin(origins = "http://domain2.com",
@@ -25,13 +28,15 @@ In the above example CORS support is enabled for the whole `PersonRepository`. `
maxAge = 3600)
interface PersonRepository extends CrudRepository {}
----
+====
-This example enables CORS support for the whole `PersonRepository` providing one origin, restricted to `GET`, `POST` and `DELETE` methods with a max age of 3600 seconds.
+The preceding example enables CORS support for the whole `PersonRepository` by providing one origin, restricted to the `GET`, `POST`, and `DELETE` methods and with a max age of 3600 seconds.
-== Repository REST Controller method CORS configuration
+== Repository REST Controller Method CORS Configuration
-Spring Data REST fully supports http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/web.html#controller-method-cors-configuration[Spring Web MVC's Controller method configuration] on custom REST Controllers sharing repository base paths.
+Spring Data REST fully supports http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/web.html#controller-method-cors-configuration[Spring Web MVC's controller method configuration] on custom REST controllers that share repository base paths, as the following example shows:
+====
[source, java]
----
@RepositoryRestController
@@ -44,15 +49,19 @@ public class PersonController {
}
}
----
+====
NOTE: Controllers annotated with `@RepositoryRestController` inherit `@CrossOrigin` configuration from their associated repositories.
-== Global CORS configuration
+== Global CORS Configuration
-In addition to fine-grained, annotation-based configuration you’ll probably want to define some global CORS configuration as well. This is similar to Spring Web MVC'S CORS configuration but can be declared within Spring Data REST and combined with fine-grained `@CrossOrigin` configuration. By default all origins and `GET`, `HEAD`, and `POST` methods are allowed.
+In addition to fine-grained, annotation-based configuration, you probably want to define some global CORS configuration as well. This is similar to Spring Web MVC'S CORS configuration but can be declared within Spring Data REST and combined with fine-grained `@CrossOrigin` configuration. By default, all origins and `GET`, `HEAD`, and `POST` methods are allowed.
NOTE: Existing Spring Web MVC CORS configuration is not applied to Spring Data REST.
+The following example sets an allowed origin, adds the PUT and DELETE HTTP methods, adds and exposes some headers, and sets a maximum age of an hour:
+
+====
[source, java]
----
@Component
@@ -70,4 +79,4 @@ public class SpringDataRestCustomization extends RepositoryRestConfigurerAdapter
}
}
----
-
+====
diff --git a/src/main/asciidoc/configuring-the-rest-url-path.adoc b/src/main/asciidoc/configuring-the-rest-url-path.adoc
index 2441c1573..c89d54a0a 100644
--- a/src/main/asciidoc/configuring-the-rest-url-path.adoc
+++ b/src/main/asciidoc/configuring-the-rest-url-path.adoc
@@ -1,29 +1,34 @@
[[customizing-sdr.configuring-the-rest-url-path]]
-= 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.
+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 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:
+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 {}
----
+====
-Will, by default, be exposed under the URL `http://localhost:8080/persons/`
+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:
+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 {}
----
+====
-Now the repository will be accessible under the URL: `http://localhost:8080/people/`
+The repository defined by the preceding example is accessible at `http://localhost:8080/people/`.
-If you have query methods defined, those also default to be exposed by their name:
+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 {
@@ -31,13 +36,15 @@ interface PersonRepository extends CrudRepository {
List findByName(String name);
}
----
+====
-This would be exposed under the URL: `http://localhost:8080/persons/search/findByName`
+The method in the preceding example is exposed at `http://localhost:8080/persons/search/findByName`.
-NOTE: All query method resources are exposed under the resource `search`.
+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, use the `@RestResource` annotation again:
+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")
@@ -47,15 +54,17 @@ interface PersonRepository extends CrudRepository {
List findByName(String name);
}
----
+====
-Now this query method will be exposed under the URL: `http://localhost:8080/people/search/names`
+Now the query method in the preceding example is exposed at `http://localhost:8080/people/search/names`.
-== Handling rels
+== 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.
+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:
+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]
----
{
@@ -66,9 +75,11 @@ For instance, in the default configuration, if you issue a request to `http://lo
}
}
----
+====
-To change the rel value, use the `rel` property on the `@RestResource` annotation:
+To change the `rel` value, use the `rel` property on the `@RestResource` annotation, as the following example shows:
+====
[source,java]
----
@RepositoryRestResource(path = "people")
@@ -78,9 +89,11 @@ interface PersonRepository extends CrudRepository {
List findByName(String name);
}
----
+====
-This would result in a link value of:
+The preceding example results in the following link value:
+====
[source,javascript]
----
{
@@ -91,10 +104,13 @@ This would result in a link value of:
}
}
----
+====
-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.
+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")
@@ -104,9 +120,11 @@ interface PersonRepository extends CrudRepository {
List findByName(String name);
}
----
+====
-Altering the rel of a Repository changes the top level name:
+Altering the `rel` of a repository changes the top-level name, as the following example output shows:
+====
[source,javascript]
----
{
@@ -118,14 +136,16 @@ Altering the rel of a Repository changes the top level name:
}
}
----
+====
-In the top level fragment above:
+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`
+* `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:
+When you navigate to the `search` resource of this repository, the finder method's `@RestResource` annotation has altered the path, as follows:
+====
[source,javascript]
----
{
@@ -136,29 +156,33 @@ When you navigate to the *search* resource of this repository, the finder-method
}
}
----
+====
-This collection of annotations in your Repository definition has caused the following changes:
+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`
+* 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
+== 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`.
+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:
+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 {}
----
+====
-To skip exporting a query method:
+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")
@@ -168,9 +192,11 @@ interface PersonRepository extends CrudRepository {
List findByName(String name);
}
----
+====
-Or to skip exporting a field:
+Similarly, to skip exporting a field, you can annotate the field with `@RestResource(exported = false)`, as follows:
+====
[source,java]
----
@Entity
@@ -183,14 +209,16 @@ public class Person {
private Map profiles;
}
----
+====
-WARNING: Projections provide the means to change what is exported and effectively <>. If you create any projections against the same domain object, it's your responsiblity to NOT export the fields. See
+WARNING: Projections provide the means to change what is exported and effectively <>. 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
+== 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.
+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")
@@ -205,5 +233,6 @@ interface PersonRepository extends CrudRepository {
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`.
+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`.
diff --git a/src/main/asciidoc/custom-jackson-deserialization.adoc b/src/main/asciidoc/custom-jackson-deserialization.adoc
index 3c35e96f3..0bc643e89 100644
--- a/src/main/asciidoc/custom-jackson-deserialization.adoc
+++ b/src/main/asciidoc/custom-jackson-deserialization.adoc
@@ -1,14 +1,15 @@
[[customizing-sdr.custom-jackson-deserialization]]
-= Adding custom (de)serializers to Jackson's ObjectMapper
+= Adding Custom Serializers and Deserializers to Jackson's `ObjectMapper`
-Sometimes the behavior of the Spring Data REST's `ObjectMapper`, which has been specially configured to use intelligent serializers that can turn domain objects into links and back again, may not handle your domain model correctly. There are so many ways one can structure your data that you may find your own domain model isn't being translated to JSON correctly. It's also sometimes not practical in these cases to try and support a complex domain model in a generic way. Sometimes, depending on the complexity, it's not even possible to offer a generic solution.
+Sometimes, the behavior of the Spring Data REST `ObjectMapper` (which has been specially configured to use intelligent serializers that can turn domain objects into links and back again) may not handle your domain model correctly. You can structure your data in so many ways that you may find your own domain model does not correctly translate to JSON. It is also sometimes not practical in these cases to support a complex domain model in a generic way. Sometimes, depending on the complexity, it is not even possible to offer a generic solution.
-So to accommodate the largest percentage of the use cases, Spring Data REST tries very hard to render your object graph correctly. It will try and serialize unmanaged beans as normal POJOs and it will try and create links to managed beans where that's necessary. But if your domain model doesn't easily lend itself to reading or writing plain JSON, you may want to configure Jackson's ObjectMapper with your own custom type mappings and (de)serializers.
+To accommodate the largest percentage of the use cases, Spring Data REST tries to render your object graph correctly. It tries to serialize unmanaged beans as normal POJOs, and tries to create links to managed beans where necessary. However, if your domain model does not easily lend itself to reading or writing plain JSON, you may want to configure Jackson's `ObjectMapper` with your own custom type mappings and (de)serializers.
-== Abstract class registration
+== Abstract Class Registration
-One key configuration point you might need to hook into is when you're using an abstract class (or an interface) in your domain model. Jackson won't know by default what implementation to create for an interface. Take the following example:
+One key configuration point you might need to hook into is when you use an abstract class (or an interface) in your domain model. Jackson does not, by default, know what implementation to create for an interface. Consider the following example:
+====
[source,java]
----
@Entity
@@ -18,11 +19,13 @@ public class MyEntity {
private List interfaces;
}
----
+====
-In a default configuration, Jackson has no idea what class to instantiate when POSTing new data to the exporter. This is something you'll need to tell Jackson either through an annotation, or, more cleanly, by registering a type mapping using a http://wiki.fasterxml.com/JacksonFeatureModules[Module].
+In a default configuration, Jackson has no idea what class to instantiate when POSTing new data to the exporter. You need to tell Jackson either through an annotation or, more cleanly, by registering a type mapping by using a http://wiki.fasterxml.com/JacksonFeatureModules[Module].
-Any `Module` bean declared within the scope of your `ApplicationContext` will be picked up by the exporter and registered with its `ObjectMapper`. To add this special abstract class type mapping, create a `Module` bean and in the `setupModule` method, add an appropriate `TypeResolver`:
+Any `Module` bean declared within the scope of your `ApplicationContext` is picked up by the exporter and registered with its `ObjectMapper`. To add this special abstract class type mapping, you can create a `Module` bean and, in the `setupModule` method, add an appropriate `TypeResolver`, as follows:
+====
[source,java]
----
public class MyCustomModule extends SimpleModule {
@@ -39,15 +42,17 @@ public class MyCustomModule extends SimpleModule {
}
}
----
+====
-Once you have access to the `SetupContext` object in your `Module`, you can do all sorts of cool things to configure Jackon's JSON mapping. You can read more about how http://wiki.fasterxml.com/JacksonFeatureModules[Module`s work on Jackson's wiki].
+Once you have access to the `SetupContext` object in your `Module`, you can do all sorts of cool things to configure Jackon's JSON mapping. You can read more about how http://wiki.fasterxml.com/JacksonFeatureModules[Modules work on Jackson's wiki].
-== Adding custom serializers for domain types
+== Adding Custom Serializers for Domain Types
-If you want to (de)serialize a domain type in a special way, you can register your own implementations with Jackson's `ObjectMapper` and the Spring Data REST exporter will transparently handle those domain objects correctly.
+If you want to serialize or deserialize a domain type in a special way, you can register your own implementations with Jackson's `ObjectMapper`. Then the Spring Data REST exporter transparently handles those domain objects correctly.
-To add serializers, from your `setupModule` method implementation, do something like the following:
+To add serializers from your `setupModule` method implementation, you can do something like the following:
+====
[source,java]
----
public class MyCustomModule extends SimpleModule {
@@ -68,5 +73,6 @@ public class MyCustomModule extends SimpleModule {
}
}
----
+====
-Now Spring Data REST will correctly handle your domain objects in case they are too complex for the 80% generic use case that Spring Data REST tries to cover.
+Thanks to the custom module shown in the preceding example, Spring Data REST correctly handles your domain objects when they are too complex for the 80% generic use case that Spring Data REST tries to cover.
diff --git a/src/main/asciidoc/customizing-json-output.adoc b/src/main/asciidoc/customizing-json-output.adoc
index dce15d356..3e1419e70 100644
--- a/src/main/asciidoc/customizing-json-output.adoc
+++ b/src/main/asciidoc/customizing-json-output.adoc
@@ -1,14 +1,15 @@
[[customizing-sdr.customizing-json-output]]
-= Customizing the JSON output
+= Customizing the JSON Output
-Sometimes in your application you need to provide links to other resources from a particular entity. For example, a `Customer` response might be enriched with links to a current shopping cart, or links to manage resources related to that entity. Spring Data REST provides integration with https://github.com/SpringSource/spring-hateoas[Spring HATEOAS] and provides an extension hook for users to alter the representation of resources going out to the client.
+Sometimes in your application, you need to provide links to other resources from a particular entity. For example, a `Customer` response might be enriched with links to a current shopping cart or links to manage resources related to that entity. Spring Data REST provides integration with https://github.com/SpringSource/spring-hateoas[Spring HATEOAS] and provides an extension hook that lets you alter the representation of resources that go out to the client.
-== The ResourceProcessor interface
+== The `ResourceProcessor` Interface
-Spring HATEOAS defines a `ResourceProcessor<>` interface for processing entities. All beans of type `ResourceProcessor<Resource<T>>` will be automatically picked up by the Spring Data REST exporter and triggered when serializing an entity of type `T`.
+Spring HATEOAS defines a `ResourceProcessor<>` interface for processing entities. All beans of type `ResourceProcessor<Resource<T>>` are automatically picked up by the Spring Data REST exporter and triggered when serializing an entity of type `T`.
-For example, to define a processor for a `Person` entity, add a `@Bean` to your `ApplicationContext like the following (which is taken from the Spring Data REST tests):
+For example, to define a processor for a `Person` entity, add a `@Bean` similar to the following (which is taken from the Spring Data REST tests) to your `ApplicationContext`:
+====
[source,java]
----
@Bean
@@ -25,15 +26,16 @@ public ResourceProcessor> personProcessor() {
};
}
----
+====
-IMPORTANT: This example hard codes a link to `http://localhost:8080/people`. If you have a Spring MVC endpoint inside your app that you wish to link to, consider using Spring HATEOAS's https://github.com/spring-projects/spring-hateoas#building-links-pointing-to-methods[`linkTo(...)`] method to avoid managing the URL.
+IMPORTANT: The preceding example hard codes a link to `http://localhost:8080/people`. If you have a Spring MVC endpoint inside your app to which you wish to link, consider using Spring HATEOAS's https://github.com/spring-projects/spring-hateoas#building-links-pointing-to-methods[`linkTo(...)`] method to avoid managing the URL.
== Adding Links
-It's possible to add links to the default representation of an entity by simply calling `resource.add(Link)` like the example above. Any links you add to the `Resource` will be added to the final output.
+You can add links to the default representation of an entity by calling `resource.add(Link)`, as the preceding example shows. Any links you add to the `Resource` are added to the final output.
-== Customizing the representation
+== Customizing the Representation
-The Spring Data REST exporter executes any discovered ```ResourceProcessor```s before it creates the output representation. It does this by registering a `Converter` instance with an internal `ConversionService`. This is the component responsible for creating the links to referenced entities (e.g. those objects under the *_links* property in the object's JSON representation). It takes an `@Entity` and iterates over its properties, creating links for those properties that are managed by a `Repository` and copying across any embedded or simple properties.
+The Spring Data REST exporter executes any discovered `ResourceProcessor` instances before it creates the output representation. It does so by registering a `Converter` instance with an internal `ConversionService`. This is the component responsible for creating the links to referenced entities (such as those objects under the `_links` property in the object's JSON representation). It takes an `@Entity` and iterates over its properties, creating links for those properties that are managed by a `Repository` and copying across any embedded or simple properties.
-If your project needs to have output in a different format, however, it's possible to completely replace the default outgoing JSON representation with your own. If you register your own `ConversionService` in the ApplicationContext and register your own `Converter`, then you can return a `Resource` implementation of your choosing.
\ No newline at end of file
+If your project needs to have output in a different format, however, you can completely replace the default outgoing JSON representation with your own. If you register your own `ConversionService` in the `ApplicationContext` and register your own `Converter`, you can return a `Resource` implementation of your choosing.
diff --git a/src/main/asciidoc/customizing-sdr.adoc b/src/main/asciidoc/customizing-sdr.adoc
index 61b4ff29b..42fe7ab20 100644
--- a/src/main/asciidoc/customizing-sdr.adoc
+++ b/src/main/asciidoc/customizing-sdr.adoc
@@ -3,18 +3,19 @@
There are many options to tailor Spring Data REST. These subsections show how.
-== Customizing item resource URIs
+== Customizing Item Resource URIs
-By default the URI for item resources are comprised of the path segment used for the collection resource with the database identifier appended.
-That allows us to use the repository's `findOne(…)` method to lookup entity instances.
-As of Spring Data REST 2.5 this can be customized by using configuration API on `RepositoryRestConfiguration` (preferred on Java 8) or by registering an implementation of `EntityLookup` as Spring bean in your application.
-Spring Data REST will pick those up and tweak the URI generation according to their implementation.
+By default, the URI for item resources are comprised of the path segment used for the collection resource with the database identifier appended.
+That lets you use the repository's `findOne(…)` method to lookup entity instances.
+As of Spring Data REST 2.5, this can be customized by using configuration API on `RepositoryRestConfiguration` (preferred on Java 8) or by registering an implementation of `EntityLookup` as a Spring bean in your application.
+Spring Data REST picks those up and tweaks the URI generation according to their implementation.
Assume a `User` with a `username` property that uniquely identifies it.
-Also, assume we have a method `Optional findByUsername(String username)` on the according repository.
+Further assume that we have a `Optional findByUsername(String username)` method on the corresponding repository.
-On Java 8 we can simply register the mapping methods as method references to weak the URI creation as follows:
+On Java 8, we can register the mapping methods as method references to tweak the URI creation, as follows:
+====
[source, java]
----
@Component
@@ -28,12 +29,14 @@ public class SpringDataRestCustomization extends RepositoryRestConfigurerAdapter
}
}
----
+====
-`forRepository(…)` takes the repository type as first argument a method reference mapping the repositories domain type to some target type, as well as another method reference to map that value back using the repository mentioned as first argument.
+`forRepository(…)` takes the repository type as the first argument, a method reference mapping the repositories domain type to some target type as the second argument, and another method reference to map that value back by using the repository mentioned as the first argument.
-If you're not running Java 8 or better, you could use the method but it would require a few quite verbose anonymous inner classes to be use.
-That's why on older Java versions you probably prefer implementing a `UserEntityLookup` looking like this:
+If you are not running Java 8 or better, you could use the method, but it would require a few quite verbose anonymous inner classes.
+On older Java versions, you should probably prefer implementing a `UserEntityLookup` that resembles the following:
+====
[source, java]
----
@Component
@@ -56,8 +59,9 @@ public class UserEntityLookup extends EntityLookupSupport {
}
}
----
+====
-Note, how `getResourceIdentifier(…)` returns the username to be used by the URI creation. To load entity instances by the value returned from that method we now implement `lookupEntity(…)` using the query method available on the `UserRepository`.
+Notice how `getResourceIdentifier(…)` returns the username to be used by the URI creation. To load entity instances by the value returned from that method, we now implement `lookupEntity(…)` by using the query method available on the `UserRepository`.
include::configuring-the-rest-url-path.adoc[leveloffset=+1]
diff --git a/src/main/asciidoc/etags-and-other-conditionals.adoc b/src/main/asciidoc/etags-and-other-conditionals.adoc
index da463fa7f..a471ebd47 100644
--- a/src/main/asciidoc/etags-and-other-conditionals.adoc
+++ b/src/main/asciidoc/etags-and-other-conditionals.adoc
@@ -2,12 +2,14 @@
= Conditional Operations with Headers
:spring-data-rest-root: ../../..
-This section shows how Spring Data REST uses standard HTTP headers to enhance performance, conditionalize operations, and easily contribute to a more sophisticated frontend.
+This section shows how Spring Data REST uses standard HTTP headers to enhance performance, conditionalize operations, and contribute to a more sophisticated frontend.
[[conditional.etag]]
-== ETag, If-Match, and If-None-Match headers
+== `ETag`, `If-Match`, and `If-None-Match` Headers
-The http://tools.ietf.org/html/rfc7232#section-2.3[ETag header] provides a way to tag resources. This can prevent clients from overriding each other while also making it possible to reduce unnecessary calls.
+The http://tools.ietf.org/html/rfc7232#section-2.3[`ETag` header] provides a way to tag resources. This can prevent clients from overriding each other while also making it possible to reduce unnecessary calls.
+
+Consider the following example:
.A POJO with a version number
====
@@ -15,36 +17,40 @@ The http://tools.ietf.org/html/rfc7232#section-2.3[ETag header] provides a way t
----
include::{spring-data-rest-root}/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/support/ETagUnitTests.java[tag=versioned-sample]
----
-====
<1> Spring Data Commons's `@Version` annotation flags this field as a version marker.
+====
-This POJO, when served up as a REST resource by Spring Data REST, will have an `ETag` header with the value of the version field.
+The POJO in the preceding example, when served up as a REST resource by Spring Data REST, has an `ETag` header with the value of the version field.
-We can conditionally `PUT`, `PATCH`, or `DELETE` that resource if we supply a `If-Match` header like this:
+We can conditionally `PUT`, `PATCH`, or `DELETE` that resource if we supply a `If-Match` header such as the following:
+====
----
curl -v -X PATCH -H 'If-Match: ' ...
----
+====
-Only if the resource's current ETag state matches this `If-Match` header will the operation be carried out. This prevents clients from stomping on each other. Two different clients can fetch the resource and have an identical ETag. If one client updates the resource, it will get a new ETag in the response. But the first client still has the old header. If that client attempts an update with the `If-Match` header, the update will fail because they no longer match. Instead, that client will receive an HTTP `412 Precondition Failed` message to be sent back. The client can then catch up however is necessary.
+Only if the resource's current `ETag` state matches the `If-Match` header is the operation carried out. This safeguard prevents clients from stomping on each other. Two different clients can fetch the resource and have an identical `ETag`. If one client updates the resource, it gets a new `ETag` in the response. But the first client still has the old header. If that client attempts an update with the `If-Match` header, the update fails because they no longer match. Instead, that client receives an HTTP `412 Precondition Failed` message to be sent back. The client can then catch up however is necessary.
-WARNING: The term "version" may carrry different semantics with different data stores, and even different semantics within your application. Spring Data REST effectively delegates to the data store's metamodel to discern if a field is versioned, and if so, only allow the listed updates if ETags match.
+WARNING: The term, "`version,`" may carry different semantics with different data stores and even different semantics within your application. Spring Data REST effectively delegates to the data store's metamodel to discern if a field is versioned and, if so, only allows the listed updates if `ETag` elements match.
-The http://tools.ietf.org/html/rfc7232#section-3.2[If-None-Match header] provides an alternative. Instead of conditional updates, `If-None-Match` allow conditional queries.
+The http://tools.ietf.org/html/rfc7232#section-3.2[`If-None-Match` header] provides an alternative. Instead of conditional updates, `If-None-Match` allows conditional queries. Consider the following example:
+====
----
curl -v -H 'If-None-Match: ' ...
----
+====
-This command (by default) executes a `GET`. Spring Data REST will check for `If-None-Match` headers while doing a GET. If the header MATCHES the ETag, it will conclude nothing has changed, and instead of sending a copy of the resource, instead send back an HTTP `304 Not Modified` status code. Semantically, it reads "If this supplied header value doesn't match the server-side version, then send me the whole resource, otherwise, don't send me anything."
+The preceding command (by default) executes a `GET`. Spring Data REST checks for `If-None-Match` headers while doing a `GET`. If the header matches the ETag, it concludes that nothing has changed and, instead of sending a copy of the resource, sends back an HTTP `304 Not Modified` status code. Semantically, it reads "`If this supplied header value does not match the server-side version, send the whole resource. Otherwise, do not send anything.`"
-NOTE: This POJO is from an ETag-based unit test, so it doesn't have `@Entity` (JPA) or `@Document` (MongoDB) annotations as expected in application code. It simply focuses on how a field with `@Version` results in an ETag header.
+NOTE: This POJO is from an `ETag`-based unit test, so it does not have `@Entity` (JPA) or `@Document` (MongoDB) annotations, as expected in application code. It focuses solely on how a field with `@Version` results in an `ETag` header.
[[conditional.if-modified-since]]
-== If-Modified-Since header
+== `If-Modified-Since` header
-The http://tools.ietf.org/html/rfc7232#section-3.3[If-Modified-Since header] provides a way to check if a resource has been updated since the last request to avoid resending the same data.
+The http://tools.ietf.org/html/rfc7232#section-3.3[`If-Modified-Since` header] provides a way to check whether a resource has been updated since the last request, which lets applications avoid resending the same data. Consider the following example:
.The last modification date captured in a domain type
====
@@ -52,40 +58,43 @@ The http://tools.ietf.org/html/rfc7232#section-3.3[If-Modified-Since header] pro
----
include::{spring-data-rest-root}/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/main/java/org/springframework/data/rest/tests/mongodb/Receipt.java[tag=code]
----
+
+<1> Spring Data Commons's `@LastModifiedDate` annotation allows capturing this information in multiple formats (JodaTime's `DateTime`, legacy Java `Date` and `Calendar`, JDK8 date/time types, and `long`/`Long`).
====
-<1> Spring Data Commons's `@LastModifiedDate` annotation allows capturing this information in multiple formats (JodaTime's `DateTime`, legacy Java `Date` and `Calendar`, JDK8 date/time types, as well as `long`/`Long`).
-
-With this field, Spring Data REST will return a `Last-Modified` header like this:
+With the date field in the preceding example, Spring Data REST returns a `Last-Modified` header similar to the following:
----
Last-Modified: Wed, 24 Jun 2015 20:28:15 GMT
----
-This value can be capture and used for subsequent queries to avoid fetching the same data twice if it hasn't been updated.
+This value can be captured and used for subsequent queries to avoid fetching the same data twice when it has not been updated, as the following example shows:
+====
----
curl -H "If-Modified-Since: Wed, 24 Jun 2015 20:28:15 GMT" ...
----
+====
-With this simple command, you are asking that a resource only be fetched if it's changed since that time. If so, you will get a revised `Last-Modified` header to update the client. If not, you will receive an HTTP `304 Not Modified` status code.
+With the preceding command, you are asking that a resource be fetched only if it has changed since the specified time. If so, you get a revised `Last-Modified` header with which to update the client. If not, you receive an HTTP `304 Not Modified` status code.
The header is perfectly formatted to send back for a future query.
-WARNING: Don't mix and match header value with different queries. Results could be disastrous. ONLY use the header values when you are requesting the exact same URI and parameters.
+WARNING: Do not mix and match header value with different queries. Results could be disastrous. Use the header values ONLY when you request the exact same URI and parameters.
[[headers.better-client-architecture]]
-== Architecting a more efficient frontend
+== Architecting a More Efficient Front End
-ETags combined with the `If-Match` and `If-None-Match` headers empower you to build frontend that is more friendly to consumer's data plans and mobile battery lives.
+`ETag` elements, combined with the `If-Match` and `If-None-Match` headers, let you build a front end that is more friendly to consumers' data plans and mobile battery lives. To do so:
-. Identify the entities that need locking and add a version attribute. HTML5 nicely supports data-* attributes, so store it in the DOM somewhere like `data-etag` attribute.
-. Identify the entiries that would benefit from tracking most recent updates. When fetching these resources, store the `Last-Modified` in the DOM (`data-last-modified` perhaps).
-. When fetching resources, also embed self URIs into your DOM nodes (perhaps `data-uri` or `data-self`) so it's very easy to go back to the resource.
+. Identify the entities that need locking and add a version attribute.
++
+HTML5 nicely supports `data-*` attributes, so store the version in the DOM (somewhere such as an `data-etag` attribute).
+. Identify the entries that would benefit from tracking the most recent updates. When fetching these resources, store the `Last-Modified` value in the DOM (`data-last-modified` perhaps).
+. When fetching resources, also embed `self` URIs in your DOM nodes (perhaps `data-uri` or `data-self`) so that it is easy to go back to the resource.
. Adjust `PUT`/`PATCH`/`DELETE` operations to use `If-Match` and also handle HTTP `412 Precondition Failed` status codes.
-. Adjust `GET` operations to use `If-None-Match`, `If-Modified-Since`, and also handle HTTP `304 Not Modified` status codes.
+. Adjust `GET` operations to use `If-None-Match` and `If-Modified-Since` and handle HTTP `304 Not Modified` status codes.
-By embedding `ETags` and `Last-Modified` values into your DOM (or perhaps elsewhere for a native mobile app), you can then reduce the consumption of data/battery by NOT retrieving the same thing over and over. You can also avoid colliding with other clients, and instead, be alerted when you need to reconcile differences.
-
-Hence, with just a little tweaking on your frontend and some entity-level edits, the backend will serve up time sensitive details you can cash in on when building a customer-friendly client.
+By embedding `ETag` elements and `Last-Modified` values in your DOM (or perhaps elsewhere for a native mobile app), you can then reduce the consumption of data and battery power by not retrieving the same thing over and over. You can also avoid colliding with other clients and, instead, be alerted when you need to reconcile differences.
+In this fashion, with just a little tweaking on your front end and some entity-level edits, the backend serves up time-sensitive details you can cash in on when building a customer-friendly client.
diff --git a/src/main/asciidoc/events.adoc b/src/main/asciidoc/events.adoc
index 495b66953..7d4ad491a 100644
--- a/src/main/asciidoc/events.adoc
+++ b/src/main/asciidoc/events.adoc
@@ -1,7 +1,7 @@
[[events]]
= Events
-There are eight different events that the REST exporter emits throughout the process of working with an entity. Those are:
+The REST exporter emits eight different events throughout the process of working with an entity:
* `BeforeCreateEvent`
* `AfterCreateEvent`
@@ -13,10 +13,11 @@ There are eight different events that the REST exporter emits throughout the pro
* `AfterDeleteEvent`
[[events.application-listener]]
-== Writing an ApplicationListener
+== Writing an `ApplicationListener`
-There is an abstract class you can subclass which listens for these kinds of events and calls the appropriate method based on the event type. You just override the methods for the events you're interested in.
+You can subclass an abstract class that listens for these kinds of events and calls the appropriate method based on the event type. To do so, override the methods for the events in question, as follows:
+====
[source,java]
----
public class BeforeSaveEventListener extends AbstractRepositoryEventListener {
@@ -32,17 +33,19 @@ public class BeforeSaveEventListener extends AbstractRepositoryEventListener {
}
}
----
+====
-One thing to note with this approach, however, is that it makes no distinction based on the type of the entity. You'll have to inspect that yourself.
+One thing to note with this approach, however, is that it makes no distinction based on the type of the entity. You have to inspect that yourself.
-== Writing an annotated handler
+== Writing an Annotated Handler
-Another approach is to use an annotated handler, which does filter events based on domain type.
+Another approach is to use an annotated handler, which filters events based on domain type.
To declare a handler, create a POJO and put the `@RepositoryEventHandler` annotation on it. This tells the `BeanPostProcessor` that this class needs to be inspected for handler methods.
-Once it finds a bean with this annotation, it iterates over the exposed methods and looks for annotations that correspond to the event you're interested in. For example, to handle `BeforeSaveEvent`s in an annotated POJO for different kinds of domain types, you'd define your class like this:
+Once the `BeanPostProcessor` finds a bean with this annotation, it iterates over the exposed methods and looks for annotations that correspond to the event in question. For example, to handle `BeforeSaveEvent` instances in an annotated POJO for different kinds of domain types, you could define your class as follows:
+====
[source,java]
----
@RepositoryEventHandler <1>
@@ -60,12 +63,14 @@ public class PersonEventHandler {
}
----
-<1> It's possible to narrow the types this handler applies against by using `@RepositoryEventHandler(Person.class)`.
+<1> It's possible to narrow the types to which this handler applies by using (for example) `@RepositoryEventHandler(Person.class)`.
+====
-The domain type whose events you're interested in is determined from the type of the first parameter of the annotated methods.
+The domain type whose events you are interested in is determined from the type of the first parameter of the annotated methods.
-To register your event handler, either mark the class with one of Spring's `@Component` stereotypes so it can be picked up by `@SpringBootApplication` or `@ComponentScan`. Or declare an instance of your annotated bean in your `ApplicationContext`. Then the `BeanPostProcessor` that is created in `RepositoryRestMvcConfiguration` will inspect the bean for handlers and wire them to the correct events.
+To register your event handler, either mark the class with one of Spring's `@Component` stereotypes (so that it can be picked up by `@SpringBootApplication` or `@ComponentScan`) or declare an instance of your annotated bean in your `ApplicationContext`. Then the `BeanPostProcessor` that is created in `RepositoryRestMvcConfiguration` inspects the bean for handlers and wires them to the correct events. The following example shows how to create an event handler for the `Person` class:
+====
[source,java]
----
@Configuration
@@ -77,5 +82,6 @@ public class RepositoryConfiguration {
}
}
----
+====
-NOTE: Spring Data REST events are customized http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/core.html#context-functionality-events[Spring application events]. Spring events are synchronous by default, unless they get republished across a boundary (like issuing a WebSocket event or crossing into a thread).
+NOTE: Spring Data REST events are customized http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/core.html#context-functionality-events[Spring application events]. By default, Spring events are synchronous, unless they get republished across a boundary (such as issuing a WebSocket event or crossing into a thread).
diff --git a/src/main/asciidoc/example-api-usage-with-curl.adoc b/src/main/asciidoc/example-api-usage-with-curl.adoc
index e93abc7b5..74585f57f 100644
--- a/src/main/asciidoc/example-api-usage-with-curl.adoc
+++ b/src/main/asciidoc/example-api-usage-with-curl.adoc
@@ -2,7 +2,7 @@
[appendix]
= Using cURL to talk to Spring Data REST
-This appendix contains a list of guides that demonstrate interacting with a Spring Data REST service via cURL:
+This appendix contains a list of guides that demonstrate interacting with a Spring Data REST service over cURL:
* https://spring.io/guides/gs/accessing-data-rest/[Accessing JPA Data with REST]
* https://spring.io/guides/gs/accessing-neo4j-data-rest/[Accessing Neo4j Data with REST]
diff --git a/src/main/asciidoc/getting-started.adoc b/src/main/asciidoc/getting-started.adoc
index ce82a4249..405039891 100644
--- a/src/main/asciidoc/getting-started.adoc
+++ b/src/main/asciidoc/getting-started.adoc
@@ -1,17 +1,15 @@
[[install-chapter]]
= Getting started
-[[getting-started.introduction]]
-== Introduction
-
-Spring Data REST is itself a Spring MVC application and is designed in such a way that it should integrate with your existing Spring MVC applications with very little effort. An existing (or future) layer of services can run alongside Spring Data REST with only minor considerations.
+Spring Data REST is itself a Spring MVC application and is designed in such a way that it should integrate with your existing Spring MVC applications with little effort. An existing (or future) layer of services can run alongside Spring Data REST with only minor additional work.
[[getting-started.boot]]
-== Adding Spring Data REST to a Spring Boot project
+== Adding Spring Data REST to a Spring Boot Project
-The simplest way to get to started is if you are building a Spring Boot application. That's because Spring Data REST has both a starter as well as auto-configuration.
+The simplest way to get to started is to build a Spring Boot application because Spring Boot has a starter for Spring Data REST and uses auto-configuration. The following example shows how to use Gradle to include Spring Data Rest in a Spring Boot project:
.Spring Boot configuration with Gradle
+====
[source,groovy]
----
dependencies {
@@ -20,8 +18,12 @@ dependencies {
...
}
----
+====
+
+The following example shows how to use Maven to include Spring Data Rest in a Spring Boot project:
.Spring Boot configuration with Maven
+====
[source,xml]
----
@@ -33,16 +35,18 @@ dependencies {
...
----
+====
-NOTE: You don't have to supply the version number if you are using the http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#build-tool-plugins-gradle-plugin[Spring Boot Gradle plugin] or the http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#build-tool-plugins-maven-plugin[Spring Boot Maven plugin].
+NOTE: You need not supply the version number if you use the http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#build-tool-plugins-gradle-plugin[Spring Boot Gradle plugin] or the http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#build-tool-plugins-maven-plugin[Spring Boot Maven plugin].
-When using Spring Boot, Spring Data REST gets configured automatically.
+When you use Spring Boot, Spring Data REST gets configured automatically.
[[getting-started.gradle]]
== Adding Spring Data REST to a Gradle project
-To add Spring Data REST to a Gradle-based project, add the `spring-data-rest-webmvc` artifact to your compile-time dependencies:
+To add Spring Data REST to a Gradle-based project, add the `spring-data-rest-webmvc` artifact to your compile-time dependencies, as follows:
+====
[source,groovy,subs="verbatim,attributes"]
----
dependencies {
@@ -50,12 +54,14 @@ dependencies {
compile("org.springframework.data:spring-data-rest-webmvc:{version}")
}
----
+====
[[getting-started.maven]]
== Adding Spring Data REST to a Maven project
-To add Spring Data REST to a Maven-based project, add the `spring-data-rest-webmvc` artifact to your compile-time dependencies:
+To add Spring Data REST to a Maven-based project, add the `spring-data-rest-webmvc` artifact to your compile-time dependencies, as follows:
+====
[source,xml,subs="verbatim,attributes"]
----
@@ -64,50 +70,61 @@ To add Spring Data REST to a Maven-based project, add the `spring-data-rest-webm
{version}
----
+====
[[getting-started.configuration]]
== Configuring Spring Data REST
To install Spring Data REST alongside your existing Spring MVC application, you need to include the appropriate MVC configuration.
-Spring Data REST configuration is defined in a class called `RepositoryRestMvcConfiguration` and that class can just be imported into your applications configuration.
+Spring Data REST configuration is defined in a class called `RepositoryRestMvcConfiguration` and you can import that class into your application's configuration.
-IMPORTANT: This step is unnecessary if you are using Spring Boot's auto-configuration. Spring Boot will automatically enable Spring Data REST when you include *spring-boot-starter-data-rest* and either in your list of dependencies, and you your app is flagged with either `@SpringBootApplication` or `@EnableAutoConfiguration`.
+IMPORTANT: This step is unnecessary if you use Spring Boot's auto-configuration. Spring Boot automatically enables Spring Data REST when you include *spring-boot-starter-data-rest* and, in your list of dependencies, your app is flagged with either `@SpringBootApplication` or `@EnableAutoConfiguration`.
To customize the configuration, register a `RepositoryRestConfigurer` (or extend `RepositoryRestConfigurerAdapter`) and implement or override the `configure…`-methods relevant to your use case.
-Make sure you also configure Spring Data repositories for the store you use. For details on that, please consult the reference documentation for the http://projects.spring.io/spring-data/[corresponding Spring Data module].
+Make sure you also configure Spring Data repositories for the store you use. For details on that, see the reference documentation for the http://projects.spring.io/spring-data/[corresponding Spring Data module].
[[getting-started.basic-settings]]
-== Basic settings for Spring Data REST
+== Basic Settings for Spring Data REST
-=== Which repositories get exposed by defaults?
+This section covers the basic settings that you can manipulate when you configure a Spring Data REST application, including:
-Spring Data REST uses a `RepositoryDetectionStrategy` to determine if a repository will be exported as REST resource or not. The following strategies (enumeration values of `RepositoryDiscoveryStrategies`) are available:
+* <>
+* <>
+* <>
+
+[[getting-started.setting-repository-detection-strategy]]
+=== Setting the Repository Detection Strategy
+
+Spring Data REST uses a `RepositoryDetectionStrategy` to determine whether a repository is exported as a REST resource. The `RepositoryDiscoveryStrategies` enumeration includes the following values:
.Repository detection strategies
[cols="1,5". options="header"]
|===
| Name | Description
-
-| `DEFAULT` | Exposes all public repository interfaces but considers `@(Repository)RestResource`'s `exported` flag.
+| `DEFAULT` | Exposes all public repository interfaces but considers the `exported` flag of `@(Repository)RestResource`.
| `ALL` | Exposes all repositories independently of type visibility and annotations.
| `ANNOTATION` | Only repositories annotated with `@(Repository)RestResource` are exposed, unless their `exported` flag is set to `false`.
| `VISIBILITY` | Only public repositories annotated are exposed.
|===
-=== Changing the base URI
+[[getting-started.changing-base-uri]]
+=== Changing the Base URI
-By default, Spring Data REST serves up REST resources at the root URI, "/". There are multiple ways to change the base path.
+By default, Spring Data REST serves up REST resources at the root URI, '/'. There are multiple ways to change the base path.
-With Spring Boot 1.2+, all it takes is a single property in `application.properties`:
+With Spring Boot 1.2 and later versions, you can do change the base URI by setting a single property in `application.properties`, as follows:
+====
[source,properties]
----
spring.data.rest.basePath=/api
----
+====
-With Spring Boot 1.1 or earlier, or if you are not using Spring Boot, simply do this:
+With Spring Boot 1.1 or earlier, or if you are not using Spring Boot, you can do the following:
+====
[source,java]
----
@Configuration
@@ -126,9 +143,11 @@ class CustomRestMvcConfiguration {
}
}
----
+====
-Alternatively just register a custom implementation of `RepositoryRestConfigurer` as Spring bean and make sure it gets picked up by component scanning:
+Alternatively, you can register a custom implementation of `RepositoryRestConfigurer` as a Spring bean and make sure it gets picked up by component scanning, as follows:
+====
[source,java]
----
@Component
@@ -140,31 +159,32 @@ public class CustomizedRestMvcConfiguration extends RepositoryRestConfigurerAdap
}
}
----
+====
-Both of these approaches will change the base path to `/api`.
+Both of the preceding approaches change the base path to `/api`.
-=== Changing other Spring Data REST properties
+[[getting-started.changing-other-properties]]
+=== Changing Other Spring Data REST Properties
-There are many properties you can alter:
+You can alter the following properties:
.Spring Boot configurable properties
[cols="1,5". options="header"]
|===
-| Name | Description
-
-| basePath | root URI for Spring Data REST
-| defaultPageSize | change default number of items served in a single page
-| maxPageSize | change maximum number of items in a single page
-| pageParamName | change name of the query parameter for selecting pages
-| limitParamName | change name of the query parameter for number of items to show in a page
-| sortParamName | change name of the query parameter for sorting
-| defaultMediaType | change default media type to use when none is specified
-| returnBodyOnCreate | change if a body should be returned on creating a new entity
-| returnBodyOnUpdate | change if a body should be returned on updating an entity
+| Property | Description
+| `basePath` | the root URI for Spring Data REST
+| `defaultPageSize` | change the default for the number of items served in a single page
+| `maxPageSize` | change the maximum number of items in a single page
+| `pageParamName` | change the name of the query parameter for selecting pages
+| `limitParamName` | change the name of the query parameter for the number of items to show in a page
+| `sortParamName` | change the name of the query parameter for sorting
+| `defaultMediaType` | change the default media type to use when none is specified
+| `returnBodyOnCreate` | change whether a body should be returned when creating a new entity
+| `returnBodyOnUpdate` | change whether a body should be returned when updating an entity
|===
[[getting-started.bootstrap]]
-== Starting the application
+== Starting the Application
At this point, you must also configure your key data store.
@@ -176,7 +196,7 @@ Spring Data REST officially supports:
* http://projects.spring.io/spring-data-gemfire/[Spring Data GemFire]
* http://projects.spring.io/spring-data-cassandra/[Spring Data Cassandra]
-Here are some Getting Started guides to help you get up and running quickly:
+The following Getting Started guides can help you get up and running quickly:
* https://spring.io/guides/gs/accessing-data-rest/[Spring Data JPA]
* https://spring.io/guides/gs/accessing-mongodb-data-rest/[Spring Data MongoDB]
@@ -185,8 +205,8 @@ Here are some Getting Started guides to help you get up and running quickly:
These linked guides introduce how to add dependencies for the related data store, configure domain objects, and define repositories.
-You can run your application as either a Spring Boot app (with links showns above) or configure it as a classic Spring MVC app.
+You can run your application as either a Spring Boot app (with the links shown earlier) or configure it as a classic Spring MVC app.
-NOTE: In general Spring Data REST doesn't add functionality to a given data store. This means that by definition, it should work with any Spring Data project that supports the Repository programming model. The data stores listed above are simply the ones we have written integration tests to verify.
+NOTE: In general, Spring Data REST does not add functionality to a given data store. This means that, by definition, it should work with any Spring Data project that supports the repository programming model. The data stores listed above are the ones for which we have written integration tests to verify that Spring Data REST works with them.
-From this point, you can are free to <> with various options.
+From this point, you can <> with various options.
diff --git a/src/main/asciidoc/images/epub-cover.png b/src/main/asciidoc/images/epub-cover.png
new file mode 100644
index 000000000..9dd6651ca
Binary files /dev/null and b/src/main/asciidoc/images/epub-cover.png differ
diff --git a/src/main/asciidoc/images/epub-cover.svg b/src/main/asciidoc/images/epub-cover.svg
new file mode 100644
index 000000000..69cbf6946
--- /dev/null
+++ b/src/main/asciidoc/images/epub-cover.svg
@@ -0,0 +1,9 @@
+
+
+
diff --git a/src/main/asciidoc/index.adoc b/src/main/asciidoc/index.adoc
index 63cdab229..ff37b3524 100644
--- a/src/main/asciidoc/index.adoc
+++ b/src/main/asciidoc/index.adoc
@@ -1,22 +1,25 @@
[[spring-data-rest-reference]]
-= Spring Data REST - Reference Documentation
-Jon Brisbin, Oliver Gierke, Greg Turnquist
+= Spring Data REST Reference Guide
+Jon Brisbin, Oliver Gierke, Greg Turnquist, Jay Bryant
:revnumber: {version}
:revdate: {localdate}
+:linkcss:
+:doctype: book
+:docinfo: shared
:toc:
:toc-placement!:
+:source-highlighter: prettify
+:icons: font
+:imagesdir: images
+ifdef::backend-epub3[:front-cover-image: image:epub-cover.png[Front Cover,1050,1600]]
:spring-data-commons-docs: ../../../../spring-data-commons/src/main/asciidoc
-(C) 2012-2015 Original authors
+(C) 2012-2018 Original authors
-NOTE: _Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically._
-
-toc::[]
+NOTE: Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.
include::preface.adoc[]
-:leveloffset: +1
-include::{spring-data-commons-docs}/dependencies.adoc[]
-:leveloffset: -1
+include::{spring-data-commons-docs}/dependencies.adoc[leveloffset=+1]
[[reference]]
= Reference Documentation
@@ -41,4 +44,4 @@ include::customizing-sdr.adoc[leveloffset=+1]
:numbered!:
include::example-api-usage-with-curl.adoc[leveloffset=+1]
-include::spring-data-rest-examples.adoc[leveloffset=+1]
\ No newline at end of file
+include::spring-data-rest-examples.adoc[leveloffset=+1]
diff --git a/src/main/asciidoc/integration.adoc b/src/main/asciidoc/integration.adoc
index eee248751..6c3a57f24 100644
--- a/src/main/asciidoc/integration.adoc
+++ b/src/main/asciidoc/integration.adoc
@@ -6,16 +6,17 @@ This section details various ways to integrate with Spring Data REST components,
== Programmatic Links
-Sometimes you need to add links to exported resources in your own custom built Spring MVC controllers. There are three basic levels of linking available:
+Sometimes you need to add links to exported resources in your own custom-built Spring MVC controllers. There are three basic levels of linking available:
-. Manually assembling links
-. Using Spring HATEOAS's http://docs.spring.io/spring-hateoas/docs/current/reference/html/#fundamentals.obtaining-links.builder[LinkBuilder] with `linkTo()`, `slash()`, etc.
-. Using Spring Data REST's implementation of http://docs.spring.io/spring-data/rest/docs/current/api/org/springframework/data/rest/webmvc/support/RepositoryEntityLinks.html[RepositoryEntityLinks].
+* Manually assembling links.
+* Using Spring HATEOAS's http://docs.spring.io/spring-hateoas/docs/current/reference/html/#fundamentals.obtaining-links.builder[`LinkBuilder`] with `linkTo()`, `slash()`, and so on.
+* Using Spring Data REST's implementation of http://docs.spring.io/spring-data/rest/docs/current/api/org/springframework/data/rest/webmvc/support/RepositoryEntityLinks.html[`RepositoryEntityLinks`].
-The first suggestion is terrible and should be avoided at all costs. It makes your code brittle and high risk. The second is handy when creating links to other hand written Spring MVC controllers. The last one, which you'll see in a moment, is good for looking up resource links that are exported by Spring Data REST.
+The first suggestion is terrible and should be avoided at all costs. It makes your code brittle and high-risk. The second is handy when creating links to other hand-written Spring MVC controllers. The last one, which we explore in the rest of this section, is good for looking up resource links that are exported by Spring Data REST.
-Assuming you have configured your code to use Spring's autowiring,
+Consider the following class ,which uses Spring's autowiring:
+====
[source,java]
----
public class MyWebApp {
@@ -28,15 +29,16 @@ public class MyWebApp {
}
}
----
+====
-...you can then use the following operations:
+With the class in the preceding example, you can use the following operations:
.Ways to link to exported resources
|===
|Method | Description
|`entityLinks.linkToCollectionResource(Person.class)`
-|Provide a link to the collection resource of that type.
+|Provide a link to the collection resource of the specified type (`Person`, in this case).
|`entityLinks.linkToSingleResource(Person.class, 1)`
|Provide a link to a single resource.
@@ -48,8 +50,8 @@ public class MyWebApp {
|Provides a list of links for all the finder methods exposed by the corresponding repository.
|`entityLinks.linkToSearchResource(Person.class, "findByLastName")`
-|Provide a finder link by rel, i.e. the name of the finder.
+|Provide a finder link by `rel` (that is, the name of the finder).
|===
-NOTE: All of the search-based links support extra parameters for paging and sorting. Checkout http://docs.spring.io/spring-data/rest/docs/current/api/org/springframework/data/rest/webmvc/support/RepositoryEntityLinks.html[RepositoryEntityLinks] for specifics. There is also `linkFor(Class> type)`, but that returns a Spring HATEOAS `LinkBuilder`, which returns you to the lower level API. Try to use the other ones first.
+NOTE: All of the search-based links support extra parameters for paging and sorting. See http://docs.spring.io/spring-data/rest/docs/current/api/org/springframework/data/rest/webmvc/support/RepositoryEntityLinks.html[`RepositoryEntityLinks`] for the details. There is also `linkFor(Class> type)`, but that returns a Spring HATEOAS `LinkBuilder`, which returns you to the lower level API. Try to use the other ones first.
diff --git a/src/main/asciidoc/intro.adoc b/src/main/asciidoc/intro.adoc
index ff100b150..013d4f2df 100644
--- a/src/main/asciidoc/intro.adoc
+++ b/src/main/asciidoc/intro.adoc
@@ -1,6 +1,6 @@
[[intro-chapter]]
= Introduction
-REST web services have become the number one means for application integration on the web. In its core, REST defines that a system consists of resources that clients interact with. These resources are implemented in a hypermedia driven way. Spring MVC offers a solid foundation to build theses kinds of services. But implementing even the simplest tenet of REST web services for a multi-domain object system can be quite tedious and result in a lot of boilerplate code.
+REST web services have become the number one means for application integration on the web. In its core, REST defines that a system that consists of resources with which clients interact. These resources are implemented in a hypermedia-driven way. https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/web.html#spring-web[Spring MVC] and https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/web-reactive.html#spring-webflux[Spring WebFlux] each offer a solid foundation to build theses kinds of services. However, implementing even the simplest tenet of REST web services for a multi-domain object system can be quite tedious and result in a lot of boilerplate code.
-Spring Data REST builds on top of Spring Data repositories and automatically exports those as REST resources. It leverages hypermedia to allow clients to find functionality exposed by the repositories and integrates these resources into related hypermedia based functionality automatically.
\ No newline at end of file
+Spring Data REST builds on top of the Spring Data repositories and automatically exports those as REST resources. It leverages hypermedia to let clients automatically find functionality exposed by the repositories and integrate these resources into related hypermedia-based functionality.
diff --git a/src/main/asciidoc/metadata.adoc b/src/main/asciidoc/metadata.adoc
index 0e68363a2..9ca8d41ac 100644
--- a/src/main/asciidoc/metadata.adoc
+++ b/src/main/asciidoc/metadata.adoc
@@ -10,11 +10,12 @@ This section details the various forms of metadata provided by a Spring Data RES
http://alps.io/[ALPS] is a data format for defining simple descriptions of application-level semantics, similar in complexity to HTML microformats. An ALPS document can be used as a profile to explain the application semantics of a document with an application-agnostic media type (such as HTML, HAL, Collection+JSON, Siren, etc.). This increases the reusability of profile documents across media types.
Spring Data REST provides an ALPS document for every exported repository. It contains information about both the RESTful transitions
-as well as the attributes of each repository.
+and the attributes of each repository.
-At the root of a Spring Data REST app is a *profile* link. Assuming you had an app with both *persons* and related *addresses*, the root
-document would look like this:
+At the root of a Spring Data REST app is a profile link. Assuming you had an app with both `persons` and related `addresses`, the root
+document would be as follows:
+====
[source,javascript]
----
{
@@ -31,13 +32,15 @@ document would look like this:
}
}
----
+====
-A *profile* link, as defined in https://tools.ietf.org/html/rfc6906[RFC 6906], is a place to include application level details. The
-http://tools.ietf.org/html/draft-amundsen-richardson-foster-alps-00[ALPS draft spec] is meant to define a particular profile format
-which we'll explore further down in this section.
+A profile link, as defined in https://tools.ietf.org/html/rfc6906[RFC 6906], is a place to include application-level details. The
+http://tools.ietf.org/html/draft-amundsen-richardson-foster-alps-00[ALPS draft spec] is meant to define a particular profile format,
+which we explore later in this section.
-If you navigate into the *profile* link at `localhost:8080/profile`, you would see something like this:
+If you navigate into the profile link at `localhost:8080/profile`, you see content resembling the following:
+====
[source,javascript]
----
{
@@ -54,12 +57,14 @@ If you navigate into the *profile* link at `localhost:8080/profile`, you would s
}
}
----
+====
-IMPORTANT: At the root level, *profile* is a single link and hence can't handle serving up more than one application profile. That
+IMPORTANT: At the root level, `profile` is a single link and cannot serve up more than one application profile. That
is why you must navigate to `/profile` to find a link for each resource's metadata.
-Let's navigate to `/profile/persons` and look at the profile data for a `Person` resource.
+If you navigate to `/profile/persons` and look at the profile data for a `Person` resource, you see content resembling the following example:
+====
[source,javascript]
----
{
@@ -114,17 +119,19 @@ Let's navigate to `/profile/persons` and look at the profile data for a `Person`
}
----
-<1> At the top is a detailed listing of the attributes of a `Person` resource, identified as `#person-representation`. It lists the names
+<1> A detailed listing of the attributes of a `Person` resource, identified as `#person-representation`, lists the names
of the attributes.
-<2> After the resource representation are all the supported operations. This one is how to create a new `Person`.
-<3> The name is *persons*, which indicates that a POST should be applied to the whole collection, not a single *person*.
-<4> The *type* is `UNSAFE` because this operation can alter the state of the system.
+<2> The supported operations. This one indicates how to create a new `Person`.
+<3> The `name` is `persons`, which indicates (because it is plural) that a POST should be applied to the whole collection, not a single `person`.
+<4> The `type` is `UNSAFE`, because this operation can alter the state of the system.
+====
-NOTE: This JSON document has a media type of `application/alps+json`. This is different than the previous JSON document, which had
+NOTE: This JSON document has a media type of `application/alps+json`. This is different from the previous JSON document, which had
a media type of `application/hal+json`. These formats are different and governed by different specs.
-You will also find a "profile" link shown in the collection of *_links* when you are looking at a collection resource.
+You can also find a `profile` link in the collection of `_links` when you examine a collection resource, as the following example shows:
+====
[source,javascript]
----
{
@@ -143,11 +150,12 @@ You will also find a "profile" link shown in the collection of *_links* when you
<1> This HAL document respresents the `Person` collection.
<2> It has a *profile* link to the same URI for metadata.
+====
-The *profile* link, again, will serve up ALPS by default or if you use an http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1[Accept header] of *application/alps+json*.
+Again, by default, the `profile` link serves up ALPS. However, if you use an http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1[`Accept` header], it can serve `application/alps+json`.
[[metadata.alps.control-types]]
-=== Hypermedia control types
+=== Hypermedia Control Types
ALPS displays types for each hypermedia control. They include:
@@ -156,23 +164,24 @@ ALPS displays types for each hypermedia control. They include:
|===
| Type | Description
-| SEMANTIC | A state element (e.g. HTML.SPAN, HTML.INPUT, etc.).
-| SAFE | A hypermedia control that triggers a safe, idempotent state transition (e.g. *GET* or *HEAD*).
-| IDEMPOTENT | A hypermedia control that triggers an unsafe, idempotent state transition (e.g. *PUT* or *DELETE*).
-| UNSAFE | A hypermedia control that triggers an unsafe, non-idempotent state transition (e.g. *POST*).
+| SEMANTIC | A state element (such as `HTML.SPAN`, `HTML.INPUT`, and others).
+| SAFE | A hypermedia control that triggers a safe, idempotent state transition (such as `GET` or `HEAD`).
+| IDEMPOTENT | A hypermedia control that triggers an unsafe, idempotent state transition (such as `PUT` or `DELETE`).
+| UNSAFE | A hypermedia control that triggers an unsafe, non-idempotent state transition (such as `POST`).
|===
-In the representation section up above, bits of data from the application are marked *SEMANTIC*. The *address* field
-is a link that involves a safe *GET* to retrive. Hence, it is marked *SAFE*. Hypermedia operations themselves map onto the types as
-shown the table.
+In the representation section shown earlier, bits of data from the application are marked as being `SEMANTIC`. The `address` field
+is a link that involves a safe `GET` to retrieve. Consequently, it is marked as being `SAFE`. Hypermedia operations themselves map onto the types as
+shown in the preceding table.
[[metadata.alps.projections]]
=== ALPS with Projections
-If you define any projections, they are also listed in the ALPS metadata. Assuming we also defined *inlineAddress* and *noAddresses*, they
-would appear inside the relevant operations, i.e. *GET* for the whole collection as well *GET* for a single resource. The following shows
-the alternate version of the *get-persons* subsection:
+If you define any projections, they are also listed in the ALPS metadata. Assuming we also defined `inlineAddress` and `noAddresses`, they
+would appear inside the relevant operations. (See "`<>`" for the definitions and discussion of these two projections.) That is *GET* would appear in the operations for the whole collection, and *GET* would appear in the operations for a single resource. The following example shows
+the alternate version of the `get-persons` subsection:
+====
[source,javascript]
----
...
@@ -217,19 +226,21 @@ the alternate version of the *get-persons* subsection:
...
----
-<1> A new attribute, *descriptors*, appears containing an array with one entry, *projection*.
-<2> Inside the *projection.descriptors* we can see *inLineAddress* listed. It will render *address*, *firstName*, and *lastName*.
-Relationships rendered inside a projection result in inlining the data fields.
-<3> Also found is *noAddresses*, which serves up a subset containing *firstName* and *lastName*.
+<1> A new attribute, `descriptors`, appears, containing an array with one entry, `projection`.
+<2> Inside the `projection.descriptors`, we can see `inLineAddress`. It render `address`, `firstName`, and `lastName`.
+Relationships rendered inside a projection result in including the data fields inline.
+<3> `noAddresses` serves up a subset that contains `firstName` and `lastName`.
+====
-With all this information, a client should be able to deduce not only the RESTful transitions avaiable, but also, to some degree, the
-data elements needed to interact.
+With all this information, a client can deduce not only the available RESTful transitions but also, to some degree, the
+data elements needed to interact with the back end.
[[metadata.alps.descriptions]]
-=== Adding custom details to your ALPS descriptions
+=== Adding Custom Details to Your ALPS Descriptions
-It's possible to create custom messages that appear in your ALPS metadata. Just create `rest-messages.properties` like this:
+You can create custom messages that appear in your ALPS metadata. To do so, create `rest-messages.properties`, as follows:
+====
[source,properties]
----
rest.description.person=A collection of people
@@ -238,9 +249,11 @@ rest.description.person.firstName=Person's first name
rest.description.person.lastName=Person's last name
rest.description.person.address=Person's address
----
+====
-As you can see, this defines details to display for a `Person` resource. They alter the ALPS format of the *person-representation* as follows:
+These `rest.description.*` properties define details to display for a `Person` resource. They alter the ALPS format of the `person-representation`, as follows:
+====
[source,javascript]
----
...
@@ -284,13 +297,14 @@ As you can see, this defines details to display for a `Person` resource. They al
...
----
-By supplying these property settings, each field has an extra *doc* attribute.
-
<1> The value of `rest.description.person` maps into the whole representation.
-<2> The value of `rest.description.person.firstName` maps to the *firstName* attribute.
-<3> The value of `rest.description.person.lastName` maps to the *lastName* attribute.
-<4> The value of `rest.description.person.id` maps to the *id* attribute, a field not normally displayed.
-<5> The value of `rest.description.person.address` maps to the *address* attribute.
+<2> The value of `rest.description.person.firstName` maps to the `firstName` attribute.
+<3> The value of `rest.description.person.lastName` maps to the `lastName` attribute.
+<4> The value of `rest.description.person.id` maps to the `id` attribute, a field not normally displayed.
+<5> The value of `rest.description.person.address` maps to the `address` attribute.
+====
+
+Supplying these property settings causes each field to have an extra `doc` attribute.
NOTE: Spring MVC (which is the essence of a Spring Data REST application) supports locales, meaning you can bundle up multiple
properties files with different messages.
@@ -301,12 +315,13 @@ properties files with different messages.
http://json-schema.org/[JSON Schema] is another form of metadata supported by Spring Data REST. Per their website, JSON Schema has the following advantages:
-* describes your existing data format
-* clear, human- and machine-readable documentation
-* complete structural validation, useful for automated testing and validating client-submitted data
+* Describes your existing data format
+* Clear, human- and machine-readable documentation
+* Complete structural validation, useful for automated testing and validating client-submitted data
-As shown in the <>, you can reach this data by navigating from the root URI to the "profile" link.
+As shown in the <>, you can reach this data by navigating from the root URI to the `profile` link.
+====
[source,javascript]
----
{
@@ -323,11 +338,13 @@ As shown in the <>, you can reach this data by n
}
}
----
+====
-These links are the same as shown earlier. To retrieve JSON Schema you invoke them with Accept header *application/schema+json*.
+These links are the same as shown earlier. To retrieve JSON Schema, you can invoke them with the following `Accept` header: `application/schema+json`.
-In this case, if you executed `curl -H 'Accept:application/schema+json' http://localhost:8080/profile/persons`, you would see something like this:
+In this case, if you executed `curl -H 'Accept:application/schema+json' http://localhost:8080/profile/persons`, you would see output resembling the following:
+====
[source,javascript]
----
{
@@ -373,11 +390,13 @@ In this case, if you executed `curl -H 'Accept:application/schema+json' http://l
<1> The type that was exported
<2> A listing of properties
+====
There are more details if your resources have links to other resources.
-You will also find a "profile" link shown in the collection of *_links* when you are looking at a collection resource.
+You can also find a `profile` link in the collection of `_links` when you examine a collection resource, as the following example shows:
+====
[source,javascript]
----
{
@@ -396,8 +415,9 @@ You will also find a "profile" link shown in the collection of *_links* when you
<1> This HAL document respresents the `Person` collection.
<2> It has a *profile* link to the same URI for metadata.
+====
-The *profile* link, again, will serve up <> by default. If you supply it with an http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1[Accept header] of *application/schema+json*, it will render the JSON Schema representation.
+Again, the `profile` link serves <> by default. If you supply it with an http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1[`Accept` header] of `application/schema+json`, it renders the JSON Schema representation.
//= JSON Patch
diff --git a/src/main/asciidoc/overriding-sdr-response-handlers.adoc b/src/main/asciidoc/overriding-sdr-response-handlers.adoc
index cdba19600..e6dfeb313 100644
--- a/src/main/asciidoc/overriding-sdr-response-handlers.adoc
+++ b/src/main/asciidoc/overriding-sdr-response-handlers.adoc
@@ -1,8 +1,9 @@
[[customizing-sdr.overriding-sdr-response-handlers]]
= Overriding Spring Data REST Response Handlers
-Sometimes you may want to write a custom handler for a specific resource. To take advantage of Spring Data REST's settings, message converters, exception handling, and more, use the `@RepositoryRestController` annotation instead of a standard Spring MVC `@Controller` or `@RestController`:
+Sometimes, you may want to write a custom handler for a specific resource. To take advantage of Spring Data REST's settings, message converters, exception handling, and more, use the `@RepositoryRestController` annotation instead of a standard Spring MVC `@Controller` or `@RestController`. Controllers annotated with `@RepositoryRestController` are served from the API base path defined in `RepositoryRestConfiguration.setBasePath`, which is used by all other RESTful endpoints (for example, `/api`). The following example shows how to use the `@RepositoryRestController` annotation:
+====
[source,java]
----
@RepositoryRestController
@@ -35,19 +36,18 @@ public class ScannerController {
}
----
-This controller will be served from the same API base path defined in `RepositoryRestConfiguration.setBasePath` that is used by all other RESTful endpoints (e.g. */api*). It also has these characteristics:
-
<1> This example uses constructor injection.
<2> This handler plugs in a custom handler for a Spring Data finder method.
-<3> This handler is using the underlying repository to fetch data, but will then do some form of post processing before returning the final data set to the client.
-<4> The results need to be wrapped up in a Spring HATEOAS `Resources` object to return a collection, but only a `Resource` for a single item.
-<5> Add a link back to this exact method as a "self" link.
-<6> Returning the collection using Spring MVC's `ResponseEntity` wrapper ensure the collection is properly wrapped and rendered in the proper accept type.
+<3> This handler uses the underlying repository to fetch data, but then does some form of post processing before returning the final data set to the client.
+<4> The results need to be wrapped up in a Spring HATEOAS `Resources` object to return a collection but only a `Resource` for a single item.
+<5> Add a link back to this exact method as a `self` link.
+<6> Returning the collection by using Spring MVC's `ResponseEntity` wrapper ensures that the collection is properly wrapped and rendered in the proper accept type.
+====
-`Resources` is for a collection while `Resource` is for a single item. These types can be combined. If you know the links for each item in a collection, use `Resources>` (or whatever the core domain type is). This lets you assemble links for each item as well as for the whole collection.
+`Resources` is for a collection, while `Resource` is for a single item. These types can be combined. If you know the links for each item in a collection, use `Resources>` (or whatever the core domain type is rather than `String`). Doing so lets you assemble links for each item as well as for the whole collection.
-IMPORTANT: In this example, the combined path will be `RepositoryRestConfiguration.getBasePath()` + `/scanners/search/listProducers`.
+IMPORTANT: In this example, the combined path is `RepositoryRestConfiguration.getBasePath()` + `/scanners/search/listProducers`.
-If you're NOT interested in entity-specific operations but still want to build custom operations underneath `basePath`, such as Spring MVC views, resources, etc. use `@BasePathAwareController`.
+If you are not interested in entity-specific operations but still want to build custom operations underneath `basePath`, such as Spring MVC views, resources, and others, use `@BasePathAwareController`.
-WARNING: If you use `@Controller` or `@RestController` for anything, that code will be totally outside the scope of Spring Data REST. This extends to request handling, message converters, exception handling, etc.
\ No newline at end of file
+WARNING: If you use `@Controller` or `@RestController` for anything, that code is totally outside the scope of Spring Data REST. This extends to request handling, message converters, exception handling, and other uses.
diff --git a/src/main/asciidoc/paging-and-sorting.adoc b/src/main/asciidoc/paging-and-sorting.adoc
index 26a76c28b..e86e6682f 100644
--- a/src/main/asciidoc/paging-and-sorting.adoc
+++ b/src/main/asciidoc/paging-and-sorting.adoc
@@ -1,41 +1,48 @@
[[paging-and-sorting]]
= Paging and Sorting
-_This documents Spring Data REST's usage of the Spring Data Repository paging and sorting abstractions. To familiarize yourself with those features, please see the Spring Data documentation for the Repository implementation you're using._
+This section documents Spring Data REST's usage of the Spring Data Repository paging and sorting abstractions. To familiarize yourself with those features, see the Spring Data documentation for the repository implementation you use (such as Spring Data JPA).
== Paging
-Rather than return everything from a large result set, Spring Data REST recognizes some URL parameters that will influence the page size and starting page number.
+Rather than return everything from a large result set, Spring Data REST recognizes some URL parameters that influence the page size and the starting page number.
-If you extend `PagingAndSortingRepository` and access the list of all entities, you'll get links to the first 20 entities. To set the page size to any other number, add a `size` parameter:
+If you extend `PagingAndSortingRepository` and access the list of all entities, you get links to the first 20 entities. To set the page size to any other number, add a `size` parameter, as follows:
+====
----
http://localhost:8080/people/?size=5
----
+====
-This will set the page size to 5.
+The preceding example sets the page size to 5.
-To use paging in your own query methods, you need to change the method signature to accept an additional `Pageable` parameter and return a `Page` rather than a `List`. For example, the following query method will be exported to `/people/search/nameStartsWith` and will support paging:
+To use paging in your own query methods, you need to change the method signature to accept an additional `Pageable` parameter and return a `Page` rather than a `List`. For example, the following query method is exported to `/people/search/nameStartsWith` and supports paging:
+====
[source,java]
----
@RestResource(path = "nameStartsWith", rel = "nameStartsWith")
public Page findByNameStartsWith(@Param("name") String name, Pageable p);
----
+====
-The Spring Data REST exporter will recognize the returned `Page` and give you the results in the body of the response, just as it would with a non-paged response, but additional links will be added to the resource to represent the previous and next pages of data.
+The Spring Data REST exporter recognizes the returned `Page` and gives you the results in the body of the response, just as it would with a non-paged response, but additional links are added to the resource to represent the previous and next pages of data.
[[paging-and-sorting.prev-and-next-links]]
=== Previous and Next Links
-Each paged response will return links to the previous and next pages of results based on the current page using the IANA defined link relations http://www.w3.org/TR/html5/links.html#link-type-prev[`prev`] and http://www.w3.org/TR/html5/links.html#link-type-next[`next`]. If you are currently at the first page of results, however, no `prev` link will be rendered. The same is true for the last page of results: no `next` link will be rendered.
+Each paged response returns links to the previous and next pages of results based on the current page by using the IANA-defined link relations http://www.w3.org/TR/html5/links.html#link-type-prev[`prev`] and http://www.w3.org/TR/html5/links.html#link-type-next[`next`]. If you are currently at the first page of results, however, no `prev` link is rendered. For the last page of results, no `next` link is rendered.
-Look at the following example, where we set the page size to 5:
+Consider the following example, where we set the page size to 5:
+====
----
curl localhost:8080/people?size=5
----
+====
+====
[source,javascript]
----
{
@@ -63,22 +70,26 @@ curl localhost:8080/people?size=5
At the top, we see `_links`:
-<1> This `self` link serves up the whole collection with some options
-<2> This `next` link points to the next page, assuming the same page size.
+<1> The `self` link serves up the whole collection with some options.
+<2> The `next` link points to the next page, assuming the same page size.
<3> At the bottom is extra data about the page settings, including the size of a page, total elements, total pages, and the page number you are currently viewing.
+====
-NOTE: When using tools like *curl* on the command line, if you have a "&" in your statement, wrap the whole URI with quotes.
+NOTE: When using tools such as `curl` on the command line, if you have a ampersand (`&`) in your statement, you need to wrap the whole URI in quotation marks.
-It's also important to notice that the `self` and `next` URIs are, in fact, URI templates. They accept not only `size`, but also `page`, `sort` as optional flags.
+Note that the `self` and `next` URIs are, in fact, URI templates. They accept not only `size`, but also `page` and `sort` as optional flags.
-As mentioned, at the bottom of the HAL document, is a collection of details about the page. This extra information makes it very easy for you to configure UI tools like sliders or indicators to reflect overall position the user is in viewing the data. For example, the document above shows we are looking at the first page (with page numbers indexed to 0 being the first).
+As mentioned earlier, the bottom of the HAL document includes a collection of details about the page. This extra information makes it easy for you to configure UI tools like sliders or indicators to reflect the user's overall position when they view the data. For example, the document in the preceding example shows we are looking at the first page (with page numbers starting at 0).
-What happens if we follow the `next` link?
+The following example shows What happens when we follow the `next` link:
+====
----
$ curl "http://localhost:8080/persons?page=1&size=5"
----
+====
+====
[source,javascript]
----
{
@@ -110,21 +121,24 @@ $ curl "http://localhost:8080/persons?page=1&size=5"
This looks very similar, except for the following differences:
-<1> The `next` link now points to yet another page, indicating it's relative perspective to the `self` link.
+<1> The `next` link now points to yet another page, indicating its relative perspective to the `self` link.
<2> A `prev` link now appears, giving us a path to the previous page.
<3> The current number is now 1 (indicating the second page).
+====
-This feature makes it quite easy to map optional buttons on the screen to these hypermedia controls, hence allowing easy navigational features for the UI experience without having to hard code the URIs. In fact, the user can be empowered to pick from a list of page sizes, dynamically changing the content served, without having to rewrite the `next` and `prev controls at the top or bottom.
+This feature lets you map optional buttons on the screen to these hypermedia controls, letting you implement navigational features for the UI experience without having to hard code the URIs. In fact, the user can be empowered to pick from a list of page sizes, dynamically changing the content served, without having to rewrite the `next` and `prev controls at the top or bottom.
[[paging-and-sorting.sorting]]
== Sorting
-Spring Data REST recognizes sorting parameters that will use the Repository sorting support.
+Spring Data REST recognizes sorting parameters that use the repository sorting support.
-To have your results sorted on a particular property, add a `sort` URL parameter with the name of the property you want to sort the results on. You can control the direction of the sort by appending a `,` to the the property name plus either `asc` or `desc`. The following would use the `findByNameStartsWith` query method defined on the `PersonRepository` for all `Person` entities with names starting with the letter "K" and add sort data that orders the results on the `name` property in descending order:
+To have your results sorted on a particular property, add a `sort` URL parameter with the name of the property on which you want to sort the results. You can control the direction of the sort by appending a comma (`,`) to the the property name plus either `asc` or `desc`. The following would use the `findByNameStartsWith` query method defined on the `PersonRepository` for all `Person` entities with names starting with the letter "`K`" and add sort data that orders the results on the `name` property in descending order:
+====
----
curl -v "http://localhost:8080/people/search/nameStartsWith?name=K&sort=name,desc"
----
+====
-To sort the results by more than one property, keep adding as many `sort=PROPERTY` parameters as you need. They will be added to the `Pageable` in the order they appear in the query string. Results can be sorted by top-level and nested properties. Use property path notation to express a nested sort property. Sorting by linkable associations (i.e. resources to top-level resources) is not supported.
\ No newline at end of file
+To sort the results by more than one property, keep adding as many `sort=PROPERTY` parameters as you need. They are added to the `Pageable` in the order in which they appear in the query string. Results can be sorted by top-level and nested properties. Use property path notation to express a nested sort property. Sorting by linkable associations (that is, links to top-level resources) is not supported.
diff --git a/src/main/asciidoc/preface.adoc b/src/main/asciidoc/preface.adoc
index 843e68823..cf6ba8e81 100644
--- a/src/main/asciidoc/preface.adoc
+++ b/src/main/asciidoc/preface.adoc
@@ -3,12 +3,11 @@
[[Project]]
[preface]
-== Project metadata
-
-* Version control - https://github.com/spring-projects/spring-data-rest
-* Bugtracker - https://jira.spring.io/browse/DATAREST
-* Project page - http://projects.spring.io/spring-data-rest
-* Release repository - https://repo.spring.io/libs-release
-* Milestone repository - https://repo.spring.io/libs-milestone
-* Snapshot repository - https://repo.spring.io/libs-snapshot
+== Project Metadata
+* Version control: https://github.com/spring-projects/spring-data-rest
+* Bugtracker: https://jira.spring.io/browse/DATAREST
+* Project page: http://projects.spring.io/spring-data-rest
+* Release repository: https://repo.spring.io/libs-release
+* Milestone repository: https://repo.spring.io/libs-milestone
+* Snapshot repository: https://repo.spring.io/libs-snapshot
diff --git a/src/main/asciidoc/projections-excerpts.adoc b/src/main/asciidoc/projections-excerpts.adoc
index 19384eaf2..0eebe32ec 100644
--- a/src/main/asciidoc/projections-excerpts.adoc
+++ b/src/main/asciidoc/projections-excerpts.adoc
@@ -1,13 +1,14 @@
[[projections-excerpts]]
= Projections and Excerpts
-Spring Data REST presents a default view of the domain model you are exporting. But sometimes, you may need to alter the view of that model for various reasons. In this section, you will learn how to define projections and excerpts to serve up simplified and reduced views of resources.
+Spring Data REST presents a default view of the domain model you export. However, sometimes, you may need to alter the view of that model for various reasons. This section covers how to define projections and excerpts to serve up simplified and reduced views of resources.
[[projections-excerpts.projections]]
== Projections
-Look at the following domain model:
+Consider the following domain model:
+====
[source,java]
----
@Entity
@@ -22,29 +23,35 @@ public class Person {
…
}
----
+====
-This `Person` has several attributes:
+The `Person` object in the preceding example has several attributes:
-* `id` is the primary key
-* `firstName` and `lastName` are data attributes
-* `address` is a link to another domain object
+* `id` is the primary key.
+* `firstName` and `lastName` are data attributes.
+* `address` is a link to another domain object.
-Now assume we create a corresponding repository as follows:
+Now assume that we create a corresponding repository, as follows:
+====
[source,java]
----
interface PersonRepository extends CrudRepository {}
----
+====
-By default, Spring Data REST will export this domain object including all of its attributes. `firstName` and `lastName` will be exported as the plain data objects that they are. There are two options regarding the `address` attribute. One option is to also define a repository for `Address` objects like this:
+By default, Spring Data REST exports this domain object, including all of its attributes. `firstName` and `lastName` are exported as the plain data objects that they are. There are two options regarding the `address` attribute. One option is to also define a repository for `Address` objects, as follows:
+====
[source,java]
----
interface AddressRepository extends CrudRepository {}
----
+====
-In this situation, a `Person` resource will render the `address` attribute as a URI to it's corresponding `Address` resource. If we were to look up "Frodo" in the system, we could expect to see a HAL document like this:
+In this situation, a `Person` resource renders the `address` attribute as a URI to its corresponding `Address` resource. If we were to look up "`Frodo`" in the system, we could expect to see a HAL document like this:
+====
[source,javascript]
----
{
@@ -60,9 +67,11 @@ In this situation, a `Person` resource will render the `address` attribute as a
}
}
----
+====
-There is another route. If the `Address` domain object does not have it's own repository definition, Spring Data REST will inline the data fields right inside the `Person` resource.
+There is another way. If the `Address` domain object does not have its own repository definition, Spring Data REST includes the data fields inside the `Person` resource, as the following example shows:
+====
[source,javascript]
----
{
@@ -80,9 +89,11 @@ There is another route. If the `Address` domain object does not have it's own re
}
}
----
+====
-But what if you don't want `address` details at all? Again, by default, Spring Data REST will export all its attributes (except the `id`). You can offer the consumer of your REST service an alternative by defining one or more projections.
+But what if you do not want `address` details at all? Again, by default, Spring Data REST exports all of its attributes (except the `id`). You can offer the consumer of your REST service an alternative by defining one or more projections. The following example shows a projection that does not include the address:
+====
[source,java]
----
@Projection(name = "noAddresses", types = { Person.class }) <1>
@@ -94,17 +105,16 @@ interface NoAddresses { <2>
}
----
-This projection has the following details:
-
-<1> The `@Projection` annotation flags this as a projection. The `name` attributes provides
-the name of the projection, which you'll see how to use shortly. The `types` attributes targets this projection to only apply to `Person` objects.
-
-<2> It's a Java interface making it declarative.
+<1> The `@Projection` annotation flags this as a projection. The `name` attribute provides
+the name of the projection, which we cover in more detail shortly. The `types` attributes targets this projection to apply only to `Person` objects.
+<2> It is a Java interface, making it declarative.
<3> It exports the `firstName`.
<4> It exports the `lastName`.
+====
-The `NoAddresses` projection only has getters for `firstName` and `lastName` meaning that it won't serve up any address information. Assuming you have a separate repository for `Address` resources, the default view from Spring Data REST is slightly different as shown below:
+The `NoAddresses` projection only has getters for `firstName` and `lastName`, meaning that it does not serve up any address information. Assuming you have a separate repository for `Address` resources, the default view from Spring Data REST differs slightly from the previous representation, as the following example shows:
+====
[source,javascript]
----
{
@@ -122,29 +132,31 @@ The `NoAddresses` projection only has getters for `firstName` and `lastName` mea
}
----
-<1> There is a new option listed for this resource, `{?projection}`.
+<1> This resource has a new option: `{?projection}`.
<2> The `self` URI is a URI Template.
+====
-To view apply the projection to the resource, look up `http://localhost:8080/persons/1?projection=noAddresses`.
+To view the projection to the resource, look up `http://localhost:8080/persons/1?projection=noAddresses`.
-NOTE: The value supplied to the `projection` query parameter is the same as specified in `@Projection(name = "noAddress")`. It has nothing to do with the name of the projection's interface.
+NOTE: The value supplied to the `projection` query parameter is the same as that specified in `@Projection(name = "noAddress")`. It has nothing to do with the name of the projection's interface.
-It's possible to have multiple projections.
+You can have multiple projections.
-NOTE: Visit <> to see an example project you can experiment with.
+NOTE: See <> to see an example project. We encourage you to experiment with it.
-How does Spring Data REST finds projection definitions?
+Spring Data REST finds projection definitions as follows:
-* Any `@Projection` interface found in the same package as your entity definitions (or one of it's sub-packages) is registered.
-* You can manually register via `RepositoryRestConfiguration.getProjectionConfiguration().addProjection(…)`.
+* Any `@Projection` interface found in the same package as your entity definitions (or one of its sub-packages) is registered.
+* You can manually register a projection by using `RepositoryRestConfiguration.getProjectionConfiguration().addProjection(…)`.
-In either situation, the interface with your projection MUST have the `@Projection` annotation.
+In either case, the projection interface must have the `@Projection` annotation.
[[projections-excerpts.finding-projections]]
-=== Finding existing projections
+=== Finding Existing Projections
-Spring Data REST exposes <> documents, a micro metadata format. To view the ALPS metadata, follow the `profile` link exposed by the root resource. If you navigate down to the ALPS document for `Person` resources (which would be `/alps/persons`), you can find many details about `Person` resources. Projections will be listed along with the details about the `GET` REST transition, something like this:
+Spring Data REST exposes <> documents, a micro metadata format. To view the ALPS metadata, follow the `profile` link exposed by the root resource. If you navigate down to the ALPS document for `Person` resources (which would be `/alps/persons`), you can find many details about `Person` resources. Projections are listed, along with the details about the `GET` REST transition, in blocks similar to the following example:
+====
[source,javascript]
----
{ …
@@ -176,23 +188,25 @@ Spring Data REST exposes <> documents, a micro metadata format. T
----
<1> This part of the ALPS document shows details about `GET` and `Person` resources.
-<2> Further down are the `projection` options.
-<3> Further down you can see projection `noAddresses` listed.
+<2> This part contais the `projection` options.
+<3> This part contains the `noAddresses` projection.
<4> The actual attributes served up by this projection include `firstName` and `lastName`.
+====
[NOTE]
====
-Projection definitions will be picked up and made available for clients if they are:
+Projection definitions are picked up and made available for clients if they are:
* Flagged with the `@Projection` annotation and located in the same package (or sub-package) of the domain type, OR
-* Manually registered via `RepositoryRestConfiguration.getProjectionConfiguration().addProjection(…)`.
+* Manually registered by using `RepositoryRestConfiguration.getProjectionConfiguration().addProjection(…)`.
====
[[projections-excerpts.projections.hidden-data]]
-=== Bringing in hidden data
+=== Bringing in Hidden Data
-So far, you have seen how projections can be used to reduce the information that is presented to the user. Projections can also bring in normally unseen data. For example, Spring Data REST will ignore fields or getters that are marked up with `@JsonIgnore` annotations. Look at the following domain object:
+So far in this section, we have covered how projections can be used to reduce the information that is presented to the user. Projections can also bring in normally unseen data. For example, Spring Data REST ignores fields or getters that are marked up with `@JsonIgnore` annotations. Consider the following domain object:
+====
[source,java]
----
@Entity
@@ -208,14 +222,16 @@ public class User {
…
----
-<1> Jackson's `@JsonIgnore` is used to prevent the `password` field from getting serialized into JSON.
+<1> Jackson's `@JsonIgnore` is used to prevent the `password` field from being serialized into JSON.
+====
-This `User` class can be used to store user information as well as integration with Spring Security. If you create a `UserRepository`, the `password` field would normally have been exported. Not good! In this example, we prevent that from happening by applying Jackson's `@JsonIgnore` on the `password` field.
+The `User` class in the preceding example can be used to store user information as well as integration with Spring Security. If you create a `UserRepository`, the `password` field would normally have been exported, which is not good. In the preceding example, we prevent that from happening by applying Jackson's `@JsonIgnore` on the `password` field.
-NOTE: Jackson will also not serialize the field into JSON if `@JsonIgnore` is on the field's corresponding getter function.
+NOTE: Jackson also does not serialize the field into JSON if `@JsonIgnore` is on the field's corresponding getter function.
-However, projections introduce the ability to still serve this field. It's possible to create a projection like this:
+However, projections introduce the ability to still serve this field. It is possible to create the following projection:
+====
[source,java]
----
@Projection(name = "passwords", types = { User.class })
@@ -224,13 +240,15 @@ interface PasswordProjection {
String getPassword();
}
----
+====
-If such a projection is created and used, it will side step the `@JsonIgnore` directive placed on `User.password`.
+If such a projection is created and used, it sidesteps the `@JsonIgnore` directive placed on `User.password`.
-IMPORTANT: This example may seem a bit contrived, but it's possible with a richer domain model and many projections, to accidentally leak such details. Since Spring Data REST cannot discern the sensitivity of such data, it is up to the developers to avoid such situations.
+IMPORTANT: This example may seem a bit contrived, but it is possible, with a richer domain model and many projections, to accidentally leak such details. Since Spring Data REST cannot discern the sensitivity of such data, it is up to you to avoid such situations.
Projections can also generate virtual data. Imagine you had the following entity definition:
+====
[source,java]
----
@Entity
@@ -243,9 +261,11 @@ public class Person {
...
}
----
+====
-You can create a projection that combines these two data fields together like this:
+You can create a projection that combines the two data fields in the preceding example together, as follows:
+====
[source,java]
----
@Projection(name = "virtual", types = { Person.class })
@@ -257,30 +277,34 @@ public interface VirtualProjection {
}
----
-<1> Spring's `@Value` annotation let's you plugin a SpEL expression that takes the target object, and splices together its `firstName` and `lastName` attributes to render a read-only `fullName`.
+<1> Spring's `@Value` annotation lets you plug in a SpEL expression that takes the target object and splices together its `firstName` and `lastName` attributes to render a read-only `fullName`.
+====
[[projections-excerpts.excerpts]]
== Excerpts
-An excerpt is a projection that is applied to a resource collection automatically. For an example, you can alter the `PersonRepository` as follows:
+An excerpt is a projection that is automatically applied to a resource collection. For example, you can alter the `PersonRepository` as follows:
+====
[source,java]
----
@RepositoryRestResource(excerptProjection = NoAddresses.class)
interface PersonRepository extends CrudRepository {}
----
+====
-This directs Spring Data REST to use the `NoAddresses` projection when embedding `Person` resources into collections or related resources.
+The preceding example directs Spring Data REST to use the `NoAddresses` projection when embedding `Person` resources into collections or related resources.
-NOTE: Excerpt projections are *NOT* applied to _single resources_ automatically. They have to be applied deliberately. Excerpt projections are meant to provide a default preview of collection data, but not when fetching individual resources. See http://stackoverflow.com/questions/30220333/why-is-an-excerpt-projection-not-applied-automatically-for-a-spring-data-rest-it[Why is an excerpt projection not applied automatically for a Spring Data REST item resource?] for a discussion on the subject.
+NOTE: Excerpt projections are not automatically applied to single resources. They have to be applied deliberately. Excerpt projections are meant to provide a default preview of collection data but not when fetching individual resources. See http://stackoverflow.com/questions/30220333/why-is-an-excerpt-projection-not-applied-automatically-for-a-spring-data-rest-it[Why is an excerpt projection not applied automatically for a Spring Data REST item resource?] for a discussion on the subject.
-In addition to altering the default rendering, excerpts have additional rendering options as shown below.
+In addition to altering the default rendering, excerpts have additional rendering options as shown in the next section.
[[projections-excerpts.excerpting-commonly-accessed-data]]
-== Excerpting commonly accessed data
+=== Excerpting Commonly Accessed Data
-A common situation with REST services arises when you compose domain objects. For example, a `Person` is stored in one table and their related `Address` is stored in another. By default, Spring Data REST will serve up the person's `address` as a URI the client must navigate. But if it's common for consumers to always fetch this extra piece of data, an excerpt projection can go ahead and inline this extra piece of data, saving you an extra `GET`. To do so, let's define another excerpt projection:
+A common situation with REST services arises when you compose domain objects. For example, a `Person` is stored in one table and their related `Address` is stored in another. By default, Spring Data REST serves up the person's `address` as a URI the client must navigate. But if it is common for consumers to always fetch this extra piece of data, an excerpt projection can put this extra piece of data inline, saving you an extra `GET`. To do so, you can define another excerpt projection, as follows:
+====
[source,java]
----
@Projection(name = "inlineAddress", types = { Person.class }) <1>
@@ -295,18 +319,22 @@ interface InlineAddress {
----
<1> This projection has been named `inlineAddress`.
-<2> This projection adds in `getAddress` which returns the `Address` field. When used inside a projection, it causes the information to be inlined.
+<2> This projection adds `getAddress`, which returns the `Address` field. When used inside a projection, it causes the information to be included inline.
+====
-We can plug it into the `PersonRepository` definition as follows:
+You can plug it into the `PersonRepository` definition, as follows:
+====
[source,java]
----
@RepositoryRestResource(excerptProjection = InlineAddress.class)
interface PersonRepository extends CrudRepository {}
----
+====
-This will cause the HAL document to appear as follows:
+Doing so causes the HAL document to appear as follows:
+====
[source,javascript]
----
{
@@ -328,9 +356,10 @@ This will cause the HAL document to appear as follows:
}
----
-This should appear as a mix of what you've seen so far.
-
-<1> The `address` data is inlined directly, so you don't have to navigate to get it.
+<1> The `address` data is directly included inline, so you do not have to navigate to get it.
<2> The link to the `Address` resource is still provided, making it still possible to navigate to its own resource.
+====
-WARNING: Configuring `@RepositoryRestResource(excerptProjection=...)` for a repository alters the default behavior. This can potentially case breaking change to consumers of your service if you have already made a release. Use with caution.
+Note that the preceding example is a mix of the examples shown earlier in this chapter. You may want to read back through them to follow the progression to the final example.
+
+WARNING: Configuring `@RepositoryRestResource(excerptProjection=...)` for a repository alters the default behavior. This can potentially cause breaking changes to consumers of your service if you have already made a release.
diff --git a/src/main/asciidoc/repository-resources.adoc b/src/main/asciidoc/repository-resources.adoc
index fe247feaf..c09ece4ea 100644
--- a/src/main/asciidoc/repository-resources.adoc
+++ b/src/main/asciidoc/repository-resources.adoc
@@ -4,37 +4,40 @@
[[repository-resources.fundamentals]]
== Fundamentals
-The core functionality of Spring Data REST is to export resources for Spring Data repositories. Thus, the core artifact to look at and potentially tweak to customize the way the exporting works is the repository interface. Assume the following repository interface:
+The core functionality of Spring Data REST is to export resources for Spring Data repositories. Thus, the core artifact to look at and potentially customize the way the exporting works is the repository interface. Consider the following repository interface:
+====
[source]
----
public interface OrderRepository extends CrudRepository { }
----
+====
For this repository, Spring Data REST exposes a collection resource at `/orders`. The path is derived from the uncapitalized, pluralized, simple class name of the domain class being managed. It also exposes an item resource for each of the items managed by the repository under the URI template `/orders/{id}`.
By default the HTTP methods to interact with these resources map to the according methods of `CrudRepository`. Read more on that in the sections on <> and <>.
[[repository-resources.default-status-codes]]
-=== Default status codes
+=== Default Status Codes
For the resources exposed, we use a set of default status codes:
-* `200 OK` - for plain `GET` requests.
-* `201 Created` - for `POST` and `PUT` requests that create new resources.
-* `204 No Content` - for `PUT`, `PATCH`, and `DELETE` requests if the configuration is set to not return response bodies for resource updates (`RepositoryRestConfiguration.returnBodyOnUpdate`). If the configuration value is set to include responses for `PUT`, `200 OK` will be returned for updates, `201 Created` will be returned for resource created through `PUT`.
+* `200 OK`: For plain `GET` requests.
+* `201 Created`: For `POST` and `PUT` requests that create new resources.
+* `204 No Content`: For `PUT`, `PATCH`, and `DELETE` requests when the configuration is set to not return response bodies for resource updates (`RepositoryRestConfiguration.returnBodyOnUpdate`). If the configuration value is set to include responses for `PUT`, `200 OK` is returned for updates, and `201 Created` is returned for resource created through `PUT`.
-If the configuration values (`RepositoryRestConfiguration.returnBodyOnUpdate` and `RepositoryRestConfiguration.returnBodyCreate)` are explicitly set to null, the presence of the HTTP Accept header will be used to determine the response code.
+If the configuration values (`RepositoryRestConfiguration.returnBodyOnUpdate` and `RepositoryRestConfiguration.returnBodyCreate)` are explicitly set to `null`, the presence of the HTTP Accept header is used to determine the response code.
[[repository-resources.resource-discoverability]]
-=== Resource discoverability
+=== Resource Discoverability
-A core principle of https://spring.io/understanding/HATEOAS[HATEOAS] is that resources should be discoverable through the publication of links that point to the available resources. There are a few competing de-facto standards of how to represent links in JSON. By default, Spring Data REST uses http://tools.ietf.org/html/draft-kelly-json-hal[HAL] to render responses. HAL defines links to be contained in a property of the returned document.
+A core principle of https://spring.io/understanding/HATEOAS[HATEOAS] is that resources should be discoverable through the publication of links that point to the available resources. There are a few competing de-facto standards of how to represent links in JSON. By default, Spring Data REST uses http://tools.ietf.org/html/draft-kelly-json-hal[HAL] to render responses. HAL defines the links to be contained in a property of the returned document.
-Resource discovery starts at the top level of the application. By issuing a request to the root URL under which the Spring Data REST application is deployed, the client can extract a set of links from the returned JSON object that represent the next level of resources that are available to the client.
+Resource discovery starts at the top level of the application. By issuing a request to the root URL under which the Spring Data REST application is deployed, the client can extract, from the returned JSON object, a set of links that represent the next level of resources that are available to the client.
-For example, to discover what resources are available at the root of the application, issue an HTTP `GET` to the root URL:
+For example, to discover what resources are available at the root of the application, issue an HTTP `GET` to the root URL, as follows:
+====
[source]
----
curl -v http://localhost:8080/
@@ -52,224 +55,270 @@ curl -v http://localhost:8080/
}
}
----
+====
-The property of the result document is an object in itself consisting of keys representing the relation type with nested link objects as specified in HAL.
+The property of the result document is an object that consists of keys representing the relation type, with nested link objects as specified in HAL.
-NOTE: For more details about the *profile* link, see <>.
+NOTE: For more details about the `profile` link, see <>.
[[repository-resources.collection-resource]]
-== The collection resource
+== The Collection Resource
-Spring Data REST exposes a collection resource named after the uncapitalized, pluralized version of the domain class the exported repository is handling. Both the name of the resource and the path can be customized using the `@RepositoryRestResource` on the repository interface.
+Spring Data REST exposes a collection resource named after the uncapitalized, pluralized version of the domain class the exported repository is handling. Both the name of the resource and the path can be customized by using `@RepositoryRestResource` on the repository interface.
=== Supported HTTP Methods
-Collections resources support both `GET` and `POST`. All other HTTP methods will cause a `405 Method Not Allowed`.
+Collections resources support both `GET` and `POST`. All other HTTP methods cause a `405 Method Not Allowed`.
-==== GET
+==== `GET`
-Returns all entities the repository servers through its `findAll(…)` method. If the repository is a paging repository we include the pagination links if necessary and additional page metadata.
+The `GET` method returns all entities the repository serves through its `findAll(…)` method. If the repository is a paging repository, we include the pagination links (if the total number of results exceeds the page size) and additional page metadata.
===== Parameters
-If the repository has pagination capabilities the resource takes the following parameters:
+If the repository has pagination capabilities, the resource takes the following parameters:
-* `page` - the page number to access (0 indexed, defaults to 0).
-* `size` - the page size requested (defaults to 20).
-* `sort` - a collection of sort directives in the format `($propertyname,)+[asc|desc]`?.
+* `page`: The page number to access (0 indexed, defaults to 0).
+* `size`: The page size requested (defaults to 20).
+* `sort`: A collection of sort directives in the format `($propertyname,)+[asc|desc]`?.
-===== Custom status codes
+===== Custom Status Codes
-* `405 Method Not Allowed` - if the `findAll(…)` methods was not exported (through `@RestResource(exported = false)`) or is not present in the repository at all.
+The `GET` method has only one custom status code:
-===== Supported media types
+* `405 Method Not Allowed`: If the `findAll(…)` methods were not exported (through `@RestResource(exported = false)`) or are not present in the repository.
-* application/hal+json
-* application/json
+===== Supported Media Types
-===== Related resources
+The `GET` method supports the following media types:
-* `search` - a <> if the backing repository exposes query methods.
+* `application/hal+json`
+* `application/json`
-==== HEAD
+===== Related Resources
-Returns whether the collection resource is available.
+The `GET` method supports a single link for discovering related resources:
-==== POST
+* `search`: A <> is exposed if the backing repository exposes query methods.
-Creates a new entity from the given request body.
+==== `HEAD`
-===== Custom status codes
+The `HEAD` method returns whether the collection resource is available. It has no status codes, media types, or related resources.
-* `405 Method Not Allowed` - if the `save(…)` methods was not exported (through `@RestResource(exported = false)`) or is not present in the repository at all.
+==== `POST`
-===== Supported media types
+The `POST` method creates a new entity from the given request body.
+
+===== Custom Status Codes
+
+The `POST` method has only one custom status code:
+
+* `405 Method Not Allowed`: If the `save(…)` methods were not exported (through `@RestResource(exported = false)`) or are not present in the repository at all.
+
+===== Supported Media Types
+
+The `POST` method supports the following media types:
* application/hal+json
* application/json
[[repository-resources.item-resource]]
-== The item resource
+== The Item Resource
Spring Data REST exposes a resource for individual collection items as sub-resources of the collection resource.
-=== Supported HTTP methods
+=== Supported HTTP Methods
-Item resources generally support `GET`, `PUT`, `PATCH` and `DELETE` unless explicit configuration prevents that (see below for details).
+Item resources generally support `GET`, `PUT`, `PATCH`, and `DELETE`, unless explicit configuration prevents that (see "`<>`" for details).
==== GET
-Returns a single entity.
+The `GET` method returns a single entity.
-===== Custom status codes
+===== Custom Status Codes
-* `405 Method Not Allowed` - if the `findOne(…)` methods was not exported (through `@RestResource(exported = false)`) or is not present in the repository at all.
+The `GET` method has only one custom status code:
-===== Supported media types
+* `405 Method Not Allowed`: If the `findOne(…)` methods were not exported (through `@RestResource(exported = false)`) or are not present in the repository.
+
+===== Supported Media Types
+
+The `GET` method supports the following media types:
* application/hal+json
* application/json
-===== Related resources
+===== Related Resources
-For every association of the domain type we expose links named after the association property. This can be customized by using `@RestResource` on the property. The related resources are of type <>.
+For every association of the domain type, we expose links named after the association property. You can customize this behavior by using `@RestResource` on the property. The related resources are of the <> type.
-==== HEAD
+==== `HEAD`
-Returns whether the item resource is available.
+The `HEAD` method returns whether the item resource is available. It has no status codes, media types, or related resources.
-==== PUT
+==== `PUT`
-Replaces the state of the target resource with the supplied request body.
+The `PUT` method replaces the state of the target resource with the supplied request body.
-===== Custom status codes
+===== Custom Status Codes
-* `405 Method Not Allowed` - if the `save(…)` methods was not exported (through `@RestResource(exported = false)`) or is not present in the repository at all.
+The `PUT` method has only one custom status code:
-===== Supported media types
+* `405 Method Not Allowed`: If the `save(…)` methods were not exported (through `@RestResource(exported = false)`) or is not present in the repository at all.
+
+===== Supported Media Types
+
+The `PUT` method supports the following media types:
* application/hal+json
* application/json
-==== PATCH
+==== `PATCH`
-Similar to `PUT` but partially updating the resources state.
+The `PATCH` method is similar to the `PUT` method but partially updates the resources state.
-===== Custom status codes
+===== Custom Status Codes
-* `405 Method Not Allowed` - if the `save(…)` methods was not exported (through `@RestResource(exported = false)`) or is not present in the repository at all.
+The `PATCH` method has only one custom status code:
-===== Supported media types
+* `405 Method Not Allowed`: If the `save(…)` methods were not exported (through `@RestResource(exported = false)`) or are not present in the repository.
+
+===== Supported Media Types
+
+The `PATCH` method supports the following media types:
* application/hal+json
* application/json
* https://tools.ietf.org/html/rfc6902[application/patch+json]
* https://tools.ietf.org/html/rfc7386[application/merge-patch+json]
-==== DELETE
+==== `DELETE`
-Deletes the resource exposed.
+The `DELETE` method deletes the resource exposed.
-===== Custom status codes
+===== Custom Status Codes
-* `405 Method Not Allowed` - if the `delete(…)` methods was not exported (through `@RestResource(exported = false)`) or is not present in the repository at all.
+The `DELETE` method has only one custom status code:
+
+* `405 Method Not Allowed`: If the `delete(…)` methods were not exported (through `@RestResource(exported = false)`) or are not present in the repository.
[[repository-resources.association-resource]]
-== The association resource
+== The Association Resource
-Spring Data REST exposes sub-resources of every item resource for each of the associations the item resource has. The name and path of the of the resource defaults to the name of the association property and can be customized using `@RestResource` on the association property.
+Spring Data REST exposes sub-resources of every item resource for each of the associations the item resource has. The name and path of the resource defaults to the name of the association property and can be customized by using `@RestResource` on the association property.
-=== Supported HTTP methods
+=== Supported HTTP Methods
-==== GET
+The association resource supports the following media types:
-Returns the state of the association resource
+* GET
+* PUT
+* POST
+* DELETE
-===== Supported media types
+==== `GET`
+
+The `GET` method returns the state of the association resource.
+
+===== Supported Media Types
+
+The `GET` method supports the following media types:
* application/hal+json
* application/json
-==== PUT
+==== `PUT`
-Binds the resource pointed to by the given URI(s) to the resource. This
+The `PUT` method binds the resource pointed to by the given URI(s) to the resource. This
-===== Custom status codes
+===== Custom Status Codes
-* `400 Bad Request` - if multiple URIs were given for a to-one-association.
+The `PUT` method has only one custom status code:
-===== Supported media types
+* `400 Bad Request`: When multiple URIs were given for a to-one-association.
-* text/uri-list - URIs pointing to the resource to bind to the association.
+===== Supported Media Types
-==== POST
+The `PUT` method supports only one media type:
-Only supported for collection associations. Adds a new element to the collection.
+* text/uri-list: URIs pointing to the resource to bind to the association.
-===== Supported media types
+==== `POST`
-* text/uri-list - URIs pointing to the resource to add to the association.
+The `POST` method is supported only for collection associations. It adds a new element to the collection.
-==== DELETE
+===== Supported Media Types
-Unbinds the association.
+The `POST` method supports only one media type:
-===== Custom status codes
+* text/uri-list: URIs pointing to the resource to add to the association.
-* `405 Method Not Allowed` - if the association is non-optional.
+==== `DELETE`
+
+The `DELETE` method unbinds the association.
+
+===== Custom Status Codes
+
+The `POST` method has only one custom status code:
+
+* `405 Method Not Allowed`: When the association is non-optional.
[[repository-resources.search-resource]]
-== The search resource
+== The Search Resource
The search resource returns links for all query methods exposed by a repository. The path and name of the query method resources can be modified using `@RestResource` on the method declaration.
-=== Supported HTTP methods
+=== Supported HTTP Methods
-As the search resource is a read-only resource it supports `GET` only.
+As the search resource is a read-only resource, it supports only the `GET` method.
-==== GET
+==== `GET`
-Returns a list of links pointing to the individual query method resources
+The `GET` method returns a list of links pointing to the individual query method resources.
-===== Supported media types
+===== Supported Media Types
+
+The `GET` method supports the following media types:
* application/hal+json
* application/json
-===== Related resources
+===== Related Resources
-For every query method declared in the repository we expose a <>. If the resource supports pagination, the URI pointing to it will be a URI template containing the pagination parameters.
+For every query method declared in the repository, we expose a <>. If the resource supports pagination, the URI pointing to it is a URI template containing the pagination parameters.
-==== HEAD
+==== `HEAD`
-Returns whether the search resource is available. A 404 return code indicates no query method resources available at all.
+The `HEAD` method returns whether the search resource is available. A 404 return code indicates no query method resources are available.
[[repository-resources.query-method-resource]]
-== The query method resource
+== The Query Method Resource
-The query method resource executes the query exposed through an individual query method on the repository interface.
+The query method resource runs the exposed query through an individual query method on the repository interface.
-=== Supported HTTP methods
+=== Supported HTTP Methods
-As the search resource is a read-only resource it supports `GET` only.
+As the search resource is a read-only resource, it supports `GET` only.
-==== GET
+==== `GET`
-Returns the result of the query execution.
+The `GET` method returns the result of the query execution.
===== Parameters
If the query method has pagination capabilities (indicated in the URI template pointing to the resource) the resource takes the following parameters:
-* `page` - the page number to access (0 indexed, defaults to 0).
-* `size` - the page size requested (defaults to 20).
-* `sort` - a collection of sort directives in the format `($propertyname,)+[asc|desc]`?.
+* `page`: The page number to access (0 indexed, defaults to 0).
+* `size`: The page size requested (defaults to 20).
+* `sort`: A collection of sort directives in the format `($propertyname,)+[asc|desc]`?.
-===== Supported media types
+===== Supported Media Types
-* application/hal+json
-* application/json
+The `GET` method supports the following media types:
-==== HEAD
+* `application/hal+json`
+* `application/json`
-Returns whether a query method resource is available.
+==== `HEAD`
+
+The `HEAD` method returns whether a query method resource is available.
diff --git a/src/main/asciidoc/representations.adoc b/src/main/asciidoc/representations.adoc
index 1f7f57bf4..a129bfb85 100644
--- a/src/main/asciidoc/representations.adoc
+++ b/src/main/asciidoc/representations.adoc
@@ -1,23 +1,21 @@
[[representations]]
-= Domain Object Representations
+= Domain Object Representations (Object Mapping)
-[[representations.mapping]]
-== Object Mapping
-
-Spring Data REST returns a representation of a domain object that corresponds to the requested `Accept` type specified in the HTTP request.
+Spring Data REST returns a representation of a domain object that corresponds to the `Accept` type specified in the HTTP request.
Currently, only JSON representations are supported. Other representation types can be supported in the future by adding an appropriate converter and updating the controller methods with the appropriate content-type.
-Sometimes the behavior of the Spring Data REST's ObjectMapper, which has been specially configured to use intelligent serializers that can turn domain objects into links and back again, may not handle your domain model correctly. There are so many ways one can structure your data that you may find your own domain model isn't being translated to JSON correctly. It's also sometimes not practical in these cases to try and support a complex domain model in a generic way. Sometimes, depending on the complexity, it's not even possible to offer a generic solution.
+Sometimes, the behavior of the Spring Data REST `ObjectMapper` (which has been specially configured to use intelligent serializers that can turn domain objects into links and back again) may not handle your domain model correctly. There are so many ways you can structure your data that you may find your own domain model is not translated to JSON correctly. It is also sometimes not practical in these cases to try and support a complex domain model in a generic way. Sometimes, depending on the complexity, it is not even possible to offer a generic solution.
-=== Adding custom (de)serializers to Jackson's ObjectMapper
+== Adding Custom Serializers and Deserializers to Jackson's ObjectMapper
-To accommodate the largest percentage of use cases, Spring Data REST tries very hard to render your object graph correctly. It will try and serialize unmanaged beans as normal POJOs and it will try and create links to managed beans where that's necessary. But if your domain model doesn't easily lend itself to reading or writing plain JSON, you may want to configure Jackson's ObjectMapper with your own custom type mappings and (de)serializers.
+To accommodate the largest percentage of use cases, Spring Data REST tries very hard to render your object graph correctly. It tries to serialize unmanaged beans as normal POJOs, and it tries to create links to managed beans where necessary. However, if your domain model does not easily lend itself to reading or writing plain JSON, you may want to configure Jackson's ObjectMapper with your own custom mappings, serializers, and deserializers.
-==== Abstract class registration
+=== Abstract Class Registration
-One key configuration point you might need to hook into is when you're using an abstract class (or an interface) in your domain model. Jackson won't know by default what implementation to create for an interface. Take the following example:
+One key configuration point you might need to hook into is when you use an abstract class (or an interface) in your domain model. By defualt, Jackson does not know what implementation to create for an interface. Consider the following example:
+====
[source,java]
----
@Entity
@@ -26,11 +24,13 @@ public class MyEntity {
private List interfaces;
}
----
+====
-In a default configuration, Jackson has no idea what class to instantiate when POSTing new data to the exporter. This is something you'll need to tell Jackson either through an annotation, or, more cleanly, by registering a type mapping using a `Module`.
+In a default configuration, Jackson has no idea what class to instantiate when POSTing new data to the exporter. This is something you need to tell Jackson either through an annotation, or (more cleanly) by registering a type mapping by using a `Module`.
-To add your own Jackson configuration to the `ObjectMapper` used by Spring Data REST, override the `configureJacksonObjectMapper` method. That method will be passed an `ObjectMapper` instance that has a special module to handle serializing and deserializing `PersistentEntity`s. You can register your own modules as well, like in the following example.
+To add your own Jackson configuration to the `ObjectMapper` used by Spring Data REST, override the `configureJacksonObjectMapper` method. That method is passed an `ObjectMapper` instance that has a special module to handle serializing and deserializing `PersistentEntity` objects. You can register your own modules as well, as the following example shows:
+====
[source,java]
----
@Override
@@ -46,13 +46,15 @@ protected void configureJacksonObjectMapper(ObjectMapper objectMapper) {
});
}
----
+====
-Once you have access to the `SetupContext` object in your `Module`, you can do all sorts of cool things to configure Jackson's JSON mapping. You can read more about how ``Module``s work on Jackson's wiki: http://wiki.fasterxml.com/JacksonFeatureModules[ http://wiki.fasterxml.com/JacksonFeatureModules ]
+Once you have access to the `SetupContext` object in your `Module`, you can do all sorts of cool things to configure Jackson's JSON mapping. You can read more about how `Module` instances work on http://wiki.fasterxml.com/JacksonFeatureModules[Jackson's wiki].
-==== Adding custom serializers for domain types
+=== Adding Custom Serializers for Domain Types
-If you want to (de)serialize a domain type in a special way, you can register your own implementations with Jackson's `ObjectMapper` and the Spring Data REST exporter will transparently handle those domain objects correctly. To add serializers, from your `setupModule` method implementation, do something like the following:
+If you want to serialize or deserialize a domain type in a special way, you can register your own implementations with Jackson's `ObjectMapper`, and the Spring Data REST exporter transparently handles those domain objects correctly. To add serializers from your `setupModule` method implementation, you can do something like the following:
+====
[source,java]
----
@Override
@@ -67,4 +69,4 @@ public void setupModule(SetupContext context) {
context.addDeserializers(deserializers);
}
----
-
+====
diff --git a/src/main/asciidoc/security.adoc b/src/main/asciidoc/security.adoc
index 7d500e6c7..5b28a490f 100644
--- a/src/main/asciidoc/security.adoc
+++ b/src/main/asciidoc/security.adoc
@@ -3,12 +3,12 @@
:spring-data-rest-root: ../../..
:spring-security-docs: http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle
-Spring Data REST works quite well with Spring Security. This section will show examples of how to secure your Spring Data REST services with *method level security*.
+Spring Data REST works quite well with Spring Security. This section shows examples of how to secure your Spring Data REST services with method-level security.
[[security.pre-and-post]]
-== @Pre and @Post security
+== `@Pre` and `@Post` Security
-The following example from Spring Data REST's test suite shows Spring Security's {spring-security-docs}/#el-pre-post-annotations[PreAuthorization model], the most sophisticated version:
+The following example from Spring Data REST's test suite shows Spring Security's {spring-security-docs}/#el-pre-post-annotations[PreAuthorization model] (the most sophisticated security model):
.spring-data-rest-tests/spring-data-rest-tests-security/src/test/java/org/springframework/data/rest/tests/security/PreAuthorizedOrderRepository.java
====
@@ -17,14 +17,14 @@ The following example from Spring Data REST's test suite shows Spring Security's
include::{spring-data-rest-root}/spring-data-rest-tests/spring-data-rest-tests-security/src/test/java/org/springframework/data/rest/tests/security/PreAuthorizedOrderRepository.java[tag=code]
----
+
+<1> This Spring Security annotation secures the entire repository. The {spring-security-docs}/#el-common-built-in[Spring Security SpEL expression] indicates that the principal must have `ROLE_USER` in its collection of roles.
+<2> To change method-level settings, you must override the method signature and apply a Spring Security annotation. In this case, the method overrides the repository-level settings with the requirement that the user have `ROLE_ADMIN` to perform a delete.
====
-This is a standard Spring Data repository definition extending `CrudRepository` with some key changes.
+The preceding example shows a standard Spring Data repository definition extending `CrudRepository` with some key changes: the specification of particular roles to access the various methods:
-<1> This Spring Security annotation secures the entire repository. The {spring-security-docs}/#el-common-built-in[Spring Security SpEL expression] indicates the principal must have *ROLE_USER* in his collection of roles.
-<2> To change method-level settings, you must override the method signature and apply a Spring Security annotation. In this case, the method overrides the repository-level settings with the requirement that the user have *ROLE_ADMIN* to perform a delete.
-
-IMPORTANT: Repository and method level security settings don't combine. Instead, method-level settings _override_ repository level settings.
+IMPORTANT: Repository and method level security settings do not combine. Instead, method-level settings override repository level settings.
The previous example illustrates that `CrudRepository`, in fact, has four delete methods. You must override all delete methods to properly secure it.
@@ -40,17 +40,17 @@ The following example shows Spring Security's older `@Secured` annotation, which
----
include::{spring-data-rest-root}/spring-data-rest-tests/spring-data-rest-tests-security/src/test/java/org/springframework/data/rest/tests/security/SecuredPersonRepository.java[tag=code]
----
+
+<1> This results in the same security check as the previous example but has less flexibility. It allows only roles as the means to restrict access.
+<2> Again, this shows that delete methods require `ROLE_ADMIN`.
====
-<1> This results in the same security check, but has less flexibility. It only allows roles as the means to restrict access.
-<2> Again, this shows that delete methods require *ROLE_ADMIN*.
-
-NOTE: If you are starting with a new project or first applying Spring Security, `@PreAuthorize` is the recommended solution. If are already using Spring Security with `@Secured` in other parts of your app, you can continue on that path without rewriting everything.
+NOTE: If you start with a new project or first apply Spring Security, `@PreAuthorize` is the recommended solution. If are already using Spring Security with `@Secured` in other parts of your app, you can continue on that path without rewriting everything.
[[security.enable-method-level]]
-== Enabling method level security
+== Enabling Method-level Security
-To configure method level security, here is a brief snippet from Spring Data REST's test suite:
+To configure method-level security, here is a brief snippet from Spring Data REST's test suite:
.spring-data-rest-tests/spring-data-rest-tests-security/src/test/java/org/springframework/data/rest/tests/security/SecurityConfiguration.java
====
@@ -60,10 +60,10 @@ include::{spring-data-rest-root}/spring-data-rest-tests/spring-data-rest-tests-s
...
}
----
-====
<1> This is a Spring configuration class.
<2> It uses Spring Security's `@EnableGlobalMethodSecurity` annotation to enable both `@Secured` and `@Pre`/`@Post` support. NOTE: You don't have to use both. This particular case is used to prove both versions work with Spring Data REST.
<3> This class extends Spring Security's `WebSecurityConfigurerAdapter` which is used for pure Java configuration of security.
+====
-The rest of the configuration class isn't listed because it follows {spring-security-docs}/#hello-web-security-java-configuration[standard practices] you can read about in the Spring Security reference docs.
+The rest of the configuration class is not listed, because it follows {spring-security-docs}/#hello-web-security-java-configuration[standard practices] that you can read about in the Spring Security reference docs.
diff --git a/src/main/asciidoc/spring-data-rest-examples.adoc b/src/main/asciidoc/spring-data-rest-examples.adoc
index de460aa4a..1628107eb 100644
--- a/src/main/asciidoc/spring-data-rest-examples.adoc
+++ b/src/main/asciidoc/spring-data-rest-examples.adoc
@@ -2,28 +2,26 @@
[appendix]
= Spring Data REST example projects
-This appendix contains a list of Spring Data REST sample applications. The exact version of each example isn't guaranteed to match the version of this reference manual.
+This appendix contains a list of Spring Data REST sample applications. The exact version of each example is not guaranteed to match the version of this reference manual.
-NOTE: To get them all, visit https://github.com/spring-projects/spring-data-examples and either clone or download a zipball. This will give you example apps for ALL supported Spring Data projects. Simply navigate to `spring-data-examples/rest`.
+NOTE: To get them all, visit https://github.com/spring-projects/spring-data-examples and either clone or download a zipball. Doing so gives you example applications for all supported Spring Data projects. To see them, navigate to `spring-data-examples/rest`.
[[spring-data-examples.multi-store]]
-== Multi-store example
+== Multi-store Example
https://github.com/spring-projects/spring-data-examples/tree/master/rest/multi-store[This example] shows how to mix together several underlying Spring Data projects.
[[spring-data-examples.projections]]
== Projections
-https://github.com/spring-projects/spring-data-examples/tree/master/rest/projections[This example] contains more detailed code you can use to poke around with <>.
+https://github.com/spring-projects/spring-data-examples/tree/master/rest/projections[This example] contains more detailed code you can use to explore <>.
[[spring-data-examples.spring-security]]
-== Spring Data REST + Spring Security
+== Spring Data REST with Spring Security
https://github.com/spring-projects/spring-data-examples/tree/master/rest/security[This example] shows how to secure a http://projects.spring.io/spring-data-rest[Spring Data REST] application in multiple ways with http://projects.spring.io/spring-security[Spring Security].
[[spring-data-examples.starbucks]]
== Starbucks example
-https://github.com/spring-projects/spring-data-examples/tree/master/rest/starbucks[This example] exposes 10843 Starbucks coffee shops via a RESTful API that allows to access the stores in a hypermedia based way and exposes a resource to execute geo-location search for coffee shops.
-
-
+https://github.com/spring-projects/spring-data-examples/tree/master/rest/starbucks[This example] exposes 10,843 Starbucks coffee shops through a RESTful API that allows access to the stores in a hypermedia-based way and exposes a resource to execute a geo-location search for coffee shops.
diff --git a/src/main/asciidoc/tools.adoc b/src/main/asciidoc/tools.adoc
index a52787336..4757043d5 100644
--- a/src/main/asciidoc/tools.adoc
+++ b/src/main/asciidoc/tools.adoc
@@ -4,12 +4,13 @@
== The HAL Browser
-The developer of the http://stateless.co/hal_specification.html[HAL spec] has a useful application: https://github.com/mikekelly/hal-browser[the HAL Browser]. It's a web app that stirs in a little HAL-powered JavaScript. You can point it at any Spring Data REST API and use it to navigate the app and create new resources.
+The developer of the http://stateless.co/hal_specification.html[HAL specification] has a useful application: https://github.com/mikekelly/hal-browser[the HAL Browser]. It is a web application that stirs in a little HAL-powered JavaScript. You can point it at any Spring Data REST API and use it to navigate the app and create new resources.
Instead of pulling down the files, embedding them in your application, and crafting a Spring MVC controller to serve them up, all you need to do is add a single dependency.
-In Maven:
+The following listing shows how to add the dependency in Maven:
+====
[source,xml]
----
@@ -19,34 +20,37 @@ In Maven:
----
+====
-In Gradle:
+The following listing shows how to add the dependency in Gradle:
+====
[source,groovy]
----
dependencies {
compile 'org.springframework.data:spring-data-rest-hal-browser'
}
----
+====
-NOTE: If you use Spring Boot or the Spring Data BOM (bill of materials), you don't need to specify the version.
+NOTE: If you use Spring Boot or the Spring Data BOM (bill of materials), you do not need to specify the version.
-This dependency will autoconfigure the HAL Browser to be served up when you visit your application's root URI in a browser. (NOTE: http://localhost:8080 was plugged into the browser, and it redirect to the URL shown below.)
+This dependency auto-configures the HAL Browser to be served up when you visit your application's root URI in a browser. (NOTE: http://localhost:8080 was plugged into the browser, and it redirected to the URL shown in the following image.)
image::hal-browser-1.png[]
-The screen shot above shows the root path of the API. On the right side are details from the response including headers and the body (a HAL document).
+The preceding screen shot shows the root path of the API. On the right side are details from the response, including headers and the body (a HAL document).
-The HAL Browser reads the links from the response and puts them on a list on the left side. You can either click on the *GET* button and navigate to one of the collections, or click on the *non-GET* option to make changes.
+The HAL Browser reads the links from the response and puts them in a list on the left side. You can either click on the *GET* button and navigate to one of the collections, or click on the *NON-GET* option to make changes.
-The HAL Browser speaks *URI Template*. You may notice up above the *GET* button next to *persons* has a question mark icon. An expansion dialog will pop-up if you choose to navigate to it like this:
+The HAL Browser speaks *URI Template*. Above the *GET* button and next to *persons*, the UI has a question mark icon. An expansion dialog pops up if you choose to navigate to it, as follows:
image::hal-browser-3.png[]
-If you click *Follow URI* without entering anything, the variables will essentially be ignored. For situations like <> or <>, this can be useful.
+If you click *Follow URI* without entering anything, the variables are essentially ignored. For situations like <> or <>, this can be useful.
-When you click on a *non-GET* button, a pop-up dialog appears. By default, it shows *POST*. This field can be adjusted to either *PUT* or *PATCH*. The headers are filled out to properly to submit a new JSON document.
+When you click on a *NON-GET* button, a pop-up dialog appears. By default, it shows *POST*. This field can be adjusted to either *PUT* or *PATCH*. The headers are filled out to properly to submit a new JSON document.
-Below the URI, method, and headers are the fields. These are automatically supplied based on the metadata of the resources, automatically generated by Spring Data REST. Update your domain objects, and the pop-up will reflect it.
+Below the URI, method, and headers are the fields. These are automatically supplied, depending on the metadata of the resources, which was automatically generated by Spring Data REST. If you update your domain objects, the pop-up reflects it, as the following image shows:
image::hal-browser-2.png[height="150"]
diff --git a/src/main/asciidoc/validation.adoc b/src/main/asciidoc/validation.adoc
index ae7c5e483..c990a5a70 100644
--- a/src/main/asciidoc/validation.adoc
+++ b/src/main/asciidoc/validation.adoc
@@ -1,14 +1,15 @@
[[validation]]
= Validation
-There are two ways to register a `Validator` instance in Spring Data REST: wire it by bean name or register the validator manually. For the majority of cases, the simple bean name prefix style will be sufficient.
+There are two ways to register a `Validator` instance in Spring Data REST: wire it by bean name or register the validator manually. For the majority of cases, the simple bean name prefix style is sufficient.
-In order to tell Spring Data REST you want a particular `Validator` assigned to a particular event, you simply prefix the bean name with the event you're interested in. For example, to validate instances of the `Person` class before new ones are saved into the repository, you would declare an instance of a `Validator` in your `ApplicationContext` with the bean name "beforeCreatePersonValidator". Since the prefix "beforeCreate" matches a known Spring Data REST event, that validator will be wired to the correct event.
+In order to tell Spring Data REST you want a particular `Validator` assigned to a particular event, prefix the bean name with the event in question. For example, to validate instances of the `Person` class before new ones are saved into the repository, you would declare an instance of a `Validator` in your `ApplicationContext` with a bean name of `beforeCreatePersonValidator`. Since the `beforeCreate` prefix matches a known Spring Data REST event, that validator is wired to the correct event.
-== Assigning Validators manually
+== Assigning Validators Manually
-If you would rather not use the bean name prefix approach, then you simply need to register an instance of your validator with the bean whose job it is to invoke validators after the correct event. In your configuration that implements `RepositoryRestConfigurer` or subclasses Spring Data REST's `RepositoryRestConfigurerAdapter`, override the `configureValidatingRepositoryEventListener` method and call `addValidator` on the `ValidatingRepositoryEventListener`, passing the event you want this validator to be triggered on, and an instance of the validator.
+If you would rather not use the bean name prefix approach, you need to register an instance of your validator with the bean whose job it is to invoke validators after the correct event. In your configuration that implements `RepositoryRestConfigurer` or subclasses Spring Data REST's `RepositoryRestConfigurerAdapter`, override the `configureValidatingRepositoryEventListener` method and call `addValidator` on the `ValidatingRepositoryEventListener`, passing the event on which you want this validator to be triggered and an instance of the validator. The following example shows how to do so:
+====
[source,java]
----
@Override
@@ -16,3 +17,4 @@ protected void configureValidatingRepositoryEventListener(ValidatingRepositoryEv
v.addValidator("beforeSave", new BeforeSaveValidator());
}
----
+====