• Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,977
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
20
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Ajax on Struts: Coding an Ajax Application with Struts 2 Wednesday, October 1st, 1:50p-2:50p Ted Husted In this session, we explore  How to integrate an Ajax UI framework with a Struts 2 business framework.  Business services Struts can provide to an Ajax UI,  Basics of the Struts 2 web application framework.  Basics of the Yahoo User Interface Library (YUI).
  • 2. Ajax on Struts: Coding an Ajax Application with Struts 2 Square One University Series
  • 3. Ajax on Struts For the latest version of this presentation, visit http://slideshare.com/ted.husted For the latest version of source code, visit http://code.google.com/p/yazaar/
  • 4. Abstract Ajax is the web's hottest user interface. Struts is Java's most popular web framework. What happens when we put Ajax on Struts? During the session, we will cover  Integrating an Ajax UI with Struts 2  Using Yahoo User Interface (YUI) Library  Using Struts to provide services to Ajax UI
  • 5. Ajax on Struts What are Ajax widgets? What are we coding? Is there an Ajax architecture? How can we switch to server-side data? What about error-handling?
  • 6. Ajax on Struts What are Ajax widgets? What are we coding? Is there an Ajax architecture? How can we switch to server-side data? What about error-handling?
  • 7. What are Ajax widgets? Ajax lets scripts make requests and update content without a page refresh Widgets are “black-box” user interfrace (UI) components Typically, widgets are configured without touching the component's internals DataGrids, Calendars, Carousels, even TextBoxes
  • 8. What are Ajax widgets? Widgets can be used with any server platform  PHP, Java, .NET, Ruby, Python Client-side widget provides UI Server-side technology provides data access and business logic
  • 9. What is Apache Struts? Free open-source framework for creating Java web applications Provides three major components  Request handler  Response handler  Tag libraries for JSP, as well as Freemarker, and Velocity
  • 10. Can we use Ajax with a Struts application? XHR is just another request/response Struts can stream data as a response Use JSP scriptlets Use Ajax JSP tag libraries Use plain-vanilla Ajax libraries
  • 11. Why use Apache Struts? Mature, well-supported, well-understood Provides input validation and data conversion Interacts well with Spring, Hibernate, et al Defacto standard for Java web applications
  • 12. Where do we start? Case study  Pure Ajax prototype  Test data encapsulated as JSON  Later, replace test data with JSON via XHR Use “spikes” to separates concerns
  • 13. How do we select an Ajax library? Submit before you commit Code your own sample application Pick the one that works for you and yours We tried Dojo and YUI
  • 14. http://dojotoolkit.org/
  • 15. http://developer.yahoo.com/yui/
  • 16. Why Yahoo User Interface (YUI) Library? Well documented and supported Lots of working examples New BSD license Easy to read code Easy to hack code
  • 17. Ajax on Struts What are Ajax widgets? What are we coding? Is there an Ajax architecture? How can we switch to server-side daa? What about error-handling?
  • 18. What did we code? 1 Provide a list of employees 2 Record employee's first name, last name, extension, username, hire date, and hours worked per week. 3 Record to be updated by authorized users 4 Allow list to be filtered by first name, last name, or username. 5 Allow full or filtered list to be sorted by any field
  • 19. What did we code? Use YUI DataTable to display list Share DataTable record with data-entry form Use TabView to separate list and edit
  • 20. What are we going to code? Prototype with static data Request data from Struts 2 Action  Use Struts 2 Plugin to return JSON
  • 21. How does the Struts 2 JSON plugin work? Exposes action properties as fields in a JSON record. { stringValue : "A string value", intArray: [10, 20], map: { Zaphod : "Just this guy, you know", Arthur : "Monkey-boy" }, record: "start a named record" }
  • 22. public class ExampleOutputAction { private String stringValue = "A string value"; public String getStringValue() { return stringValue; } public void setStringValue(String value) { stringValue = value; } private int[] intArray = {10, 20}; public int[] getIntArray() { return intArray; } public void setIntArray(int[] value) { intArray = value; } private Map map = new HashMap(); public Map getMap() { return map; } public void setMap(Map value) { map = value; }
  • 23. private String nextRecord = "start a named record"; @JSON(name="record") public String getNextRecord() { return nextRecord; } //'transient' fields are not serialized @SuppressWarnings("unused") private transient String stayHome; //fields without getter method are not serialized @SuppressWarnings("unused") private String noGetterForMe; public String execute() { map.put("Zaphod", "Just this guy, you know"); map.put("Arthur", "Monkey-Boy"); return "success"; } }
  • 24. { "intArray":[10,20], "map": { "Arthur": "Monkey-Boy", "Zaphod":"Just this guy, you know"}, "record":"start a named record", "stringValue":"A string value" } { stringValue : "A string value", intArray: [10, 20], map: { Zaphod : "Just this guy, you know", Arthur : "Monkey-boy" }, record: "start a named record" }
  • 25. package actions; import java.util.Map; import java.util.HashMap; import com.googlecode.jsonplugin.annotations.JSON; import org.texturemedia.smarturls.ParentPackage; import org.texturemedia.smarturls.Result; @ParentPackage("json-default") @Result(name="success", type="json", location="") public class ExampleOutputAction { private String stringValue = "A string value"; // ...
  • 26. How did we code a UI using static data? Entry list Entry form List shares data with form
  • 27. Ajax on Struts What are Ajax widgets? What are we coding? Is there an Ajax architecture? How can we switch to server-side data? What about error-handling?
  • 28. Is there an Ajax architecture? <script src="my.js" type="text/javascript"> </script> if (typeof parent.MY != "undefined") { var MY = parent.MY; // Prototype namespace var my = parent.my; // Variable namespace } else var var MY = {}; var my = {}; var MY.Event = { // ... } var my.oEvent = { // ... instantiate rest of my and MY
  • 29. Is there an Ajax architecture? <script src="contacts.js" type="text/javascript"> </script> MY.Contacts = function(){ MY.Contacts.superclass.constructor.call(this); }; YAHOO.lang.extend(MY.Contacts,YAHOO.yazaar.flev-base);
  • 30. What's a FLEV widget? Common business workflow is  Find / List / Edit / View  Or "FLEV" The FLEV widget defines one columnset and datasource to use with all four presentations
  • 31. MY.Contact.prototype.oColumnHeaders = [ {key:"first_name", text:"First Name", sortable:true, resizeable:true, editor:"textbox", formClassName: "required", formTitle: "Enter employee's first name"}, // more entries ]; key and text are shared attributes sortable, resizable are List attribute formClassName, formtitle are Edit attributes (validation)
  • 32. MY.Contact.prototype.oResponseSchema = { fields:["id", "last_name", "first_name", "extension", "username", "hired", "hours", "editor"] }; MY.Contact.prototype.LOCAL_DATA = { result : [{id: 'c5b6bbb1-66d6-49cb-9db6- 743af6627828', last_name: 'Beeblebrox ', first_name: 'Zaphod ', extension: '555-123- 4565', username: 'zaphie ', hired: '04/01/1978', hours: -1, editor: '1'}, // ... ];
  • 33. my.oEvent.createEvent("contactLoad") my.oEvent.onContactLoadReturn = function(oData) { my.info("Firing contactLoad Event"); my.oEvent.fireEvent("contactLoad", oData); };
  • 34. <script type="text/javascript"> var onContentReady = function() { _Contact = new MY.Contact(); my.oEvent.subscribe("contactLoad",_Contact.load, _Contact); my.oEvent.onContactLoadReturn(_Contact.LOCAL_DATA); }; YAHOO.util.Event.onContentReady("elBody", onContentReady); </script>
  • 35. Ajax on Struts What are Ajax widgets? What are we coding? Is there an Ajax architecture? How can we switch to server-side data? What about error-handling?
  • 36. How can we switch over to server-side data? Create an example Action that returns example data Create a database Action that returns persistent data
  • 37. public class ContactLoadAction { private List contactLoad = new ArrayList(); @JSON(name="result") public List getContactLoad() { contactLoad.add(new Contact( "c5b6bbb1-66d6-49cb-9db6-743af6627828", "Beeblebrox", "Zaphod", "555-123-4565", "zaphie", "04/01/1978", "-1", "1" )); // ... return contacts; }
  • 38. public class Contact { public Contact() {}; public Contact(String id, String last_name, String first_name, String extension, String username, String hired, String hours, String editor) { setId(id); setLast_name(last_name); setFirst_name(first_name); setExtension(extension); setUsername(username); setHired(new Date(hired)); setHours(new Double(hours)); setEditor(editor); } private String id; public void setId(String value) { id = value; } public String getId() { return id; } // more properties ...
  • 39. How can we switch over to server-side data? Action data: {"result":[{"editor":"1","extension":"555-123- 4565","first_name":"Zaphod ", ... ]} JavaScript data: MY.Contact.prototype.LOCAL_DATA = {result:[{id: 'c5b6bbb1-66d6-49cb-9db6- 743af6627828', last_name: 'Beeblebrox ', first_name: 'Zaphod ' ...
  • 40. http://developer.yahoo.com/yui/connection/
  • 41. <script> var transaction = YAHOO.util.Connect.asyncRequest( 'POST', sUrl, callback, null); </script> var callback = { success: function(o) {/*success handler code*/}, failure: function(o) {/*failure handler code*/}, argument: [argument1, argument2, argument3] } var responseSuccess = function(o){ /* Please see the Success Case section for more * details on the response object's properties. * o.tId * o.status * o.statusText * o.getResponseHeader[ ] * o.getAllResponseHeaders * o.responseText * o.responseXML * o.argument */ };
  • 42. // my.oEvents.onContactLoadReturn(_Self.LOCAL_DATA); YAHOO.util.Connect.asyncRequest('POST', "contact- load.do", callback, null); var callback = { success : function(o) { my.oEvent.onContactLoadReturn(o.responseText); } };
  • 43. {"result":[ {"editor":"1","extension":"555-123- 4565","first_name":"Zaphod ", ... ]} MY.Contact.prototype.LOCAL_DATA = {result:[
  • 44. // my.oEvents.onContactLoadReturn(_Self.LOCAL_DATA); YAHOO.util.Connect.asyncRequest('GET', "contact-load.do", callback, null); var callback = { success : function(o) { var payload = eval("(" + o.responseText + ")"); my.oEvent.onContactLoadReturn(payload); } }; - var payload = eval("(" + o.responseText + ")") ; + var payload = jcontext.parseJSON(o.responseText); http://json.org/json.js
  • 45. What about JavaScript Hijacking? /* {"result":[{"editor":"1","extension":"555-123-4565", ... }]} */ var data = o.responseText; var payload = eval("("+data.substring(data.indexOf("/*")+2, data.lastIndexOf("*/"))+")"); my.oEvent.onContactLoadReturn(payload);
  • 46. What about JavaScript Hijacking? <package name="my-default" extends="json-default"> <result-types> <result-type name="json" class="com.googlecode.jsonplugin.JSONResult" default="true"> <param name="wrapWithComments">true</param> </result-type> </result-types> <action name="contact-load" class="actions.ContactLoadAction"> <result /> </action> </package>
  • 47. Ajax on Struts What are Ajax widgets? What are we coding? Is there an Ajax architecture? How can we switch to server-side data? What about error-handling?
  • 48. What about error handling? var callback = { success : function(o) { var payload = eval("(" + o.responseText + ")"); my.oEvent.onContactLoadReturn(payload); } }; YAHOO.util.Connect.asyncRequest('POST', "contact- load.do", callback, null);
  • 49. What about error handling? var callback = { success: function(o) {/*success handler code*/}, failure: function(o) {/*failure handler code*/}, argument: [argument1, argument2, argument3] }
  • 50. How does JSON-RPC handle errors? { "version" : "1.1", "error" : { "name" : "JSONRPCError", "code" : 123, "message" : "An error occurred parsing the request object.", "error" : { "name" : "JSONError", "message" : "Bad array", "at" : 42, "text" : "{"id":1,"method":"sum","params":[1,2,3,4,5}"} } }
  • 51. How does Struts handle exceptions? <global-results> <result name="error"/> </global-results> <global-exception-mappings> <exception-mapping exception="java.lang.Exception" result="error"/> </global-exception-mappings>
  • 52. How does Struts handle exceptions? <h2>An unexpected error has occurred</h2> <p>Please report this error to your system administrator or appropriate technical support personnel. Thank you for your cooperation.</p> <hr/> <h3>Error Message</h3> <p> <s:property value="%{exception.message}"/> </p> <hr/> <h3>Technical Details</h3> <p> <s:property value="%{exceptionStack}"/> </p>
  • 53. How does Struts handle exceptions? public String getExceptionMessage() { ActionContext context = ActionContext.getContext(); Object value = context.getValueStack(). findValue("exception.message"); if (value==null) return null; return value.toString(); } public String getExceptionStack() { ActionContext context = ActionContext.getContext(); Object value = context.getValueStack(). findValue("exceptionStack"); if (value==null) return null; return value.toString(); }
  • 54. How does Struts handle exceptions? public String execute() throws Exception { throw new Exception("Whoops!"); // return "success"; } getExceptionMessage :” “Whoops!” getExceptionStack: “java.lang.exception Whoops! at actions.ContactLoadAction ...
  • 55. How do widgets handle errors? <!-- ... --> </div> <div id="elError" class="error"></div> <div <!-- ... -->
  • 56. How do widgets handle errors? my.asyncRequestException = function (o) { alert("Error Communicating with Server! See message area for details."); var sTemplate = "<table> <tr><th>Message:&nbsp;</th> <td>{exceptionMessage}</td></tr> <tr><th>Location:</th> <td>{exceptionStack}</td></tr> </table>"; var oPayload = eval("(" + o + ")") ; document.getElementById("elError").innerHTML = sTemplate.supplant(oPayload);
  • 57. How do widgets handle errors?
  • 58. What about error handling? var onContentReady = function() { _Contact = new MY.Contact(); my.oEvent.subscribe("contactLoad",_Contact.load, _Contact); // YAHOO.util.Connect.asyncRequest('POST', "contact- load.do", callback, null); my.asyncRequest("contact-load.do", my.oEvent.onContactLoadReturn); };
  • 59. my.asyncRequest = function (sAction, fnCallback) { return YAHOO.util.Connect.asyncRequest("POST", sAction, { success : function(o) { var oPayload = eval("(" + o.responseText + ")") ; fnCallback(oPayload); } }); };
  • 60. my.asyncRequest = function (sAction, fnCallback) { return YAHOO.util.Connect.asyncRequest("POST", sAction, { success : function(o) { var oPayload = eval("(" + o.responseText + ")") ; if (oPayload.exceptionMessage) { my.asyncRequestException(oPayload); } fnCallback(oPayload); } }); };
  • 61. my.asyncRequestException = function (oPayload) { my.errorMessage(oPayload.exceptionMessage, oPayload.exceptionStack); }; my.errorMessage = function (sMessage, sStackTrace) { alert("Error Communicating with Server! // ... var sTemplate = "<table><tr> // ... var oContext = {message: sMessage, stackTrace: sStackTrace}; document.getElementById("elError").innerHTML = sTemplate.supplant(oContext); my.isMessage(true); my.error(oContext); };
  • 62. Is that all there is? During this session, we covered  Integrating an Ajax UI with Struts 2  Using Yahoo User Interface (YUI) Library  Using Struts to provide services to Ajax U
  • 63. Struts University Series
  • 64. Whats up with Planet Yazaar? Development team Yahoo! Employees  Something like Spring, Hibernate  Unlike Apache projects No formal mechanism for contributions
  • 65. Whats up with Planet Yazaar? Development team Yahoo! Employees  Something like Spring, Hibernate  Unlike Apache projects No formal mechanism for contributions A cathderal, rather than a bazaar
  • 66. What's up with Planet Yazaar? Yazaar - (Yahoo + Bazaar = Yazaar) Accepts and maintains contributor extensions and documentation Working toward "soup to nuts" project documentation Public repository with version-to-version change logs
  • 67. What's up with Planet Yazaar? Just as an aside ...  Yahoo GeoCities for public web site  Uses GoogleCode for repository  Google Group for mailing list and change logs  Yahoo 360 for Blog
  • 68. Square One University Series