
com.introproventures.graphql.jpa.query.autoconfigure.TransactionalDelegateExecutionStrategy Maven / Gradle / Ivy
package com.introproventures.graphql.jpa.query.autoconfigure;
import graphql.ExecutionResult;
import graphql.execution.AsyncExecutionStrategy;
import graphql.execution.ExecutionContext;
import graphql.execution.ExecutionStrategy;
import graphql.execution.ExecutionStrategyParameters;
import graphql.execution.NonNullableFieldWasNullException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate;
public class TransactionalDelegateExecutionStrategy extends ExecutionStrategy {
private static final Logger log = LoggerFactory.getLogger(TransactionalDelegateExecutionStrategy.class);
private final TransactionTemplate transactionTemplate;
private final ExecutionStrategy delegate;
private final Supplier executor;
public TransactionalDelegateExecutionStrategy(
TransactionTemplate transactionTemplate,
ExecutionStrategy delegate,
Supplier executor
) {
this.transactionTemplate = transactionTemplate;
this.delegate = delegate;
this.executor = executor;
}
@Override
public CompletableFuture execute(
ExecutionContext executionContext,
ExecutionStrategyParameters parameters
) throws NonNullableFieldWasNullException {
if (!TransactionSynchronizationManager.isActualTransactionActive()) {
if (log.isTraceEnabled()) {
log.trace(
"Start root execution request {} running on {}",
executionContext.getExecutionId(),
Thread.currentThread()
);
}
return CompletableFuture.supplyAsync(
() ->
transactionTemplate.execute(status -> {
if (log.isTraceEnabled()) {
log.trace(
"Begin transaction for {} on {}",
executionContext.getExecutionId(),
Thread.currentThread()
);
}
try {
if (log.isTraceEnabled()) {
log.trace(
"Execute request for {} on {}",
executionContext.getExecutionId(),
Thread.currentThread()
);
}
return delegate.execute(executionContext, parameters).join();
} finally {
if (log.isTraceEnabled()) {
log.trace(
"End transaction for {} on {}",
executionContext.getExecutionId(),
Thread.currentThread()
);
}
}
}),
executor.get()
);
} else {
if (log.isTraceEnabled()) {
log.trace(
"Execute request {} for {} on {}",
executionContext.getExecutionId(),
parameters.getField().getName(),
Thread.currentThread()
);
}
return delegate.execute(executionContext, parameters);
}
}
public TransactionTemplate getTransactionTemplate() {
return transactionTemplate;
}
public ExecutionStrategy getDelegate() {
return delegate;
}
public Supplier getExecutor() {
return executor;
}
public static final class Builder {
private static final ExecutorService EXECUTOR_SERVICE = Executors.newCachedThreadPool();
static {
Runtime.getRuntime().addShutdownHook(new Thread(EXECUTOR_SERVICE::shutdown));
}
private TransactionTemplate transactionTemplate;
private Supplier executor = () -> EXECUTOR_SERVICE;
private ExecutionStrategy delegate = new AsyncExecutionStrategy();
private Builder() {}
public static Builder newTransactionalExecutionStrategy(TransactionTemplate transactionTemplate) {
return new Builder().transactionTemplate(transactionTemplate);
}
public Builder transactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
return this;
}
public Builder transactionTemplate(Consumer transactionTemplateCustomizer) {
transactionTemplateCustomizer.accept(transactionTemplate);
return this;
}
public Builder delegate(ExecutionStrategy delegate) {
this.delegate = delegate;
return this;
}
public Builder executor(Supplier executor) {
this.executor = executor;
return this;
}
public Builder executor(Executor executor) {
return executor(() -> executor);
}
public TransactionalDelegateExecutionStrategy build() {
return new TransactionalDelegateExecutionStrategy(transactionTemplate, delegate, executor);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy