SpringBoot method that saves users is setting lastname as null - spring-boot

I'm new at using SpringBoot (this is my first project) and I'm trying to create a simple controller to save users with a post method that requires a JSON RequestBody that also returns a JSON containing the same user as a response. The method seems to work well, I'm gettig a JSON back when I make the post request but for some reason the lastName of the User is always null, as you can see in the image.
Post method
(I've used lombok to create getters, setters and constructors)
My User entity is pretty simple:
package com.example.demo.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Long userId;
String firstName;
String lastName;
String email;
}
And this is the UserController:
package com.example.demo.controller;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
#Slf4j
#RestController
#RequestMapping("/users")
public class UserController {
#Autowired
private UserService userService;
#PostMapping("/")
public User saveUser(#RequestBody User u) {
log.info(u.toString());
return userService.saveUser(u);
}
#GetMapping("/")
public List<User> findAllUsers() {
return userService.findAllUsers();
}
}
I supposed this is a dumb question but haven't found any similar post with a solution.
Thanks a lot!

You have typo in your body
"lastName:":"xxx" see extra : as a field name?? So your field is named lastName: which obviously does not exist in User thus null.

Request contain a typo error as "lastName:":? remove the extra colon ":" used in the "lastName".In your postman pass as "lastName":"XXX".

Related

Springboot API returning null value? How can I fix it?

Postman not showing any results
Git hub link - https://github.com/Parthhsheth/Search
The code runs perfect on my system but it is not giving any output.
Simplying returning [{}] when I try to use the search function.
Controller:
package cpp.search.controller;
import java.util.List;
import org.springframework.http.ResponseEntity;
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 cpp.search.entity.Employee;
import cpp.search.service.EmployeeService;
#RestController
#RequestMapping("/Employees")
public class EmployeeController {
private EmployeeService employeeService;
public EmployeeController(EmployeeService employeeService) {
super();
this.employeeService = employeeService;
}
#GetMapping("/search")
public ResponseEntity<List<Employee>> searchEmployee(#RequestParam("query") String query){
return ResponseEntity.ok(employeeService.searchEmployee(query));
}
#PostMapping
public Employee createEmployee(#RequestBody Employee employee) {
return employeeService.createEmployee(employee);
}
}
Service:
package cpp.search.service;
import cpp.search.entity.Employee;
import java.util.List;
public interface EmployeeService {
List<Employee> searchEmployee(String query);
Employee createEmployee(Employee employee);
}
Service.Impl:
package cpp.search.service.impl;
import java.util.List;
import org.springframework.stereotype.Service;
import cpp.search.entity.Employee;
import cpp.search.repository.EmployeeRepository;
import cpp.search.service.EmployeeService;
#Service
public class EmployeeServiceImpl implements EmployeeService {
private EmployeeRepository employeeRepository;
public EmployeeServiceImpl(EmployeeRepository employeeRepository) {
super();
this.employeeRepository = employeeRepository;
}
#Override
public List<Employee> searchEmployee(String query) {
List<Employee> employees =
employeeRepository.searchEmployee(query);
return employees;
}
#Override
public Employee createEmployee(Employee employee) {
return employeeRepository.save(employee);
}
}
Repository
package cpp.search.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import cpp.search.entity.Employee;
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
#Query("SELECT e FROM Employee e WHERE " +
"e.firstName LIKE CONCAT('%', :query, '%')" +
"Or e.lastName LIKE CONCAT('%', :query, '%')" +
"Or e.id LIKE CONCAT('%', :query, '%')")
List<Employee> searchEmployee(String query);
}
Employee.java
package cpp.search.entity;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Entity
#Table(name = "employee")
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String middleName;
private String lastName;
private boolean covid_result;
}
These are all the files.
It got linked with MySQL, since it created 'employee' table in the database.
But when I'm giving JSON data in Postman it is not working and no new rows are created in MySQL.
Also the search function is not working.
I inserted an entry manually in database and tried to search it via Postman(you can see in the picture). But it is not working.
Edit
Screenshots after using h2
Adding employee
MySQL after adding employee
Manually adding a query
Searching it using API
The data you want to save probably does not get saved because you never flush the changes.
Just use employeeRepository.saveAndFlush(employee); instead of employeeRepository.save(employee); and your data should get saved.
But I have no idea why the GET isn't working since you don't get an error and everything looks fine. I recommend you test the query in a console to make sure it's working fine.
There is no issue with your code. It works perfectly fine with h2. You can find working code with in-memory database here. So can you make sure there is data in your database with firstName or lastName as "Parthh"? If yes, can you share screenshot of your query with data?
Add employee request:
Get employee request and response:

Joining tables and returning data to react with Spring JPA

I am trying to join two entities in Spring JPA so that I can access the data in react.
I have an Event and Course entity with corresponding tables in postgres.
In react I loop through all the events in the database and display them on a card for each event. The Event table contains the courseid where that event is being played at. But I want to show on the card the coursename rather than the courseid.
I dont currently have access to this so need to join the tables so I have access to it.
I have never used queries in Spring JPA and struggling to create one to make this join.
I want something like this SQL query,
select * from event join course on course.courseid=event.course_id where eventid=5
where the eventid will be passed from react to Spring so that during each loop, it will get the correct eventid and display the corresponding coursename for that event.
Implementation:
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
#Entity
public class Course {
#Id
#Column(name = "courseid")
private Long id;
#Column(name = "coursename")
private String courseName;
#OneToMany(mappedBy = "course")
private List<Event> events;
// ...
}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
#Entity
public class Event {
#Id
#Column(name = "eventid")
private Long id;
#ManyToOne
#JoinColumn(name = "course_id")
private Course course;
// ...
}
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface EventRepository extends JpaRepository<Event, Long> {
}
Usage:
import java.util.Map;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class MyController {
#Autowired
private EventRepository eventRepository;
#GetMapping
public Map<String, ? extends Object> index(#RequestParam("id") final long id) {
// find by eventid
final Optional<Event> res = eventRepository.findById(id);
res.ifPresent(e -> {
// course name
System.out.println(e.getCourse().getCourseName());
});
return res.map(e -> Map.of("id", e.getId(), "course", e.getCourse().getCourseName()))
.orElse(Map.of());
}
}

Problem Parsing request body of type json, containing a list of string to Flux of string in Spring reactive

I have a DTO as below:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import reactor.core.publisher.Flux;
#Data
#NoArgsConstructor
#AllArgsConstructor
public class InternetPackageDto {
private String id;
private String name;
private String termsAndConditions;
private String price;
private Flux<String> packageAttributes;
private Flux<String> extras;
}
And a Database Object as below:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import reactor.core.publisher.Flux;
#Document("internet_packages")
#Data
#NoArgsConstructor
#AllArgsConstructor
public class InternetPackage {
#Id
private String id;
private String name;
private String termsAndConditions;
private String price;
private Flux<StoreableAttribute> attributes;
private Flux<StoreableAttribute> extras;
}
The StorableAttribute Database Model like so:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
#Document("package_attributes")
#Data
#NoArgsConstructor
#AllArgsConstructor
public class StoreableAttribute {
#Id
private String id;
private String name;
private String description;
}
On the Data Object the fields: Flux<StoreableAttribute> attributes and Flux<StoreableAttribute> extras are stored in a separate collection alongside the Package Object. And is handled by the mapper as below:
public InternetPackage fromDto(InternetPackageDto dto) {
var internetPackage = new InternetPackage();
internetPackage.setName(dto.getName());
internetPackage.setPrice(dto.getPrice());
internetPackage.setId(dto.getId());
internetPackage.setExtras(this.resolePackageExtras(dto));
internetPackage.setAttributes(this.resolePackageAttributes(dto));
return internetPackage;
}
private Flux<StoreableAttribute> resolePackageExtras(InternetPackageDto dto) {
return this.storeableAttributeService.resolveAttributes(dto.getExtras());
}
for the extra and similarly for the attributes also.
And a simple controller method as below:
#PostMapping(produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
public Mono<InternetPackageDto> update(#RequestBody InternetPackageDto incomingPackageDto) {
return this.packageService
.updatePackage(this.dtoMapper.fromDto(incomingPackageDto))
.map(this.dtoMapper::toDto);
}
And when I make a post request I get an error stating
org.springframework.core.codec.CodecException: Type definition error: [simple type, class reactor.core.publisher.Flux]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `reactor.core.publisher.Flux` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [Source: (io.netty.buffer.ByteBufInputStream); line: 2, column: 13] (through reference chain: com.example.api.dto.InternetPackageDto["extras"])
Some more information:
I am using the class InternetPackageDto as a request object as well as a response object.
I am using Flux<String> and not List<String> since I wasn't sure if doing blocking resolution to list was a good idea.
The attributes are stored and managed separately.
And during the time of updating or inserting the package those; if a new extra or attribute is included the attributes collection in db will be updated with the insertion of new incoming extras and attributes.
It seems like I might have made a stupid mistake because I cannot find much information about this problem, or I am doing it completely wrong.
Any help would be greatly appreciated.
I think you should do smth like this
public Mono<InternetPackageDto> toDto(InternetPackage entity) {
var internetPackage = new InternetPackageDto();
internetPackage.setName(entity.getName());
internetPackage.setPrice(entity.getPrice());
internetPackage.setId(entity.getId());
return Mono.zip(Mono.just(internetPackage), entity.getExtras().collectList(), entity.getAttributes().collectList())
.flatMap(tu->{
var dto = tu.getT1();
dto.setExtras(tu.getT2()); //To make it work in my local i made entity.getAttributes() as Flux<String> so here you will probably need to use .stream().map(dbItem->dbItem.getPropertyName())
dto.setPackageAttributes(tu.getT2());
return Mono.just(dto);
});
}

How to remove ID field while inserting values through CommandLineRunner

Well I just started learning spring boot, I work for the moment on a little project inserting Data into Database.
This is understood that "Id" shall be self created since I've include #GeneratedValue method. The problem is Intellij auto assigned property names to my data, which is prevent data entering to the database,i copy also image
Due to this auto property assigning act by intellij I'm unable to enter data in to database & getting an error (this is what I understand):
/home/kash/Documents/test/demos/src/main/java/com/example/demos/StudentConfig.java:18:32
java: constructor Student in class com.example.demos.Student cannot be applied to given
types;
required:
java.lang.Long,java.lang.String,java.lang.String,java.time.LocalDate,java.lang.Integer
found: java.lang.String,java.lang.String,java.time.LocalDate,int
reason: actual and formal argument lists differ in length
I'm looking for an advise, grateful for the help I copy all the script hereunder.
Student.java
package com.example.demos;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.time.LocalDate;
#Getter
#Setter
#AllArgsConstructor
#Entity
#Table
public class Student {
#Id
#SequenceGenerator(
name = "student_sequence",
sequenceName = "student_sequence",
allocationSize = 1
)
#GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "student_sequence"
)
private Long id;
private String name;
private String email;
private LocalDate dob;
private Integer age;
}
StudentRepository.java
package com.example.demos;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface StudentRepository
extends JpaRepository <Student, Long> {
}
StudentService.java
package com.example.demos;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.Month;
import java.util.List;
#Service
#AllArgsConstructor
public class StudentService {
#Autowired
private final StudentRepository studentRepository;
List<Student> getStudents(){
return studentRepository.findAll();
}
}
StudentConfig.java
package com.example.demos;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.LocalDate;
import java.util.List;
import static java.util.Calendar.MAY;
#Configuration
public class StudentConfig {
#Bean
CommandLineRunner commandLineRunner(
StudentRepository repository){
return args -> {
Student John = new Student(
"John Doe",
"john#hotmail.com",
LocalDate.of(2010, MAY, 19 ),
11
);
Student Haider = new Student(
"Haider",
"Haider#hotmail.com",
LocalDate.of(2024, MAY, 10 ),
2
);
repository.saveAll(
List.of(John, Haider)
);
};
}
}

How to write query by using findBy..() methods for one record

I've an entity class User_Details
package vl.cybersecurityapplication.model;
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.Table;
#Entity
#Table(name = "User_Details")
public class User_Details implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "UserId")
private int userId;
#Column(name = "FirstName")
private String firstName;
#Column(name = "LastName")
private String lastName;
#Column(name = "Password")
private String password;
#Column(name = "E_Mail")
private String eMail;
#Column(name = "Mobile_Num")
private int mobileNumber;
//getters and setters
}
Here is my repo interface
package vl.cybersecurityapplication.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import vl.cybersecurityapplication.model.User_Details;
public interface IUserRepository extends JpaRepository<User_Details, Long> {
public Integer findMobileNumberByName(String userName);
}
This is my repo class
package vl.cybersecurityapplication.repository;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import vl.cybersecurityapplication.model.User_Roles;
#Transactional
#Repository
public class UserRepository{
#Autowired
IUserRepository userRepository;
public Integer findMobileNumberByName(#PathVariable String lastName) {
int mobileNumber = userRepository.findMobileNumberByName("shaik");
System.out.println("Mobile Number : "+mobileNumber);
return mobileNumber;
}
}
I'm new to Spring Boot and JPA.
Here I need to query mobile number in User_Details table by using lastname.
i.e., Select Mobile_Num from User_Details where LastName= "xyz";
Can Some one help me how to wo write this query in my repo class.
You can write like this. But you cannot fetch only MobileNumber. You will get a complete object.
List<User> findByLastName(String lastname).
If you want to get only some fields then you should check out Projections
No need to use a native query. JPA supports object based query.
You can use List findByLastName(String lastname) which will generate that query in the backend and return the result.

Resources