diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..30cf57e
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,10 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Ignored default folder with query files
+/queries/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/lab-java-springboot-rest-api.iml b/.idea/lab-java-springboot-rest-api.iml
new file mode 100644
index 0000000..d6ebd48
--- /dev/null
+++ b/.idea/lab-java-springboot-rest-api.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..188022c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..43ec782
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..af01810
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,53 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.5
+
+
+
+ com.ironhack
+ lab-springboot-rest-api
+ 1.0.0
+ lab-springboot-rest-api
+ Lab Spring Boot REST API
+
+
+ 21
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+ true
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/src/main/java/com/ironhack/lab/LabSpringbootRestApiApplication.java b/src/main/java/com/ironhack/lab/LabSpringbootRestApiApplication.java
new file mode 100644
index 0000000..b64de80
--- /dev/null
+++ b/src/main/java/com/ironhack/lab/LabSpringbootRestApiApplication.java
@@ -0,0 +1,13 @@
+package com.ironhack.lab;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class LabSpringbootRestApiApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(LabSpringbootRestApiApplication.class, args);
+ }
+}
+
diff --git a/src/main/java/com/ironhack/lab/controller/CustomerController.java b/src/main/java/com/ironhack/lab/controller/CustomerController.java
new file mode 100644
index 0000000..690131d
--- /dev/null
+++ b/src/main/java/com/ironhack/lab/controller/CustomerController.java
@@ -0,0 +1,55 @@
+package com.ironhack.lab.controller;
+
+import com.ironhack.lab.exception.CustomerNotFoundException;
+import com.ironhack.lab.model.Customer;
+import com.ironhack.lab.service.CustomerService;
+import jakarta.validation.Valid;
+import org.springframework.http.HttpStatus;
+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;
+ }
+
+ @PostMapping
+ @ResponseStatus(HttpStatus.CREATED)
+ public Customer createCustomer(@Valid @RequestBody Customer customer) {
+ return customerService.addCustomer(customer);
+ }
+
+ @GetMapping
+ public List getAllCustomers() {
+ return customerService.getAllCustomers();
+ }
+
+ @GetMapping("/{email}")
+ public Customer getCustomerByEmail(@PathVariable String email) {
+ return customerService.getCustomerByEmail(email)
+ .orElseThrow(() -> new CustomerNotFoundException("Customer not found with email: " + email));
+ }
+
+ @PutMapping("/{email}")
+ public Customer updateCustomer(@PathVariable String email,
+ @Valid @RequestBody Customer customer) {
+ return customerService.updateCustomer(email, customer)
+ .orElseThrow(() -> new CustomerNotFoundException("Customer not found with email: " + email));
+ }
+
+ @DeleteMapping("/{email}")
+ @ResponseStatus(HttpStatus.NO_CONTENT)
+ public void deleteCustomer(@PathVariable String email) {
+ boolean deleted = customerService.deleteCustomer(email);
+ if (!deleted) {
+ throw new CustomerNotFoundException("Customer not found with email: " + email);
+ }
+ }
+}
+
diff --git a/src/main/java/com/ironhack/lab/controller/ProductController.java b/src/main/java/com/ironhack/lab/controller/ProductController.java
new file mode 100644
index 0000000..79cad49
--- /dev/null
+++ b/src/main/java/com/ironhack/lab/controller/ProductController.java
@@ -0,0 +1,91 @@
+package com.ironhack.lab.controller;
+
+import com.ironhack.lab.exception.ApiKeyMissingException;
+import com.ironhack.lab.exception.InvalidPriceRangeException;
+import com.ironhack.lab.exception.ProductNotFoundException;
+import com.ironhack.lab.model.Product;
+import com.ironhack.lab.service.ProductService;
+import jakarta.validation.Valid;
+import org.springframework.http.HttpStatus;
+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 (apiKey == null || !apiKey.equals(API_KEY)) {
+ throw new ApiKeyMissingException("Invalid or missing API-Key header");
+ }
+ }
+
+ @PostMapping
+ @ResponseStatus(HttpStatus.CREATED)
+ public Product createProduct(@RequestHeader("API-Key") String apiKey,
+ @Valid @RequestBody Product product) {
+ validateApiKey(apiKey);
+ return productService.addProduct(product);
+ }
+
+ @GetMapping
+ public List getAllProducts(@RequestHeader("API-Key") String apiKey) {
+ validateApiKey(apiKey);
+ return productService.getAllProducts();
+ }
+
+ @GetMapping("/{name}")
+ public Product getProductByName(@RequestHeader("API-Key") String apiKey,
+ @PathVariable String name) {
+ validateApiKey(apiKey);
+ return productService.getProductByName(name)
+ .orElseThrow(() -> new ProductNotFoundException("Product not found with name: " + name));
+ }
+
+ @PutMapping("/{name}")
+ public Product updateProduct(@RequestHeader("API-Key") String apiKey,
+ @PathVariable String name,
+ @Valid @RequestBody Product product) {
+ validateApiKey(apiKey);
+ return productService.updateProduct(name, product)
+ .orElseThrow(() -> new ProductNotFoundException("Product not found with name: " + name));
+ }
+
+ @DeleteMapping("/{name}")
+ @ResponseStatus(HttpStatus.NO_CONTENT)
+ public void deleteProduct(@RequestHeader("API-Key") String apiKey,
+ @PathVariable String name) {
+ validateApiKey(apiKey);
+ boolean deleted = productService.deleteProduct(name);
+ if (!deleted) {
+ throw new ProductNotFoundException("Product not found with name: " + name);
+ }
+ }
+
+ @GetMapping("/category/{category}")
+ public List getProductsByCategory(@RequestHeader("API-Key") String apiKey,
+ @PathVariable String category) {
+ validateApiKey(apiKey);
+ return productService.getProductsByCategory(category);
+ }
+
+ @GetMapping("/price")
+ public List getProductsByPriceRange(@RequestHeader("API-Key") String apiKey,
+ @RequestParam Double min,
+ @RequestParam Double max) {
+ validateApiKey(apiKey);
+ if (min < 0 || max < 0 || min > max) {
+ throw new InvalidPriceRangeException("Invalid price range: min must be less than or equal to max and both must be positive");
+ }
+ return productService.getProductsByPriceRange(min, max);
+ }
+}
+
diff --git a/src/main/java/com/ironhack/lab/exception/ApiKeyMissingException.java b/src/main/java/com/ironhack/lab/exception/ApiKeyMissingException.java
new file mode 100644
index 0000000..9300b36
--- /dev/null
+++ b/src/main/java/com/ironhack/lab/exception/ApiKeyMissingException.java
@@ -0,0 +1,8 @@
+package com.ironhack.lab.exception;
+
+public class ApiKeyMissingException extends RuntimeException {
+ public ApiKeyMissingException(String message) {
+ super(message);
+ }
+}
+
diff --git a/src/main/java/com/ironhack/lab/exception/CustomerNotFoundException.java b/src/main/java/com/ironhack/lab/exception/CustomerNotFoundException.java
new file mode 100644
index 0000000..f1768ed
--- /dev/null
+++ b/src/main/java/com/ironhack/lab/exception/CustomerNotFoundException.java
@@ -0,0 +1,8 @@
+package com.ironhack.lab.exception;
+
+public class CustomerNotFoundException extends RuntimeException {
+ public CustomerNotFoundException(String message) {
+ super(message);
+ }
+}
+
diff --git a/src/main/java/com/ironhack/lab/exception/ErrorResponse.java b/src/main/java/com/ironhack/lab/exception/ErrorResponse.java
new file mode 100644
index 0000000..21959ad
--- /dev/null
+++ b/src/main/java/com/ironhack/lab/exception/ErrorResponse.java
@@ -0,0 +1,65 @@
+package com.ironhack.lab.exception;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+public class ErrorResponse {
+ private LocalDateTime timestamp;
+ private int status;
+ private String error;
+ private List messages;
+ private String path;
+
+ public ErrorResponse() {
+ this.timestamp = LocalDateTime.now();
+ }
+
+ public ErrorResponse(int status, String error, List messages, String path) {
+ this.timestamp = LocalDateTime.now();
+ this.status = status;
+ this.error = error;
+ this.messages = messages;
+ this.path = path;
+ }
+
+ public LocalDateTime getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(LocalDateTime timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public int getStatus() {
+ return status;
+ }
+
+ public void setStatus(int status) {
+ this.status = status;
+ }
+
+ public String getError() {
+ return error;
+ }
+
+ public void setError(String error) {
+ this.error = error;
+ }
+
+ public List getMessages() {
+ return messages;
+ }
+
+ public void setMessages(List messages) {
+ this.messages = messages;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+}
+
diff --git a/src/main/java/com/ironhack/lab/exception/GlobalExceptionHandler.java b/src/main/java/com/ironhack/lab/exception/GlobalExceptionHandler.java
new file mode 100644
index 0000000..cd762b8
--- /dev/null
+++ b/src/main/java/com/ironhack/lab/exception/GlobalExceptionHandler.java
@@ -0,0 +1,99 @@
+package com.ironhack.lab.exception;
+
+import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.http.HttpStatus;
+import org.springframework.validation.FieldError;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.MissingRequestHeaderException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RestControllerAdvice
+public class GlobalExceptionHandler {
+
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public ErrorResponse handleValidationErrors(MethodArgumentNotValidException ex, HttpServletRequest request) {
+ List errors = new ArrayList<>();
+ for (FieldError error : ex.getBindingResult().getFieldErrors()) {
+ errors.add(error.getField() + ": " + error.getDefaultMessage());
+ }
+ return new ErrorResponse(
+ HttpStatus.BAD_REQUEST.value(),
+ "Validation Failed",
+ errors,
+ request.getRequestURI()
+ );
+ }
+
+ @ExceptionHandler(ApiKeyMissingException.class)
+ @ResponseStatus(HttpStatus.UNAUTHORIZED)
+ public ErrorResponse handleApiKeyMissing(ApiKeyMissingException ex, HttpServletRequest request) {
+ return new ErrorResponse(
+ HttpStatus.UNAUTHORIZED.value(),
+ "Unauthorized",
+ List.of(ex.getMessage()),
+ request.getRequestURI()
+ );
+ }
+
+ @ExceptionHandler(MissingRequestHeaderException.class)
+ @ResponseStatus(HttpStatus.UNAUTHORIZED)
+ public ErrorResponse handleMissingHeader(MissingRequestHeaderException ex, HttpServletRequest request) {
+ return new ErrorResponse(
+ HttpStatus.UNAUTHORIZED.value(),
+ "Unauthorized",
+ List.of("Missing required header: " + ex.getHeaderName()),
+ request.getRequestURI()
+ );
+ }
+
+ @ExceptionHandler(ProductNotFoundException.class)
+ @ResponseStatus(HttpStatus.NOT_FOUND)
+ public ErrorResponse handleProductNotFound(ProductNotFoundException ex, HttpServletRequest request) {
+ return new ErrorResponse(
+ HttpStatus.NOT_FOUND.value(),
+ "Not Found",
+ List.of(ex.getMessage()),
+ request.getRequestURI()
+ );
+ }
+
+ @ExceptionHandler(CustomerNotFoundException.class)
+ @ResponseStatus(HttpStatus.NOT_FOUND)
+ public ErrorResponse handleCustomerNotFound(CustomerNotFoundException ex, HttpServletRequest request) {
+ return new ErrorResponse(
+ HttpStatus.NOT_FOUND.value(),
+ "Not Found",
+ List.of(ex.getMessage()),
+ request.getRequestURI()
+ );
+ }
+
+ @ExceptionHandler(InvalidPriceRangeException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public ErrorResponse handleInvalidPriceRange(InvalidPriceRangeException ex, HttpServletRequest request) {
+ return new ErrorResponse(
+ HttpStatus.BAD_REQUEST.value(),
+ "Bad Request",
+ List.of(ex.getMessage()),
+ request.getRequestURI()
+ );
+ }
+
+ @ExceptionHandler(Exception.class)
+ @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+ public ErrorResponse handleGenericException(Exception ex, HttpServletRequest request) {
+ return new ErrorResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR.value(),
+ "Internal Server Error",
+ List.of(ex.getMessage()),
+ request.getRequestURI()
+ );
+ }
+}
+
diff --git a/src/main/java/com/ironhack/lab/exception/InvalidPriceRangeException.java b/src/main/java/com/ironhack/lab/exception/InvalidPriceRangeException.java
new file mode 100644
index 0000000..2cddfc3
--- /dev/null
+++ b/src/main/java/com/ironhack/lab/exception/InvalidPriceRangeException.java
@@ -0,0 +1,8 @@
+package com.ironhack.lab.exception;
+
+public class InvalidPriceRangeException extends RuntimeException {
+ public InvalidPriceRangeException(String message) {
+ super(message);
+ }
+}
+
diff --git a/src/main/java/com/ironhack/lab/exception/ProductNotFoundException.java b/src/main/java/com/ironhack/lab/exception/ProductNotFoundException.java
new file mode 100644
index 0000000..8d44e45
--- /dev/null
+++ b/src/main/java/com/ironhack/lab/exception/ProductNotFoundException.java
@@ -0,0 +1,8 @@
+package com.ironhack.lab.exception;
+
+public class ProductNotFoundException extends RuntimeException {
+ public ProductNotFoundException(String message) {
+ super(message);
+ }
+}
+
diff --git a/src/main/java/com/ironhack/lab/model/Customer.java b/src/main/java/com/ironhack/lab/model/Customer.java
new file mode 100644
index 0000000..3ef1d11
--- /dev/null
+++ b/src/main/java/com/ironhack/lab/model/Customer.java
@@ -0,0 +1,74 @@
+package com.ironhack.lab.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;
+
+ @NotBlank(message = "Email cannot be blank")
+ @Email(message = "Email must be a valid email format")
+ private String email;
+
+ @Min(value = 18, message = "Age must be at least 18")
+ private Integer age;
+
+ @NotBlank(message = "Address cannot be blank")
+ private String address;
+
+ public Customer() {
+ }
+
+ public Customer(String name, String email, Integer age, String address) {
+ this.name = name;
+ this.email = email;
+ this.age = age;
+ this.address = address;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ @Override
+ public String toString() {
+ return "Customer{" +
+ "name='" + name + '\'' +
+ ", email='" + email + '\'' +
+ ", age=" + age +
+ ", address='" + address + '\'' +
+ '}';
+ }
+}
+
diff --git a/src/main/java/com/ironhack/lab/model/Product.java b/src/main/java/com/ironhack/lab/model/Product.java
new file mode 100644
index 0000000..432da49
--- /dev/null
+++ b/src/main/java/com/ironhack/lab/model/Product.java
@@ -0,0 +1,75 @@
+package com.ironhack.lab.model;
+
+import jakarta.validation.constraints.Min;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Positive;
+import jakarta.validation.constraints.Size;
+
+public class Product {
+
+ @NotBlank(message = "Name cannot be blank")
+ @Size(min = 3, message = "Name must have at least 3 characters")
+ private String name;
+
+ @Positive(message = "Price must be a positive number")
+ private Double price;
+
+ @NotBlank(message = "Category cannot be blank")
+ private String category;
+
+ @Positive(message = "Quantity must be a positive number")
+ private Integer quantity;
+
+ public Product() {
+ }
+
+ public Product(String name, Double price, String category, Integer quantity) {
+ this.name = name;
+ this.price = price;
+ this.category = category;
+ this.quantity = quantity;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Double getPrice() {
+ return price;
+ }
+
+ public void setPrice(Double price) {
+ this.price = price;
+ }
+
+ public String getCategory() {
+ return category;
+ }
+
+ public void setCategory(String category) {
+ this.category = category;
+ }
+
+ public Integer getQuantity() {
+ return quantity;
+ }
+
+ public void setQuantity(Integer quantity) {
+ this.quantity = quantity;
+ }
+
+ @Override
+ public String toString() {
+ return "Product{" +
+ "name='" + name + '\'' +
+ ", price=" + price +
+ ", category='" + category + '\'' +
+ ", quantity=" + quantity +
+ '}';
+ }
+}
+
diff --git a/src/main/java/com/ironhack/lab/service/CustomerService.java b/src/main/java/com/ironhack/lab/service/CustomerService.java
new file mode 100644
index 0000000..77d99ba
--- /dev/null
+++ b/src/main/java/com/ironhack/lab/service/CustomerService.java
@@ -0,0 +1,47 @@
+package com.ironhack.lab.service;
+
+import com.ironhack.lab.model.Customer;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class CustomerService {
+
+ private final List customers = new ArrayList<>();
+
+ public Customer addCustomer(Customer customer) {
+ customers.add(customer);
+ return customer;
+ }
+
+ public List getAllCustomers() {
+ return new ArrayList<>(customers);
+ }
+
+ public Optional getCustomerByEmail(String email) {
+ return customers.stream()
+ .filter(c -> c.getEmail().equalsIgnoreCase(email))
+ .findFirst();
+ }
+
+ public Optional updateCustomer(String email, Customer updatedCustomer) {
+ Optional existingCustomer = getCustomerByEmail(email);
+ if (existingCustomer.isPresent()) {
+ Customer customer = existingCustomer.get();
+ customer.setName(updatedCustomer.getName());
+ customer.setEmail(updatedCustomer.getEmail());
+ customer.setAge(updatedCustomer.getAge());
+ customer.setAddress(updatedCustomer.getAddress());
+ return Optional.of(customer);
+ }
+ return Optional.empty();
+ }
+
+ public boolean deleteCustomer(String email) {
+ return customers.removeIf(c -> c.getEmail().equalsIgnoreCase(email));
+ }
+}
+
diff --git a/src/main/java/com/ironhack/lab/service/ProductService.java b/src/main/java/com/ironhack/lab/service/ProductService.java
new file mode 100644
index 0000000..7388b75
--- /dev/null
+++ b/src/main/java/com/ironhack/lab/service/ProductService.java
@@ -0,0 +1,60 @@
+package com.ironhack.lab.service;
+
+import com.ironhack.lab.model.Product;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+@Service
+public class ProductService {
+
+ private final List products = new ArrayList<>();
+
+ public Product addProduct(Product product) {
+ products.add(product);
+ return product;
+ }
+
+ public List getAllProducts() {
+ return new ArrayList<>(products);
+ }
+
+ public Optional getProductByName(String name) {
+ return products.stream()
+ .filter(p -> p.getName().equalsIgnoreCase(name))
+ .findFirst();
+ }
+
+ public Optional updateProduct(String name, Product updatedProduct) {
+ Optional existingProduct = getProductByName(name);
+ if (existingProduct.isPresent()) {
+ Product product = existingProduct.get();
+ product.setName(updatedProduct.getName());
+ product.setPrice(updatedProduct.getPrice());
+ product.setCategory(updatedProduct.getCategory());
+ product.setQuantity(updatedProduct.getQuantity());
+ return Optional.of(product);
+ }
+ return Optional.empty();
+ }
+
+ public boolean deleteProduct(String name) {
+ return products.removeIf(p -> p.getName().equalsIgnoreCase(name));
+ }
+
+ public List getProductsByCategory(String category) {
+ return products.stream()
+ .filter(p -> p.getCategory().equalsIgnoreCase(category))
+ .collect(Collectors.toList());
+ }
+
+ public List getProductsByPriceRange(Double min, Double max) {
+ return products.stream()
+ .filter(p -> p.getPrice() >= min && p.getPrice() <= max)
+ .collect(Collectors.toList());
+ }
+}
+
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 0000000..4407030
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1,3 @@
+server.port=8080
+spring.application.name=lab-springboot-rest-api
+
diff --git a/target/classes/application.properties b/target/classes/application.properties
new file mode 100644
index 0000000..4407030
--- /dev/null
+++ b/target/classes/application.properties
@@ -0,0 +1,3 @@
+server.port=8080
+spring.application.name=lab-springboot-rest-api
+
diff --git a/target/classes/com/ironhack/lab/LabSpringbootRestApiApplication.class b/target/classes/com/ironhack/lab/LabSpringbootRestApiApplication.class
new file mode 100644
index 0000000..20c89a2
Binary files /dev/null and b/target/classes/com/ironhack/lab/LabSpringbootRestApiApplication.class differ
diff --git a/target/classes/com/ironhack/lab/controller/CustomerController.class b/target/classes/com/ironhack/lab/controller/CustomerController.class
new file mode 100644
index 0000000..17dc0d0
Binary files /dev/null and b/target/classes/com/ironhack/lab/controller/CustomerController.class differ
diff --git a/target/classes/com/ironhack/lab/controller/ProductController.class b/target/classes/com/ironhack/lab/controller/ProductController.class
new file mode 100644
index 0000000..8e009bd
Binary files /dev/null and b/target/classes/com/ironhack/lab/controller/ProductController.class differ
diff --git a/target/classes/com/ironhack/lab/exception/ApiKeyMissingException.class b/target/classes/com/ironhack/lab/exception/ApiKeyMissingException.class
new file mode 100644
index 0000000..f98733c
Binary files /dev/null and b/target/classes/com/ironhack/lab/exception/ApiKeyMissingException.class differ
diff --git a/target/classes/com/ironhack/lab/exception/CustomerNotFoundException.class b/target/classes/com/ironhack/lab/exception/CustomerNotFoundException.class
new file mode 100644
index 0000000..8ed079a
Binary files /dev/null and b/target/classes/com/ironhack/lab/exception/CustomerNotFoundException.class differ
diff --git a/target/classes/com/ironhack/lab/exception/ErrorResponse.class b/target/classes/com/ironhack/lab/exception/ErrorResponse.class
new file mode 100644
index 0000000..389be59
Binary files /dev/null and b/target/classes/com/ironhack/lab/exception/ErrorResponse.class differ
diff --git a/target/classes/com/ironhack/lab/exception/GlobalExceptionHandler.class b/target/classes/com/ironhack/lab/exception/GlobalExceptionHandler.class
new file mode 100644
index 0000000..6e6c94d
Binary files /dev/null and b/target/classes/com/ironhack/lab/exception/GlobalExceptionHandler.class differ
diff --git a/target/classes/com/ironhack/lab/exception/InvalidPriceRangeException.class b/target/classes/com/ironhack/lab/exception/InvalidPriceRangeException.class
new file mode 100644
index 0000000..af04e46
Binary files /dev/null and b/target/classes/com/ironhack/lab/exception/InvalidPriceRangeException.class differ
diff --git a/target/classes/com/ironhack/lab/exception/ProductNotFoundException.class b/target/classes/com/ironhack/lab/exception/ProductNotFoundException.class
new file mode 100644
index 0000000..0da4a39
Binary files /dev/null and b/target/classes/com/ironhack/lab/exception/ProductNotFoundException.class differ
diff --git a/target/classes/com/ironhack/lab/model/Customer.class b/target/classes/com/ironhack/lab/model/Customer.class
new file mode 100644
index 0000000..e58064f
Binary files /dev/null and b/target/classes/com/ironhack/lab/model/Customer.class differ
diff --git a/target/classes/com/ironhack/lab/model/Product.class b/target/classes/com/ironhack/lab/model/Product.class
new file mode 100644
index 0000000..963a4c7
Binary files /dev/null and b/target/classes/com/ironhack/lab/model/Product.class differ
diff --git a/target/classes/com/ironhack/lab/service/CustomerService.class b/target/classes/com/ironhack/lab/service/CustomerService.class
new file mode 100644
index 0000000..1f81dcc
Binary files /dev/null and b/target/classes/com/ironhack/lab/service/CustomerService.class differ
diff --git a/target/classes/com/ironhack/lab/service/ProductService.class b/target/classes/com/ironhack/lab/service/ProductService.class
new file mode 100644
index 0000000..a577a7d
Binary files /dev/null and b/target/classes/com/ironhack/lab/service/ProductService.class differ
diff --git a/target/lab-springboot-rest-api-1.0.0.jar b/target/lab-springboot-rest-api-1.0.0.jar
new file mode 100644
index 0000000..900b707
Binary files /dev/null and b/target/lab-springboot-rest-api-1.0.0.jar differ
diff --git a/target/lab-springboot-rest-api-1.0.0.jar.original b/target/lab-springboot-rest-api-1.0.0.jar.original
new file mode 100644
index 0000000..3c66cf8
Binary files /dev/null and b/target/lab-springboot-rest-api-1.0.0.jar.original differ
diff --git a/target/maven-archiver/pom.properties b/target/maven-archiver/pom.properties
new file mode 100644
index 0000000..9ca58c3
--- /dev/null
+++ b/target/maven-archiver/pom.properties
@@ -0,0 +1,3 @@
+artifactId=lab-springboot-rest-api
+groupId=com.ironhack
+version=1.0.0
diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
new file mode 100644
index 0000000..9e677c0
--- /dev/null
+++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
@@ -0,0 +1,13 @@
+com/ironhack/lab/service/ProductService.class
+com/ironhack/lab/model/Customer.class
+com/ironhack/lab/controller/ProductController.class
+com/ironhack/lab/model/Product.class
+com/ironhack/lab/exception/GlobalExceptionHandler.class
+com/ironhack/lab/LabSpringbootRestApiApplication.class
+com/ironhack/lab/exception/ApiKeyMissingException.class
+com/ironhack/lab/exception/InvalidPriceRangeException.class
+com/ironhack/lab/exception/ProductNotFoundException.class
+com/ironhack/lab/service/CustomerService.class
+com/ironhack/lab/controller/CustomerController.class
+com/ironhack/lab/exception/ErrorResponse.class
+com/ironhack/lab/exception/CustomerNotFoundException.class
diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
new file mode 100644
index 0000000..bae3c63
--- /dev/null
+++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
@@ -0,0 +1,13 @@
+/Users/igoryuziv/Documents/GitHub/lab-java-springboot-rest-api/src/main/java/com/ironhack/lab/controller/CustomerController.java
+/Users/igoryuziv/Documents/GitHub/lab-java-springboot-rest-api/src/main/java/com/ironhack/lab/exception/CustomerNotFoundException.java
+/Users/igoryuziv/Documents/GitHub/lab-java-springboot-rest-api/src/main/java/com/ironhack/lab/exception/GlobalExceptionHandler.java
+/Users/igoryuziv/Documents/GitHub/lab-java-springboot-rest-api/src/main/java/com/ironhack/lab/controller/ProductController.java
+/Users/igoryuziv/Documents/GitHub/lab-java-springboot-rest-api/src/main/java/com/ironhack/lab/exception/ProductNotFoundException.java
+/Users/igoryuziv/Documents/GitHub/lab-java-springboot-rest-api/src/main/java/com/ironhack/lab/service/ProductService.java
+/Users/igoryuziv/Documents/GitHub/lab-java-springboot-rest-api/src/main/java/com/ironhack/lab/service/CustomerService.java
+/Users/igoryuziv/Documents/GitHub/lab-java-springboot-rest-api/src/main/java/com/ironhack/lab/exception/ApiKeyMissingException.java
+/Users/igoryuziv/Documents/GitHub/lab-java-springboot-rest-api/src/main/java/com/ironhack/lab/model/Product.java
+/Users/igoryuziv/Documents/GitHub/lab-java-springboot-rest-api/src/main/java/com/ironhack/lab/model/Customer.java
+/Users/igoryuziv/Documents/GitHub/lab-java-springboot-rest-api/src/main/java/com/ironhack/lab/exception/InvalidPriceRangeException.java
+/Users/igoryuziv/Documents/GitHub/lab-java-springboot-rest-api/src/main/java/com/ironhack/lab/LabSpringbootRestApiApplication.java
+/Users/igoryuziv/Documents/GitHub/lab-java-springboot-rest-api/src/main/java/com/ironhack/lab/exception/ErrorResponse.java