In this recipe, we will see how to access MongoDB and perform CRUD operations using REST APIs. We will use spring-data-rest
for REST access and spring-data-mongodb
to perform the CRUD operations. Before you continue with this recipe, it is important to know how to implement CRUD repositories using spring-data-mongodb
. Refer to the Developing using spring-data-mongodb recipe to know how to use this framework.
The question that one must have is, why a REST API is needed? There are scenarios where there is a database that is being shared by many applications, possibly written in different languages. Writing JPA DAO or using spring-data-mongodb
is good enough for Java clients, but not for clients in other languages. Having APIs locally with the application doesn't even give us a centralized way to access the database. This is where REST APIs come into play. We can develop the server-side data access layer, which is the CRUD repository in Java (spring-data-mongodb
to be precise), and then expose it over a REST interface for a client written in any language to invoke it. Now, we will invoke our API in a platform-independent way and this will also give us a single point of entry into our database.
Apart from the prerequisites of the Developing using spring-data-mongodb recipe, we have a few more for this recipe. The first thing is to download the SpringDataRestTest
project from the book's website and import it into your IDE as a Maven project. Alternatively, if you do not wish to import into the IDE, you can run the server that services the requests from the command prompt, which we will see in the next section. There is no specific client application used to perform the CRUD operations over REST. I will demonstrate the concepts using the Chrome browser and use a special plugin of the browser called Advanced REST Client to send HTTP POST requests to the server. The tools can be found under the Developer Tools section on the Chrome web store.
com.packtpub.mongo.cookbook.rest.RestServer
class, which is the bootstrap class, and locally start the server that will accept client connections.mvn spring-boot:run
[INFO] Attaching agents: []
http://localhost:8080/people
in the browser's address bar, and we will see the following JSON response. The following response is seen because the underlying collection, person
, is empty:{ "_links" : { "self" : { "href" : "http://localhost:8080/people{?page,size,sort}", "templated" : true }, "search" : { "href" : "http://localhost:8080/people/search" } }, "page" : { "size" : 20, "totalElements" : 0, "totalPages" : 0, "number" : 0 } }
person
collection using the HTTP POST
request to http://localhost:8080/people
. We will send a POST
request to the server using the Advanced REST Client chrome extension. The document posted is as follows:{"lastName":"Cruise", "firstName":"Tom", "age":52, "id":1}
The request's content type is application/json
POST
request sent to the server and the response from the server:_id
field, which is 1
in this case. Enter http://localhost:8080/people/1
in the browser's address bar. You will see the document we inserted in step 5.http://localhost:8080/people/search
in the browser's address bar to view all the search options available. We will see one search method, findByLastName
, that accepts a command-line parameter, lastName
.Cruise
in our case, enter http://localhost:8080/people/search/findByLastName?lastName=Cruise
in the browser's address bar.Hanks
and age to 58
. To do this, we will use the HTTP PATCH
request, and the request will be sent to http://localhost:8080/people/1
, which uniquely identifies the document to update. The body of the HTTP PATCH
request is {"lastName":"Hanks", "age":58}
. Refer to the following screenshot for the request we sent out for update:PATCH
request), enter http://localhost:8080/people/1
again in the browser's address bar.DELETE
request to http://localhost:8080/people/1
. Once the DELETE
request is successful, send an HTTP GET request from the browser to http://localhost:8080/people/1
, and we will not get any document in return.We will not be reiterating the spring-data-mongodb
concepts in this recipe, but we will look at some of the annotations we added specifically for the REST interface to the repository class. The first one is on top of the class name as follows:
@RepositoryRestResource(path="people") public interface PersonRepository extends PagingAndSortingRepository<Person, Integer> {
This is used to instruct the server that this CRUD repository can be accessed using the people
resource. This is the reason why we always make HTTP GET
and POST
requests on http://localhost:8080/people/
.
The second annotation is in the findByLastName
method. We have the following method signature:
Person findByLastName(@Param("lastName") String lastName);
Here, the lastName
method parameter is annotated with the @Param
annotation, which is used to annotate the name of the parameter that will have the value of the lastName
parameter that will be passed while invoking this method on the repository. If we look at step 9 in the previous section, we will see that findByLastName
is invoked using an HTTP GET
request, and the value of the URL parameter, lastName
, is used as the string value passed while invoking the repository method.
Our example here is pretty simple with just one parameter used for the search operation. We can have multiple parameters for the repository method and, accordingly, an equal number of parameters in the HTTP request, which will be mapped to these parameters for the method to be invoked on the CRUD repository. For some data type such as dates to be sent out, use the @DateTimeFormat
annotation, which will be used to specify the date and time format. For more information on this annotation and its usage, refer to the Spring Javadoc at http://docs.spring.io/spring/docs/current/javadoc-api/.
That was all about the GET
request we make to the REST interface to query and search data. Initially, we created document data sending an HTTP POST
request to the server. To create new documents, we will always send a POST
request with the document to be created as a body of the request to the URL that identifies the REST endpoint, in our case, http://localhost:8080/people/
. All documents posted to this collection will make use of PersonRepository
to persist a person in the corresponding collection.
Our final three steps were to update and delete the person. The HTTP request types to perform these operations are PATCH
and DELETE
, respectively. In step 10, we updated the document for the person, Tom Cruise, and updated his last name and age. To achieve this, our PATCH
request was sent to a URL http://localhost:8080/people/1
; this URL identifies a specific person instance. Note that, when we wanted to create a new person, our POST
request was always sent to http://localhost:8080/people
as against the PATCH
and DELETE
requests, where we sent the HTTP request to a URL that represents the specific person we want to update or delete. In the case of update, the body of the PATCH
request is a JSON document whose provided fields will replace the corresponding fields in the target document to update. All the other fields will be left as they are. In our case, lastName
and age
of the target document were updated, and firstName
was left untouched. In the case of delete, the message body was not empty, and the DELETE
request itself instructs that the target to which the request was sent should be deleted.
You might also send a PUT
request instead of PATCH
to a URL that identifies a specific person; in this case, the entire document in the collection will get updated or replaced with the document provided as part of the PUT
request.
spring-data-rest
home page at http://projects.spring.io/spring-data-rest/, where you can find links to its Git repository, reference manual, and Javadoc URLs