Why does Mono.doOnSuccess() suppress errors? - project-reactor

In the following code snippet, an exception is thrown, as is to be expected:
#Test
public void testError()
{
Mono.error(new NullPointerException())
.subscribe();
}
However, in the following code snippet no exception is thrown:
#Test
public void testErrorWithDoOnSuccess()
{
Mono.error(new NullPointerException())
.doOnSuccess(aValue -> {})
.subscribe();
}
When I use the block operator instead of the subscribe operator, the exception works again:
#Test
public void testErrorWithDoOnSuccessAndBlock()
{
Mono.error(new NullPointerException())
.doOnSuccess(aBoolean -> {})
.block();
}
The documentation of the Mono.doOnSuccess operator does not say anything specifically about its behavior w.r.t. errors, but I wouldn't expect this behavior at all given the name of the operator. Why does it suppress exceptions (and only when not using the block operator)? Is this intended behavior, or is this a bug?
Reactor version used is the most recent one at time of writing, 3.1.8.RELEASE.

This is a bug, the operator should suppress the "No error callback implemented" exception only in the case where you use doOnTerminate/doAfterTerminate, not doOnSuccess...
That said, operator still propagates the NPE and this bug is easily worked around by implementing best practices: always define at least value handler and error handler in subscribe(...).

Related

ANTLR best practice for finding and catching parse errors

This question concerns how to get error messages out of an ANTLR4 parser in C# in Visual Studio. I feed the ANTLR parser a known bad input string, but I am not seeing any errors or parse exceptions thrown during the (bad) parse. Thus, my exception handler does not get a chance to create and store any error messages during the parse.
I am working with an ANTLR4 grammar that I know to be correct because I can see correct parse operation outputs in graphical form with an ANTLR extension to Visual Studio Code. I know the generated parser code is correct because I can compile it correctly without errors, override the base visitor class, and print out various bits of information from the parse tree with my overwritten VisitXXX methods.
At this point, I am running a very simple test case that feeds in a bad input string and looks for a nonzero count on my list of stored parse errors. I am confident of the error-handling code because it works in a similar situation on another grammar. But the error-handling code must catch a parse exception to generate an error message. (Maybe that's not the right way to catch/detect parse errors such as unexpected tokens or other errors in the input stream.)
Here is the code that I used to replace the default lexer and parser error listeners.
// install the custom ErrorListener into the parser object
sendLexer.RemoveErrorListeners();
sendLexer.AddErrorListener(MyErrorListener.Instance);
Parser.RemoveErrorListeners();
Parser.AddErrorListener(MyErrorListener.Instance);
I have attached a screenshot of the graphical output showing the presence of unexpected tokens in the input string.
Q1. Why don't the unexpected tokens cause parse exceptions that I can catch with my exception handler? Are all parse errors supposed to throw exceptions?
Q2. If catching parse exceptions is not the right way, could someone please suggest a strategy for me to follow to detect the unexpected token errors (or other errors that do not throw parse exceptions)?
Q3. Is there a best practice way of catching or finding parse errors, such as generating errors from walking the parse tree, rather than hoping that ANTLR will throw a parse exception for every unexpected token? (I am wondering if unexpected tokens are supposed to generate parse exceptions, as opposed to producing and legitimate parse tree that happens to contain unexpected tokens? If so, do they just show up as unexpected children in the parse tree?)
Thank you.
Screenshot showing unexpected tokens in the (deliberate) bad input string to trigger errors:
UPDATE:
Currently, the parser and unit tests are working. If I feed a bad input string into the parser, the default parser error listener produces a suitable error message. However, when I install a custom error listener, it never gets called. I don't know why it doesn't get called when I see an error message when the custom error listener is not installed.
I have the parser and unit tests working now. When I inject a bad input string, the default parse error listener prints out a message. But when I install a custom error listener, it never gets called. 1) A breakpoint placed in the error listener never gets hit, and 2) (as a consequence) no error message is collected nor printed.
Here is my C# code for the unit test call to ParseText:
// the unit test
public void ModkeyComboThreeTest() {
SendKeysHelper.ParseText("this input causes a parse error);
Assert.AreEqual(0, ParseErrors.Count);
// the helper class that installs the custom error listener
public static class SendKeysHelper {
public static List<string> ParseErrorList = new List<string>();
public static MyErrorListener MyErrorListener;
public static SendKeysParser ParseText(string text) {
ParseErrors.Clear();
try {
var inputStream = new AntlrInputStream(text);
var sendLexer = new SendKeysLexer(inputStream);
var commonTokenStream = new CommonTokenStream(sendLexer);
var sendKeysParser = new SendKeysParser(commonTokenStream);
Parser = sendKeysParser;
MyErrorListener = new MyErrorListener(ParseErrorList);
Parser.RemoveErrorListeners();
Parser.AddErrorListener(MyErrorListener);
// parse the input from the starting rule
var ctx = Parser.toprule();
if (ParseErrorList.Count > 0) {
Dprint($"Parse error count: {ParseErrorList.Count}");
}
...
}
// the custom error listener class
public class MyErrorListener : BaseErrorListener, IAntlrErrorListener<int>{
public List<string> ErrorList { get; private set; }
// pass in the helper class error list to this constructor
public MyErrorListener(List<string> errorList) {
ErrorList = errorList;
}
public void SyntaxError(IRecognizer recognizer, int offendingSymbol,
int line, int offset, string msg, RecognitionException e) {
var errmsg = "Line " + line + ", 0-offset " + offset + ": " + msg;
ErrorList.Add(errmsg);
}
}
So, I'm still trying to answer my original question on how to get error information out of the failed parse. With no syntax errors on installation, 1) the default error message goes away (suggesting my custom error listener was installed), but 2) my custom error listener SyntaxError method does not get called to register an error.
Or, alternatively, I leave the default error listener in place and add my custom error listener as well. In the debugger, I can see both of them registered in the parser data structure. On an error, the default listener gets called, but my custom error listener does not get called (meaning that a breakpoint in the custom listener does not get hit). No syntax errors or operational errors in the unit tests, other than that my custom error listener does not appear to get called.
Maybe the reference to the custom listener is somehow corrupt or not working, even though I can see it in the parser data structure. Or maybe a base class version of my custom listener is being called instead. Very strange.
UPDATE
The helpful discussion/answer for this thread was deleted for some reason. It provided much useful information on writing custom error listeners and error strategies for ANTLR4.
I have opened a second question here ANTLR4 errors not being reported to custom lexer / parser error listeners that suggests an underlying cause for why I can't get error messages out of ANTLR4. But the second question does not address the main question of this post, which is about best practices. I hope the admin who deleted this thread undeletes it to make the best practice information visible again.
The parser ErrorListener SyntaxError method needs the override modifier to bypass the default method.
public class ParserErrorListener : BaseErrorListener
{
public override void SyntaxError(
TextWriter output, IRecognizer recognizer,
IToken offendingSymbol, int line,
int charPositionInLine, string msg,
RecognitionException e)
{
string sourceName = recognizer.InputStream.SourceName;
Console.WriteLine("line:{0} col:{1} src:{2} msg:{3}", line, charPositionInLine, sourceName, msg);
Console.WriteLine("--------------------");
Console.WriteLine(e);
Console.WriteLine("--------------------");
}
}
The lexer ErrorListener is a little different. While the parser BaseErrorListener implements IAntlrErrorListener of type IToken, the lexer requires an implementation of IAntlrErrorListener of type int. The SyntaxError method does not have an override modifier. Parameter offendingSymbol is an int instead of IToken.
public class LexerErrorListener : IAntlrErrorListener<int>
{
public void SyntaxError(
TextWriter output, IRecognizer recognizer,
int offendingSymbol, int line,
int charPositionInLine, string msg,
RecognitionException e)
{
string sourceName = recognizer.InputStream.SourceName;
Console.WriteLine("line:{0} col:{1} src:{2} msg:{3}", line, charPositionInLine, sourceName, msg);
Console.WriteLine("--------------------");
Console.WriteLine(e);
Console.WriteLine("--------------------");
}
}

dart: how to catch TypeError during compilation

Below code throws a runtime error.
TypeError: Instance of 'FormatException': type 'FormatException' is not a subtype of type 'CustomException'
Why Test(e) does not fail at compilation as type of e is Exception and expected is CustomException. How to enforce it so one cannot pass Exception there.
abstract class CustomException implements Exception {
String get code;
}
class Test {
final CustomException ex;
Test(this.ex);
}
void main() {
try {
throw new FormatException();
} on Exception catch (e) {
final t = Test(e);
print('message: $t');
}
}
Dart has (for now) implicit downcasts from a supertype to a subtype. You are allowed to use an expression which is a super-type of the actual type that is required, under the assumption that you know what you are doing.
Here you have a value with static type Exception (the e that was caught), and you pass it to a constructor requiring a CustomException, which is a subtype of Exception.
The language allows this, but inserts a run-time downcast (equivalent to e as CustomException). That cast fails because the value is actually a FormatException.
With the up-coming null safety feature, implicit downcasts will be removed except from dynamic (because dynamic turns off static type checks anyway). When that happens, the Test(e) invocation becomes invalid. Until then, this code compilers and fails at run-time.
Until then, you can get the analyzer to warn you about implicit calls by configuring it in the analysis_options.yaml file

Reactor StepVerifier test fails with blockFirst()

Here is code to check duplicate names in database
public Mono<Void> validateDuplicateName(String name) throws RuntimeException {
Flux<Customer> customerFlux = customerRepository.findByNameIgnoreCase(name);
customerFlux.take(1).flatMap( customer -> {
return Mono.error( new RuntimeException ("ABC99") );
}).blockFirst();
return Mono.empty();
}
Below is the test script to test the validateDuplicateName method
when(customerRepositoryMocked.findByNameIgnoreCase(Mockito.anyString())).thenReturn(Flux.just(customerMocked));
StepVerifier.create(customerValidator.validateDuplicateName(Mockito.anyString()))
.expectErrorMatches( exception -> exception instanceof RuntimeException )
.verify();
But the test fails with the below error
java.lang.RuntimeException: ABC99
..
..
Suppressed: java.lang.Exception: #block terminated with an error
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:93)
at reactor.core.publisher.Flux.blockFirst(Flux.java:2013)
... 34 more
Can I please get some help ?
Your StepVerifier can actually only test the Mono.empty() that is systematically returned by the method. In the meantime, your use blockFirst, which will throw any exception emitted by the publisher, shortcircuiting the whole assertion.
Remember StepVerifier lets you assert what you expect will be asynchronously emitted by the sequence (including errors, in the form of onError signals). If the sequence can't even be created because the method creating it (validateDuplicateName) throws, then the StepVerifier is helpless.
But the real question is why on earth would you block inside a method that has a Mono return type AND has a perfectly fine Mono source handy? Your return Mono must be derived from that customerFlux.
You could use then() to switch to a Mono<Void>: this ignores the source's elements, but correctly propagates an error.

catch any error in angular dart (like angular's ErrorHandler)

I need to catch any front end (angulardart) error and send it back to the server.
I saw there is something like his in regular Angular ErrorHandler, but I can't find any equivalent in angular dart (or dart it self).
Maybe I should hack the Exception object's constructor, but I don't find it a good approach (assuming it's possible)
any hints please?
In Dart it's quite similar:
#Injectable()
class ErrorHandler implements ExceptionHandler {
ApplicationRef _appRef;
ErrorHandler(Injector injector) {
// prevent DI circular dependency
new Future<Null>.delayed(Duration.ZERO, () {
_appRef = injector.get(ApplicationRef) as ApplicationRef;
});
}
#override
void call(dynamic exception, [dynamic stackTrace, String reason]) {
final stackTraceParam = stackTrace is StackTrace
? stackTrace
: (stackTrace is String
? new StackTrace.fromString(stackTrace)
: (stackTrace is List
? new StackTrace.fromString(stackTrace.join('\n'))
: null));
_log.shout(reason ?? exception, exception, stackTraceParam);
// We can try to get an error shown, but don't assume the app is
// in a healthy state after this error handler was reached.
// You can for example still instruct the user to reload the
// page with danger to cause hare because of inconsistent
// application state..
// To get changes shown, we need to explicitly invoke change detection.
_appRef?.tick();
}
}
Provide the error handler
return bootstrap(AppComponent, [const Provide(ExceptionHandler, useClass: ErrorHandler)]);
For errors that might be caused outside Angular, see also How to catch all uncaught errors in a dart polymer app?

Groovy give NPE on list.find call but only after a period of time

We have a chunk of code something like this
// semi-pseudo code
def result = someList.find { condition == true }
(someList may be null, but that is ok in groovy as null.find{…} works fine.)
This line of code is running in an action of a grails controller and deployed in production to a server. After a period of time (sometimes hours, sometimes longer) the above line of code will start throwing a NullPointerException — and once it starts throwing the NPE it always throws the NPE.
Through debugging we've proven that it works fine even when someList is null (up until we get the seemingly random first NPE)… also through debugging we were able to get a more detail stacktrace that indicated there error was in Groovy's MetaClassRegistryImpl.java line 214.
I've googled every combination I can think of to see if there are any known Groovy bugs but found nothing of value.
(It is using Grails 1.3.7, thus Groovy 1.7.8)
A JMeter script was setup to run through a series of site interactions that makes this problem semi-repeatable. The script will iterate through 50-100 series and then the error starts appearing - once the error appears it is always in error until the application is redeployed to the server (Glassfish).
Tracing through the groovy code it looks something like this:
//AbstractCallSite.java
public Object call(Object receiver, Object arg1) throws Throwable {
return call(receiver, ArrayUtil.createArray(arg1));
}
//PerInstancePojoMetaClassSite.java
public Object call(Object receiver, Object[] args) throws Throwable {
if (info.hasPerInstanceMetaClasses()) {
try {
return InvokerHelper.getMetaClass(receiver).invokeMethod(receiver, name, args);
} catch (GroovyRuntimeException gre) {
throw ScriptBytecodeAdapter.unwrap(gre);
}
} else {
return CallSiteArray.defaultCall(this, receiver, args);
}
}
//InvokerHelper.java
public static MetaClass getMetaClass(Object object) {
if (object instanceof GroovyObject)
return ((GroovyObject) object).getMetaClass();
else
return ((MetaClassRegistryImpl) GroovySystem.getMetaClassRegistry()).getMetaClass(object);
}
//MetaClassRegistryImpl.java
public MetaClass getMetaClass(Object obj) {
return ClassInfo.getClassInfo(obj.getClass()).getMetaClass(obj);
}
So it appears the NPE is on the obj.getClass() — if that's the case I'm a little baffled how it ever works when someList is null (but that is a separate topic).
FWIW, we are not doing any class or instance level meta-class coding of our own on someList.
Is there a bug in Groovy or what could we possibly be doing wrong to cause a (random) NPE deep in Groovy code?
UPDATE—
The observation is that someList is being set to a 'java null' instead of a 'groovy null' (NullObject). The object is coming from a map (flow context) via a flow in a controller action...
class SomeController {
def someActionFlow = {
action {
def someList = flow.someList
}
}
}
The case in question is when flow.someList has never been set it should always be null (groovy null). flow is just a map so it is the same as doing flow.get('someList')
The above code works fine for an unknown number of iterations and then starts returning 'java nulls' instead of 'groovy nulls'.
I'm going to hazard a guess that it's dependent on how someList is created. That is, if it's created in Groovy as
def someList = null
Then Groovy assigns the NullObject to the variable. However, if the value is returned from some other Java component as a real Java null, then it will throw the NPE. Going further, there might be some optimization in Groovy/Java/JVM where callsite caching is causing it to always return NPE.
Then again, this is just a wild guess.
Fixed: Similarly to GROOVY-5248 (call site caching missing null check), add a receiver null check to avoid NPEs under certain circumstances
commit 641c6a8d4b6b3046f4d8a1a2ac5f08f1f2769f0f

Resources