JavaFX for Rich Internet Application
Transcript of JavaFX for Rich Internet Application
<Insert Picture Here>
JavaFX for Rich Internet ApplicationLee Chuk MunnStaff [email protected]
Focus onRESTful Web,
Polygot Application and
Deployment
<Insert Picture Here>
Presentation Agenda
RESTful WebPolygot ApplicationDeploying JavaFX
<Insert Picture Here>
RESTful WebRESTful Web
REST Overview• REpresentational State Transfer
– Architectural styles and the design of network base software architectures – Roy Fielding PhD thesis
• Major components– Nouns (resources) are identified by URIs
• Eg. http://twitter.com/statuses/public_timeline.json– Small set of verbs to manipulate the nouns
• Eg. GET– Representation is how you would like to view the state (data)
• Eg. Twitter example, we requested JSON format– Use verbs to exchange application state and representation
• Eg. POST a tweet – changing the public timeline• Key to being mashable
RESTful Exchange ExampleRequestGET /music/artists/magnum/recordings HTTP/1.1Host: media.example.comAccept: application/xml
ResponseHTTP/1.1 200 OKDate: Tue, 08 May 2007 16:41:58 GMTServer: Apache/1.3.6Content-Type: application/xml; charset=UTF-8
<?xml version="1.0"?><recordings xmlns="…"> <recording>…</recording> …</recordings>
Verb Noun
Representation
Statetransfer
JavaFX Support• Provides three categories of API
– HTTP – javafx.io.http– Parser – javafx.data.pull, javafx.data.xml– Feeds – javafx.data.feed.atom, javafx.data.feed.rss
• All are in the Common profile– Works across desktop, mobile and TV
• Utility class to encode and decode URLs– Eg. <space> is %20– Useful for submitting URLs with parameters
Making a HTTP Request• Asynchronous HTTP client
– For making standard or non-standard HTTP request• POST, GET, PUT, etc
• Uses java.io.InputStream java.io.OutputStream to send and receive data
• Track request either via callbacks or indicators– Callbacks – provide function to preform action – Indicators – members that changes from false → true
• Eg. Bind to provide visual feedback
HTTP Request
• Need to provide location (URL)• Method attribute defaults to GET• Request is asynchronous
– Invoke start() to start the request
def http = HttpRequest {location: “http://twitter.com/statuses/public_timeline.json”method: HttpRequest.GET
}
http.start();
Reading def cache = Storage { source: “cache.txt” }def outputStream = cache.resource.openOutputStream(true)
def http = HttpRequest {location: “http://twitter.com/statuses/public_timeline.json”method: HttpRequest.GETsink: outputStreamreading: bind // to something to provide visual cueonDoneRead: function(): Void {
outputStream.close();}
}
http.start();
Creates an OutputStream
Must close the streamValue changes from false to true
Setting HTTP Headers def http = HttpRequest {
location: “http://api.twitter.com/1/statuses/update.json”method: HttpRequest.POSTsource: inputStreamHeaders: [
HttpHeader.basicAuth(user, password), HttpHeader {
name: HttpHeader.CONTENT_TYPEvalue: “application/json”
}]onResponseCode: function(respCode: Integer): Void {
if (respCode == 401) {//Handle authentication failure
}}
}
Parsing Data• Supports two build in data types
– XML and JSON• Parse is 'pull' model
– Small memory foot print – does not build DOM object• Mobile friendly
– Generates a sequence of events– Can also work in 'linear' mode
• Request for certain event by forwarding• Invoke PullParser.parse() to parse
– Asynchronous
Parsing Exampledef parser: PullParser = PullParser {
documentType: PullParser.XMLinput: inputStreamonEvent: function(evt: Event): Void {
if (evt.type == PullParser.START_ELEMENT) {if ((evt.qname.name == ”user”) and (evt.level == 0)) {
… } else if ((evt.qname.name == “id”) and (evt.level == 1)) {
cityName = parser.forward().event.text;} … …
} else if (evt.type == PullParser.END_DOCUMENT) {inputStream.close();
}…
Type of document we are parsing. Must be set before parsing starts
Stream to parse from
Event callback
Event type
Level at which the event occurs
'Linear' mode
Document to Events – XML
<user>
<id>123456
</id>
<name>Tweety Bird
</name>
</user>
START_DOCUMENT
START_ELEMENT 0 “user”
START_ELEMENT 1 “id”TEXT 1 “123456”
END_ELEMENT 1 “id”
START_ELEMENT 1 “name”TEXT 1 “Tweety Bird”
END_ELEMENT 1 “name”
END_ELEMENT 0 “user”
END_DOCUMENT
Document to Events – JSON
{“user”: {
“id”: “123456”,“name”: “Tweety Bird”
}}
START_DOCUMENT
START_VALUE “user”
START_ELEMENT 0
START_VALUE “id”TEXT “123456”
END_VALUE “id”
START_VALUE “name”TEXT “Tweety Bird”
END_VALUE “name”
END_ELEMENT 0
END_VALUE “user”
END_DOCUMENT
Parsing HTTP Requestdef parser: PullParser = PullParser {
documentType: PullParser.JSONonEvent: function(evt: Event) {
… else if (evt.eventType == PullParser.END_DOCUMENT) {
parser.input.close();}
}}def http = HttpRequest {
location: “http://twitter.com/statuses/public_timeline.json”method: HttpRequest.GETonInput: function(inputStream: InputStream): Void {
parser.input = inputStream;parser.parse();
}}http.start();
Callback when input stream is ready
Close stream when done
Start then request then start the parsing
RSS and Atom• Convenience classes to read RSS and Atom
– Exercise: write a RSS parser with HttpRequest and PullParser• RssTask contains channels with multiple items• AtomTask contains feeds with multiple entries• Specify the location and the pool interval
RssTask {location: “http://....”internal: 30monChannel: function(channel: Channel): Void {
…onItem: function(item: Item): Void {
… }.start()
URL Encoder and Decoder• URLConverter to encode and decode parameters
def params = [Pair { name: “w”, value: “2502265” },Pair { name: “u”, value: “c” }
];var convert = URLConverter { }var url = “http://weather.yahooapis.com/forecastrss?{convert.encodeParameters(params)}”;
def yahooWeather = HttpRequest {location: url…
}
<Insert Picture Here>
Polygot ApplicationPolygot Application
JavaFX RIA Architecture
Java Plugin
JavaFX Application
JavaFX Runtime
Web Start / Applet
BrowserOperating System
Knowing Where You Are• JavaFX design to run in multiple environments
– “For all the screens of your life”• Application can find out where are they running• __PROFILE__ pseudo variable provides the following
values– browser, mobile, desktop
var inApplet = __PROFILE__ == "browser"; var inMobile = __PROFILE__ == "mobile";var inDesktop = __PROFILE__ == "desktop";
Tapping into the Environment• Applications can take advantage of the environment• StageExtension allows developers to add platform
extension to the application– Extension will not be enabled if not running in that particular
environment• AppletStageExtension – only extension defined
– Events on when the JavaFX application is dragged out of the browser
• draggable property must be set to true– Interacting with the browser
• Evaluate JavaScript statement only• Cause the browser to display a particular web page
Draggable JavaFX Applet• Only supported in JDK6u10 and beyond• Enabled with new applet parameter
– Default drag: Alt + Left-click– Can be overridden programmatically– Need to be enable at deployment
• More later• Events generated by extension
– onDragStarted – dragging started– onDragFinished – dragging completed– onAppletRestored – applet returned to the browser– shouldDragStart – call back to indicate if dragging should
commence
AppletStageExtension ExampleStage {
… extensions: [
AppletStageExtension {onDragFinished: function(): Void {
label.text = “I'm out”;}onAppletRestored: function(): Void {
label.text = “Back in the browser”}shouldDragStart: function(evt: MouseEvent): Boolean {
return (evt.shiftDown and (evt.clickCount == 2));}
}]
};
LiveConnect – Java to JavaScript• JavaFX cannot directly interact with the browser• Use “LiveConnect”
– Java to JavaScript bridge• netscape.javascript.JSObject provides access to
HTML DOM– getWindow() returns a JavaScript object containing the applet– JSObject.getWindow(this) – 'this' is the instance of the applet– FX.getArgument(“javafx.applet”) to return applet container
• JSObject provides the following methods– call(String jsMethod, Object args[ ]) - invoke a JavaScript
method in the browser– eval(String jsStatement) – evaulate a JavaScript statement– getMember(String domName) – reference to a tag
Invoking a JavaScript Functionfunction sayHello(name) {
document.getElementById("name").innerHTML = “Hello “ + name;
} <div id="name" style="text-align: center;"></div>
//Get Applet instancevar applet: Applet = FX.getArgument("javafx.applet") as Applet;if (applet == null) {
//We are not running in the browser...} else { // Get JSObject instance
var window = netscape.javascript.JSObject.getWindow(applet);// Invoke JSObject.call function passing name as argumentwindow.call("sayHello", ["Fred"]);
}
Easier to manipulate DOM in browser than in JavaFX
Reading a HTML Field<input id=”my_name” name=”my_name” type=”text”/>
… // Get JSObject instancevar window = netscape.javascript.JSObject.getWindow(applet);
// Get the documentvar doc = window.getMember(“document”) as JSObject;
// Get the input field within the documentvar myNameField = doc.getMember(“my_name”) as JSObject;
// Get the textvar name = myNameField.getMember(“value”) as String;
From JavaScript to JavaFX• Manipulate JavaFX from within the browser
– Access variable– Invoke function– Descend into scene graph
• JavaFX must have an 'id' on the web page• Conversion rules and convention similar to JSR-223
Example of JavaScript to JavaFX
• Accessing script level variable/functions
• Manipulating the scene graph
public var message = “Hello”;Stage {
Scene: Text {fill: Color.LIGHTGREENcontent: bind message
… }
var app = document.getElementById(“myApp”);app.script.message = “Hello from “ + navigator.userAgent;
app.stage.scene.content[0].fill = app.Packages.javafx.scene.paint.Color.RED;
JavaWeb Start• Better to control JavaFX from JavaWeb Start if
– More imperative than declarative in style– Application is large– Application is patched often– Facelift for your Swing application
• What is JavaWeb Start?– Its a regular Java application loaded and launched over the
network• Network launching protocol for applications
– Applications is cached on the client – Works on and off line– Express dependencies on other JARS– Advance features like application partitioning, single instance,
printing, platform specific native code, etc.
JavaWeb Start Illustrated
JAR
Client
Web Start
WebServer
WebStart
Servlet
Browser loads JNLP
Browser launches JWSJWS check JARs in local
cache
Cache
JWS patches local version and creates new JARS
New version available.Request diff download
Creates diff
JARs not installed.Full download
JWS launches app
v 1.0 v 1.2
diff
Integrating JavaFX into Web Start• Hacks abound on how you can launch JavaFX from
Java• Recommended way is to start the 'Java' part of your
application from within JavaFX• Define an interface use to communicate with JavaFX
– Methods will be the point of interaction• Implement the interface in JavaFX• Launch JavaFX and start 'Java' from a thread
public interface ShowMessage {public void show();public void display(String msg);
}
Integrating JavaFX with Java Illustrated
'Java'Application
JavaFXMain
JavaFXUI
Interface
Creates as thread
Pass interface as handle
JavaFX UI Implements Interfacepublic class DisplayText extends ShowMessage {
var text: String;
override public function show(): Void {var stage: Stage = State {
//Initialize you stage…
content: bind text};stage.visible = true;
}override public function displayText(msg: String): Void {
text = msg;}
Good to have a method to control Stage visibility
Implements the interface
Java Applicationpublic class Main implements RunnableFuture {
private ShowMessage msgInterface;
public Main(ShowMessage intf) {msgInterface = intf;
}
public void run() {// Entry into Java application
}}
JavaFX Main class JavaFXTask extends JavaTaskBase {
public-init var msgInterface : ShowMessage;
override function create() : RunnableFuture { return new Main(msgInterface); }}
def display = DisplayText { };display.show();
def javaFXTask = JavaFXTask { msgInterface: display};javaFXTask.start();
Define a thread to start 'Java'
Create and starts the thread
<Insert Picture Here>
Deploying JavaFXDeploying JavaFX
Java Deployment Reloaded• Really bad experience • Lots of improvements over the last few years
– JDK 6u10 – improve startup time– Java Plugin2 – more robust browser plugin– Deployment toolkit – easier deployment– Unifying JavaWeb Start and Applet programming model –
liberating the Applet
New Java Plugin• Live outside of the
browser– Will not crash the browser
• Applets can run in separate VM– Choose the JDK version– Configurable on a per
Applet basis– Live beyond the browser
• Unify Applet and the Web Start deployment– Applet runs on Web Start
JVMin
Browser
JVM
Applet
Applet
JVM
Applet
Deployment Toolkit• A JavaScript library for
– Detecting, downloading and installing JDK– Query the environment– Programmatically creates <applet> or equivalent tags– Launching JavaWeb Start applications
• Works without and JRE installed• Includes deployJava.js in web page
– Introduces deployJava JavaScript object– http://java.sun.com/javase/6/docs/technotes/guides/jweb/depl
oyment_advice.html
<script src=”http://java.com/js/deployJava.js”/>
Example – Launch an Applet<script src=“http://java.com/js/deployJava.js”/><script>
function launch() {deployJava.runApplet({
codebase:'http://www.mycompany.com/java/',archive:'myapplet.jar', code:'Main.class',width:400, height:300
}, null, “1.5+”);}
if (deployJava.versionCheck(“1.5+”)) {document.writeln('<button onclick=”launch()”>Launch Applet</button>');
} else {document.writeln('<button
onclick=”javascript:deployJava.installLatestJRE();”>Install Java</button>');
}
Applet attributes
Applet parameters
Minimum JDK version
Unifying Applets and WebStart• Applets can now be describe with JNLP
<applet width="300" height="300" code="com.mycompany.MyApplet">
<param name="jnlp_href" value="my_applet.jnlp"></applet>
<jnlp href="my_applet.jnlp" codebase=”http://...”><offline-allowed/><shortcut><desktop/></shortcut><resources>
<j2se version="1.5+" initial-heap-size=”512m” java-vm-args=”-esa” /><jar href="my_applet.jar" main="true" />
<extension name="ext" href=".../ext.jnlp" /></resources><applet-desc name="My Applet" main-class="com.mycompany.MyApplet">
<param name=”host” value=”myserver.com”/></applet-desc>
</jnlp>
Applet in JavaWeb Start• Applet runs in a sandbox
– Cannot read/write to filesystem, print, etc– Needs to be signed for security
• Plugin2 allows applet to access JNLP API– Do not need to sign, yet secure– User retains control
FileOpenService fos = (FileOpenService)ServiceManager.lookup(“javax.jnlp.FileOpenService”);
//Open dialog pops upFileContent fc = fos.openFileDialog(null, null);
Deploying JavaFX• Deployed as an Applet on JavaWeb Start
– Can also be deployed purely as a JavaWeb Start• Typical JavaFX application deployment
– Java SE, JavaFX runtime• Consist of Java and platform specific/native libraries
• dtfx.js JavaScript library– Introduces javafx JavaScript object– Use is identical to deployJava JavaScript object– Build on deployJava.js
Using javafx JavaScript Object<script src="http://dl.javafx.com/1.2/dtfx.js"><script>
javafx({archive: "MyFXApp.jar", code: "myapp.Main" width: 480, height: 120,id: “myApp”draggable: true
},{ param1: “my_para,”});
</script>
Enable drag
Access with FX.getArgument(“param1”) as String
Setting id
JavaFX Deployment Artifact• Typical JavaFX artifact
– HTML launch page– Applet JNLP file– Application JNLP file– JAR file
• javafxpackager – one command to generate all– Options to compress with pack200, sign, set codebase, etc
• Or use NetBeans
javafxpackager -src src -appClass myapp.Main \-appWidth 500 -appHeight 500 -pack200
<Insert Picture Here>
ConclusionConclusion
Summary• JavaFX provides simple and easy to use APIs to
access and parse REST resources• Tight integration with the Java platform and the
browser– LiveConnect provides AJAX like functionality– JavaWeb Start API provides secure access to the platform
• Deployment toolkit Java Plugin2 enhances user's experience
We encourage you to use the newly minted corporate tagline“Software. Hardware. Complete.” at the end of all your presentations.This message should replace any reference to our previous corporate tagline “Oracle Is the Information Company.”
For More Information
search.oracle.com
ororacle.com
Alternate Title with SubheadArial Size 18 (Gray)
• First-level bullet– Second-level bullet
• Third-level bullet– Fourth-level bullet
• Fifth-level bullet
Deploying with JavaWeb Start• Default deployment mode for JavaWeb Start
– Automatically generated with NetBeans• Set your Java main instead of JavaFX main• That's it!• Might have to customize JNLP if you have library
dependencies
Polygot Programming• Multiple programming languages
– Already happening with JavaEE on different layers– Everything is now in a single VM– Leverage the strength of a particular language
• JavaFX + Groovy• Libraries and components from multiple sources
– Java, Groovy, Scala, JavaFX, etc• Integration at the JVM level
– Class files and bytecode