240 likes | 380 Views
CS569 Selected Topics in Software Engineering Spring 2012. Mobile: Accessing remote data. Integrating remote content into native mobile apps. User opens mobile app App calls up the server, sends URL Server figures out how to handle request Maybe just sends a file back
E N D
CS569 Selected Topics in Software EngineeringSpring 2012 Mobile: Accessing remote data
Integrating remote content into native mobile apps • User opens mobile app • App calls up the server, sends URL • Server figures out how to handle request • Maybe just sends a file back • Maybe calls some custom code (JSP or servlet) • Server sends HTML/XML/JSON to app • App interprets data • 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 AppUI AppJS Server Servlet Data store UI event URL Request Query, etc Data HTML/XML/JSON HTML/XML/JSON updates
Very simple example: just get html varurl = "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(); Make a servlet that returns some HTML Hit the URL
Debugging iOS apps locally on a Mac iOS apps in simulator often can’t access GAE. Here’s a hideous workaround. • 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) %> varurl = "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(); Make a servlet that returns some HTML In iOS app, create an http client, with specified “onload” and “onerror” handlers. 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")) %> varurl = "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(); Make a servlet that returns some HTML In iOS app, create an http client, with specified “onload” and “onerror” handlers. 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("<myelementcnt=\""+i+"\" />"); %> </mydocument>
JS for reading XML in Titanium … onload : function(e) { var xml = this.responseXML; varels = 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); varjson = 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 JSONObjectjson = new JSONObject(); json.put(”id", data.someValue()); json.put("title", data.someOtherValue()); json.put("emails", data.someEmailProperty()); json.put("notes", whatever()); JSONObjectsomeSubObject = 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