DEV Community

Er. Bhupendra
Er. Bhupendra

Posted on

CONTROLLER ALL CONCEPT IN SPRINGBOOT PROJECT

ResponseEntity - Complete Methods & Features List

πŸ“‹ Status Code Methods

βœ… Success Responses (2xx)

ResponseEntity.ok()                              // 200 OK
ResponseEntity.ok(body)                          // 200 OK with body
ResponseEntity.ok().build()                      // 200 OK without body
ResponseEntity.status(HttpStatus.OK).body(data)  // 200 explicit

ResponseEntity.created(location)                 // 201 CREATED
ResponseEntity.created(location).body(data)      // 201 with body
ResponseEntity.status(HttpStatus.CREATED).body(data)

ResponseEntity.accepted()                        // 202 ACCEPTED
ResponseEntity.accepted().body(data)             // 202 with body

ResponseEntity.noContent()                       // 204 NO CONTENT
ResponseEntity.noContent().build()               // 204 (common for DELETE)
Enter fullscreen mode Exit fullscreen mode

❌ Client Error Responses (4xx)

ResponseEntity.badRequest()                      // 400 BAD REQUEST
ResponseEntity.badRequest().body(error)          // 400 with error

ResponseEntity.status(HttpStatus.UNAUTHORIZED)   // 401 UNAUTHORIZED
ResponseEntity.status(401).body(error)           // 401 with message

ResponseEntity.status(HttpStatus.FORBIDDEN)      // 403 FORBIDDEN
ResponseEntity.status(403).body(error)           // 403 with message

ResponseEntity.notFound()                        // 404 NOT FOUND
ResponseEntity.notFound().build()                // 404 (most common)

ResponseEntity.status(HttpStatus.METHOD_NOT_ALLOWED)  // 405
ResponseEntity.status(HttpStatus.CONFLICT)       // 409 CONFLICT
ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY) // 422
ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS)    // 429
Enter fullscreen mode Exit fullscreen mode

πŸ”΄ Server Error Responses (5xx)

ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) // 500
ResponseEntity.status(500).body(error)           // 500 with error

ResponseEntity.status(HttpStatus.BAD_GATEWAY)    // 502
ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE) // 503
ResponseEntity.status(HttpStatus.GATEWAY_TIMEOUT) // 504
Enter fullscreen mode Exit fullscreen mode

πŸ”€ Redirection Responses (3xx)

ResponseEntity.status(HttpStatus.MOVED_PERMANENTLY)  // 301
    .location(newUri).build()

ResponseEntity.status(HttpStatus.FOUND)          // 302
    .location(uri).build()

ResponseEntity.status(HttpStatus.NOT_MODIFIED)   // 304
Enter fullscreen mode Exit fullscreen mode

🎯 Builder Methods

Basic Building

ResponseEntity.status(statusCode)                // Set status code
ResponseEntity.status(HttpStatus.OK)             // Using enum
.body(data)                                      // Set response body
.build()                                         // Build without body
Enter fullscreen mode Exit fullscreen mode

Headers

.header(name, value)                             // Single header
.headers(HttpHeaders)                            // Multiple headers
.contentType(MediaType)                          // Content-Type header
.location(URI)                                   // Location header
.allow(HttpMethod...)                            // Allowed methods
Enter fullscreen mode Exit fullscreen mode

Caching

.cacheControl(CacheControl)                      // Cache control
.cacheControl(CacheControl.maxAge(60, TimeUnit.SECONDS))
.cacheControl(CacheControl.noCache())
.cacheControl(CacheControl.noStore())

.eTag(String)                                    // ETag header
.eTag("version-123")

.lastModified(long)                              // Last-Modified
.lastModified(ZonedDateTime)
.lastModified(Instant)
Enter fullscreen mode Exit fullscreen mode

Content

.contentLength(long)                             // Content-Length
.accept(MediaType...)                            // Accept header
.acceptCharset(Charset...)                       // Accept-Charset
.varyBy(String...)                               // Vary header
Enter fullscreen mode Exit fullscreen mode

πŸ“¦ Generic Types

ResponseEntity<String>                           // String response
ResponseEntity<User>                             // Single object
ResponseEntity<List<User>>                       // List
ResponseEntity<Page<User>>                       // Paginated
ResponseEntity<Map<String, Object>>              // Map
ResponseEntity<ApiResponse<User>>                // Wrapper
ResponseEntity<byte[]>                           // Binary data
ResponseEntity<Resource>                         // File/Resource
ResponseEntity<Void>                             // No body
ResponseEntity<?>                                // Wildcard
Enter fullscreen mode Exit fullscreen mode

πŸ”§ Content-Type Options

.contentType(MediaType.APPLICATION_JSON)         // JSON
.contentType(MediaType.APPLICATION_XML)          // XML
.contentType(MediaType.TEXT_PLAIN)               // Plain text
.contentType(MediaType.TEXT_HTML)                // HTML
.contentType(MediaType.APPLICATION_PDF)          // PDF
.contentType(MediaType.IMAGE_PNG)                // PNG image
.contentType(MediaType.IMAGE_JPEG)               // JPEG image
.contentType(MediaType.APPLICATION_OCTET_STREAM) // Binary
.contentType(MediaType.MULTIPART_FORM_DATA)      // Form data
.contentType(MediaType.parseMediaType("text/csv")) // CSV
.contentType(MediaType.parseMediaType(
    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
))                                               // Excel
Enter fullscreen mode Exit fullscreen mode

πŸ“₯ File Download Headers

// Download as attachment
.header(HttpHeaders.CONTENT_DISPOSITION, 
        "attachment; filename=\"file.pdf\"")

// Display inline (PDF in browser)
.header(HttpHeaders.CONTENT_DISPOSITION,
        "inline; filename=\"document.pdf\"")

// Content length
.header(HttpHeaders.CONTENT_LENGTH, "12345")

// Complete file download
ResponseEntity.ok()
    .contentType(MediaType.APPLICATION_OCTET_STREAM)
    .header(HttpHeaders.CONTENT_DISPOSITION, 
            "attachment; filename=\"report.pdf\"")
    .body(fileBytes)
Enter fullscreen mode Exit fullscreen mode

🌐 CORS Headers

.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Origin", "https://example.com")
.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE")
.header("Access-Control-Allow-Headers", "Content-Type, Authorization")
.header("Access-Control-Allow-Credentials", "true")
.header("Access-Control-Max-Age", "3600")
Enter fullscreen mode Exit fullscreen mode

πŸ” Security Headers

.header("X-Content-Type-Options", "nosniff")
.header("X-Frame-Options", "DENY")
.header("X-XSS-Protection", "1; mode=block")
.header("Strict-Transport-Security", "max-age=31536000")
.header("Content-Security-Policy", "default-src 'self'")
Enter fullscreen mode Exit fullscreen mode

🎨 Custom Headers

.header("X-Request-Id", UUID.randomUUID().toString())
.header("X-User-Id", "123")
.header("X-API-Version", "v1")
.header("X-Rate-Limit-Remaining", "99")
.header("X-Total-Count", "1000")
.header("X-Page-Number", "1")
Enter fullscreen mode Exit fullscreen mode

πŸ“Š All HTTP Status Codes (HttpStatus Enum)

1xx Informational

HttpStatus.CONTINUE                              // 100
HttpStatus.SWITCHING_PROTOCOLS                   // 101
HttpStatus.PROCESSING                            // 102
Enter fullscreen mode Exit fullscreen mode

2xx Success

HttpStatus.OK                                    // 200 βœ…
HttpStatus.CREATED                               // 201 βœ…
HttpStatus.ACCEPTED                              // 202 βœ…
HttpStatus.NON_AUTHORITATIVE_INFORMATION         // 203
HttpStatus.NO_CONTENT                            // 204 βœ…
HttpStatus.RESET_CONTENT                         // 205
HttpStatus.PARTIAL_CONTENT                       // 206
HttpStatus.MULTI_STATUS                          // 207
Enter fullscreen mode Exit fullscreen mode

3xx Redirection

HttpStatus.MULTIPLE_CHOICES                      // 300
HttpStatus.MOVED_PERMANENTLY                     // 301 βœ…
HttpStatus.FOUND                                 // 302 βœ…
HttpStatus.SEE_OTHER                             // 303
HttpStatus.NOT_MODIFIED                          // 304 βœ…
HttpStatus.TEMPORARY_REDIRECT                    // 307
HttpStatus.PERMANENT_REDIRECT                    // 308
Enter fullscreen mode Exit fullscreen mode

4xx Client Errors

HttpStatus.BAD_REQUEST                           // 400 βœ…
HttpStatus.UNAUTHORIZED                          // 401 βœ…
HttpStatus.PAYMENT_REQUIRED                      // 402
HttpStatus.FORBIDDEN                             // 403 βœ…
HttpStatus.NOT_FOUND                             // 404 βœ…
HttpStatus.METHOD_NOT_ALLOWED                    // 405 βœ…
HttpStatus.NOT_ACCEPTABLE                        // 406
HttpStatus.PROXY_AUTHENTICATION_REQUIRED         // 407
HttpStatus.REQUEST_TIMEOUT                       // 408
HttpStatus.CONFLICT                              // 409 βœ…
HttpStatus.GONE                                  // 410
HttpStatus.LENGTH_REQUIRED                       // 411
HttpStatus.PRECONDITION_FAILED                   // 412
HttpStatus.PAYLOAD_TOO_LARGE                     // 413
HttpStatus.URI_TOO_LONG                          // 414
HttpStatus.UNSUPPORTED_MEDIA_TYPE                // 415
HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE       // 416
HttpStatus.EXPECTATION_FAILED                    // 417
HttpStatus.I_AM_A_TEAPOT                         // 418 (joke)
HttpStatus.UNPROCESSABLE_ENTITY                  // 422 βœ…
HttpStatus.LOCKED                                // 423
HttpStatus.FAILED_DEPENDENCY                     // 424
HttpStatus.TOO_EARLY                             // 425
HttpStatus.UPGRADE_REQUIRED                      // 426
HttpStatus.PRECONDITION_REQUIRED                 // 428
HttpStatus.TOO_MANY_REQUESTS                     // 429 βœ…
HttpStatus.REQUEST_HEADER_FIELDS_TOO_LARGE       // 431
HttpStatus.UNAVAILABLE_FOR_LEGAL_REASONS         // 451
Enter fullscreen mode Exit fullscreen mode

5xx Server Errors

HttpStatus.INTERNAL_SERVER_ERROR                 // 500 βœ…
HttpStatus.NOT_IMPLEMENTED                       // 501
HttpStatus.BAD_GATEWAY                           // 502 βœ…
HttpStatus.SERVICE_UNAVAILABLE                   // 503 βœ…
HttpStatus.GATEWAY_TIMEOUT                       // 504 βœ…
HttpStatus.HTTP_VERSION_NOT_SUPPORTED            // 505
HttpStatus.VARIANT_ALSO_NEGOTIATES               // 506
HttpStatus.INSUFFICIENT_STORAGE                  // 507
HttpStatus.LOOP_DETECTED                         // 508
HttpStatus.BANDWIDTH_LIMIT_EXCEEDED              // 509
HttpStatus.NOT_EXTENDED                          // 510
HttpStatus.NETWORK_AUTHENTICATION_REQUIRED       // 511
Enter fullscreen mode Exit fullscreen mode

🎯 Common Patterns

Pattern 1: Simple Success

ResponseEntity.ok(data)
Enter fullscreen mode Exit fullscreen mode

Pattern 2: Created with Location

ResponseEntity.created(location).body(data)
Enter fullscreen mode Exit fullscreen mode

Pattern 3: No Content (Delete)

ResponseEntity.noContent().build()
Enter fullscreen mode Exit fullscreen mode

Pattern 4: Not Found

ResponseEntity.notFound().build()
Enter fullscreen mode Exit fullscreen mode

Pattern 5: Bad Request with Error

ResponseEntity.badRequest().body(errorMessage)
Enter fullscreen mode Exit fullscreen mode

Pattern 6: Conditional Response

data != null 
    ? ResponseEntity.ok(data) 
    : ResponseEntity.notFound().build()
Enter fullscreen mode Exit fullscreen mode

Pattern 7: With Custom Headers

ResponseEntity.ok()
    .header("X-Custom", "value")
    .contentType(MediaType.APPLICATION_JSON)
    .body(data)
Enter fullscreen mode Exit fullscreen mode

Pattern 8: File Download

ResponseEntity.ok()
    .contentType(MediaType.APPLICATION_OCTET_STREAM)
    .header(HttpHeaders.CONTENT_DISPOSITION, 
            "attachment; filename=\"file.pdf\"")
    .body(fileBytes)
Enter fullscreen mode Exit fullscreen mode

Pattern 9: Cached Response

ResponseEntity.ok()
    .cacheControl(CacheControl.maxAge(60, TimeUnit.SECONDS))
    .eTag("version-1")
    .body(data)
Enter fullscreen mode Exit fullscreen mode

Pattern 10: Complex Builder

ResponseEntity
    .status(HttpStatus.CREATED)
    .contentType(MediaType.APPLICATION_JSON)
    .header("X-Request-Id", requestId)
    .cacheControl(CacheControl.noCache())
    .location(uri)
    .body(data)
Enter fullscreen mode Exit fullscreen mode

βœ… Most Used (90% Cases)

// Success
ResponseEntity.ok(data)                          // GET, PUT
ResponseEntity.created(location).body(data)      // POST
ResponseEntity.noContent().build()               // DELETE

// Errors
ResponseEntity.notFound().build()                // 404
ResponseEntity.badRequest().body(error)          // 400
ResponseEntity.status(500).body(error)           // 500

// With headers
.header("name", "value")
.contentType(MediaType.APPLICATION_JSON)
Enter fullscreen mode Exit fullscreen mode

πŸ“ Quick Reference Table

Use Case Code Status
Success (GET) ResponseEntity.ok(data) 200
Created (POST) ResponseEntity.created(uri).body(data) 201
Success (DELETE) ResponseEntity.noContent().build() 204
Not Found ResponseEntity.notFound().build() 404
Bad Input ResponseEntity.badRequest().body(error) 400
Unauthorized ResponseEntity.status(401).body(error) 401
Forbidden ResponseEntity.status(403).body(error) 403
Server Error ResponseEntity.status(500).body(error) 500
File Download ResponseEntity.ok().contentType(...).body(bytes) 200
Conditional data != null ? ok(data) : notFound().build() 200/404

πŸ”‘ Key Points

βœ… ResponseEntity is inbuilt (org.springframework.http)
βœ… Gives complete control over HTTP response
βœ… Can set status code, headers, body
βœ… Type-safe with generics
βœ… Builder pattern for fluent API
βœ… Immutable - thread-safe

❌ Not required for simple cases (Spring auto-converts)
❌ Don't use for every endpoint (only when control needed)

==================================

======================================

ResponseEntity - Internal Structure/Hierarchy

Class Hierarchy

java.lang.Object
    ↓
org.springframework.http.HttpEntity<T>
    ↓
org.springframework.http.ResponseEntity<T>
Enter fullscreen mode Exit fullscreen mode

ResponseEntity Class Structure

public class ResponseEntity<T> extends HttpEntity<T> {

    // Fields (inherited + own)
    private final HttpStatusCode status;  // Status code (200, 404, etc.)
    // From HttpEntity: body (T), headers (HttpHeaders)

    // Constructors
    public ResponseEntity(HttpStatusCode status) { }

    public ResponseEntity(T body, HttpStatusCode status) { }

    public ResponseEntity(MultiValueMap<String, String> headers, 
                          HttpStatusCode status) { }

    public ResponseEntity(T body, 
                          MultiValueMap<String, String> headers, 
                          HttpStatusCode status) { }

    // Static Factory Methods (Builder Pattern)
    public static BodyBuilder status(HttpStatusCode status) { }
    public static BodyBuilder ok() { }
    public static <T> ResponseEntity<T> ok(T body) { }
    public static BodyBuilder created(URI location) { }
    public static BodyBuilder accepted() { }
    public static BodyBuilder noContent() { }
    public static BodyBuilder badRequest() { }
    public static HeadersBuilder<?> notFound() { }

    // Getters
    public HttpStatusCode getStatusCode() { }
    public int getStatusCodeValue() { }  // Deprecated in newer versions

    // From HttpEntity
    public T getBody() { }
    public HttpHeaders getHeaders() { }
    public boolean hasBody() { }
}
Enter fullscreen mode Exit fullscreen mode

ResponseEntity ke 3 Main Parts

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚     ResponseEntity<T>           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                 β”‚
β”‚  1. Status Code (HttpStatus)    β”‚
β”‚     β”œβ”€β”€β”€ 200 (OK)              β”‚
β”‚     β”œβ”€β”€β”€ 201 (CREATED)         β”‚
β”‚     β”œβ”€β”€β”€ 404 (NOT_FOUND)       β”‚
β”‚     └─── 500 (ERROR)           β”‚
β”‚                                 β”‚
β”‚  2. Headers (HttpHeaders)       β”‚
β”‚     β”œβ”€β”€β”€ Content-Type          β”‚
β”‚     β”œβ”€β”€β”€ Authorization         β”‚
β”‚     └─── Custom headers        β”‚
β”‚                                 β”‚
β”‚  3. Body (Generic Type T)       β”‚
β”‚     β”œβ”€β”€β”€ User object           β”‚
β”‚     β”œβ”€β”€β”€ List<User>            β”‚
β”‚     β”œβ”€β”€β”€ String                β”‚
β”‚     └─── Any POJO              β”‚
β”‚                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Enter fullscreen mode Exit fullscreen mode

Builder Pattern - Nested Classes

// ResponseEntity ke andar nested interfaces/classes

public interface BodyBuilder extends HeadersBuilder<BodyBuilder> {
    BodyBuilder contentLength(long contentLength);
    BodyBuilder contentType(MediaType contentType);
    <T> ResponseEntity<T> body(T body);
}

public interface HeadersBuilder<B extends HeadersBuilder<B>> {
    B header(String headerName, String... headerValues);
    B headers(HttpHeaders headers);
    ResponseEntity<Void> build();
}
Enter fullscreen mode Exit fullscreen mode

Practical Example - Internal Flow

@GetMapping("/user/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {

    // Step 1: ResponseEntity.ok() β†’ Creates BodyBuilder
    // Step 2: body(user) β†’ Sets body and returns ResponseEntity

    User user = new User(id, "Raj", "raj@email.com");

    return ResponseEntity
            .ok()              // status = 200
            .header("X-Custom", "MyValue")  // headers set
            .body(user);       // body set, ResponseEntity created
}
Enter fullscreen mode Exit fullscreen mode

Memory Structure

ResponseEntity Instance:
{
    status: HttpStatus.OK (200),
    headers: {
        "Content-Type": "application/json",
        "X-Custom": "MyValue"
    },
    body: User {
        id: 1,
        name: "Raj",
        email: "raj@email.com"
    }
}
Enter fullscreen mode Exit fullscreen mode

Key Points

  1. Generic Class hai: ResponseEntity<T> - T koi bhi type ho sakta hai
  2. Immutable hai: Ek baar create karne ke baad change nahi hota
  3. Builder Pattern use karta hai: Fluent API ke liye
  4. HttpEntity ko extend karta hai: Body aur headers inherit karta hai
  5. HttpStatus enum use karta hai: Predefined status codes ke liye

Yeh structure Spring Framework mein predefined hai, aapko sirf use karna hai! 🎯

==========================================================

============================================================

Spring Boot Controller - Complete Learning Pattern

🎯 Step-by-Step Learning Roadmap


LEVEL 1: Basic Annotations Samjho

1. Controller Banane ke Annotations

@RestController  // JSON/XML response deta hai (REST API ke liye)
@Controller      // View/HTML return karta hai (traditional web apps)

@RequestMapping("/api")  // Base URL for entire controller
Enter fullscreen mode Exit fullscreen mode

2. HTTP Methods ke Annotations

@GetMapping      // Data READ karne ke liye
@PostMapping     // Data CREATE karne ke liye
@PutMapping      // Data UPDATE karne ke liye (complete)
@PatchMapping    // Data UPDATE karne ke liye (partial)
@DeleteMapping   // Data DELETE karne ke liye
Enter fullscreen mode Exit fullscreen mode

LEVEL 2: Request Data Kaise Receive Kare

Pattern: 5 Tarike se data aata hai

@RestController
@RequestMapping("/api/users")
public class UserController {

    // 1. PATH VARIABLE - URL mein data
    @GetMapping("/{id}")  // /api/users/123
    public User getUser(@PathVariable Long id) {
        return userService.findById(id);
    }

    // 2. REQUEST PARAM - Query string mein data
    @GetMapping  // /api/users?name=Raj&age=25
    public List<User> searchUsers(
        @RequestParam String name,
        @RequestParam(required = false) Integer age
    ) {
        return userService.search(name, age);
    }

    // 3. REQUEST BODY - JSON/XML body mein data
    @PostMapping
    public User createUser(@RequestBody User user) {
        return userService.save(user);
    }

    // 4. REQUEST HEADER - Headers mein data
    @GetMapping("/secure")
    public String secureData(
        @RequestHeader("Authorization") String token
    ) {
        return "Token: " + token;
    }

    // 5. MODEL ATTRIBUTE - Form data ke liye
    @PostMapping("/form")
    public String submitForm(@ModelAttribute User user) {
        userService.save(user);
        return "success";
    }
}
Enter fullscreen mode Exit fullscreen mode

LEVEL 3: Response Kaise Bheje

Pattern: 3 Ways to Return Data

@RestController
@RequestMapping("/api/products")
public class ProductController {

    // WAY 1: Direct Object Return (Simple)
    @GetMapping("/{id}")
    public Product getProduct(@PathVariable Long id) {
        return productService.findById(id);  // Auto 200 OK
    }

    // WAY 2: ResponseEntity (Control chahiye)
    @GetMapping("/detail/{id}")
    public ResponseEntity<Product> getProductDetail(@PathVariable Long id) {
        Product product = productService.findById(id);

        if (product != null) {
            return ResponseEntity.ok(product);  // 200
        } else {
            return ResponseEntity.notFound().build();  // 404
        }
    }

    // WAY 3: ResponseEntity with Custom Response
    @PostMapping
    public ResponseEntity<ApiResponse> createProduct(@RequestBody Product product) {
        Product saved = productService.save(product);

        ApiResponse response = new ApiResponse(
            "Product created successfully",
            saved,
            HttpStatus.CREATED.value()
        );

        return ResponseEntity
            .status(HttpStatus.CREATED)
            .header("X-Product-Id", saved.getId().toString())
            .body(response);
    }
}
Enter fullscreen mode Exit fullscreen mode

LEVEL 4: CRUD Pattern - Sabse Important

Standard CRUD Controller Template

@RestController
@RequestMapping("/api/books")
public class BookController {

    @Autowired
    private BookService bookService;

    // CREATE - POST
    @PostMapping
    public ResponseEntity<Book> createBook(@RequestBody Book book) {
        Book saved = bookService.save(book);
        return ResponseEntity.status(HttpStatus.CREATED).body(saved);
    }

    // READ ALL - GET
    @GetMapping
    public ResponseEntity<List<Book>> getAllBooks() {
        List<Book> books = bookService.findAll();
        return ResponseEntity.ok(books);
    }

    // READ ONE - GET with ID
    @GetMapping("/{id}")
    public ResponseEntity<Book> getBook(@PathVariable Long id) {
        Book book = bookService.findById(id);

        if (book != null) {
            return ResponseEntity.ok(book);
        }
        return ResponseEntity.notFound().build();
    }

    // UPDATE - PUT
    @PutMapping("/{id}")
    public ResponseEntity<Book> updateBook(
        @PathVariable Long id,
        @RequestBody Book book
    ) {
        Book updated = bookService.update(id, book);

        if (updated != null) {
            return ResponseEntity.ok(updated);
        }
        return ResponseEntity.notFound().build();
    }

    // DELETE - DELETE
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteBook(@PathVariable Long id) {
        boolean deleted = bookService.delete(id);

        if (deleted) {
            return ResponseEntity.noContent().build();  // 204
        }
        return ResponseEntity.notFound().build();  // 404
    }
}
Enter fullscreen mode Exit fullscreen mode

LEVEL 5: Validation Add Karo

@RestController
@RequestMapping("/api/employees")
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;

    @PostMapping
    public ResponseEntity<Employee> createEmployee(
        @Valid @RequestBody Employee employee  // @Valid for validation
    ) {
        Employee saved = employeeService.save(employee);
        return ResponseEntity.status(HttpStatus.CREATED).body(saved);
    }
}

// Employee class mein validation
public class Employee {

    @NotNull(message = "Name is required")
    @Size(min = 2, max = 50)
    private String name;

    @Email(message = "Invalid email format")
    private String email;

    @Min(value = 18, message = "Age must be at least 18")
    private Integer age;

    // getters, setters
}
Enter fullscreen mode Exit fullscreen mode

LEVEL 6: Exception Handling

@RestController
@RequestMapping("/api/orders")
public class OrderController {

    @Autowired
    private OrderService orderService;

    @GetMapping("/{id}")
    public ResponseEntity<Order> getOrder(@PathVariable Long id) {
        try {
            Order order = orderService.findById(id);
            return ResponseEntity.ok(order);

        } catch (OrderNotFoundException e) {
            return ResponseEntity.notFound().build();

        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }
}

// Global Exception Handler (Better approach)
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(OrderNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleNotFound(OrderNotFoundException ex) {
        ErrorResponse error = new ErrorResponse(
            HttpStatus.NOT_FOUND.value(),
            ex.getMessage(),
            LocalDateTime.now()
        );
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
    }
}
Enter fullscreen mode Exit fullscreen mode

πŸŽ“ Learning Pattern - Yaad Rakhne ke Tips

1. URL Pattern

HTTP_METHOD  /base-path/resource/{id}?queryParam=value
Enter fullscreen mode Exit fullscreen mode

2. Controller Flow

Request β†’ Controller β†’ Service β†’ Repository β†’ Database
                ↓
Response ← Controller ← Service ← Repository ← Database
Enter fullscreen mode Exit fullscreen mode

3. Common Status Codes

  • 200 OK - Success (GET, PUT)
  • 201 Created - Resource created (POST)
  • 204 No Content - Success but no data (DELETE)
  • 400 Bad Request - Validation error
  • 404 Not Found - Resource not found
  • 500 Internal Server Error - Server error

4. Practice Template

@RestController
@RequestMapping("/api/{resource-name}")
public class {Resource}Controller {

    @Autowired
    private {Resource}Service service;

    @PostMapping          // CREATE
    @GetMapping           // READ ALL
    @GetMapping("/{id}")  // READ ONE
    @PutMapping("/{id}")  // UPDATE
    @DeleteMapping("/{id}") // DELETE
}
Enter fullscreen mode Exit fullscreen mode

πŸš€ Practice Kaise Kare

  1. Simple CRUD bano - Student, Product, Book
  2. Postman se test karo - Har endpoint test karo
  3. Validation add karo - Input validation
  4. Exception handling add karo - Error scenarios
  5. Custom responses bano - ResponseEntity use karo

Yeh pattern follow karo, 2-3 projects bana lo, sab clear ho jayega! πŸ’ͺ

================================

============================================

===========================================================

Controller Code Kaise Likhe - Step by Step Thinking Process 🧠


🎯 STEP 1: Requirements Samjho - Kya Banana Hai?

Example: E-commerce Order System

Requirements:

  • User order create kar sake
  • User apne orders dekh sake
  • Admin sab orders dekh sake
  • Order cancel kar sake

πŸ”₯ STEP 2: Sochne Ka Pattern - Mental Checklist

Har Feature Ke Liye 6 Sawaal Pucho:

1. KYA karna hai? (What)
   β†’ Order create karna hai

2. KON karega? (Who)
   β†’ User karega (authentication chahiye)

3. KAHAN se data aayega? (Input)
   β†’ Request body se JSON aayega

4. KYA validation chahiye? (Validation)
   β†’ Items empty nahi hone chahiye
   β†’ Price valid hona chahiye

5. KAHAN bhejenge? (Process)
   β†’ Service layer ko bhejenge business logic ke liye

6. KYA return karenge? (Output)
   β†’ Created order ka data with status 201
Enter fullscreen mode Exit fullscreen mode

πŸ“ STEP 3: Real Example - Order Controller Banana

Mental Process Dikhata Hoon:

Requirement: "User order create kar sake"

πŸ€” Sochna Start:
β”œβ”€ URL kya hoga? 
β”‚  β†’ /api/orders (resource name plural)
β”‚
β”œβ”€ HTTP method?
β”‚  β†’ POST (kyunki create kar rahe)
β”‚
β”œβ”€ Input kahan se?
β”‚  β†’ Request body se JSON (OrderRequest DTO)
β”‚
β”œβ”€ Authentication?
β”‚  β†’ Haan, user login hona chahiye
β”‚  β†’ User ID header se milega
β”‚
β”œβ”€ Response kya?
β”‚  β†’ Created order details
β”‚  β†’ Status: 201 Created
β”‚
└─ Error handling?
   β†’ Validation fail? β†’ 400
   β†’ Product not found? β†’ 404
   β†’ Payment fail? β†’ 422
Enter fullscreen mode Exit fullscreen mode

πŸ’‘ STEP 4: Code Likhne Ka Actual Process

Step-by-Step Sochkar Code Likho:

@RestController
@RequestMapping("/api/orders")
public class OrderController {

    // STEP 1: Dependencies sochna
    // Kisko call karna padega?
    // β†’ Service layer (business logic)
    // β†’ Mapper (DTO to Entity conversion)

    @Autowired
    private OrderService orderService;  // Business logic ke liye

    @Autowired
    private OrderMapper orderMapper;    // DTO conversion ke liye


    // STEP 2: Method signature sochna
    // β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    // β”‚ @PostMapping β†’ kyunki CREATE operation β”‚
    // β”‚ ResponseEntity β†’ control chahiye       β”‚
    // β”‚ <ApiResponse<OrderResponse>> β†’ wrapper β”‚
    // β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

    @PostMapping
    public ResponseEntity<ApiResponse<OrderResponse>> createOrder(

        // STEP 3: Parameters sochna - Kya kya chahiye?

        // 3a. Order data β†’ Request body se
        @RequestBody @Valid OrderRequest request,

        // 3b. User identification β†’ Header se
        @RequestHeader("X-User-Id") Long userId

        // Yeh sochna: Aur kya chahiye?
        // - Authentication token? (Spring Security handle karega)
        // - Request ID for tracing? (optional)
    ) {

        // STEP 4: Method body - Logic step by step

        // 4a. INPUT VALIDATION (already @Valid se ho gaya)
        //     But extra business validation?

        // 4b. LOGGING (debugging ke liye)
        log.info("Creating order for user: {}", userId);

        // 4c. DTO to ENTITY conversion
        //     Kyunki service ko entity chahiye, DTO nahi
        Order order = orderMapper.toEntity(request);
        order.setUserId(userId);  // User ID set karna

        // 4d. SERVICE CALL (actual business logic)
        Order createdOrder = orderService.createOrder(order);

        // 4e. ENTITY to DTO conversion
        //     Kyunki user ko DTO bhejenge, entity nahi
        OrderResponse response = orderMapper.toResponse(createdOrder);

        // 4f. RESPONSE WRAPPER
        //     Standard format mein return
        ApiResponse<OrderResponse> apiResponse = ApiResponse.success(
            "Order created successfully",
            response
        );

        // 4g. RETURN with proper STATUS
        return ResponseEntity
                .status(HttpStatus.CREATED)  // 201
                .body(apiResponse);
    }
}
Enter fullscreen mode Exit fullscreen mode

🎨 STEP 5: Har Component Kyu Banana - Decision Tree

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚        Controller Method Banana             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚ 1. HTTP Mapping?    β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚ POST   β†’ Create (insert)        β”‚
        β”‚ GET    β†’ Read (fetch)           β”‚
        β”‚ PUT    β†’ Update (full)          β”‚
        β”‚ PATCH  β†’ Update (partial)       β”‚
        β”‚ DELETE β†’ Delete (remove)        β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚ 2. Input Source?    β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚ @RequestBody    β†’ JSON data       β”‚
        β”‚ @PathVariable   β†’ URL mein {id}   β”‚
        β”‚ @RequestParam   β†’ ?name=value     β”‚
        β”‚ @RequestHeader  β†’ Headers         β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚ 3. Validation?      β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚ @Valid        β†’ DTO validation β”‚
        β”‚ @NotNull      β†’ Field level    β”‚
        β”‚ Custom logic  β†’ Business rules β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚ 4. Processing?      β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚ Service call β†’ Business logic β”‚
        β”‚ Repository  β†’ Direct DB (bad) β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚ 5. Response?        β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚ Object        β†’ Auto serialize  β”‚
        β”‚ ResponseEntity β†’ Control status β”‚
        β”‚ ApiResponse   β†’ Standard format β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Enter fullscreen mode Exit fullscreen mode

🧩 STEP 6: DTOs Kab Aur Kyu Banana

Decision Making:

// ❌ BAD: Entity directly use
@PostMapping
public Order createOrder(@RequestBody Order order) {
    return orderService.save(order);
}

// βœ… GOOD: DTO use karo
@PostMapping
public ResponseEntity<OrderResponse> createOrder(
    @RequestBody OrderRequest request
) {
    Order order = orderMapper.toEntity(request);
    Order saved = orderService.save(order);
    OrderResponse response = orderMapper.toResponse(saved);
    return ResponseEntity.ok(response);
}
Enter fullscreen mode Exit fullscreen mode

Kyu DTOs?

1. SECURITY
   Entity mein sensitive fields ho sakte hain
   (password, internal IDs, audit fields)

2. FLEXIBILITY
   Database change ho, API same rahe

3. VALIDATION
   Input aur output different validation

4. VERSIONING
   API v1, v2 different DTOs use kar sakte
Enter fullscreen mode Exit fullscreen mode

πŸ”§ STEP 7: Service Layer Ko Call Kaise Kare

Thinking Process:

// Controller ka kaam SIRF:
// 1. Request receive karna
// 2. Validation karna
// 3. Service ko call karna
// 4. Response return karna

@RestController
@RequestMapping("/api/products")
public class ProductController {

    // Service inject karo (dependency)
    @Autowired
    private ProductService productService;

    @GetMapping("/{id}")
    public ResponseEntity<ProductResponse> getProduct(@PathVariable Long id) {

        // ❌ GALAT: Controller mein business logic
        // Product product = productRepository.findById(id);
        // if (product.getStock() > 0) {
        //     product.setAvailable(true);
        // }

        // βœ… SAHI: Service ko call karo
        Product product = productService.getProductById(id);

        ProductResponse response = productMapper.toResponse(product);
        return ResponseEntity.ok(response);
    }
}
Enter fullscreen mode Exit fullscreen mode

🎯 STEP 8: Complete Example - Sochte Hue Likho

Requirement: User apne orders list dekhe with filters

@RestController
@RequestMapping("/api/orders")
public class OrderController {

    @Autowired
    private OrderService orderService;

    // SOCHNA START:
    // ────────────────────────────────────────
    // GET method β†’ read operation
    // Pagination β†’ large data ho sakta hai
    // Filters β†’ status, date range
    // User-specific β†’ userId header se

    @GetMapping
    public ResponseEntity<PageResponse<OrderResponse>> getMyOrders(

        // USER IDENTIFICATION
        @RequestHeader("X-User-Id") Long userId,

        // PAGINATION PARAMETERS
        @RequestParam(defaultValue = "0") int page,
        @RequestParam(defaultValue = "10") int size,

        // SORTING
        @RequestParam(defaultValue = "createdAt") String sortBy,
        @RequestParam(defaultValue = "DESC") String sortDirection,

        // FILTERS (optional - required = false)
        @RequestParam(required = false) String status,
        @RequestParam(required = false) String startDate,
        @RequestParam(required = false) String endDate

    ) {

        // STEP 1: Log the request
        log.info("Fetching orders for user: {}, page: {}", userId, page);

        // STEP 2: Validation (optional parameters check)
        if (page < 0 || size <= 0 || size > 100) {
            throw new InvalidRequestException("Invalid pagination parameters");
        }

        // STEP 3: Build filter object
        // Kyunki bahut parameters hain, object mein wrap karo
        OrderFilter filter = OrderFilter.builder()
                .userId(userId)
                .status(status)
                .startDate(startDate)
                .endDate(endDate)
                .build();

        // STEP 4: Build pagination object
        PageRequest pageRequest = PageRequest.of(
            page, 
            size,
            Sort.by(Sort.Direction.fromString(sortDirection), sortBy)
        );

        // STEP 5: Service call
        Page<Order> orderPage = orderService.getOrders(filter, pageRequest);

        // STEP 6: Convert to DTO
        List<OrderResponse> responses = orderPage.getContent()
                .stream()
                .map(orderMapper::toResponse)
                .collect(Collectors.toList());

        // STEP 7: Build page response
        PageResponse<OrderResponse> pageResponse = PageResponse.<OrderResponse>builder()
                .content(responses)
                .pageNumber(orderPage.getNumber())
                .pageSize(orderPage.getSize())
                .totalElements(orderPage.getTotalElements())
                .totalPages(orderPage.getTotalPages())
                .build();

        // STEP 8: Return with proper status
        return ResponseEntity.ok(pageResponse);
    }
}
Enter fullscreen mode Exit fullscreen mode

πŸ“Š STEP 9: Decision Chart - Kya Use Karu?

Input Parameters Decision:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Data kahan se aa raha hai?                     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                 β”‚
β”‚ URL path mein?                                  β”‚
β”‚ /orders/123          β†’ @PathVariable Long id   β”‚
β”‚                                                 β”‚
β”‚ Query string mein?                              β”‚
β”‚ /orders?status=pending β†’ @RequestParam String  β”‚
β”‚                                                 β”‚
β”‚ Request body mein?                              β”‚
β”‚ JSON payload         β†’ @RequestBody OrderDTO   β”‚
β”‚                                                 β”‚
β”‚ Headers mein?                                   β”‚
β”‚ Authorization token  β†’ @RequestHeader String   β”‚
β”‚                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Enter fullscreen mode Exit fullscreen mode

Return Type Decision:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Kya control chahiye?                           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                 β”‚
β”‚ Status code + headers + body?                   β”‚
β”‚ β†’ ResponseEntity<T>                            β”‚
β”‚                                                 β”‚
β”‚ Sirf data return?                              β”‚
β”‚ β†’ Direct object (Spring auto-converts)         β”‚
β”‚                                                 β”‚
β”‚ Standard API format?                           β”‚
β”‚ β†’ ResponseEntity<ApiResponse<T>>               β”‚
β”‚                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Enter fullscreen mode Exit fullscreen mode

πŸŽ“ STEP 10: Practice Pattern - Khud Se Code Karo

Template Follow Karo:

// TEMPLATE for any new endpoint:

@[HttpMethod]Mapping("[url-path]")
public ResponseEntity<ApiResponse<[ResponseDTO]>> methodName(

    // 1. Identify karo - kya chahiye?
    @PathVariable [Type] [name],           // URL se ID
    @RequestParam [Type] [name],           // Query params
    @RequestBody @Valid [RequestDTO] dto,  // JSON body
    @RequestHeader [Type] [name]           // Headers

) {
    // 2. Log karo
    log.info("Doing something with: {}", name);

    // 3. DTO to Entity (agar chahiye)
    [Entity] entity = mapper.toEntity(dto);

    // 4. Service call (business logic)
    [Entity] result = service.doSomething(entity);

    // 5. Entity to DTO
    [ResponseDTO] response = mapper.toResponse(result);

    // 6. Wrap in ApiResponse
    ApiResponse<[ResponseDTO]> apiResponse = 
        ApiResponse.success("Success message", response);

    // 7. Return with status
    return ResponseEntity
            .status(HttpStatus.[STATUS])
            .body(apiResponse);
}
Enter fullscreen mode Exit fullscreen mode

πŸ”₯ STEP 11: Common Patterns Yaad Rakho

CRUD Operations:

// CREATE
@PostMapping β†’ @RequestBody β†’ service.create() β†’ 201 CREATED

// READ (single)
@GetMapping("/{id}") β†’ @PathVariable β†’ service.findById() β†’ 200 OK

// READ (all)
@GetMapping β†’ @RequestParam (filters) β†’ service.findAll() β†’ 200 OK

// UPDATE
@PutMapping("/{id}") β†’ @PathVariable + @RequestBody β†’ service.update() β†’ 200 OK

// DELETE
@DeleteMapping("/{id}") β†’ @PathVariable β†’ service.delete() β†’ 204 NO_CONTENT
Enter fullscreen mode Exit fullscreen mode

πŸ’ͺ Practice Exercise - Khud Karo:

Requirement: Product management system

TODO:
1. Product create karo (name, price, stock)
2. Products list fetch karo (with pagination)
3. Product by ID fetch karo
4. Product update karo
5. Product delete karo

Socho:
- Kis method mein kya parameters?
- Kis method mein kya validation?
- Kis method mein kya return type?
- Kis method mein kya status code?
Enter fullscreen mode Exit fullscreen mode

Yeh pattern follow karo, 2-3 CRUD modules khud likho, sab clear ho jayega! πŸš€

Top comments (0)