As soon as you have a ScriptEvaluator that extends a class it breaks - this was something that definitely worked in 2.1.0:
java.lang.NullPointerException
at org.codehaus.janino.Java$ClassDeclaration.compile(Java.java:850)
at org.codehaus.janino.Java$CompilationUnit.compile(Java.java:378)
at org.codehaus.janino.Java$CompilationUnit.compile(Java.java:367)
at org.codehaus.janino.EvaluatorBase.compileAndLoad(EvaluatorBase.java:259)
at org.codehaus.janino.EvaluatorBase.compileAndLoad(EvaluatorBase.java:293)
at org.codehaus.janino.ScriptEvaluator.<init>(ScriptEvaluator.java:323)
at org.codehaus.janino.ScriptEvaluator.createFastScriptEvaluator(ScriptEvaluator.java:416)
at org.drools.semantics.java.TestJanino.test1(TestJanino.java:47)
I have made a junit test script to prove this:
package org.drools.semantics.java;
import java.util.HashMap;
import org.codehaus.janino.ByteArrayClassLoader;
import org.codehaus.janino.ClassBodyEvaluator;
import org.codehaus.janino.Scanner;
import org.codehaus.janino.ScriptEvaluator;
import junit.framework.TestCase;
public class TestJanino extends TestCase
{
public void test1() throws Exception
{
String func = "public void helloWorld(java.lang.String hello)";
func += "{";
func += " System.err.println(hello + \" World\");";
func += "}";
ClassLoader classLoader = new ByteArrayClassLoader( new HashMap( ),
Thread.currentThread( ).getContextClassLoader( ) );
ClassBodyEvaluator classBody = new ClassBodyEvaluator( new Scanner( null,
new java.io.StringReader( func ) ),
"func0",
null,
new Class[]{},
classLoader );
Class funcClass = classBody.evaluate( );
String text = "return true;";
try
{
Script script = (Script) ScriptEvaluator.createFastScriptEvaluator( new Scanner( null,
new java.io.StringReader( text ) ),
"condition0",
null,
Script.class,
new String[]{},
classLoader );
}
catch ( Exception e )
{
fail( "this should pass" );
}
try
{
Script script = (Script) ScriptEvaluator.createFastScriptEvaluator( new Scanner( null,
new java.io.StringReader( text ) ),
"condition0",
funcClass,
Script.class,
new String[]{},
classLoader );
fail( "this should fail" );
}
catch ( Exception e )
{
e.printStackTrace( );
}
}
public static interface Script
{
public boolean invoke() throws Exception;
}
}
your problem is caused by a subtle incompatible change that I introduced in version 2.2.0 and didn't document clearly enough. I'll make good for that in the next version (JAVADOC and change log).
<p>
The description of the incompatible change is:
<pre>
* otherwise a new {@link ByteArrayClassLoader} was created with the
* <dt>2.2.0
* <dd>A new {@link ByteArrayClassLoader} is always created with the
* <code>optionalClassLoader</code> as the parent {@link ClassLoader}.
</pre>
As a consequence, the "old trick":
<pre>
ClassLoader cl = new ByteArrayClassLoader();
Class class1 = new ClassBodyEvaluator(... , cl);
new XyzEvaluator(... , class1, ... , cl);
</pre>
doesn't work any more, instead you have to write:
<pre>
Class class1 = new ClassBodyEvaluator(...);
new XyzEvaluator(... , class1, ... , class1.getClassLoader());
</pre>
Notice that the new code works both for 2.1.0 AND 2.2.0.
<p>
I also added code that avoids the NullPointerException and throws a verbose
RuntimeException instead:
<p>
java.lang.RuntimeException: Cannot load class "func0" through the given ClassLoader
<p>
Sorry for the inconvenience!