Reactor StepVerifier test fails with blockFirst() - project-reactor

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.

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("--------------------");
}
}

Avoid exception causes to stop Mono.zip immediately

Is it possible to avoid that if one mono in mono.zip throws exception all other monos are stopping immediately? I want them to end normally and perhaps to handle the erroneous one by something like „.doOnError“ or „.continueOnError. Is that a way to go?
Regards
Bernado
Yes, it's possible. You can use Mono.zipDelayError. As you can understand from the method's name, it delays errors from the Monos. If several Monos error, their exceptions are combined.
If you have to get the combined result anyway, zipDelayError is not the solution. Use the zip operator and handle the error case with a fallback operator like onErrorResume or retry on the zipped Mono or any upstream one.
I stated that my question is answered but it is not yet. The following example states my case: some mono will fail, but i want the result as the error too. i expected the follwoing code as to run to completion but it fails:
Mono<String> error = Mono.error(new RuntimeException());
error = error.onErrorResume(throwable -> Mono.just("hell0"));
Mono<String> test = Mono.just("test");
Mono<String> test1 = Mono.just("test1");
Mono<String> test2 = Mono.just("test2");
List<Mono<String>> monolist = new ArrayList<>();
monolist.add(test);
monolist.add(test1);
monolist.add(test2);
monolist.add(error);
Mono<Long> zipDelayError = Mono.zipDelayError(monolist, arrayObj -> Arrays.stream(arrayObj).count());
System.out.println(zipDelayError.block());

Why does Mono.doOnSuccess() suppress errors?

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(...).

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

Grails Services / Transactions / RuntimeException / Testing

I'm testing come code in a service with transactional set to true , which talks
to a customer supplied web service the main part of which looks like
class BarcodeService {
..
/// some stuff ...
try{
cancelBarCodeResponse = cancelBarCode(cancelBarcodeRequest)
} catch(myCommsException e) {
throw new RuntimeException(e)
}
...
where myCommsException extends Exception ..
I have a test which looks like
// As no connection from my machine, it should fail ..
shouldFailWithCause(RuntimeException){
barcodeServices.cancelBarcodeDetails()
}
The test fails cause it's catching a myCommsException rather than the
RuntimeException i thought i'd converted it to .. Anyone care to point out what
i'm doing wrong ? Also will the fact that it's not a RuntimeException mean any
transaction related info done before my try/catch actually be written out rather
than thrown away ??
Thanks
From what I see, it looks ok. The problem might be in the ///some stuff and the ... parts of the code. Use a debugger to find out exactly where the exception is being thrown.

Resources