Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

Polyglot programming on the JVM

Polyglot programming on the JVM

How do you share code between client (JavaScript) and the server (Java)? An overview over Java 8 and project Nashorn.

This presentation was given at enterJS 2014 (2014-05-30).

Ben Ripkens

June 30, 2014
Tweet

More Decks by Ben Ripkens

Other Decks in Programming

Transcript

  1. Agenda • How not to "share" code • Possible alternatives

    • Nashorn and JS engine primer • complete Nashorn example • Other ecosystems • Summary
  2. Web App Server Java JavaScript function getPwStrength(s) { return 'weak';

    } Strength getPwStrength(String s) { return Strength.WEAK; }
  3. function getPwStrength(s) { return 'weak'; } Strength getPwStrength(String s) {

    return Strength.WEAK; } SonarQube is happy! Duplications 2.4% 520 lines 28 blocks 20 files
  4. Possibility 1:
 Logic only on the server-side Web App Server

    Java JavaScript function getPwStrength(s) { var url = '/pwstrength?pw=' + encodeURIComponent(s); return $.get(url); } @GET @Path("/pwstrength") @Produces("application/json") Strength getPwStrength( @QueryParam("pw") String pw) { return Strength.WEAK; }
  5. Possibility 2:
 Domain Specific Languages must contain /a-z/ must contain

    /A-Z/ must contain /0-9/ should be longer than 6
  6. Possibility 4:
 JavaScript on the Server Web App Server Java

    JavaScript function getPwStrength(s) { return 'weak'; } JavaScript
  7. How is this better than GWT? • Java is not

    a native language of the web • GWT compiles Java to another language • GWT needs to include many standard libraries in order to make the magic work • GWT needs complex build steps
  8. “GWT is a reasonable implementation of a poor architectural choice.

    [...] First, in many ways, JavaScript is more powerful and expressive than Java, so we suspect that the generation is going in the wrong direction. [...]” ! ThoughtWorks Technology Radar July 2011 http://www.thoughtworks.com/radar/#/platforms/gwt
  9. Nashorn in a nutshell • JavaScript engine (ECMAScript 5) •

    part of JDK 8 • JavaScript is compiled to bytecode in memory • replaces Mozilla's Rhino engine
  10. Hello World ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine =

    manager.getEngineByName("nashorn"); String js = "print('Hello World!');" engine.eval(js); Unfortunately there is a small issue...
  11. HTML 5 Specification (section 6) ECMAScript XMLHttpRequest Specification Syntax and

    Semantic Event Loop setTimeout Call Stack Task Queue setInterval XMLHttpRequest Math / Date
  12. • It is possible to import and use Java classes

    • this provides the ability to build your own event loop • some awesome people have already done this, but it needs to be improved: ! • if you only need the event loop: Simulating Browser APIs https://gist.github.com/bripkens/8597903 https://bugs.openjdk.java.net/browse/JDK-8006183
  13. Step 1 (contd.):
 Our PW check shouldn't suck bower install

    --save dropbox/zxcvbn#v1.0 Remember this dependency Install from GitHub dropbox/zxcvbn repository the tag v1.0 Save dependency to local disc
  14. Step 2
 Make it work on the server var result

    = zxcvbn('myPasswordIsRatherLong'); expect(result.score).toBe(2);
  15. assertThat(result.get("score"), is(2)); Step 2 (contd.):
 Make it work on the

    server ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("nashorn"); Bindings globalScope = engine.getBindings(ScriptContext.ENGINE_SCOPE); globalScope.put("window", globalScope); engine.eval(slurp("/bower_components/zxcvbn/zxcvbn.js")); String js = "zxcvbn('myPasswordIsRatherLong');";
 Map<String, Object> result = (Map<String, Object>) engine.eval(js);
  16. • Generate hints for the user based on data that

    has been loaded • use the same template engine on client and server • compile LESS CSS on the server What you might want to do
  17. • basically Node.js on the JVM with the help of

    Nashorn • enables you to do require('events') and more • uses libuv to support Node.js APIs • unfortunately still very young and not well documented Avatar.js to the rescue
  18. Node.js modules Run with Avatar.js on the JVM Transpile with

    browserify Run in the browser [ browser ] [ JVM ] Run on Node.js [ Node.js ]
  19. Objective-C #import <JavaScriptCore/JavaScriptCore.h> ! NSString* js = @"Math.max(2, 3);"; JSContext*

    context = [[JSContext alloc] init]; JSValue* value = [context evaluateScript:js]; NSLog(@"Max = %d", [value toInt32]);
  20. • Share not only business, but also UI logic •

    Offline-first becomes more and more viable • run Node.js modules as part of your Maven based build process • we will probably come up with some very interesting use cases Summary
  21. • On password strength estimation • http://xkcd.com/936/ • https://tech.dropbox.com/2012/04/zxcvbn-realistic-password-strength- estimation/

    • http://www.troyhunt.com/2014/05/the-ebay-breach-answers-to-questions.html • Specifications • http://www.ecma-international.org/ecma-262/5.1/ • http://www.w3.org/TR/html5/webappapis.html#timers • http://www.w3.org/TR/XMLHttpRequest/ • Misc • https://avatar-js.java.net/ • http://alistapart.com/article/offline-first References