IllegalStateException: The current thread cannot be blocked: vert.x-eventloop-thread-1 - java

I am trying to use quarkus reactive api to fetch data from another hibernate reactive project.
I am getting this error whenever i try to get data from my hibernate project. I've figured that the error occurs in methods where i've called another method as well.the error i am getting
code for quarkus api
#GET
#Path("/getEquipCls")
public Uni<List<Tuple>> getMethod() {
return reactiveMethod();
}
code for service class of hibernate reactive method
#Override
public Uni<List<Tuple>> reactiveMethod(params) {
Long variable = methodForVariable.await().indefinitely();
return reactiveMethod(variable);
}
I've tried #Blocking & #NonBlocking annotations but none of them worked.
Any help would be greatly appreciated.

It seems there is a bit of misunderstanding, Reactive is not the same as Mutiny.
Returning Type Uni<> or Multi<> from your method is Mutiny. Which could be Reactive, but it's not always the case depending on what dependencies you added.
That said, I've seen that you call await().indefinitely(); which wait for result and then give the correct non Uni type.
Disclaimer: I'm not a Mutiny expert so i'll try to help as much as i can.
Maybe you should try with this :
return methodForVariable.onItem()
.transform(variable -> reactiveMethod(variable))
instead of this :
Long variable = methodForVariable.await().indefinitely();
return reactiveMethod(variable);
I think your blocking problem comes from here, where you try to block thread to wait for async processing, and then call an async method with previously fetched value.
The way i suggested always keep processing async, so it should do the trick.
For more, be sure to check Mutiny's documentation

Related

Java Micrometer #Counted - exception="none" and result="success" for #ExceptionHandler?

Quick question regarding Java Micrometer with #Counted and #ExceptionHandler please.
I have a very straightforward #ExceptionHandler:
#ExceptionHandler
#Counted(value = "MY_EXCEPTION", description = "SOME_DESCRIPTION")
public Mono<ResponseEntity<String>> myCoolExceptionHandler(final RuntimeException runtimeException) {
System.err.println("an exception!" + runtimeException);
return Mono.just("bad");
}
I think this combination is quite interesting, as it gives visibility on exception happening. We can build dashboard, alerts, etc, quite cool.
Unfortunately, when I looked at the metric generated, it was something like:
# HELP MY_EXCEPTION_total SOME_DESCRIPTION
# TYPE MY_EXCEPTION_total counter
MY_EXCEPTION_total{class="package.MyController",exception="none",method="myCoolExceptionHandler",result="success",} 3.0
I am quite puzzled on exception="none" and result="success"
May I ask how those values got into the metric in the first place?
Also, how to change them into something more meaningful, such as the exception class for instance?
Thank you!
The annotated method itself does not throw an exception and always completes normally. Therefore, the intercepting code installed by the annotation will never record an exception (exception=none) and the outcome will always be good (result=success). Only exceptions thrown from within the annotated method will be recorded as an error outcome.
You can always manually record metrics by injecting the MetricRegistry and then registering a metric with the appropriate name and tags.

Spring WebFlux + ReactiveMongoDB, Can't save entity

I expect that after the execution of the program, Rubber will be saved in the mongo. The result is 200 O.K, but nothing was saved to the database, I suspect that the problem is in the doOnSuccess method. How to use it? Or what else could be the problem?
#PostMapping
public Mono<Rubber> create(#RequestBody Rubber rubber) {
return rubberService.create(rubber);
}
#Override
public Mono<Rubber> create(Rubber rubber) {
return Mono.just(rubber)
.map(rubberToRubberEntityConverter::convert)
.doOnSuccess(rubberRepository::save)
.doOnError((throwable) -> Mono.error(new ApplicationException("Can't create ruber :( ", throwable)))
.map(rubberEntityToRubberConverter::convert);
}
#Repository
public interface RubberRepository extends ReactiveMongoRepository<RubberEntity, String> {
}
Your reactive chain isn't set up correctly:
return Mono.just(rubber)
.map(rubberToRubberEntityConverter::convert)
.doOnSuccess(rubberRepository::save)
You're not actually doing anything reactive here - you're taking a value, wrapping it in a Mono, converting it (synchronously), then performing a side-effect (also synchronously.) In this case, your side-effect is simply setting up the reactive chain to save to the repository (which will return a Mono), but since that Mono is never subscribed to, the save never actually occurs.
Your doOnError() call has a similar issue - you're again returning a Mono rather than performing a side-effect. Instead, you almost certainly want to use onErrorMap() to convert between one error and another.
In short, any time you use doOnSuccess(), doOnError() etc. and use a method that returns a publisher of some description, it's almost always going to be the wrong thing to do. Using Mono.just() is also a hint that you're not starting with a reactive chain - not necessarily wrong in and of itself, but it can be a warning sign that you're not actually creating a "real" reactive chain.
Instead, you probably want something like:
return rubberRepository.save(rubberToRubberEntityConverter.convert(rubber))
.onErrorMap((throwable) -> new ApplicationException("Can't create rubber :( ", throwable))
.map(rubberEntityToRubberConverter::convert);

Creating a generic error object to indicate partial success of data retrieval in Spring Boot

My question should be quite simple.
I have a Spring Boot REST API.
#GetMapping("/customer")
public Customer getCustomer() {
return service.getCustomer()
}
My controller returns List<Customer> and works well. But now I want to return another object with the errors that can happen when gathering the customers. Let's say it's called GenericErrorClass
So to return this I need to create a class that groups List and GenericErrorClass and return that class, right?
that will work but now I have Account, Product, etc... I don't think it makes sence create a class for each one of them.
How can I build a custom object without creating classes and return that as json from the rest controller?
Don't do that.
Throw your exception, or let it escape from your call stack. Use #ControllerAdvice (or #RestControllerAdvice) with #ExceptionHandler instead.
You can extend the abstract class ResponseEntityExceptionHandler, and provide additional handling methods. On the long run that will matter for a clean application design.
If you intend to return the error with a status code of 200, I'd like to understand why. I witness developers serving out responses for errored requests with 200 just because handling the HTTP error in another code branch at client side seems "difficult".
At first, you should know that there is already a similar class org.springframework.http.ResponseEntity, which object you could return as a response of your API. It can wrap your response body - List, Account, Product, etc. with the possibility to override default Http status.
So, based on this example you can write your own simple wrapper class like this:
public class Response<T>
{
private GenericErrorClass error;
private T body;
// constructors + getters + setters
}
and when your API method should return List<Customer> you will return Response<List<Customer>> , in the same way other objects.
However, I would recommend you to catch exceptions and send detailed error message + corresponding error code to API client. This is much better from a design point of view.
To implement this here is a good read.
If you have time to think about the design of your API, I would recommend this guide.
Generally you would return error information when the request is not succeeded, that coincides with a 4/5xx error code. Usually with Spring you manage this situation with exception handlers, as shown here where you can define a different response body. There is also another good practice: use envelopes to manage all responses, I will show you an example
{
status: 200,
message: 'user retrieved',
result:
[
{foo1:"bar1"},
.....
]
}
OR
{
status: 400,
message: 'bad request',
error:
{
reason : "wrong field xxx in request"
}
}
in this way clients can process the request and provide useful info to users. To do this you have to define a class that is used for all responses and should encapsulate the result or the error

How can I pass a customized value to a spring aop advice?

If I take a service method named public void delete(int id); as the pointcut, I want to add an after-returning advice on it, but I don't know what kind of object was deleted(however, the servlet which called the service knows the type value), so I was wondering if I can pass a customized value to this after-returning advice when it is activated, like 'user'. I've already checked the related document on Spring's website and I still know nothing. I'd appreciate your answer, THX.
One solution but its required refactoring in Service method
1) Refactoring
public class DeleteRequest {
String type;
Long id;
}
public boolean delete(DeleteRequest request){ // impl}
2) Use Around Advice
2.1) Before proceeding method execution, read passed parameter & get to be deleted object for "XYZ" requirement.
2.2) Capture result of delete method execution
IF its TRUE then DO your stuff
Note: I used this approach for deleted entity notification. So how we can get deleted entity information in after-advice, hence keep it entity information in before phase & use it in after-successful execution.

how to catch astyanax failures in asynchronous executions

The project I work on uses astyanax driver to access Cassandra. I want to implement an asynchronous operation:
MutationBatch m;
//…
ListenableFuture<OperationResult<Void>> lf = m.executeAsync();
lf.addListener(myRunnableCallback, myExecutor);
Question: assuming the exception was not thrown right away within executeAsync() call, how do I distinguish between successful and failed executions?
The only way I can think of is that when the completion callback is invoked lf.get() throws an exception in case of failure. If this is the right way, is there a document or lines in astyanax sources confirming that?
I found a workaround: instead of ListenableFuture's addListener method taking Runnable parameter I can use Futures.addCallback(ListenableFuture<V>, FutureCallback<V>, Executor). FutureCallback has 2 methods: onSuccess and onFailure. That solves my problem.
https://code.google.com/p/guava-libraries/wiki/ListenableFutureExplained

Categories