Upload
fabricematrat
View
1.093
Download
25
Embed Size (px)
DESCRIPTION
Today your customers want to tailor applications to their specific needs, in terms of both business logic and user interface. In short, they want to inject custom code to transform a mainstream system into a platform as a service (PaaS). To support this vision, Amadeus built an extensibility framework relying on the JVM and JSR 223 to turn its business-critical solutions into a PaaS. Attend this session to hear how it dealt with JSR 223 limitations, why it picked Groovy as its favorite language, and the challenges it faced with sandboxing and hot swap on multitenant systems. The presentation also shares what Amadeus expects from invokedynamic and the coming support of JavaScript on the JVM.
Citation preview
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
©
20
12 A
mad
eu
s IT
Gro
up
SA
Polyglot alchemy: JSR 223 in action
Fabrice MatratMarc Campora
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Marc Campora Sr Manager Java Middleware [email protected] @mcampora
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Fabrice Matrat System Architect Technical Evangelist [email protected] @fabricematrat
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Context & Pb Statement
Key design decisions
Looking forward & Conclusion
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Context & Pb Statement
Key design decisions
Looking forward & Conclusion
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Amadeus
Leading provider of IT solutions for the travel industry Connect Providers (ex. airlines) and Resellers
(ex. TAs)
Provide IT solutions (ex. check-in or inventory system)
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
System Constraints
3.7MBookings/day
1.6BTransactions/day
100+IT changes/day
<0.5sResponse time
99.99%Availability
600kTerminals
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Our products
Inventory Departure
control Self Booking
Tools Point-of-sale e-Commerce Mobile
companions
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Technical platform
A clear technical strategy RIA even for the mobile
Community products
SaaS, multi-tenants infrastructure
Web-based
Common hardware
Common code
Java, JEE, JavaScript
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Problem statement
Community versus specific
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
From SaaS to PaaS
Application logic
Middleware & Framework
Application UI
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
From SaaS to PaaS
Application logic
Middleware & Framework
Script execution environment
API
Application UI
Custom logic
Custom UICustom UI
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Features and ambition
Dev. Env.• Distributed version control• Self service loads and fallbacks• Access control and traceability• Life cycle management
UI• Custom dialogs• UI extensions
API• Call reservation systems• Call any external Web services• Store and retrieve custom data• Send emails• …
Runtime• Hotswap• Sandboxing• Isolation• Usage monitoring
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Context & Pb Statement
Key design decisions
Looking forward & Conclusion
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
JSR 223 Sandbox Integration
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Scripting on JVM
Application logic
Middleware & Framework
Script execution environment
API
Application UI
Script Script
Script
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Scripting for Amadeus PaaS
PaaS
JVM
Performance
Memory
WSTemplating
StrongCommunity
Dev. Productivit
y
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Language Choice (2010)
Language
• Java 1.6• Groovy 1.6• Jython 2.5• JRuby 1.4• Rhino 1.7
Methodology
• Popularity• Documentation• Depth-first
search• Fibonacci• Templating• WebService
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Groovy
0 200 400 600 800 1000 1200 14000
50
100
150
200
250
300
350
400
450
500
Java
Rhino
Groovy
JRuby
Jython
Time
Memory
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Embed Groovy
Binding binding = new Binding(); binding.setVariable("foo", new Integer(2)); GroovyShell shell = new GroovyShell(binding); shell.evaluate("println 'Hello World!'; x = 123; return foo * 10");
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Embed Groovy
ClassLoader parent = getClass().getClassLoader(); GroovyClassLoader loader = new GroovyClassLoader(parent); File script = new File("HelloWorld.groovy")Class<GroovyObject> groovyClass = loader.parseClass(script); GroovyObject groovyObject = groovyClass.newInstance(); groovyObject.invokeMethod("run", new Object[0]);
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Embed Groovy
String[] roots = new String[] { "/my/groovy/script/path" }; GroovyScriptEngine gse = new GroovyScriptEngine(roots); Binding binding = new Binding(); binding.setVariable("input", "world"); gse.run("hello.groovy", binding); System.out.println(binding.getVariable("output"));
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Groovy
Plug to Amadeus PaaS
What about JavaScript ?
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
JSR 223
Standard to embed scripting in JVM
Independent from language
Part of JDK 6+
One entry point: javax.script
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Groovy vs. JSR 223
Binding binding = new Binding(); binding.setVariable("foo", new Integer(2)); GroovyShell shell = new GroovyShell(binding); shell.evaluate("println 'Hello World!'; x = 123; return foo * 10");
ScriptEngineManager mgr = new ScriptEngineManager(); ScriptEngine engine= mgr.getEngineByName("groovy"); Bindigs bindings = engine.createBindings();bindings.put("foo", new Integer(2)); engine.eval("println 'Hello World!'; x = 123; return foo * 10", bindings);
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
JSR 223 in and out
In Out
Performance
Security
Engine Wrapper
Multiple script technologies
Common API
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
In Out
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Multiple script technology
Freemarker
Groovy
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName( "groovy");
engine.eval("println 'Hello World!'");
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine =
mgr.getEngineByName( "freemarker"); engine.eval("Hello ${who}!");
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Common APIInterface Description
ScriptEngine Main wrapper
ScriptEngineFactory Factory for ScriptEngine
Compilable ScriptEngine which contains methods to compile script
Invocable ScriptEngine whose methods allow scripts to be executed.
Bindings A mapping of key/value pairs, all of whose keys are Strings.
ScriptContext Context
Classes Description
ScriptEngineManager Discovery and instantiation mechanism for ScriptEngine
AbstractScriptEngine Super Class
CompiledScript Store results of compilations.
SimpleBindings HashMap bindings
SimpleScriptContext Simple ScriptContext.
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
In Out
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Availability 800 languages on JVM
Around 60 are maintained
20 have JSR 223 Implementation
Language Availability
Groovy Yes
Scala Yes
Jython Yes
JRuby Yes
Clojure Yes
Ceylon No
Golo No
… ..
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Performance
Compilation Result JSR 223 No Access
Storage
Script Compilation Result
Script Script
Script
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Cache
Performance
Byte
Code
Custom classloader
Cache
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Hot swapping Groovy
Run 2 versions of the same script
Passport.groovygot changed
Passport.class
new code1110000011
new hash
new code1110000011
new hash
Custom classloader
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
JSR 223 Sandbox Integration
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Script in JVM sharing platform and resources
Sandbox
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Bad things can happen Consume resources (CPU, disk, threads)
Java and Amadeus API is available
Sandbox
java.lang.System.exit(1)
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Access control
Compile Runtime
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Compile : How ?
Check every node in AST @ compile time
org.codehaus.groovy.control.customizers.CompilationCustomizerorg.codehaus.groovy.ast.GroovyCodeVisitor
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Compile : Design
Deny/Allow/Deny Blacklist Everything
Whitelist
BlacklistMethods granularity in whitelisted classes
java.lang.System
java.lang.System.exit java.lang.System.currentTimeMillis
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Compile : Implementation
class SecureCodeCustomizer extends CompilationCustomizer { public SecureCodeCustomizer() { super(CompilePhase.CANONICALIZATION); } public void call(…) { final ModuleNode ast = source.getAST(); ast.getStatementBlock().visit(new SecureCodeVisitor()); … }}class SecureCodeVisitor implements GroovyCodeVisitor { public void visitMethodCallExpression(MethodCallExpression call) { checkMethodAuthorized(call); … } public void visitStaticMethodCallExpression (…) {…} public void visitClassExpression (…) {…} …}
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Access control
Compile Runtime
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Runtime
Java Security leverage the JVM's Security Managers
Wrap Primitive/Method
Add Wrapping
((Object)"ls").execute()
def obj = ((Object)"ls")// Throw an exception if necessaryauthorizeStatement(obj, "execute")obj.execute();
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Resource Sharing
Stability Isolation
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Sandbox code (for stability)
Timeout enforcement Protection against infinite loops and other
patterns
Injected @ compile time via AST transformation
@groovy.transform.TimedInterrupt( value = 10L, unit = TimeUnit.SECONDS)
def config = new CompilerConfiguration() def customizer = new ASTTransformationCustomizer( [value:10L, unit:TimeUnit.SECONDS], TimedInterrupt)config.addCompilationCustomizers(customizer)
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
We are not alone
Oracle Application Developer Framework https://github.com/sjurgemeyer/
GR8ConfUS2013/tree/master/JimDriscoll Jenkins
http://kohsuke.org/2012/04/27/groovy-secureastcustomizer-is-harmful/
Call to the community for improvement !
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Resource Sharing
Stability Isolation
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Remoting
AST can optimize the Contextual information sent to the Execution Farm.
Applicationfarm
Scriptingfarm(s)
REST/Jsonwith applicationcontext
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Remoting
Isolation SandBox Failure
Memory or IO contentions
No Resources Impact on Main application Farm
Customers or staging isolation
On demand provisioning Fine grain usage reports
Billing Model
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
JSR 223 Sandbox Integration
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Developer experience
Production
Preview
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Groovy productivity
Java
XML appears as objects TripPlan<extends XMLNode> tp = TripPlanFactory.tripplan
tp.AIR.ITINERARIES.each {itinerary -> Logger.info itinerary.text()
}
Untyped language Actually you have the choice
def unknown = "we’re @ J1 2013"
String message = "we’re @ J1 2013"
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
A practical case study…
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
A practical case study…
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
A practical case study…
UI
Hook
Action
Server
Placeholder import amadeus.pnr.tripplan
// get PNR in-memory representation (a.k.a. TripPlan)def tripplan = TripPlan.getTripPlan()
// defining a list of eligible countriesdef COUNTRY_LIST=["US", "PR", "AS", "VI", "MP", "GU"]// defining a list of eligible carriersdef CARRIER_LIST=["UA","AA"]
// business condition if one goes to or comes from US,// or if carrier is UA or AAdef eligibleTrip = !tripplan.AIR.LIST_ITINERARY.LIST_SEGMENT.findAll { ((it.E_LOCATION.COUNTRY_CODE in COUNTRY_LIST) || (it.B_LOCATION.COUNTRY_CODE in COUNTRY_LIST)) || (it.AIRLINE.CODE in CARRIER_LIST)}.isEmpty()
// if trip eligible, trigger the UI enrichmentbean.with { if (eligibleTrip) { // the id of the product UI placeholder in which to display. placeholder = "customTSAPlaceholder"
// the script to be called during the next step to // process the user inputs. actionId = "CustomTSAProcess" }}
{Template} {macro init()} <div style="padding-left: 20px;"> {@aria:TextField { label: 'Maiden name', labelWidth: 210, block: true, bind: to("pspt") } /} {@aria:TextField { label: 'Redress number', block: true, labelWidth: 210, bind: to("redn") } /} {@aria:TextField { label: 'Known traveler id', block: true, labelWidth: 210, bind: to("knwt") } /} </div> {/macro}{/Template}
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
A practical case study…
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Context & Pb Statement
Key design decisions
Looking forward & Conclusion
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Remaining challenges
A productive development environment
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Remaining challenges
A productive development environment Success leads to Elasticity
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Remaining challenges
A productive development environment Success leads to Elasticity Add new languages to enlarge the user
base
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Take home messages
Groovy is great to customize applications
The JVM and JSR223 give you access to other languages
Sandboxing and isolation are a must
Unfortunately sandboxing and isolation are specific to the language
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Some more…
Special thanks to the team!
UI produced using AriaTemplates ™ (github.com/ariatemplates)To know more about Amadeus: http://www.amadeus.com
JavaOne Polyglot Enterprise Development on the JVM [CON2382]
Mark Little – VP Red Hat Inc The JVM Is Over: The Polyglot Virtual Machine Is Here
[CON5344]Marcus Lagergren - Runtime Futurist, Oracle
Liftoff with Groovy 2.1 [CON2591]Guillaume Laforge - Pivotal
Embedded DSL: Groovy and Scala Fair Duel [TUT4524]Corinne Krych - RedHat and Pascal Cohen - Amadeus
© 2
01
3 A
mad
eu
s IT
Gro
up
SA
Q&A