DATAREST-364 - Reference documentation is now written in Asciidoctor.

Original pull request: #146.
This commit is contained in:
Greg Turnquist
2014-08-04 12:51:25 -05:00
committed by Oliver Gierke
parent 2d64fb4d84
commit 50d9c6914f
15 changed files with 556 additions and 1096 deletions

View File

@@ -32,6 +32,10 @@
<groupId>org.codehaus.mojo</groupId>
<artifactId>wagon-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

View File

@@ -1,137 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xml:id="events-chapter"
xmlns="http://docbook.org/ns/docbook"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd">
<title>Events</title>
<para>There are six different events that the REST exporter emits throughout the process of working with an entity.
Those are:
<itemizedlist>
<listitem>
<para>BeforeCreateEvent</para>
</listitem>
<listitem>
<para>AfterCreateEvent</para>
</listitem>
<listitem>
<para>BeforeSaveEvent</para>
</listitem>
<listitem>
<para>AfterSaveEvent</para>
</listitem>
<listitem>
<para>BeforeLinkSaveEvent</para>
</listitem>
<listitem>
<para>AfterLinkSaveEvent</para>
</listitem>
<listitem>
<para>BeforeDeleteEvent</para>
</listitem>
<listitem>
<para>AfterDeleteEvent</para>
</listitem>
</itemizedlist>
</para>
<section>
<title>Writing an
<classname>ApplicationListener</classname>
</title>
<para>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.
<programlisting language="java"><![CDATA[
public class BeforeSaveEventListener extends AbstractRepositoryEventListener {
@Override public void onBeforeSave(Object entity) {
... logic to handle inspecting the entity before the Repository saves it
}
@Override public void onAfterDelete(Object entity) {
... send a message that this entity has been deleted
}
}]]></programlisting>
</para>
<para>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.
</para>
</section>
<section>
<title>Writing an annotated handler</title>
<para>Another approach is to use an annotated handler, which does filter events based on domain type.</para>
<para>To declare a handler, create a POJO and put the
<classname>@RepositoryEventHandler</classname>
annotation on it. This tells the
<classname>BeanPostProcessor</classname>
that this class needs to be inspected for handler methods.
</para>
<para>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 BeforeSaveEvents
in an annotated POJO for different kinds of domain types, you'd define your class like this:
<programlisting language="java"><![CDATA[
@RepositoryEventHandler
public class PersonEventHandler {
@HandleBeforeSave(Person.class) public void handlePersonSave(Person p) {
... you can now deal with Person in a type-safe way
}
@HandleBeforeSave(Profile.class) public void handleProfileSave(Profile p) {
... you can now deal with Profile in a type-safe way
}
}]]></programlisting>
</para>
<para>You can also declare the domain type at the class level:
<programlisting language="java"><![CDATA[
@RepositoryEventHandler(Person.class)
public class PersonEventHandler {
@HandleBeforeSave public void handleBeforeSave(Person p) {
...
}
@HandleAfterDelete public void handleAfterDelete(Person p) {
...
}
}]]></programlisting>
</para>
<para>Just declare an instance of your annotated bean in your
<classname>ApplicationContext</classname>
and the
<classname>BeanPostProcessor</classname>
that is by default created in
<classname>RepositoryRestMvcConfiguration</classname>
will inspect the bean for handlers and wire them to the correct events.
<programlisting language="java"><![CDATA[
@Configuration
public class RepositoryConfiguration {
@Bean PersonEventHandler personEventHandler() {
return new PersonEventHandler();
}
}]]></programlisting>
</para>
</section>
</chapter>

View File

@@ -1,115 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.0"
xsi:schemaLocation="http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd"
xml:id="install-chapter" xmlns="http://docbook.org/ns/docbook"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ns="http://docbook.org/ns/docbook">
<title xml:id="getting-started">Getting started</title>
<section>
<title xml:id="getting-started.introduction">Introduction</title>
<para>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.</para>
<para>To install Spring Data REST alongside your application, simply add
the required dependencies, include the stock <code>@Configuration</code>
class <classname>RepositoryRestMvcConfiguration</classname> (or subclass
it and perform any required manual configuration), and map some URLs to be
managed by Spring Data REST.</para>
</section>
<section>
<title xml:base="getting-started.gradle">Adding Spring Data REST to a
Gradle project</title>
<para>To add Spring Data REST to a Gradle-based project, add the
<code>spring-data-rest-webmvc</code> artifact to your compile-time
dependencies: <programlisting language="groovy">dependencies {
… other project dependencies
compile "org.springframework.data:spring-data-rest-webmvc:${spring-data-rest-version}"
}</programlisting></para>
</section>
<section>
<title xml:id="getting-started.maven">Adding Spring Data REST to a Maven
project</title>
<para>To add Spring Data REST to a Maven-based project, add the
<code>spring-data-rest-webmvc</code> artifact to your compile-time
dependencies: <programlisting language="xml">&lt;dependency&gt;
&lt;groupId&gt;org.springframework.data&lt;/groupId&gt;
&lt;artifactId&gt;spring-data-rest-webmvc&lt;/artifactId&gt;
&lt;version&gt;${spring-data-rest-version}&lt;/version&gt;
&lt;/dependency&gt;</programlisting></para>
</section>
<section>
<title xml:id="getting-started.configuration">Configuring Spring Data
REST</title>
<para>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
<classname>RepositoryRestMvcConfiguration</classname>. You can either
import this class into your existing configuration using an
<code>@Import</code> annotation or you can subclass it and override any of
the <code>configureXXX</code> methods to add your own configuration to
that of Spring Data REST.</para>
<para>In the following example, we'll subclass the standard
<classname>RepositoryRestMvcConfiguration</classname> and add some
<classname>ResourceMapping</classname> configurations for the
<classname>Person</classname> domain object to alter how the JSON will
look and how the links to related entities will be handled.
<programlisting language="java">@Configuration
@Import(RepositoryRestMvcConfiguration.class)
public class MyWebConfiguration extends RepositoryRestMvcConfiguration {
// … further configuration
}</programlisting></para>
<para>Make sure you also configure Spring Data repositories for the store
you use. For details on that, please consult the reference documentation
for the corresponding Spring Data module.</para>
</section>
<section>
<title xml:id="getting-started.bootstrap">Starting the application</title>
<para>As Spring Data REST is build on SpringMVC, you simply stick to the
means you use to bootstrap Spring MVC. In a Servlet 3.0 environment this
might look something like this:</para>
<para><programlisting language="java">public class RestExporterWebInitializer implements WebApplicationInitializer {
@Override public void onStartup(ServletContext servletContext) throws ServletException {
// Bootstrap repositories in root application context
AnnotationConfigWebApplicationContext rootCtx = new AnnotationConfigWebApplicationContext();
rootCtx.register(JpaRepositoryConfig.class); // Include JPA entities, Repositories
servletContext.addListener(new ContextLoaderListener(rootCtx));
// Enable Spring Data REST in the DispatcherServlet
AnnotationConfigWebApplicationContext webCtx = new AnnotationConfigWebApplicationContext();
webCtx.register(MyWebConfiguration.class);
DispatcherServlet dispatcherServlet = new DispatcherServlet(webCtx);
ServletRegistration.Dynamic reg = servletContext.addServlet("rest-exporter", dispatcherServlet);
reg.setLoadOnStartup(1);
reg.addMapping("/*");
}
}</programlisting></para>
<para>The equivalent of the above in a standard web.xml will also work
identically to this configuration if you are still in a servlet 2.5
environment. When you deploy this application to your servlet container,
you should be able to see what repositories are exported by accessing the
root of the application.</para>
</section>
</chapter>

View File

@@ -1,56 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<book version="5.0"
xsi:schemaLocation="http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd"
xml:id="spring-data-rest-reference"
xmlns="http://docbook.org/ns/docbook"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:ns="http://docbook.org/ns/docbook">
<info>
<title>Spring Data REST Reference Documentation</title>
<productname>Spring Data REST</productname>
<releaseinfo>version;</releaseinfo>
<authorgroup>
<author>
<personname><firstname>Jon</firstname>
<surname>Brisbin</surname></personname>
</author>
<author>
<personname><firstname>Oliver</firstname>
<surname>Gierke</surname></personname>
</author>
</authorgroup>
<copyright>
<year>2012-2014</year>
</copyright>
<legalnotice>
<para>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.</para>
</legalnotice>
</info>
<toc/>
<xi:include href="intro.xml"/>
<xi:include href="getting-started.xml"/>
<xi:include href="repository-resources.xml" />
<xi:include href="representations.xml"/>
<xi:include href="validation.xml"/>
<xi:include href="events.xml"/>
</book>

View File

@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xsi:schemaLocation="http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd http://www.w3.org/1999/xlink http://docbook.org/xml/5.0/xsd/xlink.xsd"
xml:id="intro-chapter" xmlns="http://docbook.org/ns/docbook"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ns="http://docbook.org/ns/docbook">
<title>Introduction</title>
<para>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 drive way. Spring MVC offers a solid foundation to build theses
kinds of services but implementic very basic functionality of REST web
service can be tedious and result in a lot of boilderplate code.</para>
<para>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 allows
to integrate the resources into related hypermedia based functionality as
easy as possible.</para>
</chapter>

View File

@@ -1,603 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.0"
xsi:schemaLocation="http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd"
xml:id="repository-resources" xmlns="http://docbook.org/ns/docbook"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ns="http://docbook.org/ns/docbook">
<title>Repository resources</title>
<section xml:id="repository-resources.fundamentals">
<title>Fundamentals</title>
<para>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:</para>
<programlisting>public interface OrderRepository extends CrudRepository&lt;Order, Long&gt; { }</programlisting>
<para>For this repository, Spring Data REST exposes a collection resource
at <code>/orders</code>. 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 <uri>/orders/{id}</uri>.</para>
<para>By default the HTTP methods to interact with these resources map to
the according methods of <interfacename>CrudRepository</interfacename>.
Read more on that in the sections on <link
linkend="repository-resources.collection-resource">collection
resources</link> and <link
linkend="repository-resources.item-resource">item resources</link>.</para>
<section xml:id="repository-resources.default-status-codes">
<title>Default status codes</title>
<para>For the resources exposed, we use a set of default status
codes:</para>
<itemizedlist>
<listitem>
<para><code>200 OK</code> - for plain <code>GET</code>
requests.</para>
</listitem>
<listitem>
<para><code>201 Created</code> - for <code>POST</code> and
<code>PUT</code> requests that create new resources.</para>
</listitem>
<listitem>
<para><code>204 No Content</code> - for <code>PUT</code>,
<code>PATCH</code>, and <code>DELETE</code> requests if the
configuration is set to not return response bodies for resource
updates
(<code>RepositoryRestConfiguration.returnBodyOnUpdate</code>). If
the configuration value is set to include responses for
<code>PUT</code>, <code>200 OK</code> will be returned for updates,
<code>201 Created</code> will be returned for resource created
through <code>PUT</code>.</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="repository-resources.resource-discoverability">
<title>Resource discoverability</title>
<para>A core principle of 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 <link
xlink:href="http://tools.ietf.org/html/draft-kelly-json-hal">HAL</link>
to render responses. HAL defines links to be contained in a
<property>_link</property> property of the returned document.</para>
<para>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.</para>
<para>For example, to discover what resources are available at the root
of the application, issue an HTTP <code>GET</code> to the root
URL:</para>
<programlisting>curl -v http://localhost:8080/
&lt; HTTP/1.1 200 OK
&lt; Content-Type: application/hal+json
{ "_links" : {
"orders" : {
"href" : "http://localhost:8080/orders"
}
}
}</programlisting>
<para>The <property>_links</property> 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.</para>
</section>
</section>
<section xml:id="repository-resources.collection-resource">
<title>The collection resource</title>
<para>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
<interfacename>@RepositoryRestResource</interfacename> on the repository
interface.</para>
<section>
<title>Supported HTTP Methods</title>
<para>Collections resources support both <code>GET</code> and
<code>POST</code>. All other HTTP methods will cause a <code>405 Method
Not Allowed</code>.</para>
<section>
<title><code>GET</code></title>
<para>Returns all entities the repository servers through its
<methodname>findAll(…)</methodname> method. If the repository is a
paging repository we include the pagination links if necessary and
additional page metadata.</para>
<simplesect>
<title>Parameters</title>
<para>If the repository has pagination capabilities the resource
takes the following parameters:</para>
<itemizedlist>
<listitem>
<para><code>page</code> - the page number to access (0 indexed,
defaults to 0).</para>
</listitem>
<listitem>
<para><code>size</code> - the page size requested (defaults to
20).</para>
</listitem>
<listitem>
<para><code>sort</code> - a collection of sort directives in the
format <code>($propertyname,)+[asc|desc]</code>?.</para>
</listitem>
</itemizedlist>
</simplesect>
<simplesect>
<title>Custom status codes</title>
<itemizedlist>
<listitem>
<para><code>405 Method Not Allowed</code> - if the
<methodname>findAll(…)</methodname> methods was not exported
(through <code>@RestResource(exported = false)</code>) or is not
present in the repository at all.</para>
</listitem>
</itemizedlist>
</simplesect>
<simplesect>
<title>Supported media types</title>
<itemizedlist>
<listitem>
<para>application/hal+json</para>
</listitem>
<listitem>
<para>application/json</para>
</listitem>
</itemizedlist>
</simplesect>
<simplesect>
<title>Related resources</title>
<itemizedlist>
<listitem>
<para><code>search</code> - a <link
linkend="repository-resources.search-resource">search
resource</link> if the backing repository exposes query
methods.</para>
</listitem>
</itemizedlist>
</simplesect>
</section>
<section>
<title><code>HEAD</code></title>
<para>Returns whether the collection resource is available.</para>
</section>
<section>
<title><code>POST</code></title>
<para>Creates a new entity from the given request body.</para>
<simplesect>
<title>Custom status codes</title>
<itemizedlist>
<listitem>
<para><code>405 Method Not Allowed</code> - if the
<methodname>save(…)</methodname> methods was not exported
(through <code>@RestResource(exported = false)</code>) or is not
present in the repository at all.</para>
</listitem>
</itemizedlist>
</simplesect>
<simplesect>
<title>Supported media types</title>
<itemizedlist>
<listitem>
<para>application/hal+json</para>
</listitem>
<listitem>
<para>application/json</para>
</listitem>
</itemizedlist>
</simplesect>
</section>
</section>
</section>
<section xml:id="repository-resources.item-resource">
<title>The item resource</title>
<para>Spring Data REST exposes a resource for individual collection items
as sub-resources of the collection resource.</para>
<section>
<title>Supported HTTP methods</title>
<para>Item resources generally support <code>GET</code>,
<code>PUT</code>, <code>PATCH</code> and <code>DELETE</code> unless
explicit configuration prevents that (see below for details).</para>
<section>
<title><code>GET</code></title>
<para>Returns a single entity.</para>
<simplesect>
<title>Custom status codes</title>
<itemizedlist>
<listitem>
<para><code>405 Method Not Allowed</code> - if the
<methodname>findOne(…)</methodname> methods was not exported
(through <code>@RestResource(exported = false)</code>) or is not
present in the repository at all.</para>
</listitem>
</itemizedlist>
</simplesect>
<simplesect>
<title>Supported media types</title>
<itemizedlist>
<listitem>
<para>application/hal+json</para>
</listitem>
<listitem>
<para>application/json</para>
</listitem>
</itemizedlist>
</simplesect>
<simplesect>
<title>Related resources</title>
<para>For every association of the domain type we expose links named
after the association property. This can be customized by using
<interfacename>@RestResource</interfacename> on the property. The
related resources are of type <link
linkend="repository-resources.association-resource">association
resource</link>.</para>
</simplesect>
</section>
<section>
<title><code>HEAD</code></title>
<para>Returns whether the item resource is available.</para>
</section>
<section>
<title><code>PUT</code></title>
<para>Replaces the state of the target resource with the supplied
request body.</para>
<simplesect>
<title>Custom status codes</title>
<itemizedlist>
<listitem>
<para><code>405 Method Not Allowed</code> - if the
<methodname>save(…)</methodname> methods was not exported
(through <code>@RestResource(exported = false)</code>) or is not
present in the repository at all.</para>
</listitem>
</itemizedlist>
</simplesect>
<simplesect>
<title>Supported media types</title>
<itemizedlist>
<listitem>
<para>application/hal+json</para>
</listitem>
<listitem>
<para>application/json</para>
</listitem>
</itemizedlist>
</simplesect>
</section>
<section>
<title><code>PATCH</code></title>
<para>Similar to <code>PUT</code> but only applying values sent with
the request body.</para>
<simplesect>
<title>Custom status codes</title>
<itemizedlist>
<listitem>
<para><code>405 Method Not Allowed</code> - if the
<methodname>save(…)</methodname> methods was not exported
(through <code>@RestResource(exported = false)</code>) or is not
present in the repository at all.</para>
</listitem>
</itemizedlist>
</simplesect>
<simplesect>
<title>Supported media types</title>
<itemizedlist>
<listitem>
<para>application/hal+json</para>
</listitem>
<listitem>
<para>application/json</para>
</listitem>
</itemizedlist>
</simplesect>
</section>
<section>
<title><code>DELETE</code></title>
<para>Deletes the resource exposed.</para>
<simplesect>
<title>Custom status codes</title>
<itemizedlist>
<listitem>
<para><code>405 Method Not Allowed</code> - if the
<methodname>delete(…)</methodname> methods was not exported
(through <code>@RestResource(exported = false)</code>) or is not
present in the repository at all.</para>
</listitem>
</itemizedlist>
</simplesect>
</section>
</section>
</section>
<section xml:id="repository-resources.association-resource">
<title>The association resource</title>
<para>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 <interfacename>@RestResource</interfacename> on the
association property.</para>
<section>
<title>Supported HTTP methods</title>
<section>
<title>GET</title>
<para>Reutrns the state of the association resource</para>
<simplesect>
<title>Supported media types</title>
<itemizedlist>
<listitem>
<para>application/hal+json</para>
</listitem>
<listitem>
<para>application/json</para>
</listitem>
</itemizedlist>
</simplesect>
</section>
<section>
<title>PUT</title>
<para>Binds the resource pointed to by the given URI(s) to the
resource. This</para>
<simplesect>
<title>Custom status codes</title>
<itemizedlist>
<listitem>
<para><code>400 Bad Request</code> - if multiple URIs were given
for a to-one-association.</para>
</listitem>
</itemizedlist>
</simplesect>
<simplesect>
<title>Supported media types</title>
<itemizedlist>
<listitem>
<para>text/uri-list - URIs pointing to the resource to bind to
the association.</para>
</listitem>
</itemizedlist>
</simplesect>
</section>
<section>
<title>POST</title>
<para>Only supported for collection associations. Adds a new element
to the collection.</para>
<simplesect>
<title>Supported media types</title>
<itemizedlist>
<listitem>
<para>text/uri-list - URIs pointing to the resource to add to
the association.</para>
</listitem>
</itemizedlist>
</simplesect>
</section>
<section>
<title>DELETE</title>
<para>Unbinds the association.</para>
<simplesect>
<title>Custom status codes</title>
<itemizedlist>
<listitem>
<para><code>405 Method Not Allowed</code> - if the association
is non-optional.</para>
</listitem>
</itemizedlist>
</simplesect>
</section>
</section>
</section>
<section xml:id="repository-resources.search-resource">
<title>The search resource</title>
<para>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 <interfacename>@RestResource</interfacename> on the method
declaration.</para>
<section>
<title>Supported HTTP methods</title>
<para>As the search resource is a read-only resource it supports
<code>GET</code> only.</para>
<section>
<title><code>GET</code></title>
<para>Returns a list of links pointing to the individual query method
resources</para>
<simplesect>
<title>Supported media types</title>
<itemizedlist>
<listitem>
<para>application/hal+json</para>
</listitem>
<listitem>
<para>application/json</para>
</listitem>
</itemizedlist>
</simplesect>
<simplesect>
<title>Related resources</title>
<para>For every query method declared in the repository we expose a
<link linkend="repository-resources.query-method-resource">query
method resource</link>. If the resource supports pagination, the URI
pointing to it will be a URI template containing the pagination
parameters.</para>
</simplesect>
</section>
<section>
<title><code>HEAD</code></title>
<para>Returns whether the search resource is available. A 404 return
code indicates no query method resources available at all.</para>
</section>
</section>
</section>
<section xml:id="repository-resources.query-method-resource">
<title>The query method resource</title>
<para>The query method resource executes the query exposed through an
individual query method on the repository interface.</para>
<section>
<title>Supported HTTP methods</title>
<para>As the search resource is a read-only resource it supports
<code>GET</code> only.</para>
<section>
<title><code>GET</code></title>
<para>Returns the result of the query execution.</para>
<simplesect>
<title>Parameters</title>
<para>If the query method has pagination capabilities (indicated in
the URI template pointing to the resource) the resource takes the
following parameters:</para>
<itemizedlist>
<listitem>
<para><code>page</code> - the page number to access (0 indexed,
defaults to 0).</para>
</listitem>
<listitem>
<para><code>size</code> - the page size requested (defaults to
20).</para>
</listitem>
<listitem>
<para><code>sort</code> - a collection of sort directives in the
format <code>($propertyname,)+[asc|desc]</code>?.</para>
</listitem>
</itemizedlist>
</simplesect>
<simplesect>
<title>Supported media types</title>
<itemizedlist>
<listitem>
<para>application/hal+json</para>
</listitem>
<listitem>
<para>application/json</para>
</listitem>
</itemizedlist>
</simplesect>
</section>
<section>
<title><code>HEAD</code></title>
<para>Returns whether a query method resource is available.</para>
</section>
</section>
</section>
</chapter>

View File

@@ -1,114 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xsi:schemaLocation="http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd http://www.w3.org/1999/xlink http://docbook.org/xml/5.0/xsd/xlink.xsd"
xml:id="representations-chapter"
xmlns="http://docbook.org/ns/docbook"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ns="http://docbook.org/ns/docbook">
<title>Domain Object Representations</title>
<section xml:id="mapping">
<title>Object Mapping</title>
<para>Spring Data REST returns a representation of a domain object that
corresponds to the requested <code>Accept</code> type specified in the
HTTP request. <footnote>
<para>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.</para>
</footnote></para>
<para>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.</para>
<section>
<title>Adding custom (de)serializers to Jackson's ObjectMapper</title>
<para>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.</para>
<section>
<title>Abstract class registration</title>
<para>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:</para>
<programlisting language="java">@Entity
public class MyEntity {
@OneToMany
private List&lt;MyInterface&gt; interfaces;
}</programlisting>
<para>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
<classname>Module</classname>.</para>
<para>To add your own Jackson configuration to the
<classname>ObjectMapper</classname> used by Spring Data REST, override
the <code>configureJacksonObjectMapper</code> method. That method will
be passed an <classname>ObjectMapper</classname> instance that has a
special module to handle serializing and deserializing
<classname>PersistentEntity</classname>s. You can register your own
modules as well, like in the following example. <programlisting
language="java">
@Override protected void configureJacksonObjectMapper(ObjectMapper objectMapper) {
objectMapper.registerModule(new SimpleModule("MyCustomModule"){
@Override public void setupModule(SetupContext context) {
context.addAbstractTypeResolver(
new SimpleAbstractTypeResolver().addMapping(MyInterface.class,
MyInterfaceImpl.class)
);
}
});
}</programlisting></para>
<para>Once you have access to the <classname>SetupContext</classname>
object in your <classname>Module</classname>, you can do all sorts of
cool things to configure Jacskon's JSON mapping. You can read more
about how <classname>Module</classname>s work on Jackson's wiki: <link
xlink:href="http://wiki.fasterxml.com/JacksonFeatureModules">
http://wiki.fasterxml.com/JacksonFeatureModules </link></para>
</section>
<section>
<title>Adding custom serializers for domain types</title>
<para>If you want to (de)serialize a domain type in a special way, you
can register your own implementations with Jackson's
<classname>ObjectMapper</classname> and the Spring Data REST exporter
will transparently handle those domain objects correctly. To add
serializers, from your <code>setupModule</code> method implementation,
do something like the following:</para>
<programlisting language="java">
@Override public void setupModule(SetupContext context) {
SimpleSerializers serializers = new SimpleSerializers();
SimpleDeserializers deserializers = new SimpleDeserializers();
serializers.addSerializer(MyEntity.class, new MyEntitySerializer());
deserializers.addDeserializer(MyEntity.class, new MyEntityDeserializer());
context.addSerializers(serializers);
context.addDeserializers(deserializers);
}</programlisting>
</section>
</section>
</section>
</chapter>

View File

@@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xml:id="validation-chapter"
xmlns="http://docbook.org/ns/docbook"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd">
<title>Validation</title>
<para>There are two ways to register a
<classname>Validator</classname>
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.
</para>
<para>In order to tell Spring Data REST you want a particular
<classname>Validator</classname>
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
<classname>Person</classname>
class before new ones are saved into the repository, you would declare an instance of a
<classname>Validator&lt;Person&gt;</classname>
in your
<classname>ApplicationContext</classname>
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.
</para>
<section>
<title>Assigning Validators manually</title>
<para>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 who's job it is to invoke validators after the correct event. In your configuration
that subclasses Spring Data REST's
<classname>RepositoryRestMvcConfiguration</classname>, override the
<code>configureValidatingRepositoryEventListener</code>
method and call the
<code>addValidator</code>
method on the
<classname>ValidatingRepositoryEventListener</classname>, passing the event you want this validator
to be triggered on, and an instance of the validator.
<programlisting language="java"><![CDATA[
@Override protected void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener v) {
v.addValidator("beforeSave", new BeforeSaveValidator());
}]]></programlisting>
</para>
</section>
</chapter>

View File

@@ -0,0 +1,86 @@
[[events-chapter]]
= Events
There are eight different events that the REST exporter emits throughout the process of working with an entity. Those are:
* BeforeCreateEvent
* AfterCreateEvent
* BeforeSaveEvent
* AfterSaveEvent
* BeforeLinkSaveEvent
* AfterLinkSaveEvent
* BeforeDeleteEvent
* AfterDeleteEvent
== 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.
[source,java]
----
public class BeforeSaveEventListener extends AbstractRepositoryEventListener {
@Override public void onBeforeSave(Object entity) {
... logic to handle inspecting the entity before the Repository saves it
}
@Override public void onAfterDelete(Object entity) {
... send a message that this entity has been deleted
}
}
----
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.
== Writing an annotated handler
Another approach is to use an annotated handler, which does filter 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 BeforeSaveEvents in an annotated POJO for different kinds of domain types, you'd define your class like this:
[source,java]
----
@RepositoryEventHandler
public class PersonEventHandler {
@HandleBeforeSave(Person.class) public void handlePersonSave(Person p) {
... you can now deal with Person in a type-safe way
}
@HandleBeforeSave(Profile.class) public void handleProfileSave(Profile p) {
... you can now deal with Profile in a type-safe way
}
}
----
You can also declare the domain type at the class level:
[source,java]
----
@RepositoryEventHandler(Person.class)
public class PersonEventHandler {
@HandleBeforeSave public void handleBeforeSave(Person p) {
...
}
@HandleAfterDelete public void handleAfterDelete(Person p) {
...
}
}
----
Just declare an instance of your annotated bean in your `ApplicationContext` and the `BeanPostProcessor` that is by default created in `RepositoryRestMvcConfiguration` will inspect the bean for handlers and wire them to the correct events.
[source,java]
----
@Configuration
public class RepositoryConfiguration {
@Bean PersonEventHandler personEventHandler() {
return new PersonEventHandler();
}
}
----

View File

@@ -0,0 +1,88 @@
[[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.
To install Spring Data REST alongside your application, simply add the required dependencies, include the stock `@Configuration` class `RepositoryRestMvcConfiguration` (or subclass it and perform any required manual configuration), and map some URLs to be managed by Spring Data REST.
[[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:
[source,groovy]
----
dependencies {
… other project dependencies
compile "org.springframework.data:spring-data-rest-webmvc:${spring-data-rest-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:
[source,xml]
----
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-webmvc</artifactId>
<version>${spring-data-rest-version}</version>
</dependency>
----
[[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`. You can either import this class into your existing configuration using an `@Import` annotation or you can subclass it and override any of the `configureXXX` methods to add your own configuration to that of Spring Data REST.
In the following example, we'll subclass the standard `RepositoryRestMvcConfiguration` and add some `ResourceMapping` configurations for the `Person` domain object to alter how the JSON will look and how the links to related entities will be handled.
[source,java]
----
@Configuration
@Import(RepositoryRestMvcConfiguration.class)
public class MyWebConfiguration extends RepositoryRestMvcConfiguration {
// … further configuration
}
----
Make sure you also configure Spring Data repositories for the store you use. For details on that, please consult the reference documentation for the corresponding Spring Data module.
[[getting-started.bootstrap]]
== Starting the application
As Spring Data REST is build on SpringMVC, you simply stick to the means you use to bootstrap Spring MVC. In a Servlet 3.0 environment this might look something like this:
[source,java]
----
public class RestExporterWebInitializer implements WebApplicationInitializer {
@Override public void onStartup(ServletContext servletContext) throws ServletException {
// Bootstrap repositories in root application context
AnnotationConfigWebApplicationContext rootCtx = new AnnotationConfigWebApplicationContext();
rootCtx.register(JpaRepositoryConfig.class); // Include JPA entities, Repositories
servletContext.addListener(new ContextLoaderListener(rootCtx));
// Enable Spring Data REST in the DispatcherServlet
AnnotationConfigWebApplicationContext webCtx = new AnnotationConfigWebApplicationContext();
webCtx.register(MyWebConfiguration.class);
DispatcherServlet dispatcherServlet = new DispatcherServlet(webCtx);
ServletRegistration.Dynamic reg = servletContext.addServlet("rest-exporter", dispatcherServlet);
reg.setLoadOnStartup(1);
reg.addMapping("/*");
}
}
----
The equivalent of the above in a standard web.xml will also work identically to this configuration if you are still in a servlet 2.5 environment. When you deploy this application to your servlet container, you should be able to see what repositories are exported by accessing the root of the application.

View File

@@ -0,0 +1,19 @@
[[spring-data-rest-reference]]
= Spring Data REST Reference Documentation
Jon Brisbin, Oliver Gierke
:toc:
:idprefix:
{version}
(C) 2012-2014 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._
:leveloffset: 1
include::intro.adoc[]
include::getting-started.adoc[]
include::repository-resources.adoc[]
include::representations.adoc[]
include::validation.adoc[]
include::events.adoc[]

View File

@@ -0,0 +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 drive way. Spring MVC offers a solid foundation to build theses kinds of services but implementing very basic functionality of REST web service can be 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 allows to integrate the resources into related hypermedia based functionality as easy as possible.

View File

@@ -0,0 +1,266 @@
[[repository-resources]]
= Repository resources
[[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:
[source]
----
public interface OrderRepository extends CrudRepository<Order, Long> { }
----
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 <<repository-resources.collection-resource,collection resources>> and <<repository-resources.item-resource,item resources>>.
[[repository-resources.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`.
[[repository-resources.resource-discoverability]]
=== Resource discoverability
A core principle of 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.
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.
For example, to discover what resources are available at the root of the application, issue an HTTP `GET` to the root URL:
[source]
----
curl -v http://localhost:8080/
< HTTP/1.1 200 OK
< Content-Type: application/hal+json
{ "_links" : {
"orders" : {
"href" : "http://localhost:8080/orders"
}
}
}
----
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.
[[repository-resources.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.
=== Supported HTTP Methods
Collections resources support both `GET` and `POST`. All other HTTP methods will cause a `405 Method Not Allowed`.
==== 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.
===== 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]`?.
===== 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.
===== Supported media types
* application/hal+json
* application/json
===== Related resources
* `search` - a <<repository-resources.search-resource,search resource>> if the backing repository exposes query methods.
==== HEAD
Returns whether the collection resource is available.
==== POST
Creates a new entity from the given request body.
===== 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.
===== Supported media types
* application/hal+json
* application/json
[[repository-resources.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
Item resources generally support `GET`, `PUT`, `PATCH` and `DELETE` unless explicit configuration prevents that (see below for details).
==== GET
Returns a single entity.
===== 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.
===== Supported media types
* application/hal+json
* application/json
===== 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 <<repository-resources.association-resource,association resource>>.
==== HEAD
Returns whether the item resource is available.
==== PUT
Replaces the state of the target resource with the supplied request body.
===== 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.
===== Supported media types
* application/hal+json
* application/json
==== PATCH
Similar to `PUT` but only applying values sent with the request body.
===== 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.
===== Supported media types
* application/hal+json
* application/json
==== DELETE
Deletes the resource exposed.
===== 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.
[[repository-resources.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.
=== Supported HTTP methods
==== GET
Returns the state of the association resource
===== Supported media types
* application/hal+json
* application/json
==== PUT
Binds the resource pointed to by the given URI(s) to the resource. This
===== Custom status codes
* `400 Bad Request` - if multiple URIs were given for a to-one-association.
===== Supported media types
* text/uri-list - URIs pointing to the resource to bind to the association.
==== POST
Only supported for collection associations. Adds a new element to the collection.
===== Supported media types
* text/uri-list - URIs pointing to the resource to add to the association.
==== DELETE
Unbinds the association.
===== Custom status codes
* `405 Method Not Allowed` - if the association is non-optional.
[[repository-resources.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
As the search resource is a read-only resource it supports `GET` only.
==== GET
Returns a list of links pointing to the individual query method resources
===== Supported media types
* application/hal+json
* application/json
===== Related resources
For every query method declared in the repository we expose a <<repository-resources.query-method-resource,query method resource>>. If the resource supports pagination, the URI pointing to it will be a URI template containing the pagination parameters.
==== HEAD
Returns whether the search resource is available. A 404 return code indicates no query method resources available at all.
[[repository-resources.query-method-resource]]
== The query method resource
The query method resource executes the query exposed through an individual query method on the repository interface.
=== Supported HTTP methods
As the search resource is a read-only resource it supports `GET` only.
==== GET
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]`?.
===== Supported media types
* application/hal+json
* application/json
==== HEAD
Returns whether a query method resource is available.

View File

@@ -0,0 +1,69 @@
[[representations-chapter]]
= Domain Object 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.
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.
=== Adding custom (de)serializers 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.
==== 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:
[source,java]
----
@Entity
public class MyEntity {
@OneToMany
private List<MyInterface> 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`.
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.
[source,java]
----
@Override
protected void configureJacksonObjectMapper(ObjectMapper objectMapper) {
objectMapper.registerModule(new SimpleModule("MyCustomModule") {
@Override
public void setupModule(SetupContext context) {
context.addAbstractTypeResolver(
new SimpleAbstractTypeResolver().addMapping(MyInterface.class,
MyInterfaceImpl.class)
);
}
});
}
----
Once you have access to the `SetupContext` object in your `Module`, you can do all sorts of cool things to configure Jacskon'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 ]
==== 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:
[source,java]
----
@Override
public void setupModule(SetupContext context) {
SimpleSerializers serializers = new SimpleSerializers();
SimpleDeserializers deserializers = new SimpleDeserializers();
serializers.addSerializer(MyEntity.class, new MyEntitySerializer());
deserializers.addDeserializer(MyEntity.class, new MyEntityDeserializer());
context.addSerializers(serializers);
context.addDeserializers(deserializers);
}
----

View File

@@ -0,0 +1,18 @@
[[validation-chapter]]
= 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.
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<Person>` 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.
== 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 who's job it is to invoke validators after the correct event. In your configuration that subclasses Spring Data REST's `RepositoryRestMvcConfiguration`, override the `configureValidatingRepositoryEventListener` method and call the `addValidator` method on the `ValidatingRepositoryEventListener`, passing the event you want this validator to be triggered on, and an instance of the validator.
[source,java]
----
@Override
protected void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener v) {
v.addValidator("beforeSave", new BeforeSaveValidator());
}
----