Invoking other service URL using feign client gives error in postman - spring-boot

I have two services. One is UserDetails service and another is Post service. In userdetails I have a controller in which I am filtering the details of user using areacode.
#GetMapping("/userdetailsbyareacode/{areacode}")
public ResponseEntity<List<UserDetails>> getUserByAreacode(#PathVariable(value="areacode") Long areacode){
List<UserDetails> user=userdetailsService.getuserByAreacode(areacode);
if(user==null) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok().body(user);
}
now in post service I am calling this controller method using feign client and filter the post details based on areacode which is in the userdetails. Bothe userdetails and post service have u_id common.
Based on u_id I am filtering the post details from my repository.
public interface PostRepository extends JpaRepository<Posts,Long>
{
#Transactional
#Query(nativeQuery=true,value="SELECT * FROM POSTS WHERE U_ID=:u_id")
List<Posts> findPostsByU_id(#Param("u_id") Long u_id);
}
And here is my post DAO-
public List<Posts> findByU_id(Long u_id){
List<Posts> post=new ArrayList<>();
postRepository.findPostsByU_id(u_id).forEach(post::add);
return post;
}
Now this is the post controller method which I am calling in postman, which is using the feign proxy for calling the UserDetails controller method.
#GetMapping("/findpostbyareacode-feign/{areacode}")
public List<Posts> getPostByAreacodeUsingfeign(#PathVariable(value="areacode") Long areacode){
List<UserDetails> usersList=userProxy.getUserByAreacode(areacode);
List<Posts> postList=new ArrayList<>();
List<Posts> totalPost=new ArrayList<>();
for(UserDetails users : usersList) {
totalPost=postService.findByU_id(users.getU_id());
for(Posts posts : totalPost) {
postList.add(posts);
}
}
return postList;
}
When I am hitting the URL in postman, I am getting this error.
"error": "Internal Server Error",
"message": "could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet",
Here is my UserDetails entity class of UserDetails service.
#Entity
#Table(name="user_details")
#Builder
#Data
#Getter #Setter #NoArgsConstructor #AllArgsConstructor
public class UserDetails implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="user_id", unique=true)
private Long user_id;
#Column(name="user_name", length=35, nullable=false)
#Size(min=2,message="Name should have atleast 2 character")
private String user_name;
#Column(name="gender", nullable=false)
private String gender;
#Column(name="dob")
#DateTimeFormat(pattern="yyyy-MM-dd")
private Date dob;
#Column(name="email", length=50, unique=true, nullable=false)
private String email;
#Column(name="phno", length=11, nullable=false)
private String phno;
#Column(name="password", nullable=false)
//#JsonIgnore
private String password;
#Column(name="areacode", length=11)
private Long areacode;
#Column(name="u_Id")
private Long u_id;
}
And here is my post entity of Post service-
#Entity
#Table(name="vob_posts")
#Getter #Setter #NoArgsConstructor #AllArgsConstructor
public class Posts implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="post_id", unique=true)
private Long post_id;
#Column(name="contents")
private String contents;
#Column(name="u_id")
private Long u_id;
}
My both services are registered in eureka.
Cant solve this issue, pls help anyone.

why you are making code complex and How come primary key returns List<Posts>. Try with the below code.
Just make change below in your Entity and Repository.
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="user_id", unique=true)
private Long id;
//private Long userId;
#Column(name="user_name", length=35, nullable=false)
#Size(min=2,message="Name should have atleast 2 character")
private String userName;
public interface PostRepository extends JpaRepository<Posts,Long>
{
}
(or)
public interface PostRepository extends CrudRepository<Posts,Long>
{
//Optional<Posts> posts findByUserId(Long userId);
}
Service Layer :
Approach 1 : Using JPA Repository
Posts posts = repo.getOne(userId);
Approach 2 : Using Crud Repository
Posts posts = repo.findById(userId).get();
//Posts posts = repo.findByUserId(userId).get();

Related

How to use Spring Boot CRUD API to insert data in multiple tables using one POST endpoint

How can a data be inserted using single POST endpoint in multiple tables. For example there are two tables
1. Employee
2. Department
These two tables have a primary key and foreign key relationship.
How to achieve data insertion in two tables using a single POST endpoint ?
Ok I see what you want.... your entities have to look like this...
You have to create a one to one relationship something like this:
Department entity:
#Entity
#Table
#Data
public class Department {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String description;
}
Employee entity:
#Entity
#Table
#Data
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String email;
private String address;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "department_id", referencedColumnName = "id")
private Department department;
}
And than you can add Data on Startup like this:
#Component
public class DBSeeder implements CommandLineRunner {
#Autowired
private EmployeeRepository repository;
#Override
public void run(String... args) throws Exception {
Department dep1 = new Department();
dep1.setName("Demolition");
dep1.setDescription("Do demo");
Employee emp1 = new Employee();
emp1.setName("John Rambo");
emp1.setEmail("john.rambo#demolition.com");
emp1.setAddress("Demolition Av. 5");
emp1.setDepartment(dep1);
this.repository.save(emp1);
}
}
#Repository
public interface EmployeeRepository extends CrudRepository<Employee, Long> {
Employee save(Employee employee);
}
Do you also ask how the entity objects have to look like?

When does the hibernate session gets closed

I have created the following entities.
#Entity
public class Student {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
#OneToMany(mappedBy = "student")
private List<Book> books;
}
#Entity
public class Book {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
#ManyToOne
#JoinColumn(name = "STUDENT_ID")
private Student student;
}
My controller looks like this
#RestController
public class Controller {
MyService myService;
public Controller(MyService myService) {
this.myService = myService;
}
#GetMapping("student")
public List<Book> getBooksForStudent(Long id) {
return myService.getBooks(id);
}
}
The service is as follows.
public class MyService {
#Autowired
private StudentRepo studentRepo;
public List<Book> getStudent(Long id) {
Optional<Student> studentOptional = studentRepo.findById(id);
return studentOptional.map(Student::getBooks).orElseThrow(IllegalArgumentException::new);
}
}
I am getting the list of books as expected. But as I'm having lazy loaded list for books I should be getting a LazyInitializationException. I have not added transnational to the method and I'm returning the list of books from the entity itself without mapping it to a DTO. Why is the hibernate session not getting closed after the end of the method?
#RestController is transactional by default. Spring boot automatically registers an OpenEntityManagerInViewInterceptor when you use a web application/you use JPA. Refer #RestController methods seem to be Transactional by default, Why?

How get User to email?

I need get user to email with jpa
i have this code:
#Repository
public interface UserRepository extends JpaRepository<User, Long> {
User findByEmail(#Param("email") String email);
User findById(#Param("id") Long id);
}
When i tried this :
User owner = userRepository.findById(user.getId()); //yes
User user=userRepository.findByEmail(email);//no
My class User is:
#Entity
#Table(name = "User")
public class User implements Serializable {
private static final long serialVersionUID = -3009157732242241606L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "name")
private String name;
#Column(name = "password")
private String password;
#Column(name = "email")
private String email;
public User() {
}
//getters and setters
}
I want to obtain a user through the user's email, if I can obtain it through his id but I also need to obtain it through email
In you Model class "email" is not an unique so that it will return multiple rows to avoid that add
#Entity
#Table(name = "User")
public class User implements Serializable {
.....
#Column(unique=true,...)// .. add your extra
private String email;
.....
}
If you want top 1 result to be returned you could change the method
User findByEmail(#Param("email") String email);
with
User findOneByEmail(String email);

Are there #MappedSuperclass in Spring Reactive Data (R2DBC)

I have a super Entity class like this:
#Getter
#Setter
#NoArgsConstructor
public class GenericEntity {
#Id
private Long id;
#JsonIgnore
#CreatedBy
private Long createdBy;
#JsonIgnore
#CreatedDate
private Long createdDate;
#JsonIgnore
#LastModifiedBy
private Long updatedBy;
#JsonIgnore
#LastModifiedDate
private Long updatedDate;
#JsonIgnore
#Version
private Integer version = 0;
}
and a Role class extends from GenericEntity like this:
#Getter
#Setter
#NoArgsConstructor
public class Role extends GenericEntity {
private String name;
private String desc;
private Integer sort;
}
And after that I have interface RoleRepo like this:
#Repository
public interface RoleRepo extends ReactiveCrudRepository<Role, Long>;
In Router function, I have 2 handler methods
private Mono<ServerResponse> findAllHandler(ServerRequest request) {
return ok()
.contentType(MediaType.APPLICATION_JSON)
.body(roleRepo.findAll(), Role.class);
}
private Mono<ServerResponse> saveOrUpdateHandler(ServerRequest request) {
return ok()
.contentType(MediaType.APPLICATION_JSON_UTF8)
.body(request.bodyToMono(Role.class).flatMap(role -> {
return roleRepo.save(role);
}), Role.class);
}
The method findAllHandler works fine, but the saveOrUpdateHandler throw exception like this:
java.lang.IllegalStateException: Required identifier property not found for class org.sky.entity.system.Role!
at org.springframework.data.mapping.PersistentEntity.getRequiredIdProperty(PersistentEntity.java:105) ~[spring-data-commons-2.2.0.M2.jar:2.2.0.M2]
at org.springframework.data.r2dbc.function.convert.MappingR2dbcConverter.lambda$populateIdIfNecessary$0(MappingR2dbcConverter.java:85) ~[spring-data-r2dbc-1.0.0.M1.jar:1.0.0.M1]
But when I move
#Id
private Long id;
from GenericEntity class to Role class, the two methods work fine.
Are there any Annations #MappedSuperclass/JPA in Spring Reactive Data like that
I wish the id field in GenericEntity for all extends class
Thanks for your help
Sorry, my English so bad
I had a similar problem and after some search, I didn't find an answer to your question, so I test it by writing code and the answer is spring data R2DBC doesn't need #Mappedsuperclass. it aggregates Role class properties with Generic class properties and then inserts all into the role table without the need to use any annotation.

Retrieve an object which has a POJO as a primary key with Spring JPA

I have the following classes: DepartmentMember and Account, mapped by a OneToOne relationship.
This is the DepartmentMember class:
#Entity(name="departmentmember")
#Table(name="departmentmember")
#Embeddable
public class DepartmentMember {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name="name", nullable=false)
private String nume;
#Column(name="lastName", nullable=false)
private String prenume;
#OneToOne(mappedBy="departmentMember",cascade=CascadeType.ALL,fetch=FetchType.LAZY, optional=false)
#JsonIgnore
private Account account;
public DepartmentMember() {}
public DepartmentMember(String nume, String prenume, String cNP, String email) {
super();
this.nume = nume;
this.prenume = prenume;
}
//getters and setters
}
And this is the Account class :
#Entity(name="users")
#Table(name="users")
public class Account {
#Id
private int id;
#Column(name="username", unique=true, nullable=false)
private String username;
#Column(name="password", nullable = false)
private String password;
#Column(name="authorities", nullable=false)
private String authorities;
#OneToOne(fetch=FetchType.EAGER)
#MapsId
#Embedded
private DepartmentMember departmentMember;
public Account() {}
public Account(String username, String password, String authorities) {
super();
this.username = username;
this.password = password;
this.authorities = authorities;
}
//getters and setters
}
I have defined an interface AccountRepository which extends the CrudRepository interface provided by Spring JPA.
What I want to do is define a query, which takes as a parameter a DepartmentMember id and retrieves the associated account for that member. Now this is how an Account object looks like:
{
"username": "Maria_Popescu",
"password": "4ec38c6e-2463-4562-99ba-9f6c2b4528c4",
"authorities": "ROLE_USER",
"departamentMember": {
"id": 2,
"nume": "Popescu",
"prenume": "Maria",
}
I tried using the findOne(int id) method, but it didn't work, so which is the correct approach to solve this?
Edit:
In the AccountRepository I have defined the following method :
Account findByDepartmentMemberId(int id) and I still get a not found error.
There was actually another problem in my controller. I managed to get it working by adding
Account findByDepartmentMemberId(#Param("id")int id);
in the AccountRepository

Resources