javafx and scala in the cloud

39
Stephen Chin | Oracle Andrew Phillips | jclouds JavaFX and Scala in the Cloud @steveonjava @jclouds

Upload: stephen-chin

Post on 15-Jan-2015

1.001 views

Category:

Technology


1 download

DESCRIPTION

Talk about an end-to-end application leveraging JavaFX, Scala, Java DB, and cloud technologies. Given at the JAX conference in San Francisco.

TRANSCRIPT

Page 1: JavaFX and Scala in the Cloud

Stephen Chin | OracleAndrew Phillips | jclouds

JavaFX and Scala in the Cloud

@steveonjava

@jclouds

Page 2: JavaFX and Scala in the Cloud

+

Page 3: JavaFX and Scala in the Cloud

Heaven

Photo by Alberto Fernandez Fernandez

Page 4: JavaFX and Scala in the Cloud
Page 5: JavaFX and Scala in the Cloud
Page 6: JavaFX and Scala in the Cloud

When This Architecture Makes Sense

• Data is mostly read-only– Transactional updates still require a server (but

can be simpler/smaller)

• User's view of data is small to medium– Initial DB download of < 10K records is reasonable– Not total DB size, but subset of data visible to user

Conference App has 3K large records and compresses to only 330KB DB size

Page 7: JavaFX and Scala in the Cloud

Cloud Data Advantages

• Offline Operation– Once DB is cached, application works 100% offline

• Responsive Client Performance– All DB queries are fast and local

• High Availability & Scalability– 99.99% Availability– Easily scales up to 100s of requests per second

But, with proper hashes scales up to millions of requests per second!

Page 8: JavaFX and Scala in the Cloud

Cloud Data Advantages (continued)

• Insanely cheap server costs!

Number of Users Monthly Cost*

3,000 Free (S3 free tier)

10,000 $0.28

100,000 $3.84

1,000,000 $39.48

* For 330KB of hosted data in Amazon S3

Page 9: JavaFX and Scala in the Cloud

Cloud Data Advantages (continued)

• Insanely cheap server costs!

Number of Users Monthly Cost*

3,000 Free (S3 free tier)

10,000 $0.28

100,000 $3.84

1,000,000 $39.48

* For 330KB of hosted data in Amazon S3

Page 10: JavaFX and Scala in the Cloud

Cloud Data Advantages (continued)

• Insanely cheap server costs!

Number of Users Monthly Cost*

3,000 Free (S3 free tier)

10,000 $0.28

100,000 $3.84

1,000,000 $39.48

* For 330KB of hosted data in Amazon S3

Page 11: JavaFX and Scala in the Cloud

Cloud Data Advantages (continued)

• Insanely cheap server costs!

Number of Users Monthly Cost*

3,000 Free (S3 free tier)

10,000 $0.28

100,000 $3.84

1,000,000 $39.48

* For 330KB of hosted data in Amazon S3

Page 12: JavaFX and Scala in the Cloud

UI

Page 13: JavaFX and Scala in the Cloud

JavaFX 2.0 PlatformImmersive Application Experience

Leverage your Java skills with modern JavaFX APIs

• Cross-platform Animation, Video, Charting

• Integrate Java, JavaScript, and HTML5 in the same application

• New graphics stack takes advantage of hardware acceleration for 2D and 3D applications

• Use your favorite IDE: NetBeans, Eclipse, IntelliJ, etc.

Page 14: JavaFX and Scala in the Cloud

What is Scala

• Started in 2001 by Martin Odersky• Compiles to Java bytecodes• Pure object-oriented language• Also a functional programming language

2001• Scala Started

2003/2004• Scala v1.0

2006• Scala v2.0

2011• Scala 2.9.2 (latest)

Page 15: JavaFX and Scala in the Cloud

Why Scala?

• Shares many language features with JavaFX Script that make GUI programming easier:– Static Type Checking – Catch your errors

at compile time– Closures – Wrap behavior and pass it by

reference– Declarative – Express the UI by describing

what it should look like

Page 16: JavaFX and Scala in the Cloud

Why Scala?

• Scala also supports Type Safe DSLs!– Implicit Conversions – type safe class

extension– Operator Overloading – with standard

precedence rules– DelayedInit / @specialized – advanced

language features

(continued)

Page 17: JavaFX and Scala in the Cloud

Java vs. Scala DSLpublic class JavaFXEEDemo extends Application {

public static void main(String[] args) { launch(JavaFXEEDemo.class, args); } private SpeakerModel speakerModel = getInstance(); private TextField filter; private ChoiceBox<String> items; @Override public void start(Stage primaryStage) { primaryStage.setTitle("JavaOne Speaker List"); speakerModel.load(); EventHandler<ActionEvent> filterAction = new EventHandler<ActionEvent>() { public void handle(ActionEvent event) { String field = items.selectionModelProperty().getValue().getSelectedItem(); String text = filter.getText(); speakerModel.filter(field, text); } }; primaryStage.setScene(SceneBuilder.create() .width(625) .height(700) .fill(Color.web("#fcfcfc")) .root(StackPaneBuilder.create().children( // Background image and gradient VBoxBuilder.create().children( ImageViewBuilder.create() .image(new Image(getClass().getResourceAsStream("JavaOneLogo.png"))).build(), RectangleBuilder.create().width(625).height(50).fill(LinearGradientBuilder.create().endX(0).stops( StopBuilder.create().color(Color.WHITE).offset(0).build(), StopBuilder.create().color(Color.web("#d0cbc8")).offset(1).build() ).build()).build() ).build(), // Foreground controls VBoxBuilder.create() .padding(new Insets(100, 20, 20, 20)) .spacing(30) .children(HBoxBuilder.create() .alignment(Pos.BASELINE_LEFT) .spacing(15) .children( items = new ChoiceBox<String>( FXCollections.observableArrayList(FIRST_NAME, LAST_NAME, JOB_TITLE, COMPANY) ), filter = TextFieldBuilder.create().prefColumnCount(20).onAction(filterAction).build(), ButtonBuilder.create().text("Filter").onAction(filterAction).build(), ButtonBuilder.create().text("Clear").onAction(new EventHandler<ActionEvent>() { public void handle(ActionEvent event) { speakerModel.clearFilter(); } }).build(), ButtonBuilder.create().text("Reload").onAction(new EventHandler<ActionEvent>() { public void handle(ActionEvent event) { speakerModel.load(); } }).build() ).build(), TableViewBuilder.<Speaker>create().items(speakerModel.getFilteredData()).prefHeight(1000).columns( TableColumnBuilder.<Speaker, String>create() .text(FIRST_NAME) .cellValueFactory(new PropertyValueFactory<Speaker, String>(FIRST_NAME_FIELD)).build(), TableColumnBuilder.<Speaker, String>create() .text(LAST_NAME) .cellValueFactory(new PropertyValueFactory<Speaker, String>(LAST_NAME_FIELD)).build(), TableColumnBuilder.<Speaker, String>create() .text(JOB_TITLE) .prefWidth(200) .cellValueFactory(new PropertyValueFactory<Speaker, String>(JOB_TITLE_FIELD)).build(), TableColumnBuilder.<Speaker, String>create() .text(COMPANY) .prefWidth(212) .cellValueFactory(new PropertyValueFactory<Speaker, String>(COMPANY_FIELD)).build() ).build() ).build() ).build() ).build() ); items.getSelectionModel().selectFirst(); primaryStage.show(); }}

object ConferenceUI extends JFXApp { val model = ConferenceModel stage = new Stage { width = 625 height = 700 scene = new Scene(new StackPane()) { fill = "#fcfcfc" children = Seq( new VBox { children = Seq( new ImageView { image = new Image(getClass().getResourceAsStream("JavaOneLogo.png")) }, new Rectangle { width = 625 height = 50 fill = new LinearGradient( endX = 0, stops = Stops(WHITE, "#d0cbc8") ) } ) }, new VBox { padding = Insets(100, 20, 20, 20) spacing = 30 children = Seq( new HBox { val filter = new TextField(); val items = new ChoiceBox[ruco.TextField[Speaker]]() { items = ObservableBuffer(Speaker.firstName, Speaker.lastName, Speaker.jobTitle, Speaker.company) converter = StringConverter.toStringConverter({s:ruco.TextField[Speaker] => s.name}) } alignment = Pos.BASELINE_LEFT spacing = 15 children = Seq( items, filter, new Button("Filter") { onAction = { e:ActionEvent => model.filter(items.selectionModel().getSelectedItem(), filter.text()) } }, new Button("Clear") { onAction = { e:ActionEvent => filter.text = "" model.clear() } }, new Button("Reload") { onAction = { e:ActionEvent => filter.text = "" model.load() } } ) items.selectionModel().selectFirst() }, new TableView[Speaker](model.filteredSpeakers) { columns = Seq( new TableColumn[Speaker, String] { text = "First Name" converter = {_.firstName()} }, new TableColumn[Speaker, String] { text = "Last Name" converter = {_.lastName()} }, new TableColumn[Speaker, String] { text = "Job Title" converter = {_.jobTitle()} prefWidth = 200 }, new TableColumn[Speaker, String] { text = "Company" converter = {_.company()} prefWidth = 212 } ) prefHeight = 1000 } ) } ) } onCloseRequest = {_:Any => Platform.exit} }}

83 Lines2622 Characters

88 Lines1452 Characters

Page 18: JavaFX and Scala in the Cloud

ScalaFX Application

object ConferenceUI extends JFXApp { val model = ConferenceModel stage = new Stage { width = 625 height = 700 scene = new Scene(new StackPane()) { fill = "#fcfcfc" children = Seq( // create background // create foreground ) } }}

Page 19: JavaFX and Scala in the Cloud

Loading Images

new ImageView { image = new Image( getClass().getResourceAsStream( "JavaOneLogo.png" ) )}

Page 20: JavaFX and Scala in the Cloud

Creating Buttons

new Button("Filter") { onAction = { e:ActionEvent => model.filter(items.selectionModel().getSelectedItem(), filter.text()) }}

new Button("Clear") { onAction = { e:ActionEvent => filter.text = "" model.clear() }}

Page 21: JavaFX and Scala in the Cloud

ScalaFX Table Construction

new TableView[Speaker](model.filteredSpeakers) { columns = Seq( new TableColumn[Speaker, String] { text = "First Name" converter = {_.firstName()} }, new TableColumn[Speaker, String] { text = "Last Name" converter = {_.lastName()} } … ) prefHeight = 1000}

Page 22: JavaFX and Scala in the Cloud

DATABASEBy RRZEicons (Own work) [CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons

Page 23: JavaFX and Scala in the Cloud

Java DB / Apache Derby

• Embedded Database• Small Footprint (2.7MB)• Standards Based (Java, JDBC, SQL)• Extremely Easy to Configure

– With JDBC 4 / SE 6, just drop in the jar!

Page 24: JavaFX and Scala in the Cloud

Circumflex ORM

• Scala-based ORM(Object-RelationalMapping)

• SQL-based Query Syntax• DSL for Domain Object Definition• Lazy and Eager Fetch Strategies

Page 25: JavaFX and Scala in the Cloud

Embedded DB Config

orm.connection.driver= org.apache.derby.jdbc.EmbeddedDriverorm.connection.url=jdbc:derby:conferenceDataorm.connection.username=user1orm.connection.password=user1orm.defaultSchema=APP

Page 26: JavaFX and Scala in the Cloud

Speaker Domain Object

class Speaker extends Record[String, Speaker] { val id = "id".VARCHAR(255).NOT_NULL val company = "company".VARCHAR(255) val firstName = "firstName".VARCHAR(255) val jobTitle = "jobTitle".VARCHAR(255) val lastName = "lastName".VARCHAR(255)

def PRIMARY_KEY = id def relation = Speaker}object Speaker extends Speaker with Table[String, Speaker]

Page 27: JavaFX and Scala in the Cloud

Query the Database

def clear() { val speakers = Speaker.criteria.list() filteredSpeakers.setAll(speakers)}

def filter(field: TextField[Speaker], filterString: String) { val speakers = Speaker.criteria.add( field LIKE "%" + filterString + "%").list() filteredSpeakers.setAll(speakers)}

Page 28: JavaFX and Scala in the Cloud

CLOUD

Page 29: JavaFX and Scala in the Cloud

@jclouds

An OSSM Persistence Store

• On-demand• Self-service• Scalable• Measurable

• ™ Dave Nielsen, CloudCamp

Page 30: JavaFX and Scala in the Cloud

open source

simple: feels like java (and clojure)unit testable

tested across multiple clouds

vibrant community

Page 31: JavaFX and Scala in the Cloud

BlobStore LoadBalancer

Compute What do you want?

Portable APIs

Embeddable

Provider-Specific Hooks

github jclouds-examples

Page 32: JavaFX and Scala in the Cloud

@jclouds

Anatomy of a BlobStore Project

1.Create context

2.Get BlobStore API

3.Do stuff

4.Close context

Page 33: JavaFX and Scala in the Cloud

jclouds modularity

APIs are software focused Providers are offering focused

API + location + defaults = Provider

Page 34: JavaFX and Scala in the Cloud

Cloud Access in Scala

val context = ContextBuilder.newBuilder("aws-s3") .credentials("identity", "secret") .buildView(classOf[BlobStoreContext])

def loadFromCloud(container:String, resource:String):InputStream = { val blobStore = context.getBlobStore val blob = blobStore.getBlob(container, resource) blob.getPayload.getInput}

def close() { context.close()}

Page 35: JavaFX and Scala in the Cloud

@jclouds

Why jclouds?• Data Portability

o APIs are not as compatible as they might appear• Code Portability

o Currently 33 cloud providers• Enterprise-grade

o Move petabytes of data• Parallel operations without threading

concernso Outperforms many native SDKso GAE compatibleo Many tuning options

Page 36: JavaFX and Scala in the Cloud

@jclouds

Why jclouds?

• OSGi compatible• Clojure binding• “Invented” many standard SDK features

o e.g. sync/async APIs

• Tested!o “official” TCK for a number of cloud providerso also supports offline/local testing

Page 37: JavaFX and Scala in the Cloud

@jclouds

Why jclouds?

• Location metadatao Don’t get locked in to a provider’s deployment policy

• Does the hard work so you don’t have too Multi-part in native SDKs vs. .multipart() in

jclouds

• Strong & active communityo ~65 contributors, commercial support

Page 38: JavaFX and Scala in the Cloud

Conference App Demo

Page 39: JavaFX and Scala in the Cloud

Stephen Chin <[email protected]> | Oracle @steveonjava

Andrew Phillips <[email protected]> | jclouds @jclouds

Thank You!