Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Creating a REST Web Service With Java and Spring (Part 4)

DZone's Guide to

Creating a REST Web Service With Java and Spring (Part 4)

We've come to the end, my friends. In this article, we show you how to get the application you've create running and consuming our web service.

· Java Zone
Free Resource

Get the Edge with a Professional Java IDE. 30-day free trial.

In part 1 of this series, we laid the groundwork for our web service by delving into the architecture and design of our web service, which we later developed into the domain and data source layers and the presentation layer in part 2 and part 3, respectively. With these layers complete, we can now move onto the deployment and testing of our web service.

Running and Consuming the Web Service

Since we are using Maven to manage the dependencies and build the lifecycle of our application, and Spring Boot to configure our application, we can build our project and start the HTTP server using the following command (once Maven has been installed):

mvn spring-boot:run

This will host the REST web service on http://localhost:8080. If we look closely at the output, we can see the following statements:

INFO 15204 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/order/{id}],methods=[PUT],produces=[application/json]}" onto public org.springframework.http.ResponseEntity<com.dzone.albanoj2.example.rest.resource.OrderResource> com.dzone.albanoj2.example.rest.controller.OrderController.updateOrder(java.lang.Long,com.dzone.albanoj2.example.rest.domain.Order)
INFO 15204 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/order],methods=[POST],produces=[application/json]}" onto public org.springframework.http.ResponseEntity<com.dzone.albanoj2.example.rest.resource.OrderResource> com.dzone.albanoj2.example.rest.controller.OrderController.createOrder(com.dzone.albanoj2.example.rest.domain.Order)
INFO 15204 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/order/{id}],methods=[GET],produces=[application/json]}" onto public org.springframework.http.ResponseEntity<com.dzone.albanoj2.example.rest.resource.OrderResource> com.dzone.albanoj2.example.rest.controller.OrderController.findOrderById(java.lang.Long)
INFO 15204 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/order],methods=[GET],produces=[application/json]}" onto public org.springframework.http.ResponseEntity<java.util.Collection<com.dzone.albanoj2.example.rest.resource.OrderResource>> com.dzone.albanoj2.example.rest.controller.OrderController.findAllOrders()
INFO 15204 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/order/{id}],methods=[DELETE],produces=[application/json]}" onto public org.springframework.http.ResponseEntity<java.lang.Void> com.dzone.albanoj2.example.rest.controller.OrderController.deleteOrder(java.lang.Long)

This output explicitly tells us that Spring has successfully found our controller class and has mapped the enumerated URLs to the respective methods of our OrderController class. With our web application started, we can retrieve the list of all existing orders by navigating tohttp://localhost:8080/order in any browser. When we enter this URL into a browser, the browser sends an HTTP GET to our web service, which in turn calls the findAllOrders() method of our OrderController class and returns a list of all orders, wrapped asOrderResource objects and displayed as serialized JSON. By default, the following should be returned when we navigate to http://localhost:8080/order:

[]

Since we have not created any orders yet, we see an empty list. In order to create an order, we must use an HTTP client program, such as Postman (for more information on how to use Postman to send HTTP requests, see the official Postman documentation). Using this client, we can create an order by setting the request type to POST, the request URL to http://localhost:8080/order, and the request body to the following:

{
    "description": "Our first test order",
    "costInCents": 450,
    "complete": false
}

After clicking the Send button, we should see a response status code of 201 Created and response body of the following:

{
    "description": "Our first test order",
    "costInCents": 450,
    "complete": false,
    "_links": {
        "self": {
            "href": "http://localhost:8080/order/1"
        },
        "update": {
            "href": "http://localhost:8080/order/1"
        },
        "delete": {
            "href": "http://localhost:8080/order/1"
        }
    },
    "id": 1
}

We can now navigate back to http://localhost:8080/order in our browser (or perform a GET on that address in Postman) and see the following response:

[
    {
        "description": "Our first test order",
        "costInCents": 450,
        "complete": false,
        "_links": {
            "self": {
                "href": "http://localhost:8080/order/1"
            },
            "update": {
                "href": "http://localhost:8080/order/1"
            },
            "delete": {
                "href": "http://localhost:8080/order/1"
            }
        },
        "id": 1
    }
]

This is simply a list containing our only order. If we wish to make an update to our existing order, we can simply execute a PUT to http://localhost:8080/order/1 (note the /1 at the end of the URL, denoting that we are directing our request to the order with ID 1) with the following request body:

{
    "description": "Some updated description",
    "costInCents": 700,
    "complete": true
}

If we then perform a GET on http://localhost:8080/order/1, we will see the following response:

{
    "description": "Some updated description",
    "costInCents": 700,
    "complete": true,
    "_links": {
        "self": {
            "href": "http://localhost:8080/order/1"
        },
        "update": {
            "href": "http://localhost:8080/order/1"
        },
        "delete": {
            "href": "http://localhost:8080/order/1"
        }
    },
    "id": 1
}

The last remaining task we can complete is to delete the order. To do this, simply execute a DELETE with the URL http://localhost:8080/order/1, which should return a response status code of 204 No Content. To check that we have successfully deleted the order, we can execute a GET on http://localhost:8080/order/1 and we should receive a response status code of 404 Not Found.

With the completion of this delete call, we have successfully exercised all of the CRUD operations that we implemented for orders in our REST web service. An enumeration of the calls we have made is tabulated below:

METHOD URL
GET
http://localhost:8080/order
POST

http://localhost:8080/order

PUT

http://localhost:8080/order/1

GET

http://localhost:8080/order/1

DELETE

http://localhost:8080/order/1

Conclusion

RESTful web services are at the core of most systems today. From Google to Amazon to Netflix, there is hardly a major software system that does not include some form of a RESTful web service that interacts with clients. At the origin of the REST revolution, creating these applications was a tedious task, but with the advent of frameworks such as Spring, and supplemental frameworks such as Spring Boot, this task has been tremendously simplified. With such tools, we are left to focus on the simple creation of a domain layer, persistence (data source) layer, presentation layer, and minimal configuration code to spin up a web service.

At the completion of this article, we have explored the main functionality contained in our order management RESTful web service, focusing on the design and thought process used to create both large and small REST services. Although there is much to learn in the Java and Spring REST ecosystem, we must start small and grow, and this tutorial serves as that starting point.

Get the Java IDE that understands code & makes developing enjoyable. Level up your code with IntelliJ IDEA. Download the free trial.

Topics:
web dev ,spring ,java 8 ,rest web service ,web application development

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}