Sie sind auf Seite 1von 54

<Insert Picture Here>

JavaFX for Rich Internet Application


Lee Chuk Munn
Staff Engineer
chuk-munn.lee@sun.com
Focus on
RESTful Web,
Polygot Application
and
Deployment
Presentation Agenda

RESTful Web
<Insert Picture Here>

Polygot Application
Deploying JavaFX
<Insert Picture Here>

RESTful 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 Example
Request
GET /music/artists/magnum/recordings HTTP/1.1
Host: media.example.com
Accept: application/xml

Verb Response Noun


HTTP/1.1 200 OK
Date: Tue, 08 May 2007 16:41:58 GMT
Server: Apache/1.3.6
Content-Type: application/xml; charset=UTF-8

State <?xml version="1.0"?>


<recordings xmlns="…">
transfer <recording>…</recording>

Representation
</recordings>
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
def http = HttpRequest {
location: “http://twitter.com/statuses/public_timeline.json”
method: HttpRequest.GET
}

http.start();

• Need to provide location (URL)


• Method attribute defaults to GET
• Request is asynchronous
– Invoke start() to start the request
Reading
Creates an OutputStream
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.GET
sink: outputStream
reading: bind // to something to provide visual cue
onDoneRead: function(): Void {
outputStream.close();
}
}
Must close the stream
http.start(); Value changes from false to true
Setting HTTP Headers
def http = HttpRequest {
location: “http://api.twitter.com/1/statuses/update.json”
method: HttpRequest.POST
source: inputStream
Headers: [
HttpHeader.basicAuth(user, password),
HttpHeader {
name: HttpHeader.CONTENT_TYPE
value: “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 Example Type of document we are parsing.
Must be set before parsing starts
def parser: PullParser = PullParser { Stream to parse from
documentType: PullParser.XML
Event callback
input: inputStream
onEvent: 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;
}… Level at which
… the event occurs
} else if (evt.type == PullParser.END_DOCUMENT) {
inputStream.close();
}
… 'Linear' mode
Event type
Document to Events – XML
START_DOCUMENT
<user>
START_ELEMENT 0 “user”
<id> START_ELEMENT 1 “id”
123456 TEXT 1 “123456”
</id> END_ELEMENT 1 “id”

<name> START_ELEMENT 1 “name”


Tweety Bird TEXT 1 “Tweety Bird”
</name> END_ELEMENT 1 “name”

</user> END_ELEMENT 0 “user”

END_DOCUMENT
Document to Events – JSON
START_DOCUMENT

START_VALUE “user”

START_ELEMENT 0
{
START_VALUE “id”
“user”: {
TEXT “123456”
“id”: “123456”, END_VALUE “id”
“name”: “Tweety Bird”
} START_VALUE “name”
} TEXT “Tweety Bird”
END_VALUE “name”

END_ELEMENT 0

END_VALUE “user”

END_DOCUMENT
Parsing HTTP Request
def parser: PullParser = PullParser {
documentType: PullParser.JSON
onEvent: function(evt: Event) {

else if (evt.eventType == PullParser.END_DOCUMENT) {
parser.input.close();
}
} Close stream when done
}
def http = HttpRequest {
location: “http://twitter.com/statuses/public_timeline.json”
method: HttpRequest.GET
onInput: function(inputStream: InputStream): Void {
parser.input = inputStream;
parser.parse();
Callback when input stream is ready
}
}
http.start(); 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: 30m
onChannel: 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 Application
JavaFX RIA Architecture

JavaFX Application

JavaFX Runtime
Web Start / Applet

Java Plugin

Browser
Operating 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 Example
Stage {

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 Function
function sayHello(name) {
document.getElementById("name").innerHTML =
“Hello “ + name; Easier to manipulate DOM in
} browser than in JavaFX
<div id="name" style="text-align: center;"></div>

//Get Applet instance


var 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 argument
window.call("sayHello", ["Fred"]);
}
Reading a HTML Field
<input id=”my_name” name=”my_name” type=”text”/>


// Get JSObject instance
var window = netscape.javascript.JSObject.getWindow(applet);

// Get the document


var doc = window.getMember(“document”) as JSObject;

// Get the input field within the document


var myNameField = doc.getMember(“my_name”) as JSObject;

// Get the text


var 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
public var message = “Hello”;
Stage {
Scene: Text {
fill: Color.LIGHTGREEN
content: bind message

}
• Accessing script level variable/functions

var app = document.getElementById(“myApp”);


app.script.message = “Hello from “ + navigator.userAgent;
• Manipulating the scene graph
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
Browser loads JNLP

Client Browser launches JWS


Web
JWS check JARs in local
cache
Server
JARs not installed.
Full download
JAR
Cache New version available.
Web
Request diff download
Web Start Start Creates diff
Servlet
JWS patches local version
and creates new JARS diff
JWS launches app
v 1.0 v 1.2
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

Creates as thread 'Java'


Application

JavaFX
Main Pass interface as handle

Interface

JavaFX
UI
JavaFX UI Implements Interface
public class DisplayText extends ShowMessage {
var text: String;
Implements the interface
override public function show(): Void {
var stage: Stage = State {
//Initialize you stage Good to have a method
… to control Stage visibility
content: bind text
};
stage.visible = true;
}
override public function displayText(msg: String): Void {
text = msg;
}
Java Application
public 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;


Define a thread to
override function create() : RunnableFuture { start 'Java'
return new Main(msgInterface);
}
}

def display = DisplayText { };


display.show();

def javaFXTask = JavaFXTask { Create and starts


msgInterface: display the thread
};
javaFXTask.start();
<Insert Picture Here>

Deploying 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
JVM
– Configurable on a per in
Browser
Applet basis
– Live beyond the browser
• Unify Applet and the Web Applet Applet

Start deployment
JVM
– Applet runs on Web Start
Applet
JVM
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() { Applet attributes
deployJava.runApplet({
codebase:'http://www.mycompany.com/java/',
archive:'myapplet.jar', code:'Main.class',
width:400, height:300
}, null, “1.5+”); Minimum JDK version
}
Applet parameters
if (deployJava.versionCheck(“1.5+”)) {
document.writeln('<button onclick=”launch()”>Launch Applet</button>');
} else {
document.writeln('<button
onclick=”javascript:deployJava.installLatestJRE();”>
Install Java</button>');
}
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 up


FileContent 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” Setting id
draggable: true
}, Enable drag
{ param1: “my_para,”
});
</script>
Access with
FX.getArgument(“param1”) as String
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

javafxpackager -src src -appClass myapp.Main \


-appWidth 500 -appHeight 500 -pack200

• Or use NetBeans
<Insert Picture Here>

Conclusion
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

or
oracle.com
Alternate Title with Subhead
Arial 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

Das könnte Ihnen auch gefallen