Play Framework 2.3.1 Promise exception handling within inner class - java

What is the right approach in order to implement a correct exception handling within a WS API Request?
An example:
F.Promise<List<String>> modulesPromise = WS.url(requestUrl).setAuth(apiUser, apiPassword).get().map(
new F.Function<WSResponse, List<String>>() {
public List<String> apply(WSResponse response) {
List<String> modules = new ArrayList<>();
JsonNode json = response.asJson();
for (JsonNode node : json) {
modules.add(node.get("name").toString().replace("\"", StringUtils.EMPTY));
}
return modules;
}
}
);
modulesPromise.recover(new F.Function<Throwable, List<String>>() {
#Override
public List<String> apply(Throwable throwable) throws Throwable {
Logger.error("error", throwable);
return new ArrayList<>();
}
});
If an exception occurs in that case within the inner class, the exception ll be thrown further. Its the same problem with the method .onFailure(). Isn't it the best way to use a try catch block in order to catch potential exceptions? The recover and the onFailure method seems to be useless.

In your case, it appears that recover isn't going to do you much good. recover is used for provide a default value when the Promise fails (e.g. an exception is thrown inside it).
In this case you're operating on a List where calling node.get("name").toString() will throw an exception if name is not a field in the JsonNode. This will cause the Promise to fail entirely, and so the rest of your list is gone. You could wrap it in a try/catch, but it's not necessary.
Since node.get("name") returns null if there is no name, then you should just check for null before operating on it:
for (JsonNode node : json) {
if(node.get("name") != null)
modules.add(node.get("name").toString().replace("\"", StringUtils.EMPTY));
}
So the answer really is that it depends on your use case. Often, if an exception occurs within the Promise, you want it to fail. Then the rest of your code can handle it appropriately. However, if an exception can occur that would generally not affect the final result, then either catch or it handle it otherwise to prevent it from failing the Promise (checking the null, in this case).

You were thisclose. What you had was essentially:
promise = WS.get
.map;
promise.recover;
What you originally wanted is:
promise = WS.get
.map
.recover;
Your instinct was right: while try/catch handles exceptions synchronously, inline with the currently executing thread, methods like recover handle exceptions asynchronously while those promises are being evaluated/fulfilled. The key is that each promise is separate, and those methods that return a promise are actually returning a new promise.
The get promises to return the result of the HTTP call. The map promises to take that result and extract the "name" from each node. The recover promises that if there is an exception anywhere in the chain, it will return a new empty list instead. But in your example, that last promise isn't assigned/used anywhere, so no one is listening/watching/awaiting that promise; they are awaiting the map, which can fail (either itself or the get). Note that the recover code will still execute if there is an exception, but no one wants the result.
Whether to use recover or let the entire call fail is a separate question. For example, if you are composing a response from several other calls, maybe you could replace a failed third-party call with "not available", or simply omit the elements that did not work.
While recover returns a new promise, onFailure is void. It's what your example does: do something when there is an exception, but no one is dependent on it. For example, suppose you want to log whenever a third-party call fails. You could do that inside the recover -- log then return an empty list -- or you can do it separately: the recover returns the empty list, and the onFailure logs. That way, the functionality is more composable; and again, it's important that to differentiate the various promises:
promise = WS.get
.map;
promise.onFailure;
promise = promise.recover;

Related

Returning error codes from a method

I'd like to ask something confuses me a lot. Here is the scenario, lets say I have a method preparePayload that takes some argument like messageType, destAddr etc. The duty of method is construct a fully payload (with headers, prefixes etc). Here is the problem, I want to return statusCode (which is enum, like STATUS_OK,STATUS_INVALID_DEST, STATUS_INVALID_MSG_TYPE etc.), and than respect to return status I'd like to implement my logic. But if there is no error (STATUS_OK), I need the prepared payload to move on. So my method should return eighter payload or status code.
In C language, simply sending payload buffer address as an argument to preparePayload method solves the problem perfectly. When the method returns, simply reading payload from the buffer address and moving on the application works. How can I implement this kind of logic in Java?
In addition, preparePayload method is just an example I gave, so the methods I implemented may return String, int[], some class object that I wrote etc. I mean, the type of object that method should return in success case may vary.
Any suggestion will very welcome.
Besides changing to exceptions, there is one more hackish way to allow for "input/output" parameters, like:
public ResultEnum preparePayLoad(List<PayLoad> toPrepare, ... other args) {
...
PayLoad newThing = ...
...
toPrepare.add(newThing);
return someEnum;
}
So, you could use such an approach to "emulate" the "C style"; but the more Java/OO would be
public PayLoad preparePayLoad(args) {
...
PayLoad newThing = ...
...
return newThing;
}
and to throw (checked or unchecked) exceptions for error situations.
The correct idiom in Java is to throw a checked exception (some will say unchecked is better, there is a slight controversy here).
The three important mechanisms you get is:
automatic propagation of error codes up the stack. If you do not handle some type of error in your code (don't check for it), it will get propagated up as an exception - you don't need layered checks (and avoid an error of returning an invalid result, quite common in C),
exceptions work as an "alternate return type", ensuring type safety for both correct results and the error messages (which are full objects - and can contain any number of useful information besides the code)
checked exceptions allow the compiler to check if all the important error statuses are handled in some way.
You can create a class, a wrapper, for example:
public class Result {
public enum Status {
STATUS_OK, STATUS_INVALID_DEST, STATUS_INVALID_MSG_TYPE
}
Status status;
String payload;
}
that will be returned by your method preparePayload. Then, when you call your method, you can do it like this:
Result result = preparePayload(args);
//better will be a switch with case for each possible status
if (result.state == Result.State.STATUS_OK)
//do what you want with payload
System.out.println(result.payload);
else
return;

Good Practice : Exception Handling

I have 2 classes in my module where one of the class say Class A has methods which could throw InterruptedException, NoSuchElementException and another class say class B has methods which calls the method from class A.
Could someone please guide me with what is a good practice to implement exception handling? Shall it be CASE 1 or CASE 2 or any other way to do so.
CASE 1 ::
Class A
methodA1 throws InterruptedException, NoSuchElementException {...}
methodA2 throws InterruptedException, NoSuchElementException {...}
.
.
.
.
methodA10 throws InterruptedException, NoSuchElementException {...}
Class B
a = new A();
methodB1 {
try{
a.methodA1();
a.methodA2();
}
catch(InterruptedException){
//do something
}
catch(NoSuchElementException){
//do something else
}
}
methodB2 {
try{
a.methodA9();
a.methodA10();
}
catch(InterruptedException){
//do something
}
catch(NoSuchElementException){
//do something else
}
}
SCENARIO 2 ::
Class A
methodA1 {
try{
//perform actions
}
catch(InterruptedException){
//do something
}
catch(NoSuchElementException){
//do something else
}
}
.
.
.
.
methodA10 {
try{
//perform actions
}
catch(InterruptedException){
//do something
}
catch(NoSuchElementException){
//do something else
}
}
Class B
a = new A();
methodB1 {
a.methodA1();
a.methodA2();
}
methodB2 {
a.methodA1();
a.methodA2();
}
It really depends on what you need to achieve.
The situation might be flexible enough to allow you to handle exceptions as they arise within the specific module. For instance, you have some process which queues elements, an exception is thrown and in your exception handling code, you simply try again. The caller knows that when the method is called, something will be added but does not require to be informed of when/how.
On the other hand, the situation might require that you inform the caller immediately should something happen. Taking the above example, maybe the caller would need to know if the queueing was successful or not so that they could direct the user accordingly.
There are also scenarios where bubbling up the exception, although recommended, needs to be done in such a way that internal exceptions are not divulged to the caller since it could expose the internal structure of the module, which could be a security risk.
Usually, what one does is that, where necessary, exceptions are wrapped within custom exceptions. And if any errors occur, the custom exceptions are used to bubble up the error. It will then be up to the caller to decide what to do if/when an error occurs.
rethrowing or handling depends whether the caller can handle the exception reasonably.
E.g. if an UI triggers a calculation via a method chain, it might not be reasonable that somewhere in this chain the exception gets lost, as it would be of interest to present in the ui the exception to the user.
So it mostly depends on the context which scenario is preferable.
A rule of thumb is: However can handle the exception reasonably should do so
It depends on what you want to achieve by that and where you want to handle the exceptions. If you can handle the exception properly inside the methodA1() it'll be easier to use the method (no try-catch necessary around method calls)
If you can't handle the exception in the method itself (e.g. not enough information to handle the exception properly) and you can only handle it properly in methodB1 then you should use SCENARIO 2

Mongodb async java driver find()

I have a webapp in which I have to return the results from a mongodb find() to the front-end from my java back-end.
I am using the Async Java driver, and the only way I think I have to return the results from mongo is something like this:
public String getDocuments(){
...
collection.find(query).map(Document::toJson)
.into(new HashSet<String>(), new SingleResultCallback<HashSet<String>>() {
#Override
public void onResult(HashSet<String> strings, Throwable throwable) {
// here I have to get all the Json Documents in the set,
// make a whole json string and wake the main thread
}
});
// here I have to put the main thread to wait until I get the data in
// the onResult() method so I can return the string back to the front-end
...
return jsonString;
}
Is this assumption right or thereĀ“s another way to do it?
Asynchronous APIs (any API based on callbacks, not necessarily MongoDB) can be a true blessing for multithreaded applications. But to really benefit from them, you need to design your whole application architecture in an asynchronous fashion. This is not always feasible, especially when it is supposed to fit into a given framework which isn't built on callbacks.
So sometimes (like in your case) you just want to use an asynchronous API in a synchronous fashion. In that case, you can use the class CompletableFuture.
This class provides (among others) two methods <T> get() and complete(<T> value). The method get will block until complete is called to provide the return value (should complete get called before get, get returns immediately with the provided value).
public String getDocuments(){
...
CompletableFuture<String> result = new CompletableFuture<>(); // <-- create an empty, uncompleted Future
collection.find(query).map(Document::toJson)
.into(new HashSet<String>(), new SingleResultCallback<HashSet<String>>() {
#Override
public void onResult(HashSet<String> strings, Throwable throwable) {
// here I have to get all the Json Documents in the set and
// make a whole json string
result.complete(wholeJsonString); // <--resolves the future
}
});
return result.get(); // <-- blocks until result.complete is called
}
The the get()-method of CompletableFuture also has an alternative overload with a timeout parameter. I recommend using this to prevent your program from accumulating hanging threads when the callback is not called for whatever reason. It will also be a good idea to implement your whole callback in a try { block and do the result.complete in the finally { block to make sure the result always gets resolved, even when there is an unexpected error during your callback.
Yes, you're right.
That's the correct behaviour of Mongo async driver (see MongoIterable.into).
However, Why don't you use sync driver in this situation? Is there any reason to use async method?

Is "throws Throwable" good practice

In the past I'd read tons of code with methods like:
public Object doSomething() throws Throwable {
...
}
Is it common practice to do that?
What are pros & cons?
throws Trowable seemed to me like the "Agent Orange" way of getting the Exception- matter done
EDIT
Handle expected Exceptions in the Method
Throw unexpected Exceptions (one by one)
Don't care of Errors
Is that the way to go?
You should not throw Throwable. Here's why.
Throwable is the top of the hierarchy of things that can be thrown and is made up of Exceptions and Errors. Since Errors by definition arise from unsalvagable conditions, it is pointless to include them in your method declaration. That leaves just Exception.
You should declare your method with throws Exception instead.
Note that the narrower the range of throws the better.
Declaring your method to be throws Exception is ok if your method doesn't generate the exceptions, but instead calls other code that is declared as throws Exception and you want exceptions to percolate up the call stack.
If your method is the generating the exception, then declare a narrower range, eg throws IOException, MyProcessingException, etc
That's a loaded question. This isn't so much about exception handling as it is about code readability.
It depends where you get your code samples from. Professionals prefer to be more specific when throwing out of a method. The main reason is that it keeps your APIs more readable. For example, if your method throws Throwable, that basically means anything could happen and your method doesn't want to deal with it, no matter what. But really, only a limited number of things could happen:
Whatever checked exceptions resulting from other calls you are making in your method
Whatever checked exceptions you are throwing on purpose based on your own assertions
Whatever unchecked exception you didn't plan for
Errors (java.lang.Error) that are more global to the JVM and the environment
By specifically stating the exceptions you want to throw, you are telling the users of your API about what they should beware of. For example, when you use InputStream, you'll notice most methods throw at least java.io.IOException, which gives you some useful information about what you should watch for.
When coding, as a general rule, you want to try to keep your APIs as expressive as possible. You've got essentially one line of code to show the public API of a method (i.e. its signature, annotations too I guess), so you want it completely expressive (return type, name, parameters, but also the thrown exceptions).
As far as catching the throwables and printing the stack trace, I'd say that you should not catch the exception unless you can do something about it. Instead, let it roll up the call stack until some class catches it to do something about it. Sometimes, it may roll all the way up to your main class, which I guess would have to catch it and print the stack trace as last resort. Basically, if you can't act upon the exception, then let it go up the call stack. Also it is extremely rare that you find yourself in a situation where you should silence an exception (i.e. catch it but do nothing about it). That's usually inviting problems when comes time to troubleshoot issues.
Here is a fun but interesting article around misuse of exception handling in general.
In some rare cases it is acceptable to throw Throwables. For example, #Around advices in Spring AOP are usually declared to throw a Throwable.
The following example is copied verbatim from Spring AOP docs:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.ProceedingJoinPoint;
#Aspect
public class AroundExample {
#Around("com.xyz.myapp.SystemArchitecture.businessService()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
// start stopwatch
Object retVal = pjp.proceed();
// stop stopwatch
return retVal;
}
}
Why is doBasicProfiling declared to throw a Throwable? Because the original method (i.e. the execution join point), might throw an Error, RuntimeException, or a checked exception. So it only makes sense to declare doBasicProfiling to throw a Throwable.
Functionally, it is equivalent with throws Exception, since errors are unchecked.
I see no reason to declare a method to throw Throwable. However, this doesn't mean that catch and printStackTrace is a good alternative.
Usually, you want to catch throwables where you can do something sensible with them.
Code that throws a throwable you don't expect should explode gloriously, so you can see the error and fix the bug.
Is it common practice to do that?
In the JDK it is rare. This is mostly used when it is not clear how to handle checked exceptions.
What are pros & cons?
The pros is that you get your code to compile without worrying about checked exception.s
The cons is that exception you should be handling are being ignored.
Isn't it better to catch and printStackTrace()?
Unhandled exception are usually printed anyway so catching them doesn't help much.
You should catch an exception when you can add some value by doing so and add the exception to the throws clause when you can't.
It is really debatable matter.
Having method throwing too many exceptions will result in lot of error handling code. Some times it is not intended.
But because I don't like too many exception in signature does not mean that Lets use Parent of all exceptions and we are done!! It will not work.
What one can do is categorise exceptions such as BusinessException,ServiceException so that if you have a business rule which says that minimum balance in account can not be less than say 100$ then InsufficientBalance exception will be generated which will be child of BusinessException
so you method will be like
public Object doSomething() throws BusinessException {
if(!hasMinimumbalance())
{
throw new InsufficientBalance(ErrorCode);
}
}
What this will do is club related exceptions together and whenever API user wants to detect exception specific error then he can do it, else generic error handling is possible.
The core point here is on the UI you should display to the user that You have run out of balance and you can not withdraw money
You can say on the larger aspect to display human readable form of error it is really necessary to have separation of exceptions.
Are you asking about Throwable specifically? If so, then it's not good practice. It doesn't provide any useful information to class (method) user.
Throwing (and catching) Throwable (or Exception) is generally bad practice because it 'blankets' any specific exceptions you might want to catch. Then you would have to resort to ugliness like below:
public void myMethod() throws Throwable {
if (x) {
throw new MyException1();
}
if (y) {
throw new MyException2();
}
}
public void callingMethod() {
try {
myMethod();
}
catch(Throwable t) {
if (t instanceof MyException1) {
// handle exception 1
}
else if (t instanceof MyException2) {
// handle exception 2
}
else {
// handle other exceptions
}
}
}
Which is error prone (and flagged by CheckStyle as a code violation). It is much preferrable to have code like this:
public void myMethod() throws MyException1, MyException2 {
if (x) {
throw new MyException1();
}
if (y) {
throw new MyException2();
}
}
public void callingMethod() {
try {
myMethod();
}
catch(MyException1 e) {
// handle exception 1
}
catch(MyException2 e) {
// handle exception 2
}
}
Handling an exception just by calling printStackTrace() is usually not a good idea. printStackTrace() sends the stacktrace to standard error, which may not be read at all. A better option is to use the application's logging facility (like log4j) to report the exception. Even then, just logging it might no be enough.
My rule of thumb is:
If you can handle an exception locally, do so. For example when parsing a String as an Integer you could catch the NumberFormatException and return a default value:
prvate int parseAmount(String amountValue) {
int amount;
try {
amount = Integer.parseInt(amountValue);
}
catch(NumberFormatException e) {
// default amount
amount = 0;
}
return amount;
}
If you cannot handle an exception locally, consider if you should expose the exception type that is being thrown. If this type is some obscure (implementation-dependent) type, then wrapping it in your own generic exception type is probably a good idea:
private Customer getCustomer(int customerId) throws ServiceException {
try {
return customerService.getCustomer(customerId);
}
catch(CustomerServiceSpaghettiTangledException e) {
throw new ServiceException("Error calling the customer service", e);
}
}
Here 'ServiceException' is a subclass of Exception created by you. Spring also offers an exception hierarchy specifically for this purpose.
By wrapping the exception you hide the implementation details, making your service layer much simpler to use.
If you decide to throw an exception from your method, you will need to handle it 'higher up' in the callstack. This can be a generic error page in your web application stating that something went wrong and possibly providing an error message or code. In some cases the higher level code can attempt a retry or possibly an alternative way to obtain the required result.
The only use case I can think of would be for test code like unit tests. But Adam's counterpoint still stands "If so, then it's not good practice. It doesn't provide any useful information to class (method) user."

exception execution data flow, why is my object is null when exception thrown?

I'm not sure of why this is happening, but I have a simple setup where a caller's return value is null.
I call a function which might throw registered exceptions. When it does, myXDSConsumerRequestHandler stays null. The problem is that I'm able to recover from the registered events (checked the object on the callee). So how do I call the retrieveDocuments and get my object back?
I understand the flow is broken when the exception is thrown, so should I be catching the exceptions at a higher level?
This is the caller:
try {
myXDSConsumerRequestHandler =
RetrieveDocSetUtil.retrieveDocuments(NIST, multipleRetrieveMap);
} catch (VerboseIllegalArgumentException e) {
} catch (XDSException e) {
}
This is the callee:
public static RetrieveDocumentSetImpl retrieveDocuments(
String repoURL, Map<String, String> docRepoMap)
throws VerboseIllegalArgumentException, XDSException {
RetrieveDocumentSetImpl myXDSConsumerRequestHandler =
new RetrieveDocumentSetImpl(repoURL);
myXDSConsumerRequestHandler.retrieveDocumentSet(docRepoMap);
return myXDSConsumerRequestHandler;
}
Thank you!
If retrieveDocuments() throws an exception then it never gets a chance to return something. The statement myXDSConsumerRequestHandler = RetrieveDocSetUtil.retrieveDocuments() does not finish normally.
It is not possible to both catch an exception from a method and receive the return value.
If retrieveDocuments() has something meaningful it can return to callers even when these exceptions are encountered, then this method should be catching exceptions internally and returning an appropriate return value rather than allowing the exception to propagate up to the calling method.
Your code is executed in the following order:
Call retrieveDocuments
Assign the result to myXDSConsumerRequestHandler
If an exception is thrown during step 1, step 2 will never happen.
In general, you cannot both throw an exception and return a value.
You problem comes from having a methid doing too much. It both obtains a RetrieveDocumentSetImpl and attempts to use it.
RetrieveDocumentSetImpl myXDSConsumerRequestHandler =
new RetrieveDocumentSetImpl(repoURL);
myXDSConsumerRequestHandler.retrieveDocumentSet(docRepoMap);
return myXDSConsumerRequestHandler;
Separate this into two methods:
RetrieveDocumentSetImpl myXDSConsumerRequestHandler =
new RetrieveDocumentSetImpl(repoURL);
return myXDSConsumerRequestHandler;
which either return a handler or fails, throwing an Exception, and
myXDSConsumerRequestHandler.retrieveDocumentSet(docRepoMap);
Then your caller can call the first method, grabbing the return code, and then if they so choose try various things such as cal the second, catching the indidual exceptions they throw.
Here are my suggestions
Add proper handling on public retrieveDocuments(NIST, multipleRetrieveMap) method to ensure that proper parameters are passed to your method. This will address exceptions specially related to VerboseIllegalArgumentException the parameter validation/handling should be done before you pass the paramters to the retrieveDocuments method. Im afraid that if you encounter an exception you can no longer retreive your object for the reason stated by the previous posters It is not possible to both catch an exception from a method and receive the return value. thats why proper validation and handling is very important.
After determining the cause of your exception, define/create your own exceptions. This will save you a lot of time and headache in the future.

Categories

Resources