<?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-401162125201554678</id><updated>2011-12-27T17:44:01.930+01:00</updated><title type='text'>Enterprise Tricks</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://maciekmoczkowski.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://maciekmoczkowski.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Maciej Moczkowski</name><uri>http://www.blogger.com/profile/10277409687102251243</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://2.bp.blogspot.com/_m4QcVuqJNnE/SqC1Rb_uygI/AAAAAAAAABY/5-954Qu8YWg/S220/mm.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-401162125201554678.post-3687303357511792372</id><published>2011-12-25T11:21:00.027+01:00</published><updated>2011-12-27T17:44:01.940+01:00</updated><title type='text'>Some good books I have read recently...</title><content type='html'>&lt;a href="http://3.bp.blogspot.com/-n3kqcuDy0j4/TvnncDhTKlI/AAAAAAAAAUw/u96zMMluQq8/s1600/postgis.jpg"&gt;&lt;/a&gt;&lt;div&gt;I did not have much time for programming that year. Apart of my job, of course! I think number of my blog posts confirms that;) Anyway, I read a few programming books in the mean time... and would like to recommend two of them.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;b&gt;Seven Languages in Seven Weeks&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Is a "A Pragmatic Guide to Learning Programming Languages" by Bruce A. Tate (see: &lt;a href="http://pragprog.com/book/btlang/seven-languages-in-seven-weeks"&gt;http://pragprog.com/book/btlang/seven-languages-in-seven-weeks&lt;/a&gt;).&lt;/div&gt;&lt;div&gt;&lt;img src="http://4.bp.blogspot.com/-HvucuEwxyu0/TvnnIeHvJJI/AAAAAAAAAUk/GtAaHrYO2AA/s200/seven.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5690833736869815442" style="color: rgb(0, 0, 238); text-decoration: underline; float: left; margin-top: 0px; margin-right: 10px; margin-bottom: 0px; margin-left: 0px; cursor: pointer; width: 166px; height: 200px; " /&gt;&lt;br class="Apple-interchange-newline"&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's a journey through seven programming languages, showing how different they can be and to how different programming worlds they belong to.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The book presents:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Ruby - modern dynamic, object oriented language used a lot in web development&lt;/li&gt;&lt;li&gt;Io - prototype based language that has a lot in common with JavaScript&lt;/li&gt;&lt;li&gt;Prolog - logic programming language that is just different from anything other I have ever seen before&lt;/li&gt;&lt;li&gt;Scala - getting more and more popular object oriented and functional language for JVM&lt;/li&gt;&lt;li&gt;Erlang - functional language designed in Ericsson labs for running mission critical apps&lt;/li&gt;&lt;li&gt;Clojure - modern Lisp implementation for JVM&lt;/li&gt;&lt;li&gt;Haskell - functional language, but with totally different philosophy than Lisp&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;From my perspective each of presented languages from the list has some interesting points and each has been choosen for some reason. Author does not concentrate on teaching you details of the language and its syntax, but wants you to understand its philosophy. He wants you to learn how to learn things. He wants you not to limit your thinking by knowing only one potential solution to your problem.&lt;/div&gt;&lt;div&gt;  &lt;/div&gt;&lt;div&gt;Another point is that after almost seven (like the title hi) years of professional Java development, I was finding myself a little bit closed. But that book certanly opened my eyes. I believe discovering the variety of programming worlds makes me better programmer (and brings more fun!) than learing next 187'th Java framework...&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;Author puts it that way:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;"&lt;i&gt;Java was like having a rich lawyer as a brother. He was fun when he was younger, but now he's a black hole that sucks away all the joy in a 100-mile radius.&lt;/i&gt;"&lt;div&gt;&lt;div&gt;—Bruce A. Tate - Seven Languages in Seven Weeks&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;b&gt;PostGIS in Action&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;by Regina O. Obe and Leo S. Hsu is a guide to PostGIS - spatial extension for PostgreSQL database  (see: &lt;a href="http://www.manning.com/obe/"&gt;http://www.manning.com/obe/&lt;/a&gt;)&lt;/div&gt;&lt;div&gt;&lt;img src="http://3.bp.blogspot.com/-n3kqcuDy0j4/TvnncDhTKlI/AAAAAAAAAUw/u96zMMluQq8/s200/postgis.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5690834073326660178" style="color: rgb(0, 0, 238); text-decoration: underline; float: left; margin-top: 0px; margin-right: 10px; margin-bottom: 10px; margin-left: 0px; cursor: pointer; width: 150px; height: 187px; " /&gt;&lt;/div&gt;&lt;div&gt;It allows you not only to store spatial data as a maps, locations etc but to perform a lot of operations like searching, measuring distance, areas or making geometrical transformations.&lt;/div&gt;&lt;div&gt;I would say this is a must read for GIS developers like me. It is clear that it contains deep technical explanation of spatial data types or, database functions to operate in them.&lt;/div&gt;&lt;div&gt;What is much more important is contains all the GIS background you should (must!) be aware of before you start working with spatial data. It may be surprising for some, but you can not just treat spatial data as coordinates on Euclidean coordinate systems. Earth is not flat! Earth is not a ball neither.&lt;/div&gt;&lt;div&gt;To make you "GIS ready" programmer, authors guide you through things like spatial reference systems or map projections and make you understand the difference between them. They describe which one would be the best for each set of requirements, like for example calculating accurate distances or preserving shapes and angles  for visualization.&lt;/div&gt;&lt;div&gt;I should also mention useful information about performance tuning as well as a lot general SQL hints like "do it that way" or "never use" etc. There are also nice bonus chapters like PostreSQL administration guide or SQL tutorial to get you back on track.&lt;/div&gt;&lt;div&gt;Enjoy reading and Happy New Year!&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/401162125201554678-3687303357511792372?l=maciekmoczkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://maciekmoczkowski.blogspot.com/feeds/3687303357511792372/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://maciekmoczkowski.blogspot.com/2011/12/some-good-books-i-have-read-recently.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/3687303357511792372'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/3687303357511792372'/><link rel='alternate' type='text/html' href='http://maciekmoczkowski.blogspot.com/2011/12/some-good-books-i-have-read-recently.html' title='Some good books I have read recently...'/><author><name>Maciej Moczkowski</name><uri>http://www.blogger.com/profile/10277409687102251243</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://2.bp.blogspot.com/_m4QcVuqJNnE/SqC1Rb_uygI/AAAAAAAAABY/5-954Qu8YWg/S220/mm.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-HvucuEwxyu0/TvnnIeHvJJI/AAAAAAAAAUk/GtAaHrYO2AA/s72-c/seven.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-401162125201554678.post-2110203681235602152</id><published>2010-09-01T22:49:00.004+02:00</published><updated>2010-09-01T23:02:41.088+02:00</updated><title type='text'>Desktop GUI apps with Python</title><content type='html'>I have just made my first desktop GUI application with Python using build-in Tkinter library.&lt;br /&gt;&lt;br /&gt;With so simple code:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;from Tkinter import *&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;class PythonGuiApp:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    def __init__(self, root):&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        Label(root, text="Enter your name:").grid(row=0,column=0)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        self.textInput = Entry(root)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        self.textInput.grid(row=0,column=1)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        Button(root, text="Say hi", command=self.say_hi).grid(row=1,column=0)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        self.text = StringVar()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        Label(root, textvariable=self.text).grid(row=1,column=1)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    def say_hi(self):&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        self.text.set("Hello "+self.textInput.get()+"!")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;root = Tk()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;app = PythonGuiApp(root)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;root.mainloop()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;you can get:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_m4QcVuqJNnE/TH69cijD9-I/AAAAAAAAASs/onOdgM3vScU/s1600/pythonTK.PNG"&gt;&lt;img style="cursor: pointer; width: 219px; height: 67px;" src="http://2.bp.blogspot.com/_m4QcVuqJNnE/TH69cijD9-I/AAAAAAAAASs/onOdgM3vScU/s400/pythonTK.PNG" alt="" id="BLOGGER_PHOTO_ID_5512051291955918818" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Isn't it easy? Nice tutorial can be found at &lt;a href="http://www.pythonware.com/library/tkinter/introduction/index.htm"&gt;http://www.pythonware.com/library/tkinter/introduction/index.htm&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/401162125201554678-2110203681235602152?l=maciekmoczkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://maciekmoczkowski.blogspot.com/feeds/2110203681235602152/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://maciekmoczkowski.blogspot.com/2010/09/desktop-gui-apps-with-python.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/2110203681235602152'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/2110203681235602152'/><link rel='alternate' type='text/html' href='http://maciekmoczkowski.blogspot.com/2010/09/desktop-gui-apps-with-python.html' title='Desktop GUI apps with Python'/><author><name>Maciej Moczkowski</name><uri>http://www.blogger.com/profile/10277409687102251243</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://2.bp.blogspot.com/_m4QcVuqJNnE/SqC1Rb_uygI/AAAAAAAAABY/5-954Qu8YWg/S220/mm.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_m4QcVuqJNnE/TH69cijD9-I/AAAAAAAAASs/onOdgM3vScU/s72-c/pythonTK.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-401162125201554678.post-7144419976991726168</id><published>2010-08-01T20:16:00.020+02:00</published><updated>2010-08-01T21:57:23.142+02:00</updated><title type='text'>Python web development for Google App Engine</title><content type='html'>To start your very first Python web development for GAE, you will need:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Python 2.5 - later versions are not supported by GAE (&lt;a href="http://www.python.org/ftp/python/2.5/python-2.5.msi"&gt;http://www.python.org/ftp/python/2.5/python-2.5.msi&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Google App Engine SDK for Python (&lt;a href="http://code.google.com/intl/pl/appengine/downloads.html#Google_App_Engine_SDK_for_Python"&gt;http://code.google.com/intl/pl/appengine/downloads.html#Google_App_Engine_SDK_for_Python&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Eclipse (&lt;a href="http://www.eclipse.org/downloads/"&gt;http://www.eclipse.org/downloads/&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Pydev -  eclipse plugin for Python development (eclipse update site: &lt;a href="http://pydev.org/updates"&gt;http://pydev.org/updates&lt;/a&gt;)&lt;/li&gt;&lt;/ul&gt;To run any application you should have GAE account (&lt;a href="http://code.google.com/intl/pl/appengine/"&gt;http://code.google.com/intl/pl/appengine/&lt;/a&gt;). You should also create new application on GAE administration pages.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_m4QcVuqJNnE/TFW86P8zhVI/AAAAAAAAARI/VNoKlJ9RURs/s1600/python2.PNG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 293px;" src="http://3.bp.blogspot.com/_m4QcVuqJNnE/TFW86P8zhVI/AAAAAAAAARI/VNoKlJ9RURs/s400/python2.PNG" alt="" id="BLOGGER_PHOTO_ID_5500510228802930002" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Hello World project&lt;/span&gt;&lt;br /&gt;Now, you can try to generate Hello World application using the Pydev's wizard. Create new project in eclipse - use "&lt;span style="font-style: italic;"&gt;Pydev Google App Engine Project&lt;/span&gt;". Select Python version to 2.5 and configure interpreter to the one that you installed earlier. Next, you will have to specify path to Google App Engine SDK. On next page, set name for your application (the same as was registered on GAE account admin pages) and choose "&lt;span style="font-style: italic;"&gt;Hello Webapp World&lt;/span&gt;" template. Within few seconds you should have your Hello World web app generated.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_m4QcVuqJNnE/TFW9HEQot2I/AAAAAAAAARQ/qnifJyCarqM/s1600/python1.PNG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 201px;" src="http://4.bp.blogspot.com/_m4QcVuqJNnE/TFW9HEQot2I/AAAAAAAAARQ/qnifJyCarqM/s400/python1.PNG" alt="" id="BLOGGER_PHOTO_ID_5500510449003181922" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Run Google App Engine Launcher that was installed with SDK. If you are running it first time, configure paths to Python and SDK (Edit -&gt; Preferences). Add your project to the Launcher:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_m4QcVuqJNnE/TFW9NZhdLnI/AAAAAAAAARY/ofPGE8-TamI/s1600/python3.PNG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 285px;" src="http://2.bp.blogspot.com/_m4QcVuqJNnE/TFW9NZhdLnI/AAAAAAAAARY/ofPGE8-TamI/s400/python3.PNG" alt="" id="BLOGGER_PHOTO_ID_5500510557790088818" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now, you should be able to run your application locally as well as deploy it to GAE. During deployment you will need to log into your GAE account.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_m4QcVuqJNnE/TFW9U-2ufPI/AAAAAAAAARg/EZE9M9rZ9L8/s1600/python4.PNG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 156px;" src="http://1.bp.blogspot.com/_m4QcVuqJNnE/TFW9U-2ufPI/AAAAAAAAARg/EZE9M9rZ9L8/s400/python4.PNG" alt="" id="BLOGGER_PHOTO_ID_5500510688070499570" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;More complex application&lt;/span&gt;&lt;br /&gt;As usual, I created my test app as simple Book management application. It is not even CRUD as I had no time to develope update functionality. Application requires user to log in using Google Account before they enter the main page.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_m4QcVuqJNnE/TFW9rDc8IQI/AAAAAAAAARw/KrkQyHc54YU/s1600/python5.PNG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 202px;" src="http://4.bp.blogspot.com/_m4QcVuqJNnE/TFW9rDc8IQI/AAAAAAAAARw/KrkQyHc54YU/s400/python5.PNG" alt="" id="BLOGGER_PHOTO_ID_5500511067261640962" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There, user will have links to other pages:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Book list - when user will be able to display and remove books&lt;/li&gt;&lt;li&gt;New book - page with form for adding new entries&lt;br /&gt;&lt;/li&gt;&lt;li&gt;log out&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Project structure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_m4QcVuqJNnE/TFW9elAFf3I/AAAAAAAAARo/YPAILU4X3TA/s1600/python8.PNG"&gt;&lt;img style="cursor: pointer; width: 225px; height: 291px;" src="http://3.bp.blogspot.com/_m4QcVuqJNnE/TFW9elAFf3I/AAAAAAAAARo/YPAILU4X3TA/s400/python8.PNG" alt="" id="BLOGGER_PHOTO_ID_5500510852929126258" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Projects uses Google Webapp framework that is quite simple, but on the other hand you don't need anything more sophisticated for such simple app;)&lt;br /&gt;&lt;br /&gt;Main application code and logic is in &lt;span style="font-style: italic;"&gt;books.py&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;import os&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;from google.appengine.api import users&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;from google.appengine.ext import webapp&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;from google.appengine.ext.webapp import template&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;from models import Book&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;from google.appengine.ext.webapp.util import run_wsgi_app&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;class &lt;span style="color: rgb(51, 51, 255);"&gt;MainPage&lt;/span&gt;(webapp.RequestHandler):&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    def get(self):&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        user = users.get_current_user()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        if user:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            template_values = {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;               'user' : user.nickname(),  &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;               'logoutUrl' : users.create_login_url("/")              &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            path = os.path.join(os.path.dirname(__file__)+"/templates", '&lt;span style="color: rgb(51, 51, 255);"&gt;index.html&lt;/span&gt;')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            self.response.out.write(template.render(path, template_values))&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        else:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            self.redirect(users.create_login_url(self.request.uri))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;class &lt;span style="color: rgb(51, 51, 255);"&gt;NewBookPage&lt;/span&gt;(webapp.RequestHandler):&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    def get(self):&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        path = os.path.join(os.path.dirname(__file__)+"/templates", '&lt;span style="color: rgb(51, 51, 255);"&gt;new.html&lt;/span&gt;')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        self.response.out.write(template.render(path, {}))&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;class &lt;span style="color: rgb(51, 51, 255);"&gt;ListBooksPage&lt;/span&gt;(webapp.RequestHandler):&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    def get(self):&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        books = Book.all();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        template_values = {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            'books' : books,                &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        path = os.path.join(os.path.dirname(__file__)+"/templates", '&lt;span style="color: rgb(51, 51, 255);"&gt;list.html&lt;/span&gt;')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        self.response.out.write(template.render(path, template_values))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;class &lt;span style="color: rgb(51, 51, 255);"&gt;SaveBookPage&lt;/span&gt;(webapp.RequestHandler):&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    def post(self):&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        book = Book();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        book.title = self.request.get('title')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        book.author = self.request.get('author')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        book.put()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        self.redirect("/list")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;class &lt;span style="color: rgb(51, 51, 255);"&gt;RemoveBookPage&lt;/span&gt;(webapp.RequestHandler):&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    def get(self):&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        book = Book.get(self.request.get('key'))&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        book.delete()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        self.redirect("/list")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;application = webapp.WSGIApplication(&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                                     [('&lt;span style="color: rgb(51, 51, 255);"&gt;/&lt;/span&gt;', &lt;span style="color: rgb(51, 51, 255);"&gt;MainPage&lt;/span&gt;),&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                                      ('&lt;span style="color: rgb(51, 51, 255);"&gt;/list&lt;/span&gt;', &lt;span style="color: rgb(51, 51, 255);"&gt;ListBooksPage&lt;/span&gt;),&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                                      ('&lt;span style="color: rgb(51, 51, 255);"&gt;/save&lt;/span&gt;', &lt;span style="color: rgb(51, 51, 255);"&gt;SaveBookPage&lt;/span&gt;),&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                                      ('&lt;span style="color: rgb(51, 51, 255);"&gt;/remove&lt;/span&gt;', &lt;span style="color: rgb(51, 51, 255);"&gt;RemoveBookPage&lt;/span&gt;),&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                                      ('&lt;span style="color: rgb(51, 51, 255);"&gt;/new&lt;/span&gt;', &lt;span style="color: rgb(51, 51, 255);"&gt;NewBookPage&lt;/span&gt;)],&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                                     debug=True)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;def main():&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    run_wsgi_app(application)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;if __name__ == "__main__":&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    main()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;In this module we have main "controller" classes that cover all functionality. Classes are mapped to particular URL. Responsibility of each class is to perform business logic, prepare model and return template that will render the page:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;MainPage &lt;/span&gt;- prepares model for menu, returns &lt;span style="font-style: italic;"&gt;index.html&lt;/span&gt; template&lt;/li&gt;&lt;li&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;NewBookPage &lt;/span&gt;- returns &lt;span style="font-style: italic;"&gt;new.html&lt;/span&gt; template with form&lt;/li&gt;&lt;li&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;ListBooksPage &lt;/span&gt;- selects books from Google Datastore, puts them into model and returns &lt;span style="font-style: italic;"&gt;list.html&lt;/span&gt; template&lt;/li&gt;&lt;li&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;SaveBookPage&lt;/span&gt;- saves book to datastore and redirects view to book list&lt;/li&gt;&lt;li&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;RemoveBookPage &lt;/span&gt;- removes book from datastore and redirects view to book list&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;This module contains also code that maps each controller class to particular URL.&lt;br /&gt;&lt;br /&gt;Pages are implemented using Django templated mechanism that is included in SDK. We have a main template &lt;span style="font-style: italic;"&gt;base.html&lt;/span&gt; that renders html page structure:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;head&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;link type="text/css" rel="stylesheet" href="/style/&lt;span style="color: rgb(51, 51, 255);"&gt;main.css&lt;/span&gt;" /&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;/head&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;body&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    {% block main %}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    {% endblock %}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;/body&amp;gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/html&amp;gt;    &lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;All other templates are extending the main one.&lt;br /&gt;&lt;br /&gt;Code of &lt;span style="font-style: italic;"&gt;index.html&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;{% extends "&lt;span style="color: rgb(51, 51, 255);"&gt;base.html&lt;/span&gt;" %}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;{% block main %}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Welcome {{ user }}!&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Menu:&amp;lt;br/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;a href="/list"&amp;gt;Book list&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;a href="/new"&amp;gt;New book&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;a href="{{ logoutUrl }}"&amp;gt;Logout&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;{% endblock %}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-style: italic;"&gt;list.html&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;{% extends "&lt;span style="color: rgb(51, 51, 255);"&gt;base.html&lt;/span&gt;" %}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;{% block main %}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;th&amp;gt;Title&amp;lt;/th&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;th&amp;gt;Author&amp;lt;/th&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;th&amp;gt;&amp;lt;/th&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;/tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    {% for book in books %}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;td&amp;gt;{{ book.title }}&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;td&amp;gt;{{ book.author }}&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;td&amp;gt;&amp;lt;a href="/remove?key={{ book.key }}"&amp;gt;remove&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;/tr&amp;gt;            &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        {% endfor %}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;br/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;a href="/"&amp;gt;Back&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;{% endblock %}&lt;/span&gt; &lt;/pre&gt;&lt;span style="font-style: italic;"&gt;new.html&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;{% extends "&lt;span style="color: rgb(51, 51, 255);"&gt;base.html&lt;/span&gt;" %}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;{% block main %}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;form action="/save" method="POST"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;table&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;td&amp;gt;Title:&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;td&amp;gt;&amp;lt;input type="text" name="title"/&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;/tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;td&amp;gt;Author:&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;td&amp;gt;&amp;lt;input type="text" name="author"/&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;/tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;td&amp;gt;&amp;lt;input type="submit" value="Add"&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;/tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;/table&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;br/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;a href="/"&amp;gt;Back&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;{% endblock %}&lt;/span&gt; &lt;/pre&gt;I used separete &lt;span style="font-style: italic;"&gt;main.css&lt;/span&gt; file to define look (don't take it seriously hi hi) of the application:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;body {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  font-family: Verdana, Helvetica, sans-serif;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  background-color: #DDDDDD;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;In &lt;span style="font-style: italic;"&gt;app.yaml&lt;/span&gt; file, we define that books.py module is responsible for handling all request to &lt;span style="font-style: italic;"&gt;/*&lt;/span&gt; urls and that &lt;span style="font-style: italic;"&gt;/style&lt;/span&gt; urls will be exposed as a static resource:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;application: python-test-maciekm&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;version: 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;runtime: python&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;api_version: 1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;handlers:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;- url: /style&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  static_dir: style&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;- url: /.*&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  script: &lt;span style="color: rgb(51, 51, 255);"&gt;books.py&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Data model is defined in &lt;span style="font-style: italic;"&gt;models.py&lt;/span&gt; file:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;from google.appengine.ext import db&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;class &lt;span style="color: rgb(51, 51, 255);"&gt;Book&lt;/span&gt;(db.Model):&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    title = db.StringProperty()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    author = db.StringProperty()&lt;/span&gt; &lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Let's see the result&lt;/span&gt;&lt;br /&gt;Such application should be ready to get it started using Launcher and for deployment on GAE. When it starts, you should be able to see application pages in the browser - creating new book:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_m4QcVuqJNnE/TFW9ykF1UCI/AAAAAAAAAR4/ZN9tlbOgqMc/s1600/python6.PNG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 211px;" src="http://3.bp.blogspot.com/_m4QcVuqJNnE/TFW9ykF1UCI/AAAAAAAAAR4/ZN9tlbOgqMc/s400/python6.PNG" alt="" id="BLOGGER_PHOTO_ID_5500511196282179618" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And the list:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_m4QcVuqJNnE/TFW-AvxxbmI/AAAAAAAAASA/PSbwUfapGWQ/s1600/python7.PNG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 204px;" src="http://3.bp.blogspot.com/_m4QcVuqJNnE/TFW-AvxxbmI/AAAAAAAAASA/PSbwUfapGWQ/s400/python7.PNG" alt="" id="BLOGGER_PHOTO_ID_5500511439937433186" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Was it hard? To be honest I really think it was not. Personally, I think it was even easier for me to create GAE application in Python than in Java. In the future, I would be happy to try to use Django instead of Webapp framework and to compare them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/401162125201554678-7144419976991726168?l=maciekmoczkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://maciekmoczkowski.blogspot.com/feeds/7144419976991726168/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://maciekmoczkowski.blogspot.com/2010/08/python-web-development-for-google-app.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/7144419976991726168'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/7144419976991726168'/><link rel='alternate' type='text/html' href='http://maciekmoczkowski.blogspot.com/2010/08/python-web-development-for-google-app.html' title='Python web development for Google App Engine'/><author><name>Maciej Moczkowski</name><uri>http://www.blogger.com/profile/10277409687102251243</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://2.bp.blogspot.com/_m4QcVuqJNnE/SqC1Rb_uygI/AAAAAAAAABY/5-954Qu8YWg/S220/mm.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_m4QcVuqJNnE/TFW86P8zhVI/AAAAAAAAARI/VNoKlJ9RURs/s72-c/python2.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-401162125201554678.post-8376863849478552159</id><published>2010-07-12T21:28:00.002+02:00</published><updated>2010-07-12T21:50:41.652+02:00</updated><title type='text'>Let's go Python!</title><content type='html'>It may be surprising but after few years of Java development I started to fell the need of discovering something totally different. After few chats with my job collegues I realized that sticking to one technology is not good and it is sometimes better to look at other solutions to have a better overview and to be able to look at development problems from different perspective. At first, I wanted to try C#/.NET, but I heard oppinions that it is quite similar to Java. Finally, one of my collegues told me: "why don't you give Python a try? For sure it is very different." Well, why not...&lt;br /&gt;&lt;br /&gt;So, for now I managed to:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;learn some Python basics&lt;/li&gt;&lt;li&gt;download Python - &lt;a href="http://www.python.org/"&gt;http://www.python.org/&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;install PyScripter IDE - &lt;a href="http://code.google.com/p/pyscripter/"&gt;http://code.google.com/p/pyscripter/&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;write "Hello World" application;)&lt;/li&gt;&lt;/ul&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_m4QcVuqJNnE/TDtx46QE7GI/AAAAAAAAAQo/zNpH0eMCI6Y/s1600/python.PNG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 250px;" src="http://1.bp.blogspot.com/_m4QcVuqJNnE/TDtx46QE7GI/AAAAAAAAAQo/zNpH0eMCI6Y/s400/python.PNG" alt="" id="BLOGGER_PHOTO_ID_5493109393031752802" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I know it is not too impressive, but my time is very limited recently.&lt;br /&gt;&lt;br /&gt;Plans for future:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;write some more Python code&lt;/li&gt;&lt;li&gt;try Django&lt;/li&gt;&lt;li&gt;deployment on Google Application Engine&lt;/li&gt;&lt;/ul&gt;I don't know how much time it takes me, but I will report my progress and publish some example code here. Wish me luck!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/401162125201554678-8376863849478552159?l=maciekmoczkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://maciekmoczkowski.blogspot.com/feeds/8376863849478552159/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://maciekmoczkowski.blogspot.com/2010/07/lets-go-python.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/8376863849478552159'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/8376863849478552159'/><link rel='alternate' type='text/html' href='http://maciekmoczkowski.blogspot.com/2010/07/lets-go-python.html' title='Let&apos;s go Python!'/><author><name>Maciej Moczkowski</name><uri>http://www.blogger.com/profile/10277409687102251243</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://2.bp.blogspot.com/_m4QcVuqJNnE/SqC1Rb_uygI/AAAAAAAAABY/5-954Qu8YWg/S220/mm.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_m4QcVuqJNnE/TDtx46QE7GI/AAAAAAAAAQo/zNpH0eMCI6Y/s72-c/python.PNG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-401162125201554678.post-4051335121519725171</id><published>2010-05-15T18:04:00.019+02:00</published><updated>2010-05-26T23:20:25.824+02:00</updated><title type='text'>BPEL compensation handlers with Glassfish ESB example</title><content type='html'>&lt;span style="font-weight: bold;font-size:100%;" &gt;Introduction&lt;/span&gt;&lt;br /&gt;Recently I am involved in integration project based on Glassfish ESB and I needed to get into BPEL technology. There was one thing that really impressed me -  compensation handlers.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;Why do we need compensation handlers?&lt;/span&gt;&lt;br /&gt;Imagine a simple book ordering process defined in BPEL and exposed as a webservice.&lt;br /&gt;Process flow would be:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;receive needed information: bookId, customerId, creditCardNumber&lt;/li&gt;&lt;li&gt;call BookOrderWS  - webservice responsible for creating order&lt;/li&gt;&lt;li&gt;call PaymentWS - webservice responsible for payment&lt;/li&gt;&lt;li&gt;return result of the process&lt;/li&gt;&lt;/ul&gt;Execution of this process looks very simple until we consider that something may go wrong. Unpredicted exception may occur in the middle of the process. For example payment component may not be working and we will get exception while calling it. Without any fault handling our BPEL process will just stop after customer invoking it via WS will receive fault information. The worst thing is that earlier part of the process was executed properly -  order was created by BookOrderWS. So, the book will be posted to customer even though he was not charged for it;)&lt;br /&gt;&lt;br /&gt;Possible solutions:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;use catch clause to react on errors on each webservice call&lt;/li&gt;&lt;li&gt;use componsation handlers - for each webservice call define a set of actions that will undo its execution&lt;/li&gt;&lt;/ul&gt;In first solution we could catch exception while calling PaymentWS  and call another webservice that would cancel the order that was created. It would work in our case, but imagine a process that orchestrates ten or more webservice calls - code would be very complicated.&lt;br /&gt;&lt;br /&gt;That's why I prefer second solution. No matter in which process step error occurs - all previous steps will know how to undo its operation. Process definition will be much clearer.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Implementation&lt;/span&gt;&lt;br /&gt;Now I will show a draft of simple  implementation that I prepared to test this concept. During development I  was using Glassfish ESB 2.2 and bundled Netbeans IDE 6.7.1.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;My application consists of following  projects:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;BookOrderWS&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;PaymentWS&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;BookOrderBPEL&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;BookOrderCA&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;Webservices&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;BookOrderWS is responsible for creating and canceling orders. It is implemented as EJB module and consists of one class:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;package com.maciekm;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.jws.Oneway;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.jws.WebMethod;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.jws.WebParam;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.jws.WebService;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.ejb.Stateless;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;@WebService()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;@Stateless()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;public class BookOrderWS {&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    @WebMethod(operationName = "orderBook")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    public long orderBook(@WebParam(name = "bookId") long bookId,&lt;br /&gt;@WebParam(name = "customerId") long customerId) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        long orderId = System.currentTimeMillis();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        System.out.println("Order request for bookId: " + bookId + " from customerId: " + customerId + " - created orderId: " + orderId);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        return orderId;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    @WebMethod(operationName = "cancelOrder")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    @Oneway&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    public void cancelOrder(@WebParam(name = "orderId") long orderId) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        System.out.println("Canceling orderId: "+orderId);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;PaymentWS&lt;/span&gt; is also EJB module with very simple code:&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;package com.maciekm;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.jws.WebMethod;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.jws.WebParam;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.jws.WebService;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.ejb.Stateless;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.jws.Oneway;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;@WebService()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;@Stateless()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;public class PaymentWS {&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    @WebMethod(operationName = "payForOrder")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    @Oneway&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    public void payForOrder(@WebParam(name = "orderId") long orderId,&lt;br /&gt;@WebParam(name = "creditCardNumber") String creditCardNumber) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        System.out.println("Payment received for orderId: " + orderId + ", creditNumber:" + creditCardNumber);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;        if (creditCardNumber.equals("1234")) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;            System.out.println("Payment error!");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;            throw new RuntimeException("some unexpected errors");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        System.out.println("Payment completed!");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;Here our mock implementation simulates payment processing. Unpredicted exception will occur for 1234 credit card number.&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;Process definition and composite application&lt;/span&gt;&lt;br /&gt;WSDL of our process is based on very simple input and output schemas:&lt;br /&gt;&lt;code&gt;&lt;/code&gt;&lt;span style="font-size:100%;"&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    targetNamespace="http://xml.netbeans.org/schema/order"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    xmlns:tns="http://xml.netbeans.org/schema/order"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    elementFormDefault="qualified"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;xsd:element name="order" type="tns:order"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;xsd:complexType name="order"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;xsd:sequence&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;xsd:element name="bookId" type="xsd:integer"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;xsd:element name="customerId" type="xsd:integer"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;xsd:element name="creditCardNumber" type="xsd:string"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;/xsd:sequence&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;/xsd:complexType&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/xsd:schema&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    targetNamespace="http://xml.netbeans.org/schema/orderResult"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    xmlns:tns="http://xml.netbeans.org/schema/orderResult"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    elementFormDefault="qualified"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;xsd:element name="orderResult" type="tns:orderResult"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;xsd:complexType name="orderResult"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;xsd:sequence&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;xsd:element name="isCompleted" type="xsd:boolean"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;/xsd:sequence&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;/xsd:complexType&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/xsd:schema&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;Process diagram:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_m4QcVuqJNnE/S_L6TE4SE4I/AAAAAAAAAQY/UP8wdgi8vjw/s1600/bpel.PNG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 331px;" src="http://3.bp.blogspot.com/_m4QcVuqJNnE/S_L6TE4SE4I/AAAAAAAAAQY/UP8wdgi8vjw/s400/bpel.PNG" alt="" id="BLOGGER_PHOTO_ID_5472711702842839938" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Code:&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;process&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    name="bookOrderBPEL"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    targetNamespace="http://enterprise.netbeans.org/bpel/BookOrderBPEL/bookOrderBPEL"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    xmlns:tns="http://enterprise.netbeans.org/bpel/BookOrderBPEL/bookOrderBPEL"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    xmlns:xs="http://www.w3.org/2001/XMLSchema"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    xmlns:xsd="http://www.w3.org/2001/XMLSchema"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    xmlns="http://docs.oasis-open.org/wsbpel/2.0/process/executable"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    xmlns:sxt="http://www.sun.com/wsbpel/2.0/process/executable/SUNExtension/Trace" &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    xmlns:sxed="http://www.sun.com/wsbpel/2.0/process/executable/SUNExtension/Editor"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    xmlns:sxeh="http://www.sun.com/wsbpel/2.0/process/executable/SUNExtension/ErrorHandling" xmlns:sxed2="http://www.sun.com/wsbpel/2.0/process/executable/SUNExtension/Editor2" xmlns:ns0="http://xml.netbeans.org/schema/order" xmlns:ns1="http://xml.netbeans.org/schema/orderResult"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;import namespace="http://enterprise.netbeans.org/bpel/BookOrderWSServiceWrapper"&lt;br /&gt;location="BookOrderWSServiceWrapper.wsdl" importType="http://schemas.xmlsoap.org/wsdl/"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;import namespace="http://maciekm.com/" location="BookOrderWS/wsdl/BookOrderWSService.wsdl"&lt;br /&gt;importType="http://schemas.xmlsoap.org/wsdl/"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;import namespace="http://enterprise.netbeans.org/bpel/PaymentWSServiceWrapper" location="PaymentWSServiceWrapper.wsdl"&lt;br /&gt;importType="http://schemas.xmlsoap.org/wsdl/"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;import namespace="http://maciekm.com/" location="PaymentWS/wsdl/PaymentWSService.wsdl"&lt;br /&gt;importType="http://schemas.xmlsoap.org/wsdl/"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;import namespace="http://j2ee.netbeans.org/wsdl/BookOrderBPEL/bookOrderProcessWSDL"&lt;br /&gt;location="bookOrderProcessWSDL.wsdl" importType="http://schemas.xmlsoap.org/wsdl/"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;partnerLinks&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;partnerLink name="OrderProcessPL" xmlns:tns="http://j2ee.netbeans.org/wsdl/BookOrderBPEL/bookOrderProcessWSDL"&lt;br /&gt;partnerLinkType="tns:bookOrderProcessWSDL" myRole="bookOrderProcessWSDLPortTypeRole"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;partnerLink name="BookOrderPL" xmlns:tns="http://enterprise.netbeans.org/bpel/BookOrderWSServiceWrapper"&lt;br /&gt;partnerLinkType="tns:BookOrderWSLinkType" partnerRole="BookOrderWSRole"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;partnerLink name="PaymentPL" xmlns:tns="http://enterprise.netbeans.org/bpel/PaymentWSServiceWrapper"&lt;br /&gt;partnerLinkType="tns:PaymentWSLinkType" partnerRole="PaymentWSRole"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;/partnerLinks&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;variables&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;variable name="CancelOrderIn" xmlns:tns="http://maciekm.com/" messageType="tns:cancelOrder"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;variable name="OrderBookOut" xmlns:tns="http://maciekm.com/" messageType="tns:orderBookResponse"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;variable name="PayForOrderIn" xmlns:tns="http://maciekm.com/" messageType="tns:payForOrder"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;variable name="OrderBookIn" xmlns:tns="http://maciekm.com/" messageType="tns:orderBook"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;variable name="BookOrderProcessWSDLOperationOut"&lt;br /&gt;xmlns:tns="http://j2ee.netbeans.org/wsdl/BookOrderBPEL/bookOrderProcessWSDL"&lt;br /&gt;messageType="tns:bookOrderProcessWSDLOperationResponse"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;variable name="BookOrderProcessWSDLOperationIn"&lt;br /&gt;xmlns:tns="http://j2ee.netbeans.org/wsdl/BookOrderBPEL/bookOrderProcessWSDL"&lt;br /&gt;messageType="tns:bookOrderProcessWSDLOperationRequest"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;/variables&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;sequence&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;receive name="ReceiveOrder" createInstance="yes" partnerLink="OrderProcessPL"&lt;br /&gt;operation="bookOrderProcessWSDLOperation"&lt;br /&gt;xmlns:tns="http://j2ee.netbeans.org/wsdl/BookOrderBPEL/bookOrderProcessWSDL"&lt;br /&gt;portType="tns:bookOrderProcessWSDLPortType" variable="BookOrderProcessWSDLOperationIn"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;scope name="BookOrderScope"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;           &amp;lt;compensationHandler&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;                &amp;lt;sequence name="Sequence2s"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;                    &amp;lt;assign name="Assign1"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;                        &amp;lt;copy&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;                            &amp;lt;from&amp;gt;$OrderBookOut.parameters/return&amp;lt;/from&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;                            &amp;lt;to&amp;gt;$CancelOrderIn.parameters/orderId&amp;lt;/to&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;                        &amp;lt;/copy&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;                    &amp;lt;/assign&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;                    &amp;lt;invoke name="CancelOrder" partnerLink="BookOrderPL" operation="cancelOrder"&lt;br /&gt;portType="tns:BookOrderWS" inputVariable="CancelOrderIn" xmlns:tns="http://maciekm.com/"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;                &amp;lt;/sequence&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;            &amp;lt;/compensationHandler&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;sequence name="Sequence1"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                &amp;lt;assign name="AssignToOrder"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                    &amp;lt;copy&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                        &amp;lt;from&amp;gt;$BookOrderProcessWSDLOperationIn.part1/ns0:bookId&amp;lt;/from&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                        &amp;lt;to&amp;gt;$OrderBookIn.parameters/bookId&amp;lt;/to&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                    &amp;lt;/copy&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                    &amp;lt;copy&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                        &amp;lt;from&amp;gt;$BookOrderProcessWSDLOperationIn.part1/ns0:customerId&amp;lt;/from&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                        &amp;lt;to&amp;gt;$OrderBookIn.parameters/customerId&amp;lt;/to&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                    &amp;lt;/copy&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                &amp;lt;/assign&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                &amp;lt;invoke name="OrderBook" partnerLink="BookOrderPL" operation="orderBook"&lt;br /&gt;xmlns:tns="http://maciekm.com/" portType="tns:BookOrderWS" inputVariable="OrderBookIn" outputVariable="OrderBookOut"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;/sequence&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;/scope&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;assign name="AssignToPay"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;copy&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                &amp;lt;from&amp;gt;$BookOrderProcessWSDLOperationIn.part1/ns0:creditCardNumber&amp;lt;/from&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                &amp;lt;to&amp;gt;$PayForOrderIn.parameters/creditCardNumber&amp;lt;/to&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;/copy&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;copy&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                &amp;lt;from&amp;gt;$OrderBookOut.parameters/return&amp;lt;/from&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                &amp;lt;to&amp;gt;$PayForOrderIn.parameters/orderId&amp;lt;/to&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;/copy&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;/assign&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;invoke name="Pay" partnerLink="PaymentPL" operation="payForOrder" xmlns:tns="http://maciekm.com/"&lt;br /&gt;portType="tns:PaymentWS" inputVariable="PayForOrderIn"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;assign name="AssignToReply"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;copy&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                &amp;lt;from&amp;gt;true()&amp;lt;/from&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                &amp;lt;to&amp;gt;$BookOrderProcessWSDLOperationOut.part1/ns1:isCompleted&amp;lt;/to&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;/copy&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;/assign&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;reply name="Reply" partnerLink="OrderProcessPL" operation="bookOrderProcessWSDLOperation"&lt;br /&gt;xmlns:tns="http://j2ee.netbeans.org/wsdl/BookOrderBPEL/bookOrderProcessWSDL" portType="tns:bookOrderProcessWSDLPortType"&lt;br /&gt;variable="BookOrderProcessWSDLOperationOut"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;/sequence&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/process&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;As you can see BookOrderScope defines its compensation handler. It calls cancelOrder method of &lt;span style="font-size:100%;"&gt;BookOrderWS.&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;Composite application that connects all modules together:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_m4QcVuqJNnE/S_L6aB-6uGI/AAAAAAAAAQg/PASS1zQH4mA/s1600/ca.PNG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 297px;" src="http://3.bp.blogspot.com/_m4QcVuqJNnE/S_L6aB-6uGI/AAAAAAAAAQg/PASS1zQH4mA/s400/ca.PNG" alt="" id="BLOGGER_PHOTO_ID_5472711822324447330" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;Testing how it works&lt;/span&gt;&lt;br /&gt;Composite application has a testing support in Netbeans IDE. We can use it to create test cases.&lt;br /&gt;Test case one - sending valid order and payment information - processing works properly:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;Order request for bookId: 1 from customerId: 2 - created orderId: 1274383922765&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Retrieving schema at '', relative to 'file:/PaymentWSService.wsdl'.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Payment received for orderId: 1274383922765, creditNumber:1111&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Payment completed!&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Test case two - sending valid order, but credit card number that simulates error - order created by first WS is cancelled by compensation handler:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;Order request for bookId: 1 from customerId: 2 - created orderId: 1274383962281&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Payment received for orderId: 1274383962281, creditNumber:1234&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-style: italic;"&gt;Payment error!&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;The log message is null.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;javax.ejb.EJBException&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        at com.sun.ejb.containers.BaseContainer.processSystemException(BaseContainer.java:3903)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:3803)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:3605)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;........................................................................................................................&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-style: italic;"&gt;Canceling orderId: 1274383962281&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;It works indeed:)&lt;br /&gt;&lt;br /&gt;PS. Whole application was just quick test, so forgive me messy code and totally naive business scenario;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/401162125201554678-4051335121519725171?l=maciekmoczkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://maciekmoczkowski.blogspot.com/feeds/4051335121519725171/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://maciekmoczkowski.blogspot.com/2010/05/bpel-compensation-handlers-with.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/4051335121519725171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/4051335121519725171'/><link rel='alternate' type='text/html' href='http://maciekmoczkowski.blogspot.com/2010/05/bpel-compensation-handlers-with.html' title='BPEL compensation handlers with Glassfish ESB example'/><author><name>Maciej Moczkowski</name><uri>http://www.blogger.com/profile/10277409687102251243</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://2.bp.blogspot.com/_m4QcVuqJNnE/SqC1Rb_uygI/AAAAAAAAABY/5-954Qu8YWg/S220/mm.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_m4QcVuqJNnE/S_L6TE4SE4I/AAAAAAAAAQY/UP8wdgi8vjw/s72-c/bpel.PNG' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-401162125201554678.post-7726091464916561767</id><published>2010-02-11T21:52:00.010+01:00</published><updated>2010-02-12T22:40:19.866+01:00</updated><title type='text'>In-Out to In-Only MEP transformation in ServiceMix ESB's bean component</title><content type='html'>Recently I needed to write &lt;a href="http://servicemix.apache.org/servicemix-bean.html"&gt;servicemix-bean&lt;/a&gt; component that implements following scenario:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;receives In-Out MEP request&lt;/li&gt;&lt;li&gt;sends response to received In-Out request&lt;/li&gt;&lt;li&gt;constructs In-Only MEP request and forwards it to another service&lt;/li&gt;&lt;/ul&gt;I had some problems to get it working and could not find help in the internet. So, when I finally solved that problem I decided to share my solution.&lt;br /&gt;&lt;br /&gt;My component:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;package org.maciekm;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import java.io.StringReader;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import java.util.Date;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.annotation.Resource;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.jbi.component.ComponentContext;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.jbi.messaging.DeliveryChannel;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.jbi.messaging.ExchangeStatus;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.jbi.messaging.InOnly;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.jbi.messaging.MessageExchange;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.jbi.messaging.MessageExchangeFactory;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.jbi.messaging.MessagingException;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.jbi.messaging.NormalizedMessage;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.xml.namespace.QName;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.xml.transform.Source;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.xml.transform.TransformerException;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.xml.transform.stream.StreamSource;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import org.apache.servicemix.MessageExchangeListener;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import org.apache.servicemix.client.ServiceMixClient;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import org.apache.servicemix.client.ServiceMixClientFacade;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import org.apache.servicemix.jbi.jaxp.SourceTransformer;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;public class MyService implements MessageExchangeListener {&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    @Resource&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    private DeliveryChannel channel;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    @Resource&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    private ComponentContext context;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    private String &lt;span style="color: rgb(51, 51, 255);"&gt;targetServiceNS&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    private String &lt;span style="color: rgb(51, 51, 255);"&gt;targetServiceName&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    public String getTargetServiceNS() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        return targetServiceNS;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    public void setTargetServiceNS(String targetServiceNS) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        this.targetServiceNS = targetServiceNS;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    public String getTargetServiceName() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        return targetServiceName;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    public void setTargetServiceName(String targetServiceName) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        this.targetServiceName = targetServiceName;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    public void onMessageExchange(MessageExchange exchange) throws MessagingException {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        if (exchange.getStatus() == ExchangeStatus.ACTIVE) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            try {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                NormalizedMessage message = exchange.getMessage("in");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                Source content = message.getContent();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                // getting "in" message of In-Out request&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                String body = (new SourceTransformer()).toString(content);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                //&lt;/span&gt; some your custom logic&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                // sending response to initial In-Out request - place some xml there&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                String out=".......... some xml ..............";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                StreamSource respSource = new StreamSource(new StringReader(out));&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                message.setContent(respSource);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                &lt;span style="color: rgb(51, 51, 255);"&gt;exchange.setMessage(message, "out");&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;                channel.send(exchange);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                // some business logic to prepare message to forward based on original request&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                // sending In-Only message to service defined by targetServiceNS and &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                // targetServiceName properties&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                String forwardOut=".......... some xml ..............";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                StreamSource forwardSource = new StreamSource(new StringReader(forwardOut));&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                &lt;span style="color: rgb(51, 51, 255);"&gt;MessageExchangeFactory mef =&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;                    channel.createExchangeFactoryForService(new QName(targetServiceNS, targetServiceName));&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;                InOnly inOnlyExch = mef.createInOnlyExchange();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;                NormalizedMessage forwardMessage = inOnlyExch.createMessage();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;                forwardMessage.setContent(forwardSource);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;                inOnlyExch.setInMessage(forwardMessage);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;                ServiceMixClient smc = new ServiceMixClientFacade(context);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;                smc.send(inOnlyExch);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            } catch (TransformerException te) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                // please do it better way in real project ;)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                throw new MessagingException(te);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Declaration in xbean.xml file:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;bean id="myService" class="org.maciekm.MyService"&amp;gt;&lt;br /&gt;   &amp;lt;property name="&lt;span style="color: rgb(51, 51, 255);"&gt;targetServiceNS&lt;/span&gt;" value="http://maciekm.org/esb" /&amp;gt;&lt;br /&gt;   &amp;lt;property name="&lt;span style="color: rgb(51, 51, 255);"&gt;targetServiceName&lt;/span&gt;" value="targetService" /&amp;gt;&lt;br /&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Injected properties are defining target service of In-Only message. Hope it helps some of you:)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/401162125201554678-7726091464916561767?l=maciekmoczkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://maciekmoczkowski.blogspot.com/feeds/7726091464916561767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://maciekmoczkowski.blogspot.com/2010/02/in-out-to-in-only-mep-transformation-in.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/7726091464916561767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/7726091464916561767'/><link rel='alternate' type='text/html' href='http://maciekmoczkowski.blogspot.com/2010/02/in-out-to-in-only-mep-transformation-in.html' title='In-Out to In-Only MEP transformation in ServiceMix ESB&apos;s bean component'/><author><name>Maciej Moczkowski</name><uri>http://www.blogger.com/profile/10277409687102251243</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://2.bp.blogspot.com/_m4QcVuqJNnE/SqC1Rb_uygI/AAAAAAAAABY/5-954Qu8YWg/S220/mm.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-401162125201554678.post-7937578940687118221</id><published>2010-01-30T14:11:00.020+01:00</published><updated>2010-01-30T18:49:26.247+01:00</updated><title type='text'>(Almost) RESTful application with Grails and Dojo</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Introduction&lt;/span&gt;&lt;br /&gt;As REST techniques are getting more and more popular I wanted to give it a try. Of course I wanted to use Grails. For client side I have chosen Dojo javascript framework as I already had  some experience with it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Project setup&lt;/span&gt;&lt;br /&gt;During my experiment I used Grails 1.2.0.&lt;br /&gt;Let's start with generating simple project with Book domain object and controller - almost as in Grails tutorial:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;grails create-app GrailsRestTest&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;cd GrailsRestTest&lt;/span&gt; &lt;span style="font-style: italic;"&gt;&lt;br /&gt;grails create-domain-class book&lt;/span&gt; &lt;span style="font-style: italic;"&gt;&lt;br /&gt;grails create-controller Book&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Only one thing that surprised me was a message: "&lt;span style="font-style: italic;"&gt;WARNING: You have not specified a package. It is good practise to place classes&lt;/span&gt;". I wanted to make it simple so I just ignored it by writing "&lt;span style="font-style: italic;"&gt;y&lt;/span&gt;" and pushing enter;)&lt;br /&gt;&lt;br /&gt;As in Grails tutorial,  I added some sample data to &lt;span style="font-style: italic;"&gt;/grails-app/conf/BootStrap.groovy&lt;/span&gt; file:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;def init = { servletContext -&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    new Book(author:"Stephen King",title:"The Shining").save()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    new Book(author:"James Patterson",title:"Along Came a Spider").save()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;span&gt;Final project structure will be:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_m4QcVuqJNnE/S2RLLNPzsYI/AAAAAAAAAFQ/bHQNzWOEzAU/s1600-h/rest3.PNG"&gt;&lt;img style="cursor: pointer; width: 177px; height: 400px;" src="http://2.bp.blogspot.com/_m4QcVuqJNnE/S2RLLNPzsYI/AAAAAAAAAFQ/bHQNzWOEzAU/s400/rest3.PNG" alt="" id="BLOGGER_PHOTO_ID_5432549706422268290" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;RESTful server&lt;/span&gt;&lt;br /&gt;We need to create controller that will be performing base CRUD operations and map its methods to REST style URLs.&lt;br /&gt;&lt;br /&gt;Edit &lt;span style="font-style: italic;"&gt; /grails-app/conf/UrlMappings.groovy&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;class UrlMappings {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   static mappings = {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;     "/$controller/$action?/$id?"{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;         constraints {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            // apply constraints here&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;         }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;     }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;     "/"(view:"/index")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;     "500"(view:'/error')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;     &lt;span style="color: rgb(51, 51, 255);"&gt;"/book" (controller: "book") {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;         action = [GET:"list", POST: "create"]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;     }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;     "/book/$id" (resource: "book")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Entry with &lt;span style="font-style: italic;"&gt;/book&lt;/span&gt; maps GET and POST HTTP requests to this URL to &lt;span style="font-style: italic;"&gt;list &lt;/span&gt;and &lt;span style="font-style: italic;"&gt;create &lt;/span&gt;controller methods. Below we map URLs like &lt;span style="font-style: italic;"&gt;/book/$id&lt;/span&gt; using default grails REST mapping:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;GET -&gt;  show&lt;/li&gt;&lt;li&gt;PUT -&gt; update&lt;/li&gt;&lt;li&gt;POST -&gt; save (used when you know ID of item you create - not our case;)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;DELETE -&gt; delete&lt;/li&gt;&lt;/ul&gt;Implementation of our controller will use GORM for data storage and will communicate with client application using JSON format. Edit &lt;span style="font-style: italic;"&gt;/grails-app/controllers/BookController.groovy&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;import grails.converters.*&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;class BookController {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   def &lt;span style="color: rgb(51, 51, 255);"&gt;list&lt;/span&gt; = {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       response.setHeader("Cache-Control", "no-store")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       render Book.list(params) as JSON&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   }  &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   def &lt;span style="color: rgb(51, 51, 255);"&gt;show&lt;/span&gt; = {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       Book b=Book.get(params.id)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       render b as JSON&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   }  &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   def &lt;span style="color: rgb(51, 51, 255);"&gt;create&lt;/span&gt; = {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       def json = JSON.parse(request);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       def b = new Book(json)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       b.save()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       &lt;span style="color: rgb(51, 51, 255);"&gt;response.status = 201&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;       response.setHeader('Location', '/book/'+b.id)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       render b as JSON&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   def &lt;span style="color: rgb(51, 51, 255);"&gt;delete&lt;/span&gt; = {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       Book b=Book.get(params.id)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       b.delete()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       render(status: 200)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;I guess this code is quite easy to understand. In &lt;span style="font-style: italic;"&gt;create &lt;/span&gt;operation we need to send 201 HTTP code and URL to newly created item in &lt;span style="font-style: italic;"&gt;Location &lt;/span&gt;header. I did not implement save and update methods to simplify my tutorial.&lt;br /&gt;&lt;br /&gt;Run this code with&lt;span style="font-style: italic;"&gt; grails run-app&lt;/span&gt; and point your browser to  &lt;span style="font-style: italic;"&gt;http://localhost:8080/GrailsRestTest/book&lt;/span&gt;. You should get following response:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;[{"class":"Book","id":1,"author":"Stephen King","title":"The Shining"},{"class":"Book","id":2,"author":"James Patterson","title":"Along Came a Spider"}]&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;To get particular item try &lt;span style="font-style: italic;"&gt;http://localhost:8080/GrailsRestTest/book/1&lt;/span&gt; - response should be:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;{"class":"Book","id":1,"author":"Stephen King","title":"The Shining"}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Client interface with Dojo&lt;/span&gt;&lt;br /&gt;Install Dojo with:&lt;br /&gt;&lt;span style="font-style: italic;"&gt;grails install-plugin dojo&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Add following page to &lt;span style="font-style: italic;"&gt;/grails-app/views/gui/books.gsp&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   &amp;lt;head&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       &amp;lt;script type="text/javascript" src="&amp;lt;g:createLinkTo file="/js/dojo/dojo-1.3.0/dojo/dojo.js" /&amp;gt;" djConfig="parseOnLoad:true, isDebug:false"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       &amp;lt;script type="text/javascript" src="&amp;lt;g:createLinkTo file="/js/dojo/dojo-1.3.0/dijit/dijit.js" /&amp;gt;"&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       &amp;lt;style type="text/css"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;           @import "&amp;lt;g:createLinkTo file="/js/dojo/dojo-1.3.0/dijit/themes/tundra/tundra.css" /&amp;gt;";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;           @import "&amp;lt;g:createLinkTo file="/js/dojo/dojo-1.3.0/dojox/grid/resources/Grid.css" /&amp;gt;";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;           @import "&amp;lt;g:createLinkTo file="/js/dojo/dojo-1.3.0/dojox/grid/resources/tundraGrid.css" /&amp;gt;";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       &amp;lt;/style&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   &amp;lt;/head&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   &amp;lt;body class="tundra"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       &amp;lt;script type="text/javascript"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;               dojo.require("dojox.grid.DataGrid");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;               dojo.require("dojox.data.JsonRestStore");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;               dojo.require("dijit.Dialog");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;               dojo.require("dijit.form.TextBox");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;               dojo.require("dijit.form.Button");      &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;             &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;               dojo.addOnLoad(function() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                   var restStore = new dojox.data.JsonRestStore({target:"&amp;lt;g:createLink controller="book" /&amp;gt;"});&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;         &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                   var layout = [&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                   {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                       field: 'id',&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                       name: 'Id',&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                       width: '50px'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                   },&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                   {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                       field: 'title',&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                       name: 'Title',&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                       width: '200px'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                   },&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                   {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                       field: 'author',&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                       name: 'Author',&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                       width: '100px'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                   }];&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;         &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                   var grid = new dojox.grid.DataGrid({&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                       store: restStore,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                       structure: layout,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                       selectionMode: 'single'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                   },&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                   document.createElement('div'));&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;         &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                   dojo.byId("gridContainer").appendChild(grid.domNode);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;         &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                   grid.startup();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                 &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                   saveBook = function(book) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                         restStore.newItem(book);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                         restStore.save();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;                         // to force grid refresh&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;                         grid.sort();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                   }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                 &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                   removeBook = function() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                       var book = grid.selection.getSelected()[0];&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                       if (book !=null &amp;amp;&amp;amp; book.id != null) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                             restStore.deleteItem(book);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                             restStore.save();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                       }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                   }    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                 &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                   showAddForm = function() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                       document.getElementById('title').value="";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                       document.getElementById('author').value="";              &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                       dijit.byId('dialog1').show();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;                   }                      &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;               });&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       &amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       &amp;lt;div id="gridContainer" style="width: 375px; height: 200px;"&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       &amp;lt;button dojoType="dijit.form.Button" onclick="showAddForm()"&amp;gt;Add book&amp;lt;/button&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       &amp;lt;button dojoType="dijit.form.Button" onclick="removeBook()"&amp;gt;Remove&amp;lt;/button&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       &amp;lt;div dojoType="dijit.Dialog" id="dialog1" title="Add book"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;           execute="saveBook(arguments[0]);"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;         &amp;lt;table&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;           &amp;lt;tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;             &amp;lt;td&amp;gt;&amp;lt;label for="title"&amp;gt;Title: &amp;lt;/label&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;             &amp;lt;td&amp;gt;&amp;lt;input dojoType="dijit.form.TextBox" type="text" name="title" id="title"&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;           &amp;lt;/tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;           &amp;lt;tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;             &amp;lt;td&amp;gt;&amp;lt;label for="author"&amp;gt;Author: &amp;lt;/label&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;             &amp;lt;td&amp;gt;&amp;lt;input dojoType="dijit.form.TextBox" type="text" name="author" id="author"&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;           &amp;lt;/tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;           &amp;lt;tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;             &amp;lt;td colspan="2" align="center"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;               &amp;lt;button dojoType="dijit.form.Button" type="submit"&amp;gt;Save&amp;lt;/button&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;           &amp;lt;/tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;         &amp;lt;/table&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       &amp;lt;/div&amp;gt;      &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   &amp;lt;/body&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Our client is based on three Dojo components:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;JsonRestStore - responsible for transparent client-server communication&lt;/li&gt;&lt;li&gt;DataGrid - grid presenation for data&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Dialog - simple popup for adding new book items&lt;/li&gt;&lt;/ul&gt;After starting application and pointing your browse to &lt;span style="font-style: italic;"&gt;http://localhost:8080/GrailsRestTest/gui/books.gsp&lt;/span&gt; you should see:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_m4QcVuqJNnE/S2RCEnXq1sI/AAAAAAAAAFA/zq5Io4qXNGM/s1600-h/rest1.PNG"&gt;&lt;img style="cursor: pointer; width: 390px; height: 250px;" src="http://3.bp.blogspot.com/_m4QcVuqJNnE/S2RCEnXq1sI/AAAAAAAAAFA/zq5Io4qXNGM/s400/rest1.PNG" alt="" id="BLOGGER_PHOTO_ID_5432539697570830018" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;DataGrid asked JsonRestStore for data and it made following request to server:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;GET /GrailsRestTest/book/? HTTP/1.1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Host: localhost:8080&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Accept: application/json,application/javascript&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Accept-Language: pl,en-us;q=0.7,en;q=0.3&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Accept-Encoding: gzip,deflate&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Keep-Alive: 300&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Connection: keep-alive&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Range: items=0-24&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Content-Type: application/json&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;X-Requested-With: XMLHttpRequest&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Referer: http://localhost:8080/GrailsRestTest/gui/books.gsp&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Response contains JSON data as presented earlier.&lt;br /&gt;&lt;br /&gt;Clicking &lt;span style="font-style: italic;"&gt;Add &lt;/span&gt;button will show popup that allows creating new items:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_m4QcVuqJNnE/S2RCQL7lPjI/AAAAAAAAAFI/2pUAR0SoSz8/s1600-h/rest2.PNG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 223px;" src="http://4.bp.blogspot.com/_m4QcVuqJNnE/S2RCQL7lPjI/AAAAAAAAAFI/2pUAR0SoSz8/s400/rest2.PNG" alt="" id="BLOGGER_PHOTO_ID_5432539896363695666" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Submitting data will result in following request and response:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;POST /GrailsRestTest/book/ HTTP/1.1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Host: localhost:8080&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Accept: application/json,application/javascript&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Accept-Language: pl,en-us;q=0.7,en;q=0.3&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Accept-Encoding: gzip,deflate&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Keep-Alive: 300&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Connection: keep-alive&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Transaction: commit&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Content-ID:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Content-Type: application/json; charset=UTF-8&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;X-Requested-With: XMLHttpRequest&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Referer: http://localhost:8080/GrailsRestTest/gui/books.gsp&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Content-Length: 49&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Pragma: no-cache&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Cache-Control: no-cache&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;{"title":"Test author 1","author":"Test title 1"}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;HTTP/1.x 201 Created&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Server: Apache-Coyote/1.1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Location: /book/3&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Content-Type: application/json;charset=UTF-8&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Transfer-Encoding: chunked&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Date: Sat, 30 Jan 2010 13:59:06 GMT&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;At that is the moment when I had some problems. You probably noticed commented line with &lt;span style="font-style: italic;"&gt;grid.sort()&lt;/span&gt; in gsp page. It forces grid and JsonRestStore to reload data from server after saving new item. When you remove this line, you will notice that new item is still added to store and even to the table (without reloading)  - but ID of new item is missing. According to Dojo documentation JsonRestStore should pick this ID from Location http header of response. Unfortunatelly it does not. Am I doing something wrong? Or is this a bug? Hints are welcome!&lt;br /&gt;&lt;br /&gt;To remove item select it and push &lt;span style="font-style: italic;"&gt;Remove &lt;/span&gt;button.  Dojo will make request similar to:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;DELETE /GrailsRestTest/book/8 HTTP/1.1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Host: localhost:8080&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;This time item is automatically removed from store and grid and any data reloading is not needed.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;The title of this article starts with "Almost" as it is not complete application. I did not implement any update operation. Also this ID issue with Dojo makes me a little worried. Application was tested only on Firefox... so to make it "production ready" you should also test (or get it working ;) on other browsers. Anyway, it was fun to try something new...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/401162125201554678-7937578940687118221?l=maciekmoczkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://maciekmoczkowski.blogspot.com/feeds/7937578940687118221/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://maciekmoczkowski.blogspot.com/2010/01/almost-restfull-application-with-grails.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/7937578940687118221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/7937578940687118221'/><link rel='alternate' type='text/html' href='http://maciekmoczkowski.blogspot.com/2010/01/almost-restfull-application-with-grails.html' title='(Almost) RESTful application with Grails and Dojo'/><author><name>Maciej Moczkowski</name><uri>http://www.blogger.com/profile/10277409687102251243</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://2.bp.blogspot.com/_m4QcVuqJNnE/SqC1Rb_uygI/AAAAAAAAABY/5-954Qu8YWg/S220/mm.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_m4QcVuqJNnE/S2RLLNPzsYI/AAAAAAAAAFQ/bHQNzWOEzAU/s72-c/rest3.PNG' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-401162125201554678.post-6582814312094757198</id><published>2009-11-10T20:47:00.012+01:00</published><updated>2009-11-10T22:08:18.677+01:00</updated><title type='text'>Grails on GAE and persistence</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Introduction&lt;/span&gt;&lt;br /&gt;In my last post we created very simple Grails project and deployed it on Google Application Engine. Now we will try to extend it to use Google Datastore for persistence.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Configuration&lt;/span&gt;&lt;br /&gt;Create a project in the same way as in previous post but ensure you will choose JPA as a persistence provider. Another option is JDO but I simply don't know this technology;)&lt;br /&gt;Next step will be to install gorm-jpa plugin for Grails:&lt;br /&gt;&lt;span style="font-style: italic;"&gt;grails install-plugin gorm-jpa&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Application goals&lt;/span&gt;&lt;br /&gt;We will create very simple one page application to manage list of books. On the top there will be a list of book items. At the bottom there will a form to store new ones.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_m4QcVuqJNnE/SvnNaFdVgKI/AAAAAAAAAEA/7hpI0VWgUZM/s1600-h/books1.PNG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 129px;" src="http://1.bp.blogspot.com/_m4QcVuqJNnE/SvnNaFdVgKI/AAAAAAAAAEA/7hpI0VWgUZM/s400/books1.PNG" alt="" id="BLOGGER_PHOTO_ID_5402575076033134754" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Implementation&lt;/span&gt;&lt;br /&gt;We should create class for our domain object - &lt;span style="font-style: italic;"&gt;grails-app\domain\test\Book.groovy&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-style: italic;"&gt;package test&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import javax.persistence.*;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;@Entity&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;class Book implements Serializable {&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    @Id&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    @GeneratedValue(strategy = GenerationType.IDENTITY)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    Long id&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    String title&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    static constraints = {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        id visible:false&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;We need also web controller that will be responsible for 3 web actions:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;index - main action listing all books&lt;/li&gt;&lt;li&gt;save - adding new book&lt;br /&gt;&lt;/li&gt;&lt;li&gt;remove - removing book&lt;/li&gt;&lt;/ul&gt;Add following code to &lt;span style="font-style: italic;"&gt;grails-app\controllers\BookController.groovy&lt;/span&gt;:&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;pre&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-style: italic;"&gt;import test.*&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;class BookController {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    def index = { &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            [books : Book.list( params )]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    def &lt;span style="color: rgb(51, 102, 255);"&gt;save&lt;/span&gt; = {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            Book b=new Book(params)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            b.save()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            redirect(action : index)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    def &lt;span style="color: rgb(51, 102, 255);"&gt;remove&lt;/span&gt; = {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            Book b=Book.get(params.id)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            b.delete()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            redirect(action : index)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;Finally add GSP page (&lt;span style="font-style: italic;"&gt;grails-app\views\book\index.gsp&lt;/span&gt;) that will present data and invoke particular actions of our controller:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;meta name="layout" content="main" /&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;title&amp;gt;&amp;lt;/title&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;h1&amp;gt;Books:&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;thead&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;th&amp;gt;Id&amp;lt;/th&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;th&amp;gt;Title&amp;lt;/th&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;th&amp;gt;&amp;lt;/th&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;/tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;/thead&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;g:each in="${books}" status="i" var="book"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;td&amp;gt;${book.id}&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;td&amp;gt;${book.title}&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;td&amp;gt;&amp;lt;g:link action="&lt;span style="color: rgb(51, 102, 255);"&gt;remove&lt;/span&gt;" id="${book.id}"&amp;gt;remove&amp;lt;/g:link&amp;gt; &amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;/tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;/g:each&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;h1&amp;gt;New:&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;g:form action="&lt;span style="color: rgb(51, 102, 255);"&gt;save&lt;/span&gt;"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;table&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;td&amp;gt;Title&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;td&amp;gt;&amp;lt;g:textField name="title" /&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;/tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;            &amp;lt;td colspan="2"&amp;gt;&amp;lt;input type="submit" /&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        &amp;lt;/tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &amp;lt;/table&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/g:form&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;Deploy the application just as we did it in last post. Point the browser to /book resource of your web app. You should see our page running.&lt;br /&gt;&lt;br /&gt;Now, you can also browse datastore on GAE account pages:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_m4QcVuqJNnE/SvnOUuXJKBI/AAAAAAAAAEI/FF0o6uP5WTY/s1600-h/books2.PNG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 155px;" src="http://3.bp.blogspot.com/_m4QcVuqJNnE/SvnOUuXJKBI/AAAAAAAAAEI/FF0o6uP5WTY/s400/books2.PNG" alt="" id="BLOGGER_PHOTO_ID_5402576083445426194" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/401162125201554678-6582814312094757198?l=maciekmoczkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://maciekmoczkowski.blogspot.com/feeds/6582814312094757198/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://maciekmoczkowski.blogspot.com/2009/11/grails-on-gae-and-persistence.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/6582814312094757198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/6582814312094757198'/><link rel='alternate' type='text/html' href='http://maciekmoczkowski.blogspot.com/2009/11/grails-on-gae-and-persistence.html' title='Grails on GAE and persistence'/><author><name>Maciej Moczkowski</name><uri>http://www.blogger.com/profile/10277409687102251243</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://2.bp.blogspot.com/_m4QcVuqJNnE/SqC1Rb_uygI/AAAAAAAAABY/5-954Qu8YWg/S220/mm.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_m4QcVuqJNnE/SvnNaFdVgKI/AAAAAAAAAEA/7hpI0VWgUZM/s72-c/books1.PNG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-401162125201554678.post-4970620019646783793</id><published>2009-11-07T12:04:00.013+01:00</published><updated>2009-11-10T22:28:51.276+01:00</updated><title type='text'>Deploying Grails application on Google Application Engine</title><content type='html'>&lt;span style="font-weight: bold;font-size:100%;" &gt;Introduction&lt;/span&gt;&lt;br /&gt;Some time ago it was announced that Google Application Engine supports Grails framework. As a great fan of Groovy and Grails I wanted to give it a try. I was also very curious to see how GAE works. In this article I would like to present simple "Hello World" project and its deployment process.&lt;br /&gt;&lt;br /&gt;My example uses:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Grails 1.1.1 (http://www.grails.org)&lt;/li&gt;&lt;li&gt;GAE SDK 1.2.6 for Java (http://code.google.com/intl/pl/appengine/downloads.html#Google_App_Engine_SDK_for_Java)&lt;/li&gt;&lt;li&gt;Java 1.6&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;Configuration&lt;/span&gt;&lt;br /&gt;As a first step please download required software and install it. To configure it properly you need to set up:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;variable GRAILS_HOME to directory where you installed Grails&lt;/li&gt;&lt;li&gt;variable APPENGINE_HOME to directory where you installed GAE SDK&lt;br /&gt;&lt;/li&gt;&lt;li&gt;add GRAILS_HOME\bin directory to PATH variable&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;Creating GAE account&lt;/span&gt;&lt;br /&gt;Go to GAE website (http://appengine.google.com) and create an account. Log in and add new application to your account. Specify application name - I will use "gae-grails-maciek-test".&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;Creating simple project&lt;/span&gt;&lt;br /&gt;Go the your workspace directory and type: &lt;span style="font-style: italic;"&gt;grails create-app GoogleGrailsTest&lt;/span&gt;&lt;br /&gt;Script should create your project subdirectory - &lt;span style="font-style: italic;"&gt;GoogleGrailsTest. &lt;/span&gt;You can import your project to Eclipse or another IDE.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_m4QcVuqJNnE/SvVbfu_GgJI/AAAAAAAAADo/l0VheRD7Zs0/s1600-h/gae2.PNG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 195px;" src="http://4.bp.blogspot.com/_m4QcVuqJNnE/SvVbfu_GgJI/AAAAAAAAADo/l0VheRD7Zs0/s400/gae2.PNG" alt="" id="BLOGGER_PHOTO_ID_5401323928847548562" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Please modify &lt;span style="font-style: italic;"&gt;GoogleGrailsTest\grails-app\conf\Config.groovy&lt;/span&gt; and add following line:&lt;br /&gt;&lt;span style="font-style: italic;"&gt;google.appengine.application="gae-grails-maciek-test"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Of course you should use your GAE application name.  Go to project directory and install grails GAE plugin:&lt;br /&gt;&lt;span style="font-style: italic;"&gt;grails install-plugin app-engine&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You will be asked if you want to use JPA or JDO for persistence. It is not important at all for our case.&lt;br /&gt;&lt;br /&gt;To run you project locally on your computer type: &lt;span style="font-style: italic;"&gt;grails app-engine run&lt;/span&gt;&lt;br /&gt;You should be able to access it at http://localhost:8080&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_m4QcVuqJNnE/SvVbfxbgFRI/AAAAAAAAADw/MvPPZ3dseNA/s1600-h/gae1.PNG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 61px;" src="http://3.bp.blogspot.com/_m4QcVuqJNnE/SvVbfxbgFRI/AAAAAAAAADw/MvPPZ3dseNA/s400/gae1.PNG" alt="" id="BLOGGER_PHOTO_ID_5401323929503536402" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I must confess I noticed a strange stack trace in log files, but application was still running properly...&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;Deployment&lt;/span&gt;&lt;br /&gt;Type:&lt;br /&gt;&lt;span style="font-style: italic;"&gt;grails set-version 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;grails app-engine package&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;First deployment should be done with:&lt;br /&gt;&lt;span style="font-style: italic;"&gt;$APPENGINE_HOME/bin/appcfg.cmd update ./target/war&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Later when you just update application on GAE sever you can just type:&lt;br /&gt;&lt;span style="font-style: italic;"&gt;grails app-engine deploy&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;During deployment process you will be asked about your google account email and password. I noticed strange bug during authentication process. When script asks you for email just push Enter and go to the next line and enter it there. Password can be entered normally. Without this trick I was not able to authenticate properly.&lt;br /&gt;&lt;br /&gt;Now you should be able to access your application at http://your-app-name.appspot.com - in my case on http://gae-grails-maciek-test.appspot.com/&lt;br /&gt;&lt;br /&gt;Application can be monitored on GAE pages after logging in to your account:&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_m4QcVuqJNnE/SvVbf2EJAUI/AAAAAAAAAD4/VmDQVCCLRSw/s1600-h/gae3.PNG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 270px;" src="http://4.bp.blogspot.com/_m4QcVuqJNnE/SvVbf2EJAUI/AAAAAAAAAD4/VmDQVCCLRSw/s400/gae3.PNG" alt="" id="BLOGGER_PHOTO_ID_5401323930747732290" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&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/401162125201554678-4970620019646783793?l=maciekmoczkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://maciekmoczkowski.blogspot.com/feeds/4970620019646783793/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://maciekmoczkowski.blogspot.com/2009/11/deploying-grails-application-on-google.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/4970620019646783793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/4970620019646783793'/><link rel='alternate' type='text/html' href='http://maciekmoczkowski.blogspot.com/2009/11/deploying-grails-application-on-google.html' title='Deploying Grails application on Google Application Engine'/><author><name>Maciej Moczkowski</name><uri>http://www.blogger.com/profile/10277409687102251243</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://2.bp.blogspot.com/_m4QcVuqJNnE/SqC1Rb_uygI/AAAAAAAAABY/5-954Qu8YWg/S220/mm.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_m4QcVuqJNnE/SvVbfu_GgJI/AAAAAAAAADo/l0VheRD7Zs0/s72-c/gae2.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-401162125201554678.post-124959208475623793</id><published>2009-09-06T17:46:00.045+02:00</published><updated>2009-11-07T14:23:08.823+01:00</updated><title type='text'>Partial rendering with Spring MVC and Spring Javascript</title><content type='html'>&lt;span style="font-weight: bold;font-size:100%;" &gt;Introduction&lt;/span&gt;&lt;br /&gt;Almost all modern web pages uses many AJAX techniques. One of them is partial rendering - it allows user to rerender only part of a page instead of its full contents.&lt;br /&gt;&lt;br /&gt;Main benefits are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;less response size sent via network&lt;/li&gt;&lt;li&gt;less time needed to show new page contents&lt;/li&gt;&lt;li&gt;less application server load&lt;/li&gt;&lt;li&gt;better user experience&lt;/li&gt;&lt;/ul&gt;Recently I was using partial rendering in JSF application with Ajax4JSF framework. To have wider perspecitve I was going to try another out of the box solution from lightweight stack like Spring MVC, Spring Javascript and Apache Tiles.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;Application goals&lt;/span&gt;&lt;br /&gt;Test application has a page layout configured with Tiles. Pages consist of menu on the left side and main contents on the right. Navigation links in menu are used to choose page contents for right side - it will be rerendered (Ajax) after each click on menu item.&lt;br /&gt;&lt;br /&gt;Main page (rendering time is just to show ajax behaviour):&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_m4QcVuqJNnE/SqP9L6TDQBI/AAAAAAAAACE/M9R5qPx57Rk/s1600-h/springjs2.JPG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 135px;" src="http://4.bp.blogspot.com/_m4QcVuqJNnE/SqP9L6TDQBI/AAAAAAAAACE/M9R5qPx57Rk/s400/springjs2.JPG" alt="" id="BLOGGER_PHOTO_ID_5378420761080053778" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Page after ajax rerendering triggered by click in menu:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_m4QcVuqJNnE/SqP9hgRyd6I/AAAAAAAAACM/yVP0stmD2Ww/s1600-h/springjs3.JPG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 135px;" src="http://2.bp.blogspot.com/_m4QcVuqJNnE/SqP9hgRyd6I/AAAAAAAAACM/yVP0stmD2Ww/s400/springjs3.JPG" alt="" id="BLOGGER_PHOTO_ID_5378421132052559778" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;To prepare my sample application I used:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Maven 2.0.9&lt;/li&gt;&lt;li&gt;Java 1.6.0_12&lt;/li&gt;&lt;li&gt;Spring 2.5.6&lt;/li&gt;&lt;li&gt;Spring Javascript 2.0.5&lt;/li&gt;&lt;li&gt;Apache Tiles 2.1.0&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-size:100%;"&gt;Project structure&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;I used typical maven structure for the project&lt;span style="font-weight: bold;"&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_m4QcVuqJNnE/SqPjkUg5g2I/AAAAAAAAAB8/trhGSKVprZI/s1600-h/springjs1.JPG"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 226px; height: 400px;" src="http://4.bp.blogspot.com/_m4QcVuqJNnE/SqPjkUg5g2I/AAAAAAAAAB8/trhGSKVprZI/s400/springjs1.JPG" alt="" id="BLOGGER_PHOTO_ID_5378392593131996002" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;All project dependencies are configured in maven's pom.xml:&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:georgia;font-size:100%;"  &gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;groupId&amp;gt;org.maciekm&amp;lt;/groupId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;artifactId&amp;gt;spring-js-demo&amp;lt;/artifactId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;packaging&amp;gt;war&amp;lt;/packaging&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;name&amp;gt;spring-js-demo Maven Webapp&amp;lt;/name&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;url&amp;gt;http://maven.apache.org&amp;lt;/url&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;dependency&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;groupId&amp;gt;javax.servlet&amp;lt;/groupId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       &amp;lt;artifactId&amp;gt;servlet-api&amp;lt;/artifactId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;version&amp;gt;2.4&amp;lt;/version&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;/dependency&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;dependency&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;artifactId&amp;gt;spring-webmvc&amp;lt;/artifactId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;version&amp;gt;2.5.6&amp;lt;/version&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;/dependency&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;dependency&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;groupId&amp;gt;org.springframework.webflow&amp;lt;/groupId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;artifactId&amp;gt;org.springframework.js&amp;lt;/artifactId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;version&amp;gt;2.0.5.RELEASE&amp;lt;/version&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;/dependency&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;dependency&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;groupId&amp;gt;org.apache.tiles&amp;lt;/groupId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;artifactId&amp;gt;tiles-core&amp;lt;/artifactId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;version&amp;gt;2.1.0&amp;lt;/version&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;/dependency&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;dependency&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;groupId&amp;gt;org.apache.tiles&amp;lt;/groupId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;artifactId&amp;gt;tiles-jsp&amp;lt;/artifactId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;version&amp;gt;2.1.0&amp;lt;/version&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;/dependency&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;dependency&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;groupId&amp;gt;javax.servlet&amp;lt;/groupId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;artifactId&amp;gt;jstl&amp;lt;/artifactId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;/dependency&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;dependency&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;groupId&amp;gt;taglibs&amp;lt;/groupId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;artifactId&amp;gt;standard&amp;lt;/artifactId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;/dependency&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/dependencies&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;build&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;finalName&amp;gt;spring-js-demo&amp;lt;/finalName&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;plugins&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;plugin&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;          &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;          &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       &amp;lt;/plugin&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;plugin&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;          &amp;lt;groupId&amp;gt;org.mortbay.jetty&amp;lt;/groupId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;          &amp;lt;artifactId&amp;gt;maven-jetty-plugin&amp;lt;/artifactId&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;       &amp;lt;/plugin&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;/plugins&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/build&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/project&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;Web application configuration&lt;/span&gt;&lt;br /&gt;At first we need to configure our web app in web.xml:&lt;br /&gt;&lt;pre style="font-style: italic;"&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;!DOCTYPE web-app PUBLIC&lt;br /&gt;"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"&lt;br /&gt;"http://java.sun.com/dtd/web-app_2_3.dtd" &amp;gt;&lt;br /&gt;&amp;lt;web-app&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;display-name&amp;gt;Archetype Created Web Application&amp;lt;/display-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;filter&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;filter-name&amp;gt;characterEncodingFilter&amp;lt;/filter-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;filter-class&amp;gt;org.springframework.web.filter.CharacterEncodingFilter&amp;lt;/filter-class&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;init-param&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;   &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt; &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;param-name&amp;gt;encoding&amp;lt;/param-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;param-value&amp;gt;UTF-8&amp;lt;/param-value&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;/init-param&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;init-param&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;param-name&amp;gt;forceEncoding&amp;lt;/param-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;/init-param&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;/filter&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;servlet&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;servlet-name&amp;gt;springjsdemo&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;servlet-class&amp;gt;org.springframework.web.servlet.DispatcherServlet&amp;lt;/servlet-class&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;load-on-startup&amp;gt;1&amp;lt;/load-on-startup&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;/servlet&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;servlet&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;servlet-name&amp;gt;Resource Servlet&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;servlet-class&amp;gt;org.springframework.js.resource.ResourceServlet&amp;lt;/servlet-class&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;init-param&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;param-name&amp;gt;allowedResourcePaths&amp;lt;/param-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;param-value&amp;gt;/**/*.css,/**/*.gif,/**/*.ico,/**/*.jpeg,/**/*.jpg,/**/*.js,/**/*.png,META-INF/**/*.css,META-INF/**/*.gif,META-INF/**/*.ico,META-INF/**/*.jpeg,META-INF/**/*.jpg,META-INF/**/*.js,META-INF/**/*.png,META-INF/**/dojo/resources/blank.html,/dojo/resources/blank.html&amp;lt;/param-value&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;/init-param&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;/servlet&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;servlet-mapping&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;servlet-name&amp;gt;springjsdemo&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;url-pattern&amp;gt;*.htm&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;/servlet-mapping&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;servlet-mapping&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;servlet-name&amp;gt;Resource Servlet&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;url-pattern&amp;gt;/resources/*&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;/servlet-mapping&amp;gt;&lt;br /&gt;&amp;lt;/web-app&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-style: italic;"&gt;Springjsdemo &lt;/span&gt;servlet is used to start spring web application context and as a front controller in our application. &lt;span style="font-style: italic;"&gt;Resources Servlet&lt;/span&gt; is necessary for Spring Javascript. &lt;span style="font-style: italic;"&gt;characterEncodingFilter&lt;/span&gt; is important when you want to use national characters on pages fragments rerendered by Ajax.&lt;br /&gt;&lt;br /&gt;We also have to setup application context - springjsdemo-servlet.xml:&lt;br /&gt;&lt;pre style="font-style: italic;"&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;beans xmlns="http://www.springframework.org/schema/beans"&lt;br /&gt;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;xmlns:context="http://www.springframework.org/schema/context"&lt;br /&gt;xsi:schemaLocation="http://www.springframework.org/schema/beans&lt;br /&gt;http://www.springframework.org/schema/beans/spring-beans-2.5.xsd&lt;br /&gt;http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;context:component-scan base-package="org.maciekm.springjsdemo"/&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer"&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;property name="definitions"&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;list&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;value&amp;gt;/WEB-INF/tiles/pages.xml&amp;lt;/value&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;/list&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;/property&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;bean id="tilesViewResolver" class="org.springframework.js.ajax.AjaxUrlBasedViewResolver"&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;property name="viewClass" value="org.springframework.js.ajax.tiles2.AjaxTilesView"/&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&amp;lt;/bean&amp;gt;&lt;br /&gt;&amp;lt;/beans&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;We configured Spring MVC to work with Apache Tiles. Spring MVC controller will be found and initialized by component scanning.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;Pages layout&lt;/span&gt;&lt;br /&gt;Tiles layouts are configured in pages.xml:&lt;span style="font-style: italic;"&gt;&lt;span style="font-size:100%;"&gt;&lt;pre&gt;&lt;pre&gt;&amp;lt;?xml version="1.0" encoding="ISO-8859-1" ?&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE tiles-definitions PUBLIC&lt;br /&gt;"-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"&lt;br /&gt;"http://tiles.apache.org/dtds/tiles-config_2_1.dtd"&amp;gt;&lt;br /&gt;&amp;lt;tiles-definitions&amp;gt;&lt;br /&gt;  &amp;lt;definition name="&lt;span style="color: rgb(51, 51, 255);"&gt;welcome&lt;/span&gt;" template="/WEB-INF/jsp/template.jsp"&amp;gt;&lt;br /&gt;      &amp;lt;put-attribute name="&lt;span style="color: rgb(51, 51, 255);"&gt;menu&lt;/span&gt;" value="/WEB-INF/jsp/menu.jsp"/&amp;gt;&lt;br /&gt;      &amp;lt;put-attribute name="&lt;span style="color: rgb(51, 51, 255);"&gt;body&lt;/span&gt;" value="/WEB-INF/jsp/welcome.jsp"/&amp;gt;&lt;br /&gt;  &amp;lt;/definition&amp;gt;&lt;br /&gt;  &amp;lt;definition name="&lt;span style="color: rgb(51, 51, 255);"&gt;page1&lt;/span&gt;" extends="welcome"&amp;gt;&lt;br /&gt;      &amp;lt;put-attribute name="&lt;span style="color: rgb(51, 51, 255);"&gt;body&lt;/span&gt;" value="/WEB-INF/jsp/page1.jsp"/&amp;gt;&lt;br /&gt;  &amp;lt;/definition&amp;gt;&lt;br /&gt;  &amp;lt;definition name="&lt;span style="color: rgb(51, 51, 255);"&gt;page2&lt;/span&gt;" extends="welcome"&amp;gt;&lt;br /&gt;      &amp;lt;put-attribute name="&lt;span style="color: rgb(51, 51, 255);"&gt;body&lt;/span&gt;" value="/WEB-INF/jsp/page2.jsp"/&amp;gt;&lt;br /&gt;  &amp;lt;/definition&amp;gt;&lt;br /&gt;&amp;lt;/tiles-definitions&amp;gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;Idea of using Tiles is not just to define page layouts. It helps us to define logical structure of pages so we will be able to rerender its parts.&lt;br /&gt;&lt;br /&gt;Our layout template is in template.jsp and we configured 3 views based on it: &lt;span style="font-style: italic;"&gt;welcome&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;page1&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;page2&lt;/span&gt;. Each view consist of &lt;span style="font-style: italic;"&gt;menu&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;body&lt;/span&gt; attributes.&lt;br /&gt;&lt;br /&gt;Here we have template.jsp source:&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;%@ page pageEncoding="UTF-8" %&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;%@ include file="include.jsp" %&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;title&amp;gt;Spring JS Demo&amp;lt;/title&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   &amp;lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" &amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;META HTTP-EQUIV="Pragma" CONTENT="no-cache"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;META HTTP-EQUIV="Expires" CONTENT="-1"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;meta http-equiv="Content-Language" content="pl"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;meta http-equiv="Cache-Control" content="no-store, no-cache, must-revalidate, Post-Check=0, Pre-Check=0"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;  &amp;lt;script type="text/javascript" src="&amp;lt;c:url value="/resources/dojo/dojo.js" /&amp;gt;"&amp;gt; &amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;  &amp;lt;script type="text/javascript" src="&amp;lt;c:url value="/resources/spring/Spring.js" /&amp;gt;"&amp;gt; &amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;  &amp;lt;script type="text/javascript" src="&amp;lt;c:url value="/resources/spring/Spring-Dojo.js" /&amp;gt;"&amp;gt; &amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;table cellpadding="5" cellspacing="5" border="1" width="100%"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;          &amp;lt;td id="left" width="150px"&amp;gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&amp;lt;tiles:insertAttribute name="menu" /&amp;gt;&lt;/span&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;          &amp;lt;td id="right"&amp;gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&amp;lt;tiles:insertAttribute name="body" /&amp;gt;&lt;/span&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;      &amp;lt;/tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;/table&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;JS files needed for Spring Javascript have been included.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;Web pages&lt;/span&gt;&lt;br /&gt;The core point of our application is menu. It contains links that will allow you to choose body of the web page and rerender it using Ajax.&lt;span style="font-style: italic;font-size:100%;" &gt;&lt;beans xmlns="http://www.springframework.org/schema/beans" xsi="http://www.w3.org/2001/XMLSchema-instance" context="http://www.springframework.org/schema/context" schemalocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"&gt;&lt;context:component-scan package="org.maciekm.springjsdemo"&gt;&lt;bean id="tilesViewResolver" class="org.springframework.js.ajax.AjaxUrlBasedViewResolver"&gt;&lt;property name="viewClass" value="org.springframework.js.ajax.tiles2.AjaxTilesView"&gt;&lt;/property&gt;&lt;/bean&gt;&lt;/context:component-scan&gt;&lt;/beans&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;%@ page pageEncoding="UTF-8" %&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;%@ include file="include.jsp" %&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;Menu:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;br/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;br/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;form action="&amp;lt;c:url value='&lt;span style="color: rgb(51, 51, 255);"&gt;/page1.htm&lt;/span&gt;'/&amp;gt;" method="POST" id="page1Form" style="padding: 0px;margin: 0px;"&amp;gt;&amp;lt;/form&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;a id="&lt;span style="color: rgb(51, 51, 255);"&gt;page1&lt;/span&gt;" href="#"&amp;gt;Page 1&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;form action="&amp;lt;c:url value='&lt;span style="color: rgb(51, 51, 255);"&gt;/page2.htm&lt;/span&gt;'/&amp;gt;" method="POST" id="page2Form" style="padding: 0px;margin: 0px;"&amp;gt;&amp;lt;/form&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &amp;lt;a id="&lt;span style="color: rgb(51, 51, 255);"&gt;page2&lt;/span&gt;" href="#"&amp;gt;Page 2&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Spring.addDecoration(new Spring.AjaxEventDecoration({&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   elementId: "&lt;span style="color: rgb(51, 51, 255);"&gt;page1&lt;/span&gt;",&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   formId: "page1Form",&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   event: "onclick",&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   params: {fragments: "&lt;span style="color: rgb(51, 51, 255);"&gt;body&lt;/span&gt;"}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;}));&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Spring.addDecoration(new Spring.AjaxEventDecoration({&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   elementId: "&lt;span style="color: rgb(51, 51, 255);"&gt;page2&lt;/span&gt;",&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   formId: "page2Form",&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   event: "onclick",&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;   params: {fragments: "&lt;span style="color: rgb(51, 51, 255);"&gt;body&lt;/span&gt;"}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;}));&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Rendering time:&amp;lt;br/&amp;gt;&amp;lt;%=new java.util.Date()%&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;Each link is "decorated" with special Spring Javascript code. &lt;span style="font-style: italic;"&gt;AjaxEventDecoration&lt;/span&gt; will make Ajax request to server to ask for the page configured in form definition. However, it will ask only for specified page fragment - &lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;body&lt;/span&gt;.&lt;br /&gt;Name of this fragment must be the same as name of Tiles attribute in layout of requested page.&lt;br /&gt;On both current page as well as loaded fragment we need to have a div element with ID same as fragment name - &lt;span style="font-style: italic; color: rgb(51, 51, 255);"&gt;body&lt;/span&gt;. Spring Javascript will be able to replace its old contents with new that just has been loaded from server.&lt;br /&gt;&lt;br /&gt;Note: I used POST forms to define links becouse I had some problems with GET requests and cacheing in IE8. However it is not a recommended solution in a serious project. You should consider using GET with random parameters added just to avoid caching problem.&lt;br /&gt;&lt;br /&gt;Default page body is defined in welcome.jsp as a part of &lt;span style="font-style: italic;"&gt;welcome &lt;/span&gt;tiles view:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;%@ page pageEncoding="UTF-8" %&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;%@ include file="include.jsp" %&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;div id="&lt;span style="color: rgb(51, 51, 255);"&gt;body&lt;/span&gt;"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    Main area&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;As I said, it contains &lt;span style="font-style: italic;"&gt;body &lt;/span&gt;div as an container for ajax rerendering with its initial value.&lt;br /&gt;Below we have alternative pages that can be selected from menu.&lt;br /&gt;&lt;br /&gt;page1.jsp:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;%@ page pageEncoding="UTF-8" %&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;%@ include file="include.jsp" %&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;div id="&lt;span style="color: rgb(51, 51, 255);"&gt;body&lt;/span&gt;"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    This is page 1. Rendering time: &amp;lt;%=new java.util.Date()%&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/pre&gt;And page2.jsp:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;%@ page pageEncoding="UTF-8" %&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;%@ include file="include.jsp" %&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;div id="&lt;span style="color: rgb(51, 51, 255);"&gt;body&lt;/span&gt;"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    This is page 2. Rendering time: &amp;lt;%=new java.util.Date()%&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/pre&gt;We need also some less important jsp pages to make our application running.&lt;br /&gt;We use include.jsp just to include some TLDs:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;%@ page pageEncoding="UTF-8" %&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %&amp;gt;&lt;/span&gt;&lt;/pre&gt;index.jsp is used only to redirect us from root view to our welcome page:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;%@ include file="/WEB-INF/jsp/include.jsp" %&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&amp;lt;c:redirect url="welcome.htm"/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Spring MVC controller&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Of course we need MVC controller to map our views to urls.  It our simple case it does not contain any business logic.&lt;br /&gt;&lt;br /&gt;We map:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;/welcome.htm -&gt; &lt;span style="font-style: italic;"&gt;welcome&lt;/span&gt; view&lt;/li&gt;&lt;li&gt;/page1.htm -&gt; &lt;span style="font-style: italic;"&gt;page1&lt;/span&gt; view&lt;/li&gt;&lt;li&gt;/page2.html -&gt; &lt;span style="font-style: italic;"&gt;page2&lt;/span&gt; view&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Source code:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;package org.maciekm.springjsdemo.controller;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import org.springframework.stereotype.Controller;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;import org.springframework.web.bind.annotation.RequestMapping;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;@Controller&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;public class MainController {&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    @RequestMapping("&lt;span style="color: rgb(51, 51, 255);"&gt;/welcome.htm&lt;/span&gt;")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &lt;/span&gt;&lt;span style="font-style: italic;"&gt;public String welcomePage() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &lt;/span&gt;&lt;span style="font-style: italic;"&gt;    &lt;/span&gt;&lt;span style="font-style: italic;"&gt;return "&lt;span style="color: rgb(51, 51, 255);"&gt;welcome&lt;/span&gt;";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &lt;/span&gt;&lt;span style="font-style: italic;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &lt;/span&gt;&lt;span style="font-style: italic;"&gt;@RequestMapping("&lt;span style="color: rgb(51, 51, 255);"&gt;/page1.htm&lt;/span&gt;")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &lt;/span&gt;&lt;span style="font-style: italic;"&gt;public String page1() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &lt;/span&gt;&lt;span style="font-style: italic;"&gt;    &lt;/span&gt;&lt;span style="font-style: italic;"&gt;return "&lt;span style="color: rgb(51, 51, 255);"&gt;page1&lt;/span&gt;";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &lt;/span&gt;&lt;span style="font-style: italic;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &lt;/span&gt;&lt;span style="font-style: italic;"&gt;@RequestMapping("&lt;span style="color: rgb(51, 51, 255);"&gt;/page2.htm&lt;/span&gt;")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  &lt;/span&gt;&lt;span style="font-style: italic;"&gt;  &lt;/span&gt;&lt;span style="font-style: italic;"&gt;public String page2() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &lt;/span&gt;&lt;span style="font-style: italic;"&gt;    &lt;/span&gt;&lt;span style="font-style: italic;"&gt;return "&lt;span style="color: rgb(51, 51, 255);"&gt;page2&lt;/span&gt;";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    &lt;/span&gt;&lt;span style="font-style: italic;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;}&lt;/span&gt;&lt;span style="font-family:monospace;"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-size:100%;"&gt;Running and testing&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;To run application type &lt;span style="font-style: italic;"&gt;mvn jetty:run&lt;/span&gt; from console in main project directory. It should start Jetty server and deploy our webapp to &lt;span style="font-style: italic;"&gt;http://localhost:8080/spring-js-demo. &lt;/span&gt;Point your browser to this url and test links in menu.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Hopefully our Ajax partial rendering works:)&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/401162125201554678-124959208475623793?l=maciekmoczkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://maciekmoczkowski.blogspot.com/feeds/124959208475623793/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://maciekmoczkowski.blogspot.com/2009/09/partial-rendering-with-spring-mvc-and.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/124959208475623793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/401162125201554678/posts/default/124959208475623793'/><link rel='alternate' type='text/html' href='http://maciekmoczkowski.blogspot.com/2009/09/partial-rendering-with-spring-mvc-and.html' title='Partial rendering with Spring MVC and Spring Javascript'/><author><name>Maciej Moczkowski</name><uri>http://www.blogger.com/profile/10277409687102251243</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://2.bp.blogspot.com/_m4QcVuqJNnE/SqC1Rb_uygI/AAAAAAAAABY/5-954Qu8YWg/S220/mm.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_m4QcVuqJNnE/SqP9L6TDQBI/AAAAAAAAACE/M9R5qPx57Rk/s72-c/springjs2.JPG' height='72' width='72'/><thr:total>6</thr:total></entry></feed>
