Remote data

advertisement
CS569 Selected Topics in Software Engineering
Spring 2012
Mobile: Accessing remote data
Integrating remote content into
native mobile apps
1. User opens mobile app
2. App calls up the server, sends URL
3. Server figures out how to handle request
– Maybe just sends a file back
– Maybe calls some custom code (JSP or servlet)
4. Server sends HTML/XML/JSON to app
5. App interprets data
6. User interacts with app and is happy
Big picture
App
Server
Servlet
Data store
URL
Request
Query, etc
Data
HTML/XML/JSON
HTML/XML/JSON
Zooming into the app
App
UI
App
JS
UI event
Server
Servlet
Data store
URL
Request
Query, etc
Data
HTML/XML/JSON
HTML/XML/JSON
updates
Very simple example: just get html
var url = "http://www.google.com/";
var client = Ti.Network.createHTTPClient({
// function called when the response data is available
onload : function(e) {
alert('success:'+this.responseText);
},
// function called when an error occurs, including a timeout
onerror : function(e) {
alert('error'+e.error);
},
timeout : 5000 /* in milliseconds */
});
1. Make a servlet that
client.open("GET", url);
returns some HTML
client.send();
2. Hit the URL
Ti.UI.createWindow().open();
Debugging iOS apps locally on a Mac
iOS apps in simulator often can’t access GAE. Here’s a hideous workaround.
1.
2.
3.
4.
5.
6.
7.
8.
9.
Open Terminal (spotlight > Terminal)
Map 127.0.0.1 to a fake hostname
vi /etc/hosts
arrow key down to the end of the document, type letter “a” to append
add the line: 127.0.0.1
www.cs569.com
to save, type: escape :w! escape :q
Download Burp proxy from
http://portswigger.net/burp/downloadfree.html
Unzip Burp proxy, move files some place safe
Set Burp as your Mac’s proxy (Apple Symbol in top left corner > System preferences > Advanced >
Proxies; check both Web Proxy and Secure Web Proxy, set the ip address to 127.0.0.1 and port to
8080)
Go to Terminal and start up Burp
cd wherever you saved those Burp files
java -jar -Xmx2g burpsuite_v1.4.01.jar
Now that Burp is running, go to your regular browser and try to hit
http://www.cs569.com:8888/_ah/admin
By default, Burp will block access. Go to the Burp window, proxy tab, and click “Intercept” button
to turn intercept off. Now the hostname should nicely map to your GAE admin console
In your Titanium code, you should now be able to successfully retrieve data from GAE through
the fake hostname.
Debugging Android apps locally
• Very simple: just use 10.0.2.2 in your app to
refer to your own computer
Example: Getting HTML from GAE
running locally (iOS)
<%= (1+1) %>
var url = "http://www.cs569.com:8888/lectures/mobileremote/test1.jsp";
var client = Ti.Network.createHTTPClient({
// function called when the response data is available
onload : function(e) {
alert('success:'+this.responseText);
},
// function called when an error occurs, including a timeout
onerror : function(e) {
alert('error'+e.error);
1. Make a servlet that
},
returns some HTML
timeout : 5000 /* in milliseconds */
2. In iOS app, create an http
});
client, with specified
client.open("GET", url);
“onload” and “onerror”
client.send();
handlers.
3. Open, send request.
Ti.UI.createWindow().open();
Getting fancier: posting data
just like a browser would
you sent me a total of
<%= Integer.parseInt(request.getParameter("a")) +
Integer.parseInt(request.getParameter("b")) %>
var url = "http://www.cs569.com:8888/lectures/mobileremote/test2.jsp";
var client = Ti.Network.createHTTPClient({
// function called when the response data is available
onload : function(e) {
alert('success:'+this.responseText);
},
// function called when an error occurs, including a timeout
onerror : function(e) {
1. Make a servlet that
alert('error'+e.error);
returns some HTML
},
timeout : 5000 /* in milliseconds */
2. In iOS app, create an http
});
client, with specified
client.open("POST", url);
“onload” and “onerror”
client.send({a:1,b:2});
Ti.UI.createWindow().open();
handlers.
3. Open, send POST request
with parameters.
GET vs POST
• “idempotent operation”: means that an
operation can be repeated (or not) without any
side-effects
– Idempotent operations are safe to repeat, or not
• GET: use only for idempotent operations
– Such as retrieving data
– GET requests might be cached on the network or
repeated within the network multiple times or
performed automatically (e.g., by search engines)
• POST: use for all other operations
Now you have some options…
… for what your servlet does with the data…
• Use it for some computations
• Store it in the datastore
• Forward it to another server (e.g., webservice)
And some options for what to send
back…
• HTML
– Pros: No need to write a separate servlet
– Cons: Very inefficient to send and parse HTML
• XML
– Pros: Compatible with many other systems
– Cons: Moderately inefficient to send and parse
• JSON
– Pros: Highly efficient to send and parse
– Cons: More work for you, in many cases
JSP for sending back XML
<%
// Note: there can be NO blank space at the top of the page
// The header (below) MUST be the first thing in the document
response.setContentType("text/xml");
out.write("<?xml version=\"1.0\" ?>");
%>
<mydocument>
<%
for (int i = 0; i < 10; i++)
out.write("<myelement cnt=\""+i+"\" />");
%>
</mydocument>
JS for reading XML in Titanium
…
onload : function(e) {
var xml = this.responseXML;
var els = xml.getElementsByTagName("myelement");
var sum = 0;
for (var i = 0; i < els.length; i++) {
var vl = parseFloat(els.item(i).getAttribute("cnt"));
if (!isNaN(vl) && vl > 0) sum += vl;
}
alert("the sum is "+sum);
},
…
Welcome to JSON
• “JavaScript Object Notation” – looks very
similar to how objects are defined in JS
• However, it’s just a notation, and it’s
supported in other languages, too.
• Example:
{"title":"blah blah blah",
"id":110,"emails":null,
"notes":"",
"somechildobjct":{"nm":"rufus"}
}
JS for reading JSON in Titanium
…
onload : function(e) {
Ti.API.info("Received text: " + this.responseText);
var json = null;
try {
json = JSON.parse(this.responseText);
alert('success'+json);
} catch (err) {
alert('unable to parse
json:'+this.responseText);
}
},
…
Parsing JSON on the server is a little
more of a hassle
• Import the JSON Simple library
– 1. Download JAR from
http://code.google.com/p/json-simple/
– 2. Drag+drop JAR into war/WEB-INF/lib/
– 3. Right-click project > Build Path > Add libraries >
User Library > User Libraries > New > Add JARs
• Instantiate structured object with the library,
serialize it to client (see example on next slide)
Generating JSON object from server
<%@ page import="org.json.simple.JSONObject" %>
… // load some data from the data store
JSONObject json = new JSONObject();
json.put(”id", data.someValue());
json.put("title", data.someOtherValue());
json.put("emails", data.someEmailProperty());
json.put("notes", whatever());
JSONObject someSubObject = new JSONObject();
someSubObject.put("blahblah",111222);
json.put("psomeobj", someSubObject );
out.write(json.toString());
Other features of the JSON simple
library
• Generating JSON arrays
{"myarr":[1,2,4,6,8]}
(Can be a property, or a top-level object)
• Parsing string back to JSON object
– Including partial parse: you can start a parse and
then pause or cancel parsing depending on what
you find in the JSON stream
Some cautions and caveats: Reliability
• Mobile network connections are unreliable
– You need exception handlers
– You can proactively retrieve data and cache it so
it’s available later, even if no network is present
– You can buffer data that is destined for the server,
and flush it later on
Some cautions and caveats: Usability
• Mobile network connections are slow
– If you do network operations synchronously, you
will lock up the user interface
– Do everything you can to perform network
operations asynchronously (as I have shown you)
– Try to minimize the number of times the user has
to wait for network operations to complete
• E.g., do operations in background while user can
continue working in the user interface
• Another example: have the user log in just once, and
with the option to stay logged in for a week
Some cautions and caveats:
Performance
• Mobile network connections are slow (contd)
– Try to avoid repeatedly downloading the same
data or code
• E.g., display the user interface and only transmit data;
don’t repeatedly download the UI (as in a web page)
– Avoid transmitting data unnecessarily
• E.g., define your JSP to accept a “verbose” parameter
that tells how much of a dataset should be sent
– Minimize network roundtrips
Some cautions and caveats: Security
• Mobile network connections are insecure
– Consider using https: all data are encrypted
• Although this does require more CPU and does impose
more network overhead
– Consider selectively encrypting some parameters
• Ditto, but not quite as bad; could be a good
compromise between https and no encryption at all
– Be sure to encrypt any usernames or passwords
that you store on the user’s device!
I’ll return to these caveats with more
concrete advice
• In the mean time…
– Get the “install and configure” part of your mobile
How-To finished this week
– Take a look at the pure-JS libraries available for
retrieving data in a web application (i.e., outside
of a mobile app)
• A.k.a. “AJAX” (Asynchronous Javascript And XML),
though the data do not need to be in XML format.
• http://www.w3schools.com/ajax/ajax_intro.asp
Download