You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ni...@apache.org on 2013/07/26 10:49:23 UTC
[2/2] git commit: CAMEL-6559 fixed the script builder synchronized
the operation of evaluateScript issue
CAMEL-6559 fixed the script builder synchronized the operation of evaluateScript issue
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/f66375e9
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/f66375e9
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/f66375e9
Branch: refs/heads/master
Commit: f66375e91e2755e956c1527752c255aa2d0f8c42
Parents: f478217
Author: Willem Jiang <ni...@apache.org>
Authored: Fri Jul 26 16:46:50 2013 +0800
Committer: Willem Jiang <ni...@apache.org>
Committed: Fri Jul 26 16:48:39 2013 +0800
----------------------------------------------------------------------
.../camel/builder/script/ScriptBuilder.java | 61 ++++++++++++++++----
.../camel/builder/script/ScriptLanguage.java | 17 +++++-
.../script/JavaScriptExpressionTest.java | 35 ++++++++++-
3 files changed, 99 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/f66375e9/components/camel-script/src/main/java/org/apache/camel/builder/script/ScriptBuilder.java
----------------------------------------------------------------------
diff --git a/components/camel-script/src/main/java/org/apache/camel/builder/script/ScriptBuilder.java b/components/camel-script/src/main/java/org/apache/camel/builder/script/ScriptBuilder.java
index 710be36..7477673 100644
--- a/components/camel-script/src/main/java/org/apache/camel/builder/script/ScriptBuilder.java
+++ b/components/camel-script/src/main/java/org/apache/camel/builder/script/ScriptBuilder.java
@@ -22,6 +22,8 @@ import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Method;
import java.util.Map;
+import java.util.WeakHashMap;
+
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptContext;
@@ -35,6 +37,7 @@ import org.apache.camel.Message;
import org.apache.camel.Predicate;
import org.apache.camel.Processor;
import org.apache.camel.converter.ObjectConverter;
+import org.apache.camel.support.ServiceSupport;
import org.apache.camel.util.IOHelper;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.ResourceHelper;
@@ -47,7 +50,7 @@ import org.slf4j.LoggerFactory;
*
* @version
*/
-public class ScriptBuilder implements Expression, Predicate, Processor {
+public class ScriptBuilder extends ServiceSupport implements Expression, Predicate, Processor {
/**
* Additional arguments to {@link ScriptEngine} provided as a header on the IN {@link org.apache.camel.Message}
@@ -60,8 +63,9 @@ public class ScriptBuilder implements Expression, Predicate, Processor {
private String scriptEngineName;
private String scriptResource;
private String scriptText;
- private ScriptEngine engine;
private CompiledScript compiledScript;
+ private Map<Thread, ScriptEngineHolder> engineHolders = new WeakHashMap<Thread, ScriptEngineHolder>();
+ private ThreadLocal<ScriptEngineHolder> engineHolder = new ThreadLocal<ScriptEngineHolder>();
/**
* Constructor.
@@ -194,13 +198,22 @@ public class ScriptBuilder implements Expression, Predicate, Processor {
// -------------------------------------------------------------------------
public ScriptEngine getEngine() {
- if (engine == null) {
- engine = createScriptEngine();
+ if (engineHolder.get() == null) {
+ ScriptEngineHolder holder = new ScriptEngineHolder();
+
+ engineHolder.set(holder);
+ engineHolders.put(Thread.currentThread(), holder);
}
- if (engine == null) {
+ if (engineHolder.get() == null) {
throw new IllegalArgumentException("No script engine could be created for: " + getScriptEngineName());
}
- return engine;
+ ScriptEngineHolder holder = engineHolder.get();
+ if (holder.engine == null) {
+ holder.engine = createScriptEngine();
+ engineHolders.put(Thread.currentThread(), holder);
+ }
+
+ return holder.engine;
}
public CompiledScript getCompiledScript() {
@@ -258,13 +271,20 @@ public class ScriptBuilder implements Expression, Predicate, Processor {
if (scriptText == null && scriptResource == null) {
throw new IllegalArgumentException("Neither scriptText or scriptResource are specified");
}
- if (engine == null) {
- engine = createScriptEngine();
+ ScriptEngineHolder holder = engineHolder.get();
+ if (holder == null) {
+ holder = new ScriptEngineHolder();
+ engineHolder.set(holder);
+ }
+ holder = engineHolder.get();
+ if (holder.engine == null) {
+ holder.engine = createScriptEngine();
+ engineHolders.put(Thread.currentThread(), holder);
}
if (compiledScript == null) {
// BeanShell implements Compilable but throws an exception if you call compile
- if (engine instanceof Compilable && !isBeanShell()) {
- compileScript((Compilable)engine, exchange);
+ if (holder.engine instanceof Compilable && !isBeanShell()) {
+ compileScript((Compilable)holder.engine, exchange);
}
}
}
@@ -275,6 +295,7 @@ public class ScriptBuilder implements Expression, Predicate, Processor {
protected ScriptEngine createScriptEngine() {
ScriptEngineManager manager = new ScriptEngineManager();
+ ScriptEngine engine = null;
try {
engine = manager.getEngineByName(scriptEngineName);
} catch (NoClassDefFoundError ex) {
@@ -333,7 +354,7 @@ public class ScriptBuilder implements Expression, Predicate, Processor {
}
}
- protected synchronized Object evaluateScript(Exchange exchange) {
+ protected Object evaluateScript(Exchange exchange) {
try {
getScriptContext();
populateBindings(getEngine(), exchange);
@@ -438,4 +459,22 @@ public class ScriptBuilder implements Expression, Predicate, Processor {
protected boolean isBeanShell() {
return "beanshell".equals(scriptEngineName) || "bsh".equals(scriptEngineName);
}
+
+ @Override
+ protected void doStart() throws Exception {
+ // do nothing here
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ // we need to clean up the engines map
+ for (ScriptEngineHolder holder : engineHolders.values()) {
+ holder.engine = null;
+ }
+ engineHolders.clear();
+ }
+
+ static class ScriptEngineHolder {
+ ScriptEngine engine;
+ }
}
http://git-wip-us.apache.org/repos/asf/camel/blob/f66375e9/components/camel-script/src/main/java/org/apache/camel/builder/script/ScriptLanguage.java
----------------------------------------------------------------------
diff --git a/components/camel-script/src/main/java/org/apache/camel/builder/script/ScriptLanguage.java b/components/camel-script/src/main/java/org/apache/camel/builder/script/ScriptLanguage.java
index c463cb8..171b63a 100644
--- a/components/camel-script/src/main/java/org/apache/camel/builder/script/ScriptLanguage.java
+++ b/components/camel-script/src/main/java/org/apache/camel/builder/script/ScriptLanguage.java
@@ -18,6 +18,7 @@ package org.apache.camel.builder.script;
import org.apache.camel.Expression;
import org.apache.camel.Predicate;
+import org.apache.camel.RuntimeCamelException;
import org.apache.camel.support.LanguageSupport;
/**
@@ -32,12 +33,24 @@ public class ScriptLanguage extends LanguageSupport {
public Predicate createPredicate(String expression) {
expression = loadResource(expression);
- return new ScriptBuilder(language, expression);
+ ScriptBuilder builder = new ScriptBuilder(language, expression);
+ try {
+ getCamelContext().addService(builder);
+ } catch (Exception ex) {
+ throw new RuntimeCamelException(ex);
+ }
+ return builder;
}
public Expression createExpression(String expression) {
expression = loadResource(expression);
- return new ScriptBuilder(language, expression);
+ ScriptBuilder builder = new ScriptBuilder(language, expression);
+ try {
+ getCamelContext().addService(builder);
+ } catch (Exception ex) {
+ throw new RuntimeCamelException(ex);
+ }
+ return builder;
}
}
http://git-wip-us.apache.org/repos/asf/camel/blob/f66375e9/components/camel-script/src/test/java/org/apache/camel/builder/script/JavaScriptExpressionTest.java
----------------------------------------------------------------------
diff --git a/components/camel-script/src/test/java/org/apache/camel/builder/script/JavaScriptExpressionTest.java b/components/camel-script/src/test/java/org/apache/camel/builder/script/JavaScriptExpressionTest.java
index 9581c6f..d02b1c2 100644
--- a/components/camel-script/src/test/java/org/apache/camel/builder/script/JavaScriptExpressionTest.java
+++ b/components/camel-script/src/test/java/org/apache/camel/builder/script/JavaScriptExpressionTest.java
@@ -18,6 +18,8 @@ package org.apache.camel.builder.script;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import org.apache.camel.ScriptTestHelper;
import org.apache.camel.builder.RouteBuilder;
@@ -146,7 +148,38 @@ public class JavaScriptExpressionTest extends CamelTestSupport {
assertMockEndpointsSatisfied();
}
-
+
+ @Test
+ public void testSendingRequestInMutipleThreads() throws Exception {
+ if (!ScriptTestHelper.canRunTestOnThisPlatform()) {
+ return;
+ }
+ getMockEndpoint("mock:result").expectedMessageCount(0);
+ getMockEndpoint("mock:unmatched").expectedMessageCount(100);
+ long start = System.currentTimeMillis();
+ ExecutorService executorService = Executors.newFixedThreadPool(100);
+ for (int i = 0; i < 100; i++) {
+ executorService.submit(new Runnable() {
+ @Override
+ public void run() {
+ Map<String, Object> headers = new HashMap<String, Object>();
+ String arguments = "foo";
+ headers.put(ScriptBuilder.ARGUMENTS, arguments);
+
+ sendBody("direct:start", "hello", headers);
+
+ }
+
+ });
+ }
+
+ assertMockEndpointsSatisfied();
+ long delta = System.currentTimeMillis() - start;
+ log.info("Processing the 100 request tooks: " + delta + " ms");
+ executorService.shutdown();
+
+ }
+
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
public void configure() throws Exception {