How to force a worker thread to process ServerEndpointConfig.Configurator's 'modifyHandshake' method? - quarkus

I'm modifying the handshake of Websocket by implementing ServerEndpointConfig.Configurator and overriding 'modifyHandshake', but the code is blocking and running on an IO thread,
how can I force it to run on a worker thread?
'quarkus.websocket.dispatch-to-worker=true' is working only for #serverendpoint #onopen.
I tried to annotate the 'modifyHandshake' with #Blocking but still - it's running on an IO thread.
Expected behavior -
modifyHandshake should be invoked on a worker thread.
Actual behavior
modifyHandshake invoked on an IO thread.
How to Reproduce?
public class WebSocketEndpointConfigurator extends ServerEndpointConfig.Configurator {
#Override
public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
// executing blocking code
Thread.sleep(3000)
}
}
WARN [io.vertx.core.impl.BlockedThreadChecker] (vertx-blocked-thread-checker) Thread Thread[vert.x-eventloop-thread-7,5,main] has been blocked for 128597346 ms, time limit is 2000 ms: io.vertx.core.VertxException: Thread blocked
Quarkus 2.4.1.Final

Related

Sprint boot async - does not use max-size

I am trying out Spring Boot's Async feature, but I am having some trouble getting it to work as I need.
This is my application yml
spring:
task:
execution:
pool:
max-size: 100
queue-capacity: 5
keep-alive: "10s"
core-size: 10
Application class
#SpringBootApplication
#EnableAsync
public class ServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceApplication.class, args);
}
}
Service class:
for (int i=0;i< 40; i++) {
CompletableFuture.runAsync(()-> {
try {
System.out.println("------------------Starting thread------------------");
//do some action here
System.out.println("------------------Ending thread------------------");
} catch (Exception e) {
e.printStackTrace();
}
});
}
I am expecting to see the System.out print out 40 times. The operations in between take long enough, and I have tried adding Thread.sleep(), but I do not see the sysouts printed more than 8 times. Is there something wrong with my config, or does it not work the way I expect?
Completable future has no idea about the pool that is used by Spring.
From docs of runAsync() method:
Returns a new CompletableFuture that is asynchronously completed by a
task running in the ForkJoinPool.commonPool() after it runs the given
action. Params: runnable – the action to run before completing the
returned CompletableFuture Returns: the new CompletableFuture
So, those tasks are being run on ForkJoinPool, not on executor used by Spring.
About executor used by Spring with #EnableAsync:
By default, Spring will be searching for an associated thread pool
definition: either a unique TaskExecutor bean in the context, or an
Executor bean named "taskExecutor" otherwise. If neither of the two is
resolvable, a SimpleAsyncTaskExecutor will be used to process async
method invocations. Besides, annotated methods having a void return
type cannot transmit any exception back to the caller. By default,
such uncaught exceptions are only logged.
You could try autowire that executor and pass it as an argument to
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
Returns a new CompletableFuture that is asynchronously completed by a
task running in the given executor after it runs the given action.
Params: runnable – the action to run before completing the returned
CompletableFuture executor – the executor to use for asynchronous
execution

Java client uses one thread for prompting in command line, and another for socket messaging

Java server-client program where server runs a thread for each client and the client interfaces with the user via a guided menu at the command line.
I trying to have the client main thread handle receiving messages from the server and associated processing including sending responses and generate a new thread to prompt the user.
My reasoning for this was the client could receive messages from the server while the menu is prompted and waiting for input. Here's the basics:
class Client {
Client() {
} //constructor
public static void main(String[] args) {
Client c = new Client();
//other things
MenuThread mt = new MenuThread();
mt.start();
//other things
}
class MenuThread extends Thread {
public MenuThread() {
} //constructor
#Override
public void run() {
//menu & other things
}
Also in my Client class main thread, an event happens and my MenuThread needs to reset. So I interrupt it and start a new one:
menuThread.interrupt();
menuThread = new MenuThread();
menuThread.start();
Now, I'm having weird problems at the command line, as if multiple MenuThreads are left running. (1) Does this Thread approach seem logical (unfamiliar with Runnable nuances)? (2) Any idea what would be causing what seems like concurrency problems? The interrupt and start a new thread seems like a viable approach to me to be implement in the Client class main thread to reset the menu that is displayed by MenuThread at the command line.

Spring Kafka Producer blocking http thread till Kafka thread complete

We have built an application using spring boot for enterprise reasons and using the spring Kafka project to publish Kafka messages.
I have been testing producing Kafka events and noticed that spring is blocking the HTTP thread till the Kafka thread is complete.
try {
ListenableFuture<SendResult<String, OnboardingSigningNotificationEvent>> send = this.kafkaTemplate.send(TOPIC, notificationEvent);
send.addCallback(new ListenableFutureCallback<SendResult<String, OnboardingSigningNotificationEvent>>() {
#Override
public void onSuccess(SendResult<String, OnboardingSigningNotificationEvent> sendResult) {
log.info("Successfully published onboarding signing notification event with record metadata timestamp: {}", sendResult.getRecordMetadata().timestamp());
}
#Override
public void onFailure(Throwable throwable) {
log.error("Failure while publishing kafka event : {}", throwable.getMessage());
}
});
} finally {
kafkaTemplate.flush();
}
This contradicts what is said in this documentation.
https://docs.spring.io/spring-kafka/docs/current/reference/html/#sending-messages
Notice that the send methods return a ListenableFuture.
You can register a callback with the listener to receive the result of
the send asynchronously.
Based on the documentation I would expect the producer call to be made asynchronously and the main http thread to not block waiting for it, but that's not what I see in my tests. Even if I block the kafka thread for a few seconds the caller http thread is being blocked.
Can you please explain whether it is on purpose and are there any config to override this behavior.

Run task in background using deferredResult in Spring without frozen browser as client

I have implemented a simple Rest service by which I'd like to test deferredResult from Spring. While am I getting texts in that order:
TEST
TEST 1
TEST AFTER DEFERRED RESULT
I am very interested why in a browser (client) I need to wait that 8 seconds. Isn't that deferedResult shouldn't be non-blocking and run a task in the background? If no, how to create a rest service which will be non-blocking and run tasks in the background without using Java 9 and reactive streams?
#RestController("/")
public class Controller {
#GetMapping
public DeferredResult<Person> test() {
System.out.println("TEST");
DeferredResult<Person> result = new DeferredResult<>();
CompletableFuture.supplyAsync(this::test1)
.whenCompleteAsync((res, throwable) -> {
System.out.println("TEST AFTER DEFERRED RESULT");
result.setResult(res);
});
System.out.println("TEST 1");
return result;
}
private Person test1() {
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new Person("michal", 20);
}
}
class Person implements Serializable {
private String name;
private int age;
}
DeferredResult is a holder for a WebRequest to allow the serving thread to release and serve another incoming HTTP request instead of waiting for the current one's result. After setResult or setError methods will be invoked - Spring will release that stored WebRequest and your client will receive the response.
DeferredResult holder is a Spring Framework abstraction for Non-blocking IO threading.
Deferred result abstraction has nothing with background tasks. Calling it without threading abstractions will cause the expected same thread execution. Your test1 method is running in the background because of CompletableFuture.supplyAsync method invocation that gives the execution to common pool.
The result is returned in 8 seconds because the whenCompleteAsync passed callback will be called only after test1 method will return.
You cannot receive the result immediately when your "service call logic" takes 8 seconds despite you are performing it in the background. If you want to release the HTTP request - just return an available proper object (it could contain a UUID, for example, to fetch the created person later) or nothing from the controller method. You can try to GET your created user after N seconds. There are specific HTTP response codes (202 ACCEPTED), that means the serverside is processing the request. Finally just GET your created object.
The second approach (if you should notify your clientside - but I will not recommend you to do it if this is the only reason) - you can use WebSockets to notify the clientside and message with it.

spring MVC Callable execution continues even after request timeout?

I have an Asynchronous handlermethod like this
#RequestMapping("/custom-timeout-handling")
public #ResponseBody WebAsyncTask<String> callableWithCustomTimeoutHandling() {
Callable<String> callable = new Callable<String>() {
public String call() throws Exception {
while(i==0){
System.out.println("inside while loop->");
}
return "Callable result";
}
};
return new WebAsyncTask<String>(10000, callable);
}
which will execute the while loop until the specified timeout(10sec).
When the request is timeout,it executes the handleTimeout method from TimeoutCallableProcessingInterceptor
public class TimeoutCallableProcessingInterceptor extends CallableProcessingInterceptorAdapter {
#Override
public <T> Object handleTimeout(NativeWebRequest request, Callable<T> task) throws Exception {
throw new IllegalStateException("[" + task.getClass().getName() + "] timed out");
}
}
Source:i have replaced
Thread.sleep(2000)
with
while(i==0){
System.out.println("inside while loop->");
}
My problem is even after timeout(finished executing handle timeout method)response is send from handletimeout method
the while loop is still processing until the value of i is changed to some other value other than zero.
Is the request is still held by the server?then what is the use of request timeout?
Thanks in advance...
When a servlet container thread detects that a async callable has timed-out, it invokes handleTimeout() (in its own context). Thats the reason you see the handleTimeout() getting executed. It is executed by a servlet container thread and not by the thread that runs the Callable.
If you want custom timeout handling, you need to do two things:
Override onTimeout() in your WebAsyncTask. Whatever callable you provide as the callback to onTimeout() will be invoked within a servlet container thread when it detects your callable has timed-out.
Check for timeouts/interruptions in the Callable you have created inside the controller.
If your Callable does not expect and respect interruption ("If the target thread does not poll the interrupted status the interrupt is effectively ignored"), there is no way to interrupt it! Pls refer this answer to know how to expect and respect interruption.

Resources