Top Banner
Remote Procedure Calls in GWT How they are implemented How to use them effectively Best practices and design patterns Future directions and possibilities • Discussion
36
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Gwt and rpc use 2007 1

Remote Procedure Calls in GWT• How they are implemented• How to use them effectively• Best practices and design patterns• Future directions and possibilities• Discussion

Page 2: Gwt and rpc use 2007 1

Introduction• Your presenter: Rob Jellinghaus• Contributor to GWT

– Refactored server-side RPC implementation in GWT 1.4

• Architect at SF startup• http://robjsoftware.org

Page 3: Gwt and rpc use 2007 1

What is GWT RPC?• Simple way for your GWT clients to call

your Java server code• Looks a lot like regular Java procedure

calls; can pass complex objects easily• Will skim over the basics

– GWT documentation is good

• Won’t address security– Too large a topic– Covered elsewhere at this conference

Page 4: Gwt and rpc use 2007 1

All Abstractions Leak• Abstractions are great, but hidden details

have a way of surfacing– Spolsky’s Law: All non-trivial abstractions,

to some degree, are leaky

• GWT RPC is no exception– At least GWT is upfront about such things!

• Forewarned is forearmed

Page 5: Gwt and rpc use 2007 1

Asynchrony• The biggest difference: GWT RPC returns

immediately• Normal procedure call:

Object result = myService.doWork();doSomethingWith(result);

• GWT RPC:myService.doWork(myCallback);… wait a while …public void onSuccess(Object result) {

doSomethingWith(result);

}

Page 6: Gwt and rpc use 2007 1

Asynchrony Is Your Friend• The very definition of AJAX

– Old news to AJAX hackers, but unusual in the Java world

• If your app isn’t waiting for the server, then your users aren’t either

• Don’t work around it, embrace it!– Workarounds are horrible and user-hostile

Page 7: Gwt and rpc use 2007 1

GWT RPC Lives in the Compiler• RPC is implemented as a compiler extension

– See Ray Cromwell’s talk on “Generators”

• Enables very highly optimized RPC code– Compiler looks at your interfaces and object types– Emits tightly tuned encoding / decoding Javascript

• If GWT can’t compile it, you can’t send it– Unlike RMI / Java serialization, where you can send

objects for which you don’t have source

Page 8: Gwt and rpc use 2007 1

Very brief example• This class:

public class Entry implements com.google.gwt.user.client.rpc.IsSerializable{private dto.domain.Blog blog;private java.lang.String body;…

}

• Gets this generated deserializer (details elided):function dto_domain_Entry_1FieldSerializer_deserialize(streamReader, instance) {

dto_domain_Entry_1FieldSerializer_setBlog (instance, com_google_gwt_lang_Cast_dynamicCast__Ljava_lang_Object_2I…

(streamReader.readObject__(), 17)); dto_domain_Entry_1FieldSerializer_setBody… (instance,

streamReader.readString__()); …}

Page 9: Gwt and rpc use 2007 1

GWT serialization vs. others• GWT serialization:

– Fully statically compiled, metadata-guided– No class hooks

• Java serialization:– Reflection-based– readObject, writeObject hooks

• Java persistence serialization:– Reflection-based, metadata-guided– Bytecode proxies injected

Page 10: Gwt and rpc use 2007 1

Server integration: basics• Simplest technique: RemoteServiceServlet

public interface MyServiceInterface { public Object doWork(); }

public class MyServiceServlet extends RemoteServiceServlet implements MyServiceInterface { public Object doWork() { … }

}

• Works nicely out of the box• Requires one servlet class per interface you

expose– Doesn’t work well to expose pre-existing components– Fixed with my refactorings in GWT 1.4

Page 11: Gwt and rpc use 2007 1

Server integration: Spring• Several Spring integrations exist

– George Georgovassilis & Rob Hanson’s GWT-SL server library

– Chris Lee’s one-page integration

• Couples with Spring’s “handler” mechanism for web requests

• Can expose pure POJOs (GWT-SL), or can annotate service classes (Chris Lee)

Page 12: Gwt and rpc use 2007 1

Server integration: Seam• Seam 2.0 has built-in GWT integration

– GWTService web resource

• Set your endpointURL to be “seam/resource/gwt”• RPC requests route to a Seam component by

interface name:

@Name("org.jboss.seam.example.remoting.gwt.client.MyService")public class ServiceImpl implements MyService{ @WebRemote public String askIt(String question) {

return "42. Its the real question that you seek now."; }…}

Page 13: Gwt and rpc use 2007 1

Server integration: Seam/JSF + GWT• Wrap your GWT module in a JSF

component• Drop it into a JSF page• Route its RPC to any Seam component:

<!-- routes to the BlogService on the gwtBlog component --> <bloglist:component id="main2"> <gwt:gwtListener serviceBean="#{gwtBlog}"/> </bloglist:component>

• Only one problem… broken with Seam 2 at the moment– Anyone want to help?

Page 14: Gwt and rpc use 2007 1

Using GWT RPC Effectively• We’ve covered the basics• Now for best practices

– Responsiveness– Asynchrony– Serialization interactions– API design and service orientation

Page 15: Gwt and rpc use 2007 1

Responsiveness: Balanced RPC• Messages Want To Be Small

– Small messages are quick to process– Low encoding & decoding overhead

• But Messages Want To Be Big– Networks are slow– Many messages = much exposure to network

latency

• Balance your RPC– Only pull data visible to the user; paginate on server– Don’t build too many UI elements either

Page 16: Gwt and rpc use 2007 1

Asynchrony: No More Straight Lines• Synchronous code might look like this

– (can’t use Java 5 yet in GWT 1.4):

Blog blog = blogService.getBlog();

List entries = blogService.getEntries();for (int i = 0; i < entries.size(); i++) {

BlogEntry entry = (BlogEntry)entries.get(i);TreeItem item = new TreeItem(entry.getTitle());tree.addItem(item);String body = blogService.formatText(entry.getId());entry.setBody(body);

}

Page 17: Gwt and rpc use 2007 1

Fun with Inner Classes• Anonymous inner classes split up the code inline:

Blog blog = null;

List entries = null;blogService.getBlog(new AsyncCallback() {

public void onSuccess(Object result) {blog = (Blog)result;blogService.getEntries(new AsyncCallback() {

public void onSuccess(Object result) {entries = (List)result;

}});

}});

• But gets very nested and tough to read

Page 18: Gwt and rpc use 2007 1

Callback Objects• Break out the callbacks into helpers:

Blog blog = null;

blogService.getBlog(new AsyncCallback() {public void onSuccess(Object result) {

blog = (Blog)result;

blogService.getBlogEntries(makeEntriesCallback());}

});public AsyncCallback makeEntriesCallback() {

return new AsyncCallback() {public void onSuccess(Object result) {

List entries = (List)result; …

• Makes the sequence more descriptive

Page 19: Gwt and rpc use 2007 1

Stateful Callback Objects• Multiple RPCs in flight at once:

List entries = (List)result;for (int i = 0; i < entries.size(); i++) {

BlogEntry entry = (BlogEntry)entries.get(I);TreeItem item = new TreeItem(entry.getTitle()); tree.addItem(item);blogService.fetchText(entry.getId(), makeEntryCallback(item));…

}public AsyncCallback makeEntryCallback(TreeItem item) {

return new AsyncCallback() { public void onSuccess(Object text) {

item.setText((String)text); } } }

• Each callback knows what to do with its response• Can extend this pattern to all kinds of sequences

Page 20: Gwt and rpc use 2007 1

Transactions• Updates can sometimes require multiple

server calls• Keep state in your client until commit time

– The less server state the better– But can’t send too much state at once when

committing

• Can use “chained command” pattern in your service– Send a whole sequence of API calls– Rather like offline sync in Google Gears

Page 21: Gwt and rpc use 2007 1

When Abstractions Attack• GWT makes it easy to call your Java backend• Many Java backends use Hibernate, JPA, EJB3…• GWT abstraction: serialize object graph to

Javascript– Needs to see all the source

• JPA abstraction: load partial object graph lazily– Create secret hidden $$CGLIB classes, private collections

• GWT + JPA: KABOOM!– GWT can’t serialize a lazy persistence proxy or Hibernate

PersistentMap– Spolsky’s Revenge

Page 22: Gwt and rpc use 2007 1

DTOs: Back to the Future• Data transfer objects: intermediate

object layer• Copy your persistent objects into

separate DTO structure– GWT only sees the DTO objects– Explicit control over what gets sent– Can limit features used in DTO objects (avoid

generics, annotations)– Risk of lots of boilerplate code

Page 23: Gwt and rpc use 2007 1

Generated DTOs: Less Boilerplate• Automatically generate DTOs at build time

– Codehaus JAM project: Java source walker– Compile DTOs into a standalone GWT module

for (JField field : jClass.getFields()) { String name = field.getSimpleName(); String type = field.getType().getQualifiedName(); if (type.startsWith("java.")) { // skip over classes that aren't emulated by GWT…

• Reflection can populate DTOs– Kind of an intermediate “serializer” from persistent

objects to DTO objects– Hibernate4gwt project allows this (with merging, too)

Page 24: Gwt and rpc use 2007 1

Rocket Science: Customizing RPC• GWT ServerSerializationStreamWriter

– Custom GWT class that traverses objects– Can make subclass with special handling of persistent

classes• Null out lazy collections, load lazy proxy objects

– Risks breaking if GWT changes RPC implementation

public void serializeValue(Object value, Class type) throwsSerializationException {…else if (type == java.util.Set.class) {

Set hashSet = new HashSet();if (value instanceof PersistentSet) {PersistentSet persSet = (PersistentSet) value;if (persSet.wasInitialized()){

hashSet.addAll(persSet);}…

Page 25: Gwt and rpc use 2007 1

The Trouble with Merging• Once you send your objects back up, you have to

merge them• Seam / JPA stateful dogma says this is a

weakness of GWT and other rich clients– Stateful apps keep persistence context around while

user is interacting; dirty objects tracked for free

• But persistence contexts die badly if commit fails– Only solution is to abandon all your modified state!

• GWT APIs need to clearly identify what’s changed– Simplifies the merge problem– Arguably easier to recover from conflicts– Scales better, too

Page 26: Gwt and rpc use 2007 1

DAOs are not APIs• Tempting to just expose your persistence

layer• Don’t do this!

– Persistence operations are not a good API

• APIs should be intentional– Should be tuned to application use cases– Objects exposed should be client-meaningful

• May or may not be your domain objects

– Think services rather than data accesses

• Service-oriented backends are more scalable

Page 27: Gwt and rpc use 2007 1

Serializable != IsSerializable• Java serialization is not GWT serialization

– Java serialization expects a very particular contract

– Hardcoded to binary / byte level; lots of existing readObject, writeObject methods

– Those methods not necessarily compilable by GWT

– Java serialization not efficient in Javascript

• In GWT, “java.lang.Serializable” just means “OK to send by GWT RPC”– Does NOT mean “Will use existing readObject /

writeObject implementations”

Page 28: Gwt and rpc use 2007 1

The Home Stretch• Cool tricks• GWT 1.5• Future possibilities

– Ranging from “sensible” to “wildly ambitious”

• Other interesting systems• Conclusion

Page 29: Gwt and rpc use 2007 1

Preserialized objects• You’ve got a bunch of initialization data

– You want to download it efficiently– Maximum-speed startup, one round-trip

• iPhone apps, anyone?

• Serialize the data on the server, then save the bytes

• Blast them out from cache, then deserialize them explicitly– In GWT 1.5: get SerializationStreamReader

from client-side RPC proxy

Page 30: Gwt and rpc use 2007 1

GWT 1.5: Java 5 for the win!• Plan: full support for enumerated types,

generic collections• No more @gwt.typeargs

– Typed collections get optimized RPC automatically

• Annotations are OK– Not yet clear what GWT will use them for– Compiler should be able to ignore annotations

w/o available source• So @Entity, @Component, etc. won’t choke GWT

Page 31: Gwt and rpc use 2007 1

Possibility: RPC metadata• Support for request/response headers in

RPC messages• Use cases:

– Servers that use HTTP headers for authorization– Support for Spring webflow / Seam conversations

• API totally undefined:– Stateful instantiation of Service? Callback

functions?– Related to RPC cancellation / request control?– Discuss on GWT Contributors forum

Page 32: Gwt and rpc use 2007 1

Possibility: JSON-style encoding• GWT compiler generates current

deserializers– Pretty much the best Javascript functions can do– But still not as good as JSON

• What if RPC payloads were deserialized by the browser, as with JSON?– Could be blazingly fast deserialization– AND less client-side code– But lots of issues to work out (see GWTC thread)

• Not high priority for GWT 1.5, but later…?

Page 33: Gwt and rpc use 2007 1

Possibility: Declarative data binding• Right now RPC is strictly imperative• Some modern frameworks (Seam) support

declarative data binding– Refer to server data objects by name– UI components bind to specific sub-objects

• Declarative UI support underway for GWT; perhaps data binding a natural extension?– Could also integrate some support for offline

synchronization?– Pagination done “under the hood”?

Page 34: Gwt and rpc use 2007 1

Possibility: Generalized mappings• Persistence mapping is very similar to client-

server DTO mapping– In both cases, you have data spaces containing objects

that must be transferred and correlated

• Why not a unified answer?– What if persistence mappings could be extended to

define data transfer behaviors to the client?– And then further, to define client-side update sets and

synchronization behaviors?– Attack the DTO problem at the framework level!

• See LINQ 2.0 work from Microsoft Research

Page 35: Gwt and rpc use 2007 1

Other interesting systems• Good old RMI (Sun)

– Classloader problems much worse than widely known

• Caja (Ben Laurie, Mark Miller, Google)– Capability-secure Javascript– Mobile code, with non-broken sandboxes– Influenced by E (asynchronous capability messaging)– (GWT -> Caja scriptlets???)

• LINQ 2.0 (Erik Meijer, Microsoft)– Automatically restructure sequential client app to be

asynchronous multi-tier app– Integrate SQL queries, XML mappings, RPC– MSIL -> Javascript (like GWT for .NET bytecode)

Page 36: Gwt and rpc use 2007 1

Thanks!• Hope this was helpful • Thanks to GWT team & Pearson• http://robjsoftware.org/gwt2007

– links & further references

• Go forth and create great apps!– And then post about them on the GWT

groups!– And then start contributing to GWT!!!