Accessing MongoDB over REST

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.

Getting ready

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.

How to do it…

  1. If you have imported the project in your IDE as a Maven project, execute the com.packtpub.mongo.cookbook.rest.RestServer class, which is the bootstrap class, and locally start the server that will accept client connections.
  2. If the project is to be executed from the command prompt as a Maven project, go to the root directory of the project and run the following command:
    mvn spring-boot:run
    
  3. The following output will be seen in the command prompt if all goes well and the server is started:
    [INFO] Attaching agents: []
    
  4. After starting the server in either way, enter 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
      }
    }
    
  5. We will now insert a new document in the 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

  6. The following screenshot shows the POST request sent to the server and the response from the server:
    How to do it…
  7. We will now query this document from the browser using the _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.
  8. Now that we have one document in the collection (you might try to insert more documents for people with different names and, more importantly, a unique ID), we will query the document using the last name. However, first type in 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.
  9. To search by the last name, Cruise in our case, enter http://localhost:8080/people/search/findByLastName?lastName=Cruise in the browser's address bar.
  10. We will now update the last name and age of the person with ID 1; Tom Cruise it is for now. Let's update the last name to 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:
    How to do it…
  11. To validate whether our update went through successfully or not (we know it did as we got a response status 204 after the PATCH request), enter http://localhost:8080/people/1 again in the browser's address bar.
  12. Finally, we will delete the document. This is straightforward, and we will simply send a 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.

How it works…

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.

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset