Paul Thwaite – Java 8 Quality Assurance Engineer Monday 1 October 2012 How to embed your scripting language JavaOne 2012 - CON3978 © 2012 IBM Corporation
Important Disclaimers THE INFORMATION CONTAINED IN THIS PRESENTATION IS PROVIDED FOR INFORMATIONAL PURPOSES ONLY. WHILST EFFORTS WERE MADE TO VERIFY THE COMPLETENESS AND ACCURACY OF THE INFORMATION CONTAINED IN THIS PRESENTATION, IT IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. ALL PERFORMANCE DATA INCLUDED IN THIS PRESENTATION HAVE BEEN GATHERED IN A CONTROLLED ENVIRONMENT. YOUR OWN TEST RESULTS MAY VARY BASED ON HARDWARE, SOFTWARE OR INFRASTRUCTURE DIFFERENCES. ALL DATA INCLUDED IN THIS PRESENTATION ARE MEANT TO BE USED ONLY AS A GUIDE. IN ADDITION, THE INFORMATION CONTAINED IN THIS PRESENTATION IS BASED ON IBM’S CURRENT PRODUCT PLANS AND STRATEGY, WHICH ARE SUBJECT TO CHANGE BY IBM, WITHOUT NOTICE. IBM AND ITS AFFILIATED COMPANIES SHALL NOT BE RESPONSIBLE FOR ANY DAMAGES ARISING OUT OF THE USE OF, OR OTHERWISE RELATED TO, THIS PRESENTATION OR ANY OTHER DOCUMENTATION. NOTHING CONTAINED IN THIS PRESENTATION IS INTENDED TO, OR SHALL HAVE THE EFFECT OF: - CREATING ANY WARRANT OR REPRESENTATION FROM IBM, ITS AFFILIATED COMPANIES OR ITS OR THEIR SUPPLIERS AND/OR LICENSORS 2 © 2012 IBM Corporation
Introduction to the speaker – Paul Thwaite ■ 11 years experience developing and deploying Java SDKs ■ Recent work focus: – Quality Assurance specialist • Leading cross-continent teams • System Test on IBM SDKs – Quality assurance lead for Java 8 • Focus on testing in OpenJDK • OpenJDK contributor ■ My contact information: – paul_thwaite@uk.ibm.com – linkedin.com/profile/view?id=26327969 3 © 2012 IBM Corporation
What you will learn from this talk ■ Why me and what I do ■ Why we run scripting languages on the JVM ■ Methods of embedding ■ Models of embedding ■ Comparison of two embedding frameworks ■ Which approach is best 4 © 2012 IBM Corporation
Why me and what I do ■ Test IBM's Java SDK – I break Java ■ Focus on system testing in QA – Multi-threaded load testing – Third-party applications ■ Increasing use of scripting languages running on the JVM – We need to ensure they run on the IBM SDK 5 © 2012 IBM Corporation
How many languages run on the JVM? 6 © 2012 IBM Corporation
How many languages run on the JVM? >800 >60 total active http://en.wikipedia.org/wiki/List_of_JVM_languages 7 © 2012 IBM Corporation
How many languages run on the JVM? Most popular include 8 © 2012 IBM Corporation
JavaScript How many languages run on the JVM? Most popular include 9 © 2012 IBM Corporation
How many languages run on the JVM? Why is the JVM so popular? 10 © 2012 IBM Corporation
Why is the JVM so popular? The JVM is fast ■ Runtime performance benefits ■ Threading and scaling support ■ JVM profiling tools ■ Access to the impressive array of Java APIs ■ Support for multiple languages 11 © 2012 IBM Corporation
How many languages run on the JVM? Let's examine a few implementation methods 12 © 2012 IBM Corporation
Implementation Methods ■ Compiled to bytecodes – Jython – Groovy – Scala 13 © 2012 IBM Corporation
Implementation Methods ■ Compiled to bytecodes – Jython – Groovy – Scala ■ Interpreted on the JVM – JavaScript – JRuby 14 © 2012 IBM Corporation
Implementation Methods ■ Compiled to bytecodes – Jython – Groovy – Scala ■ Interpreted on the JVM – JavaScript – JRuby ■ Embedded in a Java application on the JVM – Jython – Groovy – Scala – JavaScript – JRuby 15 © 2012 IBM Corporation
Compiled to bytecodes Compiling a Jython script to bytecodes and running it on the JVM MyJythonApp.py Jythonc MyJythonApp.class Compiler JVM MyJythonApp 16 © 2012 IBM Corporation
Interpreted on the JVM Interpreting a JRuby script on the JVM JVM JRuby Java JRuby.rb Interpreter The JRuby language provides the interpreter in Java 17 © 2012 IBM Corporation
Embedding in a Java application Embedding and running a JRuby script inside a Java application on the JVM JVM Ruby.rb JRuby MyJavaApp.class Embed Engine The language provides the embed engine 18 © 2012 IBM Corporation
Embedding in a Java application – multiple scripts Embedding and running multiple scripts inside a Java application on the JVM JVM Ruby.rb JRuby JRuby.rb JRuby Embed Engine Embed Engine MyJavaApp.class Javascript Ruby.rb JavaScript JavaScript.js Embed Engine Embed Engine The language provides the embed engine 19 © 2012 IBM Corporation
Scripting on the JVM Models 20 © 2012 IBM Corporation
Scripting on the JVM - Models Script Java JVM Java Script JVM Java Script JVM 21 © 2012 IBM Corporation
Scripting on the JVM – Script domain knowledge Language-specifc ■ Java objects are created and used from inside the Script script Java JVM ■ Requires – Scripting language knowledge to implement require 'java' Java objects frame = javax.swing.JFrame.new("Window") – Java knowledge label = javax.swing.JLabel.new("Hello") frame.getContentPane.add(label) frame.setDefaultCloseOperation ■ Limited re-use capabilities (javax.swing.JFrame::EXIT_ON_CLOSE) – Not portable code frame.pack – Locked in to using the frame.setVisible(true) chosen scripting language 22 © 2012 IBM Corporation
Scripting on the JVM – Java domain knowledge Bridge ■ Java runs a script which is embedded within the Java Java application Script ■ The APIs used to invoke the script belong to the scripting JVM language import org.jruby.embed.*; ■ Requires ScriptingContainer container = new – Java knowledge ScriptingContainer(); – Language embed API container.runScriptlet(PathType.RELATIVE, knowledge – Bridging knowledge "myscripts/ruby.rb"); ■ Re-use existing scripts – Optional bridge for legacy scripts – Investment in using chosen scripting language 23 © 2012 IBM Corporation
Scripting on the JVM – Java and script domain knowledge ■ Options – Invoke a script from a Java Script Java application – Create and use Java objects inside a script JVM ■ Requires import javax.script.*; – Java knowledge ScriptEngineManager engineMgr = new ScriptEngineManager(); – Knowledge of the JSR ScriptEngine engine = engineMgr.getEngineByName("jruby"); 223 API InputStream is = – Some knowledge of the this.getClass().getResourceAsStream("/myscripts/ruby.rb"); scripting language may Reader reader = new InputStreamReader(is); be required engine.eval(reader); ■ Re-use existing scripts – Support for multiple scripts 24 © 2012 IBM Corporation
What is embedding? 25 © 2012 IBM Corporation
Embedding in a Java application – multiple scripts Embedding and running multiple scripts inside a Java application on the JVM JVM Ruby.rb JRuby Ruby.rb JRuby Embed Engine Embed Engine MyJavaApp.class Javascript Ruby.rb JavaScript JavaScript.js Embed Engine Embed Engine The language provides the embed engine 26 © 2012 IBM Corporation
What can you do with an embedded language? Pass variables to the script Retrieve variables from the script Run a script Embedding Call a script's function and retrieve its Configure script return value environment Run multiple scripts on the same JVM 27 © 2012 IBM Corporation
Ways to embed a scripting language on the JVM JSR 223 Language-specific javax.script Embed Implementations Implementations ● A common API for embedding ● Implementation provided by the multiple languages language ● Implementation provided by the ● Similar to JSR223 language ● Extensions available ● Some popular languages provide ● Ability to fine-tune the scripting a javax.script API environment ● Most popular languages provide an embed API 28 © 2012 IBM Corporation
Comparison of embedding frameworks JSR 223 Language-specific javax.script Embed vs Implementations Implementations ■ Introduction to javax.script ■ Code examples using these languages – Jruby – Jython – Groovy ■ Exception handling may be missed off some examples to save space 29 © 2012 IBM Corporation
What is javax.script? JSR 223 Scripting for the Java Platform ■ Allows a developer to embed a scripting language in a Java application ■ Available from Java 6 SE ■ Implementation provided by the scripting language ■ JSR 223 specification defines 6 interfaces – ScriptEngine – ScriptEngineFactory – ScriptContext – Bindings – Invocable – Compilable ■ Setup – Download the JSR 223 implementation from your language provider's website – Add the jar(s) to the CLASSPATH – Add your script directory to the CLASSPATH ■ ScriptEngine is discovered at runtime via the JAR services mechanism 30 © 2012 IBM Corporation
Example: Query JAR services for installed JSR223 Java Scripting Engines JSR 223 import javax.script.*; public class ListScriptEngines { public static void main(String[] args) { ScriptEngineManager mgr = new ScriptEngineManager(); List<ScriptEngineFactory> factories = mgr.getEngineFactories(); for (ScriptEngineFactory factory: factories) { String engName = factory.getEngineName(); String engVersion = factory.getEngineVersion(); System.out.println("Script Engine: " + engName + " V" + engVersion); } } } Output to stdout: Script Engine: Groovy Scripting Engine V2.0 Script Engine: jython V2.5.3 Script Engine: JSR 223 JRuby Engine V1.6.7.2 Script Engine: Mozilla Rhino V1.7 release 3 PRERELEASE 31 © 2012 IBM Corporation
Example: Embedding a Ruby script into a Java application JSR 223 - JRuby import javax.script.*; ScriptEngineManager engineMgr = new ScriptEngineManager(); ScriptEngine engine = engineMgr.getEngineByName("jruby"); InputStream is = this.getClass().getResourceAsStream("/myscripts/ruby.rb"); Reader reader = new InputStreamReader(is); engine.eval(reader); //throws ScriptException JRuby Embed API import org.jruby.embed.*; ScriptingContainer container = new ScriptingContainer(); container.runScriptlet(PathType.RELATIVE, "myscripts/ruby.rb"); Script: /myscripts/ruby.rb Output to stdout: stringHello = "Hello, I am a jruby script!" Hello, I am a ruby script!" puts "#{stringHello.to_s}" 32 © 2012 IBM Corporation
Example: Passing a variable to a Jython script and retrieving it back again JSR 223 - Jython import javax.script.*; ScriptEngineManager engineMgr = new ScriptEngineManager(); ScriptEngine engine = engineMgr.getEngineByName("jython"); InputStream is = this.getClass().getResourceAsStream("/myscripts/jython_var.py"); Reader reader = new InputStreamReader(is); try { engine.put("javaString", "red green blue"); engine.eval(reader); System.out.println("java> received " + engine.get("javaString")); } catch (ScriptException e) {} Jython Embed API import org.python.util.PythonInterpreter; PythonInterpreter python = new PythonInterpreter(); python.set ( "javaString", new org.python.core.PyString("red green blue")); python.execfile ( "myscripts/jython_var.py" ); System.out.println("java> received " + python.get ("javaString")); Script: /myscripts/jython_var.py Output to stdout: print "jython> received " + javaString jython> received red green blue javaString += " yellow indigo white" java> received red green blue 33 yellow indigo white © 2012 IBM Corporation
Example: Invoke a Groovy function with a return value JSR 223 - Groovy ScriptEngineManager engineMgr = new ScriptEngineManager(); ScriptEngine engine = engineMgr.getEngineByName("groovy"); InputStream is = this.getClass().getResourceAsStream("/myscripts/groovy_func.groovy"); Reader reader = new InputStreamReader(is); if (engine instanceof Invocable) { //Invocable is an optional interface Invocable invocableEngine = (Invocable) engine; engine.eval(reader); System.out.println("java> What's the Square root of 360?"); double squareRoot = (double) invocableEngine.invokeFunction("squareRoot", 360); System.out.println("java> " + squareRoot); } Groovy Embed API String[] roots = new String[] { "C:scripts" }; GroovyScriptEngine gse = new GroovyScriptEngine(roots); Class<?> groovyClass = gse.loadScriptByName("groovy_func.groovy"); GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance(); System.out.println("java> What's the square root of 360?"); System.out.println("java> " + groovyObject.invokeMethod("squareRoot", 360).toString()); Script: /myscripts/groovy_func.groovy Output to stdout: def squareRoot(number) { java> What's the square root of 360? println "groovy> Sqrt of ${number} is" groovy> Sqrt of 360 is Math.sqrt(number) java> 18.973665961010276 } 34 © 2012 IBM Corporation
Example: How to set options in JRuby ■ JRuby provides many options to the developer to allow for the JRuby ScriptEngine to be customised and finely-tuned ■ In JRuby, these options are set using SystemProperty – Outside the spec of JSR 223 – Requires language-specific knowledge // Make JRuby's engine thread safe System.setProperty("org.jruby.embed.localcontext.scope", “threadsafe”); // Turn on JIT verbose logging System.setProperty("jruby.jit.logging.verbose", “true”); // Set JRuby home System.setProperty("jruby.home", “/path/to/jruby”); 35 © 2012 IBM Corporation
Example: Comparison of setting options in JRuby // JRuby EmbedCore API // Make JRuby's engine thread safe // Set via a constructor argument of Scriptingcontainer ScriptingContainer instance = new ScriptingContainer(LocalContextScope.THREADSAFE); // JSR 223 API // Make JRuby's engine thread safe System.setProperty("org.jruby.embed.localcontext.scope", “threadsafe”); ■ Jruby's EmbedCore API – Set on a per engine basis – Well documented and easy to find ■ Javax.script API – Set system wide – Multiple engines will all have the same behaviour – Harder to find documentation (not part of an API) 36 © 2012 IBM Corporation
Example: Comparison of setting options in Groovy // Groovy Embed API // Set the compiler warning message level CompilerConfiguration.setWarningLevel(int warningLevel); // JSR 223 API // Set the compiler warning message level No easy way to do it 37 © 2012 IBM Corporation
How far does javax.script go? ■ Provides useful interaction between Java and many scripting languages – Plug 'n Play support for multiple languages – Great for simple embedding – Easy-to-use API ■ Limitations – The Invocable and Compilable interfaces are optional – Setting language-specific options removes the abstraction JSR 223 provides – Not all engines will provide the same configuration options – Requires knowledge of the underlying ScriptEngine implementation beyond JSR 223 38 © 2012 IBM Corporation
Scripting on the JVM is great ■ Some of the most popular languages support Java embedding ■ Embedding a language in a new application is easy to get started ■ Deciding how to embed has consequences –JSR 223 is a great framework for basic embedding –If you need to harness the power of the language, you will need to use the language API • For example, JRuby Embed Core ■ How are you embedding your scripting language on the JVM? 39 © 2012 IBM Corporation
References ■ JSR 223 – JSR 223 specification • http://www.jcp.org/en/jsr/detail?id=223 – JRuby implementation • http://kenai.com/projects/jruby/pages/JavaIntegration – Groovy implementation • http://groovy.codehaus.org/JSR+223+Scripting+with+Groovy ■ Jython Java Integration – http://www.jython.org/jythonbook/en/1.0/JythonAndJavaIntegration.html ■ Scripting in Java: Languages, Frameworks, and Patterns – Dejan Bosanac, Addison-Wesley 40 © 2012 IBM Corporation
References ■ Get Products and Technologies: – IBM Java Runtimes and SDKs: • https://www.ibm.com/developerworks/java/jdk/ – IBM Monitoring and Diagnostic Tools for Java: • https://www.ibm.com/developerworks/java/jdk/tools/ ■ Learn: – IBM Java InfoCenter: • http://publib.boulder.ibm.com/infocenter/java7sdk/v7r0/index.jsp ■ Discuss: – IBM Java Runtimes and SDKs Forum: • http://www.ibm.com/developerworks/forums/forum.jspa?forumID=367&start=0 41 © 2012 IBM Corporation
Copyright and Trademarks © IBM Corporation 2011. All Rights Reserved. IBM, the IBM logo, and ibm.com are trademarks or registered trademarks of International Business Machines Corp., and registered in many jurisdictions worldwide. Other product and service names might be trademarks of IBM or other companies. A current list of IBM trademarks is available on the Web – see the IBM “Copyright and trademark information” page at URL: www.ibm.com/legal/copytrade.shtml 42 © 2012 IBM Corporation

JavaOne 2012 CON3978 Scripting Languages on the JVM

  • 1.
    Paul Thwaite –Java 8 Quality Assurance Engineer Monday 1 October 2012 How to embed your scripting language JavaOne 2012 - CON3978 © 2012 IBM Corporation
  • 2.
    Important Disclaimers THE INFORMATIONCONTAINED IN THIS PRESENTATION IS PROVIDED FOR INFORMATIONAL PURPOSES ONLY. WHILST EFFORTS WERE MADE TO VERIFY THE COMPLETENESS AND ACCURACY OF THE INFORMATION CONTAINED IN THIS PRESENTATION, IT IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. ALL PERFORMANCE DATA INCLUDED IN THIS PRESENTATION HAVE BEEN GATHERED IN A CONTROLLED ENVIRONMENT. YOUR OWN TEST RESULTS MAY VARY BASED ON HARDWARE, SOFTWARE OR INFRASTRUCTURE DIFFERENCES. ALL DATA INCLUDED IN THIS PRESENTATION ARE MEANT TO BE USED ONLY AS A GUIDE. IN ADDITION, THE INFORMATION CONTAINED IN THIS PRESENTATION IS BASED ON IBM’S CURRENT PRODUCT PLANS AND STRATEGY, WHICH ARE SUBJECT TO CHANGE BY IBM, WITHOUT NOTICE. IBM AND ITS AFFILIATED COMPANIES SHALL NOT BE RESPONSIBLE FOR ANY DAMAGES ARISING OUT OF THE USE OF, OR OTHERWISE RELATED TO, THIS PRESENTATION OR ANY OTHER DOCUMENTATION. NOTHING CONTAINED IN THIS PRESENTATION IS INTENDED TO, OR SHALL HAVE THE EFFECT OF: - CREATING ANY WARRANT OR REPRESENTATION FROM IBM, ITS AFFILIATED COMPANIES OR ITS OR THEIR SUPPLIERS AND/OR LICENSORS 2 © 2012 IBM Corporation
  • 3.
    Introduction to thespeaker – Paul Thwaite ■ 11 years experience developing and deploying Java SDKs ■ Recent work focus: – Quality Assurance specialist • Leading cross-continent teams • System Test on IBM SDKs – Quality assurance lead for Java 8 • Focus on testing in OpenJDK • OpenJDK contributor ■ My contact information: – paul_thwaite@uk.ibm.com – linkedin.com/profile/view?id=26327969 3 © 2012 IBM Corporation
  • 4.
    What you willlearn from this talk ■ Why me and what I do ■ Why we run scripting languages on the JVM ■ Methods of embedding ■ Models of embedding ■ Comparison of two embedding frameworks ■ Which approach is best 4 © 2012 IBM Corporation
  • 5.
    Why me andwhat I do ■ Test IBM's Java SDK – I break Java ■ Focus on system testing in QA – Multi-threaded load testing – Third-party applications ■ Increasing use of scripting languages running on the JVM – We need to ensure they run on the IBM SDK 5 © 2012 IBM Corporation
  • 6.
    How many languages run on the JVM? 6 © 2012 IBM Corporation
  • 7.
    How many languages run on the JVM? >800 >60 total active http://en.wikipedia.org/wiki/List_of_JVM_languages 7 © 2012 IBM Corporation
  • 8.
    How many languages run on the JVM? Most popular include 8 © 2012 IBM Corporation
  • 9.
    JavaScript How many languages run on the JVM? Most popular include 9 © 2012 IBM Corporation
  • 10.
    How many languages run on the JVM? Why is the JVM so popular? 10 © 2012 IBM Corporation
  • 11.
    Why is theJVM so popular? The JVM is fast ■ Runtime performance benefits ■ Threading and scaling support ■ JVM profiling tools ■ Access to the impressive array of Java APIs ■ Support for multiple languages 11 © 2012 IBM Corporation
  • 12.
    How many languages run on the JVM? Let's examine a few implementation methods 12 © 2012 IBM Corporation
  • 13.
    Implementation Methods ■ Compiled to bytecodes – Jython – Groovy – Scala 13 © 2012 IBM Corporation
  • 14.
    Implementation Methods ■ Compiled to bytecodes – Jython – Groovy – Scala ■ Interpreted on the JVM – JavaScript – JRuby 14 © 2012 IBM Corporation
  • 15.
    Implementation Methods ■ Compiled to bytecodes – Jython – Groovy – Scala ■ Interpreted on the JVM – JavaScript – JRuby ■ Embedded in a Java application on the JVM – Jython – Groovy – Scala – JavaScript – JRuby 15 © 2012 IBM Corporation
  • 16.
    Compiled to bytecodes Compilinga Jython script to bytecodes and running it on the JVM MyJythonApp.py Jythonc MyJythonApp.class Compiler JVM MyJythonApp 16 © 2012 IBM Corporation
  • 17.
    Interpreted on theJVM Interpreting a JRuby script on the JVM JVM JRuby Java JRuby.rb Interpreter The JRuby language provides the interpreter in Java 17 © 2012 IBM Corporation
  • 18.
    Embedding in aJava application Embedding and running a JRuby script inside a Java application on the JVM JVM Ruby.rb JRuby MyJavaApp.class Embed Engine The language provides the embed engine 18 © 2012 IBM Corporation
  • 19.
    Embedding in aJava application – multiple scripts Embedding and running multiple scripts inside a Java application on the JVM JVM Ruby.rb JRuby JRuby.rb JRuby Embed Engine Embed Engine MyJavaApp.class Javascript Ruby.rb JavaScript JavaScript.js Embed Engine Embed Engine The language provides the embed engine 19 © 2012 IBM Corporation
  • 20.
    Scripting on theJVM Models 20 © 2012 IBM Corporation
  • 21.
    Scripting on theJVM - Models Script Java JVM Java Script JVM Java Script JVM 21 © 2012 IBM Corporation
  • 22.
    Scripting on theJVM – Script domain knowledge Language-specifc ■ Java objects are created and used from inside the Script script Java JVM ■ Requires – Scripting language knowledge to implement require 'java' Java objects frame = javax.swing.JFrame.new("Window") – Java knowledge label = javax.swing.JLabel.new("Hello") frame.getContentPane.add(label) frame.setDefaultCloseOperation ■ Limited re-use capabilities (javax.swing.JFrame::EXIT_ON_CLOSE) – Not portable code frame.pack – Locked in to using the frame.setVisible(true) chosen scripting language 22 © 2012 IBM Corporation
  • 23.
    Scripting on theJVM – Java domain knowledge Bridge ■ Java runs a script which is embedded within the Java Java application Script ■ The APIs used to invoke the script belong to the scripting JVM language import org.jruby.embed.*; ■ Requires ScriptingContainer container = new – Java knowledge ScriptingContainer(); – Language embed API container.runScriptlet(PathType.RELATIVE, knowledge – Bridging knowledge "myscripts/ruby.rb"); ■ Re-use existing scripts – Optional bridge for legacy scripts – Investment in using chosen scripting language 23 © 2012 IBM Corporation
  • 24.
    Scripting on theJVM – Java and script domain knowledge ■ Options – Invoke a script from a Java Script Java application – Create and use Java objects inside a script JVM ■ Requires import javax.script.*; – Java knowledge ScriptEngineManager engineMgr = new ScriptEngineManager(); – Knowledge of the JSR ScriptEngine engine = engineMgr.getEngineByName("jruby"); 223 API InputStream is = – Some knowledge of the this.getClass().getResourceAsStream("/myscripts/ruby.rb"); scripting language may Reader reader = new InputStreamReader(is); be required engine.eval(reader); ■ Re-use existing scripts – Support for multiple scripts 24 © 2012 IBM Corporation
  • 25.
    What is embedding? 25 © 2012 IBM Corporation
  • 26.
    Embedding in aJava application – multiple scripts Embedding and running multiple scripts inside a Java application on the JVM JVM Ruby.rb JRuby Ruby.rb JRuby Embed Engine Embed Engine MyJavaApp.class Javascript Ruby.rb JavaScript JavaScript.js Embed Engine Embed Engine The language provides the embed engine 26 © 2012 IBM Corporation
  • 27.
    What can youdo with an embedded language? Pass variables to the script Retrieve variables from the script Run a script Embedding Call a script's function and retrieve its Configure script return value environment Run multiple scripts on the same JVM 27 © 2012 IBM Corporation
  • 28.
    Ways to embeda scripting language on the JVM JSR 223 Language-specific javax.script Embed Implementations Implementations ● A common API for embedding ● Implementation provided by the multiple languages language ● Implementation provided by the ● Similar to JSR223 language ● Extensions available ● Some popular languages provide ● Ability to fine-tune the scripting a javax.script API environment ● Most popular languages provide an embed API 28 © 2012 IBM Corporation
  • 29.
    Comparison of embeddingframeworks JSR 223 Language-specific javax.script Embed vs Implementations Implementations ■ Introduction to javax.script ■ Code examples using these languages – Jruby – Jython – Groovy ■ Exception handling may be missed off some examples to save space 29 © 2012 IBM Corporation
  • 30.
    What is javax.script? JSR 223 Scripting for the Java Platform ■ Allows a developer to embed a scripting language in a Java application ■ Available from Java 6 SE ■ Implementation provided by the scripting language ■ JSR 223 specification defines 6 interfaces – ScriptEngine – ScriptEngineFactory – ScriptContext – Bindings – Invocable – Compilable ■ Setup – Download the JSR 223 implementation from your language provider's website – Add the jar(s) to the CLASSPATH – Add your script directory to the CLASSPATH ■ ScriptEngine is discovered at runtime via the JAR services mechanism 30 © 2012 IBM Corporation
  • 31.
    Example: Query JARservices for installed JSR223 Java Scripting Engines JSR 223 import javax.script.*; public class ListScriptEngines { public static void main(String[] args) { ScriptEngineManager mgr = new ScriptEngineManager(); List<ScriptEngineFactory> factories = mgr.getEngineFactories(); for (ScriptEngineFactory factory: factories) { String engName = factory.getEngineName(); String engVersion = factory.getEngineVersion(); System.out.println("Script Engine: " + engName + " V" + engVersion); } } } Output to stdout: Script Engine: Groovy Scripting Engine V2.0 Script Engine: jython V2.5.3 Script Engine: JSR 223 JRuby Engine V1.6.7.2 Script Engine: Mozilla Rhino V1.7 release 3 PRERELEASE 31 © 2012 IBM Corporation
  • 32.
    Example: Embedding aRuby script into a Java application JSR 223 - JRuby import javax.script.*; ScriptEngineManager engineMgr = new ScriptEngineManager(); ScriptEngine engine = engineMgr.getEngineByName("jruby"); InputStream is = this.getClass().getResourceAsStream("/myscripts/ruby.rb"); Reader reader = new InputStreamReader(is); engine.eval(reader); //throws ScriptException JRuby Embed API import org.jruby.embed.*; ScriptingContainer container = new ScriptingContainer(); container.runScriptlet(PathType.RELATIVE, "myscripts/ruby.rb"); Script: /myscripts/ruby.rb Output to stdout: stringHello = "Hello, I am a jruby script!" Hello, I am a ruby script!" puts "#{stringHello.to_s}" 32 © 2012 IBM Corporation
  • 33.
    Example: Passing avariable to a Jython script and retrieving it back again JSR 223 - Jython import javax.script.*; ScriptEngineManager engineMgr = new ScriptEngineManager(); ScriptEngine engine = engineMgr.getEngineByName("jython"); InputStream is = this.getClass().getResourceAsStream("/myscripts/jython_var.py"); Reader reader = new InputStreamReader(is); try { engine.put("javaString", "red green blue"); engine.eval(reader); System.out.println("java> received " + engine.get("javaString")); } catch (ScriptException e) {} Jython Embed API import org.python.util.PythonInterpreter; PythonInterpreter python = new PythonInterpreter(); python.set ( "javaString", new org.python.core.PyString("red green blue")); python.execfile ( "myscripts/jython_var.py" ); System.out.println("java> received " + python.get ("javaString")); Script: /myscripts/jython_var.py Output to stdout: print "jython> received " + javaString jython> received red green blue javaString += " yellow indigo white" java> received red green blue 33 yellow indigo white © 2012 IBM Corporation
  • 34.
    Example: Invoke aGroovy function with a return value JSR 223 - Groovy ScriptEngineManager engineMgr = new ScriptEngineManager(); ScriptEngine engine = engineMgr.getEngineByName("groovy"); InputStream is = this.getClass().getResourceAsStream("/myscripts/groovy_func.groovy"); Reader reader = new InputStreamReader(is); if (engine instanceof Invocable) { //Invocable is an optional interface Invocable invocableEngine = (Invocable) engine; engine.eval(reader); System.out.println("java> What's the Square root of 360?"); double squareRoot = (double) invocableEngine.invokeFunction("squareRoot", 360); System.out.println("java> " + squareRoot); } Groovy Embed API String[] roots = new String[] { "C:scripts" }; GroovyScriptEngine gse = new GroovyScriptEngine(roots); Class<?> groovyClass = gse.loadScriptByName("groovy_func.groovy"); GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance(); System.out.println("java> What's the square root of 360?"); System.out.println("java> " + groovyObject.invokeMethod("squareRoot", 360).toString()); Script: /myscripts/groovy_func.groovy Output to stdout: def squareRoot(number) { java> What's the square root of 360? println "groovy> Sqrt of ${number} is" groovy> Sqrt of 360 is Math.sqrt(number) java> 18.973665961010276 } 34 © 2012 IBM Corporation
  • 35.
    Example: How toset options in JRuby ■ JRuby provides many options to the developer to allow for the JRuby ScriptEngine to be customised and finely-tuned ■ In JRuby, these options are set using SystemProperty – Outside the spec of JSR 223 – Requires language-specific knowledge // Make JRuby's engine thread safe System.setProperty("org.jruby.embed.localcontext.scope", “threadsafe”); // Turn on JIT verbose logging System.setProperty("jruby.jit.logging.verbose", “true”); // Set JRuby home System.setProperty("jruby.home", “/path/to/jruby”); 35 © 2012 IBM Corporation
  • 36.
    Example: Comparison ofsetting options in JRuby // JRuby EmbedCore API // Make JRuby's engine thread safe // Set via a constructor argument of Scriptingcontainer ScriptingContainer instance = new ScriptingContainer(LocalContextScope.THREADSAFE); // JSR 223 API // Make JRuby's engine thread safe System.setProperty("org.jruby.embed.localcontext.scope", “threadsafe”); ■ Jruby's EmbedCore API – Set on a per engine basis – Well documented and easy to find ■ Javax.script API – Set system wide – Multiple engines will all have the same behaviour – Harder to find documentation (not part of an API) 36 © 2012 IBM Corporation
  • 37.
    Example: Comparison ofsetting options in Groovy // Groovy Embed API // Set the compiler warning message level CompilerConfiguration.setWarningLevel(int warningLevel); // JSR 223 API // Set the compiler warning message level No easy way to do it 37 © 2012 IBM Corporation
  • 38.
    How far doesjavax.script go? ■ Provides useful interaction between Java and many scripting languages – Plug 'n Play support for multiple languages – Great for simple embedding – Easy-to-use API ■ Limitations – The Invocable and Compilable interfaces are optional – Setting language-specific options removes the abstraction JSR 223 provides – Not all engines will provide the same configuration options – Requires knowledge of the underlying ScriptEngine implementation beyond JSR 223 38 © 2012 IBM Corporation
  • 39.
    Scripting on theJVM is great ■ Some of the most popular languages support Java embedding ■ Embedding a language in a new application is easy to get started ■ Deciding how to embed has consequences –JSR 223 is a great framework for basic embedding –If you need to harness the power of the language, you will need to use the language API • For example, JRuby Embed Core ■ How are you embedding your scripting language on the JVM? 39 © 2012 IBM Corporation
  • 40.
    References ■ JSR 223 – JSR 223 specification • http://www.jcp.org/en/jsr/detail?id=223 – JRuby implementation • http://kenai.com/projects/jruby/pages/JavaIntegration – Groovy implementation • http://groovy.codehaus.org/JSR+223+Scripting+with+Groovy ■ Jython Java Integration – http://www.jython.org/jythonbook/en/1.0/JythonAndJavaIntegration.html ■ Scripting in Java: Languages, Frameworks, and Patterns – Dejan Bosanac, Addison-Wesley 40 © 2012 IBM Corporation
  • 41.
    References ■ Get Products and Technologies: – IBM Java Runtimes and SDKs: • https://www.ibm.com/developerworks/java/jdk/ – IBM Monitoring and Diagnostic Tools for Java: • https://www.ibm.com/developerworks/java/jdk/tools/ ■ Learn: – IBM Java InfoCenter: • http://publib.boulder.ibm.com/infocenter/java7sdk/v7r0/index.jsp ■ Discuss: – IBM Java Runtimes and SDKs Forum: • http://www.ibm.com/developerworks/forums/forum.jspa?forumID=367&start=0 41 © 2012 IBM Corporation
  • 42.
    Copyright and Trademarks ©IBM Corporation 2011. All Rights Reserved. IBM, the IBM logo, and ibm.com are trademarks or registered trademarks of International Business Machines Corp., and registered in many jurisdictions worldwide. Other product and service names might be trademarks of IBM or other companies. A current list of IBM trademarks is available on the Web – see the IBM “Copyright and trademark information” page at URL: www.ibm.com/legal/copytrade.shtml 42 © 2012 IBM Corporation