Review
In the previous section, we have updated our app's configuration, so that our repositories are exposed as RESTful endpoints. We've also applied the HATEOAS methodology which "serves to decouple client and server in a way that allows the server to evolve functionality independently" (Wikipedia). In this section, we will build and run the application using Maven, demonstrate how to import the project in Eclipse, and run a series of manual tests to examine the RESTful endpoints.Table of Contents
Part 1: Configuration- Update the pom.xml
- Update the web.xml
- Update Spring configurations
- Update the repositories
What is HATEOAS?
HATEOAS, an abbreviation for Hypermedia as the Engine of Application State, is a constraint of the REST application architecture that distinguishes it from most other network application architectures. The principle is that a client interacts with a network application entirely through hypermedia provided dynamically by application servers. A REST client needs no prior knowledge about how to interact with any particular application or server beyond a generic understanding of hypermedia. Contrast this with e.g. a service-oriented architecture (SOA), where clients and servers interact through a fixed interface shared through documentation or an interface description language (IDL).
The HATEOAS constraint serves to decouple client and server in a way that allows the server to evolve functionality independently.
Source: http://en.wikipedia.org/wiki/HATEOAS
Running the Application
Access the source code
To download the source code, please visit the project's Github repository (click here)Preparing the data source
- Run MySQL (install one if you don't have one yet)
- Create a new database:
spring_data_rest_tutorial
- Import the following file which is included in the source code under the src/main/resources folder:
spring_data_rest_tutorial.sql
Building with Maven
- Ensure Maven is installed
- Open a command window (Windows) or a terminal (Linux/Mac)
- Run the following command:
mvn tomcat:run
- You should see the following output:
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'tomcat'.
[INFO]
[INFO] --------------------------------------------------------------
[INFO] Building spring-data-rest-tutorial Maven Webapp 0.0.1-SNAPSHOT
[INFO] --------------------------------------------------------------
[INFO]
[INFO] Preparing tomcat:run
[INFO] [apt:process {execution: default}]
[INFO] [resources:resources {execution: default-resources}]
[INFO] [tomcat:run {execution: default-cli}]
[INFO] Running war on http://localhost:8080/spring-data-rest-tutorial
Nov 20, 2012 8:01:45 PM org.apache.catalina.startup.Embedded start
INFO: Starting tomcat server
Nov 20, 2012 8:01:45 PM org.apache.catalina.core.StandardEngine start
INFO: Starting Servlet Engine: Apache Tomcat/6.0.29
Nov 20, 2012 8:01:46 PM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring root WebApplicationContext
Nov 20, 2012 8:02:01 PM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring FrameworkServlet 'rest-exporter'
Nov 20, 2012 8:02:03 PM org.apache.coyote.http11.Http11Protocol init
INFO: Initializing Coyote HTTP/1.1 on http-8080
Nov 20, 2012 8:02:03 PM org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-8080 Note: If the project will not build due to missing repositories, please enable the repositories section in the pom.xml!
Access the grid page
This displays a grid that allows us to experiment with the data visually.- Follow the steps with Building with Maven
- Open a browser
- Enter the following URL (8080 is the default port for Tomcat):
http://localhost:8080/spring-data-rest-tutorial/
Access the RESTful entry endpoint
We've declared entry endpoint in spring-data-rest.xml and web.xml files.- Follow the steps with Building with Maven
- Open a browser
- Enter the following URL:
http://localhost:8080/spring-data-rest-tutorial/api/
This gives the following result:{
"links" : [ {
"rel" : "role",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/role"
}, {
"rel" : "user",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user"
} ],
"content" : [ ]
}
Access the User endpoint
- Enter the following URL:
http://localhost:8080/spring-data-rest-tutorial/api/user
This gives the following result:{
"links" : [ {
"rel" : "user.search",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/search"
} ],
"content" : [ {
"links" : [ {
"rel" : "self",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/1"
}, {
"rel" : "user.User.role",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/1/role"
} ],
"lastName" : "Smith",
"username" : "john",
"firstName" : "John",
"password" : "21232f297a57a5a743894a0e4a801fc3"
}, {
"links" : [ {
"rel" : "self",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/2"
}, {
"rel" : "user.User.role",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/2/role"
} ],
"lastName" : "Adams",
"username" : "jane",
"firstName" : "Jane",
"password" : "ee11cbb19052e40b07aac0ca060c23ee"
},
... (TRUNCATED)
... (TRUNCATED)
... (TRUNCATED)
{
"links" : [ {
"rel" : "self",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/13"
}, {
"rel" : "user.User.role",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/13/role"
} ],
"lastName" : "Zeigler",
"username" : "edward",
"firstName" : "Edward",
"password" : "mncmksk"
} ],
"page" : {
"size" : 20,
"totalElements" : 13,
"totalPages" : 1,
"number" : 1
}
}
Access the User endpoint with a limit
- Enter the following URL:
http://localhost:8080/spring-data-rest-tutorial/api/user?limit=2
This gives the following result:{
"links" : [ {
"rel" : "user.next",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user?page=2&limit=2"
}, {
"rel" : "user.search",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/search"
} ],
"content" : [ {
"links" : [ {
"rel" : "self",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/1"
}, {
"rel" : "user.User.role",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/1/role"
} ],
"lastName" : "Smith",
"username" : "john",
"firstName" : "John",
"password" : "21232f297a57a5a743894a0e4a801fc3"
}, {
"links" : [ {
"rel" : "self",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/2"
}, {
"rel" : "user.User.role",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/2/role"
} ],
"lastName" : "Adams",
"username" : "jane",
"firstName" : "Jane",
"password" : "ee11cbb19052e40b07aac0ca060c23ee"
} ],
"page" : {
"size" : 2,
"totalElements" : 12,
"totalPages" : 6,
"number" : 1
}
}
Notice the result also provided the endpoint for search and each person's record.
Let's do a search
- Open a browser
- Enter the following URL:
http://localhost:8080/spring-data-rest-tutorial/api/user/search
This gives the following result:{
"links" : [ {
"rel" : "user.findByFirstNameLike",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/search/findByFirstNameLike"
}, {
"rel" : "user.findByUsernameLike",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/search/findByUsernameLike"
}, {
"rel" : "user.findByFirstNameLikeAndLastNameLike",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/search/findByFirstNameLikeAndLastNameLike"
}, {
"rel" : "user.findByUsername",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/search/findByUsername"
}, {
"rel" : "user.findByLastNameLike",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/search/findByLastNameLike"
}, {
"rel" : "user.findByRole",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/search/findByRole"
} ],
"content" : [ ]
}
This exposes all the queries we declared in the UserRepository interface. - Let's try searching by username.
- Enter the following URL:
http://localhost:8080/spring-data-rest-tutorial/api/user/search/findByUsername?username=john
This gives the following result:{
"links" : [ ],
"content" : [ {
"links" : [ {
"rel" : "self",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/1"
}, {
"rel" : "user.User.role",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/1/role"
} ],
"lastName" : "Smith",
"username" : "john",
"firstName" : "John",
"password" : "21232f297a57a5a743894a0e4a801fc3"
} ]
}
Delete a record
You are required to have curl installed.- Open a command line.
- Enter the following command:
curl -v -X DELETE http://localhost:8080/spring-data-rest-tutorial/api/user/3
This gives the following output:If you check the records, notice that User with id 3 has been deleted.* About to connect() to localhost port 8080 (#0)
* Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 8080 (#0)
> DELETE /spring-data-rest-tutorial/api/user/3 HTTP/1.1
> User-Agent: curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8r zlib/1.2.3
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 204 No Content
< Server: Apache-Coyote/1.1
< Date: Mon, 19 Nov 2012 14:32:05 GMT
<
* Connection #0 to host localhost left intact
* Closing connection #0
Add a record
You are required to have curl installed.- Open a command line.
- Enter the following command:
curl -v -d '{"username":"homer", "firstName":"Homer", "lastName":"Simpson", "password":"12345678"}' -H "Content-Type: application/json" http://localhost:8080/spring-data-rest-tutorial/api/user
Under Windows use the following command instead:curl -v -d "{\"username\":\"homer\", \"firstName\":\"Homer\", \"lastName\":\"Simpson\", \"password\":\"12345678\"}" -H "Content-Type: application/json" http://localhost:8080/spring-data-rest-tutorial/api/user
This adds a User record and gives the following output:* About to connect() to localhost port 8080 (#0)
* Trying 127.0.0.1... connected
> POST /spring-data-rest-tutorial/api/user HTTP/1.1
> User-Agent: curl/7.22.0 (i386-pc-win32) libcurl/7.22.0 OpenSSL/1.0.0e zlib/1.2
.5
> Host: localhost:8080
> Accept: */*
> Content-Type: application/json
> Content-Length: 86
>
* upload completely sent off: 86out of 86 bytes
< HTTP/1.1 201 Created
< Server: Apache-Coyote/1.1
< Location: http://localhost:8080/spring-data-rest-tutorial/api/user/14
< Content-Type: application/octet-stream
< Content-Length: 0
< Date: Tue, 20 Nov 2012 04:58:56 GMT
<
* Connection #0 to host localhost left intact
* Closing connection #0 - However, a Role has not been associated with this User record. We have to manually create and associate one. Open a command line.
- Enter the following command:
curl -v -d '{"role":"1","user": {"rel": "user","href": "http://localhost:8080/spring-data-rest-tutorial/api/user/14"}}' -H "Content-Type: application/json" http://localhost:8080/spring-data-rest-tutorial/api/role
Under Windows use the following command instead:curl -v -d "{\"role\":\"1\",\"user\": {\"rel\": \"user\",\"href\": \"http://localhost:8080/spring-data-rest-tutorial/api/user/14\"}}" -H "Content-Type: application/json" http://localhost:8080/spring-data-rest-tutorial/api/role
This adds a Role record and gives the following output:* About to connect() to localhost port 8080 (#0)
* Trying 127.0.0.1... connected
> POST /spring-data-rest-tutorial/api/role HTTP/1.1
> User-Agent: curl/7.22.0 (i386-pc-win32) libcurl/7.22.0 OpenSSL/1.0.0e zlib/1.2
.5
> Host: localhost:8080
> Accept: */*
> Content-Type: application/json
> Content-Length: 106
>
* upload completely sent off: 106out of 106 bytes
< HTTP/1.1 201 Created
< Server: Apache-Coyote/1.1
< Location: http://localhost:8080/spring-data-rest-tutorial/api/role/14
< Content-Type: application/octet-stream
< Content-Length: 0
< Date: Tue, 20 Nov 2012 04:59:57 GMT
<
* Connection #0 to host localhost left intact
* Closing connection #0 - Examine the output and we should see the new record:
http://localhost:8080/spring-data-rest-tutorial/api/user/14
{
"links" : [ {
"rel" : "self",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/14"
}, {
"rel" : "user.User.role",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/14/role"
} ],
"lastName" : "Simpson",
"username" : "homer",
"firstName" : "Homer",
"password" : "12345678"
}
http://localhost:8080/spring-data-rest-tutorial/api/user/14/role
{
"links" : [ {
"rel" : "self",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/role/14"
}, {
"rel" : "role.Role.user",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/role/14/user"
}, {
"rel" : "user.User.role",
"href" : "http://localhost:8080/spring-data-rest-tutorial/api/user/14/role"
} ],
"role" : 1
} - Examine the grid and we shall see the new record as well:
Import the project in Eclipse
- Ensure Maven is installed
- Open a command window (Windows) or a terminal (Linux/Mac)
- Run the following command:
mvn eclipse:eclipse -Dwtpversion=2.0
- You should see the following output:
[INFO] Scanning for projects...
This command will add the following files to your project:
[INFO]
[INFO] --------------------------------------------------
[INFO] Building spring-data-rest-tutorial Maven Webapp 0.0.1-SNAPSHOT
[INFO] ---------------------------------------------------
[INFO]
[INFO] Adding support for WTP version 2.0.
[INFO]
[INFO] --------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] --------------------------------------------------.classpath
You may have to enable "show hidden files" in your file explorer to view them
.project
.settings
target - Open Eclipse and import the project
Conclusion
That's it! We've have successfully updated our Spring MVC application and exposed our repositories as RESTful endpoints using Spring Data Rest. We've also demonstrated how to access our application using pure hyperlinks with HATEOAS methodology.
I hope you've enjoyed this tutorial. Don't forget to check my other tutorials at the Tutorials section.
Revision History
Revision | Date | Description |
---|---|---|
1 | Nov 20 2012 | Uploaded tutorial and Github repository |
0 komentar:
Post a Comment