Update the documentation.
This commit is contained in:
@@ -43,7 +43,10 @@
|
||||
</toc>
|
||||
|
||||
<xi:include href="intro.xml"/>
|
||||
<xi:include href="representations.xml"/>
|
||||
<xi:include href="install.xml"/>
|
||||
<xi:include href="representations.xml"/>
|
||||
<xi:include href="paging.xml"/>
|
||||
<xi:include href="validation.xml"/>
|
||||
<xi:include href="rest-shell.xml"/>
|
||||
|
||||
</book>
|
||||
@@ -7,7 +7,7 @@
|
||||
<title>Installing Spring Data REST</title>
|
||||
|
||||
<section>
|
||||
<title>Adding Spring Data REST to an existing Spring MVC application</title>
|
||||
<title>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
|
||||
@@ -20,7 +20,171 @@
|
||||
class (or subclass it and perform any required manual configuration), and map some URLs to be managed by Spring
|
||||
Data REST.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>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><![CDATA[dependencies {
|
||||
... other project dependencies
|
||||
compile "org.springframework.data:spring-data-rest-webmvc:1.1.0.M1"
|
||||
}]]></programlisting>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>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><![CDATA[<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-rest-webmvc</artifactId>
|
||||
<version>1.1.0.M1</version>
|
||||
</dependency>]]></programlisting>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>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"><![CDATA[
|
||||
@Configuration
|
||||
public class MyWebConfiguration extends RepositoryRestMvcConfiguration {
|
||||
|
||||
@Override protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
|
||||
config.addResourceMappingForDomainType(Person.class)
|
||||
.addResourceMappingFor("lastName")
|
||||
.setPath("surname"); // Change 'lastName' to 'surname' in the JSON
|
||||
config.addResourceMappingForDomainType(Person.class)
|
||||
.addResourceMappingFor("siblings")
|
||||
.setRel("siblings")
|
||||
.setPath("siblings"); // Pointless in this example,
|
||||
// but shows how to change 'rel' and 'path' values.
|
||||
}
|
||||
|
||||
}
|
||||
]]></programlisting>
|
||||
</para>
|
||||
|
||||
<para>There are numerous methods on the
|
||||
<classname>RepositoryRestConfiguration</classname>
|
||||
object to allow you to configure various aspects of Spring Data REST. Please read the javadoc for that class to
|
||||
get detailed descriptions of the various settings you can control.
|
||||
</para>
|
||||
|
||||
<section>
|
||||
<title>Adding custom converters</title>
|
||||
|
||||
<para>It may be necessary to add a custom converter to Spring Data REST. You might need to turn a query parameter
|
||||
into a complex object, for instance. In that case, you'll want to override the
|
||||
<code>configureConversionService</code>
|
||||
method and add your own converters. To convert a query parameter to a complex object, for instance, you would
|
||||
want to register a converter for
|
||||
<classname>String[]</classname>
|
||||
to
|
||||
<classname>MyPojo</classname>.
|
||||
|
||||
<programlisting language="java"><![CDATA[
|
||||
@Bean public MyPojoConverter myPojoConverter() {
|
||||
return new MyPojoConverter();
|
||||
}
|
||||
|
||||
@Override protected void configureConversionService(ConfigurableConversionService conversionService) {
|
||||
conversionService.addConverter(String[].class, myPojoConverter());
|
||||
}]]></programlisting>
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Adding Spring Data REST to Spring MVC</title>
|
||||
|
||||
<para>Since Spring Data REST is simply a Spring MVC application, you only need to include the REST configuration
|
||||
into the configuration for the
|
||||
<classname>DispatcherServlet</classname>. If using a Servlet 3.0
|
||||
<classname>WebApplicationInitializer</classname>
|
||||
(the preferred configuration for Spring Data REST applications), you would add your subclassed configuration
|
||||
from above into the configuration for the
|
||||
<classname>DispatcherServlet</classname>. The following configuration class is from the example project and
|
||||
includes datasource configuration for three different datastores and domain models, which will all be exported
|
||||
by Spring Data REST.
|
||||
|
||||
<programlisting language="java"><![CDATA[
|
||||
public class RestExporterWebInitializer implements WebApplicationInitializer {
|
||||
|
||||
@Override public void onStartup(ServletContext servletContext) throws ServletException {
|
||||
AnnotationConfigWebApplicationContext rootCtx = new AnnotationConfigWebApplicationContext();
|
||||
rootCtx.register(
|
||||
JpaRepositoryConfig.class, // Include JPA entities, Repositories
|
||||
MongoDbRepositoryConfig.class, // Include MongoDB document entities, Repositories
|
||||
GemfireRepositoryConfig.class // Inlucde Gemfire entities, Repositories
|
||||
);
|
||||
servletContext.addListener(new ContextLoaderListener(rootCtx));
|
||||
|
||||
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.
|
||||
</para>
|
||||
|
||||
<para>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. You can use curl or, more easily, the
|
||||
<code>rest-shell</code>:
|
||||
|
||||
<programlisting><![CDATA[$ rest-shell
|
||||
|
||||
___ ___ __ _____ __ _ _ _ _ __
|
||||
| _ \ __/' _/_ _/' _/| || | / / | \ \
|
||||
| v / _|`._`. | | `._`.| >< | / / / > >
|
||||
|_|_\___|___/ |_| |___/|_||_| |_/_/ /_/
|
||||
1.2.1.RELEASE
|
||||
|
||||
Welcome to the REST shell. For assistance hit TAB or type "help".
|
||||
http://localhost:8080:> list
|
||||
rel href
|
||||
==========================================
|
||||
people http://localhost:8080/people
|
||||
profile http://localhost:8080/profile
|
||||
customer http://localhost:8080/customer
|
||||
order http://localhost:8080/order
|
||||
product http://localhost:8080/product
|
||||
]]></programlisting>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
@@ -168,617 +168,4 @@
|
||||
|
||||
</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>put</command>
|
||||
</cmdsynopsis>
|
||||
</td>
|
||||
<td>
|
||||
<para>HTTP PUT to the given path, passing JSON given in the --data parameter.</para>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<cmdsynopsis>
|
||||
<command>delete</command>
|
||||
</cmdsynopsis>
|
||||
</td>
|
||||
<td>
|
||||
<para>HTTP DELETE to the given path.</para>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<cmdsynopsis>
|
||||
<command>auth basic</command>
|
||||
</cmdsynopsis>
|
||||
</td>
|
||||
<td>
|
||||
<para>Set an HTTP Basic authentication token for use in this session.</para>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<cmdsynopsis>
|
||||
<command>auth clear</command>
|
||||
</cmdsynopsis>
|
||||
</td>
|
||||
<td>
|
||||
<para>Clear the Authorization header currently in use.</para>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<cmdsynopsis>
|
||||
<command>ssl validate</command>
|
||||
</cmdsynopsis>
|
||||
</td>
|
||||
<td>
|
||||
<para>Disable certificate checking to work with self-signed certificates.</para>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
114
src/reference/docbook/paging.xml
Normal file
114
src/reference/docbook/paging.xml
Normal file
@@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<chapter xml:id="paging-chapter"
|
||||
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.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>Paging and Sorting</title>
|
||||
|
||||
<section>
|
||||
<title>Paging</title>
|
||||
|
||||
<para>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. To add paging support to your Repositories, you need to extend
|
||||
the
|
||||
<classname>PagingAndSortingRepository<T,ID></classname>
|
||||
interface rather than the basic
|
||||
<classname>CrudRepository<T,ID></classname>
|
||||
interface. This adds methods that accept a
|
||||
<classname>Pageable</classname>
|
||||
to control the number and page of results returned.
|
||||
|
||||
<programlisting language="java"><![CDATA[public Page findAll(Pageable pageable);]]></programlisting>
|
||||
</para>
|
||||
|
||||
<para>If you extend
|
||||
<classname>PagingAndSortingRepository<T,ID></classname>
|
||||
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 limit parameter:
|
||||
|
||||
<programlisting><![CDATA[http://localhost:8080/people/?limit=50]]></programlisting>
|
||||
</para>
|
||||
|
||||
<para>To get paging in your query methods, you must change the signature of your query methods to accept a
|
||||
<classname>Pageable</classname>
|
||||
as a parameter and return a
|
||||
<classname>Page<T></classname>
|
||||
rather than a
|
||||
<classname>List<T></classname>. Otherwise, you won't get any paging information in the JSON and
|
||||
specifying the query parameters that control paging will have no effect.
|
||||
</para>
|
||||
|
||||
<para>By default, the URL query parameters recognized are
|
||||
<code>page</code>, to specify page number
|
||||
<code>limit</code>, to specify how many results to return on a page, and
|
||||
<code>sort</code>
|
||||
to specify the query method parameter on which to sort. To change the names of the query parameters, simply call
|
||||
the appropriate method on
|
||||
<classname>RepositoryRestConfiguration</classname>
|
||||
and give it the text you would like to use for the query parameter. The following, for example, would set the
|
||||
paging parameter to
|
||||
<code>p</code>, the limit parameter to
|
||||
<code>l</code>, and the sort parameter to
|
||||
<code>q</code>:
|
||||
|
||||
<programlisting language="java"><![CDATA[
|
||||
@Override protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
|
||||
config.setPageParamName("p")
|
||||
.setLimitParamName("l")
|
||||
.setSortParamName("q");
|
||||
}]]></programlisting>
|
||||
</para>
|
||||
|
||||
<para>The URL to use these parameters would then be changed to:
|
||||
|
||||
<programlisting><![CDATA[http://localhost:8080/people/?p=2&l=50]]></programlisting>
|
||||
</para>
|
||||
|
||||
<section>
|
||||
<title>Previous and Next Links</title>
|
||||
|
||||
<para>Each paged response will return links to the previous and next pages of results based on the current page.
|
||||
If
|
||||
you are currently at the first page of results, however, no "previous" link will be rendered. The same is true
|
||||
for
|
||||
the last page of results: no "next" link will be rendered if you are on the last page of results. The "rel"
|
||||
value
|
||||
of the link will end with ".next" for next links and ".prev" for previous links.
|
||||
|
||||
<programlisting><![CDATA[{
|
||||
"rel" : "people.next",
|
||||
"href" : "http://localhost:8080/people?page=2&limit=20"
|
||||
}]]></programlisting>
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Sorting</title>
|
||||
|
||||
<para>Spring Data REST also recognizes sorting parameters that will use the Repository sorting support.</para>
|
||||
|
||||
<para>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 specifying a URL parameter composed
|
||||
of the property name plus
|
||||
<code>.dir</code>
|
||||
and setting that value to either
|
||||
<code>asc</code>
|
||||
or<code>desc</code>. The following would use the
|
||||
<code>findByNameStartsWith</code>
|
||||
query method defined on the
|
||||
<classname>PersonRepository</classname>
|
||||
for all
|
||||
<classname>Person</classname>
|
||||
entities with names starting with the letter "K" and add sort data that orders the results on the name property in
|
||||
descending order:
|
||||
|
||||
<programlisting>
|
||||
<![CDATA[curl -v http://localhost:8080/people/search/nameStartsWith?name=K&sort=name&name.dir=desc]]></programlisting>
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
@@ -1,17 +1,110 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<chapter xml:id="representations-chapter"
|
||||
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.oasis-open.org/docbook/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>Domain Object Representations</title>
|
||||
|
||||
<section xml:id="links">
|
||||
<title>Links as First-Class Objects</title>
|
||||
|
||||
<para>
|
||||
|
||||
<para>Links are an essential part of RESTful resources and allow for easy discoverability of related resources. In
|
||||
Spring Data REST, a link is represented in JSON as an object with a
|
||||
<code>rel</code>
|
||||
and
|
||||
<code>href</code>
|
||||
property. These objects will appear in an array under an object's
|
||||
<code>links</code>
|
||||
property. These objects are meant to provide a user agent with the URLs necessary to retrieve resources related to
|
||||
the current resource being accessed.
|
||||
</para>
|
||||
|
||||
<para>When accessing the root of a Spring Data REST application, for example, links are provided to each repository
|
||||
that is exported. The user agent can then pick the link it is interested in and follow that<code>href</code>.
|
||||
Issue a
|
||||
<code>get</code>
|
||||
in the
|
||||
<code>rest-shell</code>
|
||||
to see an example of links.
|
||||
|
||||
<programlisting><![CDATA[
|
||||
http://localhost:8080:> get
|
||||
> GET http://localhost:8080/
|
||||
|
||||
< 200 OK
|
||||
< Content-Type: application/json
|
||||
<
|
||||
{
|
||||
"links" : [ {
|
||||
"rel" : "people",
|
||||
"href" : "http://localhost:8080/people"
|
||||
}, {
|
||||
"rel" : "profile",
|
||||
"href" : "http://localhost:8080/profile"
|
||||
}, {
|
||||
"rel" : "customer",
|
||||
"href" : "http://localhost:8080/customer"
|
||||
}, {
|
||||
"rel" : "order",
|
||||
"href" : "http://localhost:8080/order"
|
||||
}, {
|
||||
"rel" : "product",
|
||||
"href" : "http://localhost:8080/product"
|
||||
} ],
|
||||
"content" : [ ]
|
||||
}]]></programlisting>
|
||||
</para>
|
||||
|
||||
<section>
|
||||
<title>Entity Relationships</title>
|
||||
|
||||
<para>If two entities are related to one another through a database-defined relationship, then that relationship
|
||||
will appear in the JSON as a link. In JPA, one would place a
|
||||
<code>@ManyToOne</code>,
|
||||
<code>@OneToOne</code>, or other relationship annotation. If using Spring Data MongoDB, one would place a
|
||||
<code>@DBRef</code>
|
||||
annotation on a property to denote its special status as a reference to other entities. In the example project,
|
||||
the
|
||||
<classname>Person</classname>
|
||||
class has a related set of
|
||||
<classname>Person</classname>
|
||||
entities in the
|
||||
<code>siblings</code>
|
||||
property. If you
|
||||
<code>get</code>
|
||||
the resource of a
|
||||
<classname>Person</classname>
|
||||
you will see, in the
|
||||
<code>siblings</code>
|
||||
property, the link to follow to get the related
|
||||
<classname>Person</classname>s.
|
||||
|
||||
<programlisting><![CDATA[
|
||||
http://localhost:8080:> get people/1
|
||||
> GET http://localhost:8080/people/1
|
||||
|
||||
< 200 OK
|
||||
< Content-Type: application/json
|
||||
<
|
||||
{
|
||||
"firstName" : "Billy Bob",
|
||||
"surname" : "Thornton",
|
||||
"links" : [ {
|
||||
"rel" : "self",
|
||||
"href" : "http://localhost:8080/people/1"
|
||||
}, {
|
||||
"rel" : "people.person.father",
|
||||
"href" : "http://localhost:8080/people/1/father"
|
||||
}, {
|
||||
"rel" : "people.person.siblings",
|
||||
"href" : "http://localhost:8080/people/1/siblings"
|
||||
} ]
|
||||
}]]></programlisting>
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section xml:id="mapping">
|
||||
@@ -26,8 +119,107 @@
|
||||
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"><![CDATA[@Entity
|
||||
public class MyEntity {
|
||||
@OneToMany
|
||||
private List<MyInterface> 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"><![CDATA[
|
||||
@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"><![CDATA[
|
||||
@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>
|
||||
619
src/reference/docbook/rest-shell.xml
Normal file
619
src/reference/docbook/rest-shell.xml
Normal file
@@ -0,0 +1,619 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<chapter xml:id="intro-chapter"
|
||||
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.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>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>put</command>
|
||||
</cmdsynopsis>
|
||||
</td>
|
||||
<td>
|
||||
<para>HTTP PUT to the given path, passing JSON given in the --data parameter.</para>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<cmdsynopsis>
|
||||
<command>delete</command>
|
||||
</cmdsynopsis>
|
||||
</td>
|
||||
<td>
|
||||
<para>HTTP DELETE to the given path.</para>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<cmdsynopsis>
|
||||
<command>auth basic</command>
|
||||
</cmdsynopsis>
|
||||
</td>
|
||||
<td>
|
||||
<para>Set an HTTP Basic authentication token for use in this session.</para>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<cmdsynopsis>
|
||||
<command>auth clear</command>
|
||||
</cmdsynopsis>
|
||||
</td>
|
||||
<td>
|
||||
<para>Clear the Authorization header currently in use.</para>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<cmdsynopsis>
|
||||
<command>ssl validate</command>
|
||||
</cmdsynopsis>
|
||||
</td>
|
||||
<td>
|
||||
<para>Disable certificate checking to work with self-signed certificates.</para>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
28
src/reference/docbook/validation.xml
Normal file
28
src/reference/docbook/validation.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<?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://www.oasis-open.org/docbook/xml/5.0/xsd/docbook.xsd">
|
||||
|
||||
<title>Validation</title>
|
||||
|
||||
<para>Integrating validation into Spring Data REST is as easy as registering your
|
||||
<classname>Validator</classname>
|
||||
implementation with the
|
||||
<classname>ValidatingRepositoryEventListener</classname>, whose job it is to trigger
|
||||
validators whenever certain events happen inside Spring Data REST.
|
||||
</para>
|
||||
|
||||
<para>To add your validators, override the
|
||||
<code>configureValidatingRepositoryEventListener</code>
|
||||
method and call the
|
||||
<code>addValidator</code>
|
||||
method:
|
||||
|
||||
<programlisting language="java"><![CDATA[
|
||||
@Override protected void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener v) {
|
||||
v.addValidator("beforeSave", new BeforeSaveValidator());
|
||||
}]]></programlisting>
|
||||
</para>
|
||||
|
||||
</chapter>
|
||||
Reference in New Issue
Block a user