Spring boot - Post function get error while Get and Delete function still be ok - spring

I'm newly get to spring framework and handing-on basic steps however I got a error which didn't where it come from. I just use Postman to communicate with data. Get and delete function were smooth, however Post and Put didn't.
This is my code:
Class EmployeeRepo
package com.employee.demo.dao;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import com.employee.demo.model.Employee;
public interface EmployeeRepo extends JpaRepository<Employee, Integer>{
}
Class Employee
package com.employee.demo.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity
public class Employee {
#Id
private int id;
private String name;
private double salary;
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 double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String toString() {
return "Employee with [ID: " + id + ", name: " + name + " and salary: " + salary + "]";
}
}
Class EmployeeController
package com.employee.demo.controller;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
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.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.employee.demo.dao.EmployeeRepo;
import com.employee.demo.model.Employee;
#RestController
public class EmployeeController {
#Autowired
EmployeeRepo repo;
#RequestMapping("/")
public String home() {
return "home.jsp";
}
#DeleteMapping("/employee/{id}")
public String deleteEmployee(#PathVariable int id) {
Employee empl = repo.getOne(id);
repo.delete(empl);
return "deleted";
}
#PostMapping("/employee")
public Employee addEmployee(Employee empl) {
repo.save(empl);
return empl;
}
#GetMapping(path = "/employees")
public List<Employee> getEmployees() {
return repo.findAll();
}
#PutMapping(path = "/employee", consumes = {"application/json"})
public Employee saveOrUpdateEmployee(#RequestBody Employee empl) {
repo.save(empl);
return empl;
}
#RequestMapping("/employee/{id}")
public Optional<Employee> getEmployee(#PathVariable int id) {
return repo.findById(id);
}
}
And this is what I got from postman for Post query

Problem is with your POST method (addEmployee)- Whatever you are sending in request body is not accepted by addEmployee method. You can verify in DB after a POST call.
employee table will have data something like
Use #RequestBody annotation with argument as:
public Employee addEmployee(#RequestBody Employee empl)
And it will work as expected.

Related

Custom Exception not thrown in controller-method when no data is found in database

My controller always give Internal server error whenever my condition fail, and are suppose to throw custom exception ResourceNotFoundException.
When I call account/1-endpoint (no account with id 1 in database) I expect an ResourceNotFoundException, but instead I get Internal server Error.. I do not understand why ResourceNotFoundException is not thrown, I watched several youtube tutorials on the topic.
Please help by providing possible solutions.
My model classes are
package com.bank2.Model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import org.hibernate.annotations.Proxy;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
#Entity
#javax.persistence.Table(name="Account")
#Proxy(lazy = false)
#JsonIgnoreProperties(ignoreUnknown = true)
public class Account {
#Id
int accountNumber;
#Column(name="balance")
Double balance;
#Column(name="accountType")
String accountType;
public Account() {
super();
}
#Override
public String toString() {
return "Account [accountNumber=" + accountNumber + ", balance=" + balance + ", accountType=" + accountType + "]";
}
public int getAccountNumber() {
return accountNumber;
}
public void setAccountNumber(int accountNumber) {
this.accountNumber = accountNumber;
}
public Double getBalance() {
return balance;
}
public void setBalance(Double balance) {
this.balance = balance;
}
public String getAccountType() {
return accountType;
}
public void setAccountType(String accountType) {
this.accountType = accountType;
}
public Account(int accountNumber, Double balance, String accountType) {
super();
this.accountNumber = accountNumber;
this.balance = balance;
this.accountType = accountType;
}
}
package com.bank2.Model;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Proxy;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
#Entity
#Table(name="Customer")
#Proxy(lazy = false)
#JsonIgnoreProperties(ignoreUnknown = true)
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Integer customerId;
#Column(name="customerName")
String customerName;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL,targetEntity = Account.class)
#JoinColumn(name = "ca_fk",referencedColumnName ="customerId")
private List<Account> accounts;
public Customer() {
super();
}
public Customer(Integer customerId, String customerName, List<Account> accounts) {
super();
this.customerId = customerId;
this.customerName = customerName;
this.accounts = accounts;
}
public Integer getCustomerId() {
return customerId;
}
public void setCustomerId(Integer customerId) {
this.customerId = customerId;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public List<Account> getAccount() {
return accounts;
}
public void setAccount(List<Account> accounts) {
this.accounts = accounts;
}
#Override
public String toString() {
return "Customer [customerId=" + customerId + ", customerName=" + customerName + ", accounts=" + accounts + "]";
}
}
My service classes are
package com.bank2.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bank2.Model.Customer;
import com.bank2.repository.CustomerRepository;
#Service
public class CustomerService {
#Autowired
CustomerRepository customerRepository;
public Customer customerCreate(Customer customer) {
Customer x= customerRepository.save(customer);
return x;
}
}
package com.bank2.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bank2.Model.Account;
import com.bank2.repository.AccountRepository;
#Service
public class AccountService {
#Autowired
AccountRepository accountRepository;
public Account findAccountById(int accountNumber) {
return accountRepository.getById(accountNumber);
}
}
my controller class are
package com.bank2.controller;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.bank2.Exception.ResourceNotFoundException;
import com.bank2.Model.Account;
import com.bank2.ServiceImpl.AccountService;
#RestController
#RequestMapping("/account")
public class AccountController {
#Autowired
AccountService accountService;
#GetMapping("/{accountNumber}")
public ResponseEntity<?> getAccountById(#PathVariable("accountNumber") int accountNumber){
Account acc=accountService.findAccountById(accountNumber);
if(acc==null) {
throw new ResourceNotFoundException("Account [accountNumber="+accountNumber+"] can't be found");
}else {
return new ResponseEntity<>(acc,HttpStatus.FOUND);
}
}
package com.bank2.controller;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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.RestController;
import com.bank2.Exception.ResourceNotFoundException;
import com.bank2.Model.Customer;
import com.bank2.ServiceImpl.CustomerService;
#RestController
#RequestMapping("/customer")
public class CustomerController {
#Autowired
CustomerService customerService;
#PostMapping("/createCust")
public ResponseEntity<?> CreateCustomer(#RequestBody Customer customer){
Customer cus=customerService.customerCreate(customer);
Optional<Customer> cus1 = Optional.ofNullable(cus);
if(cus1.isEmpty()) {
throw new ResourceNotFoundException("customer not created!!");
}else {
return new ResponseEntity<>(cus,HttpStatus.CREATED);
}
}
}
my expection classes are
package com.bank2.Exception;
import java.time.LocalDateTime;
import java.util.List;
import org.springframework.http.HttpStatus;
public class ApiErrors {
String message;
List<String> details;
HttpStatus status;
LocalDateTime timestamp;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public List<String> getDetails() {
return details;
}
public void setDetails(List<String> details) {
this.details = details;
}
public HttpStatus getStatus() {
return status;
}
public void setStatus(HttpStatus status) {
this.status = status;
}
public LocalDateTime getTimestamp() {
return timestamp;
}
public void setTimestamp(LocalDateTime timestamp) {
this.timestamp = timestamp;
}
public ApiErrors() {
super();
// TODO Auto-generated constructor stub
}
public ApiErrors(String message, List<String> details, HttpStatus status, LocalDateTime timestamp) {
super();
this.message = message;
this.details = details;
this.status = status;
this.timestamp = timestamp;
}
#Override
public String toString() {
return "ApiErrors [message=" + message + ", details=" + details + ", status=" + status + ", timestamp="
+ timestamp + "]";
}
}
package com.bank2.Exception;
public class ResourceNotFoundException extends RuntimeException{
/**
*
*/
private static final long serialVersionUID = 1L;
public ResourceNotFoundException() {
super();
}
public ResourceNotFoundException(String message) {
super(message);
}
}
package com.bank2.Exception;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
#ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
#ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<Object> handleResourceNotFoundException(ResourceNotFoundException ex){
String msg=ex.getMessage();
List<String> details=new ArrayList<>();
details.add("Resource not found");
ApiErrors errors=new ApiErrors(msg,details,HttpStatus.BAD_REQUEST,LocalDateTime.now());
return new ResponseEntity<Object>(errors,HttpStatus.BAD_REQUEST);
}
#ExceptionHandler(Exception.class)
public ResponseEntity<Object> handleOther(Exception ex){
String msg=ex.getMessage();
List<String> details=new ArrayList<>();
details.add("Other Exceptions");
ApiErrors errors=new ApiErrors(msg,details,HttpStatus.INTERNAL_SERVER_ERROR,LocalDateTime.now());
return new ResponseEntity<Object>(errors,HttpStatus.INTERNAL_SERVER_ERROR);
}
}
This is the Internal server error I have gotten so far in Postman:
{
"message": "Unable to find com.bank2.Model.Account with id 1; nested exception is javax.persistence.EntityNotFoundException: Unable to find com.bank2.Model.Account with id 1",
"details": [
"Other Exceptions"
],
"status": "INTERNAL_SERVER_ERROR",
"timestamp": "2022-04-02T22:09:28.0486246"
}
My repositories are
'''
package com.bank2.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.bank2.Model.Account;
#Repository
public interface AccountRepository extends JpaRepository<Account, Integer> {
}
'''
'''
package com.bank2.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.bank2.Model.Customer;
#Repository
public interface CustomerRepository extends JpaRepository<Customer, Integer> {
}
'''
From the Documentation JpaRepository.html#getById-ID-
T getById(ID id)
Returns a reference to the entity with the
given identifier. Depending on how the JPA persistence provider is
implemented this is very likely to always return an instance and throw
an EntityNotFoundException on first access. Some of them will reject
invalid identifiers immediately.
The error message you get shows ...nested exception is EntityNotFoundException, so that could be normal...
So you could throw a ResourceNotFoundException in your service when the Account is not found.
#Service
public class AccountService {
public Account findAccountById(int accountNumber) {
try {
return accountRepository.getById(accountNumber);
} catch(EntityNotFoundException e) {
throw new ResourceNotFoundException("Account [accountNumber="+accountNumber+"] can't be found")
}
}

Spring boot controller not getting scanned error 404 not found

I am trying to create restful api but my controller is not working and I'm getting the error shown below:
{
"timestamp": "2020-06-11T15:28:18.103+00:00",
"status": 404,
"error": "Not Found",
"message": "",
"path": "/path/findCarsAfterYear/2020"
}
Please help me to resolve this.
Entity Class
package com.example.demo.data;
import javax.persistence.*;
#Entity
public class Car {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private long id;
#Column
private String model;
#Column
private Integer year;
// standard getters and setters
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public Integer getYear() {
return year;
}
public void setYear(Integer year) {
this.year = year;
}
}
Repository Class
package com.example.demo.Repository;
import com.example.demo.data.Car;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.jpa.repository.query.Procedure;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository
public interface CarRepository extends JpaRepository<Car, Integer> {
#Query("Select wds from Car wds where year=?1 ")
List<Car> findCarsAfterYear(Integer year);
}
Service class
package com.example.demo.service;
import com.example.demo.Repository.CarRepository;
import com.example.demo.data.Car;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
#Service
public class CarService {
#Autowired
CarRepository carRepository;
public List<Car> findCarsAfterYear(Integer id) {
return carRepository.findCarsAfterYear(id);
}
}
Controller class
package com.example.demo.Controller;
import com.example.demo.data.Car;
import com.example.demo.service.CarService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
#Controller
#RequestMapping(path="/test")
public class CarController {
#Autowired(required=true)
private CarService carService;
#GetMapping(value="/findCarsAfterYear/{id}")
public List<Car> findCarsAfterYear(Integer id) {
return carService.findCarsAfterYear(id);
}
}
Application Class
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#Configuration
#SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
#EnableJpaRepositories("com.example.demo.Repository")
#EntityScan("com.example.demo.data")
#ComponentScan(basePackages="com.example.demo.service,com.example.demo.Controller")
#EnableCaching
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
In you want to use #Controller then you have to provide #ResponseBody explicitly.
#Controller
#RequestMapping(path="/test")
public class CarController {
#Autowired(required=true)
private CarService carService;
#GetMapping(value="/findCarsAfterYear/{id}")
#ResponseBody
public List<Car> findCarsAfterYear(Integer id) {
return carService.findCarsAfterYear(id);
}
}
But in case #RestController, which is combination of #Controllerand #ResponseBody
#RestController
#RequestMapping(path="/test")
public class CarController {
#Autowired(required=true)
private CarService carService;
#GetMapping(value="/findCarsAfterYear/{id}")
public List<Car> findCarsAfterYear(Integer id) {
return carService.findCarsAfterYear(id);
}
}
I hope this will be helpful.

Error: Action : Consider defining a bean of type "package" in your configuration

the following error I am getting :
***************************
APPLICATION FAILED TO START
***************************
Description:
Field employeeDAO in com.example.demo.controller.EmployeeController required a bean of type 'com.example.demo.dao.EmployeeDAO' that could not be found.
Action:
Consider defining a bean of type 'com.example.demo.dao.EmployeeDAO' in your configuration.
my folder structure:
below are the files:
1.
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#SpringBootApplication
#EnableJpaRepositories
public class RestCrudDemo1Application {
public static void main(String[] args) {
SpringApplication.run(RestCrudDemo1Application.class, args);
}
}
2.
package com.example.demo.controller;
import java.util.List;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.http.ResponseEntity;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.dao.EmployeeDAO;
import com.example.demo.model.Employee;
#RestController
#RequestMapping("/company")
public class EmployeeController {
#Autowired
EmployeeDAO employeeDAO;
#PostMapping ("/employee")
public Employee createEmployee(#Valid #RequestBody Employee emp){
return employeeDAO.save(emp);
}
#GetMapping ("/findAll")
public List<Employee> findAll(){
return employeeDAO.findAll();
}
#GetMapping("/employees/{id}")
public ResponseEntity<Employee> getEmployeeById(#PathVariable(value = "id") Long empid){
Employee emp = employeeDAO.findOne(empid);
if (emp==null){
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok().body(emp);
}
#PutMapping("/employees/{id}")
public ResponseEntity<Employee> updateEmployee(#PathVariable(value = "id") Long empid, #Valid #RequestBody Employee empDetails){
Employee emp = employeeDAO.findOne(empid);
if (emp==null){
return ResponseEntity.notFound().build();
}
emp.setName(empDetails.getName());
emp.setDesignation(empDetails.getExpertise());
emp.setExpertise(empDetails.getExpertise());
Employee updateEmployee = employeeDAO.save(emp);
return ResponseEntity.ok().body(updateEmployee);
}
#DeleteMapping("/employees/{id}")
public ResponseEntity<Employee> deleteEmployee(#PathVariable(value = "id") Long empid){
Employee emp = employeeDAO.findOne(empid);
if (emp==null){
return ResponseEntity.notFound().build();
}
employeeDAO.delete(emp);
return ResponseEntity.ok().build();
}
}
3.
package com.example.demo.dao;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import com.example.demo.model.Employee;
import com.example.demo.repository.EmployeeRepository;
public class EmployeeDAO {
#Autowired
EmployeeRepository employeeRepository;
public Employee save(Employee emp){
return employeeRepository.save(emp);
}
public List<Employee> findAll(){
return employeeRepository.findAll();
}
public Employee findOne(Long empid){
return employeeRepository.findOne(empid);
}
public void delete(Employee emp){
employeeRepository.delete(emp);
}
}
4.
package com.example.demo.model;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotBlank;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
#Entity
#Table(name = "Employees")
#EntityListeners(AuditingEntityListener.class)
public class Employee {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long Id;
#NotBlank
private String name;
#NotBlank
private String designation;
#NotBlank
private String expertise;
#NotBlank
#Temporal(TemporalType.TIMESTAMP)
#LastModifiedDate
private Date createdAt;
public long getId() {
return Id;
}
public void setId(long id) {
Id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public String getExpertise() {
return expertise;
}
public void setExpertise(String expertise) {
this.expertise = expertise;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
}
5.
package com.example.demo.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.demo.model.Employee;
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
public Employee findOne(Long empid);
}
From the error, I get to know that employee dao bean has not been created for autowiring into the controller.
By analysing your employee dao class, you forgot to annotate with #Repository due to which bean has not been created by context scanning.
Annotate empoyeedao class with #Repository. It should solve your problem.

Error 415 Web service Rest with Spring

i'm having a problem with my service. I'm trying to send the datas to the database. However, i'm receiving this message:
Error 415
The server refused this request because the request entity is in a format not supported by the requested resource for the requested method.
I'm using Postman to sendo the code below:
Postman
Controller:
package br.com.standard.controller;
import java.util.List;
import br.com.standard.bean.Client;
import br.com.standard.service.ClientService;
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;
#RestController
public class ClientController {
#Autowired
ClientService clientService;
#RequestMapping(value = "/addClient", method = RequestMethod.POST, headers = "Accept=application/json")
public void addClient(#RequestBody Client client) {
clientService.addClient(client);
}
}
Model
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="client")
public class Client {
#Id
#Column(name="id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
int id;
#Column(name="name")
String nome;
public Client() {
super();
}
public Client(int id, String nome) {
super();
this.id = id;
this.nome = nome;
}
public long getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
}
I know that it probably is a simple question, but i tried a lot of ways without success.
Thanks in advance.
Two (alternative) solution proposals:
Be sure to send the header: Accept=application/json! (with your client.)
...or change headers = "Accept=application/json" to
consumes = org.springframework.http.MediaType.APPLICATION_JSON (leaving everything else as is)

Spring - Failed to convert property value of type java.lang.String to required type

I am making a project of the Housing Association in Spring.
When I'm trying to add an object to my list of apartments I'm getting an error that is written somehow on the page:
https://s28.postimg.org/vrhy6mbd9/blad.jpg
Apartments have relation Many to One Building.
Apartment Controller:
package pl.dmcs.spoldzielnia.controllers;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;
import pl.dmcs.spoldzielnia.domain.Apartment;
import pl.dmcs.spoldzielnia.service.ApartmentService;
import pl.dmcs.spoldzielnia.service.BuildingService;
#Controller
#SessionAttributes
public class ApartmentController {
#Autowired
ApartmentService apartmentService;
#Autowired
BuildingService buildingService;
#RequestMapping("admin/apartment")
public String listApartment(Map<String, Object> map, HttpServletRequest request) {
int apartmentId = ServletRequestUtils.getIntParameter(request, "apartmentId" , -1);
if (apartmentId > 0)
{
Apartment apartment = apartmentService.getApartment(apartmentId);
apartment.setBuilding(buildingService.getBuilding(apartmentService.getApartment(apartmentId).getBuilding().getId()));
map.put("selectedBuilding", apartmentService.getApartment(apartmentId).getBuilding().getId());
map.put("apartment", apartment);
}
else
map.put("apartment", new Apartment());
map.put("buildingList", buildingService.listBuilding());
map.put("apartmentList", apartmentService.listApartment());
return "apartment";
}
#RequestMapping(value = "admin/addApartment", method = RequestMethod.POST)
public String addContact(#ModelAttribute("apartment") Apartment apartment, BindingResult result,
HttpServletRequest request, Map<String, Object> map) {
if (result.getErrorCount()==0)
{
if (apartment.getId()==0)
{
if (apartment.getBuilding().getId() > 0)
apartment.setBuilding(buildingService.getBuilding(apartment.getBuilding().getId()));
apartmentService.addApartment(apartment);
}
else
{
apartmentService.editApartment(apartment);
}
return "redirect:/admin/apartment.html";
}
map.put("buildingList", buildingService.listBuilding());
map.put("apartmentList", apartmentService.listApartment());
return "apartment";
}
#RequestMapping("admin/delete/apartment/{apartmentId}")
public String deleteApartment(#PathVariable("apartmentId") Integer apartmentId) {
apartmentService.removeApartment(apartmentId);
return "redirect:/admin/apartment.html";
}
// #RequestMapping("/apartment")
// public ModelAndView showContacts() {
//
// return new ModelAndView("apartment", "command", new Apartment());
// }
Domain:
package pl.dmcs.spoldzielnia.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name="apartment")
public class Apartment {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
int id;
#Column(name="apartmentNumber", nullable=false)
private String number;
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#ManyToOne
private Building building;
public Building getBuilding() {
return building;
}
public void setBuilding(Building building) {
this.building = building;
}
}
}
Building Service Implementation:
package pl.dmcs.spoldzielnia.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import pl.dmcs.spoldzielnia.dao.BuildingDAO;
import pl.dmcs.spoldzielnia.domain.Building;
import pl.dmcs.spoldzielnia.domain.Building;
#Service
#Transactional
public class BuildingServiceImpl implements BuildingService{
#Autowired
BuildingDAO buildingDAO;
#Transactional
public void addBuilding(Building building) {
buildingDAO.addBuilding(building);
}
#Transactional
public List<Building> listBuilding() {
return buildingDAO.listBuilding();
}
#Transactional
public Building getBuilding(int id) {
return buildingDAO.getBuilding(id);
}
#Transactional
public void removeBuilding(int id) {
buildingDAO.removeBuilding(id);
}
#Transactional
public void editBuilding(Building building) {
buildingDAO.editBuilding(building);
}
}
Could you help me to solve my problem?
The problem is that you are assuming that Spring MVC is going to be able to fill your Apartment object from the data passed. From the form it looks like the Building number is 12, which probably is a unique identifier for the Building in the database, but how is Spring MVC going to know how to go to the database, retrieve the proper building object and put it into the Apartment object?
Remember that objects mapped through SpringMVC parameters are regular Java POJOs, not Hibernate attached entities. So, when the mapping occurs SpringMVC is trying to put "12" into the building attribute of type Building into your POJO (which explains the error you are getting).
You have two options:
First, you can register a custom formatter, that will use the passed id to retrieve a Building from the database:
import org.springframework.core.convert.converter.Converter;
public class BuildingIdToBuildingConverter implements Converter<String, Building> {
private BuildingService buildingService;
public BuildingIdToBuildingConverter(BuildingService buildingService) {
this.buildingService = buildingService;
}
#Override
public Building convert (String id) {
return buildingService.getBuilding(id);
}
}
And register it:
public class AppConfig extends WebMvcConfigurerAdapter {
...
#Bean
public BuildingService buildingService(){
return new BuildingService();
}
#Override
public void addFormatters (FormatterRegistry registry) {
registry.addConverter(new BuildingIdToBuildingConverter(buildingService()));
}
}
Second, do this work manually by sending the building id in a separate parameter:
#RequestMapping(value = "admin/addApartment", method = RequestMethod.POST)
public String addContact(#ModelAttribute("apartment") Apartment apartment, #RequestParam("buildingId") String buildingId, BindingResult result, HttpServletRequest request, Map<String, Object> map) {
if (result.getErrorCount()==0){
if (apartment.getId()==0){
apartment.setBuilding(buildingService.getBuilding(buildingId));
apartmentService.addApartment(apartment);
}
}
else{
apartmentService.editApartment(apartment);
}
return "redirect:/admin/apartment.html";
}
map.put("buildingList", buildingService.listBuilding());
map.put("apartmentList", apartmentService.listApartment());
return "apartment";
}
And change your HTML accordingly to send the buildingId value.

Resources