What is REST?
Representational state transfer (REST) or RESTful web services is a way to provide interoperability between computer systems on the Internet.
It is an architectural style for building distributed systems (defined by Roy Fielding in 2000), with six main constraints:

-
Uniform Interface - Keeping Things Consistent
- Resource identification through URIs (e.g.,/users/123, /orders)
- Manipulation of resources through representations (usually JSON today)
- Self-descriptive messages (HTTP headers tell you content-type, status, caching rules…)
- HATEOAS (Hypermedia as the Engine of Application State — optional, rarely used in practice)
- Client–Server - Separation of Responsibilities
- Stateless communication - Every Request Stands Alone
- Cacheable - Speeding Things Up
- Layered system - Scalability & Security
- Code on demand - allows the server to send executable code(I have never used)
Here is a sample retail pet store project in SpringBoot, an imaginary pet store that currently sells pet fish, Aqua World.
Core REST Concepts
1. Resources and URIs (Uniform Resource Identifier)
In REST, everything is a resource — think of it as a noun (something that can be created, read, updated, deleted).
Example URI in AquaWorld App:
2. HTTP Methods & Status Codes
REST uses standard HTTP methods to express what we want to do with a resource.
| Method | Meaning | Idempotent? | Common Status Codes | Typical Use Case |
|---|---|---|---|---|
| GET | Retrieve resource(s) | Yes | 200 OK | Read data |
| HEAD | Same as GET but no body | Yes | 200 OK | Check existence/metadata |
| POST | Create new resource | No | 201 Created | Create user, submit form, place order |
| PUT | Replace entire resource | Yes | 200 OK | Update/replace whole user profile |
| PATCH | Partially update resource | Usually | 200 OK | Change only email or status |
| DELETE | Remove resource | Yes | 204 No Content | Delete user or order |
Note:
- Safe methods: GET, HEAD — can be called any number of times without changing server state
- Idempotent methods: GET, HEAD, PUT, DELETE — repeating the same request multiple times has the same effect as doing it once
POST is neither safe nor (strictly) idempotent — that's why it's used for creation
Common status codes everyone should know:
- 200 OK → success (with body)
- 201 Created → resource created successfully
- 204 No Content → success, but no response body (common for DELETE/PUT)
- 400 Bad Request → client sent invalid data
- 401 Unauthorized → authentication required
- 403 Forbidden → authenticated but not allowed
- 404 Not Found → resource doesn't exist
- 409 Conflict → resource conflict
- 500 Internal Server Error → something broke on the server side
- 503 Service Unavailable → service temporarily down
3. Representations & Content Negotiation
A resource can be represented in different formats.
Most common today:
JSON → application/json (the default in 2025–2026)
XML → application/xml (still used in enterprise, SOAP legacy)
Content Negotiation — how client and server agree on format:
Client tells server what it accepts via Accept header:
Accept: application/json, application/xml;q=0.9, */*;q=0.1
Server responds with Content-Type:
Content-Type: application/json
Java Example
Steps to create a sample project:
1. Create a Spring Boot project
Use Spring initializer to create a sample project.
Project: Maven
Language: Java
Spring Boot: 3.3.x (Latest)
Java: 21
Dependencies:
- Spring Web (spring-boot-starter-web)
- Lombok (optional, for reducing boilerplate)
2. Maven Dependencies (pom.xml)
<dependencies>
<!-- Spring Web for REST APIs -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Lombok for @Data annotation (optional) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
3. Application Properties
pring.application.name=book-api
server.port=8080
server.servlet.context-path=/api
# Logging
logging.level.root=INFO
logging.level.com.example=DEBUG
4. Building controller
The Controller handles HTTP requests and returns responses.
In Spring Boot, we use annotations to build REST APIs. Some commonly needed Annotations:
| Annotation | Purpose |
|---|---|
| @RestController | Marks the class as a REST API controller and returns JSON responses |
| @RequestMapping("/books") | Base path for all endpoints in this controller |
| @GetMapping | Maps HTTP GET requests |
| @PostMapping | Maps HTTP POST requests |
| @PutMapping | Maps HTTP PUT requests |
| @DeleteMapping | Maps HTTP DELETE requests |
| @PathVariable | Extracts values from the URL path (e.g., {id}) |
| @RequestBody | Binds JSON request body to a Java object |
Project Aquaworld
You can clone the Aqua World project and follow the steps to run the application.
Use IntelliJ IDEA or your favourite IDE to run the application.
Or run these commands in the terminal
mvn clean install
mvn start
Check out Swagger UI to run all the endpoints.

REST Design Tips
Noun-based URIs, plural collections, predictable patterns
- Always use nouns for resources (not verbs):
Good: /users, /orders/123
Bad: /getUser, /createOrder
Use plural for collections: /users, /products (not /user or /usersList)
Keep patterns predictable & consistent:
/resource → collection
/resource/{id} → single item
/resource/{id}/sub-resource → nested (e.g. /users/123/orders)Avoid deep nesting (>2–3 levels)
Use query params or references instead
Use proper status codes & error payloads
- Never return a generic 200 OK with an error message in the body — it's misleading Refer codes above.
- Prefer RFC 9457application/problem+json for errors (modern standard):
JSON{
"type": "https://example.com/errors/validation",
"title": "Validation Failed",
"status": 400,
"detail": "Email is already in use",
"instance": "/users",
"invalidParams": [ ... ]
}
- Much better than plain
{ "error": "something went wrong" }
Basic versioning strategies
-
Two main approaches:
- URL versioning (most common & beginner-friendly)
/v1/users, /v2/usersEasy to read, cache, and route in the gateway. - Header versioning (more RESTful)
Accept: application/vnd.myapi.v2+jsonCleaner URLs, but harder for humans & some clients
- URL versioning (most common & beginner-friendly)
-
Avoid versioning every minor change
- Only version when you break backward compatibility (breaking changes, removing fields, changing semantics)
- Minor additions (new optional fields) → no new version needed
- Semantic Versioning rule: major version bump only for breaking changes
Testing and Tooling for REST APIs
Unit/Integration tests (Spring ecosystem)
- @WebMvcTest — lightweight, fast unit test for controllers only Mocks the service layer Example
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired MockMvc mockMvc;
@Test
void shouldReturnUser() throws Exception {
mockMvc.perform(get("/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("John"));
}
}
- MockMvc → simulate HTTP requests without starting a full server
- Use TestRestTemplate or WebTestClient for full integration tests
Contract tests
Goal: Ensure provider (API) & consumer (client) agree on contract
Popular tools:
- Spring Cloud Contract
- Producer generates stubs + contract tests
- Consumer uses stubs for testing
- OpenAPI/Swagger driven (most common in 2025–2026)
- Generate OpenAPI spec → use it for:
- Validation (springdoc + openapi-validator)
- Client codegen (openapi-generator)
- Contract testing (e.g. Dredd, Schemathesis, REST assured + OpenAPI)




Top comments (2)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.