API Request Response Bodies: @RequestBody @ResponseBody භාවිතය SC Guide

ඉතින් කොහොමද යාලුවනේ! අද අපි කතා කරන්න යන්නේ API Development වලදී අත්යවශ්යම වෙන දෙයක් ගැන – ඒ තමයි Request Body සහ Response Body. මේවා නිකන් වචන දෙකක් වගේ පෙනුනත්, ඕනෑම නූතන Web Application එකක Backend එක හදනකොට මේවා හරියට තේරුම් අරන් වැඩ කරන එක හරිම වැදගත්.
දැන් හිතන්නකෝ, ඔයාලා Facebook එකේ post එකක් දානවා කියලා. එතකොට ඔයාලා ටයිප් කරන text එක, දාන photo එක, මේ හැමදේම Facebook server එකට යවන්න ඕනනේ. ඒ යවන දත්ත ටික තමයි Request Body එක කියන්නේ. ඒ වගේම, ඒ post එක server එකට ගියාට පස්සේ "ඔයාගේ post එක successfully දාලා තියෙනවා" කියලා ආපහු confirmation එකක් එනවනේ. ඒ ආපහු එන දත්ත ටික තමයි Response Body එක.
ගොඩක් වෙලාවට මේ දත්ත යන එන එක වෙන්නේ JSON (JavaScript Object Notation) format එකෙන්. JSON කියන්නේ light-weight, human-readable data interchange format එකක්. ඉතින්, Java Application එකක් (විශේෂයෙන්ම Spring Boot) හරහා API හදනකොට මේ JSON data handle කරන්න අපිට තියෙන ප්රධානම tools දෙක තමයි @RequestBody
සහ @ResponseBody
annotations.
අද අපි මේ ගැන ගැඹුරින් කතා කරමු, මොකද මේවා හරියට තේරුම් ගත්තොත් ඔයාලගේ API Develop කරන වැඩේ හුඟක් පහසු වෙනවා. එහෙනම්, කෝපි එකක් එහෙම ලෑස්ති කරගෙන, එන්න අපි පටන් ගමු!
Request Body (ඉල්ලීම් සිරුර - Request Body කියන්නේ මොකක්ද?)
සරලවම කියනවා නම්, Request Body කියන්නේ Client එකක් (උදා: web browser එකක්, mobile app එකක්) Server එකට යවන දත්ත payload එක. මේක සාමාන්යයෙන් භාවිතා වෙන්නේ Client එකෙන් Server එකට අලුත් data එකක් යවන්න (data create කරන්න - POST
method එකෙන්) හෝ තියෙන data එකක් update කරන්න (PUT
/PATCH
methods වලින්) වගේ වෙලාවට.
දැන් හිතන්න ඔයාලා Product management system එකක් හදනවා කියලා. අලුත් Product එකක් add කරනවා නම්, ඒ Product එකේ නම, මිල, විස්තර වගේ දේවල් Server එකට යවන්න ඕනනේ. මේ විස්තර ටික යවන්නේ Request Body එකක් විදිහට. සාමාන්යයෙන් මේවා JSON format එකෙන් යවන එක තමයි අද දවසේදී ගොඩක්ම ජනප්රිය.
@RequestBody
Annotation එකේ වැඩේ මොකක්ද?
Spring Framework එකේදී, අපි Client එකෙන් එවන JSON Request Body එක Java Object එකකට map කරගන්න @RequestBody
annotation එක භාවිතා කරනවා. මේක දාපු ගමන් Spring MVC (Model-View-Controller) එක ඇතුලේ තියෙන HttpMessageConverter එක වැඩට බහිනවා. එයා කරන්නේ Client එකෙන් එවන JSON string එක අරගෙන, අපි දීලා තියෙන Java Class එකේ attributes වලට හරියටම ගලපලා Java Object එකක් හදලා දෙන එක.
උදාහරණයක් විදිහට, Client එකෙන් මේ වගේ JSON එකක් එවනවා කියලා හිතමු:
{
"productName": "Laptop",
"price": 1200.00,
"description": "Powerful gaming laptop"
}
අපි මේක අල්ලගන්න පුළුවන් Java Class එකක් (අපි මේවට POJO - Plain Old Java Object, නැත්නම් DTO - Data Transfer Object කියලා කියනවා) හදාගන්නවා:
public class Product {
private String productName;
private double price;
private String description;
// Getters and Setters
// Constructors
}
ඊට පස්සේ, අපේ Controller එකේදී මේ Request Body එක අල්ලගන්න @RequestBody
මෙහෙම පාවිච්චි කරනවා:
@RestController
@RequestMapping("/api/products")
public class ProductController {
@PostMapping
public ResponseEntity<String> addProduct(@RequestBody Product product) {
// 'product' object එකට client එකෙන් එව්ව JSON data ටික map වෙලා තියෙන්නේ
System.out.println("Product Name: " + product.getProductName());
System.out.println("Price: " + product.getPrice());
System.out.println("Description: " + product.getDescription());
// Database එකට save කරන්න වගේ operations මෙතනින් කරන්න පුළුවන්
return ResponseEntity.ok("Product added successfully!");
}
}
දැක්කා නේද? @RequestBody Product product
කියලා දැම්මම, Spring එක ඉබේම JSON එක Product object එකකට convert කරලා අපිට දෙනවා. වැඩේ හරිම ලේසියි නේද?
Response Body (පිළිතුරු සිරුර - Response Body එකේ වැදගත්කම)
Response Body කියන්නේ Server එකෙන් Client එකට ආපහු යවන දත්ත payload එක. Client එකක් Request එකක් යැව්වම, Server එකෙන් ඒකට අදාළ data එකක්, status එකක්, error message එකක් වගේ දේවල් Response Body එකක් විදිහට ආපහු යවනවා.
අපි කලින් Product system එකේ උදාහරණයම ගමුකෝ. ඔයාලා Product list එකක් බලන්න Request එකක් යැව්වම, Server එකෙන් Product details ටික JSON format එකෙන් ආපහු එවනවානේ. ඒ එවන Product list එක තමයි Response Body එක.
@ResponseBody
Annotation එකේ වැඩේ මොකක්ද?
Spring Framework එකේදී, අපේ Java Object එකක් JSON format එකට convert කරලා Client එකට යවන්න @ResponseBody
annotation එක භාවිතා කරනවා. මේකත් @RequestBody
වගේම HttpMessageConverter එක භාවිතා කරනවා, හැබැයි මේ වෙලාවේදී වෙන්නේ Java Object එකක් JSON string එකකට convert කරන එකයි.
අද කාලේ Spring Boot වල @RestController
annotation එක භාවිතා කරනවා නම්, @ResponseBody
එක අමුතුවෙන් දාන්න ඕන වෙන්නේ නැහැ. මොකද @RestController
එක ඇතුළතින්ම @Controller
සහ @ResponseBody
annotations දෙකම අන්තර්ගත වෙනවා. ඒ කියන්නේ, ඔයා @RestController
එකක් use කරනවා නම්, ඒ controller එකේ තියෙන හැම method එකකින්ම return කරන Java object එකක් automatically JSON (හෝ configure කරලා තියෙන වෙන format එකකට) convert වෙලා Response Body එක විදිහට යනවා.
උදාහරණයක් විදිහට, අපි Product list එකක් return කරන endpoint එකක් හදමු:
@RestController
@RequestMapping("/api/products")
public class ProductController {
@GetMapping
public List<Product> getAllProducts() {
// Database එකෙන් Product list එකක් අරන් එනවා කියලා හිතමු
List<Product> products = new ArrayList<>();
products.add(new Product("Smartphone", 800.00, "Latest model"));
products.add(new Product("Smartwatch", 250.00, "Fitness tracker"));
return products; // මේ List<Product> එක JSON Array එකක් විදිහට Client එකට යනවා
}
}
මේ code එකේ getAllProducts()
method එකෙන් List<Product>
එකක් return කරනවා. @RestController
එක නිසා, මේ List එක automatically JSON array එකකට convert වෙලා Response Body එක විදිහට Client එකට යනවා. ඒක මේ වගේ වෙයි:
[
{
"productName": "Smartphone",
"price": 800.00,
"description": "Latest model"
},
{
"productName": "Smartwatch",
"price": 250.00,
"description": "Fitness tracker"
}
]
හරිම ලේසියි නේද? ඔයාලට අමුතුවෙන් JSON conversions ගැන වද වෙන්න දෙයක් නැහැ. Spring එක ඒක බලාගන්නවා.
Practical Use Cases and Best Practices (ප්රයෝගික භාවිතය සහ හොඳම ක්රමවේද)
Request Body සහ Response Body හරියට handle කරන එක API Development වලදී හරිම වැදගත්. මෙන්න ඒ ගැන මතක තියාගන්න ඕන ටිකක්:
1. Data Transfer Objects (DTOs) භාවිතා කරන්න
අපි කලින් දැක්කා වගේ, Request Body එකක් handle කරන්න සහ Response Body එකක් return කරන්න DTOs (Data Transfer Objects) හරිම ප්රයෝජනවත්. මේවා සාමාන්යයෙන් Database Entity Class වලට වඩා වෙනස් විදිහට define කරන්නේ. මොකද සමහර වෙලාවට Client එකට යවන්න ඕන data එක Server එකේ Database එකේ තියෙන විදිහටම නෙවෙයි වෙන්න පුළුවන්. ඒ වගේම Client එකෙන් එවන data එකත් Database එකට කෙලින්ම map කරන්න බැරි වෙන්න පුළුවන්. DTOs භාවිතා කරන එකෙන් Application එකේ layers අතර data flow එක පිරිසිදුව තියාගන්න පුළුවන්.
// Request DTO for creating a product
public class CreateProductRequest {
private String name;
private double unitPrice;
// Getters and Setters
}
// Response DTO for product details
public class ProductResponse {
private Long id;
private String productName;
private double price;
private String details;
// Getters and Setters
}
මේ වගේ DTOs පාවිච්චි කරන එකෙන් අපේ API contract එක (API එකේ input/output) පැහැදිලිව තියාගන්න පුළුවන්.
2. Request Validation
Client එකෙන් එවන Request Body එකේ තියෙන data වල Validations කරන්න අමතක කරන්න එපා. Java වලට නම් Hibernate Validator වගේ libraries පාවිච්චි කරලා @Valid
annotation එකත් එක්ක request body එක validate කරන්න පුළුවන්. උදාහරණයක් විදිහට, product name එක empty වෙන්න බැහැ කියලා check කරන්න මේ වගේ කරන්න පුළුවන්:
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Min;
public class CreateProductRequest {
@NotBlank(message = "Product name cannot be empty")
private String name;
@Min(value = 0, message = "Price must be positive")
private double unitPrice;
// Getters and Setters
}
// Controller එකේදී
@PostMapping
public ResponseEntity<String> addProduct(@Valid @RequestBody CreateProductRequest request) {
// ... logic ...
return ResponseEntity.ok("Product created.");
}
මේ වගේ Validations දාන එකෙන් අනවශ්ය data Application එක ඇතුලට එන එක වළක්වාගන්න පුළුවන්.
3. Error Handling
API එකකදී වැරැද්දක් වුණොත්, ඒක Client එකට පැහැදිලිව දැනුම් දෙන්න ඕන. ඒකට අපි Error Response Body එකක් යවනවා. සාමාන්යයෙන් JSON format එකෙන් error code, error message, details වගේ දේවල් දාලා Response Body එකක් හදනවා. Spring Boot වලට නම් @ControllerAdvice
සහ @ExceptionHandler
වගේ දේවල් පාවිච්චි කරලා Global Error Handling කරන්න පුළුවන්.
{
"status": 400,
"error": "Bad Request",
"message": "Product name cannot be empty. Price must be positive.",
"timestamp": "2023-10-27T10:30:00Z"
}
4. Content-Type Header එකේ වැදගත්කම
Client එකෙන් Request Body එකක් යවනකොට, ඒ Request එකේ Content-Type
header එක හරියට දාන්න ඕන. JSON body එකක් නම්, Content-Type: application/json
කියලා දාන්න ඕන. Server එකට මේකෙන් තේරෙනවා එන data එක JSON format එකෙන් තියෙන්නේ කියලා. ඒ වගේම Server එකෙන් Response එකක් යවනකොටත්, Response එකේ Content-Type
header එක දාන්න ඕන.
A Simple Code Example (සරල කෝඩ් උදාහරණයක්)
දැන් අපි බලමු මේ @RequestBody
සහ @ResponseBody
දෙකම එකට කොහොමද වැඩ කරන්නේ කියලා, සරල Spring Boot API එකක් හදලා.
මුලින්ම, අපේ Project එකට අවශ්ය POJO (Plain Old Java Object) එක හදාගමු. මේක Product එකක් නියෝජනය කරනවා.
// src/main/java/com/example/api/dto/ProductDTO.java
package com.example.api.dto;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Min;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data // Generates getters, setters, toString, equals, hashCode
@NoArgsConstructor // Generates a constructor with no arguments
@AllArgsConstructor // Generates a constructor with all arguments
public class ProductDTO {
private Long id; // For response, if product has an ID
@NotBlank(message = "Product name cannot be empty")
private String name;
@Min(value = 0, message = "Price must be positive")
private double price;
private String description;
}
මතක තියාගන්න, මෙතනදී අපි Lombok library එක පාවිච්චි කරනවා getters, setters වගේ දේවල් auto generate කරගන්න. ඒක නිසා code එක clean වෙනවා. Project එකට Lombok dependency එක add කරන්න අමතක කරන්න එපා (pom.xml or build.gradle).
ඊළඟට, අපේ REST Controller එක හදමු:
// src/main/java/com/example/api/controller/ProductApiController.java
package com.example.api.controller;
import com.example.api.dto.ProductDTO;
import jakarta.validation.Valid;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
@RestController
@RequestMapping("/api/products")
public class ProductApiController {
// Simple in-memory "database" for demonstration
private final List<ProductDTO> products = new ArrayList<>();
private final AtomicLong counter = new AtomicLong();
// Endpoint to create a new product
// @RequestBody will map incoming JSON to ProductDTO
// @Valid will trigger validation on ProductDTO
@PostMapping
public ResponseEntity<ProductDTO> createProduct(@Valid @RequestBody ProductDTO productDTO) {
// Simulate saving to a database by assigning an ID
productDTO.setId(counter.incrementAndGet());
products.add(productDTO);
System.out.println("Product created: " + productDTO.getName() + ", ID: " + productDTO.getId());
// Return the created product with its new ID as a JSON response
// @ResponseBody is implicitly used by @RestController
return new ResponseEntity<>(productDTO, HttpStatus.CREATED);
}
// Endpoint to get all products
// @ResponseBody is implicitly used by @RestController to return List<ProductDTO> as JSON array
@GetMapping
public ResponseEntity<List<ProductDTO>> getAllProducts() {
if (products.isEmpty()) {
return new ResponseEntity<>(HttpStatus.NO_CONTENT); // 204 No Content
}
return new ResponseEntity<>(products, HttpStatus.OK); // 200 OK
}
// Endpoint to get a product by ID
@GetMapping("/{id}")
public ResponseEntity<ProductDTO> getProductById(@PathVariable Long id) {
return products.stream()
.filter(p -> p.getId().equals(id))
.findFirst()
.map(productDTO -> new ResponseEntity<>(productDTO, HttpStatus.OK))
.orElseGet(() -> new ResponseEntity<>(HttpStatus.NOT_FOUND)); // 404 Not Found
}
}
මේ Controller එකේදී, createProduct
method එකට @RequestBody ProductDTO productDTO
කියලා දාලා තියෙන නිසා, Client එකෙන් එවන JSON Product data එක automatically ProductDTO
object එකකට convert වෙනවා. ඒ වගේම, @Valid
දාලා තියෙන නිසා, ProductDTO එකේ තියෙන validations (@NotBlank
, @Min
) ක්රියාත්මක වෙනවා. ඒ වගේම, මේ method එකෙන් return කරන ProductDTO
object එකත් @RestController
එකේ බලපෑමෙන් JSON format එකට convert වෙලා Client එකට Response Body එක විදිහට යනවා.
getAllProducts
සහ getProductById
methods වලින් List<ProductDTO>
සහ ProductDTO
objects return කරනකොටත්, ඒවා automatically JSON format එකට convert වෙලා Client එකට යනවා.
මේක run කරලා බලන්න, ඔයාලට Postman හෝ cURL වගේ tool එකක් පාවිච්චි කරන්න පුළුවන්:
Product එකක් හදන්න (POST Request):
POST http://localhost:8080/api/products
Content-Type: application/json
{
"name": "Wireless Mouse",
"price": 25.50,
"description": "Ergonomic design with silent clicks"
}
සියලු Products ගන්න (GET Request):
GET http://localhost:8080/api/products
විශේෂිත Product එකක් ගන්න (GET Request):
GET http://localhost:8080/api/products/1
මේ උදාහරණයෙන් ඔයාලට @RequestBody
සහ @ResponseBody
කොහොමද real-world scenario එකකදී වැඩ කරන්නේ කියලා හොඳ අදහසක් එන්න ඇති කියලා හිතනවා.
නිගමනය (Conclusion)
ඉතින් යාලුවනේ, අද අපි Request Body සහ Response Body කියන්නේ මොකක්ද, ඒවා API Development වලදී කොච්චර වැදගත්ද, විශේෂයෙන්ම Spring Boot වලදී @RequestBody
සහ @ResponseBody
annotations පාවිච්චි කරන්නේ කොහොමද කියලා විස්තරාත්මකව කතා කළා. JSON data එහා මෙහා කරනකොට මේ concepts තේරුම් ගන්න එක ඔයාලගේ API Develop කරන හැකියාවට ලොකු රුකුලක් වෙනවා නිසැකයි.
දැන් ඔයාලට හොඳ අදහසක් එන්න ඇති මේවා ගැන. අමතක කරන්න එපා, මේවා Theory වලින් විතරක් ඉගෙනගෙන හරියන්නේ නැහැ, අනිවාර්යයෙන්ම Code කරලා බලන්න ඕන. පුළුවන් නම් ඔයාලගේම සරල Project එකක් හදලා මේ concepts implement කරලා බලන්න. එතකොට තමයි හරියටම දේ තේරෙන්නේ.
මේ ලිපිය ගැන ඔයාලට තියෙන අදහස්, ප්රශ්න, මොනවා හරි තිබ්බොත් පහළින් comment කරන්න. අපි හැමෝම එකතු වෙලා ඉගෙන ගමු. එහෙනම් තවත් අලුත් ලිපියකින් හමුවෙමු! Happy Coding! ජය වේවා!