[JAVA-4524] Observable.map calls onComplete after onError Created: 09/Mar/22  Updated: 04/May/22  Resolved: 16/Mar/22

Status: Closed
Project: Java Driver
Component/s: Scala
Affects Version/s: 4.5.0
Fix Version/s: None

Type: Bug Priority: Unknown
Reporter: Ostrzyciel Nożyczek Assignee: Ross Lawley
Resolution: Duplicate Votes: 0
Labels: external-user
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
related to JAVA-4304 Propagate exceptions thrown in map or... Closed
is related to JAVA-4487 Use project reactor for Scala Observa... Closed

 Description   

Summary

Driver version: 4.5.0

Following up from JAVA-4304, it seems that Observable.map does not take into account whether the inner function threw an exception when calling onComplete.

So, when an exception occurs, MapObservable first calls onError (which is fine) and then onComplete on the the next Observer in the chain, which is against the reactive streams spec.

How to Reproduce

The following code will throw an IllegalStateException in ToSingleObservablePublisher with message "onComplete called after the Observer has already completed or errored."

val future = SingleObservable[Int](1).map( { x =>
  throw new RuntimeException("Some exception")
} ).toSingle().toFuture()

Additional Background

I've managed to circumvent the bug by making a patched version of the Observable.map method that simply does not call onComplete after an exception has occured in the inner function. My code is really bad and Scala 3, though, so sharing it won't help much.  But the fix seems easy enough.



 Comments   
Comment by Ostrzyciel Nożyczek [ 16/Mar/22 ]

Thanks for investigating this!

Comment by Ross Lawley [ 16/Mar/22 ]

Hi ostrzycielnozyczek@gmail.com,

After testing, I can confirm this was fixed by JAVA-4487.

Ross

Comment by Ross Lawley [ 15/Mar/22 ]

Hi ostrzycielnozyczek@gmail.com,

According to the reactive streams spec 2.13, throwing an error from onNext is not allowed.

Calling onSubscribe, onNext, onError or onComplete MUST return normally except when any provided parameter is null in which case it MUST throw a java.lang.NullPointerException to the caller, for all other situations the only legal way for a Subscriber to signal failure is by cancelling its Subscription. In the case that this rule is violated, any associated Subscription to the Subscriber MUST be considered as cancelled, and the caller MUST raise this error condition in a fashion that is adequate for the runtime environment.

However, I will add a further check to ensure onComplete isn't called - as that is definitely a bug in the mapping observable and I'll ensure that the error is propagated correctly.

Ross

Comment by Esha Bhargava [ 11/Mar/22 ]

ostrzycielnozyczek@gmail.com Thank you for reporting this issue! We'll look into it and get back to you soon.

Generated at Thu Feb 08 09:02:18 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.