I'm working with RxJava and I don't know where the right place to check arguments would be. For example, say I have the following:
public Completable createDirectory(final String path) {
return Completable.create(emitter -> {
final File directory = new File(path);
final boolean createdSuccessfully = directory.mkDirs();
if (createdSuccessfully) {
emitter.onComplete();
} else {
emitter.onError(new IOException("Failed to create directory.");
}
}
}
Would it be better to check for a null path in the root of the method, or at the start of the completable? I'm leaning towards the former, but I'm interested in the pros and cons of both approaches.
I would say: it depends on what you are trying to achieve.
If you check for null-value on method-entry, before Completeable.create, you would throw the NPE/ IllegalArgumentException on calling-thread. This would follow the 'fail fast'-philosophy. Possible pros:
* fails fast on method-invocation
* Exception in callstack of calling-thread
If you check in Completable.create-lambda, it will be invoked on lambda-evaluation (subscription).
Example: Call createDirectory-Method on calling-thread, add subscribeOn and subscribe: NPE / IllegalArgumentException will be thrown on subscribeOn-Scheduler-Thread on subscription.
It will only be thrown, when you subscribe to returned Completable. Maybe you create an Completable but never subscribe to it. Then no exception will be thrown. This could be a pro for checking in lambda. If you would not check, a NPE would be thrown anyways on subscribeOn thread. Exception thrown on subscribeOn thread could be negative, because you only see the trace for subscribedOn-thread. Sometimes it is not easy to see the flow, when switching threads with only on callstack. You would not see that createDirectory-method was invoked. You would only see the lambda invocation plus some reactive-stack-polution.
I would say: use fail fast, if you subscribe to created Completable at some point. If it is possible, that no subscription to created Completable happens at any time, it would probably use some Precondition with a message, because it will only throw, when subscribed to (lazy). Anyways, if you check with Objects#requireNonNull() without any message in the lambda, you could just discard checking for null, because the NPE will be thrown anyway.
Related
I am currently creating a retry mechanism for performing requests using the failsafe-lib.
The issue: the RetryPolicy that I defined includes several timeout-related exceptions, but when I use the failsafe-lib (Failsafe.with(someFallback, somePolicy).get(() -> performRequest), exceptions that I did not specify (DataBufferLimitException) to be handled are negated instead of being thrown.
Now I understand that the FailsafeExecutor(...).get() method takes a CheckedSupplier, and this (possibly) might cause in negation of unchecked exceptions (please correct me if I'm wrong, this is just an assumption). However, I am still curious if I have done something wrong and if there is something that I can do to resolve this issue.
Below I have a simplified version of my code:
public Response performRequest() {
RetryPolicy<Object> retryPolicy = RetryPolicy.builder()
.withDelay(Duration.ofMillis(60_000L))
.handle(exceptionA, exceptionB, ...)
.withMaxRetries(3)
.onSuccess(o -> log.info("someRandomMessage"))
.onFailure(o -> log.warn("someRandomWarnMessage"))
.onRetriesExceeded(o -> log.error("someRandomErrorMessage"))
.build();
Fallback<Object> fallback = Fallback.of(event -> {
Throwable rootException = ExceptionUtils.getRootCause(event.getLastException());
if (rootException instanceof TimeoutException || rootException instanceof ConnectException) {
throw new someRandomException(rootException.getMessage());
}
}
);
Response response Failsafe.with(fallback, retryPolicy).get(() -> someRequest);
return response;
The scenario that is performed with this code:
We perform a request and (during testing) we expect to see an unchecked exception. However, this exception is 'swallowed' by functionality of the failsafe-lib, while I in fact want to see back this exception. I know this is more on my end, but I'm not sure how to fix this issue. Any tips, alternatives or corrections are much appreciated.
Found my own mistake: if the if-statement was not triggered, no exception would be thrown and null would be returned. This resulted in an empty response, etc.
doTask() is a method that performs something if previousStepResult is successful, otherwise logs and return previousStepResult as is. Below code works fine and conclude() is also executed but only when there no exceptions (errors). But if there are exceptions (which are well handled) the code returns false. So in case of error, the next step is called fine and as said, logs and return false. However conclude is not called at all. I am not sure if there is an impact of exceptions inside each step preventing thenAcceptAsync to be executed or what. Any clues ?
return CompletableFuture.supplyAsync(() -> doTask("task1", true), taskExecutor).
thenApplyAsync(previousStepResult -> doTask("task2", previousStepResult),taskExecutor).
thenApplyAsync(previousStepResult -> doTask("task3", previousStepResult),taskExecutor).
thenAcceptAsync(previousStepResult -> conclude(previousStepResult),taskExecutor);
Use CompletableFuture::handle or CompletableFuture::handleAsync after the step that is likely to throw error. This would result in further steps being called as it is, else would be skipped.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
In this answer, the code provided is:
void greet(String name) {
if (name == null) {
throw new IllegalArgumentException("Cannot greet null");
}
System.out.println("Hello, " + name);
}
I have seen similar examples on all sites where I went to learn the 'throw' keyword. What doesn't make sense to me whenever I see such examples is why would one simply not print: "Cannot greet null" instead of throwing an exception.
Questions:
Are there better examples of the utility of the throw keyword? (I am just going to pass out of high school and know only high school level Java programming so please avoid complicated examples)
In the given example, why did the user choose to throw an exception instead of simply printing the error?
Now it is time to revise the concept of Exception Handling in the Java.
First of All what is exception, whenever there is some error or say problem occur while executing the lines of code it is called the Exception.
For Example,
If a person divides something with 0, then it will give an exception as computer cannot handle the undefined entity.
Another example will be while you have declared a Scanner in order to get in integer input, but user enters an alphabet so it will also cause the exception.
Here we do exception handling, which means that we will handle exception in such a way that it will not cause program to close, those specific line which have been enclosed in the try and catch statement will not work properly but other lines will executed.
Now if we have made a method that do something lets suppose prints a line, and there is an exception occurred while printing that line, here we can do two things handle that exception at place where it has occurred or throw it.
If we handle exception at that place it is okay, and if we throw it then we have to catch it place where we have called that method.
Now as there are two types of Exceptions
1) Run Time Exception Which We Call Unchecked Exception
2) Compile Time Exception Which We Call Checked Exception
Both exceptions can be handle at the class level and method level too, one more thing we can do chain exceptional handling too. Which means that one class will throw exception to other and so on.
I think following answer can help you to understand ....
Are there better examples of the utility of the throw keyword?
Basically Throw and Throws are used to prevent the application for getting error or crashing by throwing exception.
Throws are used in the method signature and Throw are used to prevent the flow from getting error.
So here is a simple example for it.
public class Test {
// here we have used "throws" in method signature
// because we are throwing new Exception(), if array is null
public static int getValue(int[] array, int index) throws Exception {
// here we are preventing application from getting
// unconditional error (NullPointer exception)
// if array is null, then we are throwing new Exception()
if(array == null) {
throw new Exception();
}
int value = array[index];
return value;
}
public static void main(String[] args) {
int[] array = null;
// here we are wrapping our getValue() function call to try catch block
// because getValue() function can throws Exception
// so we are making it safe to execute our program
try {
int value = getValue(array, 0);
System.out.println("value " + value);
} catch (Exception e) {
System.out.println("Provided array is null... so we caught the exception...");
}
}
}
if you want to know more about how throw and throws works... then you need to know about Exception Handling (Checked and Unchecked) also.
In the given example, why did the user choose to throw an exception instead of simply printing the error?
As per the given example, your function purpose is to greet, but if some other function call greet() with
null value then there is no any reason to greet like Hello, null, so he throw an exception before executing the statement. like...
void greet(String name) {
System.out.println("Hello, " + name);
}
String myName = null;
greet(myName); // it will print "Hello, null";
'Throw' keyword is used to notify the caller that the argument passed is not valid (in this case), or in general, something went wrong while executing the code called by the caller.
Consider an example where you are writing an online shopping application. Following would be the simple sequence of events:
User scrolls through items and selects one or more items
Items are added into the cart and user clicks check out
User is redirected to 3rd party's payment page where he types in card details and makes the payment
User is shown the success page
Now, during payment, if the card number is incorrect or user doesn't have enough balance in the card, would you throw the error back to the caller (i.e. shopping app) or just log it on the console (on payment provider's side) and return the response? Of course the former, so this is just to let the caller know that there is an error and he should handle it gracefully (by showing appropriate message on checkout in our case).
A throw statement abruptly terminates the execution of the current function, and returns control right back to the caller, forcing them to deal with the error, or rethrow the exception up the chain.
An exception object contains lots of information about where and why an error occurred beyond just the error message. It keeps track of where in the call stack the error happened, and allows you to look up the sequence of calls that led up to it.
A print statement simply could not do all these things. Your example is already a good one. The job of the greet function is to print a greeting. If you pass in null, the function is unable to do so. Printing a message here would be potentially confusing. Instead, it forces you to deal with the fact that you have it invalid input rather than printing a benign message that someone might mistake for a greeting.
Try Java 8 Optional:
String nullVal = null;
System.out.println(Optional.ofNullable(nullVal).orElseGet(() -> null));
String notNull = "Hello Optional";
System.out.println(Optional.ofNullable(notNull).orElseGet(() -> null));
The method can be modify like this:
public static void greet(String name) {
System.out.println("Hello, " + Optional.ofNullable(name).orElseGet(()->null));
}
Assume a function checks that in the passed directory is no malicious file. That could be a void method where you need to catch the exception for the rare case, bypassing the normal processing after the call.
try {
checkDirectorySafe("/home/Donald");
...
} catch (VirusException e) {
...
}
The catch might be late in the code and also catch exceptions in other parts.
There is an other advantage. The function can check all files in the directory and for all subdirectories need only recursively call itself with the subdirectory path. On an exception the call stack is unwound upto the catch.
The Alternative would be to have a boolean or Optional result, and add if code. If the function also needs to return some data, that could become slightly uglier.
An exception is like a toilet in a mall.
I have 3 FutureTask<T> Objects. I want that they are processed asynchronously. However, as soon as one of the FutureTasks' get() methods doesn't return null I want to continue i.e my method (wrapper) returns and doesn't wait until the other two FutureTasks are processed.
I thought about something like:
private File wrapper(final File file) {
ExecutorService executors = Executors.newCachedThreadPool();
File returnFile;
FutureTask<File> normal= ...
FutureTask<File> medium=...
FutureTask<File> huge=...
executors.execute(normal);
executors.execute(medium);
executors.execute(huge);
try {
if((returnFile=normal.get()) != null ||
(returnFile=medium.get()) != null ||
(returnFile=huge.get()) != null)
return returnFile;
} catch(ExecutionException | InterruptedException e) { }
}
I'm not sure how to capture the exceptions (thrown by the get()) in a proper way because I assume they will be thrown since I just return without waiting for the other two tasks to be completed. Moreover I've doubts that the code will work like intended. I feel that I'm close to the solution but missing something.
May I suggest to check for FutureTask::isDone?
Would be something like this then:
while(true) {
if (normal.isDone()) {
return normal.get();
}
if (medium.isDone()) {
return medium.get();
}
if (huge.isDone()) {
return huge.get();
}
}
EDIT:
You could cancel the other tasks as soon as you have one result at hand.
Using FutureTask::get is not what you look for as it would most likely always return the result of normal.get() because the documentation already states that:
Waits if necessary for the computation to complete, and then retrieves
its result.
To clarify the above:
If you use FutureTask::get the first FutureTask you call get on will most likely block and wait until a result is available to return.
EDIT2:
Wrap that loop into a new Runnable, executed by the ExecutorService, passing the first result available to another method or implement a Callback and there's no more busy waiting.
I had an idea to design it using BlockingQueue. You extend your tasks with done method submitting results into BlockinQueue and, once client received first result, it cancels other tasks. On the other hand, experts suggest using ExecutorCompletionService instead. It seems to serialize results imself and has all appropriate examples.
This question already has answers here:
How should I unit test multithreaded code?
(29 answers)
Closed 5 years ago.
Executive Summary: When assertion errors are thrown in the threads, the unit test doesn't die. This makes sense, since one thread shouldn't be allowed to crash another thread. The question is how do I either 1) make the whole test fail when the first of the helper threads crashes or 2) loop through and determine the state of each thread after they have all completed (see code below). One way of doing the latter is by having a per thread status variable, e.g., "boolean[] statuses" and have "statuses[i] == false" mean that the thread failed (this could be extended to capture more information). However, that is not what I want: I want it to fail just like any other unit test when the assertion errors are thrown. Is this even possible? Is it desirable?
I got bored and I decided to spawn a bunch of threads in my unit test and then have them call a service method, just for the heck of it. The code looks approximately like:
Thread[] threads = new Thread[MAX_THREADS];
for( int i = 0; i < threads.length; i++ ) {
threads[i] = new Thread( new Runnable() {
private final int ID = threadIdSequenceNumber++;
public void run() {
try {
resultRefs[ID] = runTest( Integer.toString( ID ) ); // returns an object
}
catch( Throwable t ) {
// this code is EVIL - it catches even
// Errors - don't copy it - more on this below
final String message = "error testing thread with id => "
+ ID;
logger.debug( message, t );
throw new IllegalStateException( message, t );
// need to wrap throwable in a
// run time exception so it will compile
}
}
} );
}
After this, we will loop through the array of threads and start each one. After that we will wait for them all to finish. Finally, we will perform some checks on the result references.
for( Thread thread : threads )
thread.start();
logger.debug( "waiting for threads to finish ..." );
boolean done = false;
while( !done ) {
done = true;
for( Thread thread : threads )
if( thread.isAlive() )
done = false;
}
for( int i = 0; i < resultRefs.length; i++ ) {
assertTrue( "you've got the world messed, dawg!",
myCondition(resultRefs[i]) );
Here's the problem. Did you notice that nasty try-catch-throwable block? I just added that as a temporary hack so I could see what was going on. In runTest( String ) a few assertions are made, e.g., assertNotNull( null ), but since it is in a different thread, it doesn't cause the unit test to fail!!!!
My guess is that we will need to somehow iterate over the threads array, check the status of each, and manually cause an assertion error if the thread terminated in a nasty way. What's the name of the method that gives this information (the stack trace of the dead thread).
Concurrency is one of those things that are very difficult to unit test. If you are just trying to test that the code inside each thread is doing what it is supposed to test, may be you should just test this code isolated of the context.
If in this example the threads collaborate to reach a result, may be you can test that collaboration without using threads. That would be done by executing all the collaborative parts sequentially.
If you want to test for race conditions and these kind of things, unit testing is not the best way. You will get tests that sometimes fail and sometimes donĀ“t fail.
To summarize, I think that may be your problem is that you are unit testing in a level too high.
Hope this helps
The Google Testing Blog had an excellent article on this subject that's well worth reading: http://googletesting.blogspot.com/2008/08/tott-sleeping-synchronization.html
It's written in Python, but I think the principles are directly transferable to Java.
Unit testing in a multithreaded environment is tough... so some adjustments need to be made. Unit tests must be repeatable.. deterministic. As a result anything with multiple threads fails this criteria. Tests with multiple threads also tend to be slow.
I'd either try to see if I can get by with testing on a single thread.. does the logic under test really need multiple threads.
If that doesn't work, go with the member variable approach that you can check against an expected value at the end of the test, when all the threads have finished running.
Hey seems like there's another question just like this. Check my post for a link to a longer discussion at the tdd yahoogroup
Unit testing a multithreaded application?
Your runnable wrapper should be passing the exception object back to your test class and then you can store them in a collection. When all the tests are finish you can test the collection. If it isn't empty, iterate over each of the exceptions and .printStackTrace() then fail.
Implement a UncaughtExceptionHandler that sets some flags (which the Threads peridocially check) and set it on each Thread.
Another popular option for Junit concurrent thread testing is Matthieu Carbou's method using a custom JunitRunner and a simple annotation.
See the full documentation
It is possible making the unit test to fail, by using a special synchronization object. Take a look at the following article:
Sprinkler - Advanced synchronization object
I'll try to explain the main points here.
You want to be able to externalize internal threads failures to the main thread, which, in your case is the test. So you have to use a shared object/lock that both the internal thread and the test will use to sync each other.
See the following test - it creates a thread which simulates a thrown exception by calling a shared object named Sprinkler.
The main thread (the test) is blocked on Sprinkler.getInstance().await(CONTEXT, 10000)
which, by the time release is called - will be free and catch the thrown exception.
In the catch block you can write the assert which fails the test.
#Test
public void testAwait_InnerThreadExternalizeException() {
final int CONTEXT = 1;
final String EXCEPTION_MESSAGE = "test inner thread exception message";
// release will occur sometime in the future - simulate exception in the releaser thread
ExecutorServiceFactory.getCachedThreadPoolExecutor().submit(new Callable<void>() {
#Override
public Void call() throws Exception {
Sprinkler.getInstance().release(CONTEXT, new RuntimeException(EXCEPTION_MESSAGE));
return null;
}
});
Throwable thrown = null;
try {
Sprinkler.getInstance().await(CONTEXT, 10000);
} catch (Throwable t) {
// if the releaser thread delivers exception it will be externelized to this thread
thrown = t;
}
Assert.assertTrue(thrown instanceof SprinklerException);
Assert.assertEquals(EXCEPTION_MESSAGE, thrown.getCause().getMessage());
}