Handling GET requests with Spring Rest

By Daniel Vladimirov / a few months ago

In this tutorial you’ll build a simple web application, or use the tutorial in an existing project, that handles GET HTTP requests with and without path variables.

Spring Boot

Check out this tutorial on how to setup a basic Spring Boot application if you need to


If you are familiar with how to set up a Spring Boot application and want to just get the base source code for this tutorial, you can do so from GitHub

Web Application Skeleton – Tomcat (GitHub)

GET is one of the HTTP methods defined in the Hypertext Transfer Protocol. GET methods are used to retrieve data in a client-server based communication.

The GET method, by convention, is one of the SAFE methods. This means that GET endpoints should never take any action other than retrieval of data. Of course this convention cannot be enforced, you can add as many side effects as you like to your application when processing GET requests, but this would only serve to confuse your clients and eventually turn into a huge security and business problem for you, so don’t do it.

GET is also considered idempotent. This means that it doesn’t matter how many times you or your clients do the same GET request, the application should always respond in the same way. In the case that there are side-effects – they must always be the same, no matter how many times the request was made.

There are some interesting properties for the GET method

  • GET requests can be cached
  • GET requests remain in the browser history
  • GET requests can be bookmarked
  • GET requests should never be used when dealing with sensitive data
  • GET requests have length restrictions

GET can be cached and there are HTTP headers dealing with this functionality. They can be bookmarked, so logically you don’t want your users to bookmark a GET endpoint of your application that for example modifies their account, or performs a real money transaction.

Ideally, a GET method should represent an entity, identified by the request URI (Uniform Resource Identificator), or if the URI represents a data producing process, the result of such process should be returned as the response entity.

Let’s see how you can easily create an application that handles GET requests.

What you’ll be building is a small web application that will return a list of personal contacts or a single contact, based on a path variable.

First, define a @RestController class in an appropriate package and name it ContactController.  Annotate it with @RestController and @RequestMapping annotations and put “/contact” as the value for the @RequestMapping annotation. This is the base path that our controller is going to serve.

@RestController
@RequestMapping(“/contact”)
public class ContactController
{

}

Next, you need to define an entity for our return object that will contain a single contact information. You’re not going to use a database for now, so we need to mock or predefine our entity objects. Since I’m always on for good code and application structure, we’re going to define them and later retrieve them from different layers of the application, so that the concerns are separated. Separation of concerns is a concept that allows for good level of testability for your application as well as easier refactoring and adding/switching different components. More on those concepts in other tutorials however. For now just remember that if you make this in a habit, it will become easier later on and the benefits are great. Also, your colleagues will love you.

So, define an entity class named Contact in an appropriate package, for example “model”.

We’ve declared the following attributes for our entity class

private String name;
private String phoneNumber;
private String city;
private String address;

and also added a constructor, which includes all of the attributes, and also getters and setters. You can pretty much auto-generate all of this boilerplate code in any IDE.

Usually, you will have a database connection at this point and a “repository” class, which will be responsible for querying and retrieving your entities. Since we’re not doing any database stuff at the moment, we need to pre-declare our entity objects somewhere – we are still going to create a class, a Spring component, that will serve as our entity repository. Usually, repositories also implement interfaces, i.e. their public contract, which other classes use, but we’ll skip this for now.

Create a new class in an appropriate package, for example “repository”, and name it ContactRepository. Annotate the class with @Repository. The @Repository annotation basically works the same as the @Component annotation, but has other benefits when working with DAOs and also exception handling, for now it will allow you to better set the class intent and separate your application in layers.

Next, define the entities. Since we’re going to request from the repository both a list of entities and a single entity at a time, we need a relatively simple way to store and return our objects. We’ll use a map.

The entities contain some random data that will serve to test the application later on. There are also two methods in this repository – one to return the list of entities and another to query for a specific entity. This will be our repository class.

Repository or DAO classes are usually called from the service layer, where your business logic resides.

Next, create a service class in an appropriate package, for example “service” and name it ContactService. This class will have the responsibility of using our repository class and apply any business logic that is required for our application. For the purposes of this tutorial, this might seem like an unnecessary complication, but it’s worth it in the long run if you separate your application logic properly, which will become obvious in other tutorials.

The @Service annotation has no benefits over the @Component annotation, but communicates the class intent better. We have two methods in our service class, which are basically the same as in the repository class. That’s not a requirement though, the service class can have any number of methods and call any number of repositories, apply different kinds of business logic and then return your data, for example, in the “getContact(…)” method, we’re preemptively checking if the passed parameter “name” is null or an empty string, so we don’t “query” the database for nothing.

The @Autowired annotation is telling Spring that our ContactService class needs a component of type ContactRepository, so Spring provides it for us.

The final step is to go back to our empty controller class and implement two GET handler methods.

The controller class has the service class autowired and basically uses its methods.

The getContacts() method has no specific path of its own, which means it’s going to use the controller class URI.

The getContact() method on the other hand has a path variable “name”, which is used to identify a resource – in this case one of our contact entities. The method returns a ResponseEntity object, because we want to control the return HTTP status code in case of an error or in case that no such entity exists. The same can be applied to the getContacts() method. In case we find an entity, the controller will return it along with an HTTP 200 OK response.

You can now start the application and test it.

Going to http://localhost:8080/contact produces the following JSON

Requesting a single contact, for example Maria http://localhost:8080/contact/Maria

And last, requesting a contact that doesn’t exist http://localhost:8080/contact/Michael produces a response with the HTTP status of 404 NOT FOUND, which can be checked in the developer tools of most browsers or in any other tool you might be using to make the requests. (Chrome – F12/Network tab).

Drop a comment if you need anything else explained or any feedback you might have.

Have fun learning!


About the author

Daniel Vladimirov

Software engineer and founder of simplyprogram.com

Click here to add a comment

Leave a comment: