Throw InterruptedException when using parallelStream - Java [duplicate] - java

This question already has answers here:
How can I throw CHECKED exceptions from inside Java 8 lambdas/streams?
(18 answers)
Closed 4 years ago.
I have a method with nested for loops as follows:
public MinSpecSetFamily getMinDomSpecSets() throws InterruptedException {
MinSpecSetFamily result = new MinSpecSetFamily();
ResourceType minRT = this.getFirstEssentialResourceType();
if (minRT == null || minRT.noSpecies()) {
System.out.println("There is something wrong with the "
+ "minimal rticator, such as adjacent to no species. ");
}
for (Species spec : minRT.specList) {
ArrayList<SpecTreeNode> leafList = this.getMinimalConstSpecTreeRootedAt(spec).getLeaves();
for (SpecTreeNode leaf : leafList) {
result.addSpecSet(new SpecSet(leaf.getAncestors()));
}
}
return result;
}
This works fine, but the application is performance critical so I modified the method to use parallelStream() as follows:
public MinSpecSetFamily getMinDomSpecSets() throws InterruptedException {
ResourceType minRT = this.getFirstEssentialResourceType();
if (minRT == null || minRT.noSpecies()) {
System.out.println("There is something wrong with the "
+ "minimal rticator, such as adjacent to no species. ");
}
MinSpecSetFamily result = minRT.specList.parallelStream()
.flatMap(spec -> getMinimalConstSpecTreeRootedAt(spec).getLeaves().parallelStream())
.map(leaf -> new SpecSet(leaf.getAncestors()))
.collect(MinSpecSetFamily::new, MinSpecSetFamily::addSpecSet, MinSpecSetFamily::addMSSF);
return result;
}
This worked fine until I wanted to introduce an InterruptedException in the 'getLeaves()' method. Now the parallelStream version will not compile as it says I have an unreported InterruptedException which must be caught or declared to be thrown. I think this is because the parallelStream runs on multiple threads. No combination of try/catch blocks suggested by my IDE resolves the issue.
The second solution posted in Interrupt parallel Stream execution
suggests that I may be able to resolve the issue using ForkJoinPool but I have been unable to figure out how to modify my method to use this approach.

If you want to stick to your current design, you just need to catch the exception:
.flatMap(spec -> {
try {
return getMinimalConstSpecTreeRootedAt(spec).getLeaves().parallelStream();
} catch (InterruptedException e) {
// return something else to indicate interruption
// maybe an empty stream?
}
}).map(...)
Note that a parallel stream of parallel streams is possibly unnecessary and parallelising the top level stream only may be sufficient performance-wise.

Related

Test whether code throws a specific exception [duplicate]

This question already has answers here:
How do you assert that a certain exception is thrown in JUnit tests?
(35 answers)
JUnit 5: How to assert an exception is thrown?
(12 answers)
Closed 3 months ago.
I'm trying to test if an exception with a customized message is thrown when a division by zero is attempted.
Here's the method:
public static int getMultiplesOfGivenNumber(int number, int[] array){
int multiples = 0;
if (number == 0) {
throw new ArithmeticException("Number cannot be zero");
}else{
for (int i = 0; i < array.length; i++) {
if (array[i] % number == 0) {
multiples += 1;
}
}
}
After searching some solutions, I found this as a way to do the thing, but my IDE can't recognize 'expected' ...
#Test(expected=java.lang.ArithmeticException.class)
public void testDivideByZero(){
//arrange
int number = 0;
//act
int result = B3_E2.getMultiplesOfGivenNumber(number, intervalFromOneToTen());
//assert
assertEquals(expected, result);
}
I'm just unaware why my IDE is not recognizing 'expected'. Don't know if this has something to do with Junit version, or if there's some issue with the syntax I'm using.
In every other tests I used so far I never put nothing after #Test. I just found out this solution in another thread for a similar problem.
The expected argument to the #Test annotation exists only since JUnit 4. You must be using an earlier version of JUnit.
That having been said, you do not have to use this annotation, so you do not have to upgrade to JUnit 4 just for this feature.
You can use a try...catch yourself, and assert that the exception was thrown, and also assert that the custom message is what it is supposed to be.
#Test
public void testDivideByZero()
{
try
{
B3_E2.getMultiplesOfGivenNumber( 0, intervalFromOneToTen() );
assertTrue( false ); //expected exception was not thrown
}
catch( ArithmeticException e )
{
assertEquals( e.getMessage(), "Number cannot be zero" );
}
}
The benefit of going this way is that you can get your hands on the exception object, so you can examine its contents and make sure that it was initialized as expected. In the case of ArithmeticException there is nothing to check other than the message, but in other cases there may be a lot more to check.

stream has already been operated upon or closed, even after using suplier

I have below code, but gettting error:
Stream<BigDecimal> method(Stream<BigDecimal> in) {
if (in == null)
return Stream.empty();
Supplier<Stream<BigDecimal>> supplier = () -> in;
Stream<BigDecimal> s1 = supplier.get().filter(e -> e != null);
long count = s1.count();
double average = supplier.get().mapToDouble(BigDecimal::doubleValue).average().orElse(Double.NaN);
return supplier.get();
}
Error says:
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
at java.util.stream.AbstractPipeline.<init>(AbstractPipeline.java:203)
at java.util.stream.DoublePipeline.<init>(DoublePipeline.java:90)
at java.util.stream.DoublePipeline$StatelessOp.<init>(DoublePipeline.java:597)
at java.util.stream.ReferencePipeline$6.<init>(ReferencePipeline.java:238)
at java.util.stream.ReferencePipeline.mapToDouble(ReferencePipeline.java:237)
How to fix this issue, I already tried using supplier.get method, but still getting errors.
You're not really using the Supplier here. If you want this to work, the argument to method must itself be a Supplier<Stream<BigDecimal>>. () -> in doesn't actually do what you need the supplier to do, which is to generate an entirely new stream.

Continue the flow after throwing exception

In my use case, I am looping across a map and checking whether a particular key is present in a list. If it is present then I have to trow and exception otherwise continue with the execution.
Map<A,B> myMap = new HashMap<A,B>();
//code to populate values in myMap
...
...
List<A> myList = new ArrayList<A>();
//code to populate values in myList
...
...
for(Map.Entry<A,B> eachElementInMap:myMap.entrySet()){
if(myList.contains(eachElementInMap:myMap.getKey())){
//throwing exception
throw new MyCustomizedException("someString");
}
}
//code continues
...
....
In the above example, if there are 3 elements in the map(myMap) in which 1 key is present in the list(myList), I want to throw the exception for one and it should continue executing other lines of code for the rest two. Am I using a wrong design to achieve this? Any help or suggestion is appreciated! Thanks
Typically once you throw an exception, you are saying that the current line of execution should terminate, rather than continue. If you want to keep executing code, then maybe hold off on throwing an exception.
boolean fail = false;
for (Map.Entry<A,B> eachElementInMap:myMap.entrySet()) {
if (myList.contains(eachElementInMap:myMap.getKey())) {
// throw an exception later
fail = true;
}
}
if (fail) {
throw new MyCustomizedException("someString");
}
You can also create an exception object at a different location from where you throw it. This idiom will be useful in cases where the exception message is not just "someString", but needs to be constructed from data obtained from the object being iterated over.
Optional<MyCustomizedException> exception = Optional.empty();
for (Map.Entry<A, B> eachElementInMap:myMap.entrySet()) {
if (myList.contains(eachElementInMap.getKey())) {
// Create an exception object that describes e.g., the missing key(s)
// but do not throw it yet.
if( exception.isPresent() ) {
exception.get().addToDescription( /* Context-sensitive information */ );
}
else {
exception = Optional.of(
new MyCustomizedException( /* Context-sensitive information */));
}
}
}
if( exception.isPresent() ) {
throw exception.get();
}
If the only data stored in the exception is a string, an equivalent effect can be achieved by accumulating problem descriptions in a StringBuilder, but for cases where more interesting data needs to go into the exception object, building as you go might be an option worth considering.
You can split it into two lists,failList and successList. and do it.
This is clearer
failList = myMap.entrySet().stream().filter(p->myList.contains(p.getKey())).collect(Collectors.toList());
successList = myMap.entrySet().stream().filter(p->!myList.contains(p.getKey())).collect(Collectors.toList());
failList.forEach(p -> {
// fail code
});
successList .forEach(p -> {
// success code
});
why not use if...else instead of try catch ? error just means that's a mistake. if you afraid that makes some mistakes what you don't know. you can use throw error.
anyway, it should not be used when the program is running as you wish

Aggregate runtime exceptions in Java 8 streams

Let's say I have a method which throws a runtime exception. I'm using a Stream to call this method on items in a list.
class ABC {
public void doStuff(MyObject myObj) {
if (...) {
throw new IllegalStateException("Fire! Fear! Foes! Awake!");
}
// do stuff...
}
public void doStuffOnList(List<MyObject> myObjs) {
try {
myObjs.stream().forEach(ABC:doStuff);
} catch(AggregateRuntimeException??? are) {
...
}
}
}
Now I want all items in the list to be processed, and any runtime exceptions on individual items to be collected into an "aggregate" runtime exception which will be thrown at the end.
In my real code, I am making 3rd party API calls which may throw runtime exceptions. I want to make sure that all items are processed and any errors reported at the end.
I can think of a few ways to hack this out, such as a map() function which catches and returns the exception (..shudder..). But is there a native way to do this? If not, is there another way to implement it cleanly?
In this simple case where the doStuff method is void and you only care about the exceptions, you can keep things simple:
myObjs.stream()
.flatMap(o -> {
try {
ABC.doStuff(o);
return null;
} catch (RuntimeException ex) {
return Stream.of(ex);
}
})
// now a stream of thrown exceptions.
// can collect them to list or reduce into one exception
.reduce((ex1, ex2) -> {
ex1.addSuppressed(ex2);
return ex1;
}).ifPresent(ex -> {
throw ex;
});
However, if your requirements are more complicated and you prefer to stick with the standard library, CompletableFuture can serve to represent "either success or failure" (albeit with some warts):
public static void doStuffOnList(List<MyObject> myObjs) {
myObjs.stream()
.flatMap(o -> completedFuture(o)
.thenAccept(ABC::doStuff)
.handle((x, ex) -> ex != null ? Stream.of(ex) : null)
.join()
).reduce((ex1, ex2) -> {
ex1.addSuppressed(ex2);
return ex1;
}).ifPresent(ex -> {
throw new RuntimeException(ex);
});
}
There are already some implementations of Try monad for Java. I found better-java8-monads library, for example. Using it, you can write in the following style.
Suppose you want to map your values and track all the exceptions:
public String doStuff(String s) {
if(s.startsWith("a")) {
throw new IllegalArgumentException("Incorrect string: "+s);
}
return s.trim();
}
Let's have some input:
List<String> input = Arrays.asList("aaa", "b", "abc ", " qqq ");
Now we can map them to successful tries and pass to your method, then collect successfully handled data and failures separately:
Map<Boolean, List<Try<String>>> result = input.stream()
.map(Try::successful).map(t -> t.map(this::doStuff))
.collect(Collectors.partitioningBy(Try::isSuccess));
After that you can process successful entries:
System.out.println(result.get(true).stream()
.map(t -> t.orElse(null)).collect(Collectors.joining(",")));
And do something with all the exceptions:
result.get(false).stream().forEach(t -> t.onFailure(System.out::println));
The output is:
b,qqq
java.lang.IllegalArgumentException: Incorrect string: aaa
java.lang.IllegalArgumentException: Incorrect string: abc
I personally don't like how this library is designed, but probably it will be suitable for you.
Here's a gist with complete example.
Here's a variation on the theme of mapping-to-exceptions.
Start with your existing doStuff method. Note that this conforms to the functional interface Consumer<MyObject>.
public void doStuff(MyObject myObj) {
if (...) {
throw new IllegalStateException("Fire! Fear! Foes! Awake!");
}
// do stuff...
}
Now write a higher-order function that wraps this and turns this into a function that might or might not return an exception. We want to call this from flatMap, so the way "might or might not" is expressed is by returning a stream containing the exception or an empty stream. I'll use RuntimeException as the exception type here, but of course it could be anything. (In fact it might be useful to use this technique with checked exceptions.)
<T> Function<T,Stream<RuntimeException>> ex(Consumer<T> cons) {
return t -> {
try {
cons.accept(t);
return Stream.empty();
} catch (RuntimeException re) {
return Stream.of(re);
}
};
}
Now rewrite doStuffOnList to use this within a stream:
void doStuffOnList(List<MyObject> myObjs) {
List<RuntimeException> exs =
myObjs.stream()
.flatMap(ex(this::doStuff))
.collect(Collectors.toList());
System.out.println("Exceptions: " + exs);
}
The only possible way I can imagine is to map values in a list to a monad, that will represent the result of your processing execution (either success with value or failure with throwable). And then fold your stream into single result with aggregated list of values or one exception with list of suppressed ones from the previous steps.
public Result<?> doStuff(List<?> list) {
return list.stream().map(this::process).reduce(RESULT_MERGER)
}
public Result<SomeType> process(Object listItem) {
try {
Object result = /* Do the processing */ listItem;
return Result.success(result);
} catch (Exception e) {
return Result.failure(e);
}
}
public static final BinaryOperator<Result<?>> RESULT_MERGER = (left, right) -> left.merge(right)
Result implementation may vary but I think you get the idea.

Exception handling within if statements in Java

I'm a relative newbie to custom error handling in Java, and I'm trying to figure out how to use catch statements to deliver specific messages inside of an if statement. I wanted to get some extra sets of eyes to look at what I'm trying to do and offer feedback before I completely overthink this and overdo it too badly.
Consider:
We have a directory of hourly log files and I have an on-demand reporting job creates a concatenation of all today's log files created so far. I want to add a step that checks for the existence of a concatenated log file, deletes it then creates it if present, or just creates it if it's not present. With the code below, I'm returning an exception if, for some reason, the new file cannot be created.
try {
File file = new File (destinationPath + "todayToNowLogFile.csv");
if(file.exists())
{
if(file.delete())
{
System.out.println(file.getName() + " is deleted!");
} else {
System.out.println("Existing file cannot be deleted.")
}
} else {
System.out.println("File will be created.");
}
}
//
catch(Exception e) {
System.err.println("Exception: ");
System.out.println("Exception: "+ e.getMessage().getClass().getName());
e.printStackTrace();
}
Now, in the case where the file cannot be deleted, I would like to display the exception preventing file deletion. First, I would need to catch that error, but then where do I put the try?
Doing something like this...
try
{
if(file.delete())
{
System.out.println(file.getName() + " is deleted!");
}
}
else {
catch(Exception eDel) {
System.err.println("Exception: ");
System.out.println("Exception: "+ eDel.getMessage().getClass().getName());
eDel.printStackTrace();
}
}
....interrupts the if...then block. I'm not sure how to insert a try...catch within an if...then. Is there a way to do this? Or does my original code catch EVERY error associated with ANY operation on the file defined in the try block, and I would need to put if...then logic in the catch block, something along the lines of this pseudocode....
catch(Exception e) {
if(exception relates to file deletion) {
"File delete exception " + exceptionMessages;
} else if(exception relates to file creation) {
"File create exception " + exceptionMessages;
} else if(other exception) {
"other exception " + exceptionMessage;
} else {
"no exceptions encountered"
}
}
What's the most appropriate way to handle this type of situation?
You should think of try/catch as any other statement. So you can put it inside any of two branches of if/then/else statement, but it have to be whole inside:
if(statement){
...
try{
...
}catch(...){
...
}
...
}else{
...
try{
...
}catch(...){
...
}
...
}
If you have to catch multiple exceptions you can achieve this by multiple catch parts:
try{
...
}catch(Exception1 e1){
...
}catch(Exception2 e2){
...
}catch(Exception3 e3){
...
}
What you want here is to create your own Exception class.
To create an exception class say you need to extend Exception class. Here's an example.
Lets say my custom exception class should be named as MyFileErrorException
So I create a new class like this -
class MyFileErrorException extends Exception {
private String message = null;
public MyFileErrorException() {
super();
}
public MyFileErrorException(String message) {
super(message);
this.message = message;
}
public MyFileErrorException(Throwable cause) {
super(cause);
}
#Override
public String toString() {
return message;
}
#Override
public String getMessage() {
return message;
}
}
Now I need to throw this exception at will. So in Your case you wantto catch File delete exception so the code will like this -
if(file.delete())
{
System.out.println(file.getName() + " is deleted!");
} else {
try{
System.out.println("Existing file cannot be deleted.")
throw new MyFileErrorException("File Could not be deleted val is null");
}catch(MyFileErrorException ex){
//Do wahtever you want to do
}
}
At first you should check if any method could throw any specific Exceptions. You could do this by looking into the Javadoc or use your favorite IDE.
If you catch Exception as the Exception class, it catches every Exception that is subclass of it.
If you want to have specific Exception handling, e.g. for an IOException like in the delete() method, you can catch every specific Exceptionclass or use multi-catch in Java 7
try {
do regular code that can throw exceptions
} catch(Exception e) {
it catches every Exception that is a subclass of Exception.
You handle every exception raised in the try block above by the same way
}
If you want to handle exceptions in different ways, e.g. print different messages, just do this like the following example:
try {
do sth
} catch (SpecificExceptionclass sec) {
do sth specific for this exception
} catch (AnotherExceptionClass aec) {
do sth else
}
Or just use Multicatch in Java 7, if you want to have same exception handling for some specific exception classes:
try {
do sth
} catch (SpecificExceptionclass | AnotherExceptionClass e) {
do sth specific for this exception
}
To achieve different Exceptions thrown in your code the methods should at least throw different exceptions. In your example with file.exists() and file.delete() there's only an IOException thrown by your code, so there is no use of specific exception handling.
I think it would be a good idea to put your code in a function that returns true or false.
1: True means the file does not exist and was created
2: False means the file exists and was deleted.
3: An exception if the file exists but cant be deleted.
Also provide a separate function to determine if the file exists or not.
Your javadoc at the top of your functions should explain the above so the caller of your functions don't have to look at their content to determine how to use them.
Note an exception is an unusual event and shouldn't be thrown to indicate the state of inserting/deleting. It should be reserved for unusual conditions which the caller normally wouldn't encounter.
A note on exceptions: If you have a large project with 1000 classes each of which has on average 20 functions, that's 20000 functions. Its not practical to pepper each function with excessive exception handling (such as checking for nulls passed in as arguments). A solution to this is to handle checked exceptions in the java language (FileIO) and let (the bulk) of unchecked exceptions ripple up the function call chain until you leave all your business logic and are about to display the results. You only catch them if you want to add additional information to the exception before rethrowing it. Example: adding the primary key value of the record of an SQLExeption being thrown so you know what record is causing problems. Just before you return to the user, log the stack trace and display a simplified message to the user (not the stack trace). The caller of your function should read its javadoc to see how to use it. If he violates your javadoc, the function may or may not throw an exception. Its his reponsibility to follow the javadoc. Last point: your project should have general coding policies for the entire project to prevent some types of exceptions from accidently being introduced by the caller such as: all functions are not epected to recieve nulls as arguments or will return a null unless specified in its javadoc. All functions will accept as arguments (or return) empty lists or empty strings correctly unless specified in their javadoc.

Categories

Resources