diff --git a/pom.xml b/pom.xml
index b8871f358f..a048a458ed 100644
--- a/pom.xml
+++ b/pom.xml
@@ -41,6 +41,11 @@
yamlbeans
1.15
+
+ net.jcip
+ jcip-annotations
+ 1.0
+
diff --git a/src/main/java/scripting/SynchronizedInvocable.java b/src/main/java/scripting/SynchronizedInvocable.java
new file mode 100644
index 0000000000..b318837ce5
--- /dev/null
+++ b/src/main/java/scripting/SynchronizedInvocable.java
@@ -0,0 +1,39 @@
+package scripting;
+
+import net.jcip.annotations.ThreadSafe;
+
+import javax.script.Invocable;
+import javax.script.ScriptException;
+
+/**
+ * Thread safe wrapper around Invocable.
+ * Thread safety is achieved by synchronizing all methods.
+ */
+@ThreadSafe
+public class SynchronizedInvocable implements Invocable {
+ private final Invocable invocable;
+
+ public SynchronizedInvocable(Invocable invocable) {
+ this.invocable = invocable;
+ }
+
+ @Override
+ public synchronized Object invokeMethod(Object thiz, String name, Object... args) throws ScriptException, NoSuchMethodException {
+ return invocable.invokeMethod(thiz, name, args);
+ }
+
+ @Override
+ public synchronized Object invokeFunction(String name, Object... args) throws ScriptException, NoSuchMethodException {
+ return invocable.invokeFunction(name, args);
+ }
+
+ @Override
+ public synchronized T getInterface(Class clasz) {
+ return invocable.getInterface(clasz);
+ }
+
+ @Override
+ public synchronized T getInterface(Object thiz, Class clasz) {
+ return invocable.getInterface(thiz, clasz);
+ }
+}