SpringAsync etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
SpringAsync etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

23 Ağustos 2023 Çarşamba

SpringAsync @Async Anotasyonu - Sonuç Tipi

Giriş
@Async metod void veya Future veya CompletableFuture dönmelidir. CompletableFuture dönen bir örnek burada. AsyncResult dönmeye gerek yok

Örnek - Polling
Bir örnek burada

5 Haziran 2023 Pazartesi

SpringAsync AsyncConfigurer Arayüzü - Custom Thread Pool Yaratır

Giriş
Açıklaması şöyle. 
AsyncConfigurer is an Interface provided by Spring, It provides two methods. One is if you want to override the TaskExecutor(Threadpool), another is an Exception handler where you can inject your exception handler so it can catch the uncaught exceptions. 
getAsyncExecutor metodu
Örnek
Şöyle yaparız.
@Configuration
@EnableAsync
public class ServiceExecutorConfig implements AsyncConfigurer {

  @Override
  public Executor getAsyncExecutor() {
    ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
    taskExecutor.setCorePoolSize(30);
    taskExecutor.setMaxPoolSize(40);
    taskExecutor.setQueueCapacity(10);
    taskExecutor.initialize();
    return taskExecutor;
  }
}
Örnek
Şöyle yaparız
@Slf4j
@Configuration
public class BaseAsyncConfigurer implements AsyncConfigurer {

  //replace default Async Executor with Customize One.
  @Override
  public Executor getAsyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
    executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors()*5);
    executor.setQueueCapacity(Runtime.getRuntime().availableProcessors()*10);
    executor.setThreadNamePrefix("replacedAsync-");
    executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
    executor.initialize();
    return executor;
  }
  ...
}
getAsyncUncaughtExceptionHandler metodu
@Async olarak işaretli metodlardan fırlatılan exception'ları işleyen AsyncUncaughtExceptionHandler  arayüzündne kalıtan nesneyi döndürür.


Örnek
Şöyle yaparız. Burada exception handler direkt AsyncConfigurer içinde
@Slf4j @Configuration public class BaseAsyncConfigurer implements AsyncConfigurer { ... //override the getAsyncUncaughtExceptionHandler() method to return our // custom asynchronous exception handler: //!!! All the exception happened in @async will been handler here. @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return (Throwable ex, Method method, Object... params)-> { try { log.error("\n\n[Exception-Async-Handler] Class-Name: {}-{}\n Type: {}\nException: {}\n\n", method.getDeclaringClass().getName(),method.getName(), ex.getClass().getName(), ex.getMessage()); } catch (Throwable e) { log.error("catch Async Exception: {}", e); } }; } }
Örnek
Şöyle yaparız. Burada exception handler farklı bir sınıf
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import java.lang.reflect.Method; public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler { @Override public void handleUncaughtException(Throwable throwable, Method method, Object... obj) { System.out.println("Message from exception - " + throwable.getMessage()); System.out.println("Method name " + method.getName()); } }
Kullanmak için şöyle yaparız
@Configuration public class AsyncConfig implements AsyncConfigurer { @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return new AsyncExceptionHandler(); } }


10 Ağustos 2020 Pazartesi

SpringAsync application.properties Ayarları

Giriş
Ayarlar spring.task.execution ve spring.task.scheduling başlıkları altında

Örnek
Şöyle yaparız
# Core number of threads. Default is 8
spring.task.execution.pool.core-size=10

# Maximum allowed number of threads. Default is 1
spring.task.scheduling.pool.size=5
Örnek
Şöyle yaparız
spring.task.execution.pool.max-size=16
spring.task.execution.pool.queue-capacity=100
spring.task.execution.pool.keep-alive=10s
Açıklaması şöyle
This changes the thread pool to use a bounded queue so that when the queue is full (100 tasks), the thread pool increases to maximum 16 threads. Shrinking of the pool is more aggressive as threads are reclaimed when they are idle for 10 seconds (rather than 60 seconds by default).
Örnek
Şöyle yaparız
#Number of core threads
spring.task.execution.pool.core-size=10
#Maximum number of threads
spring.task.execution.pool.max-size=20
#Thread name prefix
spring.task.execution.thread-name-prefix=test
#There are other configurations that readers can configure themselves

12 Aralık 2019 Perşembe

SpringAsync @Async Anotasyonu

Giriş
Genelde servis sınıflarında kullanılır. Metod bir başka thread içinde çalıştırılır. Bu anotasyonu kullanabilmek için @EnableAsync anotasyonunun tanımlı olması gerekir. Açıklaması şöyle.
All that @Async does is execute the methods of the object on another thread, where it gets the thread from a pool (which can be specified, so some operations can have a dedicated pool).
Kısıtlar
1. @Async anotasyonu sadece bean'in public metodlarına uygulanır. Yani Async sınıfın bean olarak kullanılması gerekir. Açıklaması şöyle.
Suppose you write a class and identify a method which will act as Async and put @Async on top of that method, now if you want to use that class from another class by creating local instance then it will not fire the async, It has to be picked up by Spring @ComponentScan annotation or created inside a class marked as @Configuration.
2. Private metodlar @Async olamaz. Açıklaması şöyle.
Never use @Async on top of a private method as in runtime it will not able to create a proxy, so not working.
Açıklaması şöyle.
Please note that proxy mode allows for the interception of calls through the proxy only; local calls within the same class cannot get intercepted that way.
3. @Async Anotasyonu - Sonuç Tipi yazısına taşıdım

4. Exception handling için AsyncConfigurerSupport sınıfı ile tanımlanan exception handler kullanılır.

5. @Transactional ve @Async aynı metod üzerinde birlikte kullanılamaz.

@Transactional ve @Async Kullanımı
Örnek
Şöyle yaparız
@Slf4j
@Service
public class AsyncService {

  @Autowired
  public DataService dataService;

  @Async
  public void dbOperate(){
    log.info("some logic here first");
    dataService.allStep();
    log.info("some logic later");
  }
}

@Slf4j
@Service
public class DataService {

  @Transactional
  public void allStep(){
    saveObj();
    updateObj();
  }

  public void saveObj(){
    log.info("Some data saved");
  }

  public void updateObj(){
    log.info("Some another data updated");
  }
}
TaskExecutor Arayüzü İle İlişkisi
Açıklaması şöyle. Yani ismi taskExecutor olan bir thread pool aramaya başlar. Eğer yoksa yaratır
When you put an @Async annotation on a method, underlying it creates a proxy of that object where @Async is defined (JDK Proxy/CGlib) based on the proxyTargetClass property. Then Spring tries to find a thread pool associated with the context, to submit this method's logic as a separate path of execution to be exact it searches a unique TaskExecutor bean or a bean named as taskExecutor if not found then use default SimpleAsyncTaskExecutor.
Açıklaması şöyle
When you annotate a method with @Async annotation, it creates a proxy for that object based on “proxyTargetClass” property.

When spring executes this method, by default it will be searching for associated thread pool definition. Either a unique spring framework TaskExecutor bean in the context or Executor bean named “taskExecutor”. If neither of these two is resolvable, default it will use spring framework SimpleAsyncTaskExecutor to process async method execution.
@Async işlem için muhtemelen thread pool kullanacağımız için ThreadPoolTaskExecutor yaratmak gerekir.

value Alanı
Elimizde bir executor olsun
<task:annotation-driven executor="myExecutor"
  exception-handler="exceptionHandler"/>
<task:executor id="myExecutor" pool-size="7-42" queue-capacity="8"/>
Şöyle yaparız
@Async("myExecutor")
public void asynchronousFunction() throws InterruptedException {
  ...
}

30 Mayıs 2019 Perşembe

SpringAsync @EnableAsync Anotasyonu

Giriş
Açıklaması şöyle.
Another fact is that the class annotated with @EnableAsync must be a @Configuration as well.
Örnek
Şöyle yaparız.
@EnableAsync
@Configuration
public class AsyncConfiguration { }
mode Alanı
Şöyle yaparız.
@EnableAsync(mode = AdviceMode.ASPECTJ)
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)

8 Mayıs 2019 Çarşamba

SpringAsync AsyncConfigurerSupport Sınıfı

Giriş
Global olarak kullanılan Executor nesnesini yaratır. Açıklaması şöyle.
this now becomes the default executor to run methods annotated with @Async
Açıklaması şöyle. Yani bu sınıf yerine AsyncConfigurer arayüzünden de kalıtılabilir.
AsyncConfigurer is an Interface provided by Spring, It provides two methods One is if you want to override the TaskExecutor(Threadpool), another is an Exception handler where you can inject your exception handler so it can catch the uncaught exceptions. You can create your own class and implement that one directly. but I will not do that, as an alternative, I will use Spring  AsyncConfigurerSupport class which is annotated by @Configuration and @EnableAsync, and provides a default implementation.
getAsyncExecutor metodu
ThreadPoolTaskExecutor nesnesi döndürür

getAsyncUncaughtExceptionHandler metodu
@Async olarak işaretli metodlardan fırlatılan exception'ları işleyen AsyncUncaughtExceptionHandler  arayüzündne kalıtan nesneyi döndürür.

Örnek
Şöyle yaparız. Burada @Configuration kullanılmış ama bence gerek yok
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
public class AsynConfiguration extends AsyncConfigurerSupport {
   @Override
   public Executor getAsyncExecutor() {
      ThreadPoolTaskExecutor executor = new 
                ThreadPoolTaskExecutor();
      executor.setCorePoolSize(3);
      executor.setMaxPoolSize(4);
      executor.setThreadNamePrefix("asyn-task-thread-");
      executor.setWaitForTasksToCompleteOnShutdown(true);
      executor.initialize();
      return executor;
  }
  @Override
  public AsyncUncaughtExceptionHandler  
         getAsyncUncaughtExceptionHandler() {
     return new AsyncUncaughtExceptionHandler() {
   
        @Override
        public void handleUncaughtException(Throwable ex, 
           Method method, Object... params) {
           System.out.println("Exception: " + ex.getMessage());
           System.out.println("Method Name: " + method.getName());
           ex.printStackTrace();
        }
    };
  }
}