View
1.078
Download
2
Category
Tags:
Preview:
Citation preview
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
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!
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
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
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
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
JavaFX 2.0 Platform Immersive 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.
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)
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
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)
Java vs. Scala DSL public 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 Lines 2622 Characters
88 Lines 1452 Characters
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 ) } } }
Loading Images
new ImageView { image = new Image( getClass().getResourceAsStream( "JavaOneLogo.png" ) ) }
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() } }
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 }
DATABASE By RRZEicons (Own work) [CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons
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!
Circumflex ORM
• Scala-based ORM (Object-Relational Mapping)
• SQL-based Query Syntax • DSL for Domain Object Definition • Lazy and Eager Fetch Strategies
Embedded DB Config orm.connection.driver= org.apache.derby.jdbc.EmbeddedDriver orm.connection.url=jdbc:derby:conferenceData orm.connection.username=user1 orm.connection.password=user1 orm.defaultSchema=APP
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]
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) }
@jclouds
An OSSM Persistence Store
• On-demand • Self-service • Scalable • Measurable
• ™ Dave Nielsen, CloudCamp
open source"
simple: feels like java (and clojure)unit testable"
tested across multiple clouds"
vibrant community"
BlobStore LoadBalancer
Compute What do you want?
Portable APIs
Embeddable Provider-Specific Hooks
github jclouds-examples
@jclouds
Anatomy of a BlobStore Project
1. Create context 2. Get BlobStore API 3. Do stuff 4. Close context
jclouds modularity"
APIs are software focused Providers are offering focused"API + location + defaults = Provider"
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() }
@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
concerns o Outperforms many native SDKs o GAE compatible o Many tuning options
@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 providers o also supports offline/local testing
@jclouds
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
Recommended