540 likes | 555 Views
95-733 Internet of Things Week Two. Week Two. Objectives: Understand AJAX using Java and JavaScript Briefly review JSONP Introduce Websockets Introduce Websockets and MQTT for IOT. A Complete Example From IBM. Demonstrations: See article by Philip McCarthy on Ajax at:
E N D
95-733 Internet of ThingsWeek Two Carnegie Mellon Heinz College
Week Two • Objectives: • Understand AJAX using Java and JavaScript • Briefly review JSONP • Introduce Websockets • Introduce Websockets and MQTT for IOT Carnegie Mellon Heinz College
A Complete Example From IBM Demonstrations: See article by Philip McCarthy on Ajax at: http://www.ibm.com/developerworks/library/j-ajax1/ Eclipse workspace mm6/95-733 Visit http://localhost:8080/AjaxProject/index.jsp Netbeans workspace mm6/95-733/AjaxUsingNetbeans ACoolAjaxShoppingCart and ACoolAjaxShoppingCartImproved Carnegie Mellon Heinz College
Main Features of Index.jsp (1) This page needs access to these imported Java packages. <%@ page import="java.util.*" %> <%@ page import="developerworks.ajax.store.*"%> The store package contains Item.java, Catalog.java and Cart.java Carnegie Mellon Heinz College
Main Features of Index.jsp (2) The header holds pointers to script code to be included in the page and then executed by the browser. <script type="text/javascript" language="javascript" src="ajax1.js"> </script> <script type="text/javascript" language="javascript" src="cart.js"> </script> This is not constrained by the same origin policy! These scripts could be fetched from any URL. Carnegie Mellon Heinz College
Main Features of Index.jsp (3) The table body tag encloses table rows that are generated on the server. This is Java (part of JSP) and is not JavaScript. <tbody> <% for (Iterator<Item> I = new Catalog().getAllItems().iterator(); I.hasNext() ; ) { Item item = I.next(); %> Carnegie Mellon Heinz College
Main Features of Index.jsp (4) The addToCart call is a call on JavaScript. <!-- For each Item do --> <tr> <td><%= item.getName() %></td> <td><%= item.getDescription() %></td> <td><%= item.getFormattedPrice() %></td> <td> <button onclick="addToCart('<%= item.getCode() %>')"> Add to Cart </button> </td> </tr> <% } %> </tbody> Carnegie Mellon Heinz College
Main Features of Index.jsp (5) The <ul> and <span> tags each have a unique identifier. These identifier will be used by the event handler. <div style=”…”> <h2>Cart Contents</h2> <ul id="contents"></ul> Total cost: <span id="total">$0.00</span> </div> Carnegie Mellon Heinz College
Main Features of Item.java Getter and setters on code, name,description and price. package developerworks.ajax.store; import java.math.BigDecimal; publicclass Item { private String code; private String name; private String description; privateintprice; public Item(String code,String name,String description,int price) { this.code=code; this.name=name; this.description=description; this.price=price; } public String getCode() { returncode; } Carnegie Mellon Heinz College
Main Features of Catalog.java(1) package developerworks.ajax.store; import java.util.*; publicclass Catalog { privatestatic Map<String,Item> items; static { items = new HashMap<String,Item>(); items.put("hat001",new Item("hat001", "Hat","Stylish bowler hat (SALE!)", 1999)); : } Carnegie Mellon Heinz College
Main Features of Catalog.java(2) public Collection<Item> getAllItems() { returnitems.values(); } publicboolean containsItem(String itemCode) { returnitems.containsKey(itemCode); } public Item getItem(String itemCode) { returnitems.get(itemCode); } } Carnegie Mellon Heinz College
Main Features of Cart.java(1) package developerworks.ajax.store; public class Cart { private HashMap<Item,Integer> contents; public Cart() { contents = new HashMap<Item,Integer>(); } Carnegie Mellon Heinz College
Main Features of Cart.java(2) public void addItem(String itemCode) { Catalog catalog = new Catalog(); if (catalog.containsItem(itemCode)) { Item item = catalog.getItem(itemCode); int newQuantity = 1; if (contents.containsKey(item)) { Integer currentQuantity = contents.get(item); newQuantity += currentQuantity.intValue(); } contents.put(item, new Integer(newQuantity)); } } Carnegie Mellon Heinz College
Main Features of Cart.java(3) public String toXml() { StringBuffer xml = new StringBuffer(); xml.append("<?xml version=\"1.0\"?>\n"); xml.append("<cart generated=\""+ System.currentTimeMillis()+ "\" total=\""+getCartTotal()+"\">\n"); for (Iterator<Item> I = contents.keySet().iterator() ; I.hasNext() ; ) { Item item = I.next(); int itemQuantity = contents.get(item).intValue(); xml.append("<item code=\""+item.getCode()+"\">\n"); xml.append("<name>"); : xml.append("</cart>\n"); return xml.toString(); } Carnegie Mellon Heinz College
Main Features of CartServlet.java(1) private Cart getCartFromSession(HttpServletRequest req) { HttpSession session = req.getSession(true); Cart cart = (Cart)session.getAttribute("cart"); if (cart == null) { cart = new Cart(); session.setAttribute("cart", cart); } return cart; } Carnegie Mellon Heinz College
Main Features of CartServlet.java(2) publicvoid doPost(HttpServletRequest req, HttpServletResponse res) throws java.io.IOException { Cart cart = getCartFromSession(req); String action = req.getParameter("action"); String item = req.getParameter("item"); Carnegie Mellon Heinz College
Main Features of CartServlet.java(3) if ((action != null)&&(item != null)) { if ("add".equals(action)) { cart.addItem(item); } elseif ()….. } String cartXml = cart.toXml(); res.setContentType("text/xml"); res.getWriter().write(cartXml); } Carnegie Mellon Heinz College
Main Features Axis1.js (1) /* * Returns an new XMLHttpRequest object, or false if the browser * doesn't support it */ function newXMLHttpRequest() { var xmlreq = false; // Create XMLHttpRequest object in non-Microsoft browsers if (window.XMLHttpRequest) { xmlreq = new XMLHttpRequest(); } Carnegie Mellon Heinz College
Main Features Axis1.js (2) else if (window.ActiveXObject) { try { // Try to create XMLHttpRequest in later versions of Internet Explorer xmlreq = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e1) { // Failed to create required ActiveXObject try { // Try version supported by older versions of Internet Explorer xmlreq = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e2) { // Unable to create an XMLHttpRequest by any means xmlreq = false; } } } Carnegie Mellon Heinz College
Main Features Axis1.js (3) /* Returns a function that waits for the specified XMLHttpRequest to complete, then passes it XML response to the given handler function. req - The XMLHttpRequest whose state is changing responseXmlHandler - Function to pass the XML response to */ function getReadyStateHandler(req, responseXmlHandler) { Carnegie Mellon Heinz College
Main Features Axis1.js (4) // Return an anonymous function that listens to the // XMLHttpRequest instance return function () { // If the request's status is "complete" if (req.readyState == 4) { // Check that we received a successful response from the server if (req.status == 200) { // Pass the XML payload of the response to the handler // function. responseXmlHandler(req.responseXML); } else { // An HTTP problem has occurred alert("HTTP error "+req.status+": "+req.statusText); }}}} Carnegie Mellon Heinz College
Main Features Cart.js (1) // Timestamp of cart that page was last updated with var lastCartUpdate = 0; // Adds the specified item to the shopping cart, via Ajax call // itemCode - product code of the item to add function addToCart(itemCode) { var req = newXMLHttpRequest(); req.onreadystatechange = getReadyStateHandler(req, updateCart); req.open("POST", "cart.do", true); req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); req.send("action=add&item="+itemCode); } Establish handler and pack up and send the request. Carnegie Mellon Heinz College
Main Features Cart.js (2) /* * Update shopping-cart area of page to reflect contents of cart * described in XML document. */ function updateCart(cartXML) { var cart = cartXML.getElementsByTagName("cart")[0]; var generated = cart.getAttribute("generated"); if (generated > lastCartUpdate) { lastCartUpdate = generated; var contents = document.getElementById("contents"); contents.innerHTML = ""; Carnegie Mellon Heinz College
Main Features Cart.js (3) var items = cart.getElementsByTagName("item"); for (var I = 0 ; I < items.length ; I++) { var item = items[I]; var name = item.getElementsByTagName("name")[0].firstChild.nodeValue; var quantity = item.getElementsByTagName("quantity")[0].firstChild.nodeValue; var listItem = document.createElement("li"); listItem.appendChild(document.createTextNode(name+" x "+quantity)); contents.appendChild(listItem); } } document.getElementById("total").innerHTML = cart.getAttribute("total"); } Carnegie Mellon Heinz College
Shopping Cart Interaction post addToCart(itemCode) XML XMLHTTPRequest UpdateCart reads XML writes HTML Anonymous handler - Executed on state change. - req.responseXML points to the root of the XML - calls updateCart HTML Button Carnegie Mellon Heinz College
Main Features Cart.js (4) The handler is reading data with the following format: <?xml version="1.0"?> <cart generated="1200367057873" total="$19.99"> <item code="str001"> <name>String</name> <quantity>1</quantity> </item> </cart> Carnegie Mellon Heinz College
Another Example From Sebesta Chapter 10 A form is required to collect name, address, zip, city, and state. The zip code entry causes an asynchronous call on a servlet to automatically complete the city and state fields. The asynchronous call is made when the user blurs (or moves away from) the zip code field. This demo is in the Netbeans project mm6/www/95-733/AjaxUsingNetbeans/SebestaAjaxExample. Carnegie Mellon Heinz College
Index.jsp Main Features <tr> <td> Zip Code: </td> <td> <input type = "text" name="zip" size = "10" onblur = "getPlace(this.value)" /> </td> </tr> <tr> <td> City </td> <td> <input type = "text" name="city" id= "city" size = "30" /> </td> </tr> <tr> <td> State </td> <td> <input type = "text" name="state" id="state" size = "30" /></td> </tr> Locations written to by ajax handler Carnegie Mellon Heinz College
Javascript Main Features function getPlace(zip) { var xhr; if(window.XMLHttpRequest) xhr = new XMLHttpRequest(); else xhr = ActiveXObject("Microsoft.XMLHTTP"); xhr.onreadystatechange = function() { if(xhr.readyState == 4) { var result = xhr.responseText; var place = result.split(', '); document.getElementById("city").value = place[0]; document.getElementById("state").value = place[1]; } } xhr.open("GET", "ZipToCityStateServlet?zip="+zip,true); xhr.send(null); } Carnegie Mellon Heinz College
Two Servlets - One for AJAX protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); try { // Return simple text to Ajax request if(request.getParameter("zip").equals("15216")) out.println("Pittsburgh, PA"); else out.println("New York, NY"); } finally { out.close(); } } Carnegie Mellon Heinz College
Another For the Form out.println("<h2>Name: " + request.getParameter("name") + "</h2>"); out.println("<h2>Street: " + request.getParameter("street") + "</h2>"); out.println("<h2>Zip: " + request.getParameter("zip") + "</h2>"); out.println("<h2>City: " + request.getParameter("city") + "</h2>"); out.println("<h2>State: " + request.getParameter("state") + "</h2>"); Carnegie Mellon Heinz College
XML Or JSON ? (1) <Person firstName="John" lastName="Smith"> <Address> <streetAddress>21 2nd Street</streetAddress> <city>New York</city> <state>NY</state> <postalCode>10021</postalCode> </Address> <phoneNumber type="home"> 212 555-1234 </phoneNumber> <phoneNumber type="fax"> 646 555-4567 </phoneNumber> </Person> From Wikipedia.org Carnegie Mellon Heinz College
XML Or JSON ? (2) { "firstName": "John", "lastName": "Smith", "address": { "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", "postalCode": "10021" }, "phoneNumbers": [ { "type": "home", "number": "212 555-1234" }, { "type": "fax", "number": "646 555-4567" } ] } If this text is in the variable coolText, then we can create a JavaScript object with the line of code: var x = eval("(" + coolText + ")"); and access the data with x.phoneNumbers[0]. Better to use JSON.parse(text) and JSON.stringify(obj). From Wikipedia.org Carnegie Mellon Heinz College
Which To Use? Both formats are textual and are coarse grained. JSON has some advantages over XML: JSON messages are smaller and therefore faster. No namespaces JSON is simpler and simple is good. JSON has become very popular XML has some advantages over JSON: Namespaces Languages adopted by many industries XSLT can be used to transform a response into an appropriate format. XML Signature and XML Encryption not available for JSON. Carnegie Mellon Heinz College
jQuery AJAX Example <!DOCTYPE html> <html> <head> <script src="jquery.js"></script> <script> $(document).ready(function(){ $("button").click(function(){ $("div").load('test1.txt'); }); }); </script> </head> <body> <div><h2>Let AJAX change this text</h2></div> <button>Change Content</button> </body> </html> The syntax is: $(selector).action() A $ sign to define/access jQuery A (selector) to "query (or find)" HTML elements A jQuery action() to be performed on the element(s) Document ready before running jQuery. http://www.w3schools.com/jquery/tryit.asp?filename=tryjquery_ajax_load Carnegie Mellon Heinz College
Dojo Ajax Example dojo.io.bind ( { url : “getCityState.php?zip=“ + zip, load: function( type, data, evt ) { var place = data.split(‘, ’); if(dojo.byID(“city”).value = “” dojo.byID(“city”).value = place[0]; if(dojo.byID(“state”).value = “” dojo.byID(“state”).value = place[1]; }, error: function(type, data, evt ) { alert(“Error in request, returned data:”+data); }, method: “GET”, mimetype: “text/plain” } ); Note the use of JS object to describe an AJAX call. From Pg. 422 Of Sebesta Carnegie Mellon Heinz College
JSONP Suppose we want to visit a foreign data source from within the browser. We want to make a request and retrieve data. Or, perhaps, we want to transmit information to another site – fire and forget. Why?Perhaps we want to write a client side mashup. Or, suppose we want to simply send data to a foreign server. Why? Consider Google Analytics. How does that system work? Problem: The Same Origin Policy is enforced by the browser. Carnegie Mellon Heinz College
JSONP Example 1) Visit https://developer.yahoo.com/yql/console/ 2) Choose JSON with and without a function name in the callback box. 3) Use the Yahoo Query Language (YQL: select * from geo.places where text=”Adelaide, Au” 4) Note the REST query on the bottom of the page. The REST query includes the callback function name 5) Experiment. Visit http://rss.nytimes.com/services/xml/rss/nyt/Technology.xml 6) Try select * from rss where url = "http://rss.nytimes.com/services/xml/rss/nyt/Technology.xml" 7) Use YQL to get the same XML content in JSON and using JSONP. Carnegie Mellon Heinz College
Using JSONP Rather than AJAX The <script> and <img> elements are not subject to the same origin policy. Foreign scripts or images may be accessed. The code below dynamically creates a script tag, places it in the HTML head section, fetches the script, and executes it. Then, it deletes the script element. function jsonp(url) { // user defined function var head = document.head; // point to head var script = document.createElement("script"); // create script script.setAttribute("src", url); // set script attribute src to url head.appendChild(script); // add to head and execute the head.removeChild(script); // script that is returned } // remove script element Carnegie Mellon Heinz College
JSONP Problem The problem is the client executes the code after it is fetched. The data fetched is treated as a Javascript block statement. This results in a syntax error – if the data is JSON - not something we want to execute. Solution: We send the name of a function along with the request. The function name is included in the response by the server. When the response arrives the function is called. Suppose the request includes the function name foo. A response might look like this: foo({"message" : "Hello" }) We provide the function foo that takes a Javascript object parameter. Carnegie Mellon Heinz College
Example: Handle JSONP in Java @WebServlet(urlPatterns = {"/JSONServlet"}) public class JSONServlet extends HttpServlet { protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); System.out.println("JSON Servlet has a visitor"); try (PrintWriter out = response.getWriter()) { // the query parameter is method=callbackName String name = request.getParameter("method"); // name is the callBack // return JSON object as a String {"id" : "mike"} out.println(name + "({\"id\" : \"mike\" })"); } } Carnegie Mellon Heinz College
Using JSONP On the client <!DOCTYPE html> <!-- Index.html This is a simple demonstration of using JSONP. --> <html> <head> <title>Experiment with JSONP</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Fetch the script from web site --> <script src="jsonpscript.js"></script> Carnegie Mellon Heinz College
<!-- provide a callback handler named coolBeans --> <script> function coolBeans(x) { alert("In coolBeans with " + x.id + " from server"); } </script> </head> <body> <div> <!-- On click, get some JSON data from the JSONServlet and pass it to the callBackHandler. --> <button onclick="cooljsonp('JSONServlet','callBackHandler')">Click me for some JSON </button> <!-- On click, get some JSON data from the JSONServlet and pass it to the callBackHandler coolBeans --> <button onclick="cooljsonp('JSONServlet','coolBeans')">Or click me for some JSON </button> </div> </body> </html> Carnegie Mellon Heinz College
Using JSONP Javascript <!– jsonpscript.js function cooljsonp(url,myCallback) { alert("Calling " + url + " with " + myCallback + " for callback"); var head = document.head; var script = document.createElement("script"); script.setAttribute("src", url + '?' + 'method=' + myCallback); head.appendChild(script); head.removeChild(script); } Carnegie Mellon Heinz College
Using JSONP Javascript <!– jsonpscript.js function callBackHandler(jsonObject) { alert("callBack called"); // display the id property value // treating it as a JSON object alert(jsonObject.id); // covert the jsonObject to a String var response = JSON.stringify(jsonObject); alert(response); } Carnegie Mellon Heinz College
Web Sockets Javascript API defined by W3C – Available on many browsers. Java client side API and server side API see JSR 356 part of JEE 7 From Oracle Carnegie Mellon Heinz College
Web Sockets Lifecycle Events The typical lifecycle event of a WebSocket interaction goes as follows: One peer (a client) initiates the connection by sending an HTTP handshake request. The other peer (the server) replies with a handshake response. The connection is established. From now on, the connection is completely symmetrical. Both peers send and receive messages. One of the peers closes the connection. Most of the WebSocket lifecycle events can be mapped to Java methods, both in the annotation-driven and interface-driven approaches. Note that Web Sockets don’t describe the conversation that will take place. This is left to the layer above the web socket layer. From Oracle Carnegie Mellon Heinz College
Client side Web Sockets (1) // Establish the socket in Javascript: // Open a new WebSocket connection (ws), use wss for secure // connections over SSL. var wsUri = "ws://" + document.location.host + document.location.pathname + "whiteboardendpoint"; var websocket = new WebSocket(wsUri); Carnegie Mellon Heinz College
Client side Web Sockets (2) // Prepare to send and receive data. // A callback function is invoked for each new message from // the server websocket.onmessage = function(evt) { onMessage(evt) }; function onMessage(evt) { // Called for us when a message drawImageText(evt.data); // arrives. } function sendText(json) { // We call this when we want. websocket.send(json); } Carnegie Mellon Heinz College
Server side Web Sockets in Java (1) // The Decode is used for messages arriving from the peer. // The Encoder is used for messages being sent to the peer. @ServerEndpoint(value="/whiteboardendpoint", encoders = {FigureEncoder.class}, decoders = {FigureDecoder.class}) public class MyWhiteboard { // create a synchronized (thread safe) set of sessions in a hashset // names this collection peers private static Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>()); Carnegie Mellon Heinz College