diff --git a/pom.xml b/pom.xml
index aaf2720a..2f9b27b5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,7 +21,7 @@
1.8
1.8
1.2.0
- 1.0.0
+ 1.1.0
2.2.0
5.9.1
4.11.0
diff --git a/src/main/java/com/microsoft/azure/functions/worker/Util.java b/src/main/java/com/microsoft/azure/functions/worker/Util.java
index 2b083ed3..0adffe42 100644
--- a/src/main/java/com/microsoft/azure/functions/worker/Util.java
+++ b/src/main/java/com/microsoft/azure/functions/worker/Util.java
@@ -1,6 +1,11 @@
package com.microsoft.azure.functions.worker;
+import com.google.gson.Gson;
+import com.microsoft.azure.functions.spi.inject.GsonInstanceInjector;
+
public class Util {
+ private static Gson gsonInstance;
+ private static final Object utilLock = new Object();
public static boolean isTrue(String value) {
if(value != null && (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("1"))) {
return true;
@@ -11,4 +16,13 @@ public static boolean isTrue(String value) {
public static String getJavaVersion() {
return String.join(" - ", System.getProperty("java.home"), System.getProperty("java.version"));
}
+
+ public static void setGsonInstance(Gson instance) {
+ gsonInstance = instance;
+ }
+
+ public static Gson getGsonInstance() {
+ return gsonInstance;
+ }
+
}
\ No newline at end of file
diff --git a/src/main/java/com/microsoft/azure/functions/worker/binding/RpcJsonDataSource.java b/src/main/java/com/microsoft/azure/functions/worker/binding/RpcJsonDataSource.java
index 0d3c2d10..88fea7e1 100644
--- a/src/main/java/com/microsoft/azure/functions/worker/binding/RpcJsonDataSource.java
+++ b/src/main/java/com/microsoft/azure/functions/worker/binding/RpcJsonDataSource.java
@@ -5,6 +5,7 @@
import java.util.Collection;
import java.util.List;
+import com.microsoft.azure.functions.worker.Util;
import org.apache.commons.lang3.reflect.TypeUtils;
import com.google.gson.Gson;
@@ -17,7 +18,7 @@ public RpcJsonDataSource(String name, String value) {
super(name, value, JSON_DATA_OPERATIONS);
}
- public static final Gson gson = new Gson();
+ public static final Gson gson = Util.getGsonInstance();
public static final JsonParser gsonParser = new JsonParser();
private static final DataOperations JSON_DATA_OPERATIONS = new DataOperations<>();
diff --git a/src/main/java/com/microsoft/azure/functions/worker/broker/JavaFunctionBroker.java b/src/main/java/com/microsoft/azure/functions/worker/broker/JavaFunctionBroker.java
index 9b72f76d..d6021e87 100644
--- a/src/main/java/com/microsoft/azure/functions/worker/broker/JavaFunctionBroker.java
+++ b/src/main/java/com/microsoft/azure/functions/worker/broker/JavaFunctionBroker.java
@@ -7,10 +7,13 @@
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
+import com.google.gson.Gson;
import com.microsoft.azure.functions.internal.spi.middleware.Middleware;
import com.microsoft.azure.functions.rpc.messages.*;
import com.microsoft.azure.functions.spi.inject.FunctionInstanceInjector;
+import com.microsoft.azure.functions.spi.inject.GsonInstanceInjector;
import com.microsoft.azure.functions.worker.Constants;
+import com.microsoft.azure.functions.worker.Util;
import com.microsoft.azure.functions.worker.WorkerLogManager;
import com.microsoft.azure.functions.worker.binding.BindingDataStore;
import com.microsoft.azure.functions.worker.binding.ExecutionContextDataSource;
@@ -38,7 +41,7 @@ public class JavaFunctionBroker {
private volatile FunctionInstanceInjector functionInstanceInjector;
private final Object oneTimeLogicInitializationLock = new Object();
- private FunctionInstanceInjector newInstanceInjector() {
+ private FunctionInstanceInjector newFunctionInstanceInjector() {
return new FunctionInstanceInjector() {
@Override
public T getInstance(Class functionClass) throws Exception {
@@ -53,7 +56,7 @@ public JavaFunctionBroker(ClassLoaderProvider classLoaderProvider) {
}
public void loadMethod(FunctionMethodDescriptor descriptor, Map bindings)
- throws ClassNotFoundException, NoSuchMethodException, IOException {
+ throws Exception {
descriptor.validate();
addSearchPathsToClassLoader(descriptor);
initializeOneTimeLogics();
@@ -61,12 +64,12 @@ public void loadMethod(FunctionMethodDescriptor descriptor, Map(descriptor.getName(), functionDefinition));
}
- private void initializeOneTimeLogics() {
+ private void initializeOneTimeLogics() throws Exception{
if (!oneTimeLogicInitialized) {
synchronized (oneTimeLogicInitializationLock) {
if (!oneTimeLogicInitialized) {
initializeInvocationChainFactory();
- initializeFunctionInstanceInjector();
+ initializeInstanceInjector();
oneTimeLogicInitialized = true;
}
}
@@ -90,28 +93,45 @@ private void initializeInvocationChainFactory() {
this.invocationChainFactory = new InvocationChainFactory(middlewares);
}
- private void initializeFunctionInstanceInjector() {
+ private void initializeInstanceInjector() throws Exception{
ClassLoader prevContextClassLoader = Thread.currentThread().getContextClassLoader();
try {
//ServiceLoader will use thread context classloader to verify loaded class
Thread.currentThread().setContextClassLoader(classLoaderProvider.createClassLoader());
- Iterator iterator = ServiceLoader.load(FunctionInstanceInjector.class).iterator();
- if (iterator.hasNext()) {
- this.functionInstanceInjector = iterator.next();
- WorkerLogManager.getSystemLogger().info("Load function instance injector: " + this.functionInstanceInjector.getClass().getName());
- if (iterator.hasNext()){
- WorkerLogManager.getSystemLogger().warning("Customer function app has multiple FunctionInstanceInjector implementations.");
- throw new RuntimeException("Customer function app has multiple FunctionInstanceInjector implementations");
- }
- }else {
- this.functionInstanceInjector = newInstanceInjector();
- WorkerLogManager.getSystemLogger().info("Didn't find any function instance injector, creating function class instance every invocation.");
- }
+ loadFunctionInstanceInjector();
+ loadGsonInstanceInjector();
} finally {
Thread.currentThread().setContextClassLoader(prevContextClassLoader);
}
}
+ private void loadFunctionInstanceInjector() {
+ Iterator iterator = ServiceLoader.load(FunctionInstanceInjector.class).iterator();
+ if (iterator.hasNext()) {
+ this.functionInstanceInjector = iterator.next();
+ WorkerLogManager.getSystemLogger().info("Load function instance injector: " + this.functionInstanceInjector.getClass().getName());
+ if (iterator.hasNext()){
+ WorkerLogManager.getSystemLogger().warning("Customer function app has multiple FunctionInstanceInjector implementations.");
+ throw new RuntimeException("Customer function app has multiple FunctionInstanceInjector implementations");
+ }
+ }else {
+ this.functionInstanceInjector = newFunctionInstanceInjector();
+ WorkerLogManager.getSystemLogger().info("Didn't find any function instance injector, creating function class instance every invocation.");
+ }
+ }
+
+ private void loadGsonInstanceInjector() throws Exception{
+ Iterator iterator = ServiceLoader.load(GsonInstanceInjector.class).iterator();
+ if (iterator.hasNext()) {
+ GsonInstanceInjector gsonInstanceInjector = iterator.next();
+ Util.setGsonInstance(gsonInstanceInjector.getGsonInstance());
+ WorkerLogManager.getSystemLogger().info("Load gson instance injector: " + gsonInstanceInjector.getClass().getName());
+ }else {
+ Util.setGsonInstance(new Gson());
+ WorkerLogManager.getSystemLogger().info("Didn't find any gson instance injector, creating function class instance every invocation.");
+ }
+ }
+
private FunctionExecutionMiddleware getFunctionExecutionMiddleWare() {
FunctionExecutionMiddleware functionExecutionMiddleware = new FunctionExecutionMiddleware(
JavaMethodExecutors.createJavaMethodExecutor(this.classLoaderProvider.createClassLoader()));
diff --git a/src/test/java/com/microsoft/azure/functions/worker/binding/tests/RpcByteArrayDataSourceTest.java b/src/test/java/com/microsoft/azure/functions/worker/binding/tests/RpcByteArrayDataSourceTest.java
index ccfb9317..3ad31c14 100644
--- a/src/test/java/com/microsoft/azure/functions/worker/binding/tests/RpcByteArrayDataSourceTest.java
+++ b/src/test/java/com/microsoft/azure/functions/worker/binding/tests/RpcByteArrayDataSourceTest.java
@@ -4,16 +4,24 @@
import java.lang.invoke.WrongMethodTypeException;
import java.util.Optional;
+import com.google.gson.Gson;
+import com.microsoft.azure.functions.worker.Util;
import org.apache.commons.lang3.ArrayUtils;
import com.google.protobuf.ByteString;
import com.microsoft.azure.functions.worker.binding.BindingData;
import com.microsoft.azure.functions.worker.binding.RpcByteArrayDataSource;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class RpcByteArrayDataSourceTest {
+ @BeforeAll
+ public static void setGsonInstance() {
+ Util.setGsonInstance(new Gson());
+ }
+
@Test
public void rpcByteArrayDataSource_To_byteArray() {
String sourceKey = "testByteArray";
diff --git a/src/test/java/com/microsoft/azure/functions/worker/binding/tests/RpcStringDataSourceTest.java b/src/test/java/com/microsoft/azure/functions/worker/binding/tests/RpcStringDataSourceTest.java
index 4ce4462b..6b0c6c81 100644
--- a/src/test/java/com/microsoft/azure/functions/worker/binding/tests/RpcStringDataSourceTest.java
+++ b/src/test/java/com/microsoft/azure/functions/worker/binding/tests/RpcStringDataSourceTest.java
@@ -8,11 +8,14 @@
import java.util.List;
import java.util.Optional;
+import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
+import com.microsoft.azure.functions.worker.Util;
import com.microsoft.azure.functions.worker.binding.BindingData;
import com.microsoft.azure.functions.worker.binding.RpcJsonDataSource;
import com.microsoft.azure.functions.worker.binding.RpcStringDataSource;
import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
@@ -32,6 +35,11 @@ public void FunctionWithPOJOListInput(ArrayList items) {
public void FunctionWithStringListInput(List items) {
}
+ @BeforeAll
+ public static void setGsonInstance() {
+ Util.setGsonInstance(new Gson());
+ }
+
@Test
public void rpcStringDataSource_To_String() {
String sourceKey = "testString";