3 method to evaluate expressions in Java
The problem: You need to evaluate dynamic expression in your java code. Some common situation includes on a program contest evaluation system, on a dynamic business logic control, on evaluation of dynamic math expression, or even on evaluation of test case.
There is many ways evaluate expression. These methods can be categorized into 3 different ways generally.
Method 1. Leverage dynamic compilation in Java.
You can add the dynamic expressions to codes of a skeleton class template; and then compile the class. It is the most original and flexible way to evaluate expressions. For full instructions see my last post:
3 steps to dynamically compile, instantiate and run a Java class.
Method 2. Evaluate expressions by java libraries.
There’s dozens of libraries to evaluate expression in java. The most intuitive and powerful library should be jexl and expressionoasis.
http://commons.apache.org/jexl/
http://code.google.com/p/expressionoasis/
When evaluating expressions, JEXL merges an Expression with a JexlContext. An Expression is created using JexlEngine#createExpression(), passing a String containing valid JEXL syntax. A simple JexlContext can be created by instantiating a MapContext; a map of variables that will be internally wrapped can be optionally provided through its constructor. The following example, takes a variable named foo, and invokes the bar() method on the property innerFoo:
// Create or retrieve a JexlEngine
JexlEngine jexl = new JexlEngine();
// Create an expression object
String jexlExp = "foo.innerFoo.bar()";
Expression e = jexl.createExpression( jexlExp );
// Create a context and add data
JexlContext jctx = new MapContext();
jctx.set("foo", new Foo() );
// Now evaluate the expression, getting the result
Object o = e.evaluate(jctx);
Method 3. Evaluate expression by scripting engine
You can evaluate expression in your java code by scripting engine supported by Java platform. You are free to script the expressions in your favorite language. To show all available scripting engines in your system:
private static void availableEngine()
{
ScriptEngineManager mgr = new ScriptEngineManager();
List<ScriptEngineFactory> factories = mgr.getEngineFactories();
for (ScriptEngineFactory factory : factories)
{
System.out.println("ScriptEngineFactory Info");
String engName = factory.getEngineName();
String engVersion = factory.getEngineVersion();
String langName = factory.getLanguageName();
String langVersion = factory.getLanguageVersion();
System.out.printf("\tScript Engine: %s (%s)\n", engName, engVersion);
List<String> engNames = factory.getNames();
for (String name : engNames)
{
System.out.printf("\tEngine Alias: %s\n", name);
}
System.out.printf("\tLanguage: %s (%s)\n", langName, langVersion);
}
}
By default, JavaScript engine is included in JVM. So you can write expression in javascript with java variable support, and evaluate it in java code. Example code:
private static void jsEvalWithVariable()
{
List<String> namesList = new ArrayList<String>();
namesList.add("Jill");
namesList.add("Bob");
namesList.add("Laureen");
namesList.add("Ed");
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
jsEngine.put("namesListKey", namesList);
System.out.println("Executing in script environment...");
try
{
jsEngine.eval("var x;" +
"var names = namesListKey.toArray();" +
"for(x in names) {" +
" println(names[x]);" +
"}" +
"namesListKey.add(\"Dana\");");
}
catch (ScriptException ex)
{
ex.printStackTrace();
}
}
You can also script in groovy, ruby, python… Groovy can be well integrated with jvm, let’s take groovy as an example. Firstly include groovy 1.7.10 in pom file if you’re using maven ( or include groovy engine jar groovy-engine.jar in the classpath of the project if not using maven).
<dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy</artifactId> <version>1.7.10</version> </dependency>
Secondly write scripts in groovy, and finally evaluate them by ScriptEngine.
It is a common practice to access java variables and objects in you expressions only if you binds the variables/objects to your script engine object. You can evaluate expression in your groovy engine like this:
private static class Position
{
private int x;
private int y;
public Position(int x, int y)
{
super();
this.x = x;
this.y = y;
}
}
//require(jar:'groovy-engine.jar')
// or include any version of groovy 1.7.10 or above in your pom file
private static void groovyEval()
{
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("groovy");
if(null==engine)
{
System.err.println("Could not find groovy script engine,make sure to include groovy engine in your classpath");
}
try
{
// basic groovy expression example
System.out.println(engine.eval("(1..10).sum()"));
// example showing scripting with variables (object method invoking)
engine.put("first", "HELLO");
engine.put("second", "world");
System.out.println(engine.eval("first.toLowerCase() + second.toUpperCase()"));
//example with boolean expression
engine.put("m", 3);
engine.put("n", 9);
System.out.println(engine.eval("m<n"));
//example with variable object and object member access:
Position pos = new Position(100, 200);
engine.put("p", pos);
System.out.println(engine.eval("p.y-p.x>0"));
}
catch (ScriptException e)
{
e.printStackTrace();
}
}
Finally, if you just want to evaluate and debug complicated math expression, Math Expression Evaluator may help:
http://www.beyondlinux.com/blog/handy-utilities/math-expression-calculator/
Json and flexjson on exchanging abstract object data
JSON is a lightweight text-based open standard designed for human-readable data interchange. It is widely used in java applications as a replacement of XML. Many times we need to convert java object to json text and vice versa.
You can use Gson to convert java object to JSON format, and convert JSON into java object. And you can export your interface by JSON RPC using jsonrpc4j or json-rpc.
public class Employee
{
private String name;
private int salary;
private String dateOfBirth;
public static void main(String[] args)
{
Employee emp = new Employee();
emp.setName("david");
emp.setDateOfBirth("20080801");
Gson gson = new Gson();
String jsonString = gson.toJson(emp, Employee.class);
System.out.println(jsonString);
}
}
The output would be:
{“name”:”david”,”salary”:0,”dateOfBirth”:”20080801″}
Now you can deserialize the jsonString to an Employee object.
Employee employee = gson.fromJson(jsonString, Employee.class); System.out.println(employee.getName());
The problem with Gson is that it loses the type information on serialization, and you need to provide type information explicitly on deserialization like the above example.
How to serialize and deserialize with automatic type recognization?
Flex Json is the answer. FlexJson would add a “class” attribute in the serialized json string to represent the full qualified class name. Thus you can exchange interface/abstract object by json format. Here’s an example.
JSONSerializer serializer = new JSONSerializer();
String empString = serializer.serialize(emp);
System.out.println(empString);
JSONDeserializer<Object> deserializer = new JSONDeserializer<Object>();
Employee eee = (Employee) deserializer.deserialize(empString);
//System.out.println(eee);
The output would be like this:
{“class“:”com.beyondlinux.demo.bean.Employee”,”dateOfBirth”:”20080801″,”name”:”david”,”salary”:0}
Reference List:
http://en.wikipedia.org/wiki/JSON-RPC
http://code.google.com/p/jsonrpc4j/
http://code.google.com/p/json-rpc/
http://flexjson.sourceforge.net/
Noticeable Hacker News I Read(2011/07)
Filed under: tech watch
Post for Startup:
How to use A/B testing for better product design
Which domain registrar is best?
Why you should’nt keep your startup idea secret
How has your profession affected your non-professional thinking?
Post for Tech:
Google Running About 900,000 Servers (datacenterknowledge.com)
Stop A/B Testing and Make Out like a Bandit (untyped.com)
Why We Prefer Founding CEOs (bhorowitz.com)
Early Unix history and evolution (mit.edu)
LevelDB: A Fast Persistent Key-Value Store
Better Understanding Link-based Spam Analysis Techniques (seomoz.org)
Understanding the Git Workflow (sandofsky.com)
So you want to write a fast Python? (alexgaynor.net)
Awesome Python and django related projects (elweb.co)
Twitter Shifting More Code to JVM, Citing Performance and Encapsulation As Primary Drivers
Setting Up SSL on Tomcat in 5 minutes
JavaScript language advanced Tips & Tricks
Protocol buffer socket rpc in python/java
Akka and the java memory model
Things Everyone Should Do: Code Review (scientopia.org)
Why I read Hacker News even though I understand very little of it (alexrosen.com)
Realtime image processing in Python
http://prizes.org/
Why Every Maker Should Learn Chinese
Learn core python in one week (my way)
On Education and Life:
11 Unusual Methods for Being a Great Public Speaker (jamesaltucher.com)











