How to handle an exception inside of ifPresent? - java

Inside a method, a condition is needed to proceed the logic. An unhandled exception warning message shows up in my IDE. Wrapping the whole block with try-catch doesn't let the message go away.
public void changePassword(String login, String currentClearTextPassword, String newPassword) {
userRepository.findOneByLogin(login)
.ifPresent(user -> {
String currentEncryptedPassword = user.getUserSecret();
String encryptedInputPassword = "";
try {
encryptedInputPassword = authUtils.encrypt(currentClearTextPassword);
} catch (Exception ex) {
System.err.println("Encryption exception: " + ex.getMessage());
}
if (!Objects.equals(encryptedInputPassword, currentEncryptedPassword)) {
throw new Exception("Invalid Password"); // <-- unhandled exception
}
String encryptedNewPassword = "";
try {
encryptedNewPassword = authUtils.encrypt(newPassword);
} catch (Exception ex) {
System.err.println("Encryption exception: " + ex.getMessage());
}
user.setUserSecret(encryptedNewPassword);
userRepository.save(user);
log.debug("Changed password for User: {}", user);
});
}
How to deal with this warning message?

Treating Exception inside stream operation is a little overhead, I would like to separate the operation and makes it like so :
public void changePassword(String login, String currentClearTextPassword, String newPassword) throws Exception {
//get the user in Optional
Optional<User> check = userRepository.findOneByLogin(login);
//if the user is present 'isPresent()'
if(check.isPresent()){
//get the user from the Optional and do your actions
User user = check.get();
String currentEncryptedPassword = user.getUserSecret();
String encryptedInputPassword = "";
try {
encryptedInputPassword = authUtils.encrypt(currentClearTextPassword);
} catch (Exception ex) {
throw new Exception("Encryption exception: " + ex.getMessage());
}
if (!Objects.equals(encryptedInputPassword, currentEncryptedPassword)) {
throw new Exception("Invalid Password"); // <-- unhandled exception
}
String encryptedNewPassword = "";
try {
encryptedNewPassword = authUtils.encrypt(newPassword);
} catch (Exception ex) {
throw new Exception("Encryption exception: " + ex.getMessage());
}
user.setUserSecret(encryptedNewPassword);
userRepository.save(user);
log.debug("Changed password for User: {}", user);
}
}
Beside the Exception should be thrown not just printed.

Like #louis-wasserman said you can use an unchecked exception.
So instead of
throw new Exception("Invalid Password");
use:
throw new RuntimeException("Invalid Password"); // for example
Note: It is better to use a custom RuntimeException that fits your use case.

For the general case, #pari-ngang is correct: within a lambda expression you cannot handle a checked exception outside the calling function. Either use an unchecked or use the try construct in the lambda.
However, needing to do either of these might be a sign of poor structure. Having a large block of code within a lambda is one such sign. Here are a few suggestions for your specific case:
1. As a simplification of #ycf-l's answer, invert the logic and simply return user if not found:
Optional<User> user = userRepository.findOneByLogin(login);
if (!user.isPresent()) {
return;
}
// ... carry on as before outside of a lambda
2. Seperate the logic of fetching the user from changing the password of a user (you'll still have to pass exceptions back up):
if (user.isPresent()) {
changePassword(user.get(), currentClearTextPassword, newPassword);
}
3. You can also use libraries like vavr to simplify the try/catch blocks:
String encryptedInputPassword = Try.of(() -> authUtils.encrypt(currentClearTextPassword))
.onFailure(e -> System.err.println("Encryption exception: " + e.getMessage()))
.orElse("");
4. If you're willing to pursue vavr, you can also solve the more general problem:
userRepository.findOneByLogin(login)
.map(user -> Try.of(() -> {
// Your change password stuff goes here.
changePassword(user, currentClearTextPassword, newPassword);
return null; // I don't currently know of any way of passing a runnable.
}))
// This pulls the exception out of the lambda function, satisfying the compiler.
.orElseGet(() -> Try.success(null))
.getOrElseThrow(Function.identity());
I haven't used vavr much so can't tell you if this is the most efficient/cleanest approach/use of vavr, but it will solve your problem.

Related

Do you need a return type method to be handled in front end?

So I am trying to get more insight on Java methods as I am still new to all this. And in my method type I declared as below:
public int insert_url(long nodeid,String url,String startdt,String enddt,int enable) {
try {
// UrlLink attr = em.find(UrlLink.class,n);
String sql="INSERT INTO urllink(NODEID,URL,STARTDT,ENDDT,ENABLE) VALUES("+nodeid+",'"+url+"','"+startdt+"','"+enddt+"',"+enable+")";
em.createNativeQuery(sql).executeUpdate();
return 1;
} catch (Exception e) {
e.printStackTrace();
return -1;
}
}
And in my front end, I called it simply like below:
try {
fileFacade.insert_url(nd.getNodeid(), "f0=" + nd.getNodeid() + "&ts=" + hash, currentDate, defaultDate, 1);
} catch (Exception e) {
// error should be handled
}
Initially, I was using void method rather than int. My question is if I am not using a return method,can it be handled in the front end?
In the even that the end user encounters any error, they ought to know an error occurred.

NamingException over domain name JAVA

I have a list with domains. When I iterate over this list I get domains mx records. If the domain is invalid try catch block throws NamingException and iterating over the list stops. How to continue program execution after throwing a name exception ?
try {
logger(clazz, "job started");
List<Domain> domains = new ArrayList<>();
domains.addAll(domManager.getActiveDoms());
for (Domain d : domains) {
Attributes attributes = iDirC.getAttributes("dns:/" + d.getName(), new String[] { "MX" });
Attribute attributeMX = attributes.get("MX");
System.out.println(attributes);
}
} catch (NamingException e) {
e.printStackTrace();
}
Your code has an try-catch block with a loop inside it, that way, if something fails, the program will abort (because of e.printStackTrace()).
Note that you said "(...) after throwing a name exception" and that is not what is happening! In order to throw an exception, you have to use throw new NamingException("cause"); and have a throws NamingException in your method's declaration.
Now, answering your question:
If you handle the error inside the loop, you can continue (note that if you have e.printStackTrace() the program will still end there).
I would do something like:
logger(clazz, "job started");
List<Domain> domains = new ArrayList<>();
domains.addAll(domManager.getActiveDoms());
for (Domain d : domains) {
try {
Attributes attributes = iDirC.getAttributes("dns:/" + d.getName(), new String[] { "MX" });
Attribute attributeMX = attributes.get("MX");
System.out.println(attributes);
} catch (NamingException e) {
//do somethig here like `System.out.println("error message!");`
}
}
Hope this helps you!

Testing methods using JUnit

I am new to JUnit and I have to test a method using JUnit api. One method internall calls another. My test case goes inside the method but while catchign the exception it fails.
Method under test is
public void checkANDCondition( Map<String, Message> messagesMap ) throws EISClientException
{
List<String> codes = getMessageCodes();
if(isAllReturnedMessagesContainCodes(codes, messagesMap))
{
StringBuffer buff = new StringBuffer("All of the specified message codes matched returned errors.");
for(String code: codes )
{
Message message = messagesMap.get(code);
buff.append(message.getMessageCode() + ": " + message.getMessageType() + ": " + message.getMessageText() + " ");
}
throw new EISClientException(buff.toString());
}
}
public boolean isAllReturnedMessagesContainCodes(List<String> codes, Map<String, Message> messagesMap)
{
if(codes!=null)
{
for(String code: codes)
{
if(!messagesMap.containsKey(code))
{
return false;
}
}
}
return true;
}
What I have done so far is
#Test
public void testPostProcess() throws Exception {
clientResponse = mock(ClientResponse.class);
MessageToExceptionPostProcessFilter postProcessFilter = new MessageToExceptionPostProcessFilter();
RetrieveBillingServiceResponse serviceResponse = new RetrieveBillingServiceResponse();caughtException = false;
try {
postProcessFilter.setCondition(ConditionOperator.AND);
List<String> messagesCodes = new ArrayList<String>();
messagesCodes.add("200");
messagesCodes.add("400");
Message message = new Message();
message.setMessageCode("200");
message.setMessageType(MessageTypeEnum.MESSAGE_TYPE_INFO);
message.setMessageText("Service completed successfully");
serviceResponse.setMessages(Arrays.asList(message));
postProcessFilter.setMessageCodes(messagesCodes);
serviceResponse = postProcessFilter.postProcess(serviceResponse, clientResponse);
assertNotNull(serviceResponse.getMessages());
} catch (EISClientException ex) {
caughtException = true;
assertEquals("All of the specified message codes matched returned errors.", ex.getMessage());
}
assertTrue(caughtException);
}
How can I make it pass?
Thanks
#Test(expected = EISCLientException.class)
public void testPostProcess() throws Exception {
...
serviceResponse.getMessages();
fail("Shouldn't reach this point");
}
That way you don't need to catch, with expected if it does not get throw a EISClientException it will fail.
edit: There are two times I can think of where you wouldn't want to use this.
1) You are mocking exceptions that are thrown mock(exception.class);
this i believe then throws some Mockito excpetion and it will not match the expected exception.
2) You are wrapping caught exceptions in your code, and throwing a generic exception. Example of code:
try {
} catch (FileParseException e){
throw new (ProjectFailingException(e, "file is bad");
}
if you have multiple catches and are wrapping them as ProjectFailingExceptions then you may want to catch in the test like this...
#Test ( expected = FileParseException.class)
public void testProcess() {
try {
...
} catch (ProjectFailingException e){
throw e.getCause();
}
Then the proper exception is thrown and you can make sure that process isn't throwing an exception from a a different catch.

I want to extract a string from the current exception thrown in a java program

I am calling a method from a third party jars whose class file is not accessible to me. So for some cases it throws exception logs and I want to extract string from the current log dynamically.
This is the java program method which throws exception
public String runLayoutTest(final String xmlFile){
try{
String gettingValue = "novalue";
boolean errorFlag = perform("runLayoutTest", new Reporter.Reportable() {
#Override
public boolean run() throws Exception {
String layoutXml = null;
//current directory
Path currentRelativePath = Paths.get("");
String currentProjectPath = currentRelativePath.toAbsolutePath().toString();
System.out.println("Current relative path is: " + currentProjectPath);
System.out.println("layoutXml "+xmlFile);
String x = client.runLayoutTest(currentProjectPath+"\\Excel\\"+xmlFile);
System.out.println("******* x ********"+x);
setX(x);
return true;
}
});
gettingValue = getX();
return gettingValue;
}catch(Exception e){
System.out.println("**Any one rule in Layout is failed**");
//System.out.println(e.getMessage());
return getX();
}
}
Here the client is a object of the third party jar file , And that is throwing me the exception on some odd cases .
The Exception logs are
com.experitest.client.InternalException: Exception caught while executing runLayoutTest: {"rule_1":{"Exists":true},"rule_2":{"Exists":true,"EqualHeight":false},"rule_3":{"AlignedLeft":false}}
at com.experitest.client.JavaClientInternals.executeInternally(JavaClientInternals.java:234)
at com.experitest.client.Client.execute(Client.java:237)
at com.experitest.client.Client.runLayoutTest(Client.java:1475)
at com.igate.framework.NativeDriver$79.run(NativeDriver.java:2753)
at com.igate.framework.Reporter.action(Reporter.java:81)........
From this exception I want to extract
runLayoutTest: {"rule_1":{"Exists":true},"rule_2":{"Exists":true,"EqualHeight":false},"rule_3":{"AlignedLeft":false}}
as a String.
Hence is there any method with which I can dynamically extract such String whenever it occurs.
And I still don't know the reason why my catch method is not getting called.
In your case you can just use Exception.getMessage() which will result in
Exception caught while executing runLayoutTest:
{"rule_1":{"Exists":true},"rule_2":{"Exists":true,"EqualHeight":false},"rule_3":{"AlignedLeft":false}}
Below can be used to get the json string. You can then parse the json to get desired data from it
String message = e.getMessage();
int colonIndex = message.indexOf(":");
String json = null;
if (colonIndex != -1) {
json = message.substring(colonIndex + 1);
}
Please note that this solution will not work in case of wrapped exception
I had to implement this code to attack directly to throwable detailMessage. I had to ignore all the hierarchy of classes that extended Exception because someone implemented a horrible getMessage method that was being overlapped with web components. In JUnit was no way to define unit test cases because framework's exceptions always tried to translate its error code into the 'session' (web) language...
public static Object getThrowableDetailMessage(Throwable throwable) {
try {
// Tiramos la puerta abajo y pedimos a Throwable que nos pase el código de error
Field f = Throwable.class.getDeclaredField("detailMessage");
f.setAccessible(true);
Object detailMessageFound = f.get(throwable);
return detailMessageFound;
} catch (SecurityException ex) {
//LOG
return null;
} catch (NoSuchFieldException e) {
//LOG
return null;
} catch (IllegalArgumentException e) {
//LOG
return null;
} catch (IllegalAccessException e) {
//LOG
return null;
}
}
You also can try to replace Throwable by InternalException and keep the reflection on this level of the hierachy. But like someone is already pointing. Make sure your code is being affected by the Exception you want to inspect.
I have implemented all the catches possible because I wanted to trace a different log for everyone of them. (For debugging and testing overall)
Note: My code has been implemented under JDK 1.6_18

Catching and rethrowing an exception from a boolean method does return false whereas not doing anything causes the method not to return

I have a general query regarding the java programming language and how it deals with exceptions and methods returning boolean.
Please not that although the example below deals with Spring/Ldap/ActiveDirectory, my question is only about java and exceptions.
public boolean doAuthenticate(String userAndDomain, String password) {
UsernamePasswordAuthenticationToken userToken = new UsernamePasswordAuthenticationToken(replaceBackSlashWithAtSign(userAndDomain), password);
try {
Authentication authentication = adAuthenticationProvider.authenticate(userToken);
return authentication.isAuthenticated();
} catch (BadCredentialsException e) {
log.error("Authentication failed - wrong username\\password", e);
throw new BadCredentialsException("Authentication failed - wrong username\\password", e);
} catch (AuthenticationException e) {
log.error("Authentication failed - AuthenticationException", e);
throw new AuthenticationException("Authentication failed - AuthenticationException", e) { };
}
}
If any of BadCredentialsException or AuthenticationException is rethrown by the authenticate method, then the doAuthenticate method returns false.
However if for some reason another runtime exception is thrown by adAuthenticationProvider.authenticate(), then the method does not return false and does not return at all...
I am just curious to know why that is...
edit:
LdapAuthentifier authentifier = new LdapAuthentifierImpl();
boolean didAuthenticate = authentifier.doAuthenticate(VALID_USER, INVALID_PASSWORD);
A System.out.println of didAuthenticate does show false if one of the two specified exceptions are thrown whereas another exception halts execution of the program and the System.out.println is never reached...
edit 2:
public static void main(String[] args) {
LdapAuthentifier authentifier = new LdapAuthentifierImpl();
boolean didAuthenticate = authentifier.doAuthenticate(VALID_USER, INVALID_PASSWORD);
}
I understand what happened. Here is the explanation.
The exception I actually saw in the logs was BadCredentialsException but this exception is never thrown by adAuthenticationProvider.authenticate and therefore never rethrown by the below method.
What actually happened was that the authentication.isAuthenticated() was just returning false and I was passing this boolean value to the client code.
I am including the method again for clarity's sake:
#Override
public boolean doAuthenticate(String userAndDomain, String password) {
UsernamePasswordAuthenticationToken userToken = new UsernamePasswordAuthenticationToken(replaceBackSlashWithAtSign(userAndDomain), password);
try {
Authentication authentication = adAuthenticationProvider.authenticate(userToken);
return authentication.isAuthenticated();
} catch (BadCredentialsException e) {
log.error("Authentication failed - wrong username\\password", e);
throw new BadCredentialsException("Authentication failed - wrong username\\password", e);
} catch (AuthenticationException e) {
log.error("Authentication failed - AuthenticationException", e);
throw new AuthenticationException("Authentication failed - AuthenticationException", e) { };
}
}

Categories