Setters for session scoped bean not working in RestController - spring

I'm trying to get the username from the session scoped bean once the user has logged in using /users/login
I've Autowired a session scoped bean into a RestController and in one of the endpoints in the rest controller, I'm invoking a setter on the session scoped bean. But the effect of setters is not visible for requests from the same session.
The following is my session scoped bean:
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
#Getter
#Setter
public class SessionSpecificUserDetails implements Serializable {
private String userName;
}
import lombok.Getter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.annotation.SessionScope;
#Getter
#Configuration
public class UserSessionDetailsConfiguration {
#Bean
#SessionScope
public SessionSpecificUserDetails sessionSpecificUserDetails() {
return new SessionSpecificUserDetails();
}
}
The following is the RestController
import com.course.backend.coursebackend.config.SessionSpecificUserDetails;
import com.course.backend.coursebackend.dao.User;
import com.course.backend.coursebackend.repository.UserRepository;
import com.course.backend.coursebackend.utils.ResponseUtils;
import com.course.backend.coursebackend.utils.UserUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
#RestController
#RequestMapping("/users")
public class UserController {
#Autowired
UserRepository userRepository;
#Autowired
SessionSpecificUserDetails sessionSpecificUserDetails;
#GetMapping("/getLoggedInUser")
public String getLoggedInUser() {
return sessionSpecificUserDetails.getUserName();
}
#PostMapping("/login")
public ResponseUtils.CustomResponse login(#RequestBody User user) {
List<User> users = getAllUsers();
Optional<User> optionalUser = users.stream()
.filter(currentUser -> currentUser.getUserName().equals(user.getUserName()))
.findAny();
if (optionalUser.isEmpty()) {
return ResponseUtils.getErrorResponse(List.of("Username not found!"));
}
if (optionalUser.get().getPassword().equals(user.getPassword())) {
sessionSpecificUserDetails.setUserName(user.getUserName());
return ResponseUtils.getSuccessResponse("Login Successful!");
}
return ResponseUtils.getErrorResponse(List.of("Login failed due to wrong password!"));
}
}
I see that spring is creating proxy for the session scoped bean. (And may be because of that my setters are not having any effect even for the same session?)
My question is what's the correct way to use the session scoped beans in the RestController? And what's the good way to get the username for the same session across requests?
I tried marking UserController also as #SessionScope but that's also not working.

Related

jpa repositofy findall() returns empty list

I'm practicing making web pages using spring boot.
I created an h2 DB and connected it, and I want to show the name properties of the members table as a list on my web page.
I created the findall() method, but only an empty list is returned. What's wrong with my code?
my web page
MemberRepository
package com.example.testproject.store.h2.repository;
import com.example.testproject.store.h2.domain.Members;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface MemberRepository extends JpaRepository<Members, Integer> {
}
MemberService
package com.example.testproject.store.h2.service;
import com.example.testproject.store.h2.domain.Members;
import java.util.List;
public interface MemberService {
List<Members> getAll();
}
MemberServiceImpl
package com.example.testproject.store.h2.service;
import com.example.testproject.store.h2.domain.Members;
import com.example.testproject.store.h2.repository.MemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.lang.reflect.Member;
import java.util.List;
#Service(value = "memberServiceImpl")
public class MemberServiceImpl implements MemberService {
#Autowired
private MemberRepository memberRepository;
public List<Members> getAll(){
return memberRepository.findAll();
}
}
MemberController
package com.example.testproject.controller;
import com.example.testproject.store.h2.domain.Members;
import com.example.testproject.store.h2.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
#RestController
public class MemberController {
#Autowired
private MemberService memberService;
#GetMapping(value = "/members")
public List<Members> getAll() {
List<Members> users = memberService.getAll();
return users;
}
/*#GetMapping(value = "/members")
public List<Members> getAll() throws Exception {
return memberService.getAll();
}*/
}
Members(Entity)
package com.example.testproject.store.h2.domain;
import jakarta.persistence.*;
#Entity
#Table(name = "members")
public class Members {
#Id
private int id;
#Column
private String name;
}
I want to show the name properties of the members table as a list on my web page.
You have missed the getter setter method in entity class either you need to 1:-define getter setter method for each field or
2:-you need to add lombook dependency in pom.xml file and add #Data annootation on top of entity class so that when spring uses your entity can set and get the value from database and if you dontot want to give id explicitly then add #GeneratedValue(strategy=GenerationType.AUTO) so that spring automatically increase you id
I think you missed getters and setters in your Entity
Class just add them by using #Data annotation and try again.
You missed getters and setters for the fields in your Entity
You do not need any library, you can write it by yourself.
Otherwise, even if you use lombok, you should avoid to use #Data annotation on Entity, because it could lead to errors with default implementation of equals and hashCode. Instead you can use annotations #Getter and #Setter on the class.

How to resolve SpringBoot 405 Method Not Allowed Error?

I am expecting to receive the message "Works" on Postman (used for temporary testing until I implement the frontend and forms using HTML and CSS) when I type in the URL "http://localhost:8080/registration". This should be happening based on the code posted below. Instead, I receive the 405 Method Not Allowed Error.
WebSecurityConfig class
package com.example.finalVersionBookProject.security.config;
import com.example.finalVersionBookProject.appuser.AppUserService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final AppUserService appUserService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
public WebSecurityConfig(AppUserService appUserService, BCryptPasswordEncoder bCryptPasswordEncoder) {
this.appUserService = appUserService;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
Registration class
package com.example.finalVersionBookProject.registration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
#Controller
#RequestMapping(path = "/registration")
public class Registration {
private RegistrationService registrationService;
#PostMapping()
public String register(#RequestBody RegistrationRequest request) {
return registrationService.register(request);
}
}
Registration Service Class
package com.example.finalVersionBookProject.registration;
import org.springframework.stereotype.Service;
#Service
public class RegistrationService {
public String register(RegistrationRequest request) {
return "works";
}
}
I have tried replacing RestController with Controller, changing some of the annotations, both with no success. I tried using the IntelliJ debugger to resolve the issue, but it did not provide any new information that was helpful in solving the problem. I am expecting the message "Works" to be outputted to Postman, but I get the 405 Error.
When you type in URL http://localhost:8080/registration in Postman, what method did you use? I suspect you are using GET whilst your controller has a #PostMapping which support POST method.
You can try to use #GetMapping instead.

#PropertyResource is not working in Spring Boot

Below is my Property class:
package com.example.sdasDemo;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
#Configuration
#PropertySource("classpath:info.properties")
#ConfigurationProperties(prefix = "feeder")
#Getter
#Setter
public class Properties {
public String[] id;
}
Below is the simple controller:
package com.example.sdasDemo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class controller {
#Autowired
Properties properties;
#RequestMapping("/get")
public String getData(){
System.out.println(properties.getId());
return properties.getId();
}
}
Below is the info.properties file
feeder.id=soumik,das,21022021
http://localhost:8080/get returns null pointer exception
Why this #PropertyResouce is not working? What am I missing here. Please suggest.
I found the problem. It was happening due to wrong profile name provided. For that reason, the property file location could not be found and resulting null pointer exception.

Encountered error "Consider defining a bean of type 'java.util.concurrent.atomic.AtomicReference' in your configuration"

I am getting the below error while starting spring boot application.
The injection point has the following annotations:
#org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type
'java.util.concurrent.atomic.AtomicReference' in your configuration.
Below is the code .
package de.summer.sampleapplayerv1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#SpringBootApplication(scanBasePackages = {"de.summer.sampleapplayerv1"})
#EnableConfigurationProperties
#EnableJpaRepositories (basePackages ="de.summer.sampleapplayerv1.repository")
#EnableTransactionManagement
public class Sampleapplayerv1Application {
public static void main(String[] args) {
SpringApplication.run(Sampleapplayerv1Application.class, args);
}
}
package de.summer.sampleapplayerv1.service;
import de.summer.sampleapplayerv1.domain.QueueAndPublish;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
#Slf4j
#Service
public class QueueAndPublishServiceImpl implements QueueAndPublishService{
private final AtomicReference<List<QueueAndPublish>> currentJob;
public QueueAndPublishServiceImpl(
#Qualifier("currentJob") AtomicReference<List<QueueAndPublish>> currentJob
){
this.currentJob=currentJob;
}
#Override
public QueueAndPublish getJobStatus(UUID jobId) {
return (QueueAndPublish) currentJob.get().stream()
.filter(j -> j.getJobId()==jobId)
.collect(Collectors.toList());
}
#Override
public List<QueueAndPublish> getAllJobStatus() {
return currentJob.get();
}
#Override
public QueueAndPublish getCategoryDataProcess() {
List<QueueAndPublish> processList=new ArrayList<QueueAndPublish>();
QueueAndPublish process=QueueAndPublish.builder()
.jobId(UUID.randomUUID())
.jobName("Name for Job")
.jobStatus("Not Yet Started")
.build();
Thread t1=new Thread(process.getJobId().toString()){
#Override
public void run(){
log.info("How are you doing");
process.setJobStatus("Completed");
}
};
t1.start();
processList.add(process);
currentJob.set(processList);
return process;
}
#Override
public QueueAndPublish getCatgeoryDataProcessStatus() {
return null;
}
}
package de.summer.sampleapplayerv1.domain;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.io.Serializable;
import java.util.UUID;
#Getter
#Setter
#Builder
#Entity
public class QueueAndPublish implements Serializable {
#Id
private UUID jobId;
private String jobName;
private String jobStatus;
}
If I remove the constructor, spring boot application is starting up without any errors. If included , start up is failing with unsatisfied dependency errors.
Can someone please help on what is wrong with config?
You expect Spring to create an instance of class QueueAndPublishServiceImpl for the implementation of QueueAndPublishService. This instance needs a constructor parameter of type AtomicReference<List<QueueAndPublish>> injected.
But you obviously do not define any Spring bean (Bean, Component, Service, ...) of that type.
Edit:
public QueueAndPublishServiceImpl(
#Qualifier("currentJob") AtomicReference<List<QueueAndPublish>> currentJob
){
this.currentJob=currentJob;
}
Here you define a constructor parameter to have a AtomicReference<List<QueueAndPublish>>, and even specify it with a #Qualifier. So you need to provide a Spring bean of this class with this qualifier, otherwise Spring cannot inject it into the constructor call.
Consider defining a bean of type 'java.util.concurrent.atomic.AtomicReference' in your configuration.
Means "something like" adding this to your Sampleapplayerv1Application:
#Bean("currentJob") AtomicReference<List<QueueAndPublish>> currentJob() {
// or a list implementation of your choice.
return new AtomicReference<>(new java.util.ArrayList<>());
}

Spring rest controller does not validate my DTO

I have this request and response:
#Data
public class TestRequestDto {
#Min(7)
private String name;
}
#Data
public class TestResponseDto {
private String response;
}
And I have a controller:
package com.example.validation.demo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
#Slf4j
#RestController
public class TetController {
#PostMapping("/test")
public TestResponseDto getTestResponseDto(#Valid #RequestBody TestRequestDto request){
log.info(request.getName());
TestResponseDto response = new TestResponseDto();
response.setResponse("response");
return response;
}
}
I send a post request({"name":"test"}) with an invalid name but it works. What am I doing wrong?
Starting with Boot 2.3, we also need to explicitly add the spring-boot-starter-validation dependency

Resources