I am developing a sample spring-boot API that handles login, the API works fine however , I am having a problem during error handling. All the error handling I have seen in tutorials is done in the controller, however my logic is in the service and thats where I would like to do error handling.
How can I achieve error handling of different type of errors in the service or is it considered bad practice to do so. My current problem is that my error message looks like this :
{
"message": "Please Activate account before attempting to Sign in",
"token": " ",
"accountLocked": false,
"accountEnabled": false,
"status": false,
"balance": " ",
"profileImage": null,
"roles": null,
"baraAuthorities": null,
"customerNumber": 0,
"userEmail": "",
"name": ""
}
However I would like to have just the message and the status show and hide the rest in the response, how do I achieve this :
{
"message": "Please Activate account before attempting to Sign in",
"status": false
}
This is my code for LoginService :
@Service
public class LoginService implements UserDetailsService {
@Autowired
private UserLoginRepository loginRepository;
@Autowired
private LoginInformationRepository logininfoRepository;
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
String balance, message, pin, token, userEmail, name, profileImage = "";
Boolean status, successStatus, accounState = false;
int customerNumber, attempts;
List<Roles> userRoles = new ArrayList();
private boolean userNameExist(String username) {
UserLogin user = loginRepository.findByUsername(username);
if (user != null) {
return true;
}
return false;
}
public LoginResponse verifyLoginDetails(LoginObject user) throws LoginException {
AuthoritiesKeys userAuth = new AuthoritiesKeys();
Merchant searchedMerchant = merchantRepository.findByUserlogin_LoginCredentialsID(userdetails.getLoginCredentialsID());
DateUtility currentDate = new DateUtility();
Boolean status = false;
if (userdetails == null) {
return new LoginResponse("Unable to Login. Please check login details and try again",status);
} else {
pin = user.getPassword();
attempts = logininfoRepository.countByTodayDateAndUserLoginLoginCredentialsIDAndLoginSuccessStatusFalse(currentDate.getCurrentDate(), userdetails.getLoginCredentialsID());
if (attempts < 3) {
if (bCryptPasswordEncoder.matches(pin, userdetails.getPassword())) {
if (userdetails.isEnabled() == true) {
if (searchedMerchant != null) {
message = "Logged in Successfully";
status = userdetails.isAccountNonLocked();
accounState = userdetails.isEnabled();
userRoles = (List<Roles>) userdetails.getAuthorities();
balance = searchedMerchant.getAccount().getBalance().toString();
successStatus = true;
customerNumber = searchedMerchant.getMerchantNumber();
userEmail = searchedMerchant.getEmail();
name = searchedMerchant.getBusinessName();
return new LoginResponse(message, token, accounState, status, userRoles, successStatus, balance, userAuth, profileImage, customerNumber, userEmail, name);
} else {
return new LoginResponse("Error Merchant Information Error . Please contact the team",status);
}
} else {
return new LoginResponse("Please Activate account before attempting to Sign in",status);
}
} else {
return new LoginResponse("Wrong Username or Password",status);
}
} else {
userdetails.setAccountNonLocked(false);
userdetails.setEnabled(false);
loginRepository.save(userdetails);
return new LoginResponse("Too many attempts account has been locked",status);
}
}
}
This is my code for LoginResponse :
public class LoginResponse {
private String message;
private String token;
private Boolean accountLocked;
private Boolean accountEnabled;
private Boolean status;
private String balance;
private String profileImage;
List<Roles> roles = new ArrayList<>();
AuthoritiesKeys baraAuthorities = new AuthoritiesKeys();
private int customerNumber;
private String userEmail;
private String name;
public LoginResponse() {
}
public LoginResponse(String message, Boolean status) {
this.message = message;
this.status = status;
}
public LoginResponse(String message, String token, Boolean accountLocked, Boolean accountEnabled, List<Roles> myroles, Boolean status, String balance, AuthoritiesKeys userBaraAuthorities, String profileImage, int customerNumber, String userEmail, String name) {
this.message = message;
this.token = token;
this.accountLocked = accountLocked;
this.accountEnabled = accountEnabled;
this.status = status;
this.balance = balance;
this.roles = myroles;
this.baraAuthorities = userBaraAuthorities;
this.profileImage = profileImage;
this.customerNumber = customerNumber;
this.userEmail = userEmail;
this.name = name;
}
… // left getter and setters for brevity
}
This my code for LoginController :
@RestController
@Api(value = "Login API", produces = MediaType.APPLICATION_JSON_VALUE)
public class UserLoginController {
@Autowired
private LoginService loginService;
@RequestMapping(method = RequestMethod.POST, value = "/api/usermanagement/user/login")
@ApiOperation("login registered user")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = ResponseMessage.class)})
public LoginResponse Login(@Valid @RequestBody LoginObject credentails) throws LoginException {
return loginService.verifyLoginDetails(credentails);
}
}