Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.workshop.springbootrestapi;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootRestapiApplication {

public static void main(String[] args) {
SpringApplication.run(SpringBootRestapiApplication.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.workshop.springbootrestapi.controller;

import com.workshop.springbootrestapi.model.Customer;
import com.workshop.springbootrestapi.service.CustomerService;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/customers")
public class CustomerController {

private final CustomerService customerService;

public CustomerController(CustomerService customerService) {
this.customerService = customerService;
}

// CREATE
@PostMapping
public Customer create(@Valid @RequestBody Customer customer) {
return customerService.addCustomer(customer);
}

// GET ALL
@GetMapping
public List<Customer> getAll() {
return customerService.getAllCustomers();
}

// GET BY EMAIL
@GetMapping("/{email}")
public Customer getByEmail(@PathVariable String email) {
return customerService.getCustomerByEmail(email);
}

// UPDATE
@PutMapping("/{email}")
public Customer update(@PathVariable String email,
@RequestBody Customer customer) {
return customerService.updateCustomer(email, customer);
}

// DELETE
@DeleteMapping("/{email}")
public void delete(@PathVariable String email) {
customerService.deleteCustomer(email);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.workshop.springbootrestapi.controller;

import com.workshop.springbootrestapi.model.Product;
import com.workshop.springbootrestapi.service.ProductService;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

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

private final ProductService productService;
private static final String API_KEY = "123456";

public ProductController(ProductService productService) {
this.productService = productService;
}

private void validateApiKey(String apiKey) {
if (!API_KEY.equals(apiKey)) {
throw new RuntimeException("Invalid API Key");
}
}

@PostMapping
public ResponseEntity<Product> create(
@RequestHeader("API-Key") String apiKey,
@Valid @RequestBody Product product) {

validateApiKey(apiKey);
return ResponseEntity.ok(productService.addProduct(product));
}

@GetMapping
public List<Product> getAll(@RequestHeader("API-Key") String apiKey) {
validateApiKey(apiKey);
return productService.getAllProducts();
}

@GetMapping("/{name}")
public Product getByName(
@RequestHeader("API-Key") String apiKey,
@PathVariable String name) {

validateApiKey(apiKey);
return productService.getProductByName(name);
}

@PutMapping("/{name}")
public Product update(
@RequestHeader("API-Key") String apiKey,
@PathVariable String name,
@RequestBody Product product) {

validateApiKey(apiKey);
return productService.updateProduct(name, product);
}

@DeleteMapping("/{name}")
public void delete(
@RequestHeader("API-Key") String apiKey,
@PathVariable String name) {

validateApiKey(apiKey);
productService.deleteProduct(name);
}

@GetMapping("/category/{category}")
public List<Product> getByCategory(
@RequestHeader("API-Key") String apiKey,
@PathVariable String category) {

validateApiKey(apiKey);
return productService.getProductsByCategory(category);
}

@GetMapping("/price")
public List<Product> getByPriceRange(
@RequestHeader("API-Key") String apiKey,
@RequestParam double min,
@RequestParam double max) {

validateApiKey(apiKey);
return productService.getProductsByPriceRange(min, max);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.workshop.springbootrestapi.exception;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingRequestHeaderException;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<?> handleValidation(MethodArgumentNotValidException ex) {

Map<String, String> errors = new HashMap<>();

ex.getBindingResult().getFieldErrors()
.forEach(err -> errors.put(err.getField(), err.getDefaultMessage()));

return ResponseEntity.badRequest().body(errors);
}

@ExceptionHandler(MissingRequestHeaderException.class)
public ResponseEntity<String> handleMissingHeader(MissingRequestHeaderException ex) {
return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body("API Key is required");
}

@ExceptionHandler(ProductNotFoundException.class)
public ResponseEntity<String> handleProductNotFound(ProductNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(ex.getMessage());
}

@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<String> handleIllegalArgument(IllegalArgumentException ex) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(ex.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.workshop.springbootrestapi.exception;

public class ProductNotFoundException extends RuntimeException {
public ProductNotFoundException(String message) {
super(message);
}
}
60 changes: 60 additions & 0 deletions src/main/java/com/workshop/springbootrestapi/model/Customer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.workshop.springbootrestapi.model;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;

public class Customer {

@NotBlank(message = "Name cannot be blank")
private String name;

@Email(message = "Email must be valid")
private String email;

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

@NotBlank(message = "Address cannot be blank")
private String address;


public Customer(String name, String email, int age, String address) {
this.name = name;
this.email = email;
this.age = age;
this.address = address;
}

public String getName() {
return name;
}

public String getEmail() {
return email;
}

public int getAge() {
return age;
}

public String getAddress() {
return address;
}

public void setName(String name) {
this.name = name;
}

public void setEmail(String email) {
this.email = email;
}

public void setAge(int age) {
this.age = age;
}

public void setAddress(String address) {
this.address = address;
}
}
65 changes: 65 additions & 0 deletions src/main/java/com/workshop/springbootrestapi/model/Product.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.workshop.springbootrestapi.model;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Positive;
import jakarta.validation.constraints.Size;

import java.math.BigDecimal;

public class Product {

@NotBlank(message = "Name cannot be blank")
@Size(min = 3, message = "Name must be at least 3 characters")
private String name;

@Positive(message = "Price must be positive")
private BigDecimal price;

@NotBlank(message = "Category cannot be blank")
private String category;

@Positive(message = "Quantity must be positive")
private int quantity;

public Product() {}

public Product(String name, BigDecimal price, String category, int quantity) {
this.name = name;
this.price = price;
this.category = category;
this.quantity = quantity;
}


public String getName() {
return name;
}

public BigDecimal getPrice() {
return price;
}

public String getCategory() {
return category;
}

public int getQuantity() {
return quantity;
}

public void setName(String name) {
this.name = name;
}

public void setPrice(BigDecimal price) {
this.price = price;
}

public void setCategory(String category) {
this.category = category;
}

public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.workshop.springbootrestapi.service;

import com.workshop.springbootrestapi.model.Customer;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class CustomerService {

private final List<Customer> customers = new ArrayList<>();

public Customer addCustomer(Customer customer) {
customers.add(customer);
return customer;
}

public List<Customer> getAllCustomers() {
return customers;
}

public Customer getCustomerByEmail(String email) {
return customers.stream()
.filter(c -> c.getEmail().equalsIgnoreCase(email))
.findFirst()
.orElseThrow(() -> new RuntimeException("Customer not found: " + email));
}

public Customer updateCustomer(String email, Customer updatedCustomer) {
Customer customer = getCustomerByEmail(email);

customer.setName(updatedCustomer.getName());
customer.setAge(updatedCustomer.getAge());
customer.setAddress(updatedCustomer.getAddress());

return customer;
}

public void deleteCustomer(String email) {
Customer customer = getCustomerByEmail(email);
customers.remove(customer);
}
}
Loading