mobile: accessing remote data cs569 selected topics in software engineering spring 2012
TRANSCRIPT
Mobile: Accessing remote data
CS569 Selected Topics in Software EngineeringSpring 2012
Integrating remote content into native mobile apps
1. User opens mobile app2. App calls up the server, sends URL3. 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 app5. App interprets data6. User interacts with app and is happy
Big picture
App Server Servlet Data store
URL
RequestQuery, etc
Data
HTML/XML/JSON
HTML/XML/JSON
Zooming into the app
AppUI Server Servlet Data store
URL
RequestQuery, etc
Data
HTML/XML/JSON
HTML/XML/JSON
AppJS
UI event
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 */ }); client.open("GET", url); client.send(); Ti.UI.createWindow().open();
1. Make a servlet that returns some HTML
2. Hit the URL
Debugging iOS apps locally on a Mac
iOS apps in simulator often can’t access GAE. Here’s a hideous workaround.
1. Open Terminal (spotlight > Terminal)2. Map 127.0.0.1 to a fake hostname
vi /etc/hostsarrow key down to the end of the document, type letter “a” to appendadd the line: 127.0.0.1 www.cs569.comto save, type: escape :w! escape :q
3. Download Burp proxy from http://portswigger.net/burp/downloadfree.html
4. Unzip Burp proxy, move files some place safe5. 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)6. Go to Terminal and start up Burp
cd wherever you saved those Burp filesjava -jar -Xmx2g burpsuite_v1.4.01.jar
7. Now that Burp is running, go to your regular browser and try to hit http://www.cs569.com:8888/_ah/admin
8. 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
9. 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); }, timeout : 5000 /* in milliseconds */ }); client.open("GET", url); client.send(); Ti.UI.createWindow().open();
1. Make a servlet that returns some HTML
2. In iOS app, create an http client, with specified “onload” and “onerror” handlers.
3. Open, send request.
Getting fancier: posting datajust 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) { alert('error'+e.error); }, timeout : 5000 /* in milliseconds */ }); client.open("POST", url); client.send({a:1,b:2}); Ti.UI.createWindow().open();
1. Make a servlet that returns some HTML
2. In iOS app, create an http client, with specified “onload” and “onerror” 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 storeJSONObject 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