Java throwing wrong exception - java

I have created 2 custom exceptions to handle creating and persisting new users to a DB. The email (username) is the unique ID so if an email is duplicated an exception should be thrown since the unique ID already exists.
I'm also doing a password confirmation match. This confirmation match also will throw a custom exception of passwords don't match. These 2 piece work correctly independently of each other, however, when I put everything together and test, if a password confirmation fails its throwing the username already exists exception instead of passwords do not match exception. Why?
I've tried reordering the code but that doesn't seem to matter. I also tried if/else rather then just if but got the same results
//Username(email) must be unique
try {
//password and confirm password must match
if (!newGcUser.getPassword().equals(newGcUser.getConfirmPassword())) {
throw new PasswordMatchException("password and confirm password does not match");
}
//if passwords match - persist to DB
newGcUser.setPassword(bCryptPasswordEncoder.encode(newGcUser.getPassword()));
//Do NOT persist or show the confirm Password
newGcUser.setConfirmPassword("");
//set user
newGcUser.setName(newGcUser.getUsername());
return userRepository.save(newGcUser);
} catch (Exception e) {
throw new UsernameAlreadyExistsException("Username: '" + newGcUser.getUsername() + "' already exists.");
}
}
I'm using Postman to test.
If I test an email I know isn't registered and mismatch the passwords I get the UsernameAlreadyExistsException message instead of the PasswordMatchException

This happens because your try {} catch (Exception e) {} block is catching the exception you're throwing within the block, throw the exception outside the try catch block and it should work catch :
// password and confirm password must match
if (!newGcUser.getPassword().equals(newGcUser.getConfirmPassword())) {
throw new PasswordMatchException("password and confirm password does not match");
}
// Username(email) must be unique
try {
// if passwords match - persist to DB
newGcUser.setPassword(bCryptPasswordEncoder.encode(newGcUser.getPassword()));
// Do NOT persist or show the confirm Password
newGcUser.setConfirmPassword("");
// set user
newGcUser.setName(newGcUser.getUsername());
return userRepository.save(newGcUser);
} catch (Exception e) {
throw new UsernameAlreadyExistsException("Username: '" + newGcUser.getUsername() + "' already exists.");
}
(or catch a less generic exception eg the exception which is thrown from userRepository.save and rethrow it, then it will only catch that exception rather than all)

This is happening because your PasswordMatchException extends Exception and your catch block is catching it and throwing a UsernameAlreadyExistsException.
Reducing your code down to illustrate my point:
try {
throw new PasswordMatchException();
} catch(Exception e) {
throw new UsernameAlreadyExistsException();
}
Without knowing more about what kinds of exceptions your code can throw, you probably have two solutions:
1) Catch something more specific than Exception.
2) Move the password check outside your try/catch block.

Advise to break into different methods and make it modular:
private void matchPassword(..newGcUser..) throws PasswordMatchException{
// password and confirm password must match
if (!newGcUser.getPassword().equals(newGcUser.getConfirmPassword())) {
throw new PasswordMatchException("password and confirm password does not match");
}
}
Method to persist should catch the specific exception:
// Username(email) must be unique
try {
// if passwords match - persist to DB
...
return userRepository.save(newGcUser);
} catch (DataIntegrityViolationException e) {
throw new UsernameAlreadyExistsException("Username: '" + newGcUser.getUsername() + "' already exists.");
}

Related

Unreachable catch block for PSQLException. This exception is never thrown from the try statement body

I am trying to get the PSQLException exception, however it tells me that this block cannot be reached, does anyone know why? I mean, I can't run or anything, Eclipse marks it as an error. However, if, for example, I put Exception e, instead of PSQLException e, it does not give an error.
#DeleteMapping("/delete/{pais_id}")
public Resultado<Pais> eliminaPais(#PathVariable("pais_id") Long pais_id, HttpServletResponse response) {
Resultado<Pais> res = new Resultado<>();
try {
Optional<Pais> existePais = paisService.getFindById(pais_id);
if (existePais.isPresent()) {
if (pais_id != null) {
// monedaService.setANullPais(pais_id);
try{
paisService.getEliminaPais(pais_id);
res.setCodigo(200);
res.setMensaje("El país " + existePais.get().getNombre() + " ha sido eliminado");
res.setDatos(existePais.get());
}catch(PSQLException e) { //HERE
res.setCodigo(400);
res.setMensaje("El país no " + existePais.get().getNombre() + " ha sido eliminado");
res.setDatos(null);
}
}
} else {
res.setSuccess(false);
res.setMensaje("Se ha producido un error, el ID proporcionado no existe " + pais_id);
res.setCodigo(400);
}
} catch (Exception e) {
res.setSuccess(false);
res.setMensaje("Se ha producido un error: " + e.getMessage());
res.setCodigo(400);
}
response.setStatus(res.getCodigo());
return res;
}
PSQLException is a checked exception. That means methods which throw that exception are required to document it in their signature. The compiler has detected that no code in your try block throws that type of exception. It knows that the catch block is redundant and is likely a user error, so it produces a failure so you can fix it.
Exception is a broader classification and includes the set of all unchecked exceptions, which are not required to be documented in a method signature. In this case, the compiler doesn't know exactly what might be thrown, but it knows that something might be. So in this case, the catch block is not (necessarily) redundant, and so it will not report the same failure.
Since it is an checked exception, you are trying to catch an exception which is never thrown.
You try block code should throw an Checked exception then only you can catch it.
In your case that is PSQLException.

complaining about logging and rethrowing the exception in sonar [duplicate]

I have the following piece of code in my program and I am running SonarQube 5 for code quality check on it after integrating it with Maven.
However, Sonar is complaining that I should Either log or rethrow this exception.
What am I missing here? Am I not already logging the exception?
private boolean authenticate(User user) {
boolean validUser = false;
int validUserCount = 0;
try {
DataSource dataSource = (DataSource) getServletContext().getAttribute("dataSource");
validUserCount = new MasterDao(dataSource).getValidUserCount(user);
} catch (SQLException sqle) {
LOG.error("Exception while validating user credentials for user with username: " + user.getUsername() + " and pwd:" + user.getPwd());
LOG.error(sqle.getMessage());
}
if (validUserCount == 1) {
validUser = true;
}
return validUser;
}
You should do it this way :
try {
DataSource dataSource = (DataSource) getServletContext().getAttribute("dataSource");
validUserCount = new MasterDao(dataSource).getValidUserCount(user);
} catch (SQLException sqle) {
LOG.error("Exception while validating user credentials for user with username: " +
user.getUsername() + " and pwd:" + user.getPwd(), sqle);
}
Sonar shouldn't bother you anymore
What sonar is asking you to do, is to persist the entire exception object.
You can use something like:
try {
...
} catch (Exception e) {
logger.error("Error", e);
}
I stumbled across the same issue. I'm not 100% sure if I'm completely right at this point, but basically you should rethrow or log the complete Exception. Whereas e.getMessage() just gives you the detailed message but not the snapshot of the execution stack.
From the Oracle docs (Throwable):
A throwable contains a snapshot of the execution stack of its thread at the time it was created. It can also contain a message string that gives more information about the error. Over time, a throwable can suppress other throwables from being propagated. Finally, the throwable can also contain a cause: another throwable that caused this throwable to be constructed. The recording of this causal information is referred to as the chained exception facility, as the cause can, itself, have a cause, and so on, leading to a "chain" of exceptions, each caused by another.
This means the solution provided by abarre works, because the whole exception object (sqle) is being passed to the logger.
Hope it helps.
Cheers.
If you believe that SQLException can be safely ignored, then you can add it to the list of exceptions for squid:S1166 rule.
Go to Rule-> Search squid:S1166.
Edit exceptions in Quality Profile.
Add SQLException to the list.

How do I display database trigger errors on a web application through Payara5

This is a standard error I receive for all Errors parsed from Database Triggers. I use Payara5 as the Application Server and Netbeans 8.2 IDE. In the instance on the picture, it was supposed to display "ID Number mandatory for applicants order that 18 years of age".
How do I make sure that the exact error as in the trigger, appears on the Web Application?
Given your stacktrace it looks like you need to remove the ExceptionUtils.findRootException(ex).getMessage() and just use ex.getMessage() since the thrown topmost Exception already contains the message that you need.
I would try with the following code when an Exception is thrown:
catch (Exception ex) {
JSFUtils.addMessageSessionError(
ExceptionUtils.formatException(AdHocTools.getCurrentMethodName(),
ex.getMessage());
}
However, ExceptionUtils.findRootException(ex).getMessage() might be there for a reason. There are cases where the topmost Exception is pretty general (e.g. an EJBException) and you really need to get to the root exception to get a meaningful message.
You could also try with this code which returns an SQLException if applicable and in other cases the root Exception.
catch (Exception ex) {
Throwable rootCause = ex;
while (rootCause.getCause() != null && rootCause.getCause() != rootCause) {
if ( rootCause instanceof java.sql.SQLException ) {
break;
}
rootCause = rootCause.getCause();
}
JSFUtils.addMessageSessionError(
ExceptionUtils.formatException(AdHocTools.getCurrentMethodName(),
rootCause.getMessage());
}

AssertTrue in try/catch

Please what exactly am i doing wrong.
I have checked and checked but all to no avail.
I have also checked previous code but I am not getting an error so my code works fine but just slight error somewhere.
The code is running fine and assertTrue is behaving as expected but when I put it in the try/catch, I only get the log in the catch block, even when text was found.
I believe that if the assertTrue found the text, it should go to the next line of code in the try block and pass the test rather than the catch block. Don't get me wrong, I am not getting any error just that it's printing out the wrong message.
Code below including print out message in console.
public boolean verifyTextPresent(String value) throws Exception {
Thread.sleep(5000);
try{
boolean txtFound = driver.getPageSource().contains(value);
log.log(value + " : text Found, .......continue");
return txtFound;
}catch(Exception e)
{
log.log(value + " :NOT Found, check element again ot Contact developer.");
return false;
}
}
public static void verifySignOutBtn() throws Exception
{
log.header("VERIFY IF SIGN_OUT EXIST AND CLICKABLE.........");
callMethod.myAccountPageNative(CONSTANTElements.SIGN_IN_LINK);
Thread.sleep(2000);
log.header("LOCATE SIGN_OUT BTN, AND CLICK ......");
callMethod.elementPresent_Click(By.cssSelector(CONSTANTElements.SIGN_OUT_BTN));
Thread.sleep(4000);
log.header("VERIFY SIGN_OUT NAVIGATES TO HOME PAGE WHEN CLICKED......");
try{
Assert.assertTrue(callMethod.verifyTextPresent("SIGN IN"), "SIGN IN");
log.log("User Successfully Signed Out.......");
log.log("Test Passed!...");
//callMethod.close();
}
catch(Throwable e)
{
log.log("User NOT Successfully Signed Out.... Contact developer.");
log.log("Test Failed!...");
//callMethod.close();
}
callMethod.close();
}
}
Msg in console:
SIGN IN : text Found, .......continue
User NOT Successfully Signed Out.... Contact developer.
Test Failed!...
The confusing part is that why is it printing out the catch block instead of the next line in the try block?
Shouldn't it be the other way around?
Assert.assertTrue("Message if it is false", callMethod.verifyTextPresent("SIGN IN"));
The only possible explanation is that verifyTextPresent(String value) returns false (you never actually check the value of boolean txtFound) and assertTrue fails (throwing an AssertionError which is not handled well in your catch block). To find out, replace this
log.log(value + " : text Found, .......continue");
for example with this line
log.log(value + " : text Found, ......." + txtFound);
or just print the stacktrace in catch block.

Java SQLException separate according to errorcode

I need to separate SQLExceptions according to ErrorCode. I have the following if statement in catch block but the else condition is printed always.
catch (SQLException ex) {
if (ex.getErrorCode() == 28502){
System.out.println("Username Problem");
}
else{
System.out.println("Other Problem");
}
Logger.getLogger(FirstTimeMainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
Actually, when I enter unexpected username when creating DB, the following SQLExceptions are thrown.
java.sql.SQLException: Failed to create database 'myDB', see the next exception for details.
//rest of exception.
Caused by: ERROR XJ041: Failed to create database 'myDB', see the next exception for details.
//rest of exception.
Caused by: ERROR XBM01: Startup failed due to an exception. See next exception for details
//rest of exception.
Caused by: ERROR 28502: The user name 'AAA.AAA' is not valid.
//rest of exception.
But my catch is always print Other Problem. How can I separate different SQLExceptions according to last ErrorCode?
--- SOLVED ---
Thanks for the routed comments for #blm first.
Trick is; Other coming Exceptions (1st and 2nd) has String values in their SQLState only numeric value in their ErrorCode.
SQLException chain 3rd exception has 28502 both SQLState and ErrorCode. This is the difference between 1st and 2nd Exceptions i think.
So i have changed my
Catch Block;
catch (SQLException se) {
do {
if(se.getSQLState().equals("28502")){
System.out.println("Username Problem");
}
else{
System.out.println("Other Problem");
}
} while ((se = se.getNextException()) != null);
}
Output is;
Other Problem
Other Problem
Username Problem
you should get the cause exceptions by using the 'getCause()' method of the SqlExeption object that was caught. then, you can cast the result to Exception and check its error code.
check this for more info: Throwable.getCause()
Edit:
SQLException temp = ex;
while(temp.getCause() != null)
{
temp = (Exception)temp.getCause();
}
// check if temp is SQLException and if it is check ((SQLException)temp).getErrorCode() == whatever you want

Categories