{"id":3351,"date":"2012-07-14T19:36:31","date_gmt":"2012-07-14T23:36:31","guid":{"rendered":"http:\/\/kodegeek.com\/blog\/?p=3351"},"modified":"2012-07-14T19:36:31","modified_gmt":"2012-07-14T23:36:31","slug":"calling-python-from-java-a-quick-way-to-implement-a-rule-engine","status":"publish","type":"post","link":"http:\/\/kodegeek.com\/blog\/2012\/07\/14\/calling-python-from-java-a-quick-way-to-implement-a-rule-engine\/","title":{"rendered":"Calling Python from Java, a quick way to implement a rule engine"},"content":{"rendered":"<p><a href=\"http:\/\/www.flickr.com\/photos\/josevnz\/7503992114\/\" title=\"This is a robot that my son made with some parts I was using to assemble a crib. by josevnz, on Flickr\"><img decoding=\"async\" loading=\"lazy\" src=\"http:\/\/farm9.staticflickr.com\/8165\/7503992114_bfd50e4551.jpg\" width=\"375\" height=\"500\" alt=\"This is a robot that my son made with some parts I was using to assemble a crib.\"\/><br \/>\nIt is amazing what you can build with small simple parts!<\/a><\/p>\n<p>I have the following situation at work: One of our applications gets data from a proprietary data source and the rules on how to filter the data change very often; On top of that the traders are the ones who know what is the best criteria so hard-coding this rules into Java is tedious, error prone and takes more time than it should.<\/p>\n<p>I&#8217;ve been using <a href=\"http:\/\/jython.org\">Jython<\/a> for a while and I must say I&#8217;m in love with the project. I have the flexibility of a scripting language with the ability to use all the Java libraries and also our application classes, which is something that is priceless as the majority of the code is tested and I can reuse a lot of it.<\/p>\n<p>So, what about calling Python from Java? It would be great it I can let the traders implement their own business rules (we will work together but they can prototype stuff faster that way). Also the traders I work with are very technical savvy \ud83d\ude42<\/p>\n<p>After checking the chapter &#8216;<a href=\"http:\/\/www.jython.org\/jythonbook\/en\/1.0\/JythonAndJavaIntegration.html\">Jython and Java integration<\/a>&#8216; from the Jython book I decided to experiment myself.<\/p>\n<p>For the sake of the example, I want to have a simple Python class where I receive a Map and a String and print some values:<\/p>\n<pre lang=\"python\">\r\nfrom com.kodegeek.blog.jython import HelperInt;\r\n\r\nclass Helper(HelperInt):\r\n\r\n        def doSomething(self, data, name):\r\n\r\n                if name == None:\r\n                        raise Exception(\"Name is missing!\")\r\n\r\n                if data == None:\r\n                        raise Exception(\"No data was provided!\")\r\n\r\n                print \"Hello, my name is: %s\" % name\r\n                if data.containsKey('age'):\r\n                        age = data.get('age')\r\n                        if age > 21:\r\n                                print \"%s, you can also have a beer!\" % name\r\n                        else:\r\n                                print \"%s, it is time for your milshake :-)\" % name\r\n<\/pre>\n<p>So far is good, but who is the class &#8216;HelperInt&#8217;? Is an interface and that will help us to glue our Python class into the Java world:<\/p>\n<pre lang=\"Java\">\r\npackage com.kodegeek.blog.jython;\r\n\r\nimport java.util.Map;\r\n\r\npublic interface HelperInt {\r\n\r\n        public void doSomething(Map data, String name);\r\n\r\n}\r\n<\/pre>\n<p>Nothing weird so far, uh?. Now the most complicated part is to bring the Jython implementation back into the Java world. The book give us a really nice Singleton Factory class that I used as is (the code is below, but I strongly suggest you read the book explanation on how it works. It seems there are many ways to skin this cat):<\/p>\n<pre lang=\"Java\">\r\npackage com.kodegeek.blog.jython;\r\n\r\nimport org.python.core.Py;\r\nimport org.python.core.PyObject;\r\nimport org.python.core.PySystemState;\r\n\r\n\/**\r\n * Jython Object Factory using PySystemState\r\n *\/\r\npublic class JythonObjectFactory {\r\n\r\n private final Class interfaceType;\r\n private final PyObject klass;\r\n\r\n \/\/ Constructor obtains a reference to the importer, module, and the class name\r\n public JythonObjectFactory(PySystemState state, Class interfaceType, String moduleName, String className) {\r\n     this.interfaceType = interfaceType;\r\n     PyObject importer = state.getBuiltins().__getitem__(Py.newString(\"__import__\"));\r\n     PyObject module = importer.__call__(Py.newString(moduleName));\r\n     klass = module.__getattr__(className);\r\n     System.err.println(\"module=\" + module + \",class=\" + klass);\r\n }\r\n\r\n \/\/ This constructor passes through to the other constructor\r\n public JythonObjectFactory(Class interfaceType, String moduleName, String className) {\r\n     this(new PySystemState(), interfaceType, moduleName, className);\r\n }\r\n\r\n \/\/ All of the followng methods return\r\n \/\/ a coerced Jython object based upon the pieces of information\r\n \/\/ that were passed into the factory. The differences are\r\n \/\/ between them are the number of arguments that can be passed\r\n \/\/ in as arguents to the object.\r\n\r\n public Object createObject() {\r\n     return klass.__call__().__tojava__(interfaceType);\r\n }\r\n\r\n\r\n public Object createObject(Object arg1) {\r\n     return klass.__call__(Py.java2py(arg1)).__tojava__(interfaceType);\r\n }\r\n\r\n public Object createObject(Object arg1, Object arg2) {\r\n     return klass.__call__(Py.java2py(arg1), Py.java2py(arg2)).__tojava__(interfaceType);\r\n }\r\n\r\n public Object createObject(Object arg1, Object arg2, Object arg3)\r\n {\r\n     return klass.__call__(Py.java2py(arg1), Py.java2py(arg2),\r\n         Py.java2py(arg3)).__tojava__(interfaceType);\r\n }\r\n\r\n public Object createObject(Object args[], String keywords[]) {\r\n     PyObject convertedArgs[] = new PyObject[args.length];\r\n     for (int i = 0; i < args.length; i++) {\r\n         convertedArgs[i] = Py.java2py(args[i]);\r\n     }\r\n\r\n     return klass.__call__(convertedArgs, keywords).__tojava__(interfaceType);\r\n }\r\n\r\n public Object createObject(Object... args) {\r\n     return createObject(args, Py.NoKeywords);\r\n }\r\n<\/pre>\n<p>The last piece of the puzzle is our application, which calls the factory and then the Python object from Java:<\/p>\n<pre lang=\"Java\">\r\npackage com.kodegeek.blog.app;\r\n\r\nimport java.util.Map;\r\nimport java.util.HashMap;\r\n\r\nimport com.kodegeek.blog.jython.HelperInt;\r\nimport com.kodegeek.blog.jython.JythonObjectFactory;\r\n\r\npublic final class Caller {\r\n\r\n        public static void main(final String [] args) throws Exception {\r\n\r\n                JythonObjectFactory factory = new JythonObjectFactory(HelperInt.class, \"JHelper\", \"Helper\");\r\n                HelperInt helper = (HelperInt) factory.createObject();\r\n                Map<string , Integer> data = new HashMap<\/string><string , Integer>();\r\n                data.put(\"age\", 39);\r\n                String name = \"Jose Vicente\";\r\n                helper.doSomething(data, name);\r\n        }\r\n\r\n}\r\n<\/string><\/pre>\n<p>Time to compile and run the stuff. As usual, make sure you have Jython on the Classpath:<\/p>\n<pre lang=\"Bash\">\r\nMacintosh:jython josevnz$ javac -classpath \/users\/Shared\/jython2.5.2\/jython.jar:. -d . *.java\r\nMacintosh:jython josevnz$ \r\nMacintosh:jython josevnz$ java -classpath \/users\/Shared\/jython2.5.2\/jython.jar:. com.kodegeek.blog.app.Caller\r\n*sys-package-mgr*: processing new jar, '\/Library\/Java\/JavaVirtualMachines\/1.7.0.jdk\/Contents\/Home\/jre\/lib\/resources.jar'\r\n*sys-package-mgr*: processing new jar, '\/Library\/Java\/JavaVirtualMachines\/1.7.0.jdk\/Contents\/Home\/jre\/lib\/ext\/zipfs.jar'\r\nmodule=<module 'JHelper' from '__pyclasspath__\/JHelper.py'>,class=<class 'JHelper.Helper'>\r\nHello, my name is: Jose Vicente\r\nJose Vicente, you can also have a beer!\r\n<\/class><\/module><\/pre>\n<p>Success!. Let&#8217;s see how far I can get with this on a real application \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It is amazing what you can build with small simple parts! I have the following situation at work: One of our applications gets data from a proprietary data source and the rules on how to filter the data change very often; On top of that the traders are the ones who know what is the <a class=\"read-more\" href=\"http:\/\/kodegeek.com\/blog\/2012\/07\/14\/calling-python-from-java-a-quick-way-to-implement-a-rule-engine\/\">[&hellip;]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[9,194,438,239],"tags":[724,757,321,765],"_links":{"self":[{"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/posts\/3351"}],"collection":[{"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/comments?post=3351"}],"version-history":[{"count":11,"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/posts\/3351\/revisions"}],"predecessor-version":[{"id":3362,"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/posts\/3351\/revisions\/3362"}],"wp:attachment":[{"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/media?parent=3351"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/categories?post=3351"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/tags?post=3351"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}