diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..e6610b3
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,25 @@
+name: Java CI
+
+on:
+ pull_request:
+ push:
+ branches:
+ - main
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Check out repository
+ uses: actions/checkout@v4
+
+ - name: Set up Java 11
+ uses: actions/setup-java@v4
+ with:
+ distribution: temurin
+ java-version: "11"
+ cache: maven
+
+ - name: Run tests
+ run: ./mvnw test
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7cdf270
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,13 @@
+target/
+*.class
+
+.idea/
+.vscode/
+*.iml
+
+.classpath
+.project
+.settings/
+
+*.log
+.env
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..642d572
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
diff --git a/README.md b/README.md
index fd5f95f..814a20a 100644
--- a/README.md
+++ b/README.md
@@ -1,28 +1,178 @@
-# My-SpringBoot-MySQL-Application
+# My Spring Boot MySQL Application
-# Read Me First
-The following was discovered as part of building this project:
+This is an educational Spring Boot REST API for managing employees,
+departments, addresses, profiles, and simple login/logout state. The app uses
+Spring Web, Spring Data JPA, Bean Validation, and MySQL for local development.
-* The original package name 'com.hemant.db.springboot-mysql' is invalid and this project uses 'com.hemant.db.springbootmysql' instead.
+## Tech Stack
-# Getting Started
+- Java 11
+- Spring Boot 2.7.x
+- Spring Web
+- Spring Data JPA
+- MySQL Connector/J
+- H2 for automated tests
+- Maven Wrapper
-### Reference Documentation
-For further reference, please consider the following sections:
+## Project Structure
-* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
-* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.5.2/maven-plugin/reference/html/)
-* [Create an OCI image](https://docs.spring.io/spring-boot/docs/2.5.2/maven-plugin/reference/html/#build-image)
-* [Spring Web](https://docs.spring.io/spring-boot/docs/2.5.2/reference/htmlsingle/#boot-features-developing-web-applications)
-* [Spring Data JPA](https://docs.spring.io/spring-boot/docs/2.5.2/reference/htmlsingle/#boot-features-jpa-and-spring-data)
-* [JDBC API](https://docs.spring.io/spring-boot/docs/2.5.2/reference/htmlsingle/#boot-features-sql)
+```text
+.
+|-- pom.xml
+|-- mvnw / mvnw.cmd
+|-- src/
+| |-- main/
+| | |-- java/com/hemant/db/
+| | | |-- SpringbootMysqlApplication.java
+| | | |-- exception/
+| | | |-- model/
+| | | |-- repository/
+| | | |-- resource/
+| | | `-- service/
+| | `-- resources/application.yml
+| `-- test/
+| |-- java/com/hemant/db/
+| `-- resources/application-test.yml
+`-- .github/workflows/ci.yml
+```
-### Guides
-The following guides illustrate how to use some features concretely:
+### Main Packages
-* [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/)
-* [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/)
-* [Building REST services with Spring](https://spring.io/guides/tutorials/bookmarks/)
-* [Accessing Data with JPA](https://spring.io/guides/gs/accessing-data-jpa/)
-* [Accessing Relational Data using JDBC with Spring](https://spring.io/guides/gs/relational-data-access/)
-* [Managing Transactions](https://spring.io/guides/gs/managing-transactions/)
+`model` contains the JPA entities that map to database tables. Examples:
+`Employee`, `Department`, `Address`, and `Profile`.
+
+`repository` contains Spring Data JPA repositories. These interfaces provide
+database access methods such as `findByEmail`, `findByCity`, and `findByName`.
+
+`service` contains business logic. Controllers call services instead of talking
+directly to repositories, which keeps request handling and application rules
+separate.
+
+`resource` contains REST controllers. These preserve the original `/rest/...`
+routes while delegating work to services.
+
+`exception` contains shared API error handling. Missing records, duplicate
+records, bad requests, and validation failures return consistent JSON error
+responses.
+
+## Configuration
+
+The app reads database settings from environment variables with local defaults:
+
+| Variable | Default |
+| --- | --- |
+| `MYSQL_URL` | `jdbc:mysql://localhost:3306/employee_db` |
+| `MYSQL_USERNAME` | `root` |
+| `MYSQL_PASSWORD` | empty |
+| `JPA_DDL_AUTO` | `update` |
+| `JPA_SHOW_SQL` | `true` |
+
+Example PowerShell setup:
+
+```powershell
+$env:MYSQL_URL="jdbc:mysql://localhost:3306/employee_db"
+$env:MYSQL_USERNAME="root"
+$env:MYSQL_PASSWORD="your-password"
+```
+
+## Run Locally
+
+Start MySQL and create the database:
+
+```sql
+CREATE DATABASE employee_db;
+```
+
+Then run the application:
+
+```powershell
+.\mvnw.cmd spring-boot:run
+```
+
+On macOS/Linux:
+
+```bash
+./mvnw spring-boot:run
+```
+
+The API starts on the default Spring Boot port:
+
+```text
+http://localhost:8080
+```
+
+## API Overview
+
+The existing route style is preserved.
+
+### Employees
+
+- `GET /rest/Employee/all`
+- `POST /rest/Employee/insert`
+- `GET /rest/Employee/findbyname?name=...`
+- `GET /rest/Employee/findbydesignation?designation=...`
+- `POST /rest/Employee/updatedesignation?Id=...&designation=...`
+- `POST /rest/Employee/updatemobile?Id=...&mobile=...`
+- `POST /rest/Employee/updatepassword?Id=...&password=...`
+- `DELETE /rest/Employee/delete?Id=...`
+
+### Departments
+
+- `GET /rest/Department/all`
+- `POST /rest/Department/insert`
+- `GET /rest/Department/findbyname?name=...`
+- `GET /rest/Department/findbyaddress?address=...`
+- `POST /rest/Department/updatefloor?Id=...&floor=...`
+- `POST /rest/Department/updateaddress?Id=...&address=...`
+- `DELETE /rest/Department/delete?Id=...`
+
+### Addresses
+
+- `GET /rest/Address/all`
+- `POST /rest/Address/insert`
+- `GET /rest/Address/findbycity?city=...`
+- `GET /rest/Address/findbystate?state=...`
+- `POST /rest/Address/updateaddress?...`
+- `DELETE /rest/Address/delete?Id=...`
+
+### Profiles
+
+- `GET /rest/Profile/all`
+- `POST /rest/Profile/insert`
+- `GET /rest/Profile/findbygender?gender=...`
+- `GET /rest/Profile/findbyhobbies?hobbies=...`
+- `POST /rest/Profile/updatehobbies?Id=...&hobbies=...`
+- `DELETE /rest/Profile/delete?Id=...`
+
+### Login
+
+- `GET /rest/Login/findbyemail?email=...`
+- `POST /rest/Login/login?email=...&password=...`
+- `POST /rest/Login/logout?email=...`
+
+## Testing
+
+Tests use H2 in MySQL compatibility mode, so they do not require a local MySQL
+server.
+
+```powershell
+.\mvnw.cmd test
+```
+
+On macOS/Linux:
+
+```bash
+./mvnw test
+```
+
+The GitHub Actions workflow also runs the Maven test suite on Java 11 for pushes
+to `main` and pull requests.
+
+## Notes
+
+- Passwords are accepted for create/update/login operations but are hidden from
+ JSON responses.
+- This project intentionally keeps the original route naming style to avoid
+ breaking existing clients.
+- Authentication is educational only. It stores a login status and plain
+ password values, so it should not be used as-is for production security.
diff --git a/mvnw b/mvnw
old mode 100644
new mode 100755
diff --git a/pom.xml b/pom.xml
index 7e0c5a2..2a36394 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.boot
spring-boot-starter-parent
- 2.5.2
+ 2.7.18
com.hemant.db
@@ -35,14 +35,19 @@
test
- mysql
- mysql-connector-java
- 8.0.25
+ com.mysql
+ mysql-connector-j
+ runtime
org.springframework.boot
spring-boot-starter-validation
+
+ com.h2database
+ h2
+ test
+
diff --git a/src/main/java/com/hemant/db/exception/ApiError.java b/src/main/java/com/hemant/db/exception/ApiError.java
new file mode 100644
index 0000000..eb822d9
--- /dev/null
+++ b/src/main/java/com/hemant/db/exception/ApiError.java
@@ -0,0 +1,43 @@
+package com.hemant.db.exception;
+
+import java.time.Instant;
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class ApiError {
+ private final Instant timestamp;
+ private final int status;
+ private final String error;
+ private final String message;
+ private final Map details;
+
+ public ApiError(int status, String error, String message, Map details) {
+ this.timestamp = Instant.now();
+ this.status = status;
+ this.error = error;
+ this.message = message;
+ this.details = details;
+ }
+
+ public Instant getTimestamp() {
+ return timestamp;
+ }
+
+ public int getStatus() {
+ return status;
+ }
+
+ public String getError() {
+ return error;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public Map getDetails() {
+ return details;
+ }
+}
diff --git a/src/main/java/com/hemant/db/exception/BadRequestException.java b/src/main/java/com/hemant/db/exception/BadRequestException.java
new file mode 100644
index 0000000..f4926f0
--- /dev/null
+++ b/src/main/java/com/hemant/db/exception/BadRequestException.java
@@ -0,0 +1,7 @@
+package com.hemant.db.exception;
+
+public class BadRequestException extends RuntimeException {
+ public BadRequestException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/com/hemant/db/exception/DuplicateResourceException.java b/src/main/java/com/hemant/db/exception/DuplicateResourceException.java
new file mode 100644
index 0000000..71233d0
--- /dev/null
+++ b/src/main/java/com/hemant/db/exception/DuplicateResourceException.java
@@ -0,0 +1,7 @@
+package com.hemant.db.exception;
+
+public class DuplicateResourceException extends RuntimeException {
+ public DuplicateResourceException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/com/hemant/db/exception/GlobalExceptionHandler.java b/src/main/java/com/hemant/db/exception/GlobalExceptionHandler.java
new file mode 100644
index 0000000..89334d3
--- /dev/null
+++ b/src/main/java/com/hemant/db/exception/GlobalExceptionHandler.java
@@ -0,0 +1,64 @@
+package com.hemant.db.exception;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import javax.validation.ConstraintViolationException;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.FieldError;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.MissingServletRequestParameterException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+@RestControllerAdvice
+public class GlobalExceptionHandler {
+ @ExceptionHandler(ResourceNotFoundException.class)
+ public ResponseEntity handleResourceNotFound(ResourceNotFoundException ex) {
+ return buildResponse(HttpStatus.NOT_FOUND, ex.getMessage(), null);
+ }
+
+ @ExceptionHandler(DuplicateResourceException.class)
+ public ResponseEntity handleDuplicateResource(DuplicateResourceException ex) {
+ return buildResponse(HttpStatus.CONFLICT, ex.getMessage(), null);
+ }
+
+ @ExceptionHandler(BadRequestException.class)
+ public ResponseEntity handleBadRequest(BadRequestException ex) {
+ return buildResponse(HttpStatus.BAD_REQUEST, ex.getMessage(), null);
+ }
+
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ public ResponseEntity handleValidationExceptions(MethodArgumentNotValidException ex) {
+ Map details = new HashMap<>();
+ ex.getBindingResult().getAllErrors().forEach(error -> {
+ String fieldName = ((FieldError) error).getField();
+ String errorMessage = error.getDefaultMessage();
+ details.put(fieldName, errorMessage);
+ });
+ return buildResponse(HttpStatus.BAD_REQUEST, "Validation failed", details);
+ }
+
+ @ExceptionHandler(ConstraintViolationException.class)
+ public ResponseEntity handleConstraintViolation(ConstraintViolationException ex) {
+ Map details = ex.getConstraintViolations().stream()
+ .collect(Collectors.toMap(
+ violation -> violation.getPropertyPath().toString(),
+ violation -> violation.getMessage(),
+ (left, right) -> left));
+ return buildResponse(HttpStatus.BAD_REQUEST, "Validation failed", details);
+ }
+
+ @ExceptionHandler(MissingServletRequestParameterException.class)
+ public ResponseEntity handleMissingParameter(MissingServletRequestParameterException ex) {
+ return buildResponse(HttpStatus.BAD_REQUEST, ex.getParameterName() + " parameter is required", null);
+ }
+
+ private ResponseEntity buildResponse(HttpStatus status, String message, Map details) {
+ ApiError error = new ApiError(status.value(), status.getReasonPhrase(), message, details);
+ return new ResponseEntity<>(error, status);
+ }
+}
diff --git a/src/main/java/com/hemant/db/exception/ResourceNotFoundException.java b/src/main/java/com/hemant/db/exception/ResourceNotFoundException.java
new file mode 100644
index 0000000..93c7708
--- /dev/null
+++ b/src/main/java/com/hemant/db/exception/ResourceNotFoundException.java
@@ -0,0 +1,11 @@
+package com.hemant.db.exception;
+
+public class ResourceNotFoundException extends RuntimeException {
+ public ResourceNotFoundException(String resourceName, Integer id) {
+ super(resourceName + " not found with id " + id);
+ }
+
+ public ResourceNotFoundException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/com/hemant/db/model/Address.java b/src/main/java/com/hemant/db/model/Address.java
index fc1fe7a..adf24a5 100644
--- a/src/main/java/com/hemant/db/model/Address.java
+++ b/src/main/java/com/hemant/db/model/Address.java
@@ -5,7 +5,6 @@
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.validation.constraints.*;
-import com.hemant.db.validators.IsInteger;
@Entity
public class Address {
@@ -27,11 +26,9 @@ public class Address {
private String state;
@Min(value = 100000)
@Max(value = 999999)
- @IsInteger
@NotNull
@Column(name = "PIN")
private Integer pin;
- @IsInteger
@Column(name = "Emp_ID")
private Integer empId;
@NotBlank
diff --git a/src/main/java/com/hemant/db/model/Department.java b/src/main/java/com/hemant/db/model/Department.java
index b2ea448..30738d8 100644
--- a/src/main/java/com/hemant/db/model/Department.java
+++ b/src/main/java/com/hemant/db/model/Department.java
@@ -5,7 +5,6 @@
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.validation.constraints.*;
-import com.hemant.db.validators.IsInteger;
@Entity
public class Department {
@@ -20,7 +19,6 @@ public class Department {
@Column(name = "Address")
private String address;
@NotNull
- @IsInteger
@Max(value = 200)
@Column(name = "Floor")
private Integer floor;
@@ -54,19 +52,19 @@ public void setName(String name) {
this.name = name;
}
- public String getaddress() {
+ public String getAddress() {
return address;
}
- public void setaddress(String address) {
+ public void setAddress(String address) {
this.address = address;
}
- public Integer getfloor() {
+ public Integer getFloor() {
return floor;
}
- public void setfloor(Integer floor) {
+ public void setFloor(Integer floor) {
this.floor = floor;
}
diff --git a/src/main/java/com/hemant/db/model/Employee.java b/src/main/java/com/hemant/db/model/Employee.java
index e2d7e05..e1aeb9e 100644
--- a/src/main/java/com/hemant/db/model/Employee.java
+++ b/src/main/java/com/hemant/db/model/Employee.java
@@ -5,8 +5,8 @@
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.validation.constraints.*;
-import com.hemant.db.validators.IsInteger;
-import com.hemant.db.validators.IsLong;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
@Entity
public class Employee {
@@ -25,11 +25,9 @@ public class Employee {
@Column(name = "Salary")
private Integer salary;
@NotNull
- @IsInteger
@Column(name = "Dep_ID")
private Integer depId;
@NotNull
- @IsLong
@Min(value = (long)7e9)
@Max(value = (long)1e10 - 1)
@Column(name = "Mobile")
@@ -39,6 +37,7 @@ public class Employee {
@Column(name = "EMail")
private String email;
@NotNull
+ @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
@Column(name = "Password")
private String password;
@Column(name = "Status")
diff --git a/src/main/java/com/hemant/db/model/Profile.java b/src/main/java/com/hemant/db/model/Profile.java
index e97202a..df17483 100644
--- a/src/main/java/com/hemant/db/model/Profile.java
+++ b/src/main/java/com/hemant/db/model/Profile.java
@@ -5,7 +5,6 @@
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.validation.constraints.*;
-import com.hemant.db.validators.IsInteger;
@Entity
public class Profile {
@@ -23,7 +22,6 @@ public class Profile {
@NotBlank
@Column(name = "Hobbies")
private String hobbies;
- @IsInteger
@NotNull
@Column(name = "Emp_ID")
private Integer empId;
@@ -77,6 +75,10 @@ public Integer getEmpId() {
return empId;
}
+ public void setEmpId(Integer empId) {
+ this.empId = empId;
+ }
+
public void setDepId(Integer empId) {
this.empId = empId;
}
diff --git a/src/main/java/com/hemant/db/model/Response.java b/src/main/java/com/hemant/db/model/Response.java
index 181ff49..1375d1a 100644
--- a/src/main/java/com/hemant/db/model/Response.java
+++ b/src/main/java/com/hemant/db/model/Response.java
@@ -2,6 +2,9 @@
import java.io.Serializable;
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
public class Response implements Serializable {
private static final long serialVersionUID = 1L;
public boolean status;
diff --git a/src/main/java/com/hemant/db/repository/AddressRepository.java b/src/main/java/com/hemant/db/repository/AddressRepository.java
index 7f5b7a1..eca3c45 100644
--- a/src/main/java/com/hemant/db/repository/AddressRepository.java
+++ b/src/main/java/com/hemant/db/repository/AddressRepository.java
@@ -4,24 +4,13 @@
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Modifying;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
public interface AddressRepository extends JpaRepository {
- public List findByCity(@Param("city") String city);
+ List findByCity(String city);
- public List findByState(@Param("state") String state);
+ List findByState(String state);
- public Optional findById(@Param("Id") Integer Id);
+ Optional findById(Integer id);
- @Query("select a from Address a where a.empId = :empId")
- public List findByEmp(@Param("empId") Integer empId);
-
- @Modifying
- @Query("update Address a set a.address1 = :address1, a.address2 = :address2, a.city = :city, a.state = :state, a.pin = :pin where a.Id = :Id")
- public List updateAddress(@Param("Id") Integer Id, @Param("address1") String address1, @Param("address2") String address2, @Param("city") String city, @Param("state") String state, @Param("pin") Integer pin);
-
- @Modifying
- public void deleteById(@Param("Id") Integer Id);
+ List findByEmpId(Integer empId);
}
diff --git a/src/main/java/com/hemant/db/repository/DepartmentRepository.java b/src/main/java/com/hemant/db/repository/DepartmentRepository.java
index 899a1a4..bfde5f0 100644
--- a/src/main/java/com/hemant/db/repository/DepartmentRepository.java
+++ b/src/main/java/com/hemant/db/repository/DepartmentRepository.java
@@ -4,25 +4,11 @@
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Modifying;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
public interface DepartmentRepository extends JpaRepository {
- public List findByName(@Param("name") String Name);
+ List findByName(String name);
- public List findByAddress(@Param("address") String Address);
+ List findByAddress(String address);
- public Optional findById(@Param("Id") Integer Id);
-
- @Modifying
- @Query("update Department d set d.floor = :floor where d.Id = :Id")
- public List updateFloor(@Param("Id") Integer Id, @Param("floor") Integer floor);
-
- @Modifying
- @Query("update Department d set d.address = :address where d.Id = :Id")
- public List updateAddress(@Param("Id") Integer Id, @Param("address") String address);
-
- @Modifying
- public void deleteById(@Param("Id") Integer Id);
+ Optional findById(Integer id);
}
diff --git a/src/main/java/com/hemant/db/repository/EmployeeRepository.java b/src/main/java/com/hemant/db/repository/EmployeeRepository.java
index 851d26b..ac8938d 100644
--- a/src/main/java/com/hemant/db/repository/EmployeeRepository.java
+++ b/src/main/java/com/hemant/db/repository/EmployeeRepository.java
@@ -4,34 +4,15 @@
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Modifying;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
public interface EmployeeRepository extends JpaRepository {
- @Query("select e from Employee e where e.accountStatus = 'Activated'")
- public List findAll();
+ List findByAccountStatus(String accountStatus);
- public List findByName(@Param("name") String Name);
+ List findByName(String name);
- public List findByDesignation(@Param("designation") String Designation);
+ List findByDesignation(String designation);
- public Optional findById(@Param("Id") Integer Id);
-
- @Modifying
- @Query("update Employee e set e.designation = :designation where e.Id = :Id")
- public List updateDesignation(@Param("Id") Integer Id, @Param("designation") String designation);
-
- @Modifying
- @Query("update Employee e set e.mobile = :mobile where e.Id = :Id")
- public List updateMobile(@Param("Id") Integer Id, @Param("mobile") long mobile);
-
- @Modifying
- @Query("update Employee e set e.password = :password where e.Id = :Id")
- public List updatePassword(@Param("Id") Integer Id, @Param("password") String password);
-
- public Employee findByEmail(@Param("email") String email);
-
- @Modifying
- public void deleteById(@Param("Id") Integer Id);
+ Optional findById(Integer id);
+
+ Optional findByEmail(String email);
}
diff --git a/src/main/java/com/hemant/db/repository/ProfileRepository.java b/src/main/java/com/hemant/db/repository/ProfileRepository.java
index e8e8a75..8a2e429 100644
--- a/src/main/java/com/hemant/db/repository/ProfileRepository.java
+++ b/src/main/java/com/hemant/db/repository/ProfileRepository.java
@@ -4,21 +4,11 @@
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Modifying;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
public interface ProfileRepository extends JpaRepository {
- public List findByGender(@Param("gender") String Gender);
+ List findByGender(String gender);
- public List findByHobbies(@Param("hobbies") String Hobbies);
+ List findByHobbies(String hobbies);
- public Optional findById(@Param("Id") Integer Id);
-
- @Modifying
- @Query("update Profile p set p.hobbies = :hobbies where p.Id = :Id")
- public List updateHobbies(@Param("Id") Integer Id, @Param("hobbies") String hobbies);
-
- @Modifying
- public void deleteById(@Param("Id") Integer Id);
+ Optional findById(Integer id);
}
diff --git a/src/main/java/com/hemant/db/resource/AddressResource.java b/src/main/java/com/hemant/db/resource/AddressResource.java
index e0fbfd4..db29fc2 100644
--- a/src/main/java/com/hemant/db/resource/AddressResource.java
+++ b/src/main/java/com/hemant/db/resource/AddressResource.java
@@ -1,73 +1,67 @@
package com.hemant.db.resource;
-import com.hemant.db.model.Address;
-import com.hemant.db.repository.AddressRepository;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.MethodArgumentNotValidException;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.validation.FieldError;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
+
import javax.validation.Valid;
+import javax.validation.constraints.NotBlank;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.hemant.db.model.Address;
+import com.hemant.db.service.AddressService;
+@Validated
@RestController
@RequestMapping(value = "/rest/Address")
public class AddressResource {
-
- @Autowired
- AddressRepository AddressRepository;
+ private final AddressService addressService;
+
+ public AddressResource(AddressService addressService) {
+ this.addressService = addressService;
+ }
@GetMapping(value = "/all")
public List getAll() {
- return AddressRepository.findAll();
+ return addressService.getAllAddresses();
}
@PostMapping(value = "/insert")
- public ResponseEntity> persist(@Valid @RequestBody final Address Address) {
- AddressRepository.save(Address);
- return ResponseEntity.ok(AddressRepository.findByEmp(Address.getEmpId()));
- }
-
+ public ResponseEntity> persist(@Valid @RequestBody final Address address) {
+ return ResponseEntity.ok(addressService.createAddress(address));
+ }
+
@GetMapping(value = "/findbycity")
- public List fetchDataByCity(@Valid @RequestParam("city") String city) {
- return AddressRepository.findByCity(city);
+ public List fetchDataByCity(@RequestParam("city") @NotBlank String city) {
+ return addressService.findByCity(city);
}
-
+
@GetMapping(value = "/findbystate")
- public List fetchDataByState(@Valid @RequestParam("state") String state) {
- return AddressRepository.findByState(state);
+ public List fetchDataByState(@RequestParam("state") @NotBlank String state) {
+ return addressService.findByState(state);
}
-
+
@PostMapping("/updateaddress")
- public ResponseEntity updateAddress(@RequestParam("Id") Integer Id, @Valid @RequestParam("address1") String address1, @Valid @RequestParam("address2") String address2, @Valid @RequestParam("city") String city, @Valid @RequestParam("state") String state, @Valid @RequestParam("pin") Integer pin) {
- Address a = AddressRepository.findById(Id).get();
- a.setAddress1(address1); a.setAddress2(address2); a.setCity(city); a.setState(state); a.setPIN(pin);
- AddressRepository.save(a);
- return ResponseEntity.ok(a);
+ public ResponseEntity updateAddress(
+ @RequestParam("Id") Integer id,
+ @RequestParam("address1") @NotBlank String address1,
+ @RequestParam("address2") @NotBlank String address2,
+ @RequestParam("city") @NotBlank String city,
+ @RequestParam("state") @NotBlank String state,
+ @RequestParam("pin") Integer pin) {
+ return ResponseEntity.ok(addressService.updateAddress(id, address1, address2, city, state, pin));
}
-
+
@DeleteMapping("/delete")
- public ResponseEntity deleteUser(@RequestParam("Id") Integer Id){
- try {
- AddressRepository.deleteById(Id);
- return ResponseEntity.ok("Success");
- } catch(Exception e) {
- return new ResponseEntity<>("Error: " + e.getMessage(), HttpStatus.BAD_REQUEST);
- }
- }
-
- @ResponseStatus(HttpStatus.BAD_REQUEST)
- @ExceptionHandler(MethodArgumentNotValidException.class)
- public Map handleValidationExceptions(MethodArgumentNotValidException ex) {
- Map errors = new HashMap<>();
- ex.getBindingResult().getAllErrors().forEach((error) -> {
- String fieldName = ((FieldError) error).getField();
- String errorMessage = error.getDefaultMessage();
- errors.put(fieldName, errorMessage);
- });
- return errors;
+ public ResponseEntity deleteUser(@RequestParam("Id") Integer id) {
+ addressService.deleteAddress(id);
+ return ResponseEntity.ok("Success");
}
}
diff --git a/src/main/java/com/hemant/db/resource/DepartmentResource.java b/src/main/java/com/hemant/db/resource/DepartmentResource.java
index 45c8151..32e6066 100644
--- a/src/main/java/com/hemant/db/resource/DepartmentResource.java
+++ b/src/main/java/com/hemant/db/resource/DepartmentResource.java
@@ -1,81 +1,70 @@
package com.hemant.db.resource;
-import com.hemant.db.model.Department;
-import com.hemant.db.repository.DepartmentRepository;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.MethodArgumentNotValidException;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.validation.FieldError;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
+
import javax.validation.Valid;
+import javax.validation.constraints.NotBlank;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.hemant.db.model.Department;
+import com.hemant.db.service.DepartmentService;
+@Validated
@RestController
@RequestMapping(value = "/rest/Department")
public class DepartmentResource {
+ private final DepartmentService departmentService;
- @Autowired
- DepartmentRepository DepartmentRepository;
+ public DepartmentResource(DepartmentService departmentService) {
+ this.departmentService = departmentService;
+ }
@GetMapping(value = "/all")
public List getAll() {
- return DepartmentRepository.findAll();
+ return departmentService.getAllDepartments();
}
@PostMapping(value = "/insert")
- public ResponseEntity<@Valid Department> persist(@Valid @RequestBody final Department Department) {
- DepartmentRepository.save(Department);
- return ResponseEntity.ok(Department);
+ public ResponseEntity persist(@Valid @RequestBody final Department department) {
+ return ResponseEntity.ok(departmentService.createDepartment(department));
}
-
+
@GetMapping("/findbyname")
- public List fetchDataByName(@Valid @RequestParam("name") String name){
- return DepartmentRepository.findByName(name);
+ public List fetchDataByName(@RequestParam("name") @NotBlank String name) {
+ return departmentService.findByName(name);
}
-
+
@GetMapping("/findbyaddress")
- public List fetchDataByAddress(@Valid @RequestParam("address") String address){
- return DepartmentRepository.findByAddress(address);
+ public List fetchDataByAddress(@RequestParam("address") @NotBlank String address) {
+ return departmentService.findByAddress(address);
}
-
+
@PostMapping("/updatefloor")
- public ResponseEntity updateFloor(@RequestParam("Id") Integer Id, @Valid @RequestParam("floor") Integer floor) {
- Department d = DepartmentRepository.findById(Id).get();
- d.setfloor(floor);
- DepartmentRepository.save(d);
- return ResponseEntity.ok(d);
+ public ResponseEntity updateFloor(
+ @RequestParam("Id") Integer id,
+ @RequestParam("floor") Integer floor) {
+ return ResponseEntity.ok(departmentService.updateFloor(id, floor));
}
-
+
@PostMapping("/updateaddress")
- public ResponseEntity updateAddress(@RequestParam("Id") Integer Id, @Valid @RequestParam("address") String address) {
- Department d = DepartmentRepository.findById(Id).get();
- d.setaddress(address);
- DepartmentRepository.save(d);
- return ResponseEntity.ok(d);
+ public ResponseEntity updateAddress(
+ @RequestParam("Id") Integer id,
+ @RequestParam("address") @NotBlank String address) {
+ return ResponseEntity.ok(departmentService.updateAddress(id, address));
}
-
+
@DeleteMapping("/delete")
- public ResponseEntity deleteDepartment(@RequestParam("Id") Integer Id){
- try {
- DepartmentRepository.deleteById(Id);
- return ResponseEntity.ok("Success");
- } catch(Exception e) {
- return new ResponseEntity<>("Error: " + e.getMessage(), HttpStatus.BAD_REQUEST);
- }
- }
-
- @ResponseStatus(HttpStatus.BAD_REQUEST)
- @ExceptionHandler(MethodArgumentNotValidException.class)
- public Map handleValidationExceptions(MethodArgumentNotValidException ex) {
- Map errors = new HashMap<>();
- ex.getBindingResult().getAllErrors().forEach((error) -> {
- String fieldName = ((FieldError) error).getField();
- String errorMessage = error.getDefaultMessage();
- errors.put(fieldName, errorMessage);
- });
- return errors;
+ public ResponseEntity deleteDepartment(@RequestParam("Id") Integer id) {
+ departmentService.deleteDepartment(id);
+ return ResponseEntity.ok("Success");
}
}
diff --git a/src/main/java/com/hemant/db/resource/EmployeeResource.java b/src/main/java/com/hemant/db/resource/EmployeeResource.java
index 0dd400b..1479143 100644
--- a/src/main/java/com/hemant/db/resource/EmployeeResource.java
+++ b/src/main/java/com/hemant/db/resource/EmployeeResource.java
@@ -1,101 +1,76 @@
package com.hemant.db.resource;
-import com.hemant.db.model.Employee;
-import com.hemant.db.repository.EmployeeRepository;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.MethodArgumentNotValidException;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.validation.FieldError;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+
import javax.validation.Valid;
+import javax.validation.constraints.NotBlank;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.hemant.db.model.Employee;
+import com.hemant.db.service.EmployeeService;
+@Validated
@RestController
@RequestMapping(value = "/rest/Employee")
public class EmployeeResource {
+ private final EmployeeService employeeService;
- @Autowired
- EmployeeRepository EmployeeRepository;
+ public EmployeeResource(EmployeeService employeeService) {
+ this.employeeService = employeeService;
+ }
@GetMapping(value = "/all")
public List getAll() {
- return EmployeeRepository.findAll();
+ return employeeService.getAllEmployees();
}
@PostMapping(value = "/insert")
- public ResponseEntity<@Valid Employee> persist(@Valid @RequestBody final Employee Employee) {
- try {
- EmployeeRepository.save(Employee);
- return ResponseEntity.ok(Employee);
- } catch(Exception e) {
- Employee E = EmployeeRepository.findByEmail(Employee.getEmail());
- E.setAccountStatus("Activated");
- EmployeeRepository.save(E);
- return ResponseEntity.ok(E);
- }
- }
-
+ public ResponseEntity persist(@Valid @RequestBody final Employee employee) {
+ return ResponseEntity.ok(employeeService.createEmployee(employee));
+ }
+
@GetMapping("/findbyname")
- public List fetchDataByName(@Valid @RequestParam("name") String name){
- return EmployeeRepository.findByName(name);
+ public List fetchDataByName(@RequestParam("name") @NotBlank String name) {
+ return employeeService.findByName(name);
}
-
+
@GetMapping("/findbydesignation")
- public List fetchDataByDesignation(@Valid @RequestParam("designation") String designation){
- return EmployeeRepository.findByDesignation(designation);
+ public List fetchDataByDesignation(@RequestParam("designation") @NotBlank String designation) {
+ return employeeService.findByDesignation(designation);
}
-
+
@PostMapping("/updatedesignation")
- public ResponseEntity updateDesignation(@RequestParam("Id") Integer Id, @Valid @RequestParam("designation") String designation) {
- Employee e = EmployeeRepository.findById(Id).get();
- e.setDesignation(designation);
- EmployeeRepository.save(e);
- return ResponseEntity.ok(e);
+ public ResponseEntity updateDesignation(
+ @RequestParam("Id") Integer id,
+ @RequestParam("designation") @NotBlank String designation) {
+ return ResponseEntity.ok(employeeService.updateDesignation(id, designation));
}
-
+
@PostMapping("/updatemobile")
- public ResponseEntity updateMobile(@RequestParam("Id") Integer Id, @Valid @RequestParam("mobile") long mobile) {
- Employee e = EmployeeRepository.findById(Id).get();
- e.setMobile(mobile);
- EmployeeRepository.save(e);
- return ResponseEntity.ok(e);
+ public ResponseEntity updateMobile(
+ @RequestParam("Id") Integer id,
+ @RequestParam("mobile") long mobile) {
+ return ResponseEntity.ok(employeeService.updateMobile(id, mobile));
}
-
+
@PostMapping("/updatepassword")
- public ResponseEntity updatePassword(@RequestParam("Id") Integer Id, @Valid @RequestParam("password") String password) {
- Employee e = EmployeeRepository.findById(Id).get();
- e.setPassword(password);
- EmployeeRepository.save(e);
- return ResponseEntity.ok(e);
+ public ResponseEntity updatePassword(
+ @RequestParam("Id") Integer id,
+ @RequestParam("password") @NotBlank String password) {
+ return ResponseEntity.ok(employeeService.updatePassword(id, password));
}
-
+
@DeleteMapping("/delete")
- public ResponseEntity deleteUser(@RequestParam("Id") Integer Id){
- Optional o = EmployeeRepository.findById(Id);
- if(o.isPresent()) {
- Employee e = o.get();
- e.setAccountStatus("Deactivated");
- EmployeeRepository.save(e);
- return ResponseEntity.ok(e);
- }
- else {
- return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
- }
- }
-
- @ResponseStatus(HttpStatus.BAD_REQUEST)
- @ExceptionHandler(MethodArgumentNotValidException.class)
- public Map handleValidationExceptions(MethodArgumentNotValidException ex) {
- Map errors = new HashMap<>();
- ex.getBindingResult().getAllErrors().forEach((error) -> {
- String fieldName = ((FieldError) error).getField();
- String errorMessage = error.getDefaultMessage();
- errors.put(fieldName, errorMessage);
- });
- return errors;
+ public ResponseEntity deleteUser(@RequestParam("Id") Integer id) {
+ return ResponseEntity.ok(employeeService.deactivateEmployee(id));
}
}
diff --git a/src/main/java/com/hemant/db/resource/LoginResource.java b/src/main/java/com/hemant/db/resource/LoginResource.java
index 7710f89..d61d78d 100644
--- a/src/main/java/com/hemant/db/resource/LoginResource.java
+++ b/src/main/java/com/hemant/db/resource/LoginResource.java
@@ -1,89 +1,46 @@
package com.hemant.db.resource;
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotBlank;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
import com.hemant.db.model.Employee;
-import com.hemant.db.repository.EmployeeRepository;
import com.hemant.db.model.Response;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.MethodArgumentNotValidException;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.validation.FieldError;
-import java.util.HashMap;
-import java.util.Map;
-import javax.validation.Valid;
+import com.hemant.db.service.LoginService;
+import com.hemant.db.service.LoginService.LoginResult;
+@Validated
@RestController
@RequestMapping(value = "/rest/Login")
public class LoginResource {
-
- @Autowired
- EmployeeRepository EmployeeRepository;
-
- @GetMapping("/findbyemail")
- public Employee fetchByEmail(@Valid @RequestParam("email") String email) {
- return EmployeeRepository.findByEmail(email);
- }
-
- @PostMapping("/login")
- public ResponseEntity login(@Valid @RequestParam("email") String email, @Valid @RequestParam("password") String password) {
- Response r = new Response();
- Employee e = EmployeeRepository.findByEmail(email);
- try {
- String correctPassword = e.getPassword();
- if(e.getStatus().equals("Logged In")) {
- r.setStatus(false);
- r.setEmployee(e);
- return new ResponseEntity<>(r, HttpStatus.FORBIDDEN);
- }
- else {
- if(password.equals(correctPassword)) {
- e.setStatus("Logged In");
- EmployeeRepository.save(e);
- r.setStatus(true);
- r.setEmployee(e);
- return new ResponseEntity<>(r, HttpStatus.OK);
- }
- else {
- r.setStatus(false);
- r.setMessage("Incorrect Email or Password");
- return new ResponseEntity<>(r, HttpStatus.BAD_REQUEST);
- }
- }
- } catch(Exception e1) {
- r.setStatus(false);
- r.setMessage("Something went wrong " + e1.getMessage());
- return new ResponseEntity<>(r, HttpStatus.BAD_REQUEST);
- }
-
- }
-
- @PostMapping("/logout")
- public ResponseEntity logout(@Valid @RequestParam("email") String email) {
- Employee e = EmployeeRepository.findByEmail(email);
- try {
- if(e.getStatus().equals("Logged In")) {
- e.setStatus("Logged Out");
- EmployeeRepository.save(e);
- return new ResponseEntity<>("Logged Out", HttpStatus.OK);
- }
- else {
- return new ResponseEntity<>("Error: User Already logged out", HttpStatus.FORBIDDEN);
- }
- } catch(Exception e1) {
- return new ResponseEntity<>("Error: " + e1.getMessage(), HttpStatus.BAD_REQUEST);
- }
- }
-
- @ResponseStatus(HttpStatus.BAD_REQUEST)
- @ExceptionHandler(MethodArgumentNotValidException.class)
- public Map handleValidationExceptions(MethodArgumentNotValidException ex) {
- Map errors = new HashMap<>();
- ex.getBindingResult().getAllErrors().forEach((error) -> {
- String fieldName = ((FieldError) error).getField();
- String errorMessage = error.getDefaultMessage();
- errors.put(fieldName, errorMessage);
- });
- return errors;
+ private final LoginService loginService;
+
+ public LoginResource(LoginService loginService) {
+ this.loginService = loginService;
+ }
+
+ @GetMapping("/findbyemail")
+ public Employee fetchByEmail(@RequestParam("email") @Email String email) {
+ return loginService.findByEmail(email);
+ }
+
+ @PostMapping("/login")
+ public ResponseEntity login(
+ @RequestParam("email") @Email String email,
+ @RequestParam("password") @NotBlank String password) {
+ LoginResult result = loginService.login(email, password);
+ return new ResponseEntity<>(result.getResponse(), result.getStatus());
+ }
+
+ @PostMapping("/logout")
+ public ResponseEntity logout(@RequestParam("email") @Email String email) {
+ return ResponseEntity.ok(loginService.logout(email));
}
}
diff --git a/src/main/java/com/hemant/db/resource/ProfileResource.java b/src/main/java/com/hemant/db/resource/ProfileResource.java
index 34194ca..2297f36 100644
--- a/src/main/java/com/hemant/db/resource/ProfileResource.java
+++ b/src/main/java/com/hemant/db/resource/ProfileResource.java
@@ -1,77 +1,63 @@
package com.hemant.db.resource;
-import com.hemant.db.model.Profile;
-import com.hemant.db.repository.ProfileRepository;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.MethodArgumentNotValidException;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.validation.FieldError;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
+
import javax.validation.Valid;
+import javax.validation.constraints.NotBlank;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.hemant.db.model.Profile;
+import com.hemant.db.service.ProfileService;
+@Validated
@RestController
@RequestMapping(value = "/rest/Profile")
public class ProfileResource {
+ private final ProfileService profileService;
- @Autowired
- ProfileRepository ProfileRepository;
+ public ProfileResource(ProfileService profileService) {
+ this.profileService = profileService;
+ }
@GetMapping(value = "/all")
public List getAll() {
- return ProfileRepository.findAll();
+ return profileService.getAllProfiles();
}
@PostMapping(value = "/insert")
- public ResponseEntity<@Valid Profile> persist(@Valid @RequestBody final Profile Profile) {
- try {
- ProfileRepository.save(Profile);
- return ResponseEntity.ok(Profile);
- } catch(Exception e) {
- return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
- }
+ public ResponseEntity persist(@Valid @RequestBody final Profile profile) {
+ return ResponseEntity.ok(profileService.createProfile(profile));
}
-
+
@GetMapping("/findbygender")
- public List fetchDataByGender(@Valid @RequestParam("gender") String gender){
- return ProfileRepository.findByGender(gender);
+ public List fetchDataByGender(@RequestParam("gender") @NotBlank String gender) {
+ return profileService.findByGender(gender);
}
-
+
@GetMapping("/findbyhobbies")
- public List fetchDataByHobbies(@Valid @RequestParam("hobbies") String hobbies){
- return ProfileRepository.findByHobbies(hobbies);
+ public List fetchDataByHobbies(@RequestParam("hobbies") @NotBlank String hobbies) {
+ return profileService.findByHobbies(hobbies);
}
-
+
@PostMapping("/updatehobbies")
- public ResponseEntity updateHobbies(@RequestParam("Id") Integer Id, @Valid @RequestParam("hobbies") String hobbies) {
- Profile p = ProfileRepository.findById(Id).get();
- p.setHobbies(hobbies);
- ProfileRepository.save(p);
- return ResponseEntity.ok(p);
+ public ResponseEntity updateHobbies(
+ @RequestParam("Id") Integer id,
+ @RequestParam("hobbies") @NotBlank String hobbies) {
+ return ResponseEntity.ok(profileService.updateHobbies(id, hobbies));
}
-
+
@DeleteMapping("/delete")
- public ResponseEntity deleteProfile(@RequestParam("Id") Integer Id){
- try {
- ProfileRepository.deleteById(Id);
- return ResponseEntity.ok("Success");
- } catch(Exception e) {
- return new ResponseEntity<>("Error: " + e.getMessage(), HttpStatus.BAD_REQUEST);
- }
- }
-
- @ResponseStatus(HttpStatus.BAD_REQUEST)
- @ExceptionHandler(MethodArgumentNotValidException.class)
- public Map handleValidationExceptions(MethodArgumentNotValidException ex) {
- Map errors = new HashMap<>();
- ex.getBindingResult().getAllErrors().forEach((error) -> {
- String fieldName = ((FieldError) error).getField();
- String errorMessage = error.getDefaultMessage();
- errors.put(fieldName, errorMessage);
- });
- return errors;
+ public ResponseEntity deleteProfile(@RequestParam("Id") Integer id) {
+ profileService.deleteProfile(id);
+ return ResponseEntity.ok("Success");
}
}
diff --git a/src/main/java/com/hemant/db/service/AddressService.java b/src/main/java/com/hemant/db/service/AddressService.java
new file mode 100644
index 0000000..bba960f
--- /dev/null
+++ b/src/main/java/com/hemant/db/service/AddressService.java
@@ -0,0 +1,58 @@
+package com.hemant.db.service;
+
+import java.util.List;
+
+import javax.transaction.Transactional;
+
+import org.springframework.stereotype.Service;
+
+import com.hemant.db.exception.ResourceNotFoundException;
+import com.hemant.db.model.Address;
+import com.hemant.db.repository.AddressRepository;
+
+@Service
+@Transactional
+public class AddressService {
+ private final AddressRepository addressRepository;
+
+ public AddressService(AddressRepository addressRepository) {
+ this.addressRepository = addressRepository;
+ }
+
+ public List getAllAddresses() {
+ return addressRepository.findAll();
+ }
+
+ public List createAddress(Address address) {
+ addressRepository.save(address);
+ return addressRepository.findByEmpId(address.getEmpId());
+ }
+
+ public List findByCity(String city) {
+ return addressRepository.findByCity(city);
+ }
+
+ public List findByState(String state) {
+ return addressRepository.findByState(state);
+ }
+
+ public Address updateAddress(Integer id, String address1, String address2, String city, String state, Integer pin) {
+ Address address = findById(id);
+ address.setAddress1(address1);
+ address.setAddress2(address2);
+ address.setCity(city);
+ address.setState(state);
+ address.setPIN(pin);
+ return addressRepository.save(address);
+ }
+
+ public void deleteAddress(Integer id) {
+ Address address = findById(id);
+ addressRepository.delete(address);
+ }
+
+ private Address findById(Integer id) {
+ return addressRepository.findById(id)
+ .orElseThrow(() -> new ResourceNotFoundException("Address", id));
+ }
+}
diff --git a/src/main/java/com/hemant/db/service/DepartmentService.java b/src/main/java/com/hemant/db/service/DepartmentService.java
new file mode 100644
index 0000000..24b625d
--- /dev/null
+++ b/src/main/java/com/hemant/db/service/DepartmentService.java
@@ -0,0 +1,59 @@
+package com.hemant.db.service;
+
+import java.util.List;
+
+import javax.transaction.Transactional;
+
+import org.springframework.stereotype.Service;
+
+import com.hemant.db.exception.ResourceNotFoundException;
+import com.hemant.db.model.Department;
+import com.hemant.db.repository.DepartmentRepository;
+
+@Service
+@Transactional
+public class DepartmentService {
+ private final DepartmentRepository departmentRepository;
+
+ public DepartmentService(DepartmentRepository departmentRepository) {
+ this.departmentRepository = departmentRepository;
+ }
+
+ public List getAllDepartments() {
+ return departmentRepository.findAll();
+ }
+
+ public Department createDepartment(Department department) {
+ return departmentRepository.save(department);
+ }
+
+ public List findByName(String name) {
+ return departmentRepository.findByName(name);
+ }
+
+ public List findByAddress(String address) {
+ return departmentRepository.findByAddress(address);
+ }
+
+ public Department updateFloor(Integer id, Integer floor) {
+ Department department = findById(id);
+ department.setFloor(floor);
+ return departmentRepository.save(department);
+ }
+
+ public Department updateAddress(Integer id, String address) {
+ Department department = findById(id);
+ department.setAddress(address);
+ return departmentRepository.save(department);
+ }
+
+ public void deleteDepartment(Integer id) {
+ Department department = findById(id);
+ departmentRepository.delete(department);
+ }
+
+ private Department findById(Integer id) {
+ return departmentRepository.findById(id)
+ .orElseThrow(() -> new ResourceNotFoundException("Department", id));
+ }
+}
diff --git a/src/main/java/com/hemant/db/service/EmployeeService.java b/src/main/java/com/hemant/db/service/EmployeeService.java
new file mode 100644
index 0000000..d3e8eb2
--- /dev/null
+++ b/src/main/java/com/hemant/db/service/EmployeeService.java
@@ -0,0 +1,82 @@
+package com.hemant.db.service;
+
+import java.util.List;
+
+import javax.transaction.Transactional;
+
+import org.springframework.stereotype.Service;
+
+import com.hemant.db.exception.DuplicateResourceException;
+import com.hemant.db.exception.ResourceNotFoundException;
+import com.hemant.db.model.Employee;
+import com.hemant.db.repository.EmployeeRepository;
+
+@Service
+@Transactional
+public class EmployeeService {
+ private final EmployeeRepository employeeRepository;
+
+ public EmployeeService(EmployeeRepository employeeRepository) {
+ this.employeeRepository = employeeRepository;
+ }
+
+ public List getAllEmployees() {
+ return employeeRepository.findByAccountStatus("Activated");
+ }
+
+ public Employee createEmployee(Employee employee) {
+ return employeeRepository.findByEmail(employee.getEmail())
+ .map(existingEmployee -> reactivateOrRejectDuplicate(existingEmployee, employee.getEmail()))
+ .orElseGet(() -> employeeRepository.save(employee));
+ }
+
+ public List findByName(String name) {
+ return employeeRepository.findByName(name);
+ }
+
+ public List findByDesignation(String designation) {
+ return employeeRepository.findByDesignation(designation);
+ }
+
+ public Employee updateDesignation(Integer id, String designation) {
+ Employee employee = findById(id);
+ employee.setDesignation(designation);
+ return employeeRepository.save(employee);
+ }
+
+ public Employee updateMobile(Integer id, long mobile) {
+ Employee employee = findById(id);
+ employee.setMobile(mobile);
+ return employeeRepository.save(employee);
+ }
+
+ public Employee updatePassword(Integer id, String password) {
+ Employee employee = findById(id);
+ employee.setPassword(password);
+ return employeeRepository.save(employee);
+ }
+
+ public Employee deactivateEmployee(Integer id) {
+ Employee employee = findById(id);
+ employee.setAccountStatus("Deactivated");
+ return employeeRepository.save(employee);
+ }
+
+ public Employee findByEmail(String email) {
+ return employeeRepository.findByEmail(email)
+ .orElseThrow(() -> new ResourceNotFoundException("Employee not found with email " + email));
+ }
+
+ public Employee findById(Integer id) {
+ return employeeRepository.findById(id)
+ .orElseThrow(() -> new ResourceNotFoundException("Employee", id));
+ }
+
+ private Employee reactivateOrRejectDuplicate(Employee existingEmployee, String email) {
+ if ("Deactivated".equalsIgnoreCase(existingEmployee.getAccountStatus())) {
+ existingEmployee.setAccountStatus("Activated");
+ return employeeRepository.save(existingEmployee);
+ }
+ throw new DuplicateResourceException("Employee already exists with email " + email);
+ }
+}
diff --git a/src/main/java/com/hemant/db/service/LoginService.java b/src/main/java/com/hemant/db/service/LoginService.java
new file mode 100644
index 0000000..9ca363e
--- /dev/null
+++ b/src/main/java/com/hemant/db/service/LoginService.java
@@ -0,0 +1,84 @@
+package com.hemant.db.service;
+
+import javax.transaction.Transactional;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Service;
+
+import com.hemant.db.exception.BadRequestException;
+import com.hemant.db.exception.ResourceNotFoundException;
+import com.hemant.db.model.Employee;
+import com.hemant.db.model.Response;
+import com.hemant.db.repository.EmployeeRepository;
+
+@Service
+@Transactional
+public class LoginService {
+ private final EmployeeRepository employeeRepository;
+
+ public LoginService(EmployeeRepository employeeRepository) {
+ this.employeeRepository = employeeRepository;
+ }
+
+ public Employee findByEmail(String email) {
+ return employeeRepository.findByEmail(email)
+ .orElseThrow(() -> new ResourceNotFoundException("Employee not found with email " + email));
+ }
+
+ public LoginResult login(String email, String password) {
+ Employee employee = employeeRepository.findByEmail(email)
+ .orElseThrow(() -> new BadRequestException("Incorrect Email or Password"));
+
+ Response response = new Response();
+ response.setEmployee(employee);
+
+ if ("Logged In".equals(employee.getStatus())) {
+ response.setStatus(false);
+ response.setMessage("User is already logged in");
+ return new LoginResult(response, HttpStatus.FORBIDDEN);
+ }
+
+ if (!password.equals(employee.getPassword())) {
+ response.setStatus(false);
+ response.setMessage("Incorrect Email or Password");
+ response.setEmployee(null);
+ return new LoginResult(response, HttpStatus.BAD_REQUEST);
+ }
+
+ employee.setStatus("Logged In");
+ employeeRepository.save(employee);
+ response.setStatus(true);
+ response.setMessage("Logged In");
+ response.setEmployee(employee);
+ return new LoginResult(response, HttpStatus.OK);
+ }
+
+ public String logout(String email) {
+ Employee employee = findByEmail(email);
+ if (!"Logged In".equals(employee.getStatus())) {
+ throw new BadRequestException("User is already logged out");
+ }
+
+ employee.setStatus("Logged Out");
+ employeeRepository.save(employee);
+ return "Logged Out";
+ }
+
+ public static class LoginResult {
+ private final Response response;
+ private final HttpStatus status;
+
+ public LoginResult(Response response, HttpStatus status) {
+ this.response = response;
+ this.status = status;
+ }
+
+ public Response getResponse() {
+ return response;
+ }
+
+ public HttpStatus getStatus() {
+ return status;
+ }
+ }
+}
diff --git a/src/main/java/com/hemant/db/service/ProfileService.java b/src/main/java/com/hemant/db/service/ProfileService.java
new file mode 100644
index 0000000..32ea476
--- /dev/null
+++ b/src/main/java/com/hemant/db/service/ProfileService.java
@@ -0,0 +1,53 @@
+package com.hemant.db.service;
+
+import java.util.List;
+
+import javax.transaction.Transactional;
+
+import org.springframework.stereotype.Service;
+
+import com.hemant.db.exception.ResourceNotFoundException;
+import com.hemant.db.model.Profile;
+import com.hemant.db.repository.ProfileRepository;
+
+@Service
+@Transactional
+public class ProfileService {
+ private final ProfileRepository profileRepository;
+
+ public ProfileService(ProfileRepository profileRepository) {
+ this.profileRepository = profileRepository;
+ }
+
+ public List getAllProfiles() {
+ return profileRepository.findAll();
+ }
+
+ public Profile createProfile(Profile profile) {
+ return profileRepository.save(profile);
+ }
+
+ public List findByGender(String gender) {
+ return profileRepository.findByGender(gender);
+ }
+
+ public List findByHobbies(String hobbies) {
+ return profileRepository.findByHobbies(hobbies);
+ }
+
+ public Profile updateHobbies(Integer id, String hobbies) {
+ Profile profile = findById(id);
+ profile.setHobbies(hobbies);
+ return profileRepository.save(profile);
+ }
+
+ public void deleteProfile(Integer id) {
+ Profile profile = findById(id);
+ profileRepository.delete(profile);
+ }
+
+ private Profile findById(Integer id) {
+ return profileRepository.findById(id)
+ .orElseThrow(() -> new ResourceNotFoundException("Profile", id));
+ }
+}
diff --git a/src/main/java/com/hemant/db/validators/IntegerValidator.java b/src/main/java/com/hemant/db/validators/IntegerValidator.java
deleted file mode 100644
index 77b3eae..0000000
--- a/src/main/java/com/hemant/db/validators/IntegerValidator.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.hemant.db.validators;
-
-import javax.validation.ConstraintValidator;
-import javax.validation.ConstraintValidatorContext;
-
-public class IntegerValidator implements ConstraintValidator{
- public boolean isValid(Integer Id, ConstraintValidatorContext constraintValidatorContext) {
- if(Id instanceof Integer) {
- return true;
- } else {
- return false;
- }
- }
-}
diff --git a/src/main/java/com/hemant/db/validators/IsInteger.java b/src/main/java/com/hemant/db/validators/IsInteger.java
deleted file mode 100644
index 872e47c..0000000
--- a/src/main/java/com/hemant/db/validators/IsInteger.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.hemant.db.validators;
-
-import javax.validation.Constraint;
-import javax.validation.Payload;
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-@Documented
-@Constraint(validatedBy = IntegerValidator.class)
-@Target({FIELD, PARAMETER})
-@Retention(RUNTIME)
-public @interface IsInteger {
- String message() default "Should be an Integer";
- Class>[] groups() default {};
- Class extends Payload>[] payload() default {};
-}
diff --git a/src/main/java/com/hemant/db/validators/IsLong.java b/src/main/java/com/hemant/db/validators/IsLong.java
deleted file mode 100644
index 1791824..0000000
--- a/src/main/java/com/hemant/db/validators/IsLong.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.hemant.db.validators;
-
-import javax.validation.Constraint;
-import javax.validation.Payload;
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-@Documented
-@Constraint(validatedBy = LongValidator.class)
-@Target({FIELD, PARAMETER})
-@Retention(RUNTIME)
-public @interface IsLong {
- String message() default "Should be a Long Integer";
- Class>[] groups() default {};
- Class extends Payload>[] payload() default {};
-}
diff --git a/src/main/java/com/hemant/db/validators/LongValidator.java b/src/main/java/com/hemant/db/validators/LongValidator.java
deleted file mode 100644
index 84efeb4..0000000
--- a/src/main/java/com/hemant/db/validators/LongValidator.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.hemant.db.validators;
-
-import javax.validation.ConstraintValidator;
-import javax.validation.ConstraintValidatorContext;
-
-public class LongValidator implements ConstraintValidator {
- public boolean isValid(java.lang.Long Id, ConstraintValidatorContext constraintValidatorContext) {
- if(Id instanceof java.lang.Long) {
- return true;
- } else {
- return false;
- }
- }
-}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index cfb93a1..7fbb32a 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -1,10 +1,14 @@
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
- password: "" #your user
- url: jdbc:mysql://localhost:3306/Your_DB
- username: "" #your password
+ url: ${MYSQL_URL:jdbc:mysql://localhost:3306/employee_db}
+ username: ${MYSQL_USERNAME:root}
+ password: ${MYSQL_PASSWORD:}
jpa:
- hibernate.ddl-auto: update
+ hibernate:
+ ddl-auto: ${JPA_DDL_AUTO:update}
generate-ddl: true
- show-sql: true
+ show-sql: ${JPA_SHOW_SQL:true}
+ properties:
+ hibernate:
+ dialect: org.hibernate.dialect.MySQL8Dialect
diff --git a/src/test/java/com/hemant/db/resource/RestApiIntegrationTest.java b/src/test/java/com/hemant/db/resource/RestApiIntegrationTest.java
new file mode 100644
index 0000000..caa2e65
--- /dev/null
+++ b/src/test/java/com/hemant/db/resource/RestApiIntegrationTest.java
@@ -0,0 +1,298 @@
+package com.hemant.db.resource;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.hasSize;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.web.servlet.MockMvc;
+
+import com.hemant.db.model.Address;
+import com.hemant.db.model.Department;
+import com.hemant.db.model.Employee;
+import com.hemant.db.model.Profile;
+import com.hemant.db.repository.AddressRepository;
+import com.hemant.db.repository.DepartmentRepository;
+import com.hemant.db.repository.EmployeeRepository;
+import com.hemant.db.repository.ProfileRepository;
+
+@SpringBootTest
+@AutoConfigureMockMvc
+@ActiveProfiles("test")
+class RestApiIntegrationTest {
+ @Autowired
+ private MockMvc mockMvc;
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+
+ @Autowired
+ private DepartmentRepository departmentRepository;
+
+ @Autowired
+ private AddressRepository addressRepository;
+
+ @Autowired
+ private ProfileRepository profileRepository;
+
+ @BeforeEach
+ void cleanDatabase() {
+ addressRepository.deleteAll();
+ profileRepository.deleteAll();
+ employeeRepository.deleteAll();
+ departmentRepository.deleteAll();
+ }
+
+ @Test
+ void employeeCrudAndValidationErrorsUseSafeResponses() throws Exception {
+ mockMvc.perform(post("/rest/Employee/insert")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(employeeJson("employee@example.com")))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.email").value("employee@example.com"))
+ .andExpect(jsonPath("$.password").doesNotExist());
+
+ Employee employee = employeeRepository.findByEmail("employee@example.com").orElseThrow();
+
+ mockMvc.perform(get("/rest/Employee/all"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$", hasSize(1)))
+ .andExpect(jsonPath("$[0].email").value("employee@example.com"))
+ .andExpect(jsonPath("$[0].password").doesNotExist());
+
+ mockMvc.perform(get("/rest/Employee/findbyname").param("name", "Test Employee"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$[0].designation").value("Developer"));
+
+ mockMvc.perform(post("/rest/Employee/updatedesignation")
+ .param("Id", employee.getId().toString())
+ .param("designation", "Manager"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.designation").value("Manager"))
+ .andExpect(jsonPath("$.password").doesNotExist());
+
+ mockMvc.perform(delete("/rest/Employee/delete").param("Id", employee.getId().toString()))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.accountStatus").value("Deactivated"));
+
+ mockMvc.perform(post("/rest/Employee/updatemobile")
+ .param("Id", "999")
+ .param("mobile", "9876543210"))
+ .andExpect(status().isNotFound())
+ .andExpect(jsonPath("$.message", containsString("Employee not found with id 999")));
+
+ mockMvc.perform(post("/rest/Employee/insert")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content("{\"name\":\"Invalid\"}"))
+ .andExpect(status().isBadRequest())
+ .andExpect(jsonPath("$.message").value("Validation failed"))
+ .andExpect(jsonPath("$.details.email").exists());
+ }
+
+ @Test
+ void departmentAddressAndProfileFlowsWorkWithH2() throws Exception {
+ mockMvc.perform(post("/rest/Department/insert")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(departmentJson()))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.name").value("Engineering"));
+ Department department = departmentRepository.findByName("Engineering").get(0);
+
+ mockMvc.perform(post("/rest/Address/insert")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(addressJson(1)))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$[0].city").value("Bangalore"));
+ Address address = addressRepository.findByCity("Bangalore").get(0);
+
+ mockMvc.perform(post("/rest/Profile/insert")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(profileJson(1)))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.gender").value("Male"));
+ Profile profile = profileRepository.findByGender("Male").get(0);
+
+ mockMvc.perform(get("/rest/Department/findbyname").param("name", "Engineering"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$[0].address").value("Bangalore"));
+
+ mockMvc.perform(post("/rest/Department/updatefloor")
+ .param("Id", department.getId().toString())
+ .param("floor", "5"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.floor").value(5));
+
+ mockMvc.perform(get("/rest/Address/findbycity").param("city", "Bangalore"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$[0].pin").value(560001));
+
+ mockMvc.perform(post("/rest/Address/updateaddress")
+ .param("Id", address.getId().toString())
+ .param("address1", "Line 1")
+ .param("address2", "Line 2")
+ .param("city", "Mysore")
+ .param("state", "Karnataka")
+ .param("pin", "570001"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.city").value("Mysore"));
+
+ mockMvc.perform(get("/rest/Profile/findbygender").param("gender", "Male"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$[0].hobbies").value("Reading"));
+
+ mockMvc.perform(post("/rest/Profile/updatehobbies")
+ .param("Id", profile.getId().toString())
+ .param("hobbies", "Chess"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.hobbies").value("Chess"));
+
+ mockMvc.perform(delete("/rest/Profile/delete").param("Id", profile.getId().toString()))
+ .andExpect(status().isOk());
+ }
+
+ @Test
+ void loginAndLogoutReportExpectedStatusCodes() throws Exception {
+ employeeRepository.save(sampleEmployee("login@example.com"));
+
+ mockMvc.perform(post("/rest/Login/login")
+ .param("email", "login@example.com")
+ .param("password", "wrong"))
+ .andExpect(status().isBadRequest())
+ .andExpect(jsonPath("$.status").value(false))
+ .andExpect(jsonPath("$.employee").doesNotExist());
+
+ mockMvc.perform(post("/rest/Login/login")
+ .param("email", "login@example.com")
+ .param("password", "secret"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.status").value(true))
+ .andExpect(jsonPath("$.employee.email").value("login@example.com"))
+ .andExpect(jsonPath("$.employee.password").doesNotExist());
+
+ mockMvc.perform(post("/rest/Login/login")
+ .param("email", "login@example.com")
+ .param("password", "secret"))
+ .andExpect(status().isForbidden())
+ .andExpect(jsonPath("$.message", containsString("already logged in")));
+
+ mockMvc.perform(post("/rest/Login/logout").param("email", "login@example.com"))
+ .andExpect(status().isOk())
+ .andExpect(content().string("Logged Out"));
+
+ mockMvc.perform(get("/rest/Login/findbyemail").param("email", "login@example.com"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.email").value("login@example.com"))
+ .andExpect(jsonPath("$.password").doesNotExist());
+ }
+
+ private Employee sampleEmployee(String email) {
+ Employee employee = new Employee();
+ employee.setName("Test Employee");
+ employee.setDesignation("Developer");
+ employee.setSalary(50000);
+ employee.setDepId(1);
+ employee.setMobile(9876543210L);
+ employee.setEmail(email);
+ employee.setPassword("secret");
+ employee.setStatus("Logged Out");
+ employee.setAccountStatus("Activated");
+ employee.setCreatedBy("test");
+ employee.setCreatedAt("2026-05-10");
+ return employee;
+ }
+
+ private String employeeJson(String email) {
+ return "{"
+ + "\"name\":\"Test Employee\","
+ + "\"designation\":\"Developer\","
+ + "\"salary\":50000,"
+ + "\"depId\":1,"
+ + "\"mobile\":9876543210,"
+ + "\"email\":\"" + email + "\","
+ + "\"password\":\"secret\","
+ + "\"status\":\"Logged Out\","
+ + "\"accountStatus\":\"Activated\","
+ + "\"createdBy\":\"test\","
+ + "\"createdAt\":\"2026-05-10\""
+ + "}";
+ }
+
+ private Department sampleDepartment() {
+ Department department = new Department();
+ department.setName("Engineering");
+ department.setAddress("Bangalore");
+ department.setFloor(3);
+ department.setCreatedBy("test");
+ department.setCreatedAt("2026-05-10");
+ return department;
+ }
+
+ private String departmentJson() {
+ return "{"
+ + "\"name\":\"Engineering\","
+ + "\"address\":\"Bangalore\","
+ + "\"floor\":3,"
+ + "\"createdBy\":\"test\","
+ + "\"createdAt\":\"2026-05-10\""
+ + "}";
+ }
+
+ private Address sampleAddress(Integer empId) {
+ Address address = new Address();
+ address.setAddress1("Street 1");
+ address.setAddress2("Area 1");
+ address.setCity("Bangalore");
+ address.setState("Karnataka");
+ address.setPIN(560001);
+ address.setEmpId(empId);
+ address.setCreatedBy("test");
+ address.setCreatedAt("2026-05-10");
+ return address;
+ }
+
+ private String addressJson(Integer empId) {
+ return "{"
+ + "\"address1\":\"Street 1\","
+ + "\"address2\":\"Area 1\","
+ + "\"city\":\"Bangalore\","
+ + "\"state\":\"Karnataka\","
+ + "\"pin\":560001,"
+ + "\"empId\":" + empId + ","
+ + "\"createdBy\":\"test\","
+ + "\"createdAt\":\"2026-05-10\""
+ + "}";
+ }
+
+ private Profile sampleProfile(Integer empId) {
+ Profile profile = new Profile();
+ profile.setGender("Male");
+ profile.setDOB("2000-01-01");
+ profile.setHobbies("Reading");
+ profile.setEmpId(empId);
+ profile.setCreatedBy("test");
+ profile.setCreatedAt("2026-05-10");
+ return profile;
+ }
+
+ private String profileJson(Integer empId) {
+ return "{"
+ + "\"gender\":\"Male\","
+ + "\"dob\":\"2000-01-01\","
+ + "\"hobbies\":\"Reading\","
+ + "\"empId\":" + empId + ","
+ + "\"createdBy\":\"test\","
+ + "\"createdAt\":\"2026-05-10\""
+ + "}";
+ }
+}
diff --git a/src/test/java/com/hemant/db/service/EmployeeServiceTest.java b/src/test/java/com/hemant/db/service/EmployeeServiceTest.java
new file mode 100644
index 0000000..cb6bd51
--- /dev/null
+++ b/src/test/java/com/hemant/db/service/EmployeeServiceTest.java
@@ -0,0 +1,66 @@
+package com.hemant.db.service;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+
+import com.hemant.db.exception.ResourceNotFoundException;
+import com.hemant.db.model.Employee;
+import com.hemant.db.repository.EmployeeRepository;
+
+@SpringBootTest
+@ActiveProfiles("test")
+class EmployeeServiceTest {
+ @Autowired
+ private EmployeeService employeeService;
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+
+ @BeforeEach
+ void cleanDatabase() {
+ employeeRepository.deleteAll();
+ }
+
+ @Test
+ void createEmployeePersistsAndHidesDeactivatedRecordsFromList() {
+ Employee activeEmployee = sampleEmployee("active@example.com", "Activated");
+ Employee deactivatedEmployee = sampleEmployee("inactive@example.com", "Deactivated");
+
+ Employee savedActiveEmployee = employeeService.createEmployee(activeEmployee);
+ employeeService.createEmployee(deactivatedEmployee);
+
+ assertThat(savedActiveEmployee.getId()).isNotNull();
+ assertThat(employeeService.getAllEmployees())
+ .extracting(Employee::getEmail)
+ .containsExactly("active@example.com");
+ }
+
+ @Test
+ void updateMissingEmployeeThrowsNotFound() {
+ assertThatThrownBy(() -> employeeService.updateDesignation(999, "Manager"))
+ .isInstanceOf(ResourceNotFoundException.class)
+ .hasMessageContaining("Employee not found with id 999");
+ }
+
+ private Employee sampleEmployee(String email, String accountStatus) {
+ Employee employee = new Employee();
+ employee.setName("Test Employee");
+ employee.setDesignation("Developer");
+ employee.setSalary(50000);
+ employee.setDepId(1);
+ employee.setMobile(9876543210L);
+ employee.setEmail(email);
+ employee.setPassword("secret");
+ employee.setStatus("Logged Out");
+ employee.setAccountStatus(accountStatus);
+ employee.setCreatedBy("test");
+ employee.setCreatedAt("2026-05-10");
+ return employee;
+ }
+}
diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml
new file mode 100644
index 0000000..9d66a61
--- /dev/null
+++ b/src/test/resources/application-test.yml
@@ -0,0 +1,14 @@
+spring:
+ datasource:
+ driver-class-name: org.h2.Driver
+ url: jdbc:h2:mem:springboot_mysql_test;MODE=MySQL;DATABASE_TO_LOWER=TRUE;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
+ username: sa
+ password:
+ jpa:
+ hibernate:
+ ddl-auto: create-drop
+ generate-ddl: true
+ show-sql: false
+ properties:
+ hibernate:
+ dialect: org.hibernate.dialect.H2Dialect