<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-29163398</id><updated>2012-01-09T00:42:19.552+02:00</updated><category term='troubleshooting'/><category term='design'/><category term='gwt'/><category term='reflection'/><category term='performance'/><category term='javascript'/><category term='agile'/><category term='java'/><category term='jug'/><category term='web'/><category term='json'/><category term='play'/><title type='text'>Blog of Dmitry Buzdin</title><subtitle type='html'>Blogging about software development.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://buzdin.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://buzdin.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Dmitry Buzdin</name><uri>http://www.blogger.com/profile/14535724893723283597</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_wJqXOQNlTV4/TTmJvIpu36I/AAAAAAAAABQ/B32dD3nU1S4/s220/face.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>12</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-29163398.post-5579698863510817626</id><published>2011-07-22T15:46:00.005+03:00</published><updated>2011-07-25T12:32:16.498+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='json'/><title type='text'>Validating JSON with Schemas</title><content type='html'>&lt;h3&gt;Introducing JSON Schemas&lt;/h3&gt;The world is in transition from XML to alternative document description languages such as JSON. Some of the reasons of moving from XML to JSON are the following:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;JSON is a native Web format supported by most of the browser JavaScript engines. No conversions or usages of proprietary XML parsing extensions required.&lt;/li&gt;&lt;li&gt;Easier to read and to write, since it is more about data than markup. This format can be successfully edited in plain text editors. No more duplication of tag names at the beginning and at the end of each line.&lt;/li&gt;&lt;li&gt;Smaller document size, which saves some bandwidth.&lt;/li&gt;&lt;li&gt;Simplicity - no CDATA, no comments allowed, only few data types.&lt;/li&gt;&lt;li&gt;Flexibility - no schemas by default.&lt;/li&gt;&lt;/ul&gt;Lack of schema validation support is considered as a feature by some of JavaScript and other dynamic languages protagonists. However there are different scenarios and in some of them you would wish for such thing as JSON schema. To mention some of the example usages of JSON validation:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;You are building a REST interface for external team or application or even public service with certain restrictions on data formats and sets of processed properties.&lt;/li&gt;&lt;li&gt;You are having application configuration stored in JSON format and it should be backward compatible at all times.&lt;/li&gt;&lt;li&gt;You are storing JSON to document-oriented database such as MongoDB and want to have certain indexed fields present in each document.&lt;/li&gt;&lt;li&gt;You want to write automated test suite, which validates JSON content.&lt;/li&gt;&lt;/ul&gt;In mentioned cases you would like to ensure successful evolution of your document format. You have certain mandatory properties and limitations like max, min or format checks. And it is for sure required to validate documents, which come from external sources and can not be trusted before storing them in the database. &lt;br /&gt;&lt;br /&gt;In XML world these types of problems are solved long ago. In JSON the solution is work in progress. This leads us to JSON Schema specification published at Internet Engineering Taskforce page&amp;nbsp;&lt;a href="http://tools.ietf.org/html/draft-zyp-json-schema-03"&gt;[link]&lt;/a&gt;. The standard is in its third version and authors claim that version four will be very close to the final one and will not introduce any serious changes&amp;nbsp;&lt;a href="http://groups.google.com/group/json-schema/browse_thread/thread/2527eadb13e796c0"&gt;[reference]&lt;/a&gt;.&lt;br /&gt;&lt;h3&gt;Schema Sample&lt;/h3&gt;Assume you have the following JSON object structure.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: js"&gt;{&lt;br /&gt;  "id": 1,&lt;br /&gt;  "name": "some name",&lt;br /&gt;  "letters": ["a", "b", "c"],&lt;br /&gt;  "details": {&lt;br /&gt;    "additional": "some more"&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: center;"&gt;&lt;i&gt;JSON Document Example&lt;/i&gt;&lt;/div&gt;&lt;br /&gt;It demonstrates most of the JSON common features - arrays, nested objects and properties of number and string types. According to the referenced specification the JSON schema would look like the following.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: js"&gt;{&lt;br /&gt;  "type": "object",&lt;br /&gt;  "additionalProperties": false,&lt;br /&gt;  "properties": {&lt;br /&gt;     "id": {"type": "number"},&lt;br /&gt;     "name": {"type": "string"},&lt;br /&gt;     "items": {&lt;br /&gt;       "type": "array",&lt;br /&gt;       "items": {"type": "string",  "enum": ["a", "b", "c", "d"]}&lt;br /&gt;     }&lt;br /&gt;     "details": {&lt;br /&gt;       "type": "object",&lt;br /&gt;       "optional": true,&lt;br /&gt;       "properties" {&lt;br /&gt;          "additional": {"type": "string"}&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: center;"&gt;&lt;i&gt;JSON Schema Example&lt;/i&gt;&lt;/div&gt;&lt;br /&gt;The format is quite straightforward and readable. The schema describes the data format and could be used for validation purposes. Some of the JSON schema features are used:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;additionalProperties&lt;/b&gt; - additional properties are allowed by default, but if you are sure nothing else should be present put this setting to false;&lt;/li&gt;&lt;li&gt;&lt;b&gt;enum&lt;/b&gt; - it is possible to apply content checks such as enumerations;&lt;/li&gt;&lt;li&gt;&lt;b&gt;optional&lt;/b&gt; - all properties are mandatory by default, but you could set them to be optional.&lt;/li&gt;&lt;/ul&gt;The schema language is quite powerful and allows advanced validation features such as Regular Expressions, numeric checks etc. Refer for the documentation for the full list of features.&lt;br /&gt;&lt;h3&gt;Java Implementations&lt;/h3&gt;Schema language itself would be not so useful without successful implementations.&amp;nbsp;The reference implementation in JavaScript could is ready to be used and is available here&amp;nbsp;&lt;a href="http://code.google.com/p/jsonschema/"&gt;http://code.google.com/p/jsonschema/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Implementations in other languages and platforms are underway. Situation in JVM world is not so good.&lt;br /&gt;There is a problem finding a proper validation implementation working in JVM at the moment.&lt;br /&gt;&lt;br /&gt;First attempt to come up with the implementation was&amp;nbsp;JSONTools project&amp;nbsp;&lt;a href="http://jsontools.berlios.de/articles/archive/index.html"&gt;[link]&lt;/a&gt;. Looks pretty much dead now. Last site update was in 2008.&lt;br /&gt;&lt;br /&gt;Another options is to get a working validator draft from Git repository&amp;nbsp;&lt;a href="http://nico.vahlas.eu/2010/05/17/json-schema-first-java-implementation-available/"&gt;[link]&lt;/a&gt;. Not really production ready software, not finished yet, has relatively poor performance, but could be easily used for offline testing, since it covers most of the important features. This validator is based on&amp;nbsp;Jackson JSON processing library (&lt;a href="http://jackson.codehaus.org/"&gt;http://jackson.codehaus.org/&lt;/a&gt;). It works and does what is promised.&lt;br /&gt;&lt;br /&gt;One implementation, which looks more promising and finished has recently been announced&lt;br /&gt;&lt;a href="https://github.com/fge/json-schema-validator"&gt;https://github.com/fge/json-schema-validator&lt;/a&gt;. This implementation was inspired by the Git code from he previous link and is also Jackson based. It lacks Maven releases and has weird java package name "kitchen.eel", but let's hope that it will change over time. Not many people would like to have kitchen eels in their imports I guess, especially during code and design reviews.&lt;br /&gt;&lt;br /&gt;Scala may be a good implementation language for writing such validator for JVM. It has some native JSON parsing features and nice constructs like pattern matching, which makes writing recursive parsers a simpler task.&lt;br /&gt;&lt;br /&gt;So there is still some space for good JSON schema validator frameworks in JVM and let's wait for the new spec release. I think JSON validation will be more important topic next years as adoption is continuing. Many frameworks try to come up with custom formats and approaches, but if there is a standard, why not use that?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29163398-5579698863510817626?l=buzdin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://buzdin.blogspot.com/feeds/5579698863510817626/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29163398&amp;postID=5579698863510817626' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/5579698863510817626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/5579698863510817626'/><link rel='alternate' type='text/html' href='http://buzdin.blogspot.com/2011/07/validating-json-with-schemas.html' title='Validating JSON with Schemas'/><author><name>Dmitry Buzdin</name><uri>http://www.blogger.com/profile/14535724893723283597</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_wJqXOQNlTV4/TTmJvIpu36I/AAAAAAAAABQ/B32dD3nU1S4/s220/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29163398.post-7866150151873785242</id><published>2011-05-27T15:07:00.000+03:00</published><updated>2011-05-27T15:07:10.790+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jug'/><title type='text'>Oracle EMEA Users Group Leaders’ meeting</title><content type='html'>I have had an opportunity to represent Java User Group Latvia on annual Oracle User Groups meeting. This year it was held in Prague on May 10th and 11th.&lt;br /&gt;&lt;br /&gt;Andrei Vorobyov from Oracle User Group Latvia was there as well. No one else from Baltics was noticed. This event have gathered 52 attendees from EMEA region. The attendees were both Oracle and Java User Group Leaders from all over the Europe.&lt;br /&gt;&lt;br /&gt;In two days Oracle did several marketing and strategy-revealing presentations and user group leaders have had an opportunity to participate in open discussion events. The event was quite interesting. It is nice to feel that Latvian JUG is a part of a bigger family. Open discussion were related to collaboration of User Groups and universities, using social media tools for running UGs (e.g. Facebook, Twitter, Eventbrite), attracting sponsors and members and exchanging with speakers between UGs.&lt;br /&gt;&lt;br /&gt;Important news and rumours from Oracle, which are relevant to Java professionals. Some of them are well know for quite some time, some of them were new to me:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Oracle is not bad at all for Java (with the exception of Google law suite case).&lt;/li&gt;&lt;li&gt;Java licensing model stays the same for the end users. No paid Java is planned.&lt;/li&gt;&lt;li&gt;Java 7 release activities will start at 07.07.2011. This will be global J7 launch event with speakers travelling across the world. Let's cross fingers so Latvia is in the official list of the show.&lt;/li&gt;&lt;li&gt;Java 8 is almost ready and will be released in 2012.&lt;/li&gt;&lt;li&gt;Swag and free stuff will be available for ordering for UGs starting from June (T-Shirts and Posters).&lt;/li&gt;&lt;li&gt;There are chances bringing Oracle Tech Days to Riga late 2011 or 2012.&lt;/li&gt;&lt;li&gt;JUG London is now a member of JCP comittee and JCP will be hopefully more open from now on. This is the first time JUG is represented in JCP.&lt;/li&gt;&lt;li&gt;Oracle donated Hudson back to Open Source community where it belongs :)&lt;/li&gt;&lt;li&gt;JRockit and HotSpot will merge to Converged JVM. Mission Control and other monitoring tools from JRockit will be offered for a price as before.&lt;/li&gt;&lt;li&gt;IBM and Apple have joined the OpenJDK project for quite time already and Oracle is pleased with this collaboration.&lt;/li&gt;&lt;li&gt;Oracle Java Academy programme is being restored this year.&lt;/li&gt;&lt;li&gt;There is a site &lt;a href="http://jugevents.org/jugevents/"&gt;http://jugevents.org/jugevents/&lt;/a&gt; where references to JUG events are hosted.&lt;/li&gt;&lt;li&gt;Oracle conference call line is available upon request for JUGs.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;This was a valuable experience and the most important results and outcomes are the following:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Established contacts with European JUG leaders.&lt;/li&gt;&lt;li&gt;Established contacts with Oracle representatives responsible for Technical Communities.&lt;/li&gt;&lt;li&gt;Exchanged information on how other User Groups are operating and what are the typical challenges.&lt;/li&gt;&lt;li&gt;Learned more about Oracle strategy towards Java technology.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Our Java User Group actions that will follow after this event are the following:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Collaborate with European User Groups regarding exchange of speakers.&lt;/li&gt;&lt;li&gt;Sign-up for the Java 7 release activities in July.&lt;/li&gt;&lt;li&gt;Order free swag in June for giveaways on JUG events.&lt;/li&gt;&lt;li&gt;Start discussions about possibilities of hosting Oracle Tech Days in Riga.&lt;/li&gt;&lt;li&gt;Add several new "features" to JUG - feedback forms, task lists to facilitate the community.&lt;/li&gt;&lt;li&gt;Work harder to find interesting speakers for Latvian events.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Next year we hope to send someone to visit this meeting again. Chezch beer and the old city were also great...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29163398-7866150151873785242?l=buzdin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://buzdin.blogspot.com/feeds/7866150151873785242/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29163398&amp;postID=7866150151873785242' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/7866150151873785242'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/7866150151873785242'/><link rel='alternate' type='text/html' href='http://buzdin.blogspot.com/2011/05/oracle-emea-users-group-leaders-meeting.html' title='Oracle EMEA Users Group Leaders’ meeting'/><author><name>Dmitry Buzdin</name><uri>http://www.blogger.com/profile/14535724893723283597</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_wJqXOQNlTV4/TTmJvIpu36I/AAAAAAAAABQ/B32dD3nU1S4/s220/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29163398.post-7086138084176834958</id><published>2011-05-10T12:39:00.001+03:00</published><updated>2011-05-10T12:41:04.055+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='jug'/><title type='text'>Technical Conference Checklist</title><content type='html'>&lt;h2 id="internal-source-marker_0.7529181842648426" style="font-family: inherit;"&gt;&lt;span style="font-size: small;"&gt;&lt;b&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;After organizing several larger events in 2010/2011 related to Java and Agile User Group activities in Latvia we came up with the basic check list for such events in order not to forget anything for the next time. I believe that this checklist could be valuable for people starting to think organizing various User Group events. So here it is.&lt;/span&gt;&lt;/span&gt;&lt;span style="background-color: transparent; color: black; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline;"&gt; &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;&lt;h2 id="internal-source-marker_0.7529181842648426"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 18pt; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline;"&gt;Before (long term)&lt;/span&gt;&lt;/h2&gt;&lt;ul&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Decide how many people we expect&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Pick event date&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Check for overlapping events in the region&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Book premises&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Prepare conference site&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Find good speakers&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Estimate budget&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Find sponsors&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Sign contracts with sponsors&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Advertise the event on partner sites, blogs and specialized portals&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Create early bird discounts in case of paid events&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 18pt; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline;"&gt;Before (short term)&lt;/span&gt;&lt;/h2&gt;&lt;ul&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Print event programme for attendees&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Create T-Shirts or other conference related stuff&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Plan for food and drinks&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Prepare badges for attendees&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Create online registration form (e.g. Eventbrite)&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Prepare online-feedback form&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Review and listen to presentations&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Find the place for afterparty&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Prepare opening speech&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Prepare closing speech&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Prepare for filming&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Check with sponsors about banners and advertising materials&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Receive confirmation from all speakers&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Receive the final presentations from speakers before the event&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Check the venue for microphones, beamers and other infrastructure&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 18pt; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline;"&gt;During&lt;/span&gt;&lt;/h2&gt;&lt;ul&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Place sponsors banners&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Mention sponsors in opening and closing speeches&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Announce event Twitter channel&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Place Computer or Beamer with live twits&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Tell about afterparty, lunch and other related activities&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Elaborate on event content in introductory speech&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Control speakers time (5 minutes warning)&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Have coffee breaks&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Have few longer breaks for networking&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Help to hold Q/A session after each presentation&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Announce each speaker&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Tell about next planned events/activities&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Film presentations&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 18pt; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline;"&gt;After&lt;/span&gt;&lt;/h2&gt;&lt;ul&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Publish blog post about the event&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Publish presentations and videos online&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Send link to online-feedback form to attendees &lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Summarize feedback&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Send feedback to speakers&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Send letter of gratitude to speakers&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"&gt;Hold retrospectives meeting&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29163398-7086138084176834958?l=buzdin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://buzdin.blogspot.com/feeds/7086138084176834958/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29163398&amp;postID=7086138084176834958' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/7086138084176834958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/7086138084176834958'/><link rel='alternate' type='text/html' href='http://buzdin.blogspot.com/2011/05/technical-conference-checklist.html' title='Technical Conference Checklist'/><author><name>Dmitry Buzdin</name><uri>http://www.blogger.com/profile/14535724893723283597</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_wJqXOQNlTV4/TTmJvIpu36I/AAAAAAAAABQ/B32dD3nU1S4/s220/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29163398.post-1436924846342469943</id><published>2011-04-18T13:38:00.002+03:00</published><updated>2011-04-18T13:40:26.715+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='jug'/><category scheme='http://www.blogger.com/atom/ns#' term='play'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><title type='text'>Playing with Play</title><content type='html'>I have given the presentation on&amp;nbsp;&lt;a href="http://www.playframework.org/"&gt;http://www.playframework.org/&lt;/a&gt;&amp;nbsp;at the joint Oracle and Java User Groups event in Riga last Thursday (&lt;a href="http://www.jug.lv/events/2011/-6---april"&gt;http://www.jug.lv/events/april&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;I have ignored Play framework previously, thinking that it is yet another MVC web framework with no real use-cases. However, it turned out to be very concise and well-positioned tool for building page-oriented applications. The core selling points of Play are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Productivity - comparable to Rails-like frameworks;&lt;/li&gt;&lt;li&gt;Simplicity - I would say Play is simpler than Rails;&lt;/li&gt;&lt;li&gt;Performance - absolutely stateless, it does not encourage to use sessions at all;&lt;/li&gt;&lt;li&gt;REST support - seamless HTTP to Java mapping for HTML/JSON/XML representations.&lt;/li&gt;&lt;/ul&gt;Presentation slides are published on Slideshare. The demo was demonstrating most impressive Play features:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Instant Java code refresh&lt;/li&gt;&lt;li&gt;Java compiler errors in the browser!&lt;/li&gt;&lt;li&gt;Groovy templating language&lt;/li&gt;&lt;li&gt;Automatic HTTP request mapping&lt;/li&gt;&lt;li&gt;JPA support&lt;/li&gt;&lt;li&gt;Testing mode&lt;/li&gt;&lt;/ul&gt;&lt;div id="__ss_7660969" style="width: 425px;"&gt;&lt;strong style="display: block; margin: 12px 0 4px;"&gt;&lt;a href="http://www.slideshare.net/buzdin/java-and-the-web" title="Java and the Web"&gt;Java and the Web&lt;/a&gt;&lt;/strong&gt;&lt;object height="355" id="__sse7660969" width="425"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=jug-web-trends-110418032553-phpapp01&amp;stripped_title=java-and-the-web&amp;userName=buzdin" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse7660969" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=jug-web-trends-110418032553-phpapp01&amp;stripped_title=java-and-the-web&amp;userName=buzdin" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;div style="padding: 5px 0 12px;"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/buzdin"&gt;Dmitry Buzdin&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I would suggest every Java Web developer to take a look at Play, since my gut feeling is that it will take its part of the market pretty soon. Play is not too mature framework. The oldest mailing posts date back to 2009. However, it is designed and implemented taking into consideration modern trends and requirements for real web projects. Technologies like NoSQL, EhCache, Memcached, Scala are supported with help of additional modules. The framework is very easy to learn and you could start writing real code in no time.&lt;br /&gt;&lt;br /&gt;Since Play does not bring any advanced RIA stuff you could easily put GWT on top and let Play to handle REST backend and provide page navigation model.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29163398-1436924846342469943?l=buzdin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://buzdin.blogspot.com/feeds/1436924846342469943/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29163398&amp;postID=1436924846342469943' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/1436924846342469943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/1436924846342469943'/><link rel='alternate' type='text/html' href='http://buzdin.blogspot.com/2011/04/playing-with-play.html' title='Playing with Play'/><author><name>Dmitry Buzdin</name><uri>http://www.blogger.com/profile/14535724893723283597</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_wJqXOQNlTV4/TTmJvIpu36I/AAAAAAAAABQ/B32dD3nU1S4/s220/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29163398.post-4269102380508995092</id><published>2011-03-24T14:57:00.000+02:00</published><updated>2011-03-24T14:57:26.466+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gwt'/><title type='text'>Advanced Web Application Development with GWT</title><content type='html'>Finally, the podcast from my 10th of March session in SkillsMatter London premises is available online (&lt;span class="Apple-style-span" style="border-collapse: collapse; font-family: arial, sans-serif; font-size: 13px; line-height: 19px; white-space: nowrap;"&gt;&lt;a href="http://goo.gl/2IKz1"&gt;http://goo.gl/2IKz1&lt;/a&gt;&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;This was an introductory lecture on what GWT really is and is not. It has some interesting parallels of how GWT fits with current state of IT technology. One of the key points is that JavaScript demand increases with each day. More and more RIA application and mobile-HTML5 enabled devices are available. And as we all know JavaScript simply does not scale. I will not go in details here and I am pretty sure that there are JavaScript professionals who think differently, but it is rather a collective industry opinion, not just mine. JavaScript is a low level language with lots of portability and other non-functional problems. So either you are expert in that or you use GWT. These are the general options today (or use Flash?).&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: arial, sans-serif; font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="border-collapse: collapse; line-height: 19px; white-space: nowrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29163398-4269102380508995092?l=buzdin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://buzdin.blogspot.com/feeds/4269102380508995092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29163398&amp;postID=4269102380508995092' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/4269102380508995092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/4269102380508995092'/><link rel='alternate' type='text/html' href='http://buzdin.blogspot.com/2011/03/advanced-web-application-development.html' title='Advanced Web Application Development with GWT'/><author><name>Dmitry Buzdin</name><uri>http://www.blogger.com/profile/14535724893723283597</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_wJqXOQNlTV4/TTmJvIpu36I/AAAAAAAAABQ/B32dD3nU1S4/s220/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29163398.post-6190467875519392951</id><published>2011-02-16T13:21:00.000+02:00</published><updated>2011-02-16T13:21:20.686+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='gwt'/><title type='text'>GWT Compiler Optimizations</title><content type='html'>GWT compiler is slow, everyone knows that. Every time someone compares GWT with other "super Web 2.0 technology" the main drawback of GWT is stated quite simply - it is slow.&lt;br /&gt;&lt;br /&gt;But what does make the compiler slow. Is it just a poor quality of the framework? Or is it just a lot of things going on undercover and we would really like to run them even knowing the performance implications. This post highlights performance optimizations done in GWT Compiler. I have failed, personally, to find any decent documentation on this subject other than reading the source code, which resulted in a given description. The observations are done using SVN trunk, so it may be possible that in older versions of GWT you are using some optimizations are yet missing or work a bit differently.&lt;br /&gt;&lt;br /&gt;The entry point for the source code is&amp;nbsp;&lt;i&gt;JavaToJavaScriptCompiler&lt;/i&gt; in &lt;i&gt;gwt-dev.jar&lt;/i&gt; package. Most of the optimizations are done in &lt;i&gt;compilePermutation()&lt;/i&gt; and&amp;nbsp;&lt;i&gt;optimizeLoop()&lt;/i&gt; methods.&amp;nbsp;Optimizations are utilizing &lt;a href="http://en.wikipedia.org/wiki/Visitor_pattern"&gt;Visitor pattern&lt;/a&gt;&amp;nbsp;extensively and are work on GWT implementation of Java &lt;a href="http://en.wikipedia.org/wiki/Abstract_syntax_tree"&gt;Abstract Syntax Tree&lt;/a&gt; (AST) (JClass, JField etc.). Visitor pattern is a common choice for tool doing source code traversal (such as &lt;a href="http://findbugs.sourceforge.net/"&gt;FindBugs&lt;/a&gt;).&amp;nbsp;Note that some of the optimizations are executed several times depending on optimization settings. That is done because first round of optimizations can unlock potential improvements for the second round. It could take several loops for the complex code base to "diverge" into the stable/optimal state.&lt;br /&gt;&lt;br /&gt;On a high level the compiler does the following chain of transformations starting with the Java source code and ending with JavaScript source:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Java Source Code -&amp;gt; Java AST -&amp;gt; Optimized Java AST -&amp;gt; JavaScript AST -&amp;gt; Optimized JavaScript AST -&amp;gt; Obfuscated JavaScript AST -&amp;gt; JavaScript&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Note that GWT works with the sources, not with the bytecode as this is sometimes a misconception. GWT does not invoke Java Compiler and does not depend on that. This post describes &lt;b&gt;Java AST&lt;/b&gt; to &lt;b&gt;Optimized Java AST&lt;/b&gt; transformation only. Other transformation steps are worth separate discussion.&lt;br /&gt;&lt;br /&gt;And now lets get to the list of optimizations - in order of their appearance in the source code:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Pruning&lt;/b&gt; - removing unreferenced classes and interfaces as well as methods and fields. This is the magic optimization, which allows you to include megabytes of GWT dependencies and still produce downloadable JavaScript piece if you do not use all library features.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Finalizing&lt;/b&gt; - make methods, classes and variables final if there is such a possibility.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Make Static&lt;/b&gt; - if instance method can be done static it is rewritten to static, which means it is not overridden anywhere and does not depend on instance variables.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Type Tightening&lt;/b&gt; - optimization of field and parameter types to be more concrete. This is done in order to reduce type casts and instanceof checks.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Method Call Tightening&lt;/b&gt; - updates&amp;nbsp;polymorphic method calls in order to invoke the exact version of method right away. Walks up class hierarchy and finds most suitable method.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Dead Code Elimination&lt;/b&gt; - eliminates irrelevant parts in logical conditions and expressions (such as a || true; a + 0), which do not make any effect on program execution. This is mostly done in areas of Java primitives and logical operators.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Method Inlining&lt;/b&gt; - algorithm inlines (embeds) method bodies with no more than 2 lines and no references to other external methods. The idea is that it is more optimal to embed those one-two lines in multiple places rather than leave a separate method for that.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Same Parameter Value Optimizer&lt;/b&gt; - detects when the literal passed through parameter is used in method calls. Uses the literal directly, which makes the parameter obsolete.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Enum Ordinalizer&lt;/b&gt; - replaces references to Enum variables with their ordinal values. This is usually simply int key representation.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Remove Empty Super Calls&lt;/b&gt; - what could be simpler to understand. Does exactly what is says - removes super() calls to empty methods.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Set of Normalization Rules&lt;/b&gt; - make similar operations look unified. Merging catch blocks, working with arrays etc. The goal is to transform common parts of code to be optimal for JavaScript generation purposes without changing the behavior. Replaces calls to JDK classes with calls to com.google.gwt.lang classes.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Pruning&lt;/b&gt;&amp;nbsp;- is run for the second time as the last optimization as previous AST modifications could unlock new potential constructs, which are not referenced anymore.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;This is a full list of Java AST optimizations I could spot in the source code and which are implemented in explicit manner. The source code is easy to read and well documented therefore I advice everyone interested to take a closer look.&lt;br /&gt;&lt;br /&gt;To summarize - GWT can not be compared to other Web 2.0 technologies as those are not doing even a fraction of provided optimizations on JavaScript level. Of course server centric Ajax frameworks fully benefit from Java Compiler and JVM JIT optimizations, which are not available for GWT running in the browser unfortunately. So it is up to you what path to choose. Despite the number and complexity of optimizations GWT compiler is very stable and bugs in its core are rarely encountered. This message come both from personal experience and talks with fellow GWT users.&lt;br /&gt;&lt;br /&gt;It is possible to disable all optimizations by passing &lt;b&gt;-draftCompile&lt;/b&gt;&amp;nbsp;flag to GWT compiler. In this case most of the optimizations will be omitted. This is the answer for impatient who can not wait for their application to recompile. And don't forget to use Development mode (which does not invoke Java to JavaScript compilation), SSD disks and Dual Core Machines in your development environment.&lt;br /&gt;&lt;br /&gt;There is a&amp;nbsp;&lt;a href="http://code.google.com/p/google-web-toolkit/wiki/CompilerOptimizations"&gt;page&amp;nbsp;&lt;/a&gt;describing future planned optimizations. Sharing it just for curiosity purposes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29163398-6190467875519392951?l=buzdin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://buzdin.blogspot.com/feeds/6190467875519392951/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29163398&amp;postID=6190467875519392951' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/6190467875519392951'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/6190467875519392951'/><link rel='alternate' type='text/html' href='http://buzdin.blogspot.com/2011/02/gwt-compiler-optimizations.html' title='GWT Compiler Optimizations'/><author><name>Dmitry Buzdin</name><uri>http://www.blogger.com/profile/14535724893723283597</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_wJqXOQNlTV4/TTmJvIpu36I/AAAAAAAAABQ/B32dD3nU1S4/s220/face.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29163398.post-728277227726309286</id><published>2011-01-20T14:41:00.002+02:00</published><updated>2011-01-20T14:45:28.248+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='reflection'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><title type='text'>Is Java Reflection Really Slow?</title><content type='html'>One of the sayings you still hear nowadays from fellow developers is that not only &lt;i&gt;Java&lt;/i&gt; is slow, but also that &lt;i&gt;Reflection&lt;/i&gt; is an exceptionally slow part of the JDK.&amp;nbsp;This post is intended for those who believes that or want to have a constructive conversation with the believers.&lt;br /&gt;&lt;br /&gt;Technical topics presented in this post are years old, but somehow some of the things are surprising when you discover them.&amp;nbsp;So even if you are a seasoned Java developer you may find some interesting points here.&lt;br /&gt;&lt;br /&gt;How can anyone measure that reflection is slow? The first thought is by running a benchmarking app. This could be done as simple as following.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;long start = System.nanoTime();&lt;br /&gt;method.invoke("reflection");&lt;br /&gt;long stop = System.nanoTime();&lt;br /&gt;...&lt;br /&gt;long start = System.nanoTime();&lt;br /&gt;"reflection".length();&lt;br /&gt;long stop = System.nanoTime();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The results are quite obvious: reflection version takes around 15000 nano seconds, which is 15 micro seconds; method invocation takes 2.2 micro seconds, which is around &lt;b&gt;7 times faster&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;But was it really a clean test, which shows us real results? It turns out that not exactly. The test was far from being clean. The most obvious thing is that for the first time the results will be slower, because of the possible &lt;i&gt;Class Loading&lt;/i&gt;, initialization and other activities, which may result in excessive objects being created and &lt;i&gt;Garbage Collection&lt;/i&gt; invoked.&lt;br /&gt;&lt;br /&gt;The first thing to fix is to run the test for several times in order to warm-up the code. How many times you should do that to get the plausible results? One, two or ten? It turns out that you should do even more than that. Aside of usual &lt;i&gt;Class Loading&lt;/i&gt; there are different things happening under the hood. &lt;i&gt;JIT&lt;/i&gt; compilation may occur at some point and also internal &lt;i&gt;JVM&lt;/i&gt; implementation optimization. It turns out that you could monitor whether any classloading and/or &lt;i&gt;JIT&lt;/i&gt; compilation is happenning programmatically in order to know whether there were disturbances in test. This could be done by two provided JMX beans. Note that some of the JIT compilation processes are triggered only on if JVM started with -server switch. By default JVM works in -client mode assuming more random class invocation patterns than on the server and does not apply heavy optimization of the code. So if you have ever ran benchmarks in -client mode, please redo them, as they differ greatly as we will learn further.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;ClassLoadingMXBean classLoadingBean = ManagementFactory.getClassLoadingMXBean();&lt;br /&gt;CompilationMXBean compilationBean = ManagementFactory.getCompilationMXBean();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You could poll these beans after each test iteration and compare the timings to know whether class loading or compilation was active during last iteration. Ok, this is solved. Now more interesting topics. In Sun JVM there is a mechanism called &lt;i&gt;Reflection Inflation&lt;/i&gt;. In two words it "inflates" reflective method invokations with bytecode implementations meaning there will be less overhead to call them. Take a look at the &lt;a href="http://www.docjar.com/html/api/sun/reflect/ReflectionFactory.java.html"&gt;implementation&lt;/a&gt;. This process is triggered by default only after 15 iterations. It means that only 16th test iteration will be closer to what we will have on real application environment.&lt;br /&gt;&lt;br /&gt;Now it becomes clear that the first attempt to perform performance test of reflection was oversimplified and there are plenty of details to consider. One approach to still measure the performance is to use a &lt;b&gt;microbenchmarking&lt;/b&gt; tool. Microbenchmarkings tools are intended to bring the JVM in "stable" state prior to executing tests and run your test suite for sufficient amount of time to get statistically proven evidence of the results.&lt;br /&gt;&lt;br /&gt;One of the frameworks I tried and quite liked was &lt;a href="http://www.ibm.com/developerworks/java/library/j-benchmark2/index.html"&gt;Microbenchmarking tool&lt;/a&gt; from Brent Boyer. It has very simple API and the only thing you should do is to put your specimen code inside &lt;i&gt;Callable&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;public static void main(String[] args) throws Exception {&lt;br /&gt;    Callable task = new Callable() {&lt;br /&gt;        final Method method;&lt;br /&gt;        final FastMethod fastMethod;&lt;br /&gt;        final Object[] EMPTY_ARRAY = {};&lt;br /&gt;        {&lt;br /&gt;            method = String.class.getMethod("length");&lt;br /&gt;            FastClass fastClass = FastClass.create(String.class);&lt;br /&gt;            fastMethod = fastClass.getMethod(method);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public Object call() throws Exception {&lt;br /&gt;            //return method.invoke("hello");&lt;br /&gt;            return fastMethod.invoke("hello", EMPTY_ARRAY);&lt;br /&gt;            //return "hello".length();&lt;br /&gt;        }&lt;br /&gt;    };&lt;br /&gt;    Benchmark benchmark = new Benchmark(task);&lt;br /&gt;    System.out.println(benchmark);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I have included the third method call approach in the tests, which is &lt;i&gt;CGLib &lt;/i&gt;&lt;br /&gt;&lt;a href="http://cglib.sourceforge.net/apidocs/net/sf/cglib/reflect/FastMethod.html"&gt;FastMethod&lt;/a&gt;. By using it you force to generate bytecode method accessor from the first execution time and exactly where you want it. This approach was used in frameworks for some time (for example in Hibernate), but nowadays people are going away from that to direct reflection invocation as it does not have a radical difference on modern JVMs.&lt;br /&gt;&lt;br /&gt;The results for running direct method invocation, reflective one and CGLib FastMethod in both server and client modes are given below.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;-client getter() :         first = 36.743 us, mean = 10.317 ns (CI deltas: -46.363 ps, +178.344 ps), sd = 3.697 us (CI deltas: -2.959 us, +4.774 us)&lt;br /&gt;-client Method.invoke() :  first = 52.688 us, mean = 128.262 ns (CI deltas: -1.377 ns, +1.635 ns), sd = 17.014 us (CI deltas: -2.323 us, +3.549 us)&lt;br /&gt;-client CgLib FastMethod : first = 42.709 us, mean = 27.511 ns (CI deltas: -119.732 ps, +186.596 ps), sd = 4.722 us (CI deltas: -1.398 us, +2.178 us)&lt;br /&gt;&lt;br /&gt;-server getter() :         first = 38.303 us, mean = 3.915 ns (CI deltas: -14.731 ps, +19.287 ps), sd = 1.088 us (CI deltas: -204.310 ns, +360.180 ns)&lt;br /&gt;-server Method.invoke() :  first = 44.177 us, mean = 24.041 ns (CI deltas: -77.722 ps, +124.821 ps), sd = 3.127 us (CI deltas: -925.638 ns, +1.617 us)&lt;br /&gt;-server CgLib FastMethod : first = 44.941 us, mean = 14.756 ns (CI deltas: -97.488 ps, +165.397 ps), sd = 5.685 us (CI deltas: -1.988 us, +2.727 us)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;On my workstation calling a method by reflection 100000 (hundred thousand) of times should cost us only &lt;b&gt;~3 milliseconds&lt;/b&gt;! The conclusion is that on modern server infrastructure with proper JVM settings we should not be worried about Refelction performance too much. Another conclusion is that going in the direction of direct bytecode manipulation such as &lt;i&gt;CGLib FastMethod&lt;/i&gt; will not bring a tremendous difference in performance, but will add dependencies and complexity to your project. If someone is blaming to detect performance degradation using reflection this could be the case of &lt;i&gt;-client&lt;/i&gt; measurements with only a few iterations. Of course this is only valid if we simply compare direct invocations with&amp;nbsp;calls by&amp;nbsp;reflection. If you heavily use Class introspection API and do a lot of other fancy Reflection stuff things can become really slow.&lt;br /&gt;&lt;br /&gt;Here are the same comparison results done by &lt;a href="http://code.google.com/apis/chart/docs/making_charts.html"&gt;Google Charts API&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://chart.apis.google.com/chart?chxt=y&amp;amp;chbh=a&amp;amp;chs=400x300&amp;amp;cht=bvg&amp;amp;chco=4D89F9,C6D0FD,C6A9FD,C6A91D,66A9FD,C6E9FD&amp;amp;chds=1,128,10,128,0,100,0,100,5,100&amp;amp;chd=t:10|128|28|4|24|15&amp;amp;chdl=client+direct|client+reflection|client+cglib|server+direct|server+reflection|server+cglib&amp;amp;chp=0,0,0.05&amp;amp;chtt=Microbenchmarking+Results&amp;amp;chts=000000,12.5" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://chart.apis.google.com/chart?chxt=y&amp;amp;chbh=a&amp;amp;chs=400x300&amp;amp;cht=bvg&amp;amp;chco=4D89F9,C6D0FD,C6A9FD,C6A91D,66A9FD,C6E9FD&amp;amp;chds=1,128,10,128,0,100,0,100,5,100&amp;amp;chd=t:10|128|28|4|24|15&amp;amp;chdl=client+direct|client+reflection|client+cglib|server+direct|server+reflection|server+cglib&amp;amp;chp=0,0,0.05&amp;amp;chtt=Microbenchmarking+Results&amp;amp;chts=000000,12.5" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;So if anyone will try to blame you for writing slow reflection code you could share this results and re-run microbenchmarking tests by yourself.&lt;br /&gt;&lt;br /&gt;Similar performance benchmark results, which triggered this post could be found &lt;a href="http://www.ibm.com/developerworks/forums/thread.jspa?messageID=13862806"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29163398-728277227726309286?l=buzdin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://buzdin.blogspot.com/feeds/728277227726309286/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29163398&amp;postID=728277227726309286' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/728277227726309286'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/728277227726309286'/><link rel='alternate' type='text/html' href='http://buzdin.blogspot.com/2011/01/is-java-reflection-really-slow.html' title='Is Java Reflection Really Slow?'/><author><name>Dmitry Buzdin</name><uri>http://www.blogger.com/profile/14535724893723283597</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_wJqXOQNlTV4/TTmJvIpu36I/AAAAAAAAABQ/B32dD3nU1S4/s220/face.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29163398.post-3387673202424993136</id><published>2010-10-14T14:19:00.002+03:00</published><updated>2011-01-20T14:45:38.526+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='gwt'/><title type='text'>Simplest Code Generator with GWT</title><content type='html'>Many people tend to think of GWT as a specialized Web framework. However its main essence is Java to JavaScript compiler. One of the great things you could do with that is to write your own code generators, which gets invoked during compilation process. There is limited documentation on this topic on official GWT site. Reference to RPC implementation generator can be found at &lt;a class="external-link" href="http://code.google.com/webtoolkit/doc/latest/DevGuideCodingBasicsDeferred.html" rel="nofollow"&gt;Deferred Binding Page&lt;/a&gt;. The example given is a bit complex and require GWT source code digging to understand what is happening there.&lt;br /&gt;Therefore this post represents the simplest working code generation example, which shows the general approach and its capabilities. What we need to achieve in this example is to provide a generated implementation for Function interface shown below.&lt;br /&gt;&lt;pre&gt;&lt;span class="code-keyword"&gt;public&lt;/span&gt; &lt;span class="code-keyword"&gt;interface&lt;/span&gt; Function {&lt;br /&gt;    &lt;span class="code-keyword"&gt;public&lt;/span&gt; &lt;span class="code-object"&gt;Object&lt;/span&gt; execute();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;To test the results you should invoke GWT compilation and its code generation engine. It is possible to do so out of GWTTestCase. The following test checks that implemented funcionality works as expected. Now we have to make our test runnable and passing. The most important part here is invocation of GWT.create(), which is the entry point of the Deferred Binding.&lt;br /&gt;&lt;pre&gt;&lt;span class="code-keyword"&gt;public&lt;/span&gt; class FunctionGeneratorTest &lt;span class="code-keyword"&gt;extends&lt;/span&gt; GWTTestCase {&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    &lt;span class="code-keyword"&gt;public&lt;/span&gt; &lt;span class="code-object"&gt;String&lt;/span&gt; getModuleName() {&lt;br /&gt;        &lt;span class="code-keyword"&gt;return&lt;/span&gt; &lt;span class="code-quote"&gt;"com.acme.gwt.Generator"&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="code-keyword"&gt;public&lt;/span&gt; void testGenerator() &lt;span class="code-keyword"&gt;throws&lt;/span&gt; Exception {&lt;br /&gt;        Function function = GWT.create(Function.class);&lt;br /&gt;        assertNotNull(function);&lt;br /&gt;        assertEquals(&lt;span class="code-quote"&gt;"Hello"&lt;/span&gt;, function.execute());&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;First what you need to do is tell the compiler that the interface will be replaced by generated implementation. To do so you need to put the following instructions to your gwt.xml descriptor.&lt;br /&gt;&lt;pre class="code-java"&gt;&amp;lt;generate-with class=&lt;span class="code-quote"&gt;"com.acme.gwt.FunctionGenerator"&lt;/span&gt;&amp;gt;&lt;br /&gt;    &amp;lt;when-type-assignable class=&lt;span class="code-quote"&gt;"com.acme.gwt.Function"&lt;/span&gt; /&amp;gt;&lt;br /&gt;&amp;lt;/generate-with&amp;gt;&lt;br /&gt;&lt;/pre&gt;Now let's code the generator itself. You should extend &lt;a class="external-link" href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/index.html?overview-summary.html" rel="nofollow"&gt;Generator&lt;/a&gt; class to make it work.&lt;br /&gt;&lt;pre class="code-java"&gt;&lt;span class="code-keyword"&gt;public&lt;/span&gt; class FunctionGenerator &lt;span class="code-keyword"&gt;extends&lt;/span&gt; Generator {&lt;br /&gt;    &lt;span class="code-keyword"&gt;private&lt;/span&gt; &lt;span class="code-keyword"&gt;static&lt;/span&gt; &lt;span class="code-keyword"&gt;final&lt;/span&gt; &lt;span class="code-object"&gt;String&lt;/span&gt; IMPL_TYPE_NAME = &lt;br /&gt;Function.class.getSimpleName() + &lt;span class="code-quote"&gt;"Impl"&lt;/span&gt;;&lt;br /&gt;    &lt;span class="code-keyword"&gt;private&lt;/span&gt; &lt;span class="code-keyword"&gt;static&lt;/span&gt; &lt;span class="code-keyword"&gt;final&lt;/span&gt; &lt;span class="code-object"&gt;String&lt;/span&gt; IMPL_PACKAGE_NAME = &lt;br /&gt;Function.class.getPackage().getName();&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    &lt;span class="code-keyword"&gt;public&lt;/span&gt; &lt;span class="code-object"&gt;String&lt;/span&gt; generate(TreeLogger logger, GeneratorContext context, &lt;br /&gt;String requestedClass) throws UnableToCompleteException {&lt;br /&gt;        TypeOracle typeOracle = context.getTypeOracle();&lt;br /&gt;        JClassType functionType = typeOracle.findType(requestedClass);&lt;br /&gt;        &lt;span class="code-keyword"&gt;assert&lt;/span&gt; Function.class.equals(functionType.getClass());&lt;br /&gt;&lt;br /&gt;        ClassSourceFileComposerFactory composerFactory =&lt;br /&gt;            new ClassSourceFileComposerFactory(&lt;br /&gt;                IMPL_PACKAGE_NAME, IMPL_TYPE_NAME);&lt;br /&gt;&lt;br /&gt;        composerFactory.addImport(Function.class.getCanonicalName());&lt;br /&gt;        composerFactory.addImplementedInterface(Function.class.getName());&lt;br /&gt;&lt;br /&gt;        PrintWriter printWriter = context&lt;br /&gt;            .tryCreate(logger, IMPL_PACKAGE_NAME, IMPL_TYPE_NAME);&lt;br /&gt;        SourceWriter sourceWriter = composerFactory&lt;br /&gt;            .createSourceWriter(context, printWriter);&lt;br /&gt;&lt;br /&gt;        sourceWriter.print(&lt;span class="code-quote"&gt;"&lt;span class="code-keyword"&gt;public&lt;/span&gt; &lt;span class="code-object"&gt;Object&lt;/span&gt; execute() {"&lt;/span&gt;);&lt;br /&gt;        sourceWriter.print(&lt;span class="code-quote"&gt;"    &lt;span class="code-keyword"&gt;return&lt;/span&gt; "&lt;/span&gt;Hello&lt;span class="code-quote"&gt;";"&lt;/span&gt;);&lt;br /&gt;        sourceWriter.print(&lt;span class="code-quote"&gt;"}"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;        sourceWriter.commit(logger);&lt;br /&gt;        &lt;span class="code-keyword"&gt;return&lt;/span&gt; IMPL_PACKAGE_NAME + &lt;span class="code-quote"&gt;"."&lt;/span&gt; + IMPL_TYPE_NAME;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The Generator loads requested Function interface, determines its package and writes down FunctionImpl type with method execute implemented. You are completely in control of what Java code you are outputting. It is possible to add implementing interfaces, parent class, imports and annotations. Then the body of the class is written using simple String concatenation. Notice TypeOracle class, which is GWT internal Type introspection engine.&lt;br /&gt;This is the simplest possible generator, but here you have limitless capabilities of introspecting existing classes, looking for annotations and then generating the boilerplate code. In fact Deferred Binding and Generators are the basis for most of the advanced GWT frameworks like gwt-log and gin. Good knowledge of Generator concept is absolute must to understand how GWT technologies work internally. The example is prepared using GWT 2.0.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29163398-3387673202424993136?l=buzdin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://buzdin.blogspot.com/feeds/3387673202424993136/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29163398&amp;postID=3387673202424993136' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/3387673202424993136'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/3387673202424993136'/><link rel='alternate' type='text/html' href='http://buzdin.blogspot.com/2010/10/simplest-code-generator-with-gwt.html' title='Simplest Code Generator with GWT'/><author><name>Dmitry Buzdin</name><uri>http://www.blogger.com/profile/14535724893723283597</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_wJqXOQNlTV4/TTmJvIpu36I/AAAAAAAAABQ/B32dD3nU1S4/s220/face.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29163398.post-500308674692654425</id><published>2010-09-09T11:04:00.003+03:00</published><updated>2010-09-09T11:26:32.642+03:00</updated><title type='text'>ThoughtWorks Radar Demystified (GWT)</title><content type='html'>I have recently discovered &lt;a href="http://www.thoughtworks.com/sites/www.thoughtworks.com/files/files/thoughtworks-tech-radar-august-2010-UK-AUS-colour.pdf"&gt;ThoughtWorks technology radar&lt;/a&gt;, which is published since January this year.&lt;br /&gt;&lt;br /&gt;First of all I find it a very useful tool to follow the general trends in realistic software development. Before that, all radars, seen by myself, were either internal customer ones (means that they can not be shared) or radars from companies like Forrester and Gartner, which are an interesting reading, but more concentrated on comparing commercial products, like ESB and BPM providers. Main target of such reports are business people or IT management, so it does not spend much attention to exact low-level techniques and tools used for productivity gains. As my personal opinion is most of the heavyweight tools should stay in the past (exceptions exist of course), therefore I am not interested in this kind of reading.&lt;br /&gt;&lt;br /&gt;ThoughtWorks radar is split in four parts: techniques, tools, platforms and languages. Each part of the radar is divided in four areas: hold, assess, trial, adopt. The most interesting ones are "hold" and "adopt". On "hold" means that the technology/technique is in a risky state of being discarded or have undergoing major changes, which will make its future more clear. "Adopt" means the technology/technique is usable for productive projects and efficiency gains are worth investing.&lt;br /&gt;&lt;br /&gt;The main reasons to post this, is single particular point on the radar, which is GWT (found in Platforms section). Right now it is put "on hold", which is surprising to me, as the technology keeps gaining the momentum to become one of the major future Web technologies. Therefore I would like to understand why ThoughtWorks is thinking in this way and provide my comments on that.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Platforms - Google Web Toolkit&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The current decision is to have GWT on hold. To quote ThoughtWorks from radar's April edition:&lt;br /&gt;&lt;br /&gt;"Google Web Toolkit (GWT) offers an interesting premise: write Swing-like Java code and generate unit testable JavaScript widgets and user interfaces. From a practical standpoint this doesn’t work well. First, using code-gen to produce the artifacts is time consuming, artificially extending build times and requiring manual changes to obtain optimal package layout. Second, if the JavaScript doesn’t behave exactly as you want you will have to hack the generated code. Third, using Java to generate JavaScript means that you can’t take direct advantage of the powerful features of JavaScript or numerous libraries such as JQuery. Finally, the JUnit support is quite limited, for example code using reflection cannot be tested."&lt;br /&gt;&lt;br /&gt;Unfortunately I have an impression that this has been written by a person who did not use GWT at all, but rather studied several articles. GWT does not make you to use code generation during development. During coding in the development mode you are simply refreshing browser, which brings client code changes automatically without recompilation or lengthy code generation. This is backed up by the way GWT compiler works. It actually parses and compiles Java sources, bypassing javac invocation. That is how dynamic recompilation and reloading is implemented. This gives you the same productivity benefits as you would get by using dynamic languages on JVM such as JRuby.&lt;br /&gt;&lt;br /&gt;The section about "manual changes" can be generally applied to code generation tools, but is not met in GWT context. GWT can have a full build automation starting from compilation and to opening a browser on the required page. &lt;br /&gt;&lt;br /&gt;Statement about possible JavaScript hacks is theoretically right, however from my personal experience we have not met a single bug in GWT compiler, which would make us to go into native JavaScript coding. And I am talking about nearly a dozen of production running projects using GWT features extensively. We have been using framework versions 1.3 to 2.0 and none of them have had serious compiler bugs, which altered application behavior unexpectedly.&lt;br /&gt;&lt;br /&gt;One more thing is that you actually *can* use native JavaScript functions, for example from JQuery. It is not a recommended approach though, but with enough technical confidence this approach is easily implemented and is called &lt;a href="http://googlewebtoolkit.blogspot.com/2008/07/getting-to-really-know-gwt-part-1-jsni.html"&gt;JSNI&lt;/a&gt; (JavaScript Native Interface). Calls to JavaScript libraries are injected inside resulting generated code and the library itself can be bundled together with GWT application distribution.&lt;br /&gt;&lt;br /&gt;JUnit support is a bit limited, that one is finally true, but the statement about reflection is totally wrong. There is no reflection possible in GWT and that is why it is not possible to test that. GWT uses Java in its own specific manner. It applies more restrictions that Java static typing model itself. To be able to properly reference all execution paths in order to apply compile-time optimizations GWT should have an understanding of a full call graph. It is impossible to do with reflective calls and that is the reasons those are forbidden in Java code compiled to JavaScript. The real limitation of JUnit is that you can't unit test widgets interactions without running test in special test harness called &lt;a href="http://code.google.com/webtoolkit/doc/1.6/DevGuideTesting.html"&gt;GWTTestCase&lt;/a&gt;. This is due to the fact that underlying Browser DOM implementation is required in order to draw most of the widgets. One of the most popular design patterns in GWT world right now is &lt;a href="http://code.google.com/webtoolkit/articles/mvp-architecture.html"&gt;MVP&lt;/a&gt;, which main goal is to address these kind of issues and separate widgets (View) from logic (Presenter).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;To Summarize&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Most of the content in the radar is done in a professional manner and is worthwhile looking at, but the GWT example is either totally wrong, or ThoughtWorkers have not looked at the framework close enough yet, but still wanted to include GWT in the list, because of its current importance. My opinion is that GWT is one of the unlocking technologies for "Browser as a Platform" vision mentioned in the radar as well. Why is it so, deserves a separate post. I wish ThoughtWorkers to review their view on the GWT potential and put that at least in Trial state. Nevertheless I would recommend the radar to my colleagues to get an overall picture of what is going in the world right now and to look for technologies/practices to invest your time with best ROI.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29163398-500308674692654425?l=buzdin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://buzdin.blogspot.com/feeds/500308674692654425/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29163398&amp;postID=500308674692654425' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/500308674692654425'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/500308674692654425'/><link rel='alternate' type='text/html' href='http://buzdin.blogspot.com/2010/09/thoughtworks-radar-demystified-gwt.html' title='ThoughtWorks Radar Demystified (GWT)'/><author><name>Dmitry Buzdin</name><uri>http://www.blogger.com/profile/14535724893723283597</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_wJqXOQNlTV4/TTmJvIpu36I/AAAAAAAAABQ/B32dD3nU1S4/s220/face.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29163398.post-3143566721269421380</id><published>2010-08-30T14:54:00.000+03:00</published><updated>2010-08-30T14:54:38.450+03:00</updated><title type='text'>Agile Latvia First Event</title><content type='html'>On the last week we have had an opportunity to organize our &lt;a href="http://www.agile-latvia.org/calendar/14242695/"&gt;first Agile event in Riga&lt;/a&gt;. Initially planned as small and short we ended up in having a full-house of 62 attendees (not including speakers) and a track of six sessions. The topics were varying between organizational practices to technical ones like TDD.&lt;br /&gt;&lt;br /&gt;The general feedback on the event was positive. We received quite a number of good comments. One of the problems stated was the fact that people beginning their Agile journey were a bit frustrated, because most of the talks were done expecting listeners to have some background in Agile already. However, more experiences people were satisfied with quality and content, which is a good sign. We will have a Retrospectives session this week to identify gaps and plan better for the next time.&lt;br /&gt;&lt;br /&gt;With first Agile Latvia being a solid success we are aiming at end of November to create a larger (full-day) international event. Stay tuned...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29163398-3143566721269421380?l=buzdin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://buzdin.blogspot.com/feeds/3143566721269421380/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29163398&amp;postID=3143566721269421380' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/3143566721269421380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/3143566721269421380'/><link rel='alternate' type='text/html' href='http://buzdin.blogspot.com/2010/08/agile-latvia-first-event.html' title='Agile Latvia First Event'/><author><name>Dmitry Buzdin</name><uri>http://www.blogger.com/profile/14535724893723283597</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_wJqXOQNlTV4/TTmJvIpu36I/AAAAAAAAABQ/B32dD3nU1S4/s220/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29163398.post-4170356395856203605</id><published>2010-06-09T17:03:00.001+03:00</published><updated>2010-06-09T17:03:26.371+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='troubleshooting'/><category scheme='http://www.blogger.com/atom/ns#' term='gwt'/><title type='text'>GWT 2.0 Development Mode on IE7</title><content type='html'>We are in process of migrating our custom Widget library to GWT 2.0.3.&lt;br /&gt;When opening Development Mode in IE7 the following JavaScript exception was thrown.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;number: -2147024891&lt;br /&gt;description: Access is denied.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;at com.google.gwt.user.client.impl.HistoryImplIE6.getTokenElement(Native Method)&lt;br /&gt;at com.google.gwt.user.client.impl.HistoryImplIE6.init(HistoryImplIE6.java:78)&lt;br /&gt;at com.google.gwt.user.client.History.&lt;clinit&gt;(History.java:63)&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It turned out to be a security violation when IFRAME located code tries to access parent document.&lt;br /&gt;The solution is pretty simple - adding localhost or 127.0.0.1 to list of trusted sites in Internet Explorer Security settings.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29163398-4170356395856203605?l=buzdin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://buzdin.blogspot.com/feeds/4170356395856203605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29163398&amp;postID=4170356395856203605' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/4170356395856203605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/4170356395856203605'/><link rel='alternate' type='text/html' href='http://buzdin.blogspot.com/2010/06/gwt-20-development-mode-on-ie7.html' title='GWT 2.0 Development Mode on IE7'/><author><name>Dmitry Buzdin</name><uri>http://www.blogger.com/profile/14535724893723283597</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_wJqXOQNlTV4/TTmJvIpu36I/AAAAAAAAABQ/B32dD3nU1S4/s220/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29163398.post-5663510375551094710</id><published>2010-05-17T23:58:00.010+03:00</published><updated>2010-05-31T17:54:45.874+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='gwt'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>GWT Dynamic Model</title><content type='html'>&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In the current GWT world the most popular (at least in theory) architectural style to build serious enterprise applications is &lt;a href="http://en.wikipedia.org/wiki/Model-view-presenter"&gt;MVP&lt;/a&gt;. Quite a lot of articles and open source frameworks are dedicated to M and V of the MVP, but to my knowledge not so many information is there how to make the M (Model part) right.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This post is giving an insight on Dynamic Model approach successfully used in several serious enterprise applications based on GWT framework. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Dynamic Model is nothing new, but a generic model, backed up with a map implementation. It means that there is no traditional getters and setters at all, but instead generic get(String id) and set(String id. Object value)  methods.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Moreover nested, indexed  and key based attributes are supported. All following expressions are valid and return the same value.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;model.get("customers.[21].address.city");&lt;br /&gt;model.get("customers.[21]").get("address.city")&lt;br /&gt;((List) model.get("customers")).get(21).get("address").get("city");&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Model holds an internal relations between its nodes. Possible intermediate nodes are submodels and lists. Leaf nodes could be of any object type.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It turns out that this simple data structure has many benefits especially in GWT applications.&lt;/div&gt;&lt;div&gt;There are two major restrictions relevant to this solution:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;the more serializable Java classes you have the bigger your final JavaScript is;&lt;/li&gt;&lt;li&gt;there is no reflective method access available by default in GWT code (and we definetly do not want all class metadata being stored in resulting JavaScript);&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;By introducing Dynamic Model concept you significantly reduce the number of classes, which are being send over the wire between client and server. There is no need to support two mirrored set of objects, one for persistence, second for GWT serialization. The performance part could be solved by splitting your application via &lt;a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.1/index.html?overview-summary.html"&gt;RunAsyncCallbacks&lt;/a&gt; since 2.0, but you still need to create dozens of dumb getters and setters.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;By using Dynamic Model you are able to reference attributes by String-based mappings, which is a replacement for reflection mechanism. Just to give a hint of why we need reflection analogue on the client is this piece of code.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;rule("myRule")&lt;br /&gt;.when(eq(LARGE_RISK, Boolean.TRUE))&lt;br /&gt;.then(make(APPROVER, MANDATORY))&lt;br /&gt;.otherwise(make(APPROVER, HIDDEN));&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;The example demonstrates an internal DSL, which gets executed in uniform manner both on client and server. &amp;nbsp;The trick is not to evaluate rules themselves, but rather pass a serialized &lt;a href="http://en.wikipedia.org/wiki/Abstract_syntax_tree"&gt;AST &lt;/a&gt;to the client. It is possible to validate data on the client to show visual effects and bypass server calls, then revalidate on server to fight against HTTP requests forgery. It can not be achieved without map based model as there is no way to reference a field both on client and server (unless you use reflection emulation library on GWT).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The same Dynamic Model serves as a basis for declarative data binding.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;bind(APPROVER, comboBox);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;There is a certain performance overhead this implementation because GWT does too many class type checks behind the scenes. This can be disabled since GWT 2.0 using a compiler feature, but is not recommended thing to do. However, applications based on described &amp;nbsp;approach are able to display hundreds of widgets bound to Dynamic Model in Internet Explorer with a reasonable performance.&lt;br /&gt;&lt;br /&gt;The resulting solution is almost one model fits all approach and provides significant benefits on large applications, where serious effort should be spent to create and maintain models for all the screens.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;To achieve proper transformation to application-side model &lt;a href="http://dozer.sourceforge.net/"&gt;Dozer &lt;/a&gt;Bean Mapper is used in our reference architecture. Next example gives a hint how declarative mappings look like in described case. It is possible to define set and get method names for custom data structure like Dynamic Model and then map nested attribute to GWT model with transformation to String.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;&amp;lt;mapping&amp;gt;&lt;br /&gt;  &amp;lt;class-a&amp;gt;com.sample.server.ServerModel&amp;lt;/class-a&amp;gt;&lt;br /&gt;  &amp;lt;class-b map-get-method="get" map-set-method="set"&amp;gt;com.sample.shared.ContractModel&amp;lt;/class-b&amp;gt;&lt;br /&gt;  &amp;lt;field&amp;gt;&lt;br /&gt;    &amp;lt;a&amp;gt;contract.startDate&amp;lt;/a&amp;gt;&lt;br /&gt;    &amp;lt;b map-get-method="get" map-set-method="set" key="startDate"&amp;gt;this&amp;lt;/b&amp;gt;&lt;br /&gt;    &amp;lt;b-hint&amp;gt;java.lang.String&amp;lt;/b-hint&amp;gt;&lt;br /&gt;  &amp;lt;/field&amp;gt;&lt;br /&gt;&amp;lt;/mapping&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;The approach described here actually works in large scale applications and is running on several productive systems. This is not a feature, which can be easily recreated during weekend, so I am thinking of extracting this as a separate Open Source project. Besides the model, in the original implementation, we have simple attribute query language, data binding and GWT portable rules concept.&lt;br /&gt;&lt;br /&gt;At the moment I am aware of the following client-server communication approaches in GWT:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Name convention based Bean -&amp;gt; BeanDTO parallel object hierarchies (automatically mapped by Dozer)&lt;/li&gt;&lt;li&gt;Sending persistent model stripped down by Gilead&lt;/li&gt;&lt;li&gt;Custom mapping from Domain Model to Screen Specific Model (some mapping tool or hand written)&lt;/li&gt;&lt;li&gt;Using Enhanced Classes Serializing GWT feature&lt;/li&gt;&lt;li&gt;Dynamic Model based approach described here&lt;/li&gt;&lt;li&gt;Anything else?&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=29163398&amp;amp;postID=5663510375551094710"&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=29163398&amp;amp;postID=5663510375551094710"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29163398-5663510375551094710?l=buzdin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://buzdin.blogspot.com/feeds/5663510375551094710/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29163398&amp;postID=5663510375551094710' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/5663510375551094710'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29163398/posts/default/5663510375551094710'/><link rel='alternate' type='text/html' href='http://buzdin.blogspot.com/2010/05/gwt-dynamic-model.html' title='GWT Dynamic Model'/><author><name>Dmitry Buzdin</name><uri>http://www.blogger.com/profile/14535724893723283597</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_wJqXOQNlTV4/TTmJvIpu36I/AAAAAAAAABQ/B32dD3nU1S4/s220/face.jpg'/></author><thr:total>0</thr:total></entry></feed>
