Spring Boot Post and Get Request not working - java

I'm new to Springboot and making post/get requests, and I've been following a youtube tutorial to better understand it with postman. However, I've run into a problem while tinkering with the code, I'm trying to allow a post request for 2 entries
{
"name": "Hat",
"price": "$1"
}
however, whenever I try to send a get request it returns
{
"price": "null"
"name": "Hat"
}
I believe the problem is that the price is not being posted, thus the .orElse(null) is executing. I'm not sure why this is the case, and I would greatly appreciate the help. If any further information is needed let me know and I'll post it.
package com.example.demo.dao;
import com.example.demo.model.Person;
import org.springframework.stereotype.Repository;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
#Repository("fakeDao") //class serves as a repository
public class FakePersonDataAcessService implements PersonDao{
private static List<Person> DB = new ArrayList<>();
#Override
public int insertPerson(Person/*BigDecimal*/ price, Person person) {
DB.add(new Person(price.getPrice(), person.getName()));
return 1;
}
#Override
public List<Person> selectAllPeople() {
return DB;
}
#Override
public Optional<Person> selectPersonByPrice(Person/*BigDecimal*/ price) {
return DB.stream()
.filter(person -> person.getPrice().equals(price)) //filters through the people and checks our DB to see if that person with that price exists
.findFirst();
}
#Override
public int deletePersonByPrice(Person/*BigDecimal*/ price) {
Optional<Person> personMaybe = selectPersonByPrice(price);
if (personMaybe.isEmpty()){
return 0;
}
DB.remove(personMaybe.get());
return 1;
}
#Override
public int updatePersonByPrice(Person/*BigDecimal*/ price, Person update) {
return selectPersonByPrice(price) //select the person
.map(person -> { //map the person
int indexOfPersonToUpdate = DB.indexOf(person);
if (indexOfPersonToUpdate >= 0){ //if the index of that person is >=0 we know that we have found that person
DB.set(indexOfPersonToUpdate, new Person(price.getPrice(), update.getName())); //set contents of that person to the new person that we just recieved from thc client
return 1; //return 1 if everything is fine
}
return 0; //otherwise we return 0 or if selectpersonbyprice is not present we dont do anyhthing and just return 0
})
.orElse(0);
}
}
package com.example.demo.api;
import com.example.demo.model.Person;
import com.example.demo.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.List;
import java.util.UUID;
#RequestMapping("api/v1/person")
#RestController
public class PersonController {
private final PersonService personService;
#Autowired
public PersonController(PersonService personService) {
this.personService = personService;
}
#PostMapping
public void addPerson(Person price,/*#Valid #NotNull Stringprice,*/#Valid #NotNull #RequestBody Person person){
personService.addPerson(price,/*price,*/ person);
}
#GetMapping
public List<Person> getAllPeople(){
return personService.getAllPeople();
}
#GetMapping(path = "{price}")
public Person getPersonByPrice(#PathVariable("price") Person/*BigDecimal*/ price){
return personService.getPersonByPrice(price) //after sending a get request with that price we will either return the person, OR if they don't exisist we return null
.orElse(null);
}
#DeleteMapping(path = "{price}")
public void deletePersonByPrice(#PathVariable("price") Person/*BigDecimal*/ price){
personService.deletePerson(price);
}
#PutMapping(path = "{price}")
public void updatePerson(#PathVariable("price") Person/*BigDecimal*/ price, #Valid #NotNull #RequestBody Person personToUpdate){
personService.updatePerson(price, personToUpdate);
}
}
package com.example.demo.dao;
import com.example.demo.model.Person;
import javax.swing.text.html.Option;
import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
//actual interface where we can define our operations allowed/contract for anyone who wants to implement this interface; and using dependecy injection we can change db easily
public interface PersonDao {
int insertPerson(Person price, Person person); //allows us to insert a person with a given price
/*
default int insertPerson(Person price, Person person){
String price = new String("$"); //without an price, its default is 0
return insertPerson(price, person);
}
*/
List<Person> selectAllPeople();
Optional<Person> selectPersonByPrice(Person/*BigDecimal*/ price);
int deletePersonByPrice(Person/*BigDecimal*/ price);
int updatePersonByPrice(Person/*BigDecimal*/ price, Person person);
}
package com.example.demo.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import javax.validation.constraints.NotBlank;
import java.math.BigDecimal;
import java.util.UUID;
public class Person {
private final String price;
#NotBlank //name can't be blank
private final String name;
public Person(#JsonProperty("price") String /*BigDecimal*/ price,
#JsonProperty("name") String name) {
this.price = price;
this.name = name;
}
public String/*BigDecimal*/ getPrice() {
return price;
}
public String getName() {
return name;
}
}
package com.example.demo.service;
import com.example.demo.dao.PersonDao;
import com.example.demo.model.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
#Service
public class PersonService {
private final PersonDao personDao;
#Autowired
public PersonService(#Qualifier("fakeDao") PersonDao personDao) {
this.personDao = personDao;
}
public int addPerson(Person price,/*String price,*/ Person person){
return personDao.insertPerson(price,/*price,*/ person);
}
#GetMapping
public List<Person> getAllPeople(){
return personDao.selectAllPeople();
}
public Optional<Person> getPersonByPrice(Person/*BigDecimal*/ price){
return personDao.selectPersonByPrice(price);
}
public int deletePerson(Person/*BigDecimal*/ price){
return personDao.deletePersonByPrice(price);
}
public int updatePerson(Person/*BigDecimal*/ price, Person newPerson){
return personDao.updatePersonByPrice(price, newPerson);
}
}

For simplicity sake, I'll just keep my code limited to add and get APIs.
CHANGES IN CONTROLLER
Firstly, when retrieving the person by price, it will be a list and not Optional. The reason for the same is that multiple items( in this case, person) can be present at the same price.
Secondly,you are passing price as a Person and not as String, therefore that needs to be changed. After simplification , this becomes your controller for getting price by price
#GetMapping(path = "{price}")
public List<Person> getPersonByPrice(#PathVariable("price") String price) {
return personService.getPersonByPrice(price);
}
CHANGES IN FAKE PERSON DATA ACCESS SERVICE
Here , you need to iterate the entire list with the given price and whenever a Person matches it, it will be added to your required list .
#Override
public List<Person> selectPersonByPrice(String price) {
List<Person> p = new ArrayList<>();
Person person = new Person("", price);
for (Person temp : DB) {
if (temp.getPrice().equals(price)) {
p.add(temp);
}
}
return p;
}
Thus, your declaration of this method will also change in PersonService.
After implementing these changes and making a request to the get api, it is successfully returning an it

Related

jakarta.servlet.ServletException, different behaviour between run, test and http request with SpringBoot API

I am building a SpringBoot API to learn the framework and I am facing two curious problems which probably are linked in some way.
First problem, when I try to test my code with my own Junit test class called EmployeeControllerTest, calling the method with http request returns the following error :
jakarta.servlet.ServletException: Request processing failed: java.util.NoSuchElementException: No value present
Second problem, when I perform those tests with Postman, the request /employees returning the list of employees works perfectly but the request /employee (with or without id added to the url), the API returns nothing.
In addition to this, calling the method from inside the code (in the run class) works great, I have every result I need.
Here are the code of every part involved. First the model class :
package com.openclassrooms.api.models;
import jakarta.persistence.*;
import lombok.Data;
#Data
#Entity
#Table(name = "employees")
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
private String mail;
private String password;
}
The repository class :
package com.openclassrooms.api.repository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.openclassrooms.api.models.Employee;
#Repository
public interface EmployeeRepository extends CrudRepository<Employee, Long> {
}
The service class :
package com.openclassrooms.api.service;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.openclassrooms.api.models.Employee;
import com.openclassrooms.api.repository.EmployeeRepository;
#Service
public class EmployeeService {
#Autowired
private EmployeeRepository employeeRepository;
public Optional<Employee> getEmployee(final Long id) {
System.out.println("getEmployee ok");
return employeeRepository.findById(id);
}
public Iterable<Employee> getEmployees() {
System.out.println("getEmployees ok");
return employeeRepository.findAll();
}
public void deleteEmployee(final Long id) {
employeeRepository.deleteById(id);
}
public Employee saveEmployee(Employee employee) {
Employee savedEmployee = employeeRepository.save(employee);
return savedEmployee;
}
}
and the controller class :
package com.openclassrooms.api.controller;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import com.openclassrooms.api.models.Employee;
import com.openclassrooms.api.service.EmployeeService;
#RestController
public class EmployeeController {
#Autowired
private EmployeeService employeeService;
// Read - Get all employees
// #return - An Iterable object of Employee full filled
#GetMapping("/employees")
public Iterable<Employee> getEmployees() {
Iterable<Employee> list = employeeService.getEmployees();
System.out.println(list);
return list;
}
#GetMapping("/employee/{id}")
public Employee getEmployee(#PathVariable("id") final Long id) {
Optional<Employee> emp = employeeService.getEmployee(id);
if (emp.isEmpty()) {
Employee employe = emp.get();
System.out.println(employe.getFirstName());
return employe;
} else {
System.out.println("ABSENT");
return null;
}
}
#GetMapping("/employee")
public Employee getEmployee() {
Optional<Employee> emp = employeeService.getEmployee(1L);
if (emp.isEmpty()) {
Employee employe = emp.get();
System.out.println(employe.getFirstName());
return employe;
} else {
System.out.println("ABSENT");
return null;
}
}
}
Additionnaly, the main and test classes :
package com.openclassrooms.api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.openclassrooms.api.models.Employee;
import com.openclassrooms.api.service.EmployeeService;
#SpringBootApplication
public class ApiApplication implements CommandLineRunner {
#Autowired
private EmployeeService employeeService;
public static void main(String[] args) {
SpringApplication.run(ApiApplication.class, args);
}
public void run(String... args) throws Exception {
if (employeeService.getEmployee(1L).isPresent()) {
Employee emp1 = employeeService.getEmployee(1L).get();
System.out.println(emp1.getFirstName() + " " + emp1.getLastName());
} else {
System.out.println("Erreur, employé absent.");
}
System.out.println(employeeService.getEmployees());
}
}
package com.openclassrooms.api;
import static org.hamcrest.CoreMatchers.is;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import java.io.PrintStream;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureWebMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
//import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.ResultHandler;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.openclassrooms.api.controller.EmployeeController;
import com.openclassrooms.api.models.Employee;
import com.openclassrooms.api.service.EmployeeService;
//#SpringBootTest
//#AutoConfigureWebMvc
#WebMvcTest(controllers = EmployeeController.class)
public class EmployeeControllerTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private EmployeeService employeeService;
#Test
public void testGetEmployees() throws Exception {
Employee response = new Employee();
mockMvc.perform(get("/employee"))
.andExpect(status().isOk())
.andDo(print(System.out))
.andExpect(jsonPath("$.firstName").value("Laurent"));
//.andExpect(jsonPath("$[0].firstName", is("Laurent")));
}
}
Thanks in advance for any answer !
EDIT : the SQL script used when building the database :
DROP TABLE IF EXISTS employees;
CREATE TABLE employees (
id INT AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(250) NOT NULL,
last_name VARCHAR(250) NOT NULL,
mail VARCHAR(250) NOT NULL,
password VARCHAR(250) NOT NULL
)
INSERT INTO employees (first_name, last_name, mail, password) VALUES
('Laurent', 'GINA', 'laurentgina#mail.com', 'laurent'),
('Sophie', 'FONCEK', 'sophiefoncek#mail.com', 'sophie'),
('Agathe', 'FEELING', 'agathefeeling#mail.com', 'agathe');
There seems to be a couple of issues with the code.
First, in the getEmployee method of the EmployeeController class, the if condition checks if the Optional returned by the employeeService is empty, but if it's empty, the code returns null, which is not the desired behavior. Instead, you should check if the Optional is present, and if it is, return the value, otherwise return an appropriate response indicating that the employee was not found.
#GetMapping("/employee/{id}")
public Employee getEmployee(#PathVariable("id") final Long id) {
Optional<Employee> emp = employeeService.getEmployee(id);
if (emp.isPresent()) {
Employee employe = emp.get();
System.out.println(employe.getFirstName());
return employe;
} else {
System.out.println("ABSENT");
// return an appropriate response indicating that the employee was not found
return null;
}
}
The same issue applies to the getEmployee method without a path variable.
#GetMapping("/employee")
public Employee getEmployee() {
Optional<Employee> emp = employeeService.getEmployee(1L);
if (emp.isPresent()) {
Employee employe = emp.get();
System.out.println(employe.getFirstName());
return employe;
} else {
System.out.println("ABSENT");
// return an appropriate response indicating that the employee was not found
return null;
}
}
Regarding the issue with the Junit test class, it's difficult to determine the problem without more information, such as the exact error message or a code snippet of the test class.
Overall, the code needs to be more robust in handling cases where the employee was not found, and the test class needs to be further investigated to determine the root cause of the issue.

Swagger UI not showing all the fields from user defined model

I am learning Swagger. I have a simple Spring Boot REST API to display employee. The Employee model has an association of employee addresses. All I am trying is to display the employee details for the documentation using Swagger.
This is my Employee model:
package com.example.documentation.model;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.Arrays;
import java.util.List;
public class Employee<T> {
#Schema(type = "int", description = "id for employee")
private int id;
#Schema(type = "string", description = "name of employee")
private String name;
private List<T> listOfAddresses;
public Employee(int id, String name, List<T> listOfAddresses) {
this.listOfAddresses = listOfAddresses;
this.id = id;
this.name = name;
}
public List<T> getListOfAddresses() {
listOfAddresses = (List<T>) Arrays.asList(new Address(2201,"Street 1","UB12
1TT"), new Address(3201,"Street 1","KK12 1TP"));
return listOfAddresses;
}
public void setListOfAddresses(List<T> listOfAddresses) {
this.listOfAddresses = listOfAddresses;
}}
where Address is a normal POJO with houseNumber, Streetname and postcode.
Below is my controller:
package com.example.documentation.controller;
import com.example.documentation.model.Address;
import com.example.documentation.model.Employee;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
import java.util.List;
#RestController
public class EmployeeController {
private Employee<Address> employee;
#RequestMapping("/employee/{id}")
#Operation(
tags = {"Employee"}
)
public Employee<Address> getEmployeeDetailsById(#PathVariable(name = "id", required = true) int id,
#PathVariable(name = "name", required = false) String name) {
List<Address> list = Arrays.asList(new Address(101,"T1","Test 1"),
new Address(201,"T2","Test 2"));
employee = new Employee<>(101,"David", list);
return employee;
}
}
I am using Gradle.
When I access Swagger UI, I see the following:
As you can see the ID and the name of the employee is missing. Any idea how to resolve this?

Spring Boot URL mapping not working when files are present in multiple packages

I tried making a simple REST API using Spring Boot. I have put the classes in separate packages. In this case, the URL mapping is not working (checked using Postman), whereas its working fine if I put them all in the same package as that of the main class.
""" Hierarchy of the packages :
com.example.ProductCRUD
|-----ProductCrudApplication.java (main)
com.example.ProductCRUD.Controller
|-----ProductController.java(controller)
com.example.ProductCRUD.Entity
|------Product.java(model class)
com.example.Repository
|-----ProductRepo.java(Repository interface)
com.example.Service
|-------ProductService.java(Service class) """
I tried including #componentscan("com.example") in the main class. But in that case, it throws an error.
If somebody could help me in finding out where I went wrong, it would be helpful.
Thanks in advance for your help.
//PRODUCT MODEL CLASS (Product.java)
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
//MODEL CLASS
#Entity
public class Product {
#Id
#GeneratedValue
private int id;
private String name;
private int quantity;
private int price;
public Product() {
super();
// TODO Auto-generated constructor stub
}
public Product(int id, String name, int quantity, int price) {
super();
this.id = id;
this.name = name;
this.quantity = quantity;
this.price = price;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
//Repository (ProductRepo.java) :interface
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.Entity.Product;
public interface ProductRepo extends JpaRepository<Product,Integer> {
Product findByName(String name);
}
//Service class(ProductService.java)
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.Entity.Product;
import com.example.Repository.ProductRepo;
#Service
public class ProductService {
#Autowired
private ProductRepo repo; //service--> repository
//PUT
public Product create(Product product) {
Product p=repo.save(product); //default method of JPA to make the data persist in the DB
return p;
}
public List<Product> createproducts(List<Product> products) {
List<Product> p=repo.saveAll(products);
return p;
}
//GET
public List<Product> getProducts(){
List<Product> p=repo.findAll();
return p;
}
public Product getProductByid(int id){
Product p=repo.findById(id).orElse(null); //return id , if id not found then return null
return p;
}
public Product getProductByName(String name){
Product p=repo.findByName(name); //customized method in JPA (declared in the interface)
return p;
}
//DELETE
public String deleteProduct(int id) {
repo.deleteById(id);
return "Product removed : "+id;
}
//UPDATE
public Product updateProduct(Product product) {
Product existing=repo.findById(product.getId()).orElse(null);
existing.setName(product.getName());
existing.setPrice(product.getPrice());
existing.setQuantity(product.getQuantity());
Product p=repo.save(existing);
return p;
}
}
//Controller class (ProductController.java)
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.example.Entity.Product;
import com.example.Service.ProductService;
#RestController
public class ProductController {
#Autowired
private ProductService service; //controller --> service
#PostMapping("/create")
public Product addProduct(#RequestBody Product product) {
return service.create(product);
}
#PostMapping("/createProducts")
public List<Product> addProducts(#RequestBody List<Product> products) {
return service.createproducts(products);
}
#GetMapping("/getproducts/{id}")
public Product getProductById(#PathVariable int id){
return service.getProductByid(id);
}
#GetMapping("/getproducts/{name}")
public Product getProductByName(#PathVariable String name){
return service.getProductByName(name);
}
#GetMapping("/getproducts")
public List<Product> getProducts(){
return service.getProducts();
}
#DeleteMapping("/delete/{id}")
public String delete(#PathVariable int id) {
return service.deleteProduct(id);
}
#PutMapping("/update/{id}")
public Product update(#RequestBody Product product) {
return service.updateProduct(product);
}
}
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
#ComponentScan("com.example")
public class ProductCrudApplication {
public static void main(String[] args) {
SpringApplication.run(ProductCrudApplication.class, args);
}
}
-- If I include the #Componentscan this is the error I am receiving :
Field repo in com.example.Service.ProductService required a bean of type 'com.example.Repository.ProductRepo' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.example.Repository.ProductRepo' in your configuration.
moving the main class from
com/example/ProductCRUD
to
com/example
fixes your issue.
diff:
rename from ProductCRUD/src/main/java/com/example/ProductCRUD/ProductCrudApplication.java
rename to ProductCRUD/src/main/java/com/example/ProductCrudApplication.java
index 1633cbf..93294a2 100644
--- a/ProductCRUD/src/main/java/com/example/ProductCRUD/ProductCrudApplication.java
+++ b/ProductCRUD/src/main/java/com/example/ProductCrudApplication.java
## -1,4 +1,4 ##
-package com.example.ProductCRUD;
+package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

UnsatisfiedDependencyException: Error creating bean with name 'procjectController': Unsatisfied dependency expressed through field

I am building simple ManyToOne relationship using spring JAP. i get UnsatisfiedDependencyException Error with bean name Unsatisfied dependency expressed through field
UnsatisfiedDependencyException: Error creating bean with name 'procjectController': Unsatisfied
Here is my file.
project.java
package com.ganesh.dto;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import com.fasterxml.jackson.annotation.JsonIgnore;
#Entity
public class Project {
#Id
private int projectId;
private String projectName;
//Relation establish
#ManyToOne(
fetch = FetchType.LAZY,
optional = false
)
#JoinColumn(
name = "employee_id",
nullable = false
)
#JsonIgnore
private Employee employee;
public Project() {
}
public Project(int projectId, String projectName, int eId) {
super();
this.projectId = projectId;
this.projectName = projectName;
//Adding employee
this.employee = new Employee(eId,"","");
}
public int getProjectId() {
return projectId;
}
public void setProjectId(int projectId) {
this.projectId = projectId;
}
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
//Adding getter and setters Employee reference
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
}
ProjectDao.java
package com.ganesh.dao;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.ganesh.dto.Project;
#Repository
public interface ProjectDao extends JpaRepository<Project, Integer> {
List<Project> findEmployeeById(int eId);
}
ImpProjectService.java
package com.ganesh.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ganesh.dao.*;
import com.ganesh.dto.Project;
#Service
public class ImpProjectService implements ProjectService {
#Autowired
private ProjectDao projectDao;
#Override
public List<Project> getProjectList(int eId) {
System.out.println("in Dao class employee id"+ eId);
return projectDao.findEmployeeById(eId);
}
#Override
public Project getProjectById(int id) {
return projectDao.getOne(id);
}
#Override
public void addProject(Project project) {
projectDao.save(project);
}
#Override
public void updateProject(Project project) {
projectDao.save(project);
}
#Override
public void deleteProjectById(int id) {
projectDao.deleteById(id);
}
#Override
public List<Project> getAllProject() {
return projectDao.findAll();
}
}
ProcjectController.java
package com.ganesh.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.ganesh.dto.*;
import com.ganesh.service.*;
#RestController
public class ProcjectController {
#Autowired
private ImpProjectService projectService;
#RequestMapping("/projects")
public List<Project> getProjectList(){
return projectService.getAllProject();
}
#RequestMapping("/employees/{eId}/projects")
public List<Project> getAllProjects(#PathVariable int eId){
System.out.println("In Project Controller");
List<Project> projList = projectService.getProjectList(eId);
System.out.println(projList);
return projList;
}
#RequestMapping("/employees/{eId}/projects/{id}")
public Project getProjectById(#PathVariable int id) {
return projectService.getProjectById(id);
}
#RequestMapping(method = RequestMethod.POST, value="/employees/{eId}/projects")
public void addProject(#RequestBody Project project, #PathVariable int eId) {
project.setEmployee(new Employee(eId,"",""));
projectService.addProject(project);
}
#RequestMapping(method = RequestMethod.PUT, value="/employees/{eId}/projects/{id}")
public void updateProject(#RequestBody Project project, #PathVariable int eId) {
project.setEmployee(new Employee(eId,"",""));
projectService.updateProject(project);
}
#RequestMapping(method = RequestMethod.DELETE, value="/projects/{id}")
public void deleteProjecstById(#PathVariable int id) {
projectService.deleteProjectById(id);
}
}
Note: This answer is based on insufficient data, because stack trace is not available. With correct and complete stacktrace, we might be able to provide more precise answer.
Answer:
Looks like a problem in your Dao class.
You have written
#Repository
public interface ProjectDao extends JpaRepository<Project, Integer> {
List<Project> findEmployeeById(int eId);
}
Which means you are creating a repository of type Project and trying to fire a query as findEmployeeById, It should either be findByEmployee, which accepts Employee as a parameter, or should not be there in place at all. Because the query syntax and the Template parameters do not match. So Spring will not be able to initialize the query handlers for the same.
Try changing it as below, if is satisfies your purpose.
#Repository
public interface ProjectDao extends JpaRepository {
List<Project> findAllByEmployee(Employee emp);
}
Please check the same, and correct. If it still doesn't work, please post the full stack trace, and we can help you out.

findAll from org.springframework.data.jpa.repository.support.SimpleJpaRepository returning duplicates

So I have repository defined as follows:
public interface PersonRepository extends CrudRepository<Person, Long>
My entity is as follows:
#Entity
#Table(name="Person")
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name="PERSON_GENERATOR", sequenceName="PERSON_SEQ")
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="PERSON_GENERATOR")
private Long id;
#Column(name="ssn")
private String socialSecurityNumber;
private String name;
public Person() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
I have ommitted the getters and setters for socialSecurityNumber and Name. In the database there are 1000 records.
I have a Spring bean annotated with #Component that uses the PersonRepo by calling its findAll(). When findAll() gets called I get the list of 1000 records with their UNIQUE ID however, when I loop through the list of Persons returned by findAll() I find unexpected results.
#Component
public class PersonComponent {
#Autowired
PersonRepository personRepo;
public void printPerson() {
List<Person> people = personRepo.findAll();
for(Person person : people) {
System.out.println("id=" + person.getId() + ", ssn=" + person.getSocialSecurityNumber() + ", name=" + person.getName());
}
}
}
So if in my db i have the records
id, ssn, name
1, ssn1, Bob
2, ssn2, Mary
3, ssn3, Joe
when I call the findAll() I constantly get this back
id=1, ssn=ssn1, name=Bob
id=2, ssn=ssn2, name=Mary
id=3, ssn=ssn2, name=Mary
Notice that i get the correct Ids (ie. 1, 2, 3) but for some reason id 3 is mapped to ssn2,Mary and NOT ssn3, Joe
This behaviour happens only after the first call to findAll() (ie. the first findAll, works fine but subsequent once show the behaviour explained above). In other words, when the application starts up and the Spring bean that uses the PersonRepo gets called for the first time, findAll() seems to work fine. But when a subsequent call is made to the Spring Bean then findAll behaves as described.
Lastly, When i call the web service http://localhost/persons (which calls `findAll() under the covers) I get the correct behaviour every time.
Any thoughts?
The problem is probably relating to omitting getters and setters for name and social security variables ? After all those are declared private so we need a way to access them, hence why getters ?
I have replicated your app and if you use the following, you should not be getting duplicates at all.
Appllication.properties file:
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/findall_db
spring.datasource.username=YOUR_DATABASE_USERNAME
spring.datasource.password=YOUR_DATABASE_PASSWORD
Person Entity Java Class:
package com.example.demo;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
#Entity
#Table(name="Person")
public class PersonInfo implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name="PERSON_GENERATOR", sequenceName="PERSON_SEQ")
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="PERSON_GENERATOR")
private Long id;
#Column(name="ssn")
private String socialSecurityNumber;
private String name;
public PersonInfo() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getSocialSecurityNumber() {
return socialSecurityNumber;
}
public void setSocialSecurityNumber(String socialSecurityNumber) {
this.socialSecurityNumber = socialSecurityNumber;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "PersonInfo [id=" + id + ", socialSecurityNumber=" + socialSecurityNumber + ", name=" + name + "]";
}
}
Person Repository:
package com.example.demo;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface PersonInfoRepository extends CrudRepository<PersonInfo, Long>{
}
Person Controller:
package com.example.demo;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
#Controller
public class PersonController {
#Autowired
PersonInfoRepository personRepo;
#ResponseBody
#GetMapping("/people")
public List printPersonInfo() {
List<PersonInfo> people = (List<PersonInfo>) personRepo.findAll();
System.out.println(people.toString());
return people ;
}
}

Categories

Resources