How to handle InterruptException on Future#get()? - spring

public void produceMessage(String dataPushNotif) {
PushNotif msg = PushNotif.newBuilder()
.setDatapushnotif(dataPushNotif)
.build();
ListenableFuture<SendResult<String, PushNotif>> future =
kafkaTemplate.send(destTopic, msg);
try {
var result = future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
log.debug(buildSuccesLogMessage(result));
}
catch (InterruptedException | ExecutionException | TimeoutException e) {
log.debug("FAILED: {}", e);
}
}
With the code above I'm getting a sonarlint warning of Either re-interrupt this method or rethrow the "InterruptedException" that can be caught here. (java:S2142)
I could handle success and failure to send gracefully with addCallback(), but I don't see any other way to set a timeout on the thread execution.
Is there any way to handle the sonarlint warning? Or handle the future gracefully with a timeout option?

Don't use multi-catch and call Thread.currentThread().interrupt() in the InterruptedException catch block so that the next interruptible operation will get the exception.
It is bad practice to "swallow" interrupts.

Related

When using KafkaListener, how can I check that a topic message has been read to the end?

When using #KafkaListener, how can I check that a topic message has been read to the end?
See this answer about getting an event notification when there are no more records to read.
You can use the Consumer in the event to get the current position(), and endOffsets(); the following shows how to get the end offsets:
#EventListener
void listen(ListenerContainerIdleEvent event) {
System.out.println(event);
try {
System.out.println(event.getConsumer().assignment());
System.out.println(event.getConsumer().endOffsets(event.getConsumer().assignment(), Duration.ofSeconds(5)));
}
catch (Exception e) {
e.printStackTrace();
}
}

Kotlin Coroutines remove exception handler from scope

In code below I am fetching some data. If error/exception was thrown I want the exception handler to catch it. Once done with fetching, I am posting the result using LiveData to whoever is observing.
What I am trying to achieve is that the exception handler to finish its job once I post the result. Which means, if the observer handling the result also throws an exception, I don't want the coroutine exception handler to catch it (Which is the case in code below).
fun loadPrerequisites(resultObserver: MutableLiveData<PrerequisiteDataHolder?>) {
val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
resultObserver.postValue(null)
}
scope.launch(Dispatchers.IO + exceptionHandler) {
val deferredCreationScheme = async {
fetchCreationScheme()
}
val creationScheme = deferredCreationScheme.await()
//TODO remove exception handler at this stage?
resultObserver.postValue(PrerequisiteDataHolder(creationScheme))
}
}
Is there a way to remove the exception handler before posting the result to the LiveData? Or must I introduce a new scope?
You seem to have misunderstood the purpose of the coroutine exception handler. It is the coroutine equivalent of uncaughtExceptionExceptionHandler in Java and its purpose is to inform you of an exception that has already broken its coroutine. You seem to want to use it to implement business logic-level exception handling.
The coroutine exception handler is not a replacement for the try-catch block, and the latter is what you should use in your case.
I think you don't need async in your code in the first place, I believe this is all you really need:
scope.launch(Dispatchers.IO) {
resultObserver.postValue(
try {
PrerequisiteDataHolder(fetchCreationScheme())
} catch (e: Exception) {
null
}
)
}
I typically use a helper function for code like this:
inline fun <T> tryOrNull(block: () -> T) = try {
block()
} catch (t: Throwable) {
null
}
Then your code becomes
scope.launch(Dispatchers.IO) {
tryOrNull { PrerequisiteDataHolder(fetchCreationScheme()) }
.also { resultObserver.postValue(it) }
}

Spring Integration and returning schema validation errors

We are using Spring Integration to process a JSON payload passed into a RESTful endpoint. As part of this flow we are using a filter to validate the JSON:
.filter(schemaValidationFilter, s -> s
.discardFlow(f -> f
.handle(message -> {
throw new SchemaValidationException(message);
}))
)
This works great. However, if the validation fails we want to capture the parsing error and return that to the user so they can act on the error. Here is the overridden accept method in the SchemaValidationFilter class:
#Override
public boolean accept(Message<?> message) {
Assert.notNull(message);
Assert.isTrue(message.getHeaders().containsKey(TYPE_NAME));
String historyType = (String)message.getHeaders().get(TYPE_NAME);
JSONObject payload = (JSONObject) message.getPayload();
String jsonString = payload.toJSONString();
try {
ProcessingReport report = schemaValidator.validate(historyType, payload);
return report.isSuccess();
} catch (IOException | ProcessingException e) {
throw new MessagingException(message, e);
}
}
What we have done is in the catch block we throw a MessageException which seems to solve the problem. However this seems to break what a filter should do (simply return a true or false).
Is there a best practice for passing the error details from the filter to the client? Is the filter the right solution for this use case?
Thanks for your help!
John
I'd say you go correct way. Please, refer to the XmlValidatingMessageSelector, so your JsonValidatingMessageSelector should be similar and must follow the same design.
Since we have a throwExceptionOnRejection option we always can be sure that throwing Exception instead of just true/false is correct behavior.
What Gary says is good, too, but according to the existing logic in that MessageSelector impl we can go ahead with the same and continue to use .filter(), but, of course, already without .discardFlow(), because we won't send invalid message to the discardChannel.
When your JsonValidatingMessageSelector is ready, feel free to contribute it back to the Framework!
It's probably more correct to do the validation in a <service-activator/>...
public Message<?> validate(Message<?> message) {
...
try {
ProcessingReport report = schemaValidator.validate(historyType, payload);
return message;
}
catch (IOException | ProcessingException e) {
throw new MessagingException(message, e);
}
}
...since you're never really filtering.

Unable to throw httpResponseException

When I try to throw the below forbidden ResponseException from my controller. An exception stating "Processing of the HTTP request resulted in an exception. Please see the HTTP response returned by the 'Response' property of this exception for details." is catched in the catch block of the controller method. Need help in resolving this
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Forbidden));
Just change your controller implementation to re-throw if it's an HttpResponseException:
try
{
// action implementation
}
catch (Exception e)
{
if (e is HttpResponseException)
{
throw e;
}
// error handling logic
}
But the better answer is that #1 - you should avoid be catching all exceptions, that's bad practice. And #2 - you should use an exception filter instead to do your error handling and not catch exceptions yourself.

How to hit the breakpoint at catch block when working with TPL

As I started understanding thru the TPL. I got stuck over in this code. I have 2 task. Task1 thows ArgumentOutOfRangeException and Task2 throws NullReferenceException.
Consider this below code:
static void Main(string[] args) {
// create the cancellation token source and the token
CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
// create a task that waits on the cancellation token
Task task1 = new Task(() => {
// wait forever or until the token is cancelled
token.WaitHandle.WaitOne(-1);
// throw an exception to acknowledge the cancellation
throw new OperationCanceledException(token);
}, token);
// create a task that throws an exceptiono
Task task2 = new Task(() => {
throw new NullReferenceException();
});
// start the tasks
task1.Start(); task2.Start();
// cancel the token
tokenSource.Cancel();
// wait on the tasks and catch any exceptions
try {
Task.WaitAll(task1, task2);
} catch (AggregateException ex) {
// iterate through the inner exceptions using
// the handle method
ex.Handle((inner) => {
if (inner is OperationCanceledException) {
// ...handle task cancellation...
return true;
} else {
// this is an exception we don't know how
// to handle, so return false
return false;
}
});
}
// wait for input before exiting
Console.WriteLine("Main method complete. Press enter to finish.");
Console.ReadLine();
}
I have put the try catch block for Task.WaitAll(task1, task2). It should ideally hit the breakpoint in ex.handler statement inside Catch block. As I understand that whatever may be the result it should hit the catch block.
Same case is happening if I have task1.Result/task2.Result.
My Question is: In debug mode why isn't the breakpoint being hit at the catch block when I am intentionally throwing it from task as I want to examine the statements under catch block. It just puts yellow mark at saying "NullReferenceException unhandled by the user code".
Task task2 = new Task(() => {
throw new NullReferenceException();
});
How do I hit the break point at catch block???
Thanks for replying :)
As Arne Claassen explained in their comment, the debugger pauses execution at the point the original exception is thrown because the thread does not handle the exception. If you continue exceution (F5 or play button), the program should continue to the point where you are handling the exception in your continuation.

Resources