REST isn't just a trendy buzzword developers like to throw around. It's an architectural style that's a great fit for microservice systems because of its simplicity, flexibility, and scalability. Let's break down why.
- Ease of integration: REST uses the HTTP protocol, which is supported by all modern programming languages, so you can interact with microservices from any platform.
- Separation of concerns: a REST application separates client and server, which makes managing code easier.
- Scalability: you can scale microservices based on business needs, and the REST API remains a flexible way to exchange data.
- Caching: REST supports response caching, which reduces load on the server.
So REST is great for building microservices. But how do you design and implement it? Let's dive into the details.
Basics of REST APIs in Microservices
REST (Representational State Transfer) is an architectural style that uses standard HTTP methods (GET, POST, PUT, DELETE) to work with resources.
In a microservice architecture each service usually exposes a REST API to interact with other system components.
Example REST API for the "Order Management" microservice
Imagine we're designing an order management system. We'll have an Order Service that exposes a REST API to create, retrieve, update, and delete orders.
Example resources for our service:
GET /orders: retrieve the list of orders.GET /orders/{id}: retrieve information about a specific order.POST /orders: create a new order.PUT /orders/{id}: update an existing order.DELETE /orders/{id}: delete an order.
Spring annotations for REST API
Spring Boot makes building REST APIs easier thanks to a set of handy annotations:
@RestController: combines@Controllerand@ResponseBody. Indicates that this class will expose a REST API.@RequestMapping: used to set the path and request method (for example,GET,POST,PUT,DELETE).@GetMapping: simplified version of@RequestMappingfor HTTP GET.@PostMapping: for HTTP POST.@PutMapping: for HTTP PUT.@DeleteMapping: for HTTP DELETE.@PathVariable: extracts variables from the URI.@RequestParam: extracts parameters from the query string.@RequestBody: converts JSON from the request body into a Java object.
Implementing a REST API in practice
Let's build a simple REST API for managing orders.
- Create the
Orderentity:// Class describing an order @Data @AllArgsConstructor @NoArgsConstructor public class Order { private Long id; private String description; private Double totalAmount; } - Implement the
OrderControllercontroller:@RestController @RequestMapping("/orders") // Base URI for all methods public class OrderController { private List<Order> orders = new ArrayList<>(); @GetMapping public List<Order> getAllOrders() { return orders; } @GetMapping("/{id}") public Order getOrderById(@PathVariable Long id) { return orders.stream() .filter(order -> order.getId().equals(id)) .findFirst() .orElseThrow(() -> new RuntimeException("Order not found")); } @PostMapping public Order createOrder(@RequestBody Order order) { orders.add(order); return order; } @PutMapping("/{id}") public Order updateOrder(@PathVariable Long id, @RequestBody Order updatedOrder) { Order existingOrder = getOrderById(id); existingOrder.setDescription(updatedOrder.getDescription()); existingOrder.setTotalAmount(updatedOrder.getTotalAmount()); return existingOrder; } @DeleteMapping("/{id}") public String deleteOrder(@PathVariable Long id) { Order order = getOrderById(id); orders.remove(order); return "Order deleted successfully!"; } } - Testing the API: Now we have full CRUD for orders. You can test it using tools like Postman or curl:
- Create an order:
POST /orderswith JSON in the body ({"id":1, "description":"New Order", "totalAmount":100.0}). - Get all orders:
GET /orders. - Get an order by ID:
GET /orders/1. - Update an order:
PUT /orders/1with the updated JSON. - Delete an order:
DELETE /orders/1.
- Create an order:
Tips for designing REST APIs
How to choose URIs?
- Use nouns in URIs: instead of
/getAllOrdersuse/orders. - Use plural for resources:
/orders, not/order. - For nested resources follow the hierarchy:
/orders/{orderId}/items.
Response formatting
- Return useful HTTP codes:
201 Createdfor creation,404 Not Foundfor a missing resource. - Use JSON as the standard response format (well supported across languages).
Data validation
- Use the
@Validannotation for automatic validation. - For example:
@PostMapping public Order createOrder(@Valid @RequestBody Order order) { orders.add(order); return order; }
Error handling
Create a centralized error handler using @ControllerAdvice. Example:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> handleRuntimeException(RuntimeException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage());
}
}
REST API security
Although security is covered in detail in other lectures, a few key points:
- never send sensitive data (like passwords) in the URI.
- implement authentication and authorization (see Spring Security).
- use HTTPS to encrypt data.
Next steps
We've covered how to create REST APIs and work with them in a microservice system using Spring Boot. In the next lecture we'll dive into a hands-on example and implement a full REST API microservice, including connecting to a database, running migrations, and testing all operations. In the meantime, try building your own REST APIs for other entities — for example, products, users, or transactions.
GO TO FULL VERSION