I would like to know if there's any equivalent to AsyncRestTemplate.exchange in Spring 3.2. Most of my application is written on Spring 3.2 and I want to make asynchronous calls to a web service. In Spring 4, we can use the AsyncRestTemplate to achieve this. What would be the way to do this in Spring 3.2?
Any help on this would be great!
As #M. Deinum mentioned, writing own async code with Spring is easy. If you do something like this:
#Async("customTaskExecutor")
public Future<String> asyncRestTemplateCall(){
return new AsyncResult<String>(restTemplate.exchange(...));
}
Configuration for thread pool can look like this:
#Configuration
#EnableAsync
public class AsyncConfiguration {
#Bean
public Executor customTaskExecutor() {
return Executors.newFixedThreadPool(10);
}
}
You have wrapped RestTemplate in async call and AsyncResult implements Java Feature.
EDIT:
Max mentioned in comments that this is not using event loop with non-blocking I/O as AsyncRestTemplate, but it delegates blocking call into separate thread.
Related
I'm new in software. I'm working to understand async programming in Spring Boot. As seen above, I set thread pool size 2. When I requested same url three times one after another. My two requests are working asynchronously. Third one is waiting. This is ok. But when I don't use the asynchronous feature (neither #async annotation nor threadpool), it still performs transactions asynchronously, as before. So I'm confused. Spring Boot rest controller behaves asynchronously by default? Why we use #async in Spring Boot? Or do I misunderstand that?
#Service
public class TenantService {
#Autowired
private TenantRepository tenantRepository;
#Async("threadPoolTaskExecutor")
public Future<List<Tenant>> getAllTenants() {
System.out.println("Execute method asynchronously - "
+ Thread.currentThread().getName());
try {
List<Tenant> allTenants = tenantRepository.findAll();
Thread.sleep(5000);
return new AsyncResult<>(allTenants);
} catch (InterruptedException e) {
//
}
return null;
}
}
#Configuration
#EnableAsync
public class AsyncConfig {
#Bean(name = "threadPoolTaskExecutor")
public Executor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("AsynchThread-");
executor.initialize();
return executor;
}
#Bean(name = "threadPoolTaskExecutor2")
public Executor threadPoolTaskExecutor2() {
return new ThreadPoolTaskExecutor();
}
}
I'm assuming you are using the default embedded Tomcat from Spring Boot. If that's the case, then you are not misunderstanding. Tomcat will indeed work asynchronously by default, meaning it will start a new thread for every request (see this for on that).
The #Async annotation does not aim to replace the functionality that Tomcat provides in this case. Instead, that annotation allows executing any method of a bean in a separate thread. For your particular use case, it might be enough to let Tomcat start a new thread for every request, but sometimes you might want to parallelize work further.
An example on when you would probably want to use both is when a request must trigger some heavy computation, but the response does not depend on it. By using the #Async annotation, you can start the heavy computation on another thread, and let the request finish sooner (effectively allowing the server to handle other requests while the heavy computation runs independently on another thread).
I am using Spring Boot 1.5.x, and in details, I am using the #Async annotation. My problem is that I have the following method in a repository.
#Repository
class Repository {
#Async
CompletableFuture<String> findSomething() {
/* Some code that returns something */
}
}
And then, I have the following method in a service, which calls the above repository.
#Service
class Service {
private Repository repository;
// ...
#Async
CompletableFuture<String> findSomething() {
return repository.findSomething()
}
}
My question is: should I place the #Async annotation also in the service.findSomething() method? Or should I place the annotation only in the service method?
I mean, Spring should schedule the execution of a method marked with #Async annotation in a dedicated thread. Is it correct?
Thanks in advance.
Annotating a method with #Async will cause the caller to return immediately and the actual execution will occur in a separate thread as part of a task submitted to the default SimpleAsyncTaskExecutor (if you haven't configured another one). Please see the relevant spring documentation.
That being said, for your goal there's no added benefit in nesting the #Async. If your goal is to make Repository.findSomething asynchronous and to be able to call it from different places, not only Service.findSomething, you should annotate only this method.
Also, Service.findSomething is asynchronous itself, even if not annotated with #Async, in the scenario you depicted. The method is not blocking by calling CompletableFuture.get() and it will return immediately, although it will not be executed in a separate thread.
I'd like to create an executor service that I can use as follows:
#Asyn(value = "asyncService")
public void task() {
//...
}
When should the #Bean be created using ThreadPoolTaskExecutor or ThreadPoolExecutorFactoryBean?
#Bean
public ExecutorService getAsyncService() {
//when to favor ThreadPoolTaskExecutor over ThreadPoolExecutorFactoryBean
}
Are there any cases where one should be favored over the other?
Favor direct injection of the TaskExecutor unless running under an app server, mainframe, or other environment where you need special handling of threads. Like the docs say, it's easy to get confused on which class you're using otherwise.
My application uses the Spring Framework 4 included spring-messaging module (with key abstractions from the Spring Integration project such as Message, MessageChannel,MessageHandler and others that can serve as a foundation for such a messaging architecture.)
My application uses Websocket & STOMP. It maintains connections(websocket sessions) with a high volume of java websocket clients & one of the requirements was to use either akka or reactor.
I want to integrate spring-reactor RingBufferAsyncTaskExecutor in place of ThreadPoolTaskExecutor in clientInboundChannelExecutor & clientOutboundChannelExecutor
to get better Throughput. At least I've identified this approach as the way to integrate spring-reactor into my existing application - this may not be the right approach.
I was looking at reactor-si-quickstart, since it demonstrates how to use reactor with spring integration & since spring-messaging in Spring Framework 4 includes key abstractions from the Spring Integration project. I thought it would be the closest reference.
My working java config for web socket has the following class declaration
public class WebSocketConfig extends WebSocketMessageBrokerConfigurationSupport implements WebSocketMessageBrokerConfigurer.
WebSocketMessageBrokerConfigurationSupport extends AbstractMessageBrokerConfiguration.
In org.springframework.messaging.simp.config.AbstractMessageBrokerConfiguration I wanted to try configure RingBufferAsyncTaskExecutor in place of ThreadPoolTaskExecutor
#Bean
public ThreadPoolTaskExecutor clientInboundChannelExecutor() {
TaskExecutorRegistration reg = getClientInboundChannelRegistration().getOrCreateTaskExecRegistration();
ThreadPoolTaskExecutor executor = reg.getTaskExecutor();
executor.setThreadNamePrefix("clientInboundChannel-");
return executor;
}
When I try override this method in WebSocketConfig "The method getOrCreateTaskExecRegistration() from the type ChannelRegistration is not visible" because
in AbstractMessageBrokerConfiguration it's protected ....
protected final ChannelRegistration getClientInboundChannelRegistration() {
if (this.clientInboundChannelRegistration == null) {
ChannelRegistration registration = new ChannelRegistration();
configureClientInboundChannel(registration);
this.clientInboundChannelRegistration = registration;
}
return this.clientInboundChannelRegistration;
}
I don't fully understand the WebSocketMessageBrokerConfigurationSupport hierarchy or the WebSocketMessageBrokerConfigurer interface in my WebSocketConfig. I just played around with overriding what I needed to for my customizations to work.
Not sure if it's relevant, but I don't need an external broker because my application doesn't send any data to all connected subscribers, at the moment and is unlikely to down the line. Communication with daemon type java websocket clients is point-to-point, but the web ui websocket in the browser does use subscribe to get real-time data so it's a convenient setup (rather then spring integration direct channel) and there where clear sources on how to set it up - still I'm not sure it is most efficient application design.
STOMP Over WebSocket Messaging Architecture as described in the spring-framework reference documentation was the most comprehensive approach since this is my first spring project.
Is it possible to get the performance boosts from integrating spring-reactor into my existing application?
Or should I try to use spring integration instead, this would require a lot of modification, as far as I can tell - also it seems illogical that it would be necessary given that Spring Framework 4 included spring-messaging module was from spring integration.
How can should I integrate spring-reactor into my standard spring framework 4 STOMP Over WebSocket Messaging Architecture?
If configuring RingBufferAsyncTaskExecutor in place of ThreadPoolTaskExecutor in clientInboundChannelExecutor & clientOutboundChannelExecutor is the correct way, how should I go about doing this?
Actually the RingBufferAsyncTaskExecutor isn't ThreadPoolTaskExecutor, so you can't use it that way.
You can simply override clientInbound(Outbound)Channel beans from your AbstractWebSocketMessageBrokerConfigurer impl and just use #EnableWebSocketMessageBroker:
#Configuration
#EnableWebSocketMessageBroker
#EnableReactor
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#autowired
Environment reactorEnv;
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry configurer) {
configurer.setApplicationDestinationPrefixes("/app");
configurer.enableSimpleBroker("/topic", "/queue");
}
#Bean
public AbstractSubscribableChannel clientInboundChannel() {
ExecutorSubscribableChannel channel = new ExecutorSubscribableChannel(new RingBufferAsyncTaskExecutor(this.reactorEnv));
ChannelRegistration reg = getClientOutboundChannelRegistration();
channel.setInterceptors(reg.getInterceptors());
return channel;
}
}
And pay attention, please, to the WebSocket support in the Spring Integration.
By the way: point me out, please, to the link for that reactor-si-quickstart.
I want to have a work queue that behaves almost exactly like ruby's sidekiq(it doesn't need to use Redis, but it can - I just can't use ruby - not even Jruby). Basically I want to be able to create jobs that runs with some parameters and a worker pool executes the jobs. The workers are going to use hibernate to do some work, so I think that Spring integration could make things easier.
Spring Integration has Redis Queue inbound and outbound channel adapters.
The inbound message-driven adapter doesn't currently support concurrency; we worked around that in Spring XD with a composite adapter that wraps a collection of RedisQueueMessageDrivenEndpoint.
Or you could use RabbitMQ; the Spring Integration adapter for it does support concurrency.
EDIT
The bus was extracted to a sub project within that repo.
Spring Framework has ThreadPoolTaskExecutor. You could use it in your class as follows.
#Autowired
ThreadPoolTaskExecutor executor;
ThreadPoolTaskExecutor has properties needed to be set before it is put to use. PostConstruct will be executed after the dependency injections, so we can set the properities of ThreadPoolExecutor there.
#PostConstruct
public void init() {
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
}
Then you can start using executor as follow
executor.execute(new EmailtoCustomerTask("zhw#gmail.com"));
The only requirement needed to become a task is to implement the Runnable interface.
private class EmailtoCustomerTask implements Runnable