1. Overview
In this article, we’ll have a look at Spring REST Shell and some of its features.
It’s a Spring Shell extension so we recommend reading about it first.
2. Introduction
The Spring REST Shell is a command-line shell designed to facilitate working with Spring HATEOAS-compliant REST resources.
We no longer need to manipulate the URLs in bash by using tools like curl. Spring REST Shell provides a more convenient way of interacting with REST resources.
3. Installation
If we’re using a macOS machine with Homebrew, we can simply execute the next command:
brew install rest-shell
For users of other operating systems, we need to download a binary package from the official GitHub project page, unpack the package and find an executable to run:
tar -zxvf rest-shell-1.2.0.RELEASE.tar.gz
cd rest-shell-1.2.0.RELEASE
bin/rest-shell
Another option is to download the source code and perform a Gradle task:
git clone git://github.com/spring-projects/rest-shell.git
cd rest-shell
./gradlew installApp
cd build/install/rest-shell-1.2.0.RELEASE
bin/rest-shell
If everything is set correctly, we’ll see the following greeting:
___ ___ __ _____ __ _ _ _ _ __
| _ \ __/' _/_ _/' _/| || | / / | \ \
| v / _|`._`. | | `._`.| >< | / / / > >
|_|_\___|___/ |_| |___/|_||_| |_/_/ /_/
1.2.1.RELEASE
Welcome to the REST shell. For assistance hit TAB or type "help".
http://localhost:8080:>
4. Getting Started
We’ll be working with the API already developed for another article. The localhost:8080 is used as a base URL.
Here’s a list of exposed endpoints:
- GET /articles – get all Articles
- GET /articles/{id} – get an Article by id
- GET /articles/search/findByTitle?title={title} – get an Article by title
- GET /profile/articles – get the profile data for an Article resource
- POST /articles – create a new Article with a body provided
The Article class has three fields: id, title, and content.
4.1. Creating New Resources
Let’s add a new article. We’re going to use the post command passing a JSON String with the –data parameter.
First, we need to follow the URL associated with the resource we want to add. The command follow takes a relative URI, concatenates it with the baseUri and sets the result as the current location:
http://localhost:8080:> follow articles
http://localhost:8080/articles:> post --data "{title: "First Article"}"
The result of the execution of the command will be:
< 201 CREATED
< Location: http://localhost:8080/articles/1
< Content-Type: application/hal+json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 29 Oct 2017 23:04:43 GMT
<
{
"title" : "First Article",
"content" : null,
"_links" : {
"self" : {
"href" : "http://localhost:8080/articles/1"
},
"article" : {
"href" : "http://localhost:8080/articles/1"
}
}
}
4.2. Discovering Resources
Now, when we’ve got some resources, let’s find them out. We’re going use the discover command which reveals all available resources at the current URI:
http://localhost:8080/articles:> discover
rel href
=================================================
self http://localhost:8080/articles/
profile http://localhost:8080/profile/articles
article http://localhost:8080/articles/1
Being aware of the resource URI, we can fetch it by using the get command:
http://localhost:8080/articles:> get 1
> GET http://localhost:8080/articles/1
< 200 OK
< Content-Type: application/hal+json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 29 Oct 2017 23:25:36 GMT
<
{
"title" : "First Article",
"content" : null,
"_links" : {
"self" : {
"href" : "http://localhost:8080/articles/1"
},
"article" : {
"href" : "http://localhost:8080/articles/1"
}
}
}
4.3. Adding Query Parameters
We can specify query parameters as JSON fragments using the –params parameter.
Let’s get an article by the given title:
http://localhost:8080/articles:> get search/findByTitle \
> --params "{title: "First Article"}"
> GET http://localhost:8080/articles/search/findByTitle?title=First+Article
< 200 OK
< Content-Type: application/hal+json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 29 Oct 2017 23:39:39 GMT
<
{
"title" : "First Article",
"content" : null,
"_links" : {
"self" : {
"href" : "http://localhost:8080/articles/1"
},
"article" : {
"href" : "http://localhost:8080/articles/1"
}
}
}
4.4. Setting Headers
The command called headers allows managing headers within the session scope – every request will be sent using these headers. The headers set takes the –name and –value arguments to determine a header.
We are going to add a few headers and make a request including those headers:
http://localhost:8080/articles:>
headers set --name Accept --value application/json
{
"Accept" : "application/json"
}
http://localhost:8080/articles:>
headers set --name Content-Type --value application/json
{
"Accept" : "application/json",
"Content-Type" : "application/json"
}
http://localhost:8080/articles:> get 1
> GET http://localhost:8080/articles/1
> Accept: application/json
> Content-Type: application/json
4.5. Writing Results to a File
It’s not always desirable to print out the results of an HTTP request to the screen. Sometimes, we need to save the results in a file for further analysis.
The –output parameter allows performing such operations:
http://localhost:8080/articles:> get search/findByTitle \
> --params "{title: "First Article"}" \
> --output first_article.txt
>> first_article.txt
4.6. Reading JSON From a File
Often, JSON data is too large or too complex to be entered through the console using the –data parameter.
Also, there are some limitations on the format of the JSON data we can enter directly into the command line.
The –from parameter gives the possibility of reading data from a file or a directory.
If the value is a directory, the shell will read each file that ends with “.json” and perform a POST or PUT with the content of that file.
If the parameter is a file, then the shell will load the file and POST/PUT data from that file.
Let’s create the next article from the file second_article.txt:
http://localhost:8080/articles:> post --from second_article.txt
1 files uploaded to the server using POST
4.7. Setting Context Variables
We can also define variables within the current session context. The command var defines the get and set parameters for getting and setting a variable respectively.
By analogy with the headers, the arguments –name and –value are for giving the name and the value of a new variable:
http://localhost:8080:> var set --name articlesURI --value articles
http://localhost:8080/articles:> var get --name articlesURI
articles
Now, we’re going to print out a list of currently available variables within the context:
http://localhost:8080:> var list
{
"articlesURI" : "articles"
}
Having made sure that our variable was saved, we’ll use it with the follow command to switch to the given URI:
http://localhost:8080:> follow #{articlesURI}
http://localhost:8080/articles:>
4.8. Viewing History
All the paths we visit are recorded. The command history shows these paths in the chronological order:
http://localhost:8080:> history list
1: http://localhost:8080/articles
2: http://localhost:8080
Each URI is associated with a number that can be used to go to that URI:
http://localhost:8080:> history go 1
http://localhost:8080/articles:>
5. Conclusion
In this tutorial, we’ve focused on an interesting and rare tool in the Spring ecosystem – a command line tool.
You can find more information about the project over on GitHub.
And, as always, all the code snippets mentioned in the article can be found in our repository.