Jonathan_Medeiros 6 de ago. de 2020
Em teoria deveria, como estão as suas configurações do async?
Eu geralmente configuro da seguinte forma:
Crio uma classe que implementa o TaskDecorator (Ela é responsável por tratar separadamente os contextos de cada thread):
public class MdcTaskDecorator implements TaskDecorator {
@ Override
public Runnable decorate ( Runnable runnable ) {
var requestAttributes = RequestContextHolder . currentRequestAttributes ();
var contextMap = MDC . getCopyOfContextMap ();
return () -> {
try {
RequestContextHolder . setRequestAttributes ( requestAttributes );
MDC . setContextMap ( contextMap );
runnable . run ();
} finally {
MDC . clear ();
RequestContextHolder . resetRequestAttributes ();
}
};
}
}
Configuro uma classe para habilitar o uso do async criando um pool de thread’s:
@EnableAsync
@Configuration
public class AsyncConfiguration {
@Bean
public Executor asyncExecutor () {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor ();
executor . setTaskDecorator ( new MdcTaskDecorator ());
executor . setThreadNamePrefix ( "asyncPoolExecutor-" );
executor . initialize ();
return executor ;
}
}
Depois só chamo em qualquer método:
@Async
public void processAsync () {
...
}
guilhermebhte 6 de ago. de 2020
Está assim:
package br.com.ghnetsoft.takeprofit.config ;
import java.util.concurrent.Executor ;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler ;
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler ;
import org.springframework.boot.autoconfigure.task.TaskExecutionProperties ;
import org.springframework.context.annotation.Bean ;
import org.springframework.context.annotation.Configuration ;
import org.springframework.scheduling.annotation.AsyncConfigurer ;
import org.springframework.scheduling.annotation.EnableAsync ;
import org.springframework.scheduling.annotation.EnableScheduling ;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor ;
import io.github.jhipster.async.ExceptionHandlingAsyncTaskExecutor ;
@Configuration
@EnableAsync
@EnableScheduling
public class AsyncConfiguration implements AsyncConfigurer {
private final Logger log = LoggerFactory . getLogger ( AsyncConfiguration . class );
private final TaskExecutionProperties taskExecutionProperties ;
public AsyncConfiguration ( TaskExecutionProperties taskExecutionProperties ) {
this . taskExecutionProperties = taskExecutionProperties ;
}
@Override
@Bean ( name = "taskExecutor" )
public Executor getAsyncExecutor () {
log . debug ( "Creating Async Task Executor" );
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor ();
executor . setCorePoolSize ( taskExecutionProperties . getPool (). getCoreSize ());
executor . setMaxPoolSize ( taskExecutionProperties . getPool (). getMaxSize ());
executor . setQueueCapacity ( taskExecutionProperties . getPool (). getQueueCapacity ());
executor . setThreadNamePrefix ( taskExecutionProperties . getThreadNamePrefix ());
return new ExceptionHandlingAsyncTaskExecutor ( executor );
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler () {
return new SimpleAsyncUncaughtExceptionHandler ();
}
}
Jonathan_Medeiros 6 de ago. de 2020
Tenta configurar um TaskDecorador no bean do seu Executor e veja se muda o comportamento.
guilhermebhte 10 de ago. de 2020
Fiz assim:
package br.com.ghnetsoft.takeprofit.config ;
import java.util.concurrent.Executor ;
import org.springframework.context.annotation.Bean ;
import org.springframework.context.annotation.Configuration ;
import org.springframework.scheduling.annotation.EnableAsync ;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor ;
@Configuration
@EnableAsync
public class AsyncConfiguration {
@Bean
public Executor asyncExecutor () {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor ();
executor . setTaskDecorator ( new MdcTaskDecorator ());
executor . setThreadNamePrefix ( "asyncPoolExecutor-" );
executor . initialize ();
return executor ;
}
}
e
package br.com.ghnetsoft.takeprofit.config ;
import java.util.Map ;
import org.slf4j.MDC ;
import org.springframework.core.task.TaskDecorator ;
import org.springframework.web.context.request.RequestAttributes ;
import org.springframework.web.context.request.RequestContextHolder ;
public class MdcTaskDecorator implements TaskDecorator {
@Override
public Runnable decorate ( Runnable runnable ) {
RequestAttributes requestAttributes = RequestContextHolder . currentRequestAttributes ();
Map < String , String > contextMap = MDC . getCopyOfContextMap ();
return () -> {
try {
RequestContextHolder . setRequestAttributes ( requestAttributes );
MDC . setContextMap ( contextMap );
runnable . run ();
} finally {
MDC . clear ();
RequestContextHolder . resetRequestAttributes ();
}
};
}
}
e
@Transactional
@Async
public void run ( PdfReader pdfReader , Usuario usuarioLogado , byte [] bytes , String contentType , String nomeArquivo ,
long tamanhoArquivo ) {
}
Deu este erro:
Exception in thread "asyncPoolExecutor-1" java . lang . NullPointerException
at java . util . HashMap . putMapEntries ( Unknown Source )
at java . util . HashMap . putAll ( Unknown Source )
at java . util . Collections$SynchronizedMap . putAll ( Unknown Source )
at ch . qos . logback . classic . util . LogbackMDCAdapter . setContextMap ( LogbackMDCAdapter . java : 197 )
at org . slf4j . MDC . setContextMap ( MDC . java : 264 )
at br . com . ghnetsoft . takeprofit . config . MdcTaskDecorator . lambda$0 ( MdcTaskDecorator . java : 19 )
at java . util . concurrent . ThreadPoolExecutor . runWorker ( Unknown Source )
at java . util . concurrent . ThreadPoolExecutor$Worker . run ( Unknown Source )
at java . lang . Thread . run ( Unknown Source )
Jonathan_Medeiros 11 de ago. de 2020 1 like
Provavelmente é porquê você não está manipulando os contextos, mas isso não chega a ser algo essencial, remove ele do seu TaskDecorator!
Exemplo:
public class MdcTaskDecorator implements TaskDecorator {
@ Override
public Runnable decorate ( Runnable runnable ) {
return () -> {
try {
runnable . run ();
} catch ( Exception ex ) {
throw ex ;
}
};
}
}
guilhermebhte 11 de ago. de 2020
fica preso do mesmo jeito
Ele trava é só inicia um outro processo, quando o primeiro termina. Isso não poderia acontecer.
Jonathan_Medeiros 11 de ago. de 2020
Muito estranho, deve ter alguma coisa impactando nisso ainda