我有一个APP,它会向我的java应用程序发送一些REST调用。我必须在@Async模式下运行最后一个命令,这样用户可以继续使用应用程序,同时执行一个异步任务再执行一次SOAP调用。
问题是我在数据库中自动连接了TenantContext和几个租户标识符。在执行异步任务时,它具有我的mainthread的tenantcontext并保存错误租户的数据。
这是我为数据库中的每个事务调用的JpaTransactionManager:
@Autowired
private TenantContext tenantContext;
@Autowired
private Flyway flyway;
@Autowired
private Environment environment;
@Override
protected void doBegin(final Object transaction, final TransactionDefinition definition)
{
super.doBegin(transaction, definition);
final EntityManagerHolder entityManagerHolder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(getEntityManagerFactory());
final EntityManager entityManager = entityManagerHolder.getEntityManager();
String subAccountId = "";
if (environment.getActiveProfiles().length == 0 || !environment.getActiveProfiles()[0].equals("production"))
{
subAccountId = "SCAN4CLOUD";
} else
{
subAccountId = tenantContext.getTenant().getAccount().getId().toUpperCase();
}
entityManager.setProperty("tenant", subAccountId);
}
我试图通过以下类拦截异步调用来设置正确的tenantcontext。
@Configuration
@EnableAsync
public class AsyncConfig extends AsyncConfigurerSupport
{
@Autowired
private TenantContext tenantContext;
@Autowired
private Environment environment;
private HashMap<String, ContextAwarePoolExecutor> tenantThreadPoolTaskExecutor = new HashMap<String, ContextAwarePoolExecutor>();
@Override
@Bean
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Executor getAsyncExecutor()
{
String subAccountId = "";
if (environment.getActiveProfiles().length == 0 || !environment.getActiveProfiles()[0].equals("production"))
{
subAccountId = "SCAN4CLOUD";
} else
{
subAccountId = tenantContext.getTenant().getAccount().getId().toUpperCase();
}
if (!tenantThreadPoolTaskExecutor.containsKey(subAccountId))
{
tenantThreadPoolTaskExecutor.put(subAccountId, new ContextAwarePoolExecutor(tenantContext));
}
return tenantThreadPoolTaskExecutor.get(subAccountId);
}
}
ContextAwarePoolExecutor:
public class ContextAwarePoolExecutor extends ThreadPoolTaskExecutor
{
private TenantContext tenantContext;
public ContextAwarePoolExecutor(TenantContext tenantContext)
{
this.tenantContext = tenantContext;
}
@Override
public <T> Future<T> submit(Callable<T> task)
{
return super.submit(new ContextAwareCallable(task, tenantContext));
}
@Override
public <T> ListenableFuture<T> submitListenable(Callable<T> task)
{
return super.submitListenable(new ContextAwareCallable(task, tenantContext));
}
}
ContextAwareCallable:
public class ContextAwareCallable<T> implements Callable<T>
{
private Callable<T> task;
private TenantContext tenantContext;
public ContextAwareCallable(Callable<T> task, TenantContext tenantContext)
{
this.task = task;
this.tenantContext = tenantContext;
}
@Override
public T call() throws Exception
{
if (tenantContext != null)
{
return tenantContext.execute(tenantContext.getTenant().getId(), task);
}
return task.call();
}
}
但它仍然没有给我父线程的正确租户。
对此有何建议或其他方法?
谢谢, NOSTA
答案 0 :(得分:0)
我通过在contextawarecallable构造函数中直接添加tenantid来解决它。现在它正在工作。
答案 1 :(得分:0)
Tenantcontext类来自SAP:import com.sap.cloud.account.TenantContext; https://appdoc.app/artifact/com.sap.cloud/neo-java-web-api/1.105.21/com/sap/cloud/account/TenantContext.html
import java.util.concurrent.Callable;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import com.sap.cloud.account.TenantContext;
public class ContextAwareCallable<T> implements Callable<T>
{
private Callable<T> task;
private TenantContext tenantContext;
private String tenantId;
private RequestAttributes context;
public ContextAwareCallable(Callable<T> task, TenantContext tenantContext, RequestAttributes context)
{
this.task = task;
this.tenantContext = tenantContext;
this.context = context;
if (tenantContext != null)
{
this.tenantId = tenantContext.getTenant().getId();
}
}
@Override
public T call() throws Exception
{
if (context != null)
{
RequestContextHolder.setRequestAttributes(context);
}
if (tenantId != null)
{
return tenantContext.execute(tenantId, task);
}
return task.call();
}
}