Search code examples
javaspringspring-bootjavabeans

How to destroy or clear Bean object state in every use in spring boot


I'm new in spring boot and trying to figure out when we create a bean using @Bean and tries to access that bean where ever it requires using @Autowired. But i know @Bean is by default singleton and it will save its state but i want to clear its state so that it will give new newly append data or null if no data was append. Kindly help me on this. And i also want to know that is i'm following correct coding standard by using Bean with autowired because i want my every api give similar type of response that's why i create a pojo and make it a bean so that i don't have to create object again and again. Sorry if my problem is silly.. thanks in advance

This is my main class

@SpringBootApplication
public class GyftiV2Application {

    public static void main(String[] args) {
        SpringApplication.run(GyftiV2Application.class, args);
    }
    @Bean
    public ResponseData getResponse() {
        return new ResponseData();
    }
}

Below is the pojo

public class ResponseData {

    private boolean responce;
    private String error;
    private List<?> data = new ArrayList<>();

    public ResponseData() {
    }

    public boolean isResponce() {
        return responce;
    }

    public void setResponce(boolean responce) {
        this.responce = responce;
    }

    public String getError() {
        return error;
    }

    public void setError(String error) {
        this.error = error;
    }

    public List<?> getData() {
        return data;
    }

    public void setData(List<?> data) {
        this.data = data;
    }
}

Below is the service where is used my bean

@Service
public class UserServiceImpl implements UserService {

@Autowired
private ResponseData resData;

@Autowired
private UserRepository userRepository;

public ResponseData changePassword(PasswordChange pass) {
    User user = userRepository.getOne(pass.getUserId());
    if (null != user) {
        if (pass.getOldPassword().equals(user.getUser_password())) {
            if ((pass.getNewPassword().trim()).equals(pass.getConfirmPassword().trim())) {
                user.setUser_password(pass.getNewPassword());
                userRepository.save(user);
                resData.setResponce(true);
                resData.setData(Collections.singletonList("Password change successfully"));
                return resData;
            } else {
                resData.setResponce(false);
                resData.setError("Please write the same new password in the confirm section");
                return resData;
            }
        } else {
            resData.setResponce(false);
            resData.setError("Please write the correct old password");
            return resData;
        }
    } else {
        resData.setResponce(false);
        resData.setError("Something went wrong userId is not correct");
        return resData;
    }
}

}

With Controller

@RestController
@RequestMapping("/user")
public class UserController {

@Autowired
private UserService userService;

@PostMapping(value = "/changePassword")
    public ResponseEntity<ResponseData> changePassword(@RequestBody PasswordChange pass) {
        ResponseData response = userService.changePassword(pass);
        if (response.isResponce()) {
            return new ResponseEntity<>(response, HttpStatus.OK);
        }
        return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
    }

}

But when i didn't pass same newPassoword and confirmPassword then i got the response

{
  "responce": false,
  "error": "Please write the same new password in the confirm section",
  "data": []
}

And when i pass everything correct then i got the response

{
  "responce": true,
  "error": "Please write the same new password in the confirm section",
  "data": [
    "Password change successfully"
  ]
}

You will clearly see resData save its state that's why error key is still exist. I know if i pass "" in error field it will fix this issue but is there is any why to clear @Bean state ? Thanks for the help.


Solution

  • As said in the comment, you should not be using this as a Bean... It is just a regular object.

    Here is how should be your service code:

    @Service
    public class UserServiceImpl implements UserService {
    
        @Autowired
        private UserRepository userRepository;
    
        public ResponseData changePassword(PasswordChange pass) {
            User user = userRepository.getOne(pass.getUserId());
            if (null != user) {
                if (pass.getOldPassword().equals(user.getUser_password())) {
                    if ((pass.getNewPassword().trim()).equals(pass.getConfirmPassword().trim())) {
                        user.setUser_password(pass.getNewPassword());
                        userRepository.save(user);
                        ResponseData resData = new ResponseData();
                        resData.setResponce(true);
                        resData.setData(Collections.singletonList("Password change successfully"));
                        return resData;
                    } else {
                        ResponseData resData = new ResponseData();
                        resData.setResponce(false);
                        resData.setData("Please write the same new password in the confirm section");
                        return resData;
                    }
                } else {
                    ...
                }
            } else {
                ...
            }
        }
    }
    

    Things to consider:

    • You shouldn't be using your service to return a ResponseDate object sent directly over to the client. Maybe use exception in your service, like PasswordAndConfirmationAreDifferentException. This way, it is easier to deal the way you want in your controller.
    @RestController
    @RequestMapping("/user")
    public class UserController {
    
    @Autowired
    private UserService userService;
    
    @PostMapping(value = "/changePassword")
        public ResponseEntity<ResponseData> changePassword(@RequestBody PasswordChange pass) {
            try {
                userService.changePassword(pass);
                ResponseData resData = new ResponseData();
                resData.setResponce(true);
                resData.setData(Collections.singletonList("Password change successfully"));
                return new ResponseEntity<>(resData, HttpStatus.OK);
            } catch (PasswordAndConfirmationAreDifferentException e) {
                ResponseData resData = new ResponseData();
                resData.setResponce(false);
                resData.setData("Password incorrect");
                return new ResponseEntity<>(resData, HttpStatus.BAD_REQUEST);
            }
        }
    }
    
    • Use a builder to easily build a responseDate of type Error ResponseData.Error("my error") and of type Data ResponseData.Data("my message 1", "my message2", ...)