AVATAR 2.0
More than just Node.js
on the Java Virtual Machine
Niko Köbler (@dasniko)
I'm to Hire!
WHY
JavaScript?
(undefined is not a function!)
With Java, We Have...
- Longterm investments
- Mature solutions
- Complex and extensive business logic
- Integration of heterogeneous environments
across platforms - Blueprints and best-practices available
- Proven infrastructure
And now,
you tell us about this
Brave New (Node-)World
- Mostly new applications
- Mostly No-SQL backed
- New application approaches
- More focused silo apps
- "Cool stuff"
- > 110.000 NPM libraries available
- No enterprise integration (yet)
- Infrastructure?
Speaking JavaScript
Like it or not, JavaScript is everywhere these days - from browser to server to mobile - and now you, too, need to learn the language or dive deeper than you have.
Dr. Axel Rauschmayer
Thoughtworks
I think JavaScript has been seen as a serious language for the last two or three years; I think now increasingly we’re seeing JavaScript as a platform.
(Sam Newman, ThoughtWorks’ Global Innovation Lead)
JavaScript has emerged both as a platform for server-side code but also a platform to host other languages.
(January, 2014)
Integration?
Integration!
Nashorn
- JavaScript Enginge on the JVM
- based on invokedynamic feature
- competes with Google V8
- ECMAScript 5.1 compatible (ECMAScript 6 in future)
- Seamless interoperability of Java and JavaScript
- Language and API Extensions closures, collections & for each, multi-line string literals, string interpolation, __noSuchProperty__, __noSuchMethod__, typed arrays, binding properties, error extensions, conditional catch clause, String functions, and many, many more...
Java & JavaScript
...are similar than car and carpet are similar.
Nashorn
Command line client
$ $JAVA_HOME/bin/jjs
jjs> print('Hello Nashorn!');
Invoking JavaScript from Java
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval("print('Hello Nashorn!');");
engine.eval(new FileReader("scriptfile.js"));
Invocable invocable = (Invocable) engine;
Object result = invocable.invokeFunction("jsSayHello", "Nashorn");
Nashorn
Invoking Java from JavaScript
package my.package;
public class MyJavaClass {
static String sayHello(String name) {
return String.format("Hello %s from Java!", name);
}
}
var MyJavaClass = Java.type('my.package.MyJavaClass');
var result = MyJavaClass.sayHello('Nashorn');
print(result); // Hello Nashorn from Java!
Avatar-js
Node.js on the JVM
~95% Node.js API compatibility
no Chrome V8 native APIs
many of the node-modules work
(e.g.: abbrev, ansi, async, block-stream, chmodr, chownr, coffee-script, colors, commander, connect, debug, engine.io, express, ftsream, glob, graceful-fs, inherits, ini, init-package-json, grunt, grunt-bower-task, jade, lodash, mime, mkdirp, mocha, moment, mongodb, mongoose, mustache, node-unit, node-uuid, once, opener, optimist, osenv, passport, q, read, redis, request, retry, rimraf, ronn, semver, slide, socket.io, tar, uglify-js, uid-number, underscore, which, winston)
(e.g.: abbrev, ansi, async, block-stream, chmodr, chownr, coffee-script, colors, commander, connect, debug, engine.io, express, ftsream, glob, graceful-fs, inherits, ini, init-package-json, grunt, grunt-bower-task, jade, lodash, mime, mkdirp, mocha, moment, mongodb, mongoose, mustache, node-unit, node-uuid, once, opener, optimist, osenv, passport, q, read, redis, request, retry, rimraf, ronn, semver, slide, socket.io, tar, uglify-js, uid-number, underscore, which, winston)
https://avatar-js.java.net
Project Avatar
- End-to-end fullstack framework
- Client-Library
- Services (REST, WS, SSE)
- JMS
- Running in a Java EE Application Server
- Glassfish 4
- WebLogic 12.1.3
Avatar-JS &
Project Avatar
become
Avatar 2.0
Avatar 2.0
- no more Java EE application server needed
- single, standalone JVM
Threads &
Inter-Thread
Communication
Message Bus
var avatar = require('org/glassfish/avatar');
var threads = require('org/glassfish/avatar/threads');
var app = avatar.application;
var name = app.name;
var bus = app.bus;
// listen for messages on topic 'hello'
bus.on('hello', function(body, msg) {
print(name + ' got message: ' + JSON.stringify(body));
});
// publishing to 'hello' topic (e.g. in file hello.js):
bus.publish('hello', { x : 'x', y : 'y' });
// start a background thread for publishing
threads.newBackgroundThread('background', 'hello.js').start();
Message Bus Methods
bus.publish(topic, body);
bus.publishTo(address, topic, body);
bus.send(topic, body);
bus.sendTo(address, topic, body);
bus.reply(replyTo, body);
bus.subscribe(topic);
bus.unsubscribe(topic);
Shared State
Cache/Map API: Key-Value-Store
(Coherence backed, Cache/JSR-107 compliant)
(Coherence backed, Cache/JSR-107 compliant)
var avatar = require('org/glassfish/avatar');
var state = avatar.application.state;
state.put('key', {'value': 'myValue'});
state.keys(); // -> Array
state.contains('key'); // -> boolean
state.get('key'); // -> Object
state.remove('key'); // -> void
Avatar Persistence
Model-Store-API
Model-Store API
database setup
var store = avatar.newStore(‘mysql’, {
host: 'localhost',
port: 3306,
database: 'test',
username: 'root',
createDb: true
});
- JPA (Eclipselink) / JDBC based
- relational and non-relational
- user-transactions possible
Model-Store API
model setup
var Family = avatar.newModel('family', {
"name" : {
type : "string",
primary : true
},
"description" : "string"
});
var Product = avatar.newModel('product', {
"name" : {
type : "string",
primary : true
},
"madeBy" : "string",
"price" : "number",
"quantity" : "integer"
});
Model-Store API
relations & binding
Family.hasMany(Product, {
as : 'products',
foreign : 'family'
});
store.bind(Family, Product);
Model-Store API
usage during runtime
store.connect(function() {
Product.create({
name: 'Widget',
price: 1.00,
quantity: 2,
}, function(err, w1) {
console.log(JSON.stringify(w1));
store.disconnect(function() {
// done
});
});
});
R.I.P.
- UI Library
- REST Services
- (Web-)Socket Services
- Push Services (SSE)
- JMS
--> new t3 thin client
for JMS & remote EJB calls
Demo Time
Competitors ?
--> Java Magazin 03/2015
Avatar 2.0 - Conclusion
- Lightweight Node.js integration in Java Enterprise context
- Run JavaScript Apps on a standard Java Infrastructure
- 95% Node.js API compatibility
- Multi-threaded, asynchronous, non-blocking API
- Run one event-loop per thread,
multiple threads - Inter-Thread-communication /
shared state via event bus or map API - Avatar Persistence (Model-Store-API)
- http://avatar.java.net
Avatar 2.0
Thank you!
Questions?
Avatar 2.0
By Niko Köbler