<?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-7911563994423957036</id><updated>2011-11-28T01:34:26.526+02:00</updated><category term='logging'/><category term='lj-cut'/><category term='scala'/><category term='transaction'/><category term='solution'/><category term='subclass'/><category term='javascript'/><category term='java'/><category term='cache'/><category term='debugging'/><category term='ajax'/><category term='blogspot'/><category term='dev_appserver'/><category term='Hibernate'/><category term='datastore'/><category term='low-level'/><category term='scriptaculous'/><category term='ljcut'/><category term='django'/><category term='osx'/><category term='netbeans'/><category term='memcache'/><category term='slots'/><category term='blogger'/><category term='appengine'/><category term='superclass'/><category term='ReferenceProperty'/><category term='python'/><category term='jpa'/><category term='utf8'/><category term='nodejs'/><category term='performance'/><category term='polymorphism'/><category term='mapped'/><category term='prototype'/><title type='text'>Code tricks from Andrew Skiba</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>25</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-6764338636626369011</id><published>2011-10-16T13:39:00.006+02:00</published><updated>2011-10-16T16:41:56.578+02:00</updated><title type='text'>NetBeans project for Play - fixing the source path</title><content type='html'>&lt;p&gt;If you used NetBeans with Play framework, you could notice one feature, missing from Eclipse counterpart. In NetBeans "Navigate | Go to source" does not show the internals of Play framework, while in Eclipse the sources are readily available. So I decided to fix the command which creates NetBeans project.&lt;/p&gt;
&lt;div id="fullpost"&gt;
&lt;p&gt;The commands of Play framework are located in &lt;code&gt;framework/pym/play/commands&lt;/code&gt;, they are good old python scripts. The one responsible for &lt;code&gt;netbeansify&lt;/code&gt; command is in file &lt;code&gt;netbeans.py&lt;/code&gt;. Looking at the sources, I immediately spotted a useful shortcut: intstead of &lt;code&gt;play netbeansify&lt;/code&gt; we can run &lt;code&gt;play nb&lt;/code&gt;, I like that! :) Eclipse fans, consider switching, our command is shorter (just kidding, &lt;code&gt;eclipsify&lt;/code&gt; has a shortcut, too)&lt;/p&gt;
&lt;p&gt;Anyway, to fix the problem with "navigate to sources" I replaced the following lines:
&lt;pre name="code" class="python"&gt;
    if os.name == 'nt':
        replaceAll(os.path.join(nbproject, 'project.xml'), r'%PLAY_CLASSPATH%', ';'.join(classpath + ['nbproject\\classes']))
    else:
        replaceAll(os.path.join(nbproject, 'project.xml'), r'%PLAY_CLASSPATH%', ':'.join(classpath + ['nbproject/classes']))
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;to these lines:
&lt;pre name="code" class="python"&gt;
    newClasspath = []
    playJar = 'framework%splay-%s.jar' % (os.sep, play_env['version'])
    [newClasspath.append(x) for x in classpath if not x.endswith(playJar)]
    replaceAll(os.path.join(nbproject, 'project.xml'), r'%PLAY_CLASSPATH%', ';'.join(newClasspath + ['nbproject%sclasses'%os.sep, '%s%sframework%ssrc'%(play_env["basedir"], os.sep, os.sep)]))
&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;If you already have NetBeans project for your Play application, you need to generate it again, and reopen the project in NetBeans, to see the changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://play.lighthouseapp.com/projects/57987-play-framework/tickets/1164"&gt;I sent the fix&lt;/a&gt; to the Play framework developers, hope they accept it and you will not need to patch the script very soon.&lt;/p&gt;
&lt;p&gt;Crossposted to &lt;a href="http://www.tikalk.com/java/netbeans-project-play-fixing-source-path"&gt;Tikal Community site&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-6764338636626369011?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/6764338636626369011/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=6764338636626369011' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/6764338636626369011'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/6764338636626369011'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2011/10/netbeans-project-for-play-fixing-source.html' title='NetBeans project for Play - fixing the source path'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-4007806273627434319</id><published>2011-09-19T17:07:00.008+03:00</published><updated>2011-09-19T17:34:14.011+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='utf8'/><category scheme='http://www.blogger.com/atom/ns#' term='osx'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>UTF8 in OSX terminal</title><content type='html'>&lt;p&gt;After 3.5 years of using MacBook Pro I could not stand ???? symbols in OSX terminal anymore. Funny thing, the trigger was &lt;a href="http://michid.wordpress.com/2011/06/12/union-types/"&gt;an example of Union types&lt;/a&gt; for Scala, which used some mathematical symbols in the identifier names. So I looked for a solution, and it was so easy, I could not believe I did not do this earlier.&lt;/p&gt;
&lt;div id="fullpost"&gt;
&lt;ol&gt;
&lt;li&gt;Open /Developer/Applications/Utilities/Property List Editor. I suppose, it was installed together with developer tools from the OSX installation disk.&lt;/li&gt;
&lt;li&gt;Select File | Open in menu and open or create file environment.plist in .MacOSX directory in your home dir.&lt;/li&gt;
&lt;li&gt;Add key &lt;code&gt;LANG&lt;/code&gt; with type String and value &lt;code&gt;en_US.UTF-8&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Add key &lt;code&gt;JAVA_OPTS&lt;/code&gt; with value &lt;code&gt;-Dfile.encoding=UTF-8&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Save everything, log out and back into your account.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After doing that, I was able to use UTF-8 in Terminal. So easy!&lt;/p&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-dKokViT0B8U/TndQL3CUOEI/AAAAAAAAB2o/yeiwe3oPx8c/s1600/Screen%2BShot%2B2011-09-19%2Bat%2B17.21.01.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 299px;" src="http://1.bp.blogspot.com/-dKokViT0B8U/TndQL3CUOEI/AAAAAAAAB2o/yeiwe3oPx8c/s400/Screen%2BShot%2B2011-09-19%2Bat%2B17.21.01.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5654076021869393986" /&gt;&lt;/a&gt;
&lt;p&gt;P.S. Many kudos to blogger.com for autosaving the draft of this post. When I logged out to check this solution, I was sure the text I entered was lost. But when I opened Chrome, all the text I entered was still here. Nice!&lt;/p&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-4007806273627434319?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/4007806273627434319/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=4007806273627434319' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/4007806273627434319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/4007806273627434319'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2011/09/utf8-in-osx-terminal.html' title='UTF8 in OSX terminal'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-dKokViT0B8U/TndQL3CUOEI/AAAAAAAAB2o/yeiwe3oPx8c/s72-c/Screen%2BShot%2B2011-09-19%2Bat%2B17.21.01.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-418592896807567122</id><published>2011-09-18T16:48:00.012+03:00</published><updated>2011-09-18T18:21:16.455+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='netbeans'/><category scheme='http://www.blogger.com/atom/ns#' term='nodejs'/><title type='text'>Node.js plugin for NetBeans and daemons</title><content type='html'>Today I tried &lt;a href="http://plugins.netbeans.org/plugin/36653/nodejs"&gt;NodeJS plugin for NetBeans&lt;/a&gt; by Syntea software group. It allows to run a node straight from the NetBeans. I took an HTTP variant of "Hello, world" sample, which listens to port 8000, and responses with greetings to every request after a short delay. NetBeans stopped responding. So I downloaded the sources of this plugin to see how to fix it.&lt;p&gt;
&lt;div id="fullpost"&gt;
First of all, this is the source of my "Hello, world":
&lt;pre name="code" class="javascript"&gt;var sys = require('sys'),
    http = require('http');

    http.createServer(function (req, res) {
        setTimeout(function () {
            sys.puts('requested '+req.url)
            res.writeHead(200, {'Content-Type': 'text/plain'});
            res.end('Hello World\n');
        }, 100);
    }).listen(8000);

sys.puts('Server running at http://127.0.0.1:8000/');
&lt;/pre&gt;
So to narrow the problem, I commented out the &lt;code&gt;http.createServer&lt;/code&gt; block, so this program only lies about listening, and exits immediately. This time, NetBeans did not stuck, ran the code as expected, and printed the "Server running..." in the output window. Same happens if I do start listening, make a few requests, and then kill the node with &lt;code&gt;killall node&lt;/code&gt;.
But the output 'requested /' and 'requested /favicon.ico' which were supposed to be printed during requests, were all printed after I killed the Node.js server.&lt;p&gt;

So I started to suspect they run the server synchronously, and was right. Here is a snippet from the sources of the plugin, method &lt;code&gt;cz.kec.nb.nodejs.RunNode.performAction&lt;/code&gt;:
&lt;pre name="code" class="java"&gt;
            Process proc = Runtime.getRuntime().exec(cmd);
            proc.waitFor();                                           //    &lt;------ NetBeans gets stuck here   !!!
            BufferedReader read = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            BufferedReader readerr = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
            while (read.ready()) {
                out.println(read.readLine());
            }
            while (readerr.ready()) {

                printErrLine(readerr.readLine(), io);
                //erout.println(readerr.readLine());
            }
&lt;/pre&gt;

Unfortunately, Java designers did not provide a way to check the process status without blocking, you can only wait until process ends. So we have to waste a thread on this &lt;code&gt;proc.waitFor&lt;/code&gt;. Really annoying and wasteful.&lt;p&gt;

BTW, I looked at the implementation class, package private &lt;code&gt;java.lang.UNIXProcess&lt;/code&gt;, and it has private &lt;code&gt;hasExited&lt;/code&gt; field. Many thanks to whoever decided to make this unaccessible for the rest of us, all the wasted threads will torture you for eternity, when the time comes! Mwahaha!&lt;p&gt;

Anyway, in addition to this thread, necessary because of a lame API of java.lang.Process, another thread is necessary for reading and printing whatever Node.js application wants to print. I'm pretty sure, that's not a correct way for a NetBeans plugin to deal with long-running tasks, and will be glad if someone shows me a correct way. But it worked for me :-). So, after my changes the code looked like this:
&lt;pre name="code" class="java"&gt;
            final Process proc = Runtime.getRuntime().exec(cmd);
            final BufferedReader read = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            final BufferedReader readerr = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
            final AtomicBoolean done = new AtomicBoolean(false);
            new Thread(new Runnable() {
                public void run() {
                    try {
                        while (!done.get()) {
                            while (read.ready()) {
                                out.println(read.readLine());
                            }
                            while (readerr.ready()) {
                                printErrLine(readerr.readLine(), io);
                                //erout.println(readerr.readLine());
                            }
                            Thread.sleep(500);
                        }
                        
                        read.close();
                        readerr.close();
                    
                    } catch (Exception ex) {
                        Exceptions.printStackTrace(ex);
                    }
                }
            }).start();
            new Thread(new Runnable() {
                public void run() {
                    try {
                        proc.waitFor();
                    } catch (InterruptedException ex) {
                        Exceptions.printStackTrace(ex);
                    }
                    finally {
                        done.set(true);
                    }
                }
            }).start();&lt;/pre&gt;

Cross-posted to &lt;a href="http://www.tikalk.com"&gt;Tikal community site&lt;/a&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-418592896807567122?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/418592896807567122/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=418592896807567122' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/418592896807567122'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/418592896807567122'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2011/09/nodejs-plugin-for-netbeans-and-daemons.html' title='Node.js plugin for NetBeans and daemons'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-8332991768119210734</id><published>2009-05-07T22:03:00.005+03:00</published><updated>2009-05-09T00:43:33.760+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='netbeans'/><category scheme='http://www.blogger.com/atom/ns#' term='debugging'/><category scheme='http://www.blogger.com/atom/ns#' term='appengine'/><title type='text'>Debugging AppEngine application on NetBeans</title><content type='html'>&lt;a href="http://andskiba.blogspot.com/2009/04/appengine-project-on-netbeans.html"&gt;Earlier&lt;/a&gt; I explained how to open and compile a Java AppEngine application on NetBeans. Now let's see what it takes to debug it.&lt;br/&gt;If you are familiar with remote debug mode of NetBeans, it's actually very easy to connect to a running AppEngine &lt;code&gt;dev_appserver&lt;/code&gt;. But first we should open a port to connect to. This is how it's done on Windows.
&lt;div id="fullpost"&gt;
Edit AppEngine Java SDK &lt;code&gt;dev_appserver&lt;/code&gt; script. It's located in &lt;code&gt;appengine-java-sdk-1.2.0/bin&lt;/code&gt; folder. There are two versions of this script: for Windows (&lt;code&gt;dev_appserver.cmd&lt;/code&gt;) and for Unix/Linux/OSX (&lt;code&gt;dev_appserver.sh&lt;/code&gt;). There is also appcfg script, which we will not change. Open the script corresponding to your operating system (File|Open File... in NetBeans). The Windows command script looks like this:
&lt;pre name="code" class="xml"&gt;@java -cp "%~dp0\..\lib\appengine-tools-api.jar" ^
    com.google.appengine.tools.KickStart ^
       com.google.appengine.tools.development.DevAppServerMain %*&lt;/pre&gt;You need to edit this file to look like this:&lt;pre name="code" class="xml"&gt;@java -cp "%~dp0\..\lib\appengine-tools-api.jar" ^
    com.google.appengine.tools.KickStart ^
       --jvm_flag=-Xdebug ^
       --jvm_flag=-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n ^
       com.google.appengine.tools.development.DevAppServerMain %*&lt;/pre&gt;This will open port 8000 so a remote debugger can attach. Now open a command prompt and change current directory to &lt;code&gt;appengine-java-sdk-1.2.0&lt;/code&gt;. Then run dev_appserver with your application, for example by typing &lt;code&gt;bin\dev_appserver.cmd demos\guestbook\war&lt;/code&gt;. This will run the &lt;code&gt;dev_appserver&lt;/code&gt; as usual, but this time the debug port is open. It should print on the very first line something like: &lt;code&gt;Listening for transport dt_socket at address: 8000&lt;/code&gt;. Now attach to this port from NetBeans. In &lt;code&gt;Debug&lt;/code&gt; menu select &lt;code&gt;Attach Debugger...&lt;/code&gt;. This will open the following dialog box:&lt;br/&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_yXdc5xeEFQ4/SgM85VpvqvI/AAAAAAAABWU/S4DWjo-FsOU/s1600-h/attach_debugger.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 154px;" src="http://2.bp.blogspot.com/_yXdc5xeEFQ4/SgM85VpvqvI/AAAAAAAABWU/S4DWjo-FsOU/s320/attach_debugger.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5333173339499244274" /&gt;&lt;/a&gt;&lt;br/&gt;Fill the values like on the screen shot, and press OK. If the debugger attaches correctly, the stop and pause buttons in the toolbar and the corresponding menu items in Debug menu should become enabled.&lt;br/&gt;Let's set a break point now. Press Ctrl-O and type "Greeting" to open a persistent class and set break point in &lt;code&gt;getAuthor&lt;/code&gt; method. Now go to &lt;code&gt;http://localhost:8080/guestbook.jsp&lt;/code&gt; in your browser and NetBeans should stop on this break point for every record in the guest book. Enjoy!
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-8332991768119210734?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/8332991768119210734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=8332991768119210734' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/8332991768119210734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/8332991768119210734'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2009/05/debugging-appengine-application-on.html' title='Debugging AppEngine application on NetBeans'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_yXdc5xeEFQ4/SgM85VpvqvI/AAAAAAAABWU/S4DWjo-FsOU/s72-c/attach_debugger.PNG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-3302554676497615106</id><published>2009-04-17T22:49:00.013+03:00</published><updated>2009-05-09T00:43:17.289+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='netbeans'/><category scheme='http://www.blogger.com/atom/ns#' term='appengine'/><title type='text'>AppEngine project on NetBeans</title><content type='html'>&lt;i&gt;This is a beginning of discussion, continued &lt;a href="http://andskiba.blogspot.com/2009/05/debugging-appengine-application-on.html"&gt;here&lt;/a&gt;&lt;/i&gt;&lt;p&gt;
Recently Google released an early look of AppEngine for Java. It includes an Eclipse plugin for developing with AppEngine Java SDK. I wanted to check is it possible to develop AppEngine Java application using NetBeans
&lt;div id="fullpost"&gt;
&lt;h3&gt;Environment&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;Sun JDK 1.6.0_12&lt;/li&gt;
&lt;li&gt;NetBeans &lt;strong&gt;6.7 M2&lt;/strong&gt; (pre-release)&lt;/li&gt;
&lt;li&gt;gae-java-sdk-1.2.0&lt;/li&gt;
&lt;/ol&gt;&lt;h3&gt;Opening project&lt;/h3&gt;Let's start with basic AppEngine demo Guestbook. It's located in demos/guestbook directory of gae-sdk-java.&lt;h4&gt;Create project wizard&lt;/h4&gt;Start the wizard with File|New Project.&lt;h4&gt;Step 1&lt;/h4&gt;Select options like this:&lt;br/&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_yXdc5xeEFQ4/SejoJfA4QWI/AAAAAAAABVE/n1qSYtDnoYs/s1600-h/new_project.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 226px;" src="http://4.bp.blogspot.com/_yXdc5xeEFQ4/SejoJfA4QWI/AAAAAAAABVE/n1qSYtDnoYs/s320/new_project.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5325761809007264098" /&gt;&lt;/a&gt;&lt;h4&gt;Step 2&lt;/h4&gt;Enter the location of the project in the edit box, or click browse:&lt;br/&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_yXdc5xeEFQ4/SejqoJ_MtiI/AAAAAAAABVw/TZ_KhJS1T7k/s1600-h/new_project2.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 226px;" src="http://3.bp.blogspot.com/_yXdc5xeEFQ4/SejqoJ_MtiI/AAAAAAAABVw/TZ_KhJS1T7k/s320/new_project2.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5325764534962271778" /&gt;&lt;/a&gt;&lt;br/&gt;The rest of the lines will be filled automatically.&lt;h4&gt;Step 3&lt;/h4&gt;Leave the default options on the "Build and Run Actions" page.&lt;h4&gt;Step 4&lt;/h4&gt;Don't change anything on the "Web Sources" page.&lt;h4&gt;Step 5&lt;/h4&gt;Click "Next" on "Source Package Folders" page.&lt;h4&gt;Step 6&lt;/h4&gt;Click "Add JAR/Folder" on the "Java Sources Classpath" page and add all jars located in war/WEB-INF/lib folder under guestbook root:&lt;br/&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_yXdc5xeEFQ4/SejsQGr4m9I/AAAAAAAABV4/zb1rF79LgCM/s1600-h/new_project3.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 262px;" src="http://3.bp.blogspot.com/_yXdc5xeEFQ4/SejsQGr4m9I/AAAAAAAABV4/zb1rF79LgCM/s320/new_project3.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5325766320782351314" /&gt;&lt;/a&gt;&lt;br/&gt;Click Finish to leave default settings on the last two pages.&lt;h3&gt;Fixing classpath&lt;/h3&gt;The resulting project will look like this:&lt;br/&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_yXdc5xeEFQ4/Sejuic-qMaI/AAAAAAAABWA/4MyX38Zj3gc/s1600-h/new_project4.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 245px; height: 208px;" src="http://2.bp.blogspot.com/_yXdc5xeEFQ4/Sejuic-qMaI/AAAAAAAABWA/4MyX38Zj3gc/s320/new_project4.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5325768835027579298" /&gt;&lt;/a&gt;&lt;br/&gt;Two Servlet files have errors because NetBeans has limited abilities on parsing ant build files. It could not extract the compile time dependencies from &lt;code&gt;build.xml&lt;/code&gt;, so we pointed to WEB-INF/lib libraries at Step 6. But one of the compile dependencies (Servlet API jar) is located outside of the project tree. It's because this jar is supplied by the application server. In my pre-release version of NetBeans the UI is not able to use dependencies outside of the project tree, but it's easy to work around.&lt;h3&gt;Edit project.xml&lt;/h3&gt;Press Ctrl-F2 or select Window|Files to switch to files panel. You see all files under your project root:&lt;br/&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_yXdc5xeEFQ4/Sejx9eUvgAI/AAAAAAAABWI/nGcuAW5L1WA/s1600-h/new_project5.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 250px; height: 156px;" src="http://3.bp.blogspot.com/_yXdc5xeEFQ4/Sejx9eUvgAI/AAAAAAAABWI/nGcuAW5L1WA/s320/new_project5.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5325772597779988482" /&gt;&lt;/a&gt;&lt;br/&gt;Click on + sign to open nbproject, right-click on project.xml and select Edit. This opens internal NetBeans project file which contains all the settings we selected in the wizard. Find line which contains &lt;code&gt;&amp;lt;classpath&amp;gt;&lt;/code&gt; element near the end of the file. Go to the end of the line and add the path Servlet API jar. This jar is located in lib/shared folder under the Google AppEngine Java SDK folder, in my case the full path was &lt;code&gt;C:\work\appengine-java-sdk-1.2.0\lib\shared\geronimo-servlet_2.5_spec-1.2.jar&lt;/code&gt;&lt;p/&gt;Press Ctrl-S to save the &lt;code&gt;project.xml&lt;/code&gt; file and return to Projects pane (press Ctrl-1). Now NetBeans is happy and no errors are reported.&lt;h3&gt;Running the application&lt;/h3&gt;You can run this application as you run any project in NetBeans. If this is the main project, simply press F6. When the project is running, you will see the following line in the Output window: &lt;code&gt;The server is running at http://localhost:8080/&lt;/code&gt;. You can enter this URL in a browser and start using the Guestbook application. &lt;a href="http://andskiba.blogspot.com/2009/05/debugging-appengine-application-on.html"&gt;In this post&lt;/a&gt; you can find out how to debug AppEngine java web application using NetBeans.
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-3302554676497615106?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/3302554676497615106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=3302554676497615106' title='14 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/3302554676497615106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/3302554676497615106'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2009/04/appengine-project-on-netbeans.html' title='AppEngine project on NetBeans'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_yXdc5xeEFQ4/SejoJfA4QWI/AAAAAAAABVE/n1qSYtDnoYs/s72-c/new_project.PNG' height='72' width='72'/><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-5642311225605942051</id><published>2009-04-11T17:19:00.009+03:00</published><updated>2009-04-11T18:35:39.389+03:00</updated><title type='text'>DelayQueue via interceptor</title><content type='html'>In the &lt;a href="http://andskiba.blogspot.com/2009/04/delayqueuechannel-for-spring.html"&gt;previous post&lt;/a&gt; I published a simple solution for using &lt;code&gt;java.util.concurrent.DelayQueue&lt;/code&gt; with Spring Integration queue channel. Then Iwein Fuld &lt;a href="http://forum.springsource.org/showpost.php?p=235949&amp;postcount=4"&gt;suggested&lt;/a&gt; a nice improvement of namespace configuration. I liked the idea, but if the underlying queue is &lt;code&gt;DelayQueue&lt;/code&gt; how to ensure all elements implement &lt;code&gt;Delayed&lt;/code&gt; interface if I don't override &lt;code&gt;doSend&lt;/code&gt; method and use the standard &lt;code&gt;QueueChannel&lt;/code&gt;? That can be done with a &lt;code&gt;ChannelInterceptor&lt;/code&gt;. I really like the way the guys from Spring Integration designed the API, there is an extension point just where you need it.
&lt;p&gt;So if Iwein's proposition will be implemented, the configuration of the delay queue will look like this:&lt;pre name="code" class="xml"&gt;&lt;channel id="delayChannel"&gt;
  &lt;queue queue-class="java.util.concurrency.DelayQueue"&gt;&lt;/queue&gt;
  &lt;interceptors&gt;
    &lt;ref bean="delay10min"&gt;&lt;/ref&gt;&lt;!--Long form of closing tag to make Blogger happy--&gt;
  &lt;/interceptors&gt;
&lt;/channel&gt;

&lt;bean id="delay10min" class="SimpleDelayInterceptor" p:delay="10"
  p:timeUnit="MINUTES"&gt;
&lt;/bean&gt;&lt;/pre&gt;&lt;p&gt;This also solves the problem with different delays for messages in the same queue. I made an example with &lt;code&gt;HeaderDelayInterceptor&lt;/code&gt;, which looks at message header to set the time out.
&lt;div id="fullpost"&gt;
It can be configured similar to &lt;code&gt;SimpleDelayInterceptor&lt;/code&gt;:&lt;pre name="code" class="xml"&gt;&lt;bean id="delay10min" class="SimpleDelayInterceptor" p:delay="10" p:timeUnit="MINUTES"/&gt;&lt;/pre&gt;While we are waiting for the &lt;a href="http://jira.springframework.org/browse/INT-634"&gt;&lt;code&gt;queue-class&lt;/code&gt; feature&lt;/a&gt; to be implemented, we can create channel instances as usual Spring beans:&lt;pre name="code" class="xml"&gt;&lt;bean id="delayQueue" scope="prototype" class="java.util.concurrent.DelayQueue"/&gt;

&lt;bean id="delayChannel" class="org.springframework.integration.channel.QueueChannel"&gt;
  &lt;constructor-arg ref="delayQueue"/&gt;
  &lt;property name="interceptors"&gt;
    &lt;util:list&gt;
      &lt;ref bean="delay10min"/&gt;
    &lt;/util:list&gt;
  &lt;/property&gt;
&lt;/bean&gt;&lt;/pre&gt;The important thing to remember is to put this interceptor the last, if you need other interceptors. This is important, because other interceptors might create Message instances not implementing Delayed, and the &lt;code&gt;DelayQueue&lt;/code&gt; will throw &lt;code&gt;ClassCastException&lt;/code&gt;. While I'm looking for a better place to host source code, it will be listed here:&lt;pre name="code" class="java"&gt;/**
 * Wraps messages sent to the channel to implement Delayed interface. Required
 * for queue channel created with DelayQueue instance. Causes messages to wait
 * in the queue for the specified delay.
 * @author Andrew Skiba skibaa@gmail.com
 * Use for any purpose at your own risk.
 */
public class SimpleDelayInterceptor extends ChannelInterceptorAdapter {

    private long delay;
    private TimeUnit timeUnit;

    public SimpleDelayInterceptor(long delay, TimeUnit timeUnit) {
        this.delay = delay;
        this.timeUnit = timeUnit;
    }

    @Override
    public Message&lt;?&gt; preSend(Message&lt;?&gt; message, MessageChannel channel) {
        final long sendingTime = System.currentTimeMillis();
        return new DelayedMessageAdapter(message) {
            public long getDelay(TimeUnit unit) {
                long millisPassed = System.currentTimeMillis() - sendingTime;
                long unitsPassed = unit.convert(millisPassed, TimeUnit.MILLISECONDS);
                long delayInGivenUnits = unit.convert(delay, timeUnit);
                return delayInGivenUnits - unitsPassed;
            }
        };
    }
}

/**
 * QueueChannel requires its elements to implement Message, and
 * DelayQueue requires its elements to implement Delayed. This
 * class implements both to satisfy these requirements. For Mesage
 * interface it acts as a proxy and forwards all calls to the wrapped Message.
 * @author Andrew Skiba skibaa@gmail.com
 * Use for any purpose at your own risk.
 */
public abstract class DelayedMessageAdapter&lt;T&gt; implements Delayed, Message&lt;T&gt; {
    private Message&lt;T&gt; wrappedMessage;

    public DelayedMessageAdapter(Message wrappedMessage) {
        this.wrappedMessage = wrappedMessage;
    }

    protected Message&lt;T&gt; getMessage() {
        return wrappedMessage;
    }

    public abstract long getDelay(TimeUnit unit);

    public int compareTo(Delayed o) {
        return new Long(getDelay(TimeUnit.NANOSECONDS))
                .compareTo(o.getDelay(TimeUnit.NANOSECONDS));
    }

    public MessageHeaders getHeaders() {
        return wrappedMessage.getHeaders();
    }

    public T getPayload() {
        return wrappedMessage.getPayload();
    }

    @Override
    public String toString() {
        return wrappedMessage.toString();
    }
}

/**
 * Wraps messages sent to the channel to implement Delayed interface. Required
 * for queue channel created with DelayQueue instance. Causes messages to wait
 * in the queue till System.currentTimeInMillis() reaches the value specified
 * in message header. The header name is customizable.
 * @author Andrew Skiba skibaa@gmail.com
 * Use for any purpose at your own risk.
 */
public class HeaderDelayInterceptor extends ChannelInterceptorAdapter {
    String headerName;

    public HeaderDelayInterceptor(String headerName) {
        this.headerName = headerName;
    }

    @Override
    public Message&lt;?&gt; preSend(Message&lt;?&gt; message, MessageChannel channel) {
        //fail early if header is missing or incorrect
        Object waitTill=message.getHeaders().get(headerName);
        if (waitTill==null)
            throw new IllegalArgumentException("HeaderDelayInterceptor expects " +
                "header with name:" + headerName +
                " which was not found in message:" + message);
        if (!(waitTill instanceof Long))
            throw new IllegalArgumentException("HeaderDelayInterceptor expects " +
                "Long value in header with name:" + headerName +
                " incompatible type found in message:" + message);
        //everything looks OK, create a wrapped message
        return new DelayedMessageAdapter(message){
            public long getDelay(TimeUnit unit) {
                Long waitTill=(Long)getMessage().getHeaders().get(headerName);
                long delayRemained=waitTill-System.currentTimeMillis();
                return unit.convert(delayRemained, TimeUnit.MILLISECONDS);
            }
        };
    }
}&lt;/pre&gt;And the unit test is here:&lt;pre name="code" class="java"&gt;/**
 * @author Andrew Skiba skibaa@gmail.com
 * Use for any purpose at your own risk.
 */
public class DelayQueueChannelTests {
    static Logger logger = Logger.getLogger(DelayQueueChannelTests.class.getName());

    @Test
    public void testSimpleDelay() throws Exception {
        final AtomicBoolean messageReceived = new AtomicBoolean(false);
        final CountDownLatch latch = new CountDownLatch(1);
        final QueueChannel channel = new QueueChannel(new DelayQueue());
        channel.addInterceptor(new SimpleDelayInterceptor(100, TimeUnit.MILLISECONDS));
        new Thread(new Runnable() {

            public void run() {
                Message&lt;Long&gt; message = (Message&lt;Long&gt;)channel.receive();
                assertTrue(message instanceof DelayedMessageAdapter);
                messageReceived.set(true);
                latch.countDown();
                float waitTime=(System.currentTimeMillis()-message.getPayload())/1000.F;
                logger.info("waited for "+waitTime+" seconds ");
            }
        }).start();
        assertFalse(messageReceived.get());
        channel.send(new GenericMessage&lt;Long&gt;(System.currentTimeMillis()));
        assertFalse(messageReceived.get());
        latch.await(25, TimeUnit.MILLISECONDS);
        assertFalse(messageReceived.get());
        latch.await(1, TimeUnit.SECONDS);
        assertTrue(messageReceived.get());
    }

    private final static String HEADER_NAME="test.waitTill";

    @Test
    public void testMessageDelay() throws Exception {
        final AtomicBoolean [] messagesReceived = new AtomicBoolean[] {
            new AtomicBoolean(false), new AtomicBoolean(false)
        };
        final CountDownLatch latch1 = new CountDownLatch(1);
        final CountDownLatch latch2 = new CountDownLatch(1);
        final QueueChannel channel = new QueueChannel(new DelayQueue());
        channel.addInterceptor(new HeaderDelayInterceptor(HEADER_NAME));
        new Thread(new Runnable() {

            public void run() {
                Message&lt;Integer&gt; message = (Message&lt;Integer&gt;)channel.receive();
                assertTrue(message instanceof DelayedMessageAdapter);
                messagesReceived[message.getPayload()].set(true);
                latch1.countDown();
                message = (Message&lt;Integer&gt;)channel.receive();
                assertTrue(message instanceof DelayedMessageAdapter);
                messagesReceived[message.getPayload()].set(true);
                latch2.countDown();
            }
        }).start();
        assertFalse(messagesReceived[0].get());
        assertFalse(messagesReceived[1].get());
        long now=System.currentTimeMillis();
        channel.send(MessageBuilder.withPayload(0).setHeader(HEADER_NAME, now+200).build());
        channel.send(MessageBuilder.withPayload(1).setHeader(HEADER_NAME, now+100).build());
        assertFalse(messagesReceived[0].get());
        assertFalse(messagesReceived[1].get());
        latch1.await(25, TimeUnit.MILLISECONDS);   //not enough time for either message
        assertFalse(messagesReceived[0].get());
        assertFalse(messagesReceived[1].get());
        latch1.await(170, TimeUnit.MILLISECONDS);         //the second message should be ready before the first
        assertFalse(messagesReceived[0].get());
        assertTrue(messagesReceived[1].get());
        latch2.await(200, TimeUnit.MILLISECONDS);
        assertTrue(messagesReceived[0].get());
    }
}&lt;/pre&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-5642311225605942051?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/5642311225605942051/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=5642311225605942051' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/5642311225605942051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/5642311225605942051'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2009/04/delayqueue-via-interceptor.html' title='DelayQueue via interceptor'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-3781184450899241048</id><published>2009-04-11T11:16:00.018+03:00</published><updated>2009-04-12T00:29:01.981+03:00</updated><title type='text'>DelayQueueChannel for Spring Integration</title><content type='html'>&lt;i&gt;This is a beginning of discussion, continued &lt;a href="http://andskiba.blogspot.com/2009/04/delayqueue-via-interceptor.html"&gt;here&lt;/a&gt;.&lt;/i&gt;
&lt;p&gt;&lt;a href="http://www.springsource.org/spring-integration"&gt;Spring Integration&lt;/a&gt; is an amazing project. It allows with a few lines of code or with a small Spring XML configuration to establish a powerful Enterprise Application Integration server. We are used to think about EAI as a heavy weight solution, but with Spring Integration it's a modest library deployed together with your console or web application. I'm really excited about its ease of use.
&lt;p&gt;The central component in this framework is a message channel. It has a few implementations, most basic of which are direct channel and queue channel. Direct channel allows processing in the same thread, and queue channel holds messages until a processor will take them for processing.
&lt;p&gt;When a message processing fails, it's usually desirable to wait before retrying. In EAI your application often depends on remote servers, which may be temporarily unavailable. If you try the failing operation in a few minutes, it has better chances to succeed.
&lt;p&gt;Out of the box, Spring Integration does not provide a facility to delay messages for such a long period. While it's easy to insert a sleeping in the middle of processing, sleeping for long periods will waste precious thread resources of the server. So I extended Spring Integration queue channel to support delays.
&lt;div id="fullpost"&gt;
&lt;p&gt;Fortunately, Java has a standard DelayQueue, a part of java concurrency API, one of the best in Java. Used correctly, it performs very fast and is relatively error-proof.
&lt;p&gt;The basic Spring Integration queue channel was created with extensibility in mind. It has a constructor accepting a &lt;code&gt;java.util.concurrent.BlockingQueue&lt;/code&gt; instance, and &lt;code&gt;DelayQueue&lt;/code&gt; is just an implementation of &lt;code&gt;BlockingQueue&lt;/code&gt;. So what's left is to glue this great components together to do the job.&lt;pre name="code" class="java"&gt;/**
 * @author Andrew Skiba skibaa@gmail.com
 * Use for any purpose at your own risk.
 */
public class SimpleDelayQueueChannel extends QueueChannel {
    private long delay;
    private TimeUnit timeUnit;

    /**
     * QueueChannel requires its elements to implement Message, and
     * DelayQueue requires its elements to implement Delayed. This
     * class implements both to satisfy these requirements. For Mesage
     * interface it acts as a proxy and forwards all calls to the wrapped Message.
     */
    protected class DelayedMessage implements Delayed, Message {
        long createdClock;
        Message wrappedMessage;

        public DelayedMessage(Message wrappedMessage) {
            this.wrappedMessage = wrappedMessage;
            createdClock = System.currentTimeMillis();
        }

        public long getDelay(TimeUnit unit) {
            long millisPassed=System.currentTimeMillis()-createdClock;
            long unitsPassed=unit.convert(millisPassed, TimeUnit.MILLISECONDS);
            long delayInGivenUnits=unit.convert(delay, timeUnit);
            return delayInGivenUnits-unitsPassed;
        }

        public int compareTo(Delayed o) {
            if (o instanceof DelayedMessage)
                return new Long(createdClock)
                        .compareTo(((DelayedMessage)o).createdClock);

            return new Long(getDelay(TimeUnit.NANOSECONDS))
                    .compareTo(o.getDelay(TimeUnit.NANOSECONDS));
        }

        public MessageHeaders getHeaders() {
            return wrappedMessage.getHeaders();
        }

        public Object getPayload() {
            return wrappedMessage.getPayload();
        }

    }

    public SimpleDelayQueueChannel(long delay, TimeUnit timeUnit) {
        /* QueueChannel expects a queue capable of holding any Message,
         * but DelayQueue requires its elements to implement Delayed interface.
         * So we MUST override doSend so we control what is inserted into
         * the queue.
         */
        super((BlockingQueue)new DelayQueue());
        this.delay=delay;
        this.timeUnit=timeUnit;
    }

    @Override
    protected boolean doSend(Message&lt;?&gt; message, long timeout) {
        return super.doSend(new DelayedMessage(message), timeout);
    }
}&lt;/pre&gt;This class was created with a brevity on mind. It has a few shortcomings. The most significant is hard coded delay calculation, based on the system time when a message is inserted into the queue. I want to extract this logic into delay strategy class. This will allow the same queue to hold elements with different delays, for example.
&lt;p&gt;And the following is the unit test for the simple delay queue channel.&lt;pre name="code" class="java"&gt;public class DelayQueueChannelTests {
    static Logger logger = Logger.getLogger(DelayQueueChannelTests.class.getName());
    @Test
    public void testSimpleSendAndReceive() throws Exception {
        final AtomicBoolean messageReceived = new AtomicBoolean(false);
        final CountDownLatch latch = new CountDownLatch(1);
        final SimpleDelayQueueChannel channel = new SimpleDelayQueueChannel(100, TimeUnit.MILLISECONDS);
        new Thread(new Runnable() {

            public void run() {
                Message&lt;Long&gt; message = (Message&lt;Long&gt;)channel.receive();
                messageReceived.set(true);
                latch.countDown();
                assertTrue(message instanceof SimpleDelayQueueChannel.DelayedMessage);
                float waitTime=(System.currentTimeMillis()-message.getPayload())/1000.F;
                logger.fine("waited for "+waitTime+" seconds ");
            }
        }).start();
        assertFalse(messageReceived.get());
        channel.send(new GenericMessage&lt;Long&gt;(System.currentTimeMillis()));
        assertFalse(messageReceived.get());
        latch.await(25, TimeUnit.MILLISECONDS);
        assertFalse(messageReceived.get());
        latch.await(1, TimeUnit.SECONDS);
        assertTrue(messageReceived.get());
    }
}
//funny how blogspot lower-cases and closes &lt;long&gt; "tags" :-)
//don't copy them to java, and change long to Long in angle brackets in the code.
&lt;/pre&gt;Do you have any comments, suggestions, questions? Don't hesitate to comment here, &lt;a href="http://forum.springsource.org/showthread.php?t=70292"&gt;there&lt;/a&gt; or &lt;a href="mailto:skibaa@gmail.com"&gt;by e-mail&lt;/a&gt;.
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-3781184450899241048?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/3781184450899241048/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=3781184450899241048' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/3781184450899241048'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/3781184450899241048'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2009/04/delayqueuechannel-for-spring.html' title='DelayQueueChannel for Spring Integration'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-4892852934063074291</id><published>2009-02-04T23:25:00.004+02:00</published><updated>2009-02-05T00:00:55.503+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='logging'/><category scheme='http://www.blogger.com/atom/ns#' term='dev_appserver'/><category scheme='http://www.blogger.com/atom/ns#' term='appengine'/><title type='text'>AppEngine dev_appserver logging</title><content type='html'>For some weird reason I cannot debug on dev_appserver. My breakpoints are simply ignored. So I placed logging code in troublesome places. By default, dev_appserver sets the root logger level to INFO. If run with &lt;code&gt;-d&lt;/code&gt; option, it's DEBUG, and it logs all environment for every request. I tried to set the root level to WARNING or higher, but it was either ignored or made logger totally silent. So the best option I found is to leave the root level to INFO and to use module loggers for application-specific DEBUG messages. In the &lt;code&gt;__main__&lt;/code&gt; function I added the following lines:&lt;pre name="code" class="python"&gt;logger=logging.getLogger("my")
logger.setLevel(logging.DEBUG)&lt;/pre&gt;Every module has to get its own logger like this:&lt;pre name="code" class="python"&gt;# module engine.py
import logging

logger=logging.getLogger("my.engine")&lt;/pre&gt;Because of the dot separator &lt;code&gt;my.engine&lt;/code&gt; logger inherits the configuration of &lt;code&gt;my&lt;/code&gt; logger, so DEBUG messages are printed on the console.&lt;p&gt;I also did not find the correct way to add handlers to my logger, because if I change the logger initialization like this:&lt;pre name="code" class="python"&gt;logger=logging.getLogger("my")
logger.setLevel(logging.DEBUG)
ch=logging.StreamHandler()
logger.addHandler(ch)&lt;/pre&gt;It adds a new handler for every request, so each message is printed many times. Of course, it's possible to remove the handler after &lt;code&gt;run_wsgi_app&lt;/code&gt; call, but it looked weird to add and immediately remove the handler every time. If you know a better way to configure logging with dev_appengine, please let me know.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-4892852934063074291?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/4892852934063074291/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=4892852934063074291' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/4892852934063074291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/4892852934063074291'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2009/02/appengine-devappserver-logging.html' title='AppEngine dev_appserver logging'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-4625323465653000040</id><published>2009-02-01T23:25:00.003+02:00</published><updated>2009-02-02T00:09:39.126+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='scriptaculous'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='prototype'/><title type='text'>Scriptaculous and AJAX</title><content type='html'>I started with a task which seemed to be typical when script.aculo.us is used with Prototype &lt;code&gt;Ajax.Request&lt;/code&gt;. The old content nicely disappears with one of scriptaculous effects, AJAX request is sent and when result is available it appears with another effect. Let's use &lt;code&gt;Effect.SlideUp&lt;/code&gt; and &lt;code&gt;Effect.SlideDown&lt;/code&gt; for these effects, and &lt;code&gt;&amp;lt;div id='main_div'&amp;gt;&lt;/code&gt; for the content. Straight-forward solution looks like this:&lt;pre name="code" class="jscript"&gt;new Effect.SlideUp('main_div', {
      afterFinish: function () {
        new Ajax.Request(url, {
            method:'get',
            onSuccess: function(transport){
              $('main_div').innerHTML=transport.responseText;
              new Effect.SlideDown('main_div');
            }
          })
      }
    });&lt;/pre&gt;Failure handling is omitted for brevity. This solution works, but has a significant problem: the request is sent only after the slide up effect is finished, so the user waits more than necessary. I wanted to send the AJAX request immediately, so the response might be ready when the slide up is finished. But it's impossible to know which will finish first.
&lt;div id="fullpost"&gt;
My next try was to start slide up and immediately send the request, like this:&lt;pre name="code" class="jscript"&gt;    new Effect.SlideUp('main_div');
    new Ajax.Request(url,
    {
        method:'get',
        onSuccess: function(transport){
             $('main_div').innerHTML=transport.responseText;
             new Effect.SlideDown('main_div', {queue: 'end'});
        }
    });&lt;/pre&gt;Unfortunately, it did not work correctly. If the response comes before the slide up vanished the &lt;code&gt;main_div&lt;/code&gt;, it will be replaced with the new content for a moment, then disappear and come nicely with the slide down effect. So the problem here is that replacing the content and slide down must start only when both slide up and the AJAX are finished. I ended up with the following:&lt;pre name="code" class="jscript"&gt;    var hideEffectComplete=false;
    var ajaxResult=null;
    new Effect.SlideUp('main_div', {
        afterFinish: function () {
            complete=true;
            if (ajaxResult != null) {
                $('main_div').innerHTML=ajaxResult;
                new Effect.SlideDown('main_div');
            }
        }
    });
    new Ajax.Request(url,
    {
        method:'get',
        onSuccess: function(transport){
          ajaxResult=transport.responseText;
          if (hideEffectComplete) {
             $('main_div').innerHTML=ajaxResult;
             new Effect.SlideDown('main_div');
          }
        }
    });&lt;/pre&gt;It works better, but it's long, ugly and redundant. Also it makes problems when a user makes a few actions fast, things are just messed up. Does anybody have a better idea how to synchronize AJAX and script.aculo.us?
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-4625323465653000040?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/4625323465653000040/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=4625323465653000040' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/4625323465653000040'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/4625323465653000040'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2009/02/scriptaculous-and-ajax.html' title='Scriptaculous and AJAX'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-2451113241275726124</id><published>2009-01-31T21:18:00.008+02:00</published><updated>2009-02-01T21:48:45.159+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='jpa'/><category scheme='http://www.blogger.com/atom/ns#' term='superclass'/><category scheme='http://www.blogger.com/atom/ns#' term='mapped'/><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><title type='text'>Inherited classes in Hibernate</title><content type='html'>Few days ago I made some refactoring of a Hibernate based JavaEE application. There was a table and a view on that table which included all columns, like this:&lt;pre name="code" class="sql"&gt;CREATE TABLE Person (
  Id NUMBER,
  Name VARCHAR(10),
  BirthDate DATE,
);

CREATE VIEW PersonExtended AS
  SELECT p.*, YearsFromNow(p.BirthDate) AS Age FROM Person p;&lt;/pre&gt;Assuming we have a corresponding function this view will include all columns from Person and have an additional column named Age. Before refactoring, there were 2 corresponding entity classes. In the actual code entities have full annotated getters and corresponding setters, but for readability I'll use the most compact and not recommended format here:&lt;pre name="code" class="java"&gt;//Person.java

@Entity
class Person {
  @Id long id;
  String name;
  Date birthDate;
}

//PersonExtended.java

@Entity
class PersonExtended {
  @Id long id;
  String name;
  Date birthDate;
  int age;
}&lt;/pre&gt;&lt;div id="fullpost"&gt;Trying to remove the code duplication I changed the entities as following:&lt;pre name="code" class="java"&gt;//Person.java

@Entity
@Inheritance (strategy=InheritanceType.TABLE_PER_CLASS)
class Person {
  @Id long id;
  String name;
  Date birthDate;
}

//PersonExtended.java

@Entity
class PersonExtended extends Person {
  int age;
}&lt;/pre&gt;Alone from the cosmetic improvement, this change also allowed to use the same code for working with both entities. But this polymorphism also created new problems. For example, query fetching all data from Person generated the following SQL:&lt;pre name="code" class="sql"&gt;SELECT p.*, NULL as Age, 1 as discriminator from Person p
  UNION
SELECT pe.*, 2 as discriminator from PersonExtended pe;&lt;/pre&gt;For clarity I replaced with * the actual field list from Hibernate generated SQL. So what happened? Hibernate treats PersonExtended as kind of Person, so the result of this query would be all records from Person followed by all records of PersonExtended! They will have correct type in Java, by the way, thanks to discriminator columns generated by Hibernate. Anyway, it's not what we wanted and it's a &lt;strong&gt;regression&lt;/strong&gt; (a new bug) after the refactoring. To fix that bug we must tell Hibernate that PersonExtended is not considered Person. I used a &lt;code&gt;MappedSuperclass&lt;/code&gt; for that:&lt;pre name="code" class="java"&gt;//AbstractPersonBase.java

@MappedSuperclass
abstract class AbstractPersonBase {
  @Id long id;
  String name;
  Date birthDate;
}

//Person.java

@Entity
Person extends AbstractPersonBase {
  //empty, all person data is defined in the superclass
}

//PersonExtended.java

@Entity
PersonExtended extends AbstractPersonBase {
  int age;
}&lt;/pre&gt;This code correctly defines the relation between PersonExtended and Person. They have common part but should not be used one instead of the other. This solution with an abstract base has no problem with fetching different entities in the same query. On the other hand, it allows using AbstractPersonBase in cases where both entities are processed in the same way in Java.
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-2451113241275726124?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/2451113241275726124/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=2451113241275726124' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/2451113241275726124'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/2451113241275726124'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2009/01/inherited-classes-in-hibernate.html' title='Inherited classes in Hibernate'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-7891258207063883041</id><published>2009-01-09T23:27:00.003+02:00</published><updated>2009-02-01T00:55:27.146+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='slots'/><category scheme='http://www.blogger.com/atom/ns#' term='low-level'/><title type='text'>Python class slots</title><content type='html'>Today I came over &lt;code&gt;__slots__&lt;/code&gt; feature of Python. It's used to define the list of possible attributes at the class creation time, so by default no dictionary is kept for every instance. This can save memory, if such instances are stored in big lists. To use slots, class should be defined like this:&lt;pre name="code" class="python"&gt;class Point(object):
  __slots__=["x","y"]
&lt;/pre&gt;The next example demonstrates the difference between a class with slots and a regular class.&lt;pre name="code" class="python"&gt;class OldPoint(object):
  pass

p=OldPoint()
p.x=10
p.y=20   # these are OK
p.z=30   # this is OK as well - any attributes are allowed

p=Point()
p.x=10
p.y=20   # this are OK
p.z=30   # this causes AttributeError: 'Point' object has no attribute 'z'&lt;/pre&gt;Defining &lt;code&gt;__slots__&lt;/code&gt; affects not only the dictionary of the instances, but also the way they are serialized (or pickled in Python terminolodgy). Also a weak reference (&lt;code&gt;__weakref__&lt;/code&gt;) is not enabled by default (can be overriden)&lt;h3&gt;Links&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.network-theory.co.uk/docs/pylang/__slots__.html"&gt;More information on slots&lt;/a&gt;&lt;li&gt;&lt;a href="http://www.python.org/dev/peps/pep-0307/"&gt;Slots and serialization&lt;/a&gt;&lt;li&gt;&lt;a href="http://www.twistedmatrix.com/pipermail/twisted-python/2008-May/017729.html"&gt;Measuring memory saved by slots&lt;/a&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-7891258207063883041?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/7891258207063883041/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=7891258207063883041' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/7891258207063883041'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/7891258207063883041'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2009/01/python-class-slots.html' title='Python class slots'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-7096929080335135203</id><published>2009-01-06T11:15:00.007+02:00</published><updated>2009-04-16T20:35:47.029+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blogger'/><category scheme='http://www.blogger.com/atom/ns#' term='lj-cut'/><category scheme='http://www.blogger.com/atom/ns#' term='blogspot'/><category scheme='http://www.blogger.com/atom/ns#' term='ljcut'/><title type='text'>lj-cut on blogger</title><content type='html'>LifeJournal has a useful feature &lt;code&gt;lj-cut&lt;/code&gt;. It allows to show only a part of the post on the main page, and reveal the rest on a separate page. I was looking for a similar feature on blogger, as my posts with code examples are quite lengthy.
&lt;div id="fullpost"&gt;
Don't need to say much more, &lt;a href="http://hackosphere.blogspot.com/2006/11/selective-expandable-posts.html"&gt;the solution is here&lt;/a&gt;. &lt;strong&gt;Don't forget the step 1&lt;/strong&gt;, I started from the red part and scratched the head what's wrong.
&lt;p/&gt;
P.S. I ended up changing their tags from span to div, as span can not include &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; elements among many other limitations.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-7096929080335135203?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/7096929080335135203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=7096929080335135203' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/7096929080335135203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/7096929080335135203'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2009/01/test-cut-on-blogger.html' title='lj-cut on blogger'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-6870586101126650548</id><published>2009-01-06T00:31:00.007+02:00</published><updated>2009-02-01T00:55:52.925+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='datastore'/><category scheme='http://www.blogger.com/atom/ns#' term='solution'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='appengine'/><title type='text'>Trivial resolution of Datastore performance</title><content type='html'>In addition to &lt;code&gt;Model.put()&lt;/code&gt; Datastore has &lt;code&gt;db.put()&lt;/code&gt;. I did not notice the latter can put several entities at once until &lt;a href="https://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=7359154984961659258"&gt;Arachnid told me so&lt;/a&gt;. So in my code I changed this:&lt;pre name="code" class="python"&gt;for cell in cells:
  cell.put()&lt;/pre&gt;To this:&lt;pre name="code" class="python"&gt;db.put(cells)&lt;/pre&gt;That's all what was needed to fix the performance.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-6870586101126650548?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/6870586101126650548/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=6870586101126650548' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/6870586101126650548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/6870586101126650548'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2009/01/trivial-resolution-of-datastore.html' title='Trivial resolution of Datastore performance'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-7359154984961659258</id><published>2009-01-04T22:19:00.009+02:00</published><updated>2009-02-01T00:56:18.000+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='datastore'/><category scheme='http://www.blogger.com/atom/ns#' term='transaction'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='appengine'/><title type='text'>Improved Datastore performance</title><content type='html'>Looks like the problem with &lt;a href="http://andskiba.blogspot.com/2009/01/datastore-performance.html"&gt;Datastore performance&lt;/a&gt; is that the information was very fine-grained. I created the test following Google's suggestion (look at &lt;a href="http://code.google.com/appengine/docs/datastore/transactions.html#Uses_For_Transactions"&gt;the tip at the end of the page&lt;/a&gt;). So this time I made an opposite test:
&lt;ul&gt;
&lt;li&gt;Instead of having a single integer, each entity has a text with 10,000 characters
&lt;li&gt;A half of records is written in transactions by 10 records, and another half - record by record&lt;/ul&gt;
The results show that the &lt;strong&gt;size of entity&lt;/strong&gt; had no effect unlike &lt;strong&gt;entities' count&lt;/strong&gt;. So it's better to write a few large objects than many small ones. 
&lt;div id='fullpost'&gt;
Also, this time I had a huge difference between the real appengine server and dev_appserver after having many records in the database (real server was much faster). &lt;strong&gt;Grouping few records&lt;/strong&gt; in a transaction also helped. This is the test code:&lt;pre name="code" class="python"&gt;from google.appengine.ext import db
from time import time

print 'Content-Type: text/plain'
print ''

total_t=time()
class Root(db.Model):
    pass

class C(db.Model):
 i=db.TextProperty()

t1000="a"*10000

def add_in_transaction(root, text, amount):
     for j in range(amount):
        c=C(parent=root, i=text)
        c.put()

print "with transactions - big"
for i in range(5):
    t=time()
    root=Root()
    root.put()
    db.run_in_transaction(add_in_transaction, root, t1000, 10)
    print time()-t
print "without transactions - big"
for i in range(5):
    t=time()
    root=Root()
    root.put()
    add_in_transaction(None, t1000, 10)
    print time()-t
print "without transactions - small"
for i in range(5):
    t=time()
    root=Root()
    root.put()
    add_in_transaction(None, "a", 10)
    print time()-t

print "total time:", time()-total_t&lt;/pre&gt;And this is the result&lt;pre name="code" &gt;with transactions - big
0.161096096039
0.154489994049
0.367100000381
0.152635812759
0.153033971786
without transactions - big
0.315757989883
0.359083890915
0.559228181839
0.360776901245
0.330877780914
without transactions - small
0.279601812363
0.541454076767
0.324053049088
0.311630964279
0.306309938431
total time: 4.67810916901
&lt;/pre&gt;I think it's worth to open a bug on appengine documentation so they mention these performance considerations.&lt;p&gt;P.S. changed the test a little to demonstrate that writing one character or 10K characters has no difference.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-7359154984961659258?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/7359154984961659258/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=7359154984961659258' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/7359154984961659258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/7359154984961659258'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2009/01/improved-datastore-performance.html' title='Improved Datastore performance'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-6832367376744662097</id><published>2009-01-04T18:44:00.003+02:00</published><updated>2009-02-01T00:56:39.144+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='datastore'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='appengine'/><title type='text'>Datastore performance</title><content type='html'>&lt;p&gt;Something strange with the performance of the AppEngine Datastore. I tried to run the following code:&lt;pre name="code" class="python"&gt;from google.appengine.ext import db
from time import time

print 'Content-Type: text/plain'
print ''

total_t=time()

class C(db.Model):
 i=db.IntegerProperty()

for i in range(10):
 t=time()
 for j in range(10):
  c=C(i=i)
  c.save()
 print time()-t

print "total time:", time()-total_t&lt;/pre&gt;&lt;div id='fullpost'&gt;As you can see, this is a complete python module, not dependent on django or anything else. Just add a corresponding mapping to app.yaml and you can try it by yourself. So the output of this code, which adds 100 records to the Datastore is:&lt;pre&gt;0.307200908661
0.279258012772
0.305376052856
0.310864925385
0.286242008209
0.283288002014
0.299383878708
0.286517858505
0.281584024429
0.268044948578
total time: 2.90873217583&lt;/pre&gt;&lt;p&gt;I tried to add 200 records, and got a time-out as AppEngine does not allow long-running queries. I had pretty similar timings on the dev_appserver. This is very slow, and I cannot understand where is the catch.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-6832367376744662097?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/6832367376744662097/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=6832367376744662097' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/6832367376744662097'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/6832367376744662097'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2009/01/datastore-performance.html' title='Datastore performance'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-9098262364395242680</id><published>2009-01-03T18:52:00.002+02:00</published><updated>2009-02-01T00:57:08.394+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='datastore'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='appengine'/><title type='text'>Querying for None in Datastore</title><content type='html'>&lt;p&gt;I got a weird problem with GAE Datastore, when tried to search for &lt;code&gt;None&lt;/code&gt; value. If I use &lt;code&gt;gql&lt;/code&gt;, then the query works as expected:
&lt;pre name="code" class="python"&gt;from game.models import *
for c in Cell.gql("WHERE game=:g", g=None):
 print c&lt;/pre&gt;&lt;p&gt;The above code prints the expected cells which are not bound to any game. But I need to iterate through cells of a certain board type, so instead of &lt;code&gt;Cell.gql&lt;/code&gt; I start from &lt;code&gt;board.cell_set&lt;/code&gt; and am trying to define a filter on &lt;code&gt;game=None&lt;/code&gt;. The following code should give the same outcome as the previous one:&lt;pre name="code" class="python"&gt;from game.models import *
for c in Cell.all().filter("game=", None):
 print c&lt;/pre&gt;&lt;p&gt;But this time I get no results. Why?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-9098262364395242680?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/9098262364395242680/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=9098262364395242680' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/9098262364395242680'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/9098262364395242680'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2009/01/querying-for-none-in-datastore.html' title='Querying for None in Datastore'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-3870643388426637801</id><published>2009-01-03T02:30:00.003+02:00</published><updated>2009-06-23T13:31:09.735+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='datastore'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='appengine'/><title type='text'>Cached ReferenceProperty: now with round trip</title><content type='html'>&lt;p&gt;One thing was really missing in a &lt;a href src="http://andskiba.blogspot.com/2008/12/cached-referenceproperty.html"&gt;CachedReferenceProperty&lt;/a&gt; - cached round trip. Suppose we have the following one-to-many relationship:&lt;pre name='code' class='python'&gt;class Master(db.Model):
  pass

class Detail(db.Model):
  master=CachedReferenceProperty(Master)&lt;/pre&gt;&lt;p&gt;By &lt;strong&gt;cached round trip&lt;/strong&gt; here I mean that when a master holds a cached collection of details, those details reference the same master, so going back and forth from master to details does not make any database hits.&lt;p&gt;To make it possible, I replaced collection builder in &lt;code&gt;_CachedReverseReferenceProperty&lt;/code&gt; from this:&lt;pre name='code' class='python'&gt;  res=[c for c in query]&lt;/pre&gt;&lt;p&gt;to this:&lt;pre name='code' class='python'&gt;  res=[]
  for c in query:
    resolved_name='_RESOLVED_'+self.__prop #WARNING: using internal
    setattr(c, resolved_name, model_instance)
    res += [c]&lt;/pre&gt;&lt;p&gt;Very ugly, need an idea how to eliminate using internal attribute. The whole source file is &lt;a href="http://smart-sweeper.googlecode.com/svn/trunk/game/dbext.py"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-3870643388426637801?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/3870643388426637801/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=3870643388426637801' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/3870643388426637801'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/3870643388426637801'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2009/01/cached-referenceproperty-now-with-round.html' title='Cached ReferenceProperty: now with round trip'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-4794432756043038716</id><published>2008-12-28T22:36:00.001+02:00</published><updated>2009-02-01T00:58:31.363+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='django'/><category scheme='http://www.blogger.com/atom/ns#' term='appengine'/><title type='text'>Hello, google-app-engine-django</title><content type='html'>&lt;p&gt;Going to try &lt;a href="http://code.google.com/p/google-app-engine-django"&gt;Django patch for Appengine&lt;/a&gt;. These are my problems in the genuine Appengine with built-in Django:
&lt;dl&gt;
&lt;dt&gt;Documentation
&lt;dd&gt;It is not satisfactory - covers everything, but not enough details.
&lt;dt&gt;Debugging
&lt;dd&gt;Still cannot debug, get opaque tracebacks every time when trying.
&lt;dt&gt;Testing
&lt;dd&gt;&lt;a href="testing-appengine-django-application.html"&gt;Explained the problem here.&lt;/a&gt;
&lt;dt&gt;Flexible persistance and caching
&lt;dd&gt;Too much hacking necessary for trivial things, like cached one-to-many collections.
&lt;/dl&gt;
&lt;p&gt;To be honest, I'm thinking to switch to the full stack of Django with a normal database. Can find less and less reasons to stick to Appengine.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-4794432756043038716?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/4794432756043038716/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=4794432756043038716' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/4794432756043038716'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/4794432756043038716'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2008/12/hello-google-app-engine-django.html' title='Hello, google-app-engine-django'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-602255759338618826</id><published>2008-12-26T16:58:00.001+02:00</published><updated>2009-01-06T12:34:57.264+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='memcache'/><category scheme='http://www.blogger.com/atom/ns#' term='appengine'/><title type='text'>what memcache stores?</title><content type='html'>&lt;p&gt;Now &lt;a href="http://andskiba.blogspot.com/2008/12/cached-referenceproperty.html"&gt;after I learned how to store&lt;/a&gt; one-to-many collections with AppEngine datastore, I want to use Memcache API to eliminate DB hits between requests. Quick test shows it would not work out of the box:&lt;pre name='code' class='python'&gt;class C(object):
 def __init__(self):
   self.field='field'

c=C()
c.attr='attr'
c.__dict__['dict']='dict'
print dir(c)
memcache.add('c', c)
c=memcache.get("c")
print dir(c)&lt;/pre&gt;&lt;p&gt;I would expect this code to output the same list of public attributes before and after, but it does not happen. We can see that only &lt;code&gt;c.field&lt;/code&gt; was saved, while &lt;code&gt;c.attr&lt;/code&gt; and &lt;code&gt;c.dict&lt;/code&gt; are missing. Need to investigate memcache internals to understand why.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-602255759338618826?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/602255759338618826/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=602255759338618826' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/602255759338618826'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/602255759338618826'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2008/12/what-memcache-stores.html' title='what memcache stores?'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-8569756705260166268</id><published>2008-12-25T00:23:00.002+02:00</published><updated>2009-01-06T12:19:22.100+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ReferenceProperty'/><category scheme='http://www.blogger.com/atom/ns#' term='datastore'/><category scheme='http://www.blogger.com/atom/ns#' term='solution'/><category scheme='http://www.blogger.com/atom/ns#' term='cache'/><category scheme='http://www.blogger.com/atom/ns#' term='appengine'/><title type='text'>Cached ReferenceProperty</title><content type='html'>&lt;h3&gt;Piece of cake&lt;/h3&gt;
&lt;a href="http://andskiba.blogspot.com/2008/12/appengine-datastore-and-memcache.html"&gt;Earlier I wrote about my wish&lt;/a&gt; to subclass ReferenceProperty so the collection would not be fetched every time I iterate though it. Well, it was so easy I can post the whole implementation here.&lt;pre name='code' class='python'&gt;from google.appengine.ext import db

class CachedReferenceProperty(db.ReferenceProperty):

  def __property_config__(self, model_class, property_name):
    super(CachedReferenceProperty, self).__property_config__(model_class,
                                                       property_name)
    #Just carelessly override what super made
    setattr(self.reference_class,
            self.collection_name,
            _CachedReverseReferenceProperty(model_class, property_name,
                self.collection_name))

class _CachedReverseReferenceProperty(db._ReverseReferenceProperty):

    def __init__(self, model, prop, collection_name):
        super(_CachedReverseReferenceProperty, self).__init__(model, prop)
        self.__collection_name = collection_name

    def __get__(self, model_instance, model_class):
        if model_instance is None:
            return self
        if self.__collection_name in model_instance.__dict__:# why does it get here at all?
            return model_instance.__dict__[self.__collection_name]

        query=super(_CachedReverseReferenceProperty, self).__get__(model_instance,
            model_class)
        #replace the attribute on the instance
        res=[c for c in query]
        model_instance.__dict__[self.__collection_name]=res
        return res

    def __delete__ (self, model_instance):
        if model_instance is not None:
            del model_instance.__dict__[self.__collection_name]&lt;/pre&gt;&lt;div id='fullpost'&gt;Having these classes now we can rewrite previous example as:&lt;pre name='code' class='python'&gt;class Master(db.Model):
  pass

class Detail(db.Model):
  master=CachedReferenceProperty(Master)&lt;/pre&gt;Try to run the same cycle and you will see it executes instantly even with 100,000 iterations instead of 1000.&lt;h3&gt;Is it a free cake?&lt;/h3&gt;Not exactly. Try this:&lt;pre&gt;m=Master()
m.put()
d1=Detail(master=m)
d1.put()
print m.detail_set
d2=Detail(master=m)
d2.put()
print m.detail_set&lt;/pre&gt;The second time it returned a wrong result, which did not include d2. So we need a way to reset the cached value and fetch up-to-date values from the datastore. Fortunately, it's achieved easily:&lt;pre&gt;del m.detail_set
print m.detail_set&lt;/pre&gt;This is why I implemented &lt;code&gt;_CachedReverseReferenceProperty.__delete__&lt;/code&gt;. When &lt;code&gt;m.__dict__&lt;/code&gt; has no key&lt;code&gt;'detail_set'&lt;/code&gt;, &lt;code&gt;m.detail_set&lt;/code&gt; is dispatched to &lt;code&gt;type(m).__dict__('detail_set')&lt;/code&gt;, and there I call the base class to access the datastore. What surprised me is when I do have &lt;code&gt;m.__dict__('detail_set')&lt;/code&gt;, &lt;code&gt;m.detail_set&lt;/code&gt; is still dispatched to &lt;code&gt;Master.__dict__('detail_set')&lt;/code&gt;. I don't understand why that happens, so I worked around this problem. Have to learn Python better to answer that question.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-8569756705260166268?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/8569756705260166268/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=8569756705260166268' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/8569756705260166268'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/8569756705260166268'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2008/12/cached-referenceproperty.html' title='Cached ReferenceProperty'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-5520037235943284142</id><published>2008-12-24T17:44:00.000+02:00</published><updated>2008-12-24T18:06:57.096+02:00</updated><title type='text'>Testing AppEngine django application with Nose</title><content type='html'>&lt;p&gt;&lt;a href="http://www.cuberick.com/2008/11/unit-test-your-google-app-engine-models.html"&gt;Here&lt;/a&gt; Shlomo gives a basic example of creating unit tests for AppEngine application.&lt;/p&gt;&lt;p&gt;I tried to adopt this method in my project and it gave me a strange trace:&lt;pre&gt;----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Library/Python/2.5/site-packages/nose-0.10.4-py2.5.egg/nose/loader.py", line 364, in loadTestsFromName
    addr.filename, addr.module)
  File "/Library/Python/2.5/site-packages/nose-0.10.4-py2.5.egg/nose/importer.py", line 39, in importFromPath
    return self.importFromDir(dir_path, fqname)
  File "/Library/Python/2.5/site-packages/nose-0.10.4-py2.5.egg/nose/importer.py", line 84, in importFromDir
    mod = load_module(part_fqname, fh, filename, desc)
ImportError: Loaded module game.test_models not found in sys.modules&lt;/pre&gt;&lt;p&gt;First I thought that &lt;code&gt;nosegae&lt;/code&gt; installation is invalid. But then I found out that &lt;code&gt;nose --with-gae&lt;/code&gt; does not like when a test module is not in a root directory of the project. So I moved test_models.py from game package into the root package and it worked as expected.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-5520037235943284142?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/5520037235943284142/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=5520037235943284142' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/5520037235943284142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/5520037235943284142'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2008/12/testing-appengine-django-application.html' title='Testing AppEngine django application with Nose'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-5994677785930094760</id><published>2008-12-24T10:52:00.001+02:00</published><updated>2009-01-06T12:37:42.289+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ReferenceProperty'/><category scheme='http://www.blogger.com/atom/ns#' term='datastore'/><category scheme='http://www.blogger.com/atom/ns#' term='memcache'/><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='appengine'/><title type='text'>AppEngine Datastore and memcache</title><content type='html'>&lt;p&gt;I miss Hibernate collections. In the following code I access the collection a thousand times:&lt;pre name='code' class='python'&gt;class Master(db.Model):
  pass

class Detail(db.Model):
  master=db.ReferenceProperty(Master)

m=Master()
m.put()
d=Detail(master=m)
d.put()

for i in range(1000):
  for tmp_d in m.detail_set:
    pass
&lt;/pre&gt;&lt;p&gt;The above code takes a few second to execute. The reason is Datastore fetches the collection from the storage every time, and in Hibernate the collection would be fetched from the database only once until the end of the session. Oops, no sessions with Datastore. So Datastore developers were right when they opted to fetch collection every time - they don't know when the details change.&lt;p&gt;This is the reason Master cannot be put in memcache effectively: it would be stored without the Details. Master.detail_set holds only the definition of the query needed to get the details. So I'm thinking of a way I could decorate ReferenceProperty to make one-to-many relations suitable for the memcache. So big object trees will be read from Datastore once and then accessible in a fast way.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-5994677785930094760?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/5994677785930094760/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=5994677785930094760' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/5994677785930094760'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/5994677785930094760'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2008/12/appengine-datastore-and-memcache.html' title='AppEngine Datastore and memcache'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-3415666072066440283</id><published>2008-12-20T14:49:00.001+02:00</published><updated>2009-01-06T12:38:22.294+02:00</updated><title type='text'>Polymorphism in AppEngine Datastore Models - continued</title><content type='html'>Playing around with the Master and Details classes in the previous post, I tried to subclass a Master this time:
&lt;pre name='code' class='python'&gt;
class MoreMaster(Master):
 mmp = db.StringProperty()

mm=MoreMaster(mp='f', mmp='g')
mm.put()

d4 = Detail(dp='h', master=mm)
d4.put()

for d in mm.detail_set:
 print d.master.mmp
&lt;/pre&gt;
It printed 'g', thus resolving correctly that d4.master is derived class. So the "many to one" relation supports polymorphism, but "one to many" does not. The reason is db.Key already contains the name of the Model class. So when we do Master.get('LongLongKeyHere') the Datastore is able to create the correct class.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-3415666072066440283?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/3415666072066440283/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=3415666072066440283' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/3415666072066440283'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/3415666072066440283'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2008/12/polymorphism-in-appengine-datastore_20.html' title='Polymorphism in AppEngine Datastore Models - continued'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-7787409843626706380</id><published>2008-12-20T14:05:00.002+02:00</published><updated>2009-01-06T12:40:40.508+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='datastore'/><category scheme='http://www.blogger.com/atom/ns#' term='polymorphism'/><category scheme='http://www.blogger.com/atom/ns#' term='subclass'/><category scheme='http://www.blogger.com/atom/ns#' term='appengine'/><title type='text'>Polymorphism in AppEngine Datastore Models</title><content type='html'>There is a problem with inherited classes in AppEngine
&lt;p&gt;
Let's suppose we have the following models:
&lt;pre name='code' class='python'&gt;
class Master(db.Model):
  mp = db.StringProperty()

class Detail(db.Model):
  dp = db.StringProperty()
  master = db.ReferenceProperty(Master)
&lt;/pre&gt;

When these are declared, Datastore appends automatically Detail_set property to the Master. So if we made
&lt;pre name='code' class='python'&gt;
m=Master(mp='foo')
m.put()
d1=Detail(dp='bar', master=m)
d1.put()
d2=Detail(dp='zee', master=m)
d2.put()
&lt;/pre&gt;
then we have m.Detail_set property which will fetch &lt;code&gt;[d1, d2]&lt;/code&gt;. But if we define&lt;pre name='code' class='python'&gt;
class MoreDetail (Detail):
  mdp=db.StringProperty()

d3=MoreDetail (dp='org', mdp='jee', master=m)
d3.put()
&lt;/pre&gt;then m.detail_set will fetch the third d3 but de-serialize it as Detail instead of MoreDetail class. Here is how I checked it:
&lt;pre&gt;
&gt;&gt;&gt; for d in m.detail_set.fetch(10):
...  print d.properties()
{'master': &amp;lt;ReferenceProperty object at 0x018B8330&amp;gt;, 'dp': &amp;lt;StringProperty object at 0x023A8C10&amp;gt;}
{'master': &amp;lt;ReferenceProperty object at 0x018B8330&amp;gt;, 'dp': &amp;lt;StringProperty object at 0x023A8C10&amp;gt;}
{'master': &amp;lt;ReferenceProperty object at 0x018B8330&amp;gt;, 'dp': &amp;lt;StringProperty object at 0x023A8C10&amp;gt;}
&lt;/pre&gt;
One of these objects should have an mdp property defined in MoreDetail, but that did not happen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-7787409843626706380?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/7787409843626706380/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=7787409843626706380' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/7787409843626706380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/7787409843626706380'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2008/12/polymorphism-in-appengine-datastore.html' title='Polymorphism in AppEngine Datastore Models'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7911563994423957036.post-8973858354987243953</id><published>2008-12-18T11:05:00.000+02:00</published><updated>2008-12-23T11:15:53.112+02:00</updated><title type='text'>JavaEdge 2008</title><content type='html'>&lt;p&gt;Today I attended Java Edge, and want to share my impression while it's fresh in my memory.&lt;/p&gt;&lt;h3&gt;Java for the cloud by Baruch Sadogursky&lt;/h3&gt;&lt;p&gt;In 19 century every manufacturer was running their private electricity generator. Eventually people started to consume electricity provided by a few big companies. In the same way now the tendency will be to stop running our own servers and to use the computing power and the storage provided as a service. Today leading services are Google AppEngine, Amazon S3 and EC2, goGrid, AppNexus, FlexiScale. Soon there will be Microsoft Azure, and there are rumors about Yahoo Cloud.&lt;/p&gt;&lt;p &gt;Very important for today's crisis state of mind:&lt;strong&gt; fail cheap&lt;/strong&gt;. That means that we don't spend a lot up front to buy servers, to pay for installations, etc.&lt;/p&gt;&lt;p&gt;Overall this area is very important.&lt;/p&gt;&lt;h3&gt;OSGi and SpringSource application platform by Alef Arendsen from SpringSource&lt;/h3&gt;&lt;p &gt;Most of the session Alef demonstrated trivial OSGi stuff. But there is one amazing feature which is unique in Spring - ability to easily &lt;strong&gt;share service instances&lt;/strong&gt;. That means 2 or more OSGi consumers get the same service instance from the container. So they can share cache or state there. It is achieved very easily in Spring. Declare the service bean with osgi:service and wire it to consumer with osgi:reference. The service bean does not even have to be serializable, as no remoting happens behind the scene. Voila, beans are wired, with all dynamic features, like automatically rewiring consumers to another provider when current goes down.&lt;/p&gt;&lt;h3&gt;Smoothing your Java with DSLs by Dmitry Jemerov&lt;/h3&gt;&lt;p&gt;I'm very glad I chose this session. Dmitry demonstrated how heavy, sure-to-be-copy-pasted code can be transformed into something which a non-programmer can read and may be even write. What I liked the most, is how he prepared this session going every time one step further from the original code - first old-fashion java code, then applied &lt;strong&gt;fluent API patterns&lt;/strong&gt;, then used Groovy to make it even more readable, then using JetBrains MPS to make text format to be translated into java. And the computer generated Java code looked exactly like the original code, thanks to powerful MPS declarations. Very impressive, Dmitry.&lt;/p&gt;&lt;h3&gt;Taking control of your Maven build by Yossi Shaul&lt;/h3&gt;&lt;p&gt;Yossi shared his experience with troubleshooting Maven builds and gave some really useful tips. In short summary it's impossible to list all the general recommendations so I'll just list some important maven commands here:&lt;/p&gt;&lt;pre&gt;mvn help:effective-pom
mvn help:effective-settings
mvn dependency:list
mvn dependency:tree
mvn dependency:analyze -DignoreNonCompile
mvn dependency:analyze-dep-mgt
mvn project-info-reports:dependency-convergence
mvn enforcer:enfore&lt;/pre&gt;&lt;p&gt;The last one has to be accompanied by some restrictions in parent pom, like don't allow to rely on some dangerous defaults, etc. See Yossi's presentation for the details.&lt;/p&gt;&lt;h3&gt;Testing Web UI by Alex Waisburd&lt;/h3&gt;&lt;p&gt;Good overview of web UI testing tools. Focus on Selenium with a demonstration of a simple way to perform integration test from the nightly build server. I saw similar capabilities in Microsoft Team System and was really missing them in Java land. With Selenium it's possible to record necessary user actions with Firefox, to generate Java code from this recording, and to replay them when needed. Selenium Java API enables to access URLs, to make any user actions (clicks, type text) on the returned page, &lt;strong&gt;to wait until the page is changed by AJAX&lt;/strong&gt;, and to check if the resulting page contains the expected elements. Wow!&lt;/p&gt;&lt;p&gt;General impression: interesting and well-organized event, became better from the last year. Hope to be there again in 2009 :-)&lt;/p&gt;&lt;p&gt;Slides are available here: http://www.javaedge.net/sessions.html&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7911563994423957036-8973858354987243953?l=andskiba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andskiba.blogspot.com/feeds/8973858354987243953/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7911563994423957036&amp;postID=8973858354987243953' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/8973858354987243953'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7911563994423957036/posts/default/8973858354987243953'/><link rel='alternate' type='text/html' href='http://andskiba.blogspot.com/2008/12/javaedge-2008.html' title='JavaEdge 2008'/><author><name>Andrew Skiba</name><uri>http://www.blogger.com/profile/04482963509700477331</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_yXdc5xeEFQ4/SWJucSp50YI/AAAAAAAABOo/kmODaW7FJMo/S220/avatar.png'/></author><thr:total>0</thr:total></entry></feed>
