Set Thread context classloder for entire middleware chain (#717)

* Set Thread context classloder for entire middleware chain

* clean up code

* clean up
This commit is contained in:
kaibocai 2023-09-27 10:37:34 -05:00 коммит произвёл GitHub
Родитель 029414f7df
Коммит 531587467c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 28 добавлений и 77 удалений

Просмотреть файл

@ -1,28 +0,0 @@
package com.microsoft.azure.functions.worker.broker;
import com.microsoft.azure.functions.worker.binding.*;
/**
* Used to executor of arbitrary Java method in any JAR using reflection.
* Thread-Safety: Multiple thread.
*/
public class EnhancedJavaMethodExecutorImpl implements JavaMethodExecutor {
private final ClassLoader classLoader;
public EnhancedJavaMethodExecutorImpl(ClassLoader classLoader) {
this.classLoader = classLoader;
}
public void execute(ExecutionContextDataSource executionContextDataSource) throws Exception {
try {
Thread.currentThread().setContextClassLoader(this.classLoader);
Object retValue = ParameterResolver.resolveArguments(executionContextDataSource)
.orElseThrow(() -> new NoSuchMethodException("Cannot locate the method signature with the given input"))
.invoke(executionContextDataSource::getFunctionInstance);
executionContextDataSource.updateReturnValue(retValue);
} finally {
Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
}
}
}

Просмотреть файл

@ -113,8 +113,7 @@ public class JavaFunctionBroker {
}
private FunctionExecutionMiddleware getFunctionExecutionMiddleWare() {
FunctionExecutionMiddleware functionExecutionMiddleware = new FunctionExecutionMiddleware(
JavaMethodExecutors.createJavaMethodExecutor(this.classLoaderProvider.createClassLoader()));
FunctionExecutionMiddleware functionExecutionMiddleware = new FunctionExecutionMiddleware(JavaMethodExecutor.getInstance());
WorkerLogManager.getSystemLogger().info("Load last middleware: FunctionExecutionMiddleware");
return functionExecutionMiddleware;
}
@ -122,11 +121,21 @@ public class JavaFunctionBroker {
public Optional<TypedData> invokeMethod(String id, InvocationRequest request, List<ParameterBinding> outputs)
throws Exception {
ExecutionContextDataSource executionContextDataSource = buildExecutionContext(id, request);
this.invocationChainFactory.create().doNext(executionContextDataSource);
invoke(executionContextDataSource);
outputs.addAll(executionContextDataSource.getDataStore().getOutputParameterBindings(true));
return executionContextDataSource.getDataStore().getDataTargetTypedValue(BindingDataStore.RETURN_NAME);
}
private void invoke(ExecutionContextDataSource executionContextDataSource) throws Exception {
ClassLoader prevContextClassLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(classLoaderProvider.createClassLoader());
this.invocationChainFactory.create().doNext(executionContextDataSource);
} finally {
Thread.currentThread().setContextClassLoader(prevContextClassLoader);
}
}
private ExecutionContextDataSource buildExecutionContext(String id, InvocationRequest request)
throws NoSuchMethodException {
ImmutablePair<String, FunctionDefinition> methodEntry = this.methods.get(id);

Просмотреть файл

@ -1,14 +1,25 @@
package com.microsoft.azure.functions.worker.broker;
import java.util.*;
import com.microsoft.azure.functions.worker.binding.*;
/**
* Used to executor of arbitrary Java method in any JAR using reflection.
* Thread-Safety: Multiple thread.
*/
public interface JavaMethodExecutor {
void execute(ExecutionContextDataSource executionContextDataSource) throws Exception;
public class JavaMethodExecutor {
private static final JavaMethodExecutor INSTANCE = new JavaMethodExecutor();
public static JavaMethodExecutor getInstance(){
return INSTANCE;
}
private JavaMethodExecutor() {}
public void execute(ExecutionContextDataSource executionContextDataSource) throws Exception {
Object retValue = ParameterResolver.resolveArguments(executionContextDataSource)
.orElseThrow(() -> new NoSuchMethodException("Cannot locate the method signature with the given input"))
.invoke(executionContextDataSource::getFunctionInstance);
executionContextDataSource.updateReturnValue(retValue);
}
}

Просмотреть файл

@ -1,25 +0,0 @@
package com.microsoft.azure.functions.worker.broker;
import com.microsoft.azure.functions.worker.binding.*;
/**
* Used to executor of arbitrary Java method in any JAR using reflection.
* Thread-Safety: Multiple thread.
*/
public class JavaMethodExecutorImpl implements JavaMethodExecutor {
private static final JavaMethodExecutorImpl INSTANCE = new JavaMethodExecutorImpl();
public static JavaMethodExecutorImpl getInstance(){
return INSTANCE;
}
private JavaMethodExecutorImpl () {}
public void execute(ExecutionContextDataSource executionContextDataSource) throws Exception {
Object retValue = ParameterResolver.resolveArguments(executionContextDataSource)
.orElseThrow(() -> new NoSuchMethodException("Cannot locate the method signature with the given input"))
.invoke(executionContextDataSource::getFunctionInstance);
executionContextDataSource.updateReturnValue(retValue);
}
}

Просмотреть файл

@ -1,16 +0,0 @@
package com.microsoft.azure.functions.worker.broker;
import com.microsoft.azure.functions.worker.WorkerLogManager;
import org.apache.commons.lang3.SystemUtils;
public class JavaMethodExecutors {
public static JavaMethodExecutor createJavaMethodExecutor(ClassLoader classLoader) {
if(SystemUtils.IS_JAVA_1_8) {
WorkerLogManager.getSystemLogger().info("Loading JavaMethodExecutorImpl");
return JavaMethodExecutorImpl.getInstance();
} else {
WorkerLogManager.getSystemLogger().info("Loading EnhancedJavaMethodExecutorImpl");
return new EnhancedJavaMethodExecutorImpl(classLoader);
}
}
}