Java - How to setup validation with different error messages - java

I have a FileUtils class that I would like to call that does some validation, and if it's wrong, it needs to return a good error message as to why the validation failed. So I have:
public static boolean isValidFile(File file) throws Exception
{
if(something)
throw new Exception("Something is wrong");
if(somethingElse)
throw new Exception("Something else is wrong");
if(whatever)
throw new Exception("Whatever is wrong");
return true;
}
public void anotherMethod()
{
try
{
if(isValidFile(file))
doSomething();
} catch (Exception e) {
displayErrorMessage(e.getMessage());
}
}
But this just seems odd to me because the isValidFile call can never be false. Also if I reverse the order of the if condition to do a quick boot out of the code if it's false, it's even weirder looking. Plus I don't like having exception handling code as a way of passing an error message.
public void anotherMethod()
{
try
{
if(!isValidFile(file))
return;
doSomething();
..
doMoreThings();
} catch (Exception e) {
displayErrorMessage(e.getMessage());
}
}
Is there a way to do all this without using Exceptions to and still be able to have the isValidFile() method return an indication of what the error is without returning an int with an error code like you see in C, etc.

You can e.g. change your method to
public static List<String> isValidFile(File file)
When the file is valid return an empty list or null,
otherwise return a list with the validation problems. The
return value is your indication if validation failed or not.

You could do something like this:
public static String validateFile(File file)
{
String ret = null;
if(something) {
ret = "Something is wrong";
} else if(somethingElse) {
ret = "Something else is wrong";
} else if(whatever) {
ret ="Whatever is wrong";
}
return ret;
}
public void anotherMethod()
{
String errorMessage = validateFile(file);
boolean fileIsValid = errorMessage == null;
if (fileIsValid) {
doSomething();
} else {
displayErrorMessage(errorMessage);
}
}
Not really pretty, but it gets the job done.

Related

One method to capture most of the try catch statements

In my UI java test framework I have lots of methods that are doing try catch around element actions like click, send keys etc and return true when action is successful and false when any exception occurs. I was wondering is there any smarter way to pass the method as parameter and in that one method surround that code with try catch statement. So that code could be simpler and cleaner to read (may be Java 8 functional interfaces).
public boolean expandPanel(String panelHeading) {
boolean panelFound = false;
try {
getElement(PanelHeadings.fromString(panelHeading)).click();
panelFound = true;
} catch (Exception e) {
panelFound = false;
}
return panelFound;
}
I did try creating an actions class and defining different methods for click, sendKeys etc. But is there a way if i can just have one try catch method and pass code or behaviour to that method.
public boolean expandPanel(String panelHeading) {
return actions.click(getElement(PanelHeadings.fromString(panelHeading)));
}
public class WebElementActions {
public Boolean click(WebElement element) {
try {
element.click();
return true;
} catch (Exception e) {
log.error(e.getMessage());
return false;
}
}
}
You could do something like
public boolean executeSafely(Runnable action) {
try {
action.run();
return true;
} catch (Exception x) {
return false;
}
}
And then call it with return executeSafely(element::click).

Rewrite service request using optionals

I want to rewrite the code below using Optionals ( I do not control jpaConnector ):
public boolean deleteLockStatus() {
IMdss service = jpaConnector.getMdssService();
if ( service == null ) {
return false;
}
ServiceResponse response = null;
try {
response = service.deleteLockStatus();
} catch (Exception e) {
e.printStackTrace();
}
if ( response == null ) {
return false;
}
if ( response.isError() ) {
return false;
}
return true;
}
I have achievied this so far:
public boolean deleteLockStatus() {
Optional<IMdss> service = Optional.ofNullable(jpaConnector.getMdssService());
if (!service.isPresent()) { return false; }
Optional<ServiceResponse> response = Optional.empty();
try {
response = Optional.ofNullable(service.get().deleteLockStatus());
if ( response.isPresent() == false || response.get().isError() ) {
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
Is there a better and more native java 8 way? Thank you!!!
We start with an Optional<Service>, flat map that to an Optional<ServiceResponse> (using the regular map function would give us Optional<Optional<ServiceResponse>>), then map that to an Optional<Boolean>.
The Optional<Boolean> represents success or failure of the response. If we don't have a value here, an exception was thrown so we return false with orElse(false).
It's a shame about the checked exception and having to print the stack trace, or else it could be a lot more concise.
public boolean deleteLockStatus() {
return Optional.ofNullable(jpaConnector.getMdssService())
.flatMap(service -> {
try {
return Optional.ofNullable(service.deleteLockStatus());
}
catch(Exception e) {
e.printStackTrace();
return Optional.empty();
}
})
.map(ServiceResponse::isError)
.orElse(false);
}
Side note: catching Exception is usually a bad idea. You should be as specific as possible. Consider using this syntax if there are multiple possible exceptions which may be thrown.
As mentioned in the comments by Federico, you can replace the flatMap with this slight simplification if you don't mind using null. I would personally prefer the version above.
.map(service -> {
try {
return service.deleteLockStatus();
}
catch(Exception e) {
e.printStackTrace();
return null;
}
})

To break out main method in submethod without if-return or exception

I want to know if there is any way to break out the main method using its sub-method, but without throwing exceptions or returning a boolean.
For example
public void foo()
{
System.out.print("Trying to break out foo");
validate1();
validate2();
validate3();
System.out.print("Validation success");
}
public void validate1()
{
//todo: break out foo() if validation failed
}
public void validate2()
{
//todo: break out foo() if validation failed
}
public void validate3()
{
//todo: break out foo() if validation failed
}
No if( validate1() ) return; in foo().
No exception throwing in validate1(), validate2(), validate3().
Is that possible?
There is no such way to do so. You must get the response to your calling method and then break out of the calling method.
public void foo()
{
System.out.print("Trying to break out foo");
if(!validate1()) {
return;
}
if(!validate2()) {
return;
}
....
System.out.print("Validation success");
}
public boolean validate1()
{
try{
....
if(...) {
}
} catch(Exception e) {
//Don't throw exception. Instead just return false.
return false;
}
// no errors and validation passed
return true;
}
However, if you want the program to end, then you can simply do
public void validate1()
{
//todo: break out foo() if validation failed
System.exit(0); // abruptly close the program
}

Is there any way to don't use 'instance of' with objects that I can't extend?

I've a custom exception with few attributes that inherits from Exception class.
Depending on instance of Exception I would like to return a code.
Code:
public int manageException(Exception exception) {
int code = 0;
if (exception instanceof MyCustomException) {
code = ((MyCustomException) exception).getCode();
} else if (exception instanceof NestedRuntimeException) {
code = 444;
} else if (exception instanceof HibernateException) {
code = 555;
} else {
code = 666;
}
return code;
}
If
You need to handle these exceptions in multiple locations, and
You don't want multiple catch blocks (one for each exception type) in each location
...then instanceof is about as clean as you're likely to get in Java 7.
Having said that, though, you could do this:
public void manageException(Runnable r) {
try {
r.run();
}
catch (NestedRuntimeException nre) {
throw new MyCustomException(444, nre);
}
catch (HibernateException he) {
throw new MyCustomException(555, he);
}
catch (Exception e) {
throw new MyCustomException(666, e);
}
}
...and then everywhere you need it:
try {
this.manageException(new Runnable() {
#Override
public void run() {
// Do something
}
});
}
catch (MyCustomException mce) {
int code = mce.getCode();
}
...but it's not buying you much and it's really ugly. :-)
In Java 8, it's a lot cleaner. manageException is the same, but the calls are just:
try {
this.manageException(() => {
// Do something here
});
}
catch (MyCustomException mce) {
int code = mce.getCode();
}
For me, the Java 8 version nearly starts winning over instanceof. The Java 7 version, not so much.
(Why Runnable in the above? Because the JDK authors decided not to define a new standard functional interface that accepts no arguments and has no return value; more in this question. They generalized the concept of Runnable instead. If the semantics bother you (they would me), you can define your own.)
You can use overloading like this:
public int manageException(MyCustomException e) {
return e.getCode();
}
public int manageException(NestedRuntimeException e) {
return 444;
}
public int manageException(HibernateExceptionexception e) {
return 555;
}
public int manageException(Exception e) {
return 666;
}
Edit after comment from #T.J. Crowder:
Keep in mind that you will still need multiple catch blocks in order to call the correct method. The overload is based on the compile-time type of the exception. Simply doing catch (Exception e) { int code = this.manageException(ex); } will always return 666.
If you want to map the type of exception to different error codes, you could use a map:
Map<Class<? extends Exception>, Integer> map = new HashMap<> ();
map.put (Exception.class, 5);
map.put (NullPointerException.class, 42);
try {
throw null; //throws NPE
} catch (Exception e) {
System.out.println (map.get (e.getClass ())); //output is 42
}
I think this would be easy expendable, as you could read the mapping from a config file instead of hard coding it, so you could add other exception and error codes without making changes to your code.
You have to test the return value of map.get() for null, as it could be an Exception you didn't specify before so there is no Integer mapped to it.
Attention: As mentioned in the first comment, this would only work if you want to have an exact mapping of Classes to error codes. If Subclasses of an exception should have the same error code as their super class, this solution won't work without modification.

Functionality for automatic retry after exception

I have made this abstract class to automatically retry network calls if some exception is thrown.
I take care to not retry after InterruptedException &
UnknownHostException.
I retry 5 times. After each failure
I perform an exponential back off, starting from 300ms going upto
1500ms.
public abstract class AutoRetry {
private Object dataToReturn = null;
public Object getDataToReturn() {
return this.dataToReturn;
}
public AutoRetry() {
short retry = -1;
while (retry++ < StaticData.NETWORK_RETRY) {
try {
Thread.sleep(retry * StaticData.NETWORK_CALL_WAIT);
this.dataToReturn = doWork();
break;
} catch (InterruptedException | UnknownHostException e) {
e.printStackTrace();
this.dataToReturn = null;
return;
} catch (IOException e) {
e.printStackTrace();
}
}
}
protected abstract Object doWork() throws IOException;
}
I use it as follows :
final Object dataAfterWork = new AutoRetry() {
#Override
protected Object doWork() throws IOException {
return; //a network call which returns something
}
}.getDataToReturn();
So is this implementation good/correct ?
EDIT
moved to https://codereview.stackexchange.com/questions/87686
This looks pretty good, but I would split the running task from the retry. Also use generics, don't just throw Object about.
Use a Java 8 lambda and the return of the method:
public static <T> Optional<T> doWithRetry(final Supplier<T> t) {
for (int retry = 0; retry <= StaticData.NETWORK_RETRY; ++retry) {
try {
Thread.sleep(retry * StaticData.NETWORK_CALL_WAIT);
return Optional.of(t.get());
} catch (InterruptedException | UnknownHostException e) {
LOGGER.log(Level.SEVERE, "Call failed.", e);
return Optional.empty();
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Call failed. Retry.", e);
}
}
LOGGER.log(Level.SEVERE, "Call failed. Retries exceeded.");
return Optional.empty();
}
Also, use a real logger, not printStackTrace...
Usage:
final String data = doWithRetry(() -> {
//do stuff
});
If your lambda needs to throw an exception, you'll need to define your own #FunctionalInterface:
#FunctionalInterface
interface StuffDoer<T> {
T doStuff() throws Exception;
}
And use that in the method signature, you'll need to handle generic Exception.
Pre-Java 8 usage:
final String data = doWithRetry(new StuffDoer<T>() {
#Override
public T get() throws Exception {
return null;
}
});

Categories

Resources