JavaFX and Scala in the Cloud

1,998 views

Published on

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

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,998
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
20
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide
  • Stage.add??
  • JavaFX and Scala in the Cloud

    1. 1. Stephen Chin | Oracle @steveonjava Andrew Phillips | jclouds @jcloudsJavaFX and Scala in the Cloud
    2. 2. +
    3. 3. HeavenPhoto by Alberto Fernandez Fernandez
    4. 4. When This Architecture Makes Sense• Data is mostly read-only – Transactional updates still require a server (but can be simpler/smaller)• Users 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
    5. 5. 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!
    6. 6. 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
    7. 7. 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
    8. 8. 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
    9. 9. 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
    10. 10. UI
    11. 11. JavaFX 2.0 PlatformImmersive Application ExperienceLeverage your Java skills with modernJavaFX 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.
    12. 12. What is Scala 2001 2006 • Scala Started • Scala v2.0 2003/2004 2011 • Scala v1.0 • Scala 2.9.2 (latest)• Started in 2001 by Martin Odersky• Compiles to Java bytecodes• Pure object-oriented language• Also a functional programming language
    13. 13. 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
    14. 14. Why Scala? (continued)• Scala also supports Type Safe DSLs! – Implicit Conversions – type safe class extension – Operator Overloading – with standard precedence rules – DelayedInit / @specialized – advanced language features
    15. 15. Java vs. Scala DSLpublic class JavaFXEEDemo extends Application { object ConferenceUI extends JFXApp { val model = ConferenceModel public static void main(String[] args) { stage = new Stage { launch(JavaFXEEDemo.class, args); width = 625 } height = 700 scene = new Scene(new StackPane()) { private SpeakerModel speakerModel = getInstance(); fill = "#fcfcfc" private TextField filter; children = Seq( private ChoiceBox<String> items; new VBox { children = Seq( @Override new ImageView { public void start(Stage primaryStage) { image = new Image(getClass().getResourceAsStream("JavaOneLogo.png")) primaryStage.setTitle("JavaOne Speaker List"); }, speakerModel.load(); new Rectangle { EventHandler<ActionEvent> filterAction = new EventHandler<ActionEvent>() { width = 625 public void handle(ActionEvent event) { height = 50 String field = items.selectionModelProperty().getValue().getSelectedItem(); fill = new LinearGradient( String text = filter.getText(); endX = 0, speakerModel.filter(field, text); stops = Stops(WHITE, "#d0cbc8") } ) }; } primaryStage.setScene(SceneBuilder.create() ) .width(625) }, .height(700) new VBox { .fill(Color.web("#fcfcfc")) padding = Insets(100, 20, 20, 20) .root(StackPaneBuilder.create().children( spacing = 30 // Background image and gradient children = Seq( VBoxBuilder.create().children( new HBox { ImageViewBuilder.create() val filter = new TextField(); 83 Lines 88 Lines .image(new Image(getClass().getResourceAsStream("JavaOneLogo.png"))).build(), val items = new ChoiceBox[ruco.TextField[Speaker]]() { RectangleBuilder.create().width(625).height(50).fill(LinearGradientBuilder.create().endX(0).stops( items = ObservableBuffer(Speaker.firstName, Speaker.lastName, Speaker.jobTitle, Speaker.company) StopBuilder.create().color(Color.WHITE).offset(0).build(), converter = StringConverter.toStringConverter({s:ruco.TextField[Speaker] => s.name}) StopBuilder.create().color(Color.web("#d0cbc8")).offset(1).build() } ).build()).build() alignment = Pos.BASELINE_LEFT ).build(), spacing = 15 // Foreground controls children = Seq( VBoxBuilder.create() items, 2622 Characters 1452 Characters .padding(new Insets(100, 20, 20, 20)) filter, .spacing(30) new Button("Filter") { .children(HBoxBuilder.create() onAction = { e:ActionEvent => .alignment(Pos.BASELINE_LEFT) model.filter(items.selectionModel().getSelectedItem(), filter.text()) .spacing(15) } .children( }, items = new ChoiceBox<String>( new Button("Clear") { FXCollections.observableArrayList(FIRST_NAME, LAST_NAME, JOB_TITLE, COMPANY) onAction = { e:ActionEvent => ), filter.text = "" filter = TextFieldBuilder.create().prefColumnCount(20).onAction(filterAction).build(), model.clear() ButtonBuilder.create().text("Filter").onAction(filterAction).build(), } ButtonBuilder.create().text("Clear").onAction(new EventHandler<ActionEvent>() { }, public void handle(ActionEvent event) { new Button("Reload") { speakerModel.clearFilter(); onAction = { e:ActionEvent => } filter.text = "" }).build(), model.load() ButtonBuilder.create().text("Reload").onAction(new EventHandler<ActionEvent>() { } public void handle(ActionEvent event) { } speakerModel.load(); ) } items.selectionModel().selectFirst() }).build() }, ).build(), new TableView[Speaker](model.filteredSpeakers) { TableViewBuilder.<Speaker>create().items(speakerModel.getFilteredData()).prefHeight(1000).columns( columns = Seq( TableColumnBuilder.<Speaker, String>create() new TableColumn[Speaker, String] { .text(FIRST_NAME) text = "First Name" .cellValueFactory(new PropertyValueFactory<Speaker, String>(FIRST_NAME_FIELD)).build(), converter = {_.firstName()} TableColumnBuilder.<Speaker, String>create() }, .text(LAST_NAME) new TableColumn[Speaker, String] { .cellValueFactory(new PropertyValueFactory<Speaker, String>(LAST_NAME_FIELD)).build(), text = "Last Name" TableColumnBuilder.<Speaker, String>create() converter = {_.lastName()} .text(JOB_TITLE) }, .prefWidth(200) new TableColumn[Speaker, String] { .cellValueFactory(new PropertyValueFactory<Speaker, String>(JOB_TITLE_FIELD)).build(), text = "Job Title" TableColumnBuilder.<Speaker, String>create() converter = {_.jobTitle()} .text(COMPANY) prefWidth = 200 .prefWidth(212) }, .cellValueFactory(new PropertyValueFactory<Speaker, String>(COMPANY_FIELD)).build() new TableColumn[Speaker, String] { ).build() text = "Company" ).build() converter = {_.company()} ).build() prefWidth = 212 ).build() } ); ) items.getSelectionModel().selectFirst(); prefHeight = 1000 primaryStage.show(); } } )} } ) } onCloseRequest = {_:Any => Platform.exit} } }
    16. 16. ScalaFX Applicationobject 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 ) } }}
    17. 17. Loading Imagesnew ImageView { image = new Image( getClass().getResourceAsStream( "JavaOneLogo.png" ) )}
    18. 18. Creating Buttonsnew Button("Filter") { onAction = { e:ActionEvent => model.filter(items.selectionModel().getSelectedItem(), filter.text()) }}new Button("Clear") { onAction = { e:ActionEvent => filter.text = "" model.clear() }}
    19. 19. ScalaFX Table Constructionnew 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}
    20. 20. DATABASEBy RRZEicons (Own work) [CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons
    21. 21. 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!
    22. 22. Circumflex ORM• Scala-based ORM (Object-Relational Mapping)• SQL-based Query Syntax• DSL for Domain Object Definition• Lazy and Eager Fetch Strategies
    23. 23. Embedded DB Configorm.connection.driver= org.apache.derby.jdbc.EmbeddedDriverorm.connection.url=jdbc:derby:conferenceDataorm.connection.username=user1orm.connection.password=user1orm.defaultSchema=APP
    24. 24. Speaker Domain Objectclass 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]
    25. 25. Query the Databasedef 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)}
    26. 26. CLOUD
    27. 27. An OSSM Persistence Store • On-demand • Self-service • Scalable • Measurable • ™ Dave Nielsen, CloudCamp@jclouds
    28. 28. open sourcesimple: feels like java (and clojure)unit testabletested across multiple cloudsvibrant community
    29. 29. Portable APIs BlobStore LoadBalancer What do you Compute want?Provider-Specific HooksEmbeddable github jclouds-examples
    30. 30. Anatomy of a BlobStore Project1.Create context2.Get BlobStore API3.Do stuff4.Close context@jclouds
    31. 31. jclouds modularityAPIs are softwarefocused Providers areoffering focusedAPI + location + defaults= Provider
    32. 32. Cloud Access in Scalaval 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()}
    33. 33. 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 concerns o Outperforms many native SDKs o GAE compatible o Many tuning options@jclouds
    34. 34. 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 providers o also supports offline/local testing@jclouds
    35. 35. Why jclouds?• Location metadata o Don’t get locked in to a provider’s deployment policy• Does the hard work so you don’t have to o Multi-part in native SDKs vs. .multipart() in jclouds• Strong & active community o ~65 contributors, commercial support@jclouds
    36. 36. Conference App Demo
    37. 37. Stephen Chin <stephen.chin@oracle.com> | Oracle @steveonjavaAndrew Phillips <andrew@jclouds.org> | jclouds @jclouds Thank You!

    ×