![Page 1: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/1.jpg)
Ajax for Java developers… but without the suckage
![Page 2: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/2.jpg)
Who is this jabronie? (aka: The Braggart Slide™)
• Frank W. Zammetti
• Developer/Lead/Architect/Whatever for PNC Global Investment Servicing
• Author of four books (fifth coming soon) and a couple of articles, tech reviewer on a number of other books
• Creator of Java Web Parts (APT most “famously”) and Struts-WS
• Current lead of DataVision
• One of the original developers of PocketHobbit
• Contributor to other OSS projects (Struts, Commons, etc.)
![Page 3: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/3.jpg)
Open with a joke!
• We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true.
– Robert Wilensky
• The most likely way for the world to be destroyed, most experts agree, is by accident. That's where we come in; we're computer professionals. We cause accidents.
– Nathaniel Borenstein
• Well, thanks to the Internet, I'm now bored with sex.– Philip J. Fry
• The Internet? Is that thing still around?– Homer Simpson
• The ability to quote is a serviceable substitute for wit.– W. Somerset Maugham
![Page 4: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/4.jpg)
Ajax (for those residing in rock abodes)
• Asynchronous (almost always)
• JavaScript (almost always)
• XML (almost never)
• All about out-of-band requests and partial page loads
![Page 5: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/5.jpg)
The beating of a dead Equine
• “Jesse” James Garrett, Adaptive Path, February 2005
• IT’S NOTHING NEW!!
• It’s about the concepts, not technology
• In some ways, it was the saviour of the Internet
![Page 6: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/6.jpg)
That horse was askin’ for it!
![Page 7: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/7.jpg)
Oh the humanity!
![Page 8: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/8.jpg)
The big question: Why Ajax?
• Richer, more responsive UIs (RIAs)
• Reduced network utilization (careful!)
• Revolution in the guise of evolution
• It’s allows for a paradigm shift (once again, RIAs)
• Ajax isn’t just a communication mechanism any more (RIA == Ajax these days)
![Page 9: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/9.jpg)
An RIA (and a real looker of an ET!)
![Page 10: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/10.jpg)
Another RIA
![Page 11: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/11.jpg)
One more for good measure
![Page 12: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/12.jpg)
About that “suckage” I spoke of
• Ajax is hard to get right
• Many people don’t like doing JavaScript
• Requires a certain expertise that not every shop has
• Puts the focus on HTTP
![Page 13: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/13.jpg)
Build or buy?
![Page 14: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/14.jpg)
The star of the show: DWR
• Open-source, licensed under the ASL
• Member of the Dojo Foundation
• Java-only means no design compromises
• Implemented as a servlet, works fine in any container
• Minimizes JavaScript and deemphasizes servlet spec
• Makes calls to server-side code from JavaScript look the same as local calls
• Security is a core concept, not an afterthought
• Robust error handling
• Integration with many popular libraries and frameworks
• To put it simply: its an RPC mechanism for the Java webapps
![Page 15: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/15.jpg)
RPC mystified
(someone told me lots of pictures in a slideshow is a good idea, even superfluous ones like this!)
![Page 16: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/16.jpg)
DWR’s brand of RPC
![Page 17: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/17.jpg)
Yeah, but what does it actually DO?
• Auto-generates a JavaScript proxy “stub” for a server-side Java object
• Handles marshalling of all inbound and outbound data
• Handles instantiation and calling appropriate methods of the server-side object
• Transparently handles all that icky Ajax stuff
![Page 18: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/18.jpg)
DWR In a nutshell
![Page 19: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/19.jpg)
The basics, part 1
• Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry:
<servlet> <servlet-name>dwr-invoker</servlet-name> <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> <load-on-startup>1</load-on-startup></servlet><servlet-mapping> <servlet-name>dwr-invoker</servlet-name> <url-pattern>/dwr/*</url-pattern></servlet-mapping>
![Page 20: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/20.jpg)
The basics, part 2
• dwr.xml configures it:<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN" "http://getahead.org/dwr/dwr30.dtd">
<dwr>
<allow> <create creator="new“ javascript=“MathDelegate”> <param name="class" value="app.MathDelegate" /> </create> </allow>
</dwr>
![Page 21: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/21.jpg)
The basics, part 2a
![Page 22: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/22.jpg)
The basics, part 3
• A server-side class to call on:
package app;
public class MathDelegate {
public int add(int a, int b) { return a + b; }
public int subtract(int a, int b) { return a - b; }
public int multiply(int a, int b) { return a * b; }
public int divide(int a, int b) { return a / b; }
}
![Page 23: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/23.jpg)
The basics, part 4
Some client-side code to call it:
![Page 24: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/24.jpg)
<html> <head> <script type="text/javascript" src="dwr/interface/MathDelegate.js"></script> <script type="text/javascript" src="dwr/engine.js"></script> <script> function $(inID) { return document.getElementById(inID); } function doMath() { MathDelegate[$("op").value]($("num1").value, $("num2").value, function(answer) { $("divAnswer").innerHTML = answer } ); } </script> </head> <body> <input type="text" id="num1" size="4"> <select id="op"> <option value="add">+</option><option value="subtract">-</option> <option value="multiply">*</option><option value="divide">/</option> </select> <input type="text" id="num2" size="4"> <input type="button" value="=" onClick="doMath();"> <span id="divAnswer" style="font-size:18pt;"> </span><br><br> </body></html>
![Page 25: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/25.jpg)
Mmmm… pudding… AGHHAGGAGHAGAGA
(note to self: need to spell-check Homer Simpson biological drooling sound above)
math
![Page 26: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/26.jpg)
Interfaces and the engine, and more
• dwr/interface/* are where the dynamically generated JavaScript proxy stubs corresponding to remotable server classes are served from
• engine.js, the client-side engine behind DWR, is mostly static but with some dynamic elements
• Optionally, there’s util.js
• Note that all of this is served by the DWR servlet
![Page 27: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/27.jpg)
Call syntax
• Two ways… basic:MathDelegate.add(2, 2, function(serverResponse) { alert(serverResponse);});
• Call metadata object:MathDelegate.add(2, 2, { callback : function(serverResponse) { alert(serverResponse); }, errorHandler : function() { alert(“We’re boned!”); }});
![Page 28: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/28.jpg)
Call syntax redux
• In general, use the call metadata object paradigm
• Allows for passing of additional information (error handlers, options)
• Basic approach might be more readable if you really only need a callback
![Page 29: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/29.jpg)
The lost art of debugging
• Set debug servlet parameter to true
• http://server:port/context/dwr
• Lists all classes DWR can remote as well as test harnesses and even troubleshooting tips
• YOU’LL WANT TO TURN THIS OFF IN PRODUCTION
![Page 30: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/30.jpg)
(anyone not impressed can leave their geek credentials at the door on the way out)
debugging
![Page 31: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/31.jpg)
Yeah, neat, but what of performance?
• Lots of reflection magic
• Dynamic code generation
• You’d think performance would be terrible, but you’d be wrong!
• Interface files and util.js can be saved off and served from web server to take advantage of caching
• That DOES NOT work for engine.js!
![Page 32: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/32.jpg)
Security-security-security-security… Security-security-security-security!
![Page 33: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/33.jpg)
Threats aren’t always as cute as this
![Page 34: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/34.jpg)
Only what you want
• Only classes listed in dwr.xml can be remoted
• Further, you can limit access at the method level:<create creator="new"> <param name="class" value="app.MathDelegate" /> <include method="MyMethod" /> <!-- All others now excluded --></create>
• By default, all methods are available
• In production you probably should always use the above paradigm
![Page 35: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/35.jpg)
Only who you want
• Can limit access to J2EE roles at the method-level:
<create creator="new"> <param name="class" value="app.MathDelegate" /> <include method="MyMethod" /> <auth method="MyMethod" role="MyRole" /></create>
![Page 36: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/36.jpg)
Creators
• Creators instantiate remotable objects
• Out of the box: new, none, spring, jsf, struts, pageflow, ejb3
• Provides for integration with other libraries
• Can trivially create your own
• new and none are the most commonly used
![Page 37: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/37.jpg)
Converters
• Converters marshal beans from Java to JavaScript, and vice-versa
• Out of the box: boolean, byte, short, int, long, float, double, char, java.lang.Boolean, java.lang.Byte, java.lang.Short, java.lang.Integer, java.lang.Long, java.lang.Float, java.lang.Double, java.lang.Character, java.lang.BigInteger, java.lang.BigDecimal, java.lang.String, arrays, collections and maps of most types, enum, java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp
• bean and object converters, most frequently used (object works with data members directly, bean uses accessors/mutators)
• You can of course create your own too
![Page 38: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/38.jpg)
Beans, beans, they’re good for your heart, part 1
package app;
public class SearchVO {
private String acctNum;
public void setAcctNum(String acctNum) { this.acctNum = acctNum; }
public String getAcctNum() { return this.acctNum; }
}
![Page 39: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/39.jpg)
Beans, beans, they’re good for your heart, part 2
package app;
public class Account {
private String acctNum; private String shareholder; private Integer balance;
public void setAcctNumber(String acctNum) { this.acctNum = acctNum; } public String getAcctNum() { return this.acctNum; } public void setShareholder(String sh) { this.shareholder = sh; } public String getShareholder() { return this.shareholder; } public void setBalance(Integer balance) { this.balance = balance; } public Integer getBalance() { return this.balance; }
}
![Page 40: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/40.jpg)
Beans, beans, they’re good for your heart, part 3
package app;
public class Processor {
public Account getAccount(SearchVO searchVO) {
Account account = new Account(); account.setAcctNum(searchVO.getAcctNum()); account.setShareholder("Tapping, Amanda"); account.setBalance(new Integer(25986)); return account;
}
}
![Page 41: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/41.jpg)
Beans, beans, they’re good for your heart, part 4
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN" "http://getahead.org/dwr/dwr30.dtd">
<dwr>
<allow>
<convert converter="bean" match="app.SearchVO" /> <convert converter="bean" match="app.Account" />
<create creator="new“ javascript=“Processor”> <param name="class" value="app.Processor" /> </create>
</allow>
</dwr>
![Page 42: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/42.jpg)
Beans, beans, they’re good for your heart, part 5
Here thar be JavaScript too:
![Page 43: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/43.jpg)
<html><head> <script type="text/javascript" src="dwr/interface/Processor.js"></script> <script type="text/javascript" src="dwr/engine.js"></script> <script type="text/javascript" src="dwr/util.js"></script> <script> function doSearch() { var accountSearchVO = { acctNum : document.getElementById("acctNum").value }; Processor.getAccount(accountSearchVO, { callback : function(inAccount) { dwr.util.setValue("divAccountDetails", "Account Number: " + inAccount.acctNum + "<br>" + "Shareholder Name: " + inAccount.shareholder + "<br>" + "Current Balance: " + inAccount.balance, { escapeHtml : false } ); }}); } </script> </head><body> Account Number: <input type="text" id="acctNum"> <input type="button" value="Get Account" onClick="doSearch();"><br><br> <div id="divAccountDetails"></div> </body></html>
![Page 44: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/44.jpg)
(* yes, that is indeed a cheap Watchmen reference!)
account
![Page 45: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/45.jpg)
![Page 46: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/46.jpg)
![Page 47: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/47.jpg)
dwr.util
• General-purpose client utilities, mostly concerned with getting content into the DOM, in no way DWR-specific
• addOptions() – Add elements to lists (ol, ul, select)
• addRows() – Add rows to tables
• byId() – Shortcut to document.getElementById()
• getText() – Get text (not value) of an <option> element
• getValue()/getValues() – Get value of virtually any HTML element (it deals with the specifics of what “value” means for each)
• removeAllOptions() – Remove all <option> from a <select> or ol/ul element
• removeAllRows() – Remove all rows from a table
• setValue()/setValues() – The reverse of getValue()
• toDescriptiveString() – Output an object in a useful way
![Page 48: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/48.jpg)
I hate it when a plan doesn’t come together
![Page 49: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/49.jpg)
Error handling in DWR
• Can handle errors globally or on a per-call basis
• Warnings – Things you can usually ignore…dwr.engine.setWarningHandler(<function>)
• Errors - When DWR can tell you what went wrong (ex: server shuts down in the middle of servicing an AJAX request)…dwr.engine.setErrorHandler(<function>);
• Exceptions - Thrown from server and propagated to client. Must handle exceptions per-call…
![Page 50: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/50.jpg)
Error Handling: The Next Generation™
Processor.getAccount(accountSearchVO, { callback : function(inAccount) { dwr.util.setValue("divAccountDetails", "Account Number: " + inAccount.acctNumber + "<br>" + "Shareholder Name: " + inAccount.shareholder + "<br>" + "Current Balance: " + inAccount.balance, { escapeHtml : false } ); }, errorHandler : function(errMsg, exception) { alert(dwr.util.toDescriptiveString(exception, 4)); }});
![Page 51: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/51.jpg)
Making sense of exceptions
• Exceptions by default are not marshaled:<convert match="java.lang.Exception" converter="exception"> <param name="include" value="message,lineNumber" /></convert><convert match="java.lang.StackTraceElement" converter="bean" />
![Page 52: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/52.jpg)
(I feel so cheap for making that Lost in Space reference... UNCLEAN! UNCLEAN!)
error
![Page 53: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/53.jpg)
Are you part of the “XML is uncool” crowd?
• DWR also supports annotations:@RemoteProxypublic class WordsOfWisdom { @RemoteMethod public String getWisdom() { return “<insert something wisdom-y here>”; }}
• That’s not quite all there is to it:<servlet> <servlet-name>dwr-invoker</servlet-name> <servlet-class>org.directwebremoting.servlet.DWRServlet</servlet-class> <init-param><param-name>classes</param-name> <param-value>app.WordsOfWisdom</param-value> </init-param></servlet>
![Page 54: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/54.jpg)
Using HTTP objects
• Sometimes a POJO isn’t enough (session):WebContext wc = WebContextFactory.get();HttpSession session = wc.getSession();
• But there’s a better way:Server:Public class Remote { public void myCallableMethod(String param, HttpSession session) { }}
Client:Remote.myCallableMethod(“test”, { callback : function(resp) { alert(resp); } });
• Reduced coupling to DWR… Syntax is cleaner… Less work (always good)• “Automagic” stuff isn’t usually good… Must call data meta-object
approach, so client-side code is arguably more verbose (slightly)
![Page 55: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/55.jpg)
Call batching
• Can combine multiple operations in one:
dwr.engine.beginBath(); BatchCallClass.method1(callback1); BatchCallClass.method2(callback2); SomeOtherClass.method2(callback3);dwr.engine.endBath();function callback1() { alert(“callback1”); }function callback2() { alert(“callback2”); }function callback3() { alert(“callback3”); }
• One network request made• Order of calls and callback execution is guaranteed• Lets you keep code separated on the server while
maximizing runtime efficiency
![Page 56: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/56.jpg)
Reading from other URLs
• Read response from a URL and return as string from a method:
public class URLReader { public String read() throws ServletException, IOException { return WebContextFactory.get().forwardToString(“/another.jsp”); }}
• Allows you to continue to use all the capabilities you’re used to in JSP
• JSP becomes a (powerful) templating technology only
• Ties you to DWR• Can only do forwards, so only the same context
![Page 57: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/57.jpg)
Look out, here comes the Spring bandwagon!
• Can delegate to Spring for bean instantiation:dwr.xml:<create creator="spring" javascript="HelloHuman"> <param name="beanName" value="HelloHuman" /> <param name="location" value="spring-beans.xml" /></create>
spring-beans.xml:<?xml version="1.0" encoding="UTF-8"?>
<beans> <bean id="HelloHuman" class="app.HelloHuman" /></beans>
![Page 58: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/58.jpg)
(awww, taking it APART is so much more fun!)
alltogether
![Page 59: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/59.jpg)
When forward isn’t cool enough: Reverse Ajax
![Page 60: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/60.jpg)
If pro is the opposite of con, then isn’t progress the opposite of congress?!?• “Server-push”
• Difficult to implement on your own (thank you DWR!)
• Passive and active modes gives you lots of flexibility
• Active mode (comet specfically) chews up threads on server and proxies
• Good in small-scale apps, use with extreme caution beyond that (depending on method)
• Special servers/extensions exist to alleviate scalability concerns (depending on method)
• Speaking of methods…
![Page 61: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/61.jpg)
The three horsemen of the apocalypse, part 1: Piggybacking
Obviously not real “push”, but a decent approximation and often times “good enough”. Least resource-intensive (passive method).
![Page 62: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/62.jpg)
The three horsemen of the apocalypse, part 2: Polling
Also not real “push”, but closer than piggybacking. Medium resource utilization (active method, but controllable).
![Page 63: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/63.jpg)
Introducing New and Improved Comet!
(WARNING!! TRADEMARK INFRINGEMENT ALERT!!)
![Page 64: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/64.jpg)
The three horsemen of the apocalypse, part 3a: Let’s try this Comet thing again
As close to real “push” as you’re going to get with HTTP. It’s nothing but a hack… but an extremely clever one! (true active method)
![Page 65: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/65.jpg)
The mechanics of reverse Ajax: Piggybacking
• To activate piggybacking:
DO NOTHING!
• You can automatically piggyback on any incoming request
![Page 66: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/66.jpg)
The mechanics of reverse Ajax: Polling
• To activate polling, add to client code:dwr.engine.setActiveReverseAjax(true);
• Then, add to DWR servlet config in web.xml:<init-param> <param-name>activeReverseAjaxEnabled</param-name> <param-value>true</param-value></init-param><init-param> <param-name>org.directwebremoting.extend.ServletLoadMonitor</param-name> <param-value>org.directwebremoting.impl.PollingServerLoadMonitor</param-value></init-param><init-param> <param-name>timeToNextPoll</param-name> <param-value>1000</param-value></init-param>
![Page 67: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/67.jpg)
The mechanics of reverse Ajax: Comet
• To activate comet, add to client code:dwr.engine.setActiveReverseAjax(true);
• Then, add to DWR servlet config in web.xml:<init-param> <param-name>activeReverseAjaxEnabled</param-name> <param-value>true</param-value></init-param>
![Page 68: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/68.jpg)
What about the J in JUG?!?
• From the server, do something like:Util.setValue("divRAResponse", "Hello!", true);
• All users currently viewing the page Ajax calls are sourced from will see “Hello!” in <divRAResponse>.
![Page 69: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/69.jpg)
When you don’t want to talk to just anyone
• To do something for a single user:ScriptBuffer script = new ScriptBuffer();script.appendScript(“doSomething();");WebContext wc = WebContextFactory.get();ScriptSession scriptSession = wc.getScriptSession();scriptSession.addScript(script);
• The doSomething() Javascript function will be executed in the browser of the user belonging to the session associated with the request being serviced.
![Page 70: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/70.jpg)
Running in the background
• You can spawn a background thread, and then do reverse Ajax from it
• Just need to cache the WebContext object
• Applies to communication with a single user as well as all users
• Careful! Spawning threads in a servlet contanier is bad, m’kay?
![Page 71: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/71.jpg)
(except in the case of UFOs apparently)
ra_*
![Page 72: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/72.jpg)
![Page 73: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/73.jpg)
Binary files
• Can handle binary files (up and down)
• Can deal with byte[], java.awt.BufferedImage, java.io.inputStream or org.directwebtemoting.io.FileTransfer (gives access to filename, mime type and contents)
• Uploading: Easier than commons-fileupload or similar and can integrate with progress bar widgets
• Downloading: easier than creating a special PDF servlet or similar
• What, you don’t believe me? Ok, here you go:
![Page 74: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/74.jpg)
Server:public class Remote { public void recieveFile(byte[] f) { /* Do something with contents. */ } public FileTransfer getFile() { // buf if a ByteArayOutputStream with the contents of a PDF in it. return new FileTransfer(“myFile.pdf”, “application/pdf”, buf.toByteArray()); }}
Client:<input type=“file” id=“myFile”>
// Send file.var f = dwr.util.getValue(“myFile”);Remote.recieveFile(f);
// Receive file.Remote.getFile(null, function(pdf) { dwr.engine.openInDownload(pdf);});
![Page 75: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/75.jpg)
Poor man’s web services
• DWR supports JSON, JSON-P (so-called REST-based web services)
• Allows cross-domain access to DWR remotable classes
• Allows non-DWR clients to interact with DWR-exposed remotables
• Not perfect (manual Ajax, parameter naming, etc), but still very nice!
Server:public class Demo { public String sayHi(String name) { return “Hi there, “ + name; }}
Command Line:$ wget http://localhost/app/dwr/jsonp/Demo/sayHi?param0=Frank&callback=jsfunc
-> jsfunc(“Hi there, Frank”);
![Page 76: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/76.jpg)
Varargs
• Avoids wrapping arguments in an array, collection or VO
• Can break edge cases when mixing servlet parameters and regular parameters
Server:public class VarArgClass { public void meth(String… arg) { /* Do something */ }}
Client:VarArgClass.meth(“Apollo”, “Starbuck”, “Boomer”);
![Page 77: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/77.jpg)
Overloaded methods
• Prior to v3, overloaded methods were indeterminate (might get the right one, might not)
• Finally, in v3, true overloading support is present!
Server:public class Remoted { public void method(int num) { System.out.println(“num: “ + num); } public void method(String str) { System.out.println(“str: “ + str); }}
Client:Remoted.method(“I am a string”);Remoted.method(42);
![Page 78: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/78.jpg)
Tie-ins with Dojo and others
• Dojo data stores
• Server-side manipulation of Dijits
• Deep Tibco General Interface (nearly full control of the entire UI from the server)
![Page 79: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/79.jpg)
Reverse Ajax upgrades
• More scalable (maybe), more robust API
// Broadcast to all users currently viewing index.html page.Browser.withCurrentPage(“index.html”, new Runnable() { public void run() { Window.alert(“Hello”); }});
// Broadcast to everyone connected to DWR, regardless of current page.Browser.withAllSessions(…);
// Broadcast to a filtered subset of users.Browser.withFiltered(scriptSessionFilter, …);
// Broadcast to a specific user.Browser.withSession(sesssionID, …);
![Page 80: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/80.jpg)
Reverse Ajax upgrades continued
• The server-side API is more robust, allowing for easier manipulation of the client from server code:
Element e = doc.createElement(“p”);ScriptSessions.addFunctionCall(“document.body.appendChild”, e);
ScriptSessions.addScript(“alert(‘Hello Zark!’);”);
Document.setCookie(new Cookie(“name”, “value”));
String[] opts = new String[] { “Kruger”, “Myers”, “Vorhees” };Util.addOptions(“li”, opts);
Effect.fade(“someID”);
![Page 81: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/81.jpg)
In conclusion
• DWR kicks more arse than anything that has ever kicked arse before (and that’s only a slight exaggeration!)- simple, robust, powerful, secure*
• In short: if you’re a Java developer who does Ajax, and you do it with something other than DWR, you almost certainly want marijuana legalized!
• To sum it all up succinctly…
* and the opposite sex will find you more attractive for using it!
![Page 82: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/82.jpg)
If you don’t use DWR, you might be as dumb as her
(at least she has looks… and BTW, mad props to Mario for not cracking up big-time!)
![Page 83: Ajax for Java developers… but without the suckage · The basics, part 1 •Just add some JARs (dwr.jar and commons-logging.jar) and a servlet entry: dwr-invoker](https://reader034.vdocuments.us/reader034/viewer/2022043017/5f39ae4481771641681252ce/html5/thumbnails/83.jpg)
(And if you’d like to contact me after the show I’d be… err, surprised actually… but if you do: [email protected])
Download code and slide deck here: www.zammetti.com/philly_jug_dwr_presentation.zip