The document discusses using a cloud data architecture where the user's view of data is small to medium sized and mostly read-only. It notes advantages like offline operation, responsive performance, high availability and scalability at low cost. Specifically, it shows hosting 330KB of data for 1 million users would cost around $39 per month on Amazon S3.
6. 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
7. 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!
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. 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. 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
11. 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
13. 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.
14. 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
15. 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
16. 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
17. Java vs. Scala DSL
public
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
{
83 Lines 88 Lines
ImageViewBuilder.create()
val
filter
=
new
TextField();
.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(
2622 Characters 1452 Characters
VBoxBuilder.create()
items,
.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}
}
}
18. 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
)
}
}
}
21. 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
}
22. DATABASE
By RRZEicons (Own work) [CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons
23. 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!
25. 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
26. 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]
27. 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)
}
29. An OSSM Persistence Store
• On-demand
• Self-service
• Scalable
• Measurable
• ™ Dave Nielsen, CloudCamp
@jclouds
30. open source"
simple: feels like java (and clojure)unit testable"
tested across multiple clouds"
vibrant community"
31. Portable APIs
BlobStore
LoadBalancer
Compute
What do you want?
Provider-Specific Hooks
Embeddable
github jclouds-examples
32. Anatomy of a BlobStore Project
1. Create context
2. Get BlobStore API
3. Do stuff
4. Close context
@jclouds
33. jclouds modularity"
APIs are software
focused Providers are
offering focused"
API + location + defaults
= Provider"
34. 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()
}
35. 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
36. 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
37. 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