Work on reference documentation.

This commit is contained in:
Jon Brisbin
2013-02-26 16:39:18 -06:00
committed by Jon Brisbin
parent 7820db0231
commit c23b16bebc
4 changed files with 847 additions and 19 deletions

View File

@@ -0,0 +1,13 @@
@IMPORT url("manual.css");
body {
background: url("../images/background.png") no-repeat center top;
}
span.property {
font-family: monospace;
}
div.command-synopsis {
font-family: monospace;
}

View File

@@ -1,12 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<book xml:id="spring-data-rest-reference"
version="5.0"
xmlns="http://docbook.org/ns/docbook"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
xsi:schemaLocation="http://docbook.org/ns/docbook http://www.oasis-open.org/docbook/xml/5.0/xsd/docbook.xsd">
<info>
<title>Spring Data REST Reference Documentation</title>
@@ -34,20 +31,18 @@
</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>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></toc>
<toc>
<part xml:id="intro">
<title>Spring Data REST Introduction</title>
</toc>
<xi:include href="intro.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
</part>
<xi:include href="intro.xml"/>
<xi:include href="representations.xml"/>
</book>

View File

@@ -1,16 +1,804 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xml:id="intro-chapter"
version="5.0"
xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd">
xsi:schemaLocation="http://docbook.org/ns/docbook http://www.oasis-open.org/docbook/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.oasis-open.org/docbook/xml/5.0/xsd/xlink.xsd">
<title>Spring Data REST Introduction</title>
<title>Introduction</title>
<section xml:id="intro-overview">
<title>Overview of Spring Data REST features</title>
<para>Spring Data REST makes exporting domain objects to RESTful clients using
<link
xlink:href="http://en.wikipedia.org/wiki/HATEOAS">HATEOAS
</link>
principles very easy. It exposes the CRUD methods of the Spring Data
<link
xlink:href="http://static.springsource.org/spring-data/commons/docs/current/api/org/springframework/data/repository/CrudRepository.html">
<classname>CrudRepository</classname>
</link>
interface to HTTP. Spring Data REST also reads the body of HTTP requests and interprets them as domain objects. It
recognizes relationships between entities and represents that relationship in the form of a<code>Link</code>.
</para>
<para></para>
<section>
<title>HTTP Verb to CRUD Method Mapping</title>
<para>Spring Data REST translates HTTP calls to method calls by mapping the HTTP verbs to CRUD methods. The
following table illustrates the way in which an HTTP verb is mapped to a
<code>CrudRepository</code>
method.
</para>
<table>
<caption>HTTP verb to CRUD method mapping</caption>
<thead>
<tr>
<th>Verb</th>
<th>Method</th>
</tr>
</thead>
<tr>
<td>
<code>GET</code>
</td>
<td>
<code>CrudRepository&lt;ID,T&gt;.findOne(ID id)</code>
</td>
</tr>
<tr>
<td>
<code>POST</code>
</td>
<td>
<code>CrudRepository&lt;ID,T&gt;.save(T entity)</code>
</td>
</tr>
<tr>
<td>
<code>PUT</code>
</td>
<td>
<code>CrudRepository&lt;ID,T&gt;.save(T entity)</code>
</td>
</tr>
<tr>
<td>
<code>DELETE</code>
</td>
<td>
<code>CrudRepository&lt;ID,T&gt;.delete(ID id)</code>
</td>
</tr>
</table>
<para>By default, all of these methods are exported to clients. By placing an annotation on your
<classname>CrudRepository</classname>
subinterface, however, you can turn access to a method off. This is discussed in more detail in the section on
configuration.
</para>
</section>
<section xml:id="hateoas-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 number of ways to accomplish this but no real standard way. Spring
Data REST uses a link method that is consistent across Spring Data REST: it provides links in a property called
<code>links</code>. That property is an array of objects that take the form of something resembling an
<link xlink:href="http://tools.ietf.org/html/rfc4287#section-4.2.7">atom:link</link>
element in the
<link xlink:href="http://tools.ietf.org/html/rfc4287">Atom XML namespace</link>.
</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 GET to
the root URL:
</para>
<programlisting><![CDATA[curl -v http://localhost:8080/
< HTTP/1.1 200 OK
< Content-Type: application/json
<
{
"links" : [ {
"rel" : "customer",
"href" : "http://localhost:8080/customer"
}, {
"rel" : "profile",
"href" : "http://localhost:8080/profile"
}, {
"rel" : "order",
"href" : "http://localhost:8080/order"
}, {
"rel" : "people",
"href" : "http://localhost:8080/people"
}, {
"rel" : "product",
"href" : "http://localhost:8080/product"
} ],
"content" : [ ]
}]]></programlisting>
<para>The
<property>links</property>
property of the result document contains an array of objects that have
<property>rel</property>
and
<property>href</property>
properties on them.
</para>
<section>
<title>Compact vs. Verbose</title>
<para>When issuing a request to a resource, the default behavior is to provide as much information as possible in
the body of the response. In the case of accessing a
<classname>Repository</classname>
resource, Spring Data REST will inline entities into the body of the response. This could lead to poor network
performance in the case of a very large number of entities. To reduce the amount of data sent back in the
response, a user agent can request the special content type
<code>application/x-spring-data-compact+json</code>
by placing this in the request
<code>Accept</code>
header. Rather than inlining the entities, this content-type provides a link to each entity in the
<property>links</property>
property.
</para>
<programlisting><![CDATA[curl -v -H "Accept: application/x-spring-data-compact+json" http://localhost:8080/customer
< HTTP/1.1 200 OK
< Content-Type: application/x-spring-data-compact+json
<
{
"links" : [ {
"rel" : "customer.search",
"href" : "http://localhost:8080/customer/search"
} ],
"content" : [ ]
}]]></programlisting>
</section>
</section>
<section xml:id="rest-shell">
<title>Using the
<command>rest-shell</command>
</title>
<para>The
<link xlink:href="https://github.com/SpringSource/rest-shell">
<command>rest-shell</command>
</link>
is a command-line shell that aims to make writing REST-based applications easier. It is based on spring-shell and
integrated with Spring HATEOAS in such a way that REST resources that output JSON compliant with Spring HATEOAS
can be discovered by the shell and interactions with the REST resources become much easier than by manipulating
the URLs in bash using a tool like
<command>curl</command>.
</para>
<para>The rest-shell provides a number of useful commands for discovering and interacting with REST resources. For
example discover will discover what resources are available and print out an easily-readable table of rels and
URIs that relate to those resources. Once these resources have been discovered, the rel of those URIs can be used
in place of the URI itself in most operations, thus cutting down on the amount of typing needed to issue HTTP
requests to your REST resources.
</para>
<section>
<title>Installing the
<command>rest-shell</command>
</title>
<para>If you're using Mac OS X and Homebrew, then installation is super easy:</para>
<programlisting><![CDATA[brew install rest-shell]]></programlisting>
<para>Other platforms are simple as well: just download the archive from the GitHub page and unzip it to a
location on your local hard drive.
</para>
</section>
<section>
<title>Discovering resources</title>
<para>The rest-shell is aimed at making it easier to interact with REST resources by managing the session baseUri
much like a directory in a filesystem. Whenever resources are discovered, you can then follow to a new baseUri,
which means you can then use relative URIs. Here's an example of discovering resources, then following a link by
referencing its rel value, and then using a relative URI to access resources under that new baseUri:
</para>
<programlisting><![CDATA[http://localhost:8080:> discover
rel href
========================================================
address http://localhost:8080/address
family http://localhost:8080/family
people http://localhost:8080/person
profile http://localhost:8080/profile
http://localhost:8080:> follow people
http://localhost:8080/person:> list
rel href
===================================================
people.Person http://localhost:8080/person/1
people.Person http://localhost:8080/person/2
people.search http://localhost:8080/person/search
http://localhost:8080/person:> get 1
> GET http://localhost:8080/person/1
< 200 OK
< ETag: "2"
< Content-Type: application/json
<
{
"links" : [ {
"rel" : "self",
"href" : "http://localhost:8080/person/1"
}, {
"rel" : "peeps.Person.profiles",
"href" : "http://localhost:8080/person/1/profiles"
}, {
"rel" : "peeps.Person.addresses",
"href" : "http://localhost:8080/person/1/addresses"
} ],
"name" : "John Doe"
}]]></programlisting>
<para>
<emphasis>NOTE: If you want tab completion of discovered rels, just use the --rel flag.</emphasis>
</para>
</section>
<section>
<title>Creating new resources</title>
<para>The rest-shell can do basic parsing of JSON data within the shell (though there are some limitations due to
the nature of the command line parsing being sensitive to whitespace). This makes it easy to create new
resources
by including JSON data directly in the shell:
</para>
<programlisting><![CDATA[http://localhost:8080/person:> post --data "{name: 'John Doe'}"
> POST http://localhost:8080/person/
< 201 CREATED
< Location: http://localhost:8080/person/8
< Content-Length: 0
<
http://localhost:8080/person:> get 8
> GET http://localhost:8080/person/8
< 200 OK
< ETag: "0"
< Content-Type: application/json
<
{
"links" : [ {
"rel" : "self",
"href" : "http://localhost:8080/person/8"
}, {
"rel" : "people.Person.addresses",
"href" : "http://localhost:8080/person/8/addresses"
}, {
"rel" : "people.Person.profiles",
"href" : "http://localhost:8080/person/8/profiles"
} ],
"name" : "John Doe"
}]]></programlisting>
<para>If your needs of representing JSON get more complicated than what the spring-shell interface can handle, you
can create a directory somewhere with .json files in it, one file per entitiy, and use the --from option to the
post command. This will walk the directory and make a POST request for each .json file found.
</para>
<programlisting><![CDATA[http://localhost:8080/person:> post --from work/people_to_load
128 items uploaded to the server using POST.
http://localhost:8080/person:>]]></programlisting>
<para>You can also reference a specific file rather than an entire directory.</para>
<programlisting><![CDATA[http://localhost:8080/person:> post --from work/people_to_load/someone.json
1 items uploaded to the server using POST.
http://localhost:8080/person:>]]></programlisting>
</section>
<section>
<title>Passing query parameters</title>
<para>If you're calling URLs that require query parameters, you'll need to pass those as a JSON-like fragment in
the --params parameter to the get and list commands. Here's an example of calling a URL that expects parameter
input:
</para>
<programlisting><![CDATA[http://localhost:8080/person:> get search/byName --params "{name: 'John Doe'}"]]>
</programlisting>
</section>
<section>
<title>Outputing results to a file</title>
<para>It's not always desirable to output the results of an HTTP request to the screen. It's handy for debugging
but
sometimes you want to save the results of a request because they're not easily reproducible or any number of
other
equally valid reasons. All the HTTP commands take an --output parameter that writes the results of an HTTP
operation to the given file. For example, to output the above search to a file:
</para>
<programlisting><![CDATA[http://localhost:8080/person:> get search/byName --params "{name: 'John Doe'}" --output by_name.txt >> by_name.txt
http://localhost:8080/person:>]]></programlisting>
</section>
<section>
<title>Sending complex JSON</title>
<para>Because the rest-shell uses the spring-shell underneath, there are limitations on the format of the JSON
data
you can enter directly into the command line. If your JSON is too complex for the simplistic limitations of the
shell --data parameter, you can simply load the JSON from a file or from all the files in a directory.
</para>
<para>When doing a post or put, you can optionally pass the --from parameter. The value of this parameter should
either be a file or a directory. If the value is a directory, the shell will read each file that ends with .json
and make a POST or PUT with the contents of that file. If the parameter is a file, then the rest-shell will
simpy
load that file and POST/PUT that data in that individual file.
</para>
</section>
<section>
<title>Shelling out to bash</title>
<para>One of the nice things about spring-shell is that you can directly shell out commands to the underlying
terminal shell. This is useful for doing things like load a JSON file in an editor. For instance, assume I have
the Sublime Text 2 command subl in my path. I can then load a JSON file for editing from the rest-shell like
this:
</para>
<programlisting><![CDATA[http://localhost:8080/person:> ! subl test.json
http://localhost:8080/person:>]]></programlisting>
<para>I then edit the file as I wish. When I'm ready to POST that data to the server, I can do so using the --from
parameter:
</para>
<programlisting><![CDATA[http://localhost:8080/person:> post --from test.json
1 items uploaded to the server using POST.
http://localhost:8080/person:>]]></programlisting>
</section>
<section>
<title>Setting context variables</title>
<para>Starting with rest-shell version 1.1, you can also work with context variables during your shell session.
This
is useful for saving settings you might reference often. The rest-shell now integrates Spring Expression
Language
support, so these context variables are usable in expressions within the shell.
</para>
<programlisting><![CDATA[http://localhost:8080/person:> var set --name specialUri --value http://longdomainname.com/api
http://localhost:8080/person:> var get --name specialUri
http://longdomainname.com/api
http://localhost:8080/person:> var list
{
"responseHeaders" : {
... HTTP headers from last request
},
"responseBody" : {
... Body from the last request
},
"specialUri" : "http://longdomainname.com/api",
"requestUrl" : ... URL from the last request,
"env" : {
... System properties and environment variables
}
}]]></programlisting>
<para>The variables are accessible from SpEL expressions which are valid in a number of different contexts, most
importantly in the path argument to the HTTP and discover commands, and in the data argument to the put and post
commands.
</para>
<para>Since the rest-shell is aware of environment variables and system properties, you can incorporate external
parameters into your interaction with the shell. For example, to externally define a baseUri, you could set a
system property before invoking the shell. The shell will incorporate anything defined in the JAVA_OPTS
environment variable, so you could parameterize your interaction with a REST service.
</para>
<programlisting><![CDATA[JAVA_OPTS="-DbaseUri=http://mylongdomain.com/api" rest-shell
http://localhost:8080:> discover #{env.baseUri}
rel href
=================================================================
... resources for this URL
http://mylongdomain.com/api:>]]></programlisting>
</section>
<section>
<title>Per-user shell initialization</title>
<para>The rest-shell supports a "dotrc" type of initialization by reading in all files found in the
$HOME/.rest-shell/ directory and assuming they have shell commands in them. The rest-shell will execute these
commands on startup. This makes it easy to set variables for commonly-used URIs or possibly set a baseUri.
</para>
<programlisting><![CDATA[echo "var set --name svcuri --value http://api.myservice.com/v1" > ~/.rest-shell/00-vars
echo "discover #{svcuri}" > ~/.rest-shell/01-baseUri
> rest-shell
INFO: No resources found...
INFO: Base URI set to 'http://api.myservice.com/v1'
___ ___ __ _____ __ _ _ _ _ __
| _ \ __/' _/_ _/' _/| || | / / | \ \
| v / _|`._`. | | `._`.| >< | / / / > >
|_|_\___|___/ |_| |___/|_||_| |_/_/ /_/
1.2.1.RELEASE
Welcome to the REST shell. For assistance hit TAB or type "help".
http://api.myservice.com/v1:>]]></programlisting>
</section>
<section>
<title>SSL Certificate Validation</title>
<para>If you generate a self-signed certificate for your server, by default the rest-shell will complain and
refuse
to connect. This is the default behavior of RestTemplate. To turn off certificate and hostname checking, use the
ssl validate --enabled false command.
</para>
</section>
<section>
<title>HTTP Basic authentication</title>
<para>There is also a convenience command for setting an HTTP Basic authentication header. Use auth basic
--username
user --pasword passwd to set a username and password to base64 encode and place into the Authorization header
that
will be part of the current session's headers.
</para>
<para>You can clear the authentication by using the auth clear command or by removing the Authorization header
using
the headers clear command.
</para>
</section>
<section>
<title>Commands</title>
<para>The rest-shell provides the following commands:</para>
<table>
<caption>rest-shell commands</caption>
<thead>
<tr>
<th>Command</th>
<th>Description</th>
</tr>
</thead>
<tr>
<td>
<cmdsynopsis>
<command>baseUri</command>
<arg choice="req">
<replaceable>uri</replaceable>
</arg>
</cmdsynopsis>
</td>
<td>
<para>Set the base URI used for this point forward in the session. Relative URIs will be calculated relative
to this setting.
</para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command>discover</command>
<group>
<arg>--rel
<replaceable>rel</replaceable>
</arg>
<arg>
<replaceable>path</replaceable>
</arg>
</group>
</cmdsynopsis>
</td>
<td>
<para>Find out what resources are available at the given URI. If no URI is given, use the baseUri.
</para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command>follow</command>
<group>
<arg>--rel
<replaceable>rel</replaceable>
</arg>
<arg>
<replaceable>path</replaceable>
</arg>
</group>
</cmdsynopsis>
</td>
<td>
<para>Set the baseUri to the URI assigned to this given rel or path but do not discover resources.
</para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command>list</command>
<group>
<arg>--rel
<replaceable>rel</replaceable>
</arg>
<arg>
<replaceable>path</replaceable>
</arg>
</group>
<arg>--params
<replaceable>JSON</replaceable>
</arg>
</cmdsynopsis>
</td>
<td>
<para>Find out what resources are available at the given URI.
</para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command>headers set</command>
<arg choice="req">--name
<replaceable>name</replaceable>
</arg>
<arg choice="req">--value
<replaceable>value</replaceable>
</arg>
</cmdsynopsis>
</td>
<td>
<para>Set an HTTP header for use from this point forward in the session.</para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command>headers clear</command>
</cmdsynopsis>
</td>
<td>
<para>Clear all HTTP headers set during this session.</para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command>headers list</command>
</cmdsynopsis>
</td>
<td>
<para>Print out the currently-set HTTP headers for this session.</para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command>history list</command>
</cmdsynopsis>
</td>
<td>
<para>List the URIs previously set as baseUris during this session.</para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command>history go</command>
<arg>
<replaceable>num</replaceable>
</arg>
</cmdsynopsis>
</td>
<td>
<para>Jump to a URI by pulling one from the history.</para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command>var clear</command>
</cmdsynopsis>
</td>
<td>
<para>Clear this shell's variable context.</para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command>var get</command>
<arg>--name
<replaceable>name</replaceable>
</arg>
<arg>--value
<replaceable>expression</replaceable>
</arg>
</cmdsynopsis>
</td>
<td>
<para>Get a variable from this shell's context by name or evaluate a shell expression.</para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command>var list</command>
</cmdsynopsis>
</td>
<td>
<para>List variables currently set in this shell's context.</para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command>var set</command>
</cmdsynopsis>
</td>
<td>
<para>Set a variable in this shell's context.</para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command>up</command>
</cmdsynopsis>
</td>
<td>
<para>Traverse one level up in the URL hierarchy.</para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command>get</command>
<group>
<arg>--rel
<replaceable>rel</replaceable>
</arg>
<arg>
<replaceable>path</replaceable>
</arg>
</group>
<arg>--follow true | false</arg>
<arg>--params
<replaceable>JSON</replaceable>
</arg>
<arg>--output
<replaceable>filename</replaceable>
</arg>
</cmdsynopsis>
</td>
<td>
<para>HTTP GET from the given path. If
<code>--follow true</code>
is set, then follow any redirects automatically. If
<code>--output filename</code>
is set, output the the response into the given file.
</para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command>post</command>
</cmdsynopsis>
</td>
<td>
<para>HTTP POST to the given path, passing JSON given in the --data parameter.</para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command></command>
</cmdsynopsis>
</td>
<td>
<para></para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command></command>
</cmdsynopsis>
</td>
<td>
<para></para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command></command>
</cmdsynopsis>
</td>
<td>
<para></para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command></command>
</cmdsynopsis>
</td>
<td>
<para></para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command></command>
</cmdsynopsis>
</td>
<td>
<para></para>
</td>
</tr>
<tr>
<td>
<cmdsynopsis>
<command></command>
</cmdsynopsis>
</td>
<td>
<para></para>
</td>
</tr>
</table>
<para>
get - HTTP GET from the given path.
post - HTTP POST to the given path, passing JSON given in the --data parameter.
put - HTTP PUT to the given path, passing JSON given in the --data parameter.
delete - HTTP DELETE to the given path.
auth basic - Set an HTTP Basic authentication token for use in this session.
auth clear - Clear the Authorization header currently in use.
ssl validate - Disable certificate checking to work with self-signed certificates.
</para>
</section>
</section>
</chapter>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xml:id="intro-chapter"
xmlns="http://docbook.org/ns/docbook"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://docbook.org/ns/docbook http://www.oasis-open.org/docbook/xml/5.0/xsd/docbook.xsd">
<title>Domain Object Representations</title>
<section xml:id="links">
<title>Links as First-Class Objects</title>
<para>
</para>
</section>
<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>
</section>
</chapter>