<?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'><id>tag:blogger.com,1999:blog-17885082</id><updated>2009-12-10T14:37:32.181+01:00</updated><title type='text'>my take on things</title><subtitle type='html'>{ by david linsin }</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default?start-index=26&amp;max-results=25'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>473</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-17885082.post-5900569946785839304</id><published>2009-12-07T05:47:00.001+01:00</published><updated>2009-12-07T05:47:27.824+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quality'/><category scheme='http://www.blogger.com/atom/ns#' term='karlsruhe'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='jug-ka'/><title type='text'>Scrum @ JUG-Ka</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://picasaweb.google.com/lh/photo/zDGbEVVB5ihDeoGRJltMvA?authkey=Gv1sRgCKXY3MiLxprXDQ&amp;feat=embedwebsite"&gt;&lt;img style="float:left;margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://lh4.ggpht.com/_myUhtr_A51Y/SnWVogdEjOI/AAAAAAAAPiQ/o9MjIPCDE_s/s144/jug_logo_original_transparent.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5191388009271083842" /&gt;&lt;/a&gt;The upcoming talk at the &lt;a href="http://jug-ka.de"&gt;Java User Group Karlsruhe&lt;/a&gt; this Wednesday is kind of an experiment. It features Scrum, which according to &lt;a href="http://en.wikipedia.org/wiki/Scrum_(development)"&gt;Wikipedia&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;cite&gt;... is an iterative incremental framework for managing complex work (such as new product development) commonly used with agile software development.&lt;br /&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;It's an experiment, because we usually feature sessions on development topics like &lt;a href="http://dlinsin.blogspot.com/2009/11/restful-applications-in-practise-jug-ka.html"&gt;REST&lt;/a&gt;, &lt;a href="http://dlinsin.blogspot.com/2009/09/tuning-hibernate-and-jpa-jug-ka.html"&gt;Hibernate&lt;/a&gt; and &lt;a href="http://dlinsin.blogspot.com/2009/08/java-flex-jug-ka.html"&gt;Flex&lt;/a&gt;. A talk on a management framework, although it's closely related to development, is rather unusual for us. If you are not interested in this kind of topic, let me know, we appreciate your feedback.&lt;br /&gt;&lt;br /&gt;The talk will take place at &lt;a href="http://groups.google.com/group/jug-karlsruhe/web/how-to-find-us?_done=%2Fgroup%2Fjug-karlsruhe%3F"&gt;University Karlsruhe&lt;/a&gt; in room 102, located in the basement. Unusual topics call for unusual timings, so we'll start at 8:00pm this time. Our speaker is Dr. Jürgen Hoffmann of &lt;a href="http://www.scrumcoach.de"&gt;scrumcoach.de&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;This month we are giving away a free book called "&lt;a href="http://www.amazon.de/gp/product/0321503627?ie=UTF8&amp;tag=mytakeonthing-21&amp;linkCode=as2&amp;camp=1638&amp;creative=6742&amp;creativeASIN=0321503627"&gt;Growing Object-Oriented Software, Guided by Tests by Freeman&amp;Pryce&lt;/a&gt;". If you are interested in participating in the lottery, drop me an email. The winners will be announced at the end of the talk. &lt;br /&gt;&lt;br /&gt;This is the last gathering of the year 2009. There's even more to come in 2010, so subscribe to our &lt;a href="http://www.google.com/calendar/embed?src=ehlt6rbl1cd1s2b7t9bkj6beek%40group.calendar.google.com&amp;ctz=Europe/Berlin"&gt;Google Calendar&lt;/a&gt; and stay up-to-date.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-5900569946785839304?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/5900569946785839304/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=5900569946785839304' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/5900569946785839304'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/5900569946785839304'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/12/scrum-jug-ka_4680.html' title='Scrum @ JUG-Ka'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_myUhtr_A51Y/SnWVogdEjOI/AAAAAAAAPiQ/o9MjIPCDE_s/s72-c/jug_logo_original_transparent.png' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-7932177108590882053</id><published>2009-11-30T05:40:00.000+01:00</published><updated>2009-11-30T05:42:17.345+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web development'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='spring'/><title type='text'>Playing with Spring's RestTemplate</title><content type='html'>A couple of week ago, I saw a &lt;a href="http://www.infoq.com/presentations/rest-web-application-architectures"&gt;talk&lt;/a&gt; on &lt;a href="http://www.springsource.org/download"&gt;Spring&lt;/a&gt; 3.0's MVC &lt;a href="http://dlinsin.blogspot.com/2009/11/restful-applications-in-practise-jug-ka.html"&gt;REST&lt;/a&gt; support. It's quite impressive how simple SpringSource made REST development by applying the proven concepts of the core Spring Framework. &lt;br /&gt;&lt;br /&gt;One of those great core concepts is &lt;a href="http://en.wikipedia.org/wiki/Spring_Framework#Data_access_framework"&gt;Templates&lt;/a&gt;. Spring's &lt;a href="http://static.springsource.org/spring/docs/2.5.x/reference/spring-middle-tier.html"&gt;Data Access Framework&lt;/a&gt; is an example, where templates are used extensively. One of the templates is the &lt;em&gt;JDBCTemplate&lt;/em&gt;. It provides a set of predefined methods to access a database, without worrying about &lt;i&gt;Connection&lt;/i&gt; management or &lt;i&gt;Exception&lt;/i&gt; handling. Templates are a nice way to help you the the job done, without constraining flexibility. The book &lt;a href="http://www.amazon.de/gp/product/1590599187?ie=UTF8&amp;tag=mytakeonthing-21&amp;linkCode=as2&amp;camp=1638&amp;creative=6742&amp;creativeASIN=1590599187"&gt;"Building Spring 2 Enterprise Applications"&lt;/a&gt;, which I &lt;a href="http://dlinsin.blogspot.com/2008/05/book-review-building-spring-2.html"&gt;reviewed&lt;/a&gt; last year, there's a whole chapter on &lt;em&gt;Data Access&lt;/em&gt; and the corresponding &lt;em&gt;Templates&lt;/em&gt;. &lt;br /&gt;&lt;br /&gt;The &lt;a href="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/client/RestTemplate.html"&gt;RestTemplate&lt;/a&gt; is the latest child in the family. Arjen Poutsma from SpringSource wrote a &lt;a href="http://blog.springsource.com/2009/03/27/rest-in-spring-3-resttemplate/"&gt;blog entry&lt;/a&gt; about it and describes it as follows:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;The RestTemplate is the central Spring class for client-side HTTP access. Conceptually, it is very similar to the JdbcTemplate, JmsTemplate, and the various other templates found in the Spring Framework and other portfolio projects. This means, for instance, that the RestTemplate is thread-safe once constructed, and that you can use callbacks to customize its operations.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;In the before mentioned blog post, Arjen shows how to pull pictures from Flickr, using their REST API, and display them in a &lt;em&gt;JFrame&lt;/em&gt;. He uses an XML based approach, whereas I'll show you &lt;a href="http://github.com/dlinsin/github-java-api"&gt;some code&lt;/a&gt;, which handles JSON:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/236496.js"&gt;&lt;/script&gt;&lt;noscript&gt;&lt;pre&gt;public Issue browse(Repository argRepository, int argIssueNo) {&lt;br /&gt;    RestTemplate template = new RestTemplate();&lt;br /&gt;    template.setMessageConverters(new HttpMessageConverter[] {&lt;br /&gt;      new MappingJacksonHttpMessageConverter()});&lt;br /&gt;    IssueResponse resp = template.getForObject(BASE_URL + "issues/show/{username}/{repo}/{no}", IssueResponse.class, &lt;br /&gt;      argRepository.getOwner(), argRepository.getName(), String.valueOf(argIssueNo));&lt;br /&gt;    return resp.getIssue();&lt;br /&gt;}&lt;/pre&gt;&lt;/noscript&gt;&lt;br /&gt;&lt;br /&gt;You can see it's quite easy to work with a &lt;em&gt;RestTemplate&lt;/em&gt;. You simply create an instance, tell that instance what your expected &lt;em&gt;content&lt;/em&gt; is going to be and you are good to go. In this case we expect the request and response to be &lt;em&gt;&lt;a href="http://en.wikipedia.org/wiki/JSON"&gt;JSON&lt;/a&gt;&lt;/em&gt;. Spring is using the &lt;a href="http://jackson.codehaus.org/"&gt;Jackson JSON Processor&lt;/a&gt;, to automagically map POJOs to JSON and all the way back. &lt;br /&gt;&lt;br /&gt;The concept of a  &lt;em&gt;MessageConverter&lt;/em&gt; is really neat. You can set multiple converters and specify to use a certain converter for certain POJOs. You can also handle multiple content types by setting multiple instances of  &lt;em&gt;MessageConverter&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;In order to make a REST call with the predefined &lt;em&gt;MessageConverter&lt;/em&gt;, you simply use the &lt;em&gt;getForObject&lt;/em&gt; method. You pass the url to call, the type the response is supposed to be mapped to and the values to be replaced in the url. The type of the response is actually a wrapper class:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/236519.js"&gt;&lt;/script&gt;&lt;noscript&gt;&lt;pre&gt;public class IssueResponse {&lt;br /&gt;    private Issue issue;&lt;br /&gt;    public Issue getIssue() {&lt;br /&gt;        return issue;&lt;br /&gt;    }&lt;br /&gt;    public void setIssue(Issue argIssue) {&lt;br /&gt;        issue = argIssue;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/noscript&gt; &lt;br /&gt;&lt;br /&gt;It is necessary since the following JSON response, which is represented in the POJO &lt;em&gt;Issue&lt;/em&gt;, needs some kind of holder object:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/236521.js"&gt;&lt;/script&gt;&lt;noscript&gt;&lt;pre&gt;{"issue":&lt;br /&gt;  {"number":1,"votes":0,"created_at":"2009/11/01 07:27:56 -0800",&lt;br /&gt;   "body":"This is a sample issue! Used in my RestTemplateSample!",&lt;br /&gt;   "title":"Sample Issue",&lt;br /&gt;   "updated_at":"2009/11/01 09:16:58 -0800","closed_at":null,&lt;br /&gt;   "user":"dlinsin","labels":["minor"],"state":"open"&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;/noscript&gt;&lt;br /&gt;&lt;br /&gt;As you can see, it's really easy to work with Spring's new &lt;em&gt;RestTemplate&lt;/em&gt;. These couple of lines are enough to retrieve a JSON or XML response from a REST call. With the &lt;em&gt;Template&lt;/em&gt; approach, you have the full flexibility to hook almost every method and tweak it to your needs.  &lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-7932177108590882053?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/7932177108590882053/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=7932177108590882053' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/7932177108590882053'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/7932177108590882053'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/11/playing-with-spring-resttemplate.html' title='Playing with Spring&amp;#39;s RestTemplate'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-8648257461689003239</id><published>2009-11-23T01:01:00.000+01:00</published><updated>2009-11-23T01:03:10.035+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>Finally Running with the Snow Leopard</title><content type='html'>A little note upfront - this is not about software development, so if you are solely here to read about my take on coding, this blog entry is not for you!&lt;br /&gt;&lt;br /&gt;A little more than 2 months ago I pre-ordered Apple's new &lt;a href="http://www.apple.com/macosx/"&gt;Mac OS X 10.6&lt;/a&gt; aka &lt;a href="http://en.wikipedia.org/wiki/Mac_OS_X_Snow_Leopard"&gt;&lt;em&gt;Snow Leopard&lt;/em&gt;&lt;/a&gt; one week before the official release at &lt;a href="http://www.gravis.de/"&gt;Gravis&lt;/a&gt;. As it turns out, it was a bad idea, because it took Gravis more than 6 weeks to deliver, but I digress...&lt;br /&gt;&lt;br /&gt;After finally receiving my &lt;a href="http://www.amazon.de/gp/product/B001AZ3Y66?ie=UTF8&amp;tag=mytakeonthing-21&amp;linkCode=as2&amp;camp=1638&amp;creative=6742&amp;creativeASIN=B001AZ3Y66"&gt;Family Pack&lt;/a&gt;, I installed the &lt;em&gt;Snow Leopard&lt;/em&gt; on my wife's &lt;a href="http://www.flickr.com/photos/sutini/sets/72157615186008213/"&gt;brand new MacBook&lt;/a&gt;. The upgrade was smooth and finished after only about 40 minutes. However, when it came to &lt;a href="http://dlinsin.blogspot.com/2008/05/paying-for-software.html"&gt;my old MacBook Pro&lt;/a&gt;, the tragedy began...&lt;br /&gt;&lt;br /&gt;The first attempt to install &lt;em&gt;Snow Leopard&lt;/em&gt; resulted in the installer quitting and rebooting the old Mac OS X as if nothing happened. Booting from the 10.6 DVD and then running the installer didn't help as well. I tried a couple of times, but the &lt;em&gt;Snow Leopard&lt;/em&gt; wouldn't come out of the cage. Instead, I got an error message like "An error occurred while installing Mac OS X". &lt;br /&gt;&lt;br /&gt;My second attempt was borrowing a colleagues copy of &lt;em&gt;Snow Leopard&lt;/em&gt; and trying to install it using my built-in DVD. You might have guessed it - it failed as well, with the same error message. The next attempt was getting an external drive, which I hooked up using &lt;a href="http://en.wikipedia.org/wiki/IEEE_1394_interface"&gt;FireWire&lt;/a&gt;. Unfortunately, neither my nor my colleagues &lt;em&gt;Snow Leopard&lt;/em&gt; DVD would let me install. &lt;br /&gt;&lt;br /&gt;After I spent hours of trying to tame this animal, I decided to leverage my wife's &lt;a href="http://www.amazon.de/gp/product/B002CJNCNY?ie=UTF8&amp;tag=mytakeonthing-21&amp;linkCode=as2&amp;camp=1638&amp;creative=6742&amp;creativeASIN=B002CJNCNY"&gt;MacBook&lt;/a&gt; as a remote dvd drive. It's pretty easy to setup and worked like a charm, however it didn't get my anywhere installing the new Mac OS X. The same problem here: the installer hangs after a while no matter which DVD I tried.&lt;br /&gt;&lt;br /&gt;My last resort was using a USB stick/drive for installation. I found a nice &lt;a href="http://www.hardwareluxx.de/community/showthread.php?t=643122"&gt;description (german)&lt;/a&gt; on the web, which included the following steps:&lt;br /&gt;&lt;br /&gt;1. create an image of &lt;em&gt;Snow Leopard&lt;/em&gt; using &lt;em&gt;Disk Utility&lt;/em&gt; (I used my wife's MacBook for that)&lt;br /&gt;2. restore that image to your USB stick (I got an &lt;a href="http://www.amazon.de/gp/product/B000J35DR8?ie=UTF8&amp;tag=mytakeonthing-21&amp;linkCode=as2&amp;camp=1638&amp;creative=6742&amp;creativeASIN=B000J35DR8"&gt;8GB stick&lt;/a&gt;)&lt;br /&gt;3. boot from your USB stick (hold option/alt while booting and select the USB drive)&lt;br /&gt;4. run the installer&lt;br /&gt;&lt;br /&gt;My stick didn't work out of the box, I had to reformat it - since it came &lt;em&gt;FAT32&lt;/em&gt; formatted and I had to run &lt;em&gt;"Scan Image for Restore"&lt;/em&gt;, which you can find under the &lt;em&gt;Image&lt;/em&gt; menu in &lt;em&gt;Disk Utility&lt;/em&gt;. After getting my USB drive ready and following the steps above, it worked like a charm. The installation took about an hour and went smoothly, without any problems.&lt;br /&gt;&lt;br /&gt;Although I had so much trouble getting &lt;em&gt;Snow Leopard&lt;/em&gt; installed, it was worth the pain! My system feels much more snappy and responsive now. &lt;em&gt;Snow Leopard&lt;/em&gt; needs less space on my quite limited hard drive and Time Machine backups are reasonably fast now. &lt;br /&gt;&lt;br /&gt;Overall, I'm quite happy jumping though all those hoops to the new &lt;a href="http://www.amazon.de/gp/product/B001AZ3Y66?ie=UTF8&amp;tag=mytakeonthing-21&amp;linkCode=as2&amp;camp=1638&amp;creative=6742&amp;creativeASIN=B001AZ3Y66"&gt;Mac OS X &lt;em&gt;Snow Leopard&lt;/em&gt;&lt;/a&gt;, although the experience wasn't very Apple-like. &lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-8648257461689003239?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/8648257461689003239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=8648257461689003239' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/8648257461689003239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/8648257461689003239'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/11/finally-running-with-snow-leopard.html' title='Finally Running with the Snow Leopard'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-9195950651685202607</id><published>2009-11-16T00:44:00.000+01:00</published><updated>2009-11-18T14:44:20.235+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quality'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><title type='text'>Dependency Injection Obscures Your Code</title><content type='html'>During listening to Software Engineering Radio's &lt;a href="http://www.se-radio.net/podcast/2009-11/episode-148-software-archaeology-dave-thomas"&gt;Episode 148&lt;/a&gt; - "Software Archaeology with Dave Thomas", I got quite annoyed by a comment made by &lt;a href="http://pragdave.pragprog.com/"&gt;one of the respected authors&lt;/a&gt; of "&lt;a href=" http://www.amazon.de/gp/product/020161622X?ie=UTF8&amp;tag=mytakeonthing-21&amp;linkCode=as2&amp;camp=1638&amp;creative=6742&amp;creativeASIN=020161622X"&gt;The Pragmatic Programmer&lt;/a&gt;". &lt;br /&gt;&lt;br /&gt;To quote Dave Thomas correctly, here's what he said at around 23 minutes into the podcast:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;... that is one of the reasons why I, in general, are not very happy with the DI style of development, because I actually think it obscures the code quite a lot, when it comes to reading it ..... what it actually does is, it give you another dimension, that you have to read in order to understand the code.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;My first reaction was "What the deuce!?!". I mean how can someone claim, that &lt;a href="http://en.wikipedia.org/wiki/Dependency_injection"&gt;Dependency Injection&lt;/a&gt; obscures code and makes reading code harder? Are all those hours I spent &lt;a href="http://dlinsin.blogspot.com/search/label/spring"&gt;blogging&lt;/a&gt; and &lt;a href="http://dlinsin.blogspot.com/2008/11/eclipse-rcp-and-inversion-of-control.html"&gt;promoting&lt;/a&gt; DI in vain? Are the &lt;a href="http://www.springsource.org/"&gt;SpringSource&lt;/a&gt; guys wrong or is Dave Thomas just crazy? &lt;br /&gt;&lt;br /&gt;However, his statement and even his argument are completely reasonable, if you listen to the first couple of minutes of the podcast. Dave said at around 11 minutes into the podcast:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;.... actually, I don't typically use an IDE, I use an editor like Textmate on the Mac.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;And there you go! No wonder, you'll find it harder to read and understand code, if you compare the following two screenshots from a bunch of code, using Spring:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh4.ggpht.com/_myUhtr_A51Y/Sv0eQxuLB_I/AAAAAAAAPn0/Qxc4m-7s738/di_1.png?imgmax=800" alt="di_1.png" border="1px" width="652" height="176" align="center"/&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh3.ggpht.com/_myUhtr_A51Y/Sv0wfPnJdbI/AAAAAAAAPoM/fX0-2AcxfJA/di_2.png?imgmax=800" alt="di_2.png" border="1px" width="652" height="176" align="center" /&gt;&lt;br /&gt;&lt;br /&gt;If you are reading the code above and don't understand where those two dependencies in the constructor come from, your &lt;a href="http://www.jetbrains.com/idea/index.html"&gt;IDE&lt;/a&gt; gives you a hint, without leaving the context of that particular file. You know that, they'll be injected by &lt;a href="http://www.springframework.org"&gt;Spring&lt;/a&gt;. In addition to that, you can even directly navigate to the configuration file with a single click.&lt;br /&gt;&lt;br /&gt;Now if you are using a text editor, you really have no idea where to look for. I guess you would have to &lt;em&gt;grep&lt;/em&gt; for &lt;em&gt;new TxTestService()&lt;/em&gt;. In case of using Spring, not even that would give you any more clues.&lt;br /&gt;&lt;br /&gt;Don't get me wrong, if Dave likes &lt;em&gt;Textmate&lt;/em&gt; better than an IDE - fair enough! I just think everyone should use the right tool for the right job! Frankly, &lt;a href="http://dlinsin.blogspot.com/2007/12/reading-code-or-writing-code.html"&gt;an IDE makes a much better job&lt;/a&gt; here than a plain text editor. &lt;br /&gt;&lt;br /&gt;I think the Java world has amazing tooling and in my opinion there's almost the philosophy, that if there is &lt;a href="http://dlinsin.blogspot.com/search/label/git"&gt;no tool support for a technology&lt;/a&gt; - it sucks. I don't fully agree with that. However, I do think that, when it comes to Java, tool support can definitely &lt;br /&gt;assist you reading and thus understanding code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-9195950651685202607?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/9195950651685202607/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=9195950651685202607' title='14 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/9195950651685202607'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/9195950651685202607'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/11/dependency-injection-obscures-your-code.html' title='Dependency Injection Obscures Your Code'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-4219458025070582877</id><published>2009-11-06T05:44:00.003+01:00</published><updated>2009-11-17T02:28:35.072+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='karlsruhe'/><category scheme='http://www.blogger.com/atom/ns#' term='web development'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='jug-ka'/><title type='text'>RESTful applications in practise @ JUG-Ka</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://picasaweb.google.com/lh/photo/zDGbEVVB5ihDeoGRJltMvA?authkey=Gv1sRgCKXY3MiLxprXDQ&amp;feat=embedwebsite"&gt;&lt;img style="float:left;margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://lh4.ggpht.com/_myUhtr_A51Y/SnWVogdEjOI/AAAAAAAAPiQ/o9MjIPCDE_s/s144/jug_logo_original_transparent.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5191388009271083842" /&gt;&lt;/a&gt;This coming &lt;a href="https://www.xing.com/events/rest-praxis-entwerfen-restful-applikationen-392973"&gt;Wednesday&lt;/a&gt; Gregor Roth from 1&amp;1, you might know him from his &lt;a href="http://www.infoq.com/articles/designing-restful-http-apps-roth"&gt;InfoQ article&lt;/a&gt;, is going to give a talk on &lt;a href="http://en.wikipedia.org/wiki/Representational_State_Transfer"&gt;RESTful&lt;/a&gt; applications at the &lt;a href="https://jug-ka.dev.java.net/"&gt;Java User Group Karlsruhe&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;He will show how to implement applications leveraging a RESTful architecture and point out the mismatch between a RESTful and &lt;a href="http://en.wikipedia.org/wiki/Remote_procedure_call"&gt;RPC&lt;/a&gt;-style approach. Furthermore Gregor will highlight the difference between HTTP PUT and POST and finally demonstrate how to implement none CRUD operations using REST. &lt;br /&gt;&lt;br /&gt;I'm really looking forward to this talk. In &lt;a href="http://dlinsin.blogspot.com/2009/10/google-sitebricks.html"&gt;my spare time&lt;/a&gt; I developed the &lt;a href="http://dlinsin.blogspot.com/2009/05/make-it-easy-to-contribute.html"&gt;REST interface&lt;/a&gt; for an &lt;a href="http://doublemill.blogspot.com/"&gt;Android game&lt;/a&gt; and it's going to be interesting to see what we could have done better and hopefully what we've got right.&lt;br /&gt;&lt;br /&gt;As usual, the talk will be held at &lt;a href="http://groups.google.com/group/jug-karlsruhe/web/how-to-find-us?_done=%2Fgroup%2Fjug-karlsruhe%3F"&gt;University Karlsruhe&lt;/a&gt; in room 102, which is located in the basement. We'll start at 7:15pm, if the door opens as planned this time.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.jetbrains.net"&gt;JetBrains&lt;/a&gt; and &lt;a href="http://www.zeroturnaround.com"&gt;ZeroTurnaround&lt;/a&gt; are each giving away a free license of one of their products. If you are interested in participating in our monthly lottery, send me an email. The winners will be announced at the end of the talk. In addition to that, &lt;a href="http://www.atlassian.com/"&gt;Atlassian&lt;/a&gt; sponsored a couple of great T-Shirts, which you can pick up at the end of the talk.&lt;br /&gt;&lt;br /&gt;If you want to know more about upcoming talks, subscribe to our &lt;a href="http://www.google.com/calendar/embed?src=ehlt6rbl1cd1s2b7t9bkj6beek%40group.calendar.google.com&amp;ctz=Europe/Berlin"&gt;Google Calendar&lt;/a&gt;. You'll also be able to see the planned talks for 2010.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-4219458025070582877?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/4219458025070582877/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=4219458025070582877' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/4219458025070582877'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/4219458025070582877'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/11/restful-applications-in-practise-jug-ka.html' title='RESTful applications in practise @ JUG-Ka'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_myUhtr_A51Y/SnWVogdEjOI/AAAAAAAAPiQ/o9MjIPCDE_s/s72-c/jug_logo_original_transparent.png' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-5765095529026510336</id><published>2009-11-02T05:44:00.000+01:00</published><updated>2009-11-02T05:49:24.483+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Having Fun with JDK's tools.jar</title><content type='html'>This week I had to trace a bug in a legacy application, I'm maintaining at the moment, which drove me up the wall. The application uses a class from JDK's &lt;em&gt;tools.jar&lt;/em&gt;, to determine the JVM instances currently running. Unfortunately, there are incompatibilities between JDK versions.&lt;br /&gt;&lt;br /&gt;Tracking down the bug took a humongous amount of time, because the fun part of working on a &lt;a href="http://dlinsin.blogspot.com/2007/12/reading-code-or-writing-code.html"&gt;legacy application&lt;/a&gt; is that all the developers, which are responsible for &lt;a href="http://dlinsin.blogspot.com/2007/07/hell-is-other-peoples-code.html"&gt;the code you are maintaining&lt;/a&gt;, are usually no longer available. Don't even get me started on documentation! However, as a &lt;a href="http://dlinsin.blogspot.com/2009/02/do-you-write-unit-tests-for-yourself.html"&gt;good developer&lt;/a&gt;, I created the following JUnit test, to isolate the problem from the rest of the code.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/221475.js"&gt;&lt;/script&gt;&lt;noscript&gt;&lt;pre&gt;package de.linsin.sample.tools.bug;&lt;br /&gt;&lt;br /&gt;import static org.junit.Assert.*;&lt;br /&gt;&lt;br /&gt;import com.sun.tools.attach.VirtualMachine;&lt;br /&gt;import com.sun.tools.attach.VirtualMachineDescriptor;&lt;br /&gt;&lt;br /&gt;public class ToolsJarTest {&lt;br /&gt;    @Test&lt;br /&gt;    public void testJVMInstances() {&lt;br /&gt;        assertTrue(VirtualMachine.list() &gt; 0);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/noscript&gt;&lt;br /&gt;If you run this test with Sun's JRE 1.6 and &lt;em&gt;tools.jar&lt;/em&gt; of Sun's JDK 1.6 on the classpath, you won't encounter an problems. However, with my current project, we need backward compatibility with other Java versions. That means, there are multiple &lt;em&gt;tools.jar&lt;/em&gt; on the &lt;em&gt;classpath&lt;/em&gt;, in different versions. Depending on their order, the test above fails or succeeds. &lt;br /&gt;&lt;br /&gt;More precisely, there is a JDK 1.4 and 1.5 version of &lt;em&gt;tools.jar&lt;/em&gt; on the &lt;em&gt;classpath&lt;/em&gt;, in addition to the 1.6 version. 1.6 is needed, because in previous JDKs the class VirtualMachine doesn't reside in the package &lt;em&gt;com.sun.tools.attach&lt;/em&gt;. So running the test without &lt;em&gt;tools.jar&lt;/em&gt; in version 1.6, you'll get a &lt;em&gt;NoClassDefFoundError&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;So what's the problem you might ask? As long as &lt;em&gt;tools.jar&lt;/em&gt; of JDK 1.6 is on the &lt;em&gt;classpath&lt;/em&gt;, when running the aforementioned test, everything should be okay, right? It should be, but it isn't. As soon as &lt;em&gt;tools.jar&lt;/em&gt; of JDK 1.5 is before the 1.6 version on the runtime &lt;em&gt;classpath&lt;/em&gt;, the test fails. Every other combination works just fine. &lt;br /&gt;&lt;br /&gt;Why &lt;em&gt;tools.jar&lt;/em&gt; of JDK 1.5 causes this problem is a mystery to me. Sun's bug parade, doesn't contain any &lt;a href=" http://blogs.sun.com/jmxetc/entry/how_to_retrieve_remote_jvm"&gt;relevant information&lt;/a&gt; - at least I couldn't find any. Frankly, I think this problem is so absurd, that I cannot motivate myself getting to the bottom of it. &lt;br /&gt;&lt;br /&gt;Nevertheless, the problem exists in our application and we'll have to find a solution. I guess that's the reason why it's a legacy application - I have to deal with problems that are totally outdated and nobody knows the answer to.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-5765095529026510336?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/5765095529026510336/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=5765095529026510336' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/5765095529026510336'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/5765095529026510336'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/11/having-fun-with-jdk-toolsjar.html' title='Having Fun with JDK&amp;#39;s tools.jar'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-9187732692649265861</id><published>2009-10-26T05:35:00.000+01:00</published><updated>2009-10-26T05:35:53.880+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web development'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>Push IRC messages to your iPhone</title><content type='html'>In my &lt;a href="http://www.synyx.de"&gt;new company&lt;/a&gt; one of the main communication channels is &lt;a href="http://en.wikipedia.org/wiki/Internet_Relay_Chat"&gt;IRC&lt;/a&gt;. Unfortunately, I'm &lt;a href="http://dlinsin.blogspot.com/2008/06/how-corporation-constrain-productivity.html"&gt;not able to hang out on IRC&lt;/a&gt; all day. That means, I'm not only missing interesting discussions, but I'm also always the last to get to know about interesting developments. To put an end to my offline-misery, I came up with a solution to push IRC messages to my iPhone.&lt;br /&gt;&lt;br /&gt;First a couple of things you need to know. You'll need an &lt;a href="http://bit.ly/19T8V7"&gt;iPhone app to receive push notifications&lt;/a&gt;, more about that later on. Furthermore, you'll need a server, which is able to host a Java-based IRC bot.&lt;br /&gt;&lt;br /&gt;The bot is leveraging the famouse &lt;a href="http://www.jibble.org/pircbot.php"&gt;PircBot&lt;/a&gt; library, which &lt;a href="http://dlinsin-archives.blogspot.com/2005/08/conversation-with-erich-gamma.html"&gt;unfortunately is based on inheritance&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/208294.js"&gt;&lt;/script&gt;&lt;noscript&gt;&lt;pre&gt;public class Bot extends PircBot {&lt;br /&gt;    private boolean silentMode = false;&lt;br /&gt;    private Collection&lt;NotificationService&gt; notificationServices;&lt;br /&gt; &lt;br /&gt;    private Collection&lt;String&gt; messages;&lt;br /&gt;    private Timer messagesTimer;&lt;br /&gt;    static final int MESSAGE_BATCH_SIZE = 20;&lt;br /&gt;    static final int MESSAGE_BATCH_DELAY_MS = 60000;&lt;br /&gt; &lt;br /&gt;    @Override&lt;br /&gt;    protected void onMessage(String argChannel, String argSender, String argLogin, String argHostname, String argMessage) {&lt;br /&gt;        batchMessages(format(argSender, argMessage));&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    @Override&lt;br /&gt;    protected void onJoin(String argChannel, String argSender, String argLogin, String argHostname) {&lt;br /&gt;        User[] users = super.getUsers(argChannel);&lt;br /&gt;        switchSilentMode(users);&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    @Override&lt;br /&gt;    protected void onQuit(String argChannel, String argSender, String argLogin, String argHostname) {&lt;br /&gt;        User[] users = super.getUsers(argChannel);&lt;br /&gt;        switchSilentMode(users);&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    private void switchSilentMode(User[] argUsers) {&lt;br /&gt;        for (int i = 0; i &lt; argUsers.length; i++) {&lt;br /&gt;            User user = argUsers[i];&lt;br /&gt;            if (user.getNick().equals(alterEgoName)) {&lt;br /&gt;                silentMode = true;&lt;br /&gt;                return;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        silentMode = false;&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    private void batchMessages(String argMessage) {&lt;br /&gt;        if (messages.isEmpty()) {&lt;br /&gt;            messages.add(argMessage);&lt;br /&gt;            messagesTimer.schedule(new TimerTask() {&lt;br /&gt;                public void run() {&lt;br /&gt;                    processMessages();&lt;br /&gt;                    messagesTimer.purge();&lt;br /&gt;                }&lt;br /&gt;            }, MESSAGE_BATCH_DELAY_MS);&lt;br /&gt;        } else if (messages.size() &lt; MESSAGE_BATCH_SIZE) {&lt;br /&gt;            messages.add(argMessage);&lt;br /&gt;        } else {&lt;br /&gt;            processMessages();&lt;br /&gt;            messagesTimer.purge();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    private void processMessages() {&lt;br /&gt;        StringBuilder builder = new StringBuilder();&lt;br /&gt;        for (String message : messages) {&lt;br /&gt;            builder.append(message).append("\n");&lt;br /&gt;        }&lt;br /&gt;        sendToService("message", builder.toString());&lt;br /&gt;        messages.clear();&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    private void sendToService(String argTitle, String argMessage) {&lt;br /&gt;        for (NotificationService service : notificationServices) {&lt;br /&gt;            if (!silentMode) {&lt;br /&gt;                service.notify(argTitle, argMessage);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/noscript&gt;I stripped out some of the code, you can find the full version on &lt;a href="http://github.com/dlinsin/area51/blob/master/alterego/src/main/java/de/linsin/alterego/Bot.java"&gt;GitHub&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The usage of PircBot, as you can see above (line 11, 16 and 22), is quite easy. You simply override the methods you want to hook into, and execute your code. That's pretty much all the magic that is to PircBot. In order to limit the notifications pushed to the iPhone, I batch a certain number of messages for a pre-configured time and eventually send them to a &lt;em&gt;NotificationService&lt;/em&gt;. I'll come back to the &lt;em&gt;NotificationService&lt;/em&gt; in a second, but there's another feature I'd like to point out - silent mode. I don't want to be notified on my iPhone, when I'm actually on IRC myself. So whenver a pre-configured user enters the channel, the Bot will switch to silent mode. As soon as the user leaves the channel, it'll switch back. &lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/208326.js"&gt;&lt;/script&gt;&lt;noscript&gt;&lt;pre&gt;public class AppNotificationService implements NotificationService {&lt;br /&gt;    private final String credentials;&lt;br /&gt;    public static final String USER_CREDENTIALS = "user_credentials";&lt;br /&gt;    public static final String NOTIFICATION_LONG_MESSAGE = "notification[long_message]";&lt;br /&gt;    public static final String NOTIFICATION_TITLE = "notification[title]";&lt;br /&gt;    public static final String MESSAGE_LEVEL = "message_level";&lt;br /&gt;    public static final String URL = "https://www.appnotifications.com/account/notifications.xml";&lt;br /&gt;    public static final String HTTP_USERAGENT = "http.useragent";&lt;br /&gt; &lt;br /&gt;    public AppNotificationService(String argCredentials) {&lt;br /&gt;        credentials = argCredentials;&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    public boolean notify(String argTitle, String argMessage) {&lt;br /&gt;        HttpClient client;&lt;br /&gt;        PostMethod method = null;&lt;br /&gt;        try {&lt;br /&gt;            client = setUp();&lt;br /&gt;            method = setUp(argTitle, argMessage);&lt;br /&gt;            int returnCode = client.executeMethod(method);&lt;br /&gt; &lt;br /&gt;            if (returnCode &gt; HttpStatus.SC_OK) {&lt;br /&gt;                return false;&lt;br /&gt;            } else {&lt;br /&gt;                logger.info("Sent notification!");&lt;br /&gt;                return true;&lt;br /&gt;            }&lt;br /&gt;        } catch (Exception e) {&lt;br /&gt;            throw new AppNotificationException();&lt;br /&gt;        } finally {&lt;br /&gt;            if (method != null) {&lt;br /&gt;                method.releaseConnection();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    HttpClient setUp() {&lt;br /&gt;        HttpClient client = new HttpClient();&lt;br /&gt;        client.getParams().setParameter(HTTP_USERAGENT, "IRC Bot");&lt;br /&gt;        return client;&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    PostMethod setUp(String argTitle, String argMessage) {&lt;br /&gt;        PostMethod method = new PostMethod(URL);&lt;br /&gt;        method.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");&lt;br /&gt; &lt;br /&gt;        method.addParameter(USER_CREDENTIALS, credentials);&lt;br /&gt;        method.addParameter(NOTIFICATION_LONG_MESSAGE, argMessage);&lt;br /&gt;        method.addParameter(NOTIFICATION_TITLE, argTitle);&lt;br /&gt;        method.addParameter(MESSAGE_LEVEL, "2");&lt;br /&gt;        return method;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/noscript&gt;As you can see, the &lt;em&gt;NotificationService&lt;/em&gt; implementation, simply makes a Http Post request to a service called &lt;a href="http://www.appnotifications.com"&gt;App Notifications&lt;/a&gt;. The request contains a couple of &lt;em&gt;key/value pairs&lt;/em&gt;, which are used to configure your iPhone's push notifications. &lt;br /&gt;&lt;br /&gt;I'm using &lt;a href="http://hc.apache.org/httpcomponents-client/httpclient/"&gt;Commons HttpClient&lt;/a&gt; to makes the Post request, since I have &lt;a href="http://dlinsin.blogspot.com/2009/08/http-basic-authentication-with-android.html"&gt;some experience&lt;/a&gt; with it. In order to use App Notifications, you'll need to setup an account. After the setup, you'll receive a credential String, which must be passed along with the Post request. &lt;br /&gt;&lt;br /&gt;The only part missing is the iPhone app, that you need, in order to receive push notifications. The app is not free, but it's quite reasonable. Actually it's a good deal to pay for the app once and not on a request or monhtly bases. However, keep in mind, that the app can only receive push notifications - nothing else. If you that's what you need, this app is for you.&lt;br /&gt;&lt;br /&gt;Putting together all parts of the puzzle, you'll get an IRC bot, which connects to the channel you want to be notified about. The bot batches messages and sends them to a service, which in turn pushes them to your iPhone. On your iPhone you have the notification app, which displays the messages from IRC.&lt;br /&gt;&lt;br /&gt;The App Notification service is very reliable and super fast. However, there is one downside to the iPhoen app. You cannot switch off the notification sound without also switching off the vibration feedback. The App Notification developer told me, he'll address this issue in a future update. &lt;br /&gt;&lt;br /&gt;I also had to play with the batch size and delay, since there are a lot of messages on the channel, I'm interested in and it got quite irratating getting pounded with notifications constantly. &lt;br /&gt;&lt;br /&gt;Overall, I do admit, that this combination is quite adventurous, but it works very well. If you'd like to check it out, grab the &lt;a href="http://github.com/dlinsin/area51/blob/master/alterego/"&gt;code from GitHub&lt;/a&gt; and let me know what you think.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-9187732692649265861?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/9187732692649265861/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=9187732692649265861' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/9187732692649265861'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/9187732692649265861'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/10/push-irc-messages-to-your-iphone.html' title='Push IRC messages to your iPhone'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-7354783281697002994</id><published>2009-10-21T06:09:00.000+02:00</published><updated>2009-11-17T02:30:50.688+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='karlsruhe'/><category scheme='http://www.blogger.com/atom/ns#' term='jboss rules'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='jug-ka'/><title type='text'>jBPM 4 @ JUG-Ka</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://picasaweb.google.com/lh/photo/zDGbEVVB5ihDeoGRJltMvA?authkey=Gv1sRgCKXY3MiLxprXDQ&amp;feat=embedwebsite"&gt;&lt;img style="float:left;margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://lh4.ggpht.com/_myUhtr_A51Y/SnWVogdEjOI/AAAAAAAAPiQ/o9MjIPCDE_s/s144/jug_logo_original_transparent.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5191388009271083842" /&gt;&lt;/a&gt;Today I'm pleased to welcome &lt;a href="http://www.camunda.com/content/view/83/"&gt;Bernd Rücker&lt;/a&gt; from &lt;a href="http://www.camunda.com/"&gt;camunda services GmbH&lt;/a&gt; to the &lt;a href="https://jug-ka.dev.java.net/"&gt;Java User Group Karlsruhe&lt;/a&gt;. Bernd is going to talk about the Open Source Business Process Engine &lt;a href="http://www.jboss.com/products/jbpm/"&gt;JBoss jBPM&lt;/a&gt;. I'm really excited about this talk, because it's a &lt;a href="http://dlinsin.blogspot.com/search/label/jboss%20rules"&gt;topic&lt;/a&gt; I was quite dedicated to a couple of years ago.&lt;br /&gt;&lt;br /&gt;The session takes place today at &lt;a href="http://groups.google.com/group/jug-karlsruhe/web/how-to-find-us?_done=%2Fgroup%2Fjug-karlsruhe%3F"&gt;University Karlsruhe&lt;/a&gt;, building 50.34 in the multimedia room 102, located in the basement. The talk starts at 7:15pm, our usual timing.&lt;br /&gt;&lt;br /&gt;There will also be our monthly lottery, where &lt;a href="http://www.jetbrains.net"&gt;JetBrains&lt;/a&gt; and &lt;a href="http://www.zeroturnaround.com"&gt;ZeroTurnaround&lt;/a&gt; are each giving away a free license of one of their products. If you are interested in participating in the draw send me an email. The winners are going to be announced at the end of the talk. &lt;br /&gt;&lt;br /&gt;There are still two more great talks coming up this year. You can subscribe to our &lt;a href="http://www.google.com/calendar/embed?src=ehlt6rbl1cd1s2b7t9bkj6beek%40group.calendar.google.com&amp;ctz=Europe/Berlin"&gt;Google Calendar&lt;/a&gt; to get the latest updates. There's also a &lt;a href="http://groups.google.com/group/jug-karlsruhe"&gt;Google&lt;/a&gt; or &lt;a href="https://www.xing.com/net/jug-karlsruhe/"&gt;Xing Group&lt;/a&gt; to stay on top of things.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-7354783281697002994?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/7354783281697002994/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=7354783281697002994' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/7354783281697002994'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/7354783281697002994'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/10/jbpm-4-jug-ka.html' title='jBPM 4 @ JUG-Ka'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_myUhtr_A51Y/SnWVogdEjOI/AAAAAAAAPiQ/o9MjIPCDE_s/s72-c/jug_logo_original_transparent.png' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-4467498567363753578</id><published>2009-10-19T05:45:00.000+02:00</published><updated>2009-10-19T06:02:57.353+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='spring'/><category scheme='http://www.blogger.com/atom/ns#' term='osgi'/><title type='text'>Spring DM with Annotations</title><content type='html'>A couple of days ago, I implemented a sample application, based on &lt;a href="http://www.springsource.org/osgi"&gt;Spring Dynamic Modules (DM) 1.2.0&lt;/a&gt;, with its &lt;a href="http://static.springsource.org/osgi/docs/1.2.0/reference/html/appendix-extensions.html#appendix-extensions:annotations"&gt;annotation extension&lt;/a&gt;. Unfortunately the documentation doesn't contain any sample code, which might cause some unnecessary work, if you are not too familiar with Spring DM.&lt;br /&gt;&lt;br /&gt;Spring DM's annotation extension allows you to pull in an OSGi service reference by annotating a setter of a property:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/205746.js"&gt;&lt;/script&gt;&lt;noscript&gt;&lt;pre&gt;import org.springframework.osgi.extensions.annotation.ServiceReference;&lt;br/&gt;&lt;br /&gt;public class MyService {&lt;br /&gt;  private LogService logService;&lt;br/&gt;&lt;br /&gt;  @ServiceReference(cardinality=ServiceReferenceCardinality.C0__1)&lt;br /&gt;  public void setLogService(LogService argLogService) {&lt;br /&gt;    logService= argLogService;&lt;br /&gt;  }&lt;br /&gt;  // other stuf&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;br /&gt;Unfortunately, you don't get rid of the XML configuration completely, but that's not so bad after all, because you still want to let Spring to all your wiring:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/205762.js"&gt;&lt;/script&gt;&lt;noscript&gt;&lt;pre&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;beans xmlns="http://www.springframework.org/schema/beans" &lt;br/&gt;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" &lt;br/&gt;xsi:schemaLocation="http://www.springframework.org/schema/beans  &lt;br/&gt;http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"&amp;gt;&lt;br /&gt;&lt;br/&gt;&amp;lt;bean class="org.springframework.osgi.extensions.annotation.ServiceReferenceInjectionBeanPostProcessor"/&amp;gt;&lt;br /&gt;&amp;lt;bean id="testService" class="de.linsin.sample.springdm.MyService"/&amp;gt;&lt;br /&gt;&lt;br/&gt;&amp;lt;/beans&amp;gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;br /&gt;In addition to the instantion part, you need to configure a &lt;em&gt;BeanPostProcessor&lt;/em&gt;. It tells Spring to handle your methods annotated with &lt;em&gt;@ServiceReference&lt;/em&gt;. If you want all your bundles to use annotations, this might get a little tedious. That's why you can configure annotation processing for all bundles, by defining a &lt;em&gt;fragment bundle&lt;/em&gt;, which overrides the default configuration of &lt;em&gt;Spring DM's extender&lt;/em&gt;:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/205769.js"&gt;&lt;/script&gt;&lt;noscript&gt;&lt;pre&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;beans xmlns="http://www.springframework.org/schema/beans" &lt;br /&gt;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   &lt;br /&gt;xmlns:util="http://www.springframework.org/schema/util" &lt;br /&gt;xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/util  http://www.springframework.org/schema/util/spring-util-2.0.xsd"&amp;gt;&lt;br /&gt;&lt;br/&gt;&amp;lt;util:properties id="extenderProperties"&amp;gt;&lt;br /&gt;&amp;lt;prop key="process.annotations"&amp;gt;true&amp;lt;/prop&amp;gt;&lt;br /&gt;&amp;lt;/util:properties&amp;gt;&lt;br /&gt;&lt;br/&gt;&amp;lt;/beans&amp;gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;br /&gt;Unfortunately, the configuration of the &lt;em&gt;fragement bundle&lt;/em&gt; is &lt;a href="http://jira.springframework.org/browse/OSGI-765"&gt;not&lt;/a&gt; in the &lt;a href="http://static.springsource.org/osgi/docs/1.2.0/reference/html/app-deploy.html#app-deploy:extender-configuration"&gt;offical documentation&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Now, that you've got a glimpse of how to use annotations with Spring DM and the ways of configuring it, you might ask whether you want to use it or not? For me this boils down to the &lt;a href="http://dlinsin.blogspot.com/2007/04/guice-di-framework.html"&gt;question&lt;/a&gt;, whether you want to have your dependencies in your &lt;a href="http://dlinsin.blogspot.com/2008/07/configuration-notations.html"&gt;xml file&lt;/a&gt; or in your code?&lt;br /&gt;&lt;br /&gt;It's a tricky question and I think annotations only bring real value, if they make your life easier. Let's take a look at &lt;a href="http://static.springsource.org/spring/docs/2.5.x/reference/mvc.html"&gt;Spring's Web MVC&lt;/a&gt; for example: before annotations were introduced, you had to implement an interface in order to code a controller and thus you had dependencies on javax.servlet in your controller code. Spring Web MVC's annotation approach still leaves you with the dependency on Spring, but eliminates the javax.servlet dependency. &lt;br /&gt;&lt;br /&gt;In addition to that, it improves &lt;a href="http://www.olivergierke.de/wordpress/2009/05/unit-testing-annotation-based-spring-mvc-controllers/"&gt;testability of controller classes&lt;/a&gt; significantly, which I think is worth living with the dependency on Spring. &lt;br /&gt;&lt;br /&gt;I think, that the features of Spring DM annotations, at least at the moment, are not compelling enough to have dependencies on it in your code. With the right tooling, Spring's XML configuration should be as easy to handle as annotations.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-4467498567363753578?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/4467498567363753578/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=4467498567363753578' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/4467498567363753578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/4467498567363753578'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/10/spring-dm-with-annotations.html' title='Spring DM with Annotations'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-4652803423157516326</id><published>2009-10-12T05:48:00.000+02:00</published><updated>2009-10-12T05:48:00.223+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='spring'/><category scheme='http://www.blogger.com/atom/ns#' term='osgi'/><title type='text'>Book Review Dynamic Modules for OSGi</title><content type='html'>&lt;span style="font-style:italic;"&gt;&lt;a href="http://www.apress.com"&gt;Apress&lt;/a&gt; was kind enough to pass me a copy of this book, which I agreed to review in return.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.amazon.de/gp/product/1430216123?ie=UTF8&amp;tag=mytakeonthing-21&amp;linkCode=as2&amp;camp=1638&amp;creative=6742&amp;creativeASIN=1430216123"&gt;&lt;img style="float:left;margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://lh5.ggpht.com/_myUhtr_A51Y/SbjfrBLw6rI/AAAAAAAANTI/gCOR_SSMrP0/9781430216124.gif" border="0" alt=""id="" /&gt;&lt;/a&gt;I have been sitting on &lt;a href="http://www.amazon.de/gp/product/1430216123?ie=UTF8&amp;tag=mytakeonthing-21&amp;linkCode=as2&amp;camp=1638&amp;creative=6742&amp;creativeASIN=1430216123"&gt;Pro Spring Dynamic Modules for Osgi(tm) Service Platforms&lt;/a&gt; for a while, although I got a fresh copy right after if was released earlier this year. &lt;br /&gt;&lt;br /&gt;One reason for this might be, that after reading the first chapter, it felt like I was reading a manual rather than a book. Personally, I like a little bit more subjectiveness, because it improves the reading experience significantly. The author should spice up the dry material, so you won't get bored that easily. Unfortunately, that's what happened to me - I got bored. However, let's turn the spotlight to the content of the book.&lt;br /&gt;&lt;br /&gt;The introduction chapter on OSGi is sufficient to get you up to speed. There are about 60 pages of Spring introduction. However, I think you should at least have some practical experiences with Spring, before digging into Spring Dynamic Modules or even Spring DM Server. It's simply not enough to explain the technicalities, to get someone an understanding of what Spring an its concepts is all about. &lt;br /&gt;&lt;br /&gt;There's lot's of code in the book, which you can &lt;a href="http://apress.com/book/view/1430216123"&gt;download&lt;/a&gt; and play with. If you like to read code, printed in a book, you are probably gonna like "Pro Spring Dynamic Modules for Osgi". For me, a book is not the preffered media to consume code. I have nothing against small code samples, but having pages over pages full of code, is really confusing and hurts readability.&lt;br /&gt;&lt;br /&gt;The manual kind of feeling of the book continues the further you keep reading. Let me give you a concrete example: In chapter 4, called "Spring Dynamic Modules for OSGi", the author explains how the &lt;em&gt;scope&lt;/em&gt; attribute of a bean declaration works:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/201243.js"&gt;&lt;/script&gt;&lt;noscript&gt;&lt;pre&gt;&amp;lt;bean id="beanToBeExported" scope="bundle" class="com.xyz.MessageServiceImpl"/&amp;gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;br /&gt;Unfortunately, the &lt;i&gt;how&lt;/i&gt; is all there is to the explanation. I expected a real life example of when to use the &lt;em&gt;scope&lt;/em&gt; attribute and where it might not be suitable. I do understand, that the book can't go into details all the time, but especially those powerful Spring  DM features like &lt;em&gt;scoping&lt;/em&gt;, deserve more spotlight. Most of the time, the book stops when it gets interesting and you are left with your own imagination of how to apply that particular feature. &lt;br /&gt;&lt;br /&gt;Despite the criticism, I got some neat tips from the book. The author suggests to split the OSGi dependent and traditional Spring configuration to make life easier for testing and mocking. I also gained a lot of knowledge from chapter 6, called "Versioning with OSGi and Spring". The author explains the concepts and implementation of versioning most of the time in a very understandable manner. &lt;br /&gt;&lt;br /&gt;Overall, I think &lt;a href="http://www.amazon.de/gp/product/1430216123?ie=UTF8&amp;tag=mytakeonthing-21&amp;linkCode=as2&amp;camp=1638&amp;creative=6742&amp;creativeASIN=1430216123"&gt;Pro Spring Dynamic Modules for Osgi(tm) Service Platforms&lt;/a&gt; is a reasonable reference book, with a nice sample application. If you are new to Spring and OSGi, you might have a hard time understanding the use case for those technologies, so I'd suggest to get this book as an addition to some &lt;a href="http://dlinsin.blogspot.com/2008/05/book-review-building-spring-2.html"&gt;basic reading material&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-4652803423157516326?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/4652803423157516326/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=4652803423157516326' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/4652803423157516326'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/4652803423157516326'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/10/book-review-dynamic-modules-for-osgi.html' title='Book Review Dynamic Modules for OSGi'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-1726305450030689571</id><published>2009-10-05T05:45:00.002+02:00</published><updated>2009-10-05T09:02:18.646+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web development'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='guice'/><category scheme='http://www.blogger.com/atom/ns#' term='google'/><title type='text'>Google Sitebricks</title><content type='html'>Last week I stumbled upon an &lt;a href="http://www.infoq.com/news/2009/09/google-sitebricks"&gt;interview on InfoQ&lt;/a&gt; with a Google developer working on a new web framework called &lt;a href="http://code.google.com/p/google-sitebricks/"&gt;Google Sitebricks&lt;/a&gt;. On my research day at &lt;a href="http://www.synyx.de"&gt;Synyx&lt;/a&gt;, I had time to produce some &lt;a href="http://github.com/dlinsin/area51/tree/master/google-sitebricks-sample/"&gt;sample code&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Google's mission statement goes as follows:&lt;br /&gt;&lt;blockquote&gt;Sitebricks is a simple development layer for web applications built on top of Google Guice. Sitebricks focuses on early error detection, low-footprint code, and fast development. Like Guice, it also balances idiomatic Java with an emphasis on concise code.&lt;/blockquote&gt;&lt;br /&gt;A &lt;em&gt;Sitebrick&lt;/em&gt; based web-application is deployed as a good old WAR file in a servlet container. That's the first information not explicitly stated on the website. If you have worked with another web framework before, you probably know the concept of a controller or a REST-based Resource. You can find the same concept in &lt;em&gt;Sitebricks&lt;/em&gt;, too:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/200631.js"&gt;&lt;/script&gt;&lt;noscript&gt;&lt;pre&gt;@At("/guestbook")&lt;br /&gt;public class Guestbook {&lt;br /&gt;private List&lt;entry&gt; entries;&lt;br /&gt;private Entry newEntry = new Entry();&lt;br /&gt;&lt;br /&gt;@Inject&lt;br /&gt;private EntryDao entryDao;&lt;br /&gt;&lt;br /&gt;public List&lt;entry&gt; getEntries() {&lt;br /&gt;return entries;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Get&lt;br /&gt;public void load() {&lt;br /&gt;entries = entryDao.readAll();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Post&lt;br /&gt;public String save() {&lt;br /&gt;newEntry.setDate(new Date());&lt;br /&gt;Integer id = entryDao.save(newEntry);&lt;br /&gt;return String.format("/sample/guestbook/%1$s", id);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public Entry getNewEntry() {&lt;br /&gt;return newEntry;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void setNewEntry(Entry argNewEntry) {&lt;br /&gt;newEntry = argNewEntry;&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;&lt;/noscript&gt;&lt;br /&gt;You can see that the class is pretty simple and it reminds me a lot of &lt;a href="http://dlinsin.blogspot.com/2009/05/make-it-easy-to-contribute.html"&gt;Restlet&lt;/a&gt;, which I used extensively the past few months. With the &lt;em&gt;At&lt;/em&gt; annotation you declare the &lt;em&gt;Uri&lt;/em&gt; under which your resource should be available. You can also define variable parts in your &lt;em&gt;Uri&lt;/em&gt;, e.g. &lt;em&gt;/guestbook/:id&lt;/em&gt;, which is &lt;a href="http://github.com/dlinsin/area51/blob/master/google-sitebricks-sample/src/de/linsin/sample/sitebricks/resource/GuestbookEntry.java"&gt;used in my sample&lt;/a&gt; to access an entry of the guestbook.&lt;br /&gt;&lt;br /&gt;The methods annotated with &lt;em&gt;Get&lt;/em&gt; and &lt;em&gt;Post&lt;/em&gt; are being called upon a request with the corresponding method. If you take a closer look at the method &lt;em&gt;load()&lt;/em&gt;, you can see, that it doesn't return any value. That's where the convention or should I call it magic, of the framework begins:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/200638.js"&gt;&lt;/script&gt;&lt;noscript&gt;&lt;pre&gt;&amp;lt;body&amp;gt;&lt;br /&gt;@Repeat(items=entries, var="entry")&lt;br /&gt;&amp;lt;p&amp;gt;&lt;br /&gt;&amp;lt;a href="/guestbook/${entry.id}"&amp;gt;${entry.id} on ${entry.date}&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;form action="/guestbook" method="post"&amp;gt;&lt;br /&gt;&lt;br /&gt;Name: &amp;lt;input name="newEntry.name" type="text"/&amp;gt;&lt;br /&gt;&lt;br /&gt;Text: &amp;lt;input name="newEntry.text" type="text"/&amp;gt;&lt;br /&gt;&amp;lt;input type="submit" value="save" name="save"/&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;br /&gt;In your &lt;em&gt;Html&lt;/em&gt; file, that you define along with your resource, there are expressions, that access members of your resource class. In the &lt;a href="http://github.com/dlinsin/area51/blob/master/google-sitebricks-sample/web/Guestbook.html"&gt;&lt;em&gt;Html&lt;/em&gt; snippet above&lt;/a&gt; we iterate over a &lt;em&gt;Collection&lt;/em&gt; named "entries". It's a member of the &lt;a href="http://github.com/dlinsin/area51/blob/master/google-sitebricks-sample/src/de/linsin/sample/sitebricks/resource/Guestbook.java"&gt;Guestbook class&lt;/a&gt; and is assigned whenever there's a &lt;em&gt;Get&lt;/em&gt; request, which triggers the method &lt;em&gt;load()&lt;/em&gt; to be called. The expression &lt;em&gt;items=entries&lt;/em&gt; calls the &lt;em&gt;getEntries()&lt;/em&gt; method on &lt;em&gt;Guestbook&lt;/em&gt;, to return the &lt;em&gt;Collection&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Frankly, this strikes me kinda odd. You call a method to populate a member and then its getter to retrieve the value? Shouldn't the annotated &lt;em&gt;Get&lt;/em&gt; method return the value directly? I'm not quite sure what the design goal was here, but the first thing that comes into my mind is concurrency. If your &lt;em&gt;resource&lt;/em&gt; class is a &lt;em&gt;Singleton&lt;/em&gt;, you could run into quite some trouble.&lt;br /&gt;&lt;br /&gt;Take a look at the form in the &lt;em&gt;Html&lt;/em&gt; snipped above. It has two input fields, which are properties, mapped by name to the member &lt;em&gt;newEntry&lt;/em&gt;. The member must be accessible under the resource declared in the &lt;em&gt;action&lt;/em&gt; attribute of the form. This was &lt;a href="http://code.google.com/p/google-sitebricks/issues/detail?id=22"&gt;not mentioned&lt;/a&gt; in the Sitebrick docs either. When you submit the form, the &lt;em&gt;getNewEntry()&lt;/em&gt; method is called and the input field values are set at the returned instance. After that, the annotated &lt;em&gt;save()&lt;/em&gt; method is called with the member &lt;em&gt;newEntry&lt;/em&gt; already populated. &lt;br /&gt;&lt;br /&gt;Again, the design here is rather unusual. You are working on a member, which in case of a &lt;em&gt;Singleton&lt;/em&gt; resource, means there is &lt;a href="http://dlinsin.blogspot.com/2009/05/handling-concurrency-domain-models.html"&gt;shared state&lt;/a&gt;. Of course, if you define your resources not as &lt;em&gt;Singleton&lt;/em&gt;, you don't have any problems. However, it's definitely a pitfall, in my opinion.&lt;br /&gt;&lt;br /&gt;Overall, I think Google Sitebricks contains a couple of cool ideas. I like the &lt;em&gt;expression language&lt;/em&gt; kind of approach, which makes it easy to work with &lt;em&gt;Html&lt;/em&gt; snippets. The possibility to &lt;a href="http://code.google.com/p/google-sitebricks/wiki/EmbeddingBricks"&gt;define little components (Bricks)&lt;/a&gt; and add them in other sites, is another really cool feature. &lt;br /&gt;&lt;br /&gt;The project is still in its early stages and I hope they'll address those odd design decisions, mentioned above. Although it's not standards-based, with Google backing the framework, I could imagine Sitebricks getting some traction.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-1726305450030689571?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/1726305450030689571/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=1726305450030689571' title='16 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/1726305450030689571'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/1726305450030689571'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/10/google-sitebricks.html' title='Google Sitebricks'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-6553932053262635881</id><published>2009-09-28T06:17:00.000+02:00</published><updated>2009-09-28T06:17:00.668+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='karlsruhe'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='hibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='jug-ka'/><title type='text'>Tuning Hibernate and JPA @ JUG-Ka</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://picasaweb.google.com/lh/photo/zDGbEVVB5ihDeoGRJltMvA?authkey=Gv1sRgCKXY3MiLxprXDQ&amp;feat=embedwebsite"&gt;&lt;img style="float:left;margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://lh4.ggpht.com/_myUhtr_A51Y/SnWVogdEjOI/AAAAAAAAPiQ/o9MjIPCDE_s/s144/jug_logo_original_transparent.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5191388009271083842" /&gt;&lt;/a&gt;After &lt;a href="http://dlinsin.blogspot.com/search/label/jug-ka"&gt;two sessions&lt;/a&gt; on client development, we are now turning our attention to the server side again. I'm very happy to welcome &lt;a href="http://rockingcode.blogspot.com/"&gt;Michael Ploed&lt;/a&gt; from &lt;a href="http://www.senacor.com/"&gt;Senacor Technologies AG&lt;/a&gt; to talk about "&lt;a href="https://www.xing.com/events/tuning-hibernate-jpa-anwendungen-371794"&gt;Tuning Hibernate and JPA Applications&lt;/a&gt;" at the&lt;a href="https://jug-ka.dev.java.net/"&gt; Java User Group Karlsruhe&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Michael will show us how to approach tuning of your &lt;a href="http://www.hibernate.org"&gt;Hibernate&lt;/a&gt; powered applications and which options exist, to increase your application's performance. Furthermore he will talk about Hibernate's second-level cache, which I'm looking forward to in particular. Finally, he'll demonstrate his tuning advices with a demo application.&lt;br /&gt;&lt;br /&gt;This month we have a special prize in our monthly lottery: a free pass to the &lt;a href="http://it-republik.de/jaxenter/wjax09/"&gt;W-Jax conference&lt;/a&gt;, held this coming November in Munich. All you've got to do is send me an email and be present at the end of the session, when Michael will draw the winner.&lt;br /&gt;&lt;br /&gt;The session takes place this Wednesday at &lt;a href="http://groups.google.com/group/jug-karlsruhe/web/how-to-find-us?_done=%2Fgroup%2Fjug-karlsruhe%3F"&gt;University Karlsruhe&lt;/a&gt;, building 50.34 in the multimedia room 101, located in the basement. The talk starts at 7pm, a little earlier as usual. &lt;br /&gt;&lt;br /&gt;We have more great talks coming up, the &lt;a href="http://www.google.com/calendar/embed?src=ehlt6rbl1cd1s2b7t9bkj6beek%40group.calendar.google.com&amp;ctz=Europe/Berlin"&gt;next couple of months&lt;/a&gt;. In order to get the latest updates, sign up for our &lt;a href="http://groups.google.com/group/jug-karlsruhe"&gt;Google Group&lt;/a&gt; or join us on &lt;a href="https://www.xing.com/net/jug-karlsruhe/"&gt;Xing&lt;/a&gt;.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-6553932053262635881?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/6553932053262635881/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=6553932053262635881' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/6553932053262635881'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/6553932053262635881'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/09/tuning-hibernate-and-jpa-jug-ka.html' title='Tuning Hibernate and JPA @ JUG-Ka'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_myUhtr_A51Y/SnWVogdEjOI/AAAAAAAAPiQ/o9MjIPCDE_s/s72-c/jug_logo_original_transparent.png' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-2438408786489430085</id><published>2009-09-22T07:19:00.006+02:00</published><updated>2009-09-22T07:23:42.609+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='spring'/><category scheme='http://www.blogger.com/atom/ns#' term='osgi'/><title type='text'>Spring DM Web Extender Problems</title><content type='html'>In my current project, I'm evaluating moving a large and very old code base to &lt;a href="http://dlinsin.blogspot.com/search/label/osgi"&gt;OSGi&lt;/a&gt;. Part of that is getting the the development team on board. I'm trying to point out, how much you can benefit from designing your application with OSGi in mind and the advantages you can have, running your application in an OSGi container. &lt;br /&gt;&lt;br /&gt;I created some sample code with the help of the book &lt;a href="http://www.amazon.de/gp/product/1430216123?ie=UTF8&amp;tag=mytakeonthing-21&amp;linkCode=as2&amp;camp=1638&amp;creative=6742&amp;creativeASIN=1430216123"&gt;"Pro Spring Dynamic Modules for Osgi(tm) Service Platforms"&lt;/a&gt; to highlight some of my OSGi presentation bulletpoints. One of the samples is running Tomcat inside of Equinox together with &lt;a href="http://dlinsin.blogspot.com/2008/11/eclipse-rcp-and-inversion-of-control.html"&gt;Spring Dynamic Modules&lt;/a&gt;. Although the sample is really simple and I sticked to the steps in the book precisely, Equinox spit out the following Exception:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/190831.js"&gt;&lt;/script&gt;&lt;noscript&gt;&lt;pre&gt;17.09.2009 09:08:23 org.springframework.osgi.web.deployer.tomcat.TomcatWarDeployer afterPropertiesSet&lt;br /&gt;SEVERE: No Catalina Service found, bailing out&lt;br /&gt;org.springframework.osgi.service.ServiceUnavailableException: service matching filter=[(objectClass=org.apache.catalina.Service)] unavailable&lt;br /&gt;at org.springframework.osgi.service.importer.support.internal.aop.ServiceDynamicInterceptor.getTarget(ServiceDynamicInterceptor.java:395)&lt;br /&gt;at org.springframework.osgi.service.importer.support.internal.aop.ServiceDynamicInterceptor.afterPropertiesSet(ServiceDynamicInterceptor.java:455)&lt;br /&gt;at org.springframework.osgi.service.importer.support.OsgiServiceProxyFactoryBean.createProxy(OsgiServiceProxyFactoryBean.java:185)&lt;br /&gt;at org.springframework.osgi.service.importer.support.AbstractServiceImporterProxyFactoryBean.getObject(AbstractServiceImporterProxyFactoryBean.java:86)&lt;br /&gt;at org.springframework.osgi.service.importer.support.OsgiServiceProxyFactoryBean.getObject(OsgiServiceProxyFactoryBean.java:137)&lt;br /&gt;at org.springframework.osgi.web.deployer.internal.util.Utils.createServerServiceProxy(Utils.java:117)&lt;br /&gt;at org.springframework.osgi.web.deployer.tomcat.TomcatWarDeployer.afterPropertiesSet(TomcatWarDeployer.java:90)&lt;br /&gt;at org.springframework.osgi.web.extender.internal.activator.WarListenerConfiguration.createDefaultWarDeployer(WarListenerConfiguration.java:197)&lt;br /&gt;at org.springframework.osgi.web.extender.internal.activator.WarListenerConfiguration.&lt;init&gt;(WarListenerConfiguration.java:105)&lt;br /&gt;at org.springframework.osgi.web.extender.internal.activator.WarLoaderListener$1.run(WarLoaderListener.java:353)&lt;br /&gt;at java.lang.Thread.run(Thread.java:619)&lt;/pre&gt;&lt;/noscript&gt;&lt;br /&gt;After various failed attempts to google for a solution, I decided to consult the book again. Although, I thought I sticked to the steps closely, I missed an important point: &lt;a href="http://eclipsesource.com/blogs/2009/06/10/osgi-and-start-levels/"&gt;&lt;em&gt;start levels&lt;/em&gt;&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;A start level is simply a non-negative integer value. The Framework has an ‘active start level’ that is used to decide which bundles can be started. Bundles themselves have an associated ‘bundle start level’ which is used to determine when a bundle is started. The bundles at a given start level will all have their start method completely executed before any bundles at a higher level are started. When booted, the Framework monotonically goes through each start level and starts relevant bundles (all the way until the active start level is met).&lt;br /&gt;...&lt;br /&gt;In the end, start levels are there to simply determine the start order of bundles.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;I missed the fact that there is a start order in my Equinox run configuration. The bundles, which are in charge of bootstrapping Tomcat, need to be activated in special order, otherwise the previously mentioned Exception is raised. In particular the following bundles need to start in order:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;...&lt;br /&gt;org.springframework.osgi.catalina.osgi@3:start, \&lt;br /&gt;org.springframework.osgi.catalina.start.osgi@3:start, \&lt;br /&gt;org.springframework.bundle.osgi.web.extender@4:start, \ &lt;br /&gt;...&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In "Pro Spring Dynamic Modules for Osgi" the config only orders the bundles and doesn't add any explicit &lt;em&gt;start levels&lt;/em&gt;. However, I still ran into the same Exception from time to time, depending on other bundles I loaded. I put explicit &lt;em&gt;start levels&lt;/em&gt; in my run configuration to solve those problems.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-2438408786489430085?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/2438408786489430085/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=2438408786489430085' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/2438408786489430085'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/2438408786489430085'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/09/spring-dm-web-extender-problems.html' title='Spring DM Web Extender Problems'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-3315962791761054802</id><published>2009-09-14T06:22:00.000+02:00</published><updated>2009-09-14T06:22:57.932+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><title type='text'>Git Svn</title><content type='html'>Last week I started working for my &lt;a href="http://www.synyx.de"&gt;new company&lt;/a&gt; and like most of the IT businesses today, we are running subversion for Source Control Management (SCM). While we are still discussing, moving to a Distributed SCM (DSCM), I didn't want to lose the &lt;a href="http://dlinsin.blogspot.com/2009/07/git-stash.html"&gt;advantages&lt;/a&gt; of working with &lt;a href="http://dlinsin.blogspot.com/search/label/git"&gt;&lt;em&gt;git&lt;/em&gt;&lt;/a&gt;. Remembering &lt;a href="http://dlinsin.blogspot.com/2009/06/git-talk-jug-ka.html"&gt;Samuel's talk at Java User Group Karlsruhe&lt;/a&gt; and with a hint from &lt;a href="http://www.olivergierke.de"&gt;Ollie&lt;/a&gt;, I started using &lt;a href="http://www.kernel.org/pub/software/scm/git/docs/git-svn.html"&gt;git-svn&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The &lt;em&gt;git&lt;/em&gt; manual describes the svn capabilities as follows:&lt;br /&gt;&lt;blockquote&gt;git svn is a simple conduit for changesets between Subversion and git. It provides a bidirectional flow of changes between a Subversion and a git repository.&lt;br /&gt;&lt;br /&gt;git svn can track a standard Subversion repository....Once tracking a Subversion repository (with any of the above methods), the git repository can be updated from Subversion by the fetch command and Subversion updated from git by the dcommit command.&lt;/blockquote&gt;&lt;br /&gt;You can create a fully featured &lt;em&gt;git&lt;/em&gt; repository from the &lt;em&gt;trunk&lt;/em&gt; of a subversion repo with the following command:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;git svn init -T https://svn.hostname.de/svn/projects/project/trunk&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The &lt;em&gt;git&lt;/em&gt; repository, that you just created is hooked to the &lt;em&gt;trunk&lt;/em&gt;, passed with URL in the command. To get the &lt;em&gt;HEAD&lt;/em&gt;, just run:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;git svn fetch&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now you are ready to work with &lt;em&gt;git&lt;/em&gt;, as if you had cloned a repo from &lt;a href="http://github.com/dlinsin/"&gt;GitHub&lt;/a&gt;. You can work with branches locally and commit your changes offline. When you want to share your work and &lt;em&gt;push&lt;/em&gt; it back to subversion, you can use the following command:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;git svn dcommit&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You might ask yourself how to get the latest changes from your fellow developers? First, you should have no un-commited changes when you run:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;git svn rebase&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The reason for that, is this command is similar to &lt;em&gt;svn update&lt;/em&gt;. It uses &lt;a href="http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html"&gt;git-rebase&lt;/a&gt; instead of &lt;a href="http://www.kernel.org/pub/software/scm/git/docs/git-merge.html"&gt;git-merge&lt;/a&gt;, in order to preserves linear history.&lt;br /&gt;&lt;br /&gt;Those couple of commands got me started in no time and I didn't have to wait for a company-wide repository in order to have all the advantages that come with &lt;em&gt;git&lt;/em&gt;.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-3315962791761054802?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/3315962791761054802/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=3315962791761054802' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/3315962791761054802'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/3315962791761054802'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/09/git-svn.html' title='Git Svn'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-7223524030784113392</id><published>2009-09-07T06:03:00.000+02:00</published><updated>2009-09-07T06:05:22.305+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><title type='text'>No Improved Exception Handling</title><content type='html'>Last week Joe Darcy &lt;a href="http://blogs.sun.com/darcy/entry/project_coin_final_five"&gt;announced&lt;/a&gt; the &lt;a href="http://openjdk.java.net/projects/coin/"&gt;Project Coin&lt;/a&gt; finalists. There will be 7 "improvements" to the &lt;em&gt;Java Language&lt;/em&gt; for the upcoming JDK 7 release. Unfortunately, one of &lt;a href="http://dlinsin.blogspot.com/2009/03/jdk-7-language-changes-are-coined.html"&gt;my favorite proposals&lt;/a&gt; &lt;a href="http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000003.html"&gt;"&lt;em&gt;Improved Exception Handling&lt;/em&gt;"&lt;/a&gt; didn't make it. Don't worry, I promise this is not gonna be a rant post, rather my personal view on what I have to work with for the next couple of years. &lt;br /&gt;&lt;br /&gt;I have to admit I was a little pissed at first, when I read,  that "&lt;em&gt;Improved Exception Handling&lt;/em&gt;" didn't get in. Especially, because it was one of the &lt;a href="http://dlinsin.blogspot.com/2009/03/jdk-7-language-changes-are-coined.html"&gt;most requested proposals&lt;/a&gt;. However, after reading Joe's explanation on his blog, I do see, that it is not easy to prefer one proposal over the other:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Improved exception handling would be a fine change for the language, but it ventures near the type system and we do not estimate we have resources to fully develop the feature within JDK 7. I would like to see improved exception handling reconsidered in subsequent efforts to evolve the language.&lt;/blockquote&gt;&lt;br /&gt;At this point I would start the ranting on how &lt;a href="http://www.sun.com"&gt;Sun&lt;/a&gt; couldn't have enough resources, but I made a promise I wouldn't. There's &lt;a href="http://blogs.sun.com/darcy/entry/javaposse_277_ivory_tower"&gt;another reason&lt;/a&gt; I shouldn't start ranting:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;If there are frustrations waiting for Java language changes, I assure you there are also frustrations working on Java language changes. For example, I find it frustrating (and self-inconsistent) that people state "I don't have technical expertise in this area" while simultaneously expecting their preferences to be selected without any contribution on their part. [&lt;a href="http://blogs.sun.com/darcy/entry/project_coin_final_five#comments"&gt;LINK&lt;/a&gt;]&lt;/blockquote&gt;&lt;br /&gt;I guess I am one of those frustrated people. I have no idea, if I lack the technical expertise, but what I do know is that I have enough technical expertise to judge that &lt;a href="http://dlinsin.blogspot.com/2008/01/wonderful-checked-exceptions.html"&gt;this&lt;/a&gt; is a &lt;a href="http://en.wiktionary.org/wiki/PITA"&gt;PITA&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Statement stmt = null;&lt;br /&gt;try {&lt;br /&gt;   // do stuff that uses Statement instance&lt;br /&gt;} catch (SQLException e) {&lt;br /&gt;  // handle state&lt;br /&gt;  log.error("Bad database", e);&lt;br /&gt;} catch (NullPointerException e) {&lt;br /&gt;  // handle state&lt;br /&gt;  log.error("Bad parameter", e);&lt;br /&gt;} catch (Exception e) {&lt;br /&gt;  // handle state&lt;br /&gt;  log.error("Bad luck", e);&lt;br /&gt;} finally {&lt;br /&gt;  try {&lt;br /&gt;    stmt.close();&lt;br /&gt;  } catch (Exception ex) {}&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;It is quite irritating, that this is what Java developers have to work with for the next couple of years. It is annoying, that there is no standard in the &lt;em&gt;Java Language&lt;/em&gt; addressing this problem. There might be workarounds or some OpenJDK whatever branch with a prototype hacked into it, which exactly solves this problem. In my opinion, that's not a solution whatsoever. &lt;br /&gt;&lt;br /&gt;In order to reduce &lt;a href="http://dlinsin.blogspot.com/2009/07/when-unchecked-exceptions-go-wrong.html"&gt;programming errors&lt;/a&gt;, I think the &lt;em&gt;Java Language&lt;/em&gt; must address this problem with a standard solution like "&lt;em&gt;Improved Exception Handling&lt;/em&gt;".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-7223524030784113392?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/7223524030784113392/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=7223524030784113392' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/7223524030784113392'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/7223524030784113392'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/09/no-improved-exception-handling.html' title='No Improved Exception Handling'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-98197124055245114</id><published>2009-08-31T06:17:00.000+02:00</published><updated>2009-09-25T11:56:19.487+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='karlsruhe'/><category scheme='http://www.blogger.com/atom/ns#' term='web development'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='jug-ka'/><title type='text'>Java &amp; Flex @ JUG-Ka</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://picasaweb.google.com/lh/photo/zDGbEVVB5ihDeoGRJltMvA?authkey=Gv1sRgCKXY3MiLxprXDQ&amp;feat=embedwebsite"&gt;&lt;img style="float:left;margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://lh4.ggpht.com/_myUhtr_A51Y/SnWVogdEjOI/AAAAAAAAPiQ/o9MjIPCDE_s/s144/jug_logo_original_transparent.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5191388009271083842" /&gt;&lt;/a&gt;I was amazed how many people showed up at our &lt;a href="http://dlinsin.blogspot.com/2009/08/javafx-jug-ka.html"&gt;last session&lt;/a&gt; on &lt;a href="http://java.sun.com/javafx/"&gt;JavaFX&lt;/a&gt; and I would love to see such a crowd at every session. &lt;br /&gt;&lt;br /&gt;Was it the new technology, that made so many people show up? Was it the fact that it was about client development? Or was it simply because we had a speaker from Sun? I'm really curious to know and I would love to get some feedback, in order to improve the topics of our sessions.&lt;br /&gt;&lt;br /&gt;This Wednesday, our new theme on client development continues with a session on Flex &amp; Java. &lt;a href="http://www.adobe.com/products/flex/"&gt;Adobe Flex&lt;/a&gt; is a framework for building web and desktop clients. Corneliu Vasile Creanga from Adobe, will give us an overview of the framework and how it can interact with Java. The session starts at 7:15pm, this Wednesday and takes place at &lt;a href="http://groups.google.com/group/jug-karlsruhe/web/how-to-find-us"&gt;University Karlsruhe&lt;/a&gt; room 101 in the basement. &lt;br /&gt;&lt;br /&gt;There will also be our monthly lottery, where &lt;a href="http://www.jetbrains.net"&gt;JetBrains&lt;/a&gt; and &lt;a href="http://www.zeroturnaround.com"&gt;ZeroTurnaround&lt;/a&gt; are each giving away a free license of one of their products. If you are interested in getting a free copy of &lt;a href="http://www.jetbrains.net/confluence/display/IDEADEV/Home"&gt;IntelliJ&lt;/a&gt; or &lt;a href="http://www.zeroturnaround.com/javarebel/"&gt;JavaRebel&lt;/a&gt;, send me an email to participate in the draw. The winners are gonna be announced at the end of the talk.  &lt;br /&gt;&lt;br /&gt;We have a lot &lt;a href="http://www.xing.com/net/jug-karlsruhe/"&gt;more exciting talks coming up&lt;/a&gt; this year. To stay on top of things, sign up for our &lt;a href="http://groups.google.com/group/jug-karlsruhe"&gt;Google Group&lt;/a&gt; or join us on &lt;a href="https://www.xing.com/net/jug-karlsruhe/"&gt;XING&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-98197124055245114?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/98197124055245114/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=98197124055245114' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/98197124055245114'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/98197124055245114'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/08/java-flex-jug-ka.html' title='Java &amp;amp; Flex @ JUG-Ka'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_myUhtr_A51Y/SnWVogdEjOI/AAAAAAAAPiQ/o9MjIPCDE_s/s72-c/jug_logo_original_transparent.png' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-3289699145764093216</id><published>2009-08-24T06:00:00.000+02:00</published><updated>2009-08-24T06:04:21.184+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><category scheme='http://www.blogger.com/atom/ns#' term='gae'/><title type='text'>Http Basic Authentication with Android</title><content type='html'>The Google App Engine infrastructure, I'm &lt;a href="http://dlinsin.blogspot.com/2009/08/cron-jobs-on-google-app-engine.html"&gt;developing&lt;/a&gt; in my spare time, is meant to be used by an &lt;a href="http://www.android.com/"&gt;Android&lt;/a&gt; client. To give our users at least a vague feeling of security, we decided to use a &lt;em&gt;&lt;a href="http://en.wikipedia.org/wiki/Basic_access_authentication"&gt;Basic Authentication&lt;/a&gt;&lt;/em&gt; together with &lt;a href="http://en.wikipedia.org/wiki/HTTP_Secure"&gt;HTTPS&lt;/a&gt;. Apparently, Android 1.5 is &lt;a href="http://linklens.blogspot.com/2009/06/android-multipart-upload.html"&gt;shipping with&lt;/a&gt; &lt;a href="http://hc.apache.org/httpcomponents-client/httpclient/"&gt;Apache's HttpClient 4.0 Beta2&lt;/a&gt;, which has a pitfall, when it comes to &lt;em&gt;Basic Authentication&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;When you search for &lt;em&gt;HttpClient&lt;/em&gt; and &lt;em&gt;Basic Authentication&lt;/em&gt;, Google will most definitely send you to the &lt;a href="http://hc.apache.org/httpclient-3.x/authentication.html#Preemptive_Authentication"&gt;official documentation of HttpClient 3.x&lt;/a&gt;, which shows you, how to do Basic Authentication in a preemptive way. That means, sending the client's credentials with every request, instead of waiting for a &lt;em&gt;&lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"&gt;401&lt;/a&gt; Unauthorized&lt;/em&gt; response and only then sending the credentials. That's probably what you want to in the first place, because it saves your client a request.&lt;br /&gt;&lt;pre&gt;HttpClient client = new HttpClient();&lt;br /&gt;client.getParams().setAuthenticationPreemptive(true);&lt;br /&gt;Credentials defaultcreds = new UsernamePasswordCredentials("username", "password");&lt;br /&gt;client.getState().setCredentials(new AuthScope("myhost", 80, AuthScope.ANY_REALM), defaultcreds);&lt;/pre&gt;&lt;br /&gt;This sample code won't compile with HttpClient version 4. The method called &lt;em&gt;setAuthenticationPreemptive&lt;/em&gt; is missing. The problem is, if you omit this very method call, the code still works, but the authentication is not preemptive. We missed this little detail and only noticed after a while, that every request was preceded by a &lt;em&gt;401 Unauthorized&lt;/em&gt; request/response cycle. That doubled the amount of requests we served.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://hc.apache.org/httpcomponents-client/tutorial/html/authentication.html"&gt;HttpClient 4 documentation&lt;/a&gt; shows how to do preemptive authentication with the new API. You need to implement a so called &lt;em&gt;HttpRequestInterceptor&lt;/em&gt;:&lt;br /&gt;&lt;pre&gt;HttpRequestInterceptor preemptiveAuth = new HttpRequestInterceptor() {&lt;br /&gt;    public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {&lt;br /&gt;        AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);&lt;br /&gt;        CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(&lt;br /&gt;                ClientContext.CREDS_PROVIDER);&lt;br /&gt;        HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);&lt;br /&gt;        &lt;br /&gt;        if (authState.getAuthScheme() == null) {&lt;br /&gt;            AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());&lt;br /&gt;            Credentials creds = credsProvider.getCredentials(authScope);&lt;br /&gt;            if (creds != null) {&lt;br /&gt;                authState.setAuthScheme(new BasicScheme());&lt;br /&gt;                authState.setCredentials(creds);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }    &lt;br /&gt;};&lt;/pre&gt;&lt;br /&gt;It basically sets the Basic Authentication headers, before each requests and thus avoids the 401 response. In order for the interceptor to work, you need to add it to the request chain:&lt;br /&gt;&lt;pre&gt;DefaultHttpClient httpclient = new DefaultHttpClient();&lt;br /&gt;httpclient.addRequestInterceptor(preemptiveAuth, 0);&lt;/pre&gt;&lt;br /&gt;You might also run into the problem of using the old HttpClient 3.x way of doing &lt;em&gt;Basic Authentication&lt;/em&gt;. It does work, but it's not preemptive, which you might not notice right away. Save yourself some time and checkout the &lt;a href="https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/httpclient/src/examples/org/apache/http/examples/client/ClientPreemptiveBasicAuthentication.java"&gt;sample code&lt;/a&gt; provided by Apache.&lt;br /&gt;&lt;br /&gt;Furthermore, I wasn't abel to find any official site, which states the version of HttpClient, used in Android 1.5. There are various sources, you might encounter, when searching Google, but I would like to see an official site, that states the version. A reason for Google not to reveal this information might be, that they adopted HttpClient and thus are not compatible anymore. However, to avoid mistakes and confusion, it would be nice to know, on which version the Android HttpClient is based on.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-3289699145764093216?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/3289699145764093216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=3289699145764093216' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/3289699145764093216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/3289699145764093216'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/08/http-basic-authentication-with-android.html' title='Http Basic Authentication with Android'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-3842347694001736295</id><published>2009-08-10T06:15:00.000+02:00</published><updated>2009-08-10T06:16:57.646+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='google'/><category scheme='http://www.blogger.com/atom/ns#' term='gae'/><title type='text'>Cron Jobs on Google App Engine</title><content type='html'>I've been developing for the &lt;a href="http://code.google.com/appengine"&gt;Google App Engine&lt;/a&gt; (GAE) &lt;a href="http://dlinsin.blogspot.com/search/label/gae"&gt;for a couple of months&lt;/a&gt; now and there's a lot, I want to talk about in future blog posts. This installment is about &lt;a href="http://code.google.com/appengine/docs/java/config/cron.html"&gt;scheduled tasks&lt;/a&gt; on the GAE  - &lt;a href="http://en.wikipedia.org/wiki/Cron"&gt;cron jobs&lt;/a&gt;  - and a couple of pitfalls that you should be aware of.&lt;br /&gt;&lt;br /&gt;The configuration of a cron on GAE is pretty straightforward. You define your job in a file called &lt;em&gt;cron.xml&lt;/em&gt;, which goes to your &lt;em&gt;WEB-INF&lt;/em&gt; folder in your WAR file. &lt;br /&gt;&lt;pre&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;cronentries&amp;gt;&lt;br /&gt;    &amp;lt;cron&amp;gt;&lt;br /&gt;        &amp;lt;url&amp;gt;/cron/clean&amp;lt;/url&amp;gt;&lt;br /&gt;        &amp;lt;description&amp;gt;job to clean tmp every 5 minutes&amp;lt;/description&amp;gt;&lt;br /&gt;        &amp;lt;schedule&amp;gt;every 5 minutes&amp;lt;/schedule&amp;gt;&lt;br /&gt;    &amp;lt;/cron&amp;gt;&lt;br /&gt;&amp;lt;/cronentries&amp;gt;&lt;/pre&gt;&lt;br /&gt;The file is easy to understand: &lt;em&gt;url &lt;/em&gt;denotes where the GAE is supposed to send a GET request to, when the cron is triggered. Whatever you place behind the denoted &lt;em&gt;url&lt;/em&gt; is your own choice. It can be a plain &lt;em&gt;Servlet&lt;/em&gt; or some RESTful resource. The &lt;em&gt;schedule&lt;/em&gt; tag contains a english-like syntax to define when the &lt;em&gt;url&lt;/em&gt; is supposed to be requested. In this example GAE makes a HTTP GET request to http://yourname.appspot.com/cron/clean every 5 minutes.&lt;br /&gt;&lt;br /&gt;One of GAE's subtle details is that your application is being shutdown, as soon as there are no requests coming in for a certain period of time. That's no a problem by itself, however, if you want to access the cached data of your application from within your cron, you are in trouble. It's not a severe problem, you just need prepared for it.&lt;br /&gt;&lt;br /&gt;Another pitfall, that you might encounter, is configuring the &lt;em&gt;url&lt;/em&gt; of the cron to be secured by SSL. You can define which &lt;em&gt;urls&lt;/em&gt; are supposed to be confidential in your &lt;em&gt;web.xml&lt;/em&gt;. As soon as you add your cron's &lt;em&gt;url&lt;/em&gt;, you'll encounter an error message in your admin console under "Cron Jobs", which says "Too many continues". This indicates, that GAE wants to execute cron jobs using http instead of https, which leads to a &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"&gt;HTTP 302&lt;/a&gt; response. Browsers can easily interpret it as "don't use http, use https instead", but the GAE can't.&lt;br /&gt;&lt;br /&gt;This is not a security problem, since the urls of your cron job should only be accessible by administrators anyways. You can easily exclude the cron's &lt;em&gt;url&lt;/em&gt; from your SSL configuration and everything should work fine.&lt;br /&gt;&lt;br /&gt;There are more little gotchas, that I encountered developing for the GAE and I'm going to blog more about it soon.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-3842347694001736295?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/3842347694001736295/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=3842347694001736295' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/3842347694001736295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/3842347694001736295'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/08/cron-jobs-on-google-app-engine.html' title='Cron Jobs on Google App Engine'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-3689680441155528956</id><published>2009-08-03T06:15:00.000+02:00</published><updated>2009-08-05T15:36:52.088+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='karlsruhe'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='jug-ka'/><title type='text'>JavaFX @ JUG-Ka</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://picasaweb.google.com/lh/photo/zDGbEVVB5ihDeoGRJltMvA?authkey=Gv1sRgCKXY3MiLxprXDQ&amp;feat=embedwebsite"&gt;&lt;img style="float:left;margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://lh4.ggpht.com/_myUhtr_A51Y/SnWVogdEjOI/AAAAAAAAPiQ/o9MjIPCDE_s/s144/jug_logo_original_transparent.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5191388009271083842" /&gt;&lt;/a&gt;With our new logo, designed by &lt;a href="http://samuel-mellert.de/"&gt;Samuel Mellert&lt;/a&gt;, who held &lt;a href="http://dlinsin.blogspot.com/2009/06/git-talk-jug-ka.html"&gt;last month's session&lt;/a&gt; on &lt;a href="http://en.wikipedia.org/wiki/Git_(software)"&gt;Git&lt;/a&gt;, we want to start into the second half of 2009. There are a couple of &lt;a href="http://www.xing.com/net/jug-karlsruhe/"&gt;exciting talks coming up&lt;/a&gt; at &lt;a href="http://jug-ka.de"&gt;Java User Group Karlsruhe&lt;/a&gt;, beginning with an introduction to &lt;a href="http://java.sun.com/javafx/"&gt;JavaFX&lt;/a&gt; this week. To get the latest updates of the JUG-Ka sign up for our &lt;a href="http://groups.google.com/group/jug-karlsruhe"&gt;Google Group&lt;/a&gt; or join us on &lt;a href="https://www.xing.com/net/jug-karlsruhe/"&gt;XING&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Stefan Schneider from Sun Micorsystem is going to give an introductory level session on JavaFX, with samples and time for QA. Stefan gave &lt;a href="http://dlinsin.blogspot.com/2007/08/jvm-memory-pool-sizing-principles.html"&gt;a couple&lt;/a&gt; &lt;a href="http://dlinsin.blogspot.com/2007/07/java-se-6-tech-talk.html"&gt;of talks&lt;/a&gt; here in Karlsruhe and I'm very pleased he is back with something new.&lt;br /&gt;&lt;br /&gt;The session takes place this Wednesday at University Karlsruhe and starts at 7:15pm. As usual, &lt;a href="http://www.jetbrains.net"&gt;JetBrains&lt;/a&gt; and &lt;a href="http://www.zeroturnaround.com"&gt;ZeroTurnaround&lt;/a&gt; are each giving away a free license of one of their products. There'll be a lottery, so if you are interested in getting a free copy of &lt;a href="http://www.jetbrains.net/confluence/display/IDEADEV/Home"&gt;IntelliJ&lt;/a&gt; or &lt;a href="http://www.zeroturnaround.com/javarebel/"&gt;JavaRebel&lt;/a&gt;, send me an email to participate in the draw. The winners are gonna be announced at the end of the talk.  &lt;br /&gt;&lt;br /&gt;I'm sure you all know the &lt;a href="http://www.dzone.com"&gt;DZone network&lt;/a&gt;, which provides all sorts of services and information for developers, like &lt;a href="http://java.dzone.com/"&gt;Javalobby&lt;/a&gt;, &lt;a href="http://www.jroller.com/"&gt;JRoller&lt;/a&gt; or &lt;a href="http://eclipse.dzone.com/"&gt;EclipseZone&lt;/a&gt;. They also have a service called &lt;a href="http://refcardz.dzone.com/"&gt;Refcardz&lt;/a&gt; - nice little cheat sheets on a variety of topcis. You can download those Refcardz and print them yourself or you can come by on Wednesday and get one for free. DZone was kind enough to provide a couple of professionally printed Refcardz, which I will give out at the end of the next talk.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-3689680441155528956?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/3689680441155528956/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=3689680441155528956' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/3689680441155528956'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/3689680441155528956'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/08/javafx-jug-ka.html' title='JavaFX @ JUG-Ka'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_myUhtr_A51Y/SnWVogdEjOI/AAAAAAAAPiQ/o9MjIPCDE_s/s72-c/jug_logo_original_transparent.png' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-1230213002804593952</id><published>2009-07-29T06:10:00.000+02:00</published><updated>2009-07-29T06:10:00.397+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><title type='text'>Git Stash</title><content type='html'>After a &lt;a href="http://dlinsin.blogspot.com/2009/06/git-talk-jug-ka.html"&gt;great talk&lt;/a&gt; on &lt;a href="http://en.wikipedia.org/wiki/Git_(software)"&gt;Git&lt;/a&gt; at the &lt;a href="http://jug-ka.de"&gt;Java User Group Karlsruhe&lt;/a&gt; and a couple of &lt;a href="http://dlinsin.blogspot.com/search/label/git"&gt;other experiences&lt;/a&gt;, I started to really dig the Distributed Source Control Management (DSCM) notion and its advantages. A neat and quite helpful feature of Git is &lt;em&gt;stashing&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#interrupted-work"&gt;Git manual&lt;/a&gt; has as an exceptionally helpful description of &lt;em&gt;stashing&lt;/em&gt;. They call it "Temporarily setting aside work in progress".&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;While you are in the middle of working on something complicated, you find an unrelated but obvious and trivial bug. You would like to fix it before continuing. You can use &lt;a href="http://www.kernel.org/pub/software/scm/git/docs/git-stash.html"&gt;git-stash(1)&lt;/a&gt; to save the current state of your work, and after fixing the bug (or, optionally after doing so on a different branch and then coming back), unstash the work-in-progress changes.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;$ git stash save "work in progress for foo feature"&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;This command will save your changes away to the stash, and reset your working tree and the index to match the tip of your current branch. Then you can make your fix as usual.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;... edit and test ...&lt;br /&gt;$ git commit -a -m "blorpl: typofix"&lt;br /&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;After that, you can go back to what you were working on with git stash pop:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;$ git stash pop&lt;/em&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Git's &lt;em&gt;stashing&lt;/em&gt; feature saved me quite some trouble a couple of days ago, while working on a side project. I developed a feature on branch "B" and had quite a big change-set, while someone found a bug on the stable branch, let's call it "A". &lt;br /&gt;&lt;br /&gt;Coming from SVN, I thought I had to check-in my changes in order to switch to Branch "A" and fix the bug. That's quite ugly, because it screws with your history of commits and even might break your builds. I know that there are other possibilities with SVN, like copying your changed files or &lt;a href="http://blog.jayfields.com/2008/02/using-patch-as-subversion-stash.html"&gt;creating a patch file&lt;/a&gt;. However, to me those all look like workarounds rather than solutions.&lt;br /&gt;&lt;br /&gt;So I simply &lt;em&gt;stashed&lt;/em&gt; my changes from branch "B" and got a clean branch with HEAD. I switched to branch "A" and was able to fix and commit the bug. After switching to branch "B" again, I simply &lt;em&gt;poped&lt;/em&gt; the changes from the &lt;em&gt;stash&lt;/em&gt;, as if I had never stopped working on the feature.  &lt;br /&gt;&lt;br /&gt;After working with Git for some time, I would really recommend people to switch to a DSCM. I'm not alone with this. SpringSource's DM server team &lt;a href="http://blog.springsource.com/2009/07/15/git-migration/"&gt;migrated&lt;/a&gt; their repositories to Git a couple of weeks ago and they didn't hear any complaints from the community.  No matter if you choose Git or Mercurial, the advantages of a DSCM really outweigh the &lt;a href="http://dlinsin.blogspot.com/2009/06/github-pain.html"&gt;initial costs&lt;/a&gt; of getting started.  &lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-1230213002804593952?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/1230213002804593952/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=1230213002804593952' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/1230213002804593952'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/1230213002804593952'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/07/git-stash.html' title='Git Stash'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-3135061459129563318</id><published>2009-07-13T06:00:00.000+02:00</published><updated>2009-07-13T06:16:42.617+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='karlsruhe'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='jug-ka'/><title type='text'>Jug-Ka Summer Stammtisch</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_myUhtr_A51Y/SAuD46fTQ0I/AAAAAAAAGaU/dObCE4Jx8H8/s1600-h/jug-logo_124x77.png"&gt;&lt;img style="float:left;margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_myUhtr_A51Y/SAuD46fTQ0I/AAAAAAAAGaU/dObCE4Jx8H8/s320/jug-logo_124x77.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5191388009271083842" /&gt;&lt;/a&gt;Since we haven't had a Stammtisch of the &lt;a href="http://jug-ka.de"&gt;Java Users Group Karlsruhe&lt;/a&gt; for a while, I thought it's time to get together &lt;a href="http://dlinsin.blogspot.com/2009/03/jug-ka-stammtisch-30.html"&gt;again&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;We are gonna meet on &lt;a href="https://www.xing.com/events/319637"&gt;Wednesday, July 15th - 20:00&lt;/a&gt;, at a nice pub called &lt;a href="http://tinyurl.com/blzfzn"&gt;Litfass&lt;/a&gt;, near Marktplatz. For further information you can send an email to our &lt;a href="http://groups.google.com/group/jug-karlsruhe"&gt;Google Group&lt;/a&gt; or join us on &lt;a href="https://www.xing.com/net/jug-karlsruhe/"&gt;Xing&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-3135061459129563318?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/3135061459129563318/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=3135061459129563318' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/3135061459129563318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/3135061459129563318'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/07/jug-ka-summer-stammtisch.html' title='Jug-Ka Summer Stammtisch'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_myUhtr_A51Y/SAuD46fTQ0I/AAAAAAAAGaU/dObCE4Jx8H8/s72-c/jug-logo_124x77.png' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-4151301823886425333</id><published>2009-07-06T05:53:00.000+02:00</published><updated>2009-07-06T20:46:42.995+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><title type='text'>When Unchecked Exceptions Go Wrong</title><content type='html'>In the application I'm developing right now, we found a bug right before going live. A colleague of mine forgot to catch an unchecked Exception in a loop, which led the loop to exit, before iterating over each element. Bugs like this are so subtle and hard to track, that's why I think it was kind of my fault for not using a checked instead of an unchecked Exception.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// must work all jobs&lt;br /&gt;private void workAllJobs() {&lt;br /&gt;  for(MyJob job : allJobs) {&lt;br /&gt;    job.work(); // throws RuntimeException&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Let me be clear, I don't want to engage into the checked vs. unchecked Exception war. I made &lt;a href="http://dlinsin-area51.blogspot.com/2009/01/how-to-internationalize-exceptions-ii.html"&gt;my point&lt;/a&gt; clear a couple of times, however I simply think I need to revise &lt;a href="http://dlinsin.blogspot.com/2008/01/wonderful-checked-exceptions.html"&gt;my position&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;I &lt;a href="http://dlinsin.blogspot.com/2009/02/aspect-is-part-of-your-implementation.html"&gt;used to think&lt;/a&gt; forcing a client of an API to catch an Exception was evil! That's why I usually design custom Exceptions to inherit from &lt;em&gt;RuntimeException&lt;/em&gt; and &lt;a href="http://dlinsin.blogspot.com/2008/06/does-your-api-docs-leave-users-in-dark.html"&gt;declare each and every case&lt;/a&gt; carefully in the javadocs of my API methods. I simply followed the &lt;a href="http://www.amazon.de/gp/product/0321356683?ie=UTF8&amp;tag=mytakeonthing-21&amp;linkCode=as2&amp;camp=1638&amp;creative=6742&amp;creativeASIN=0321356683"&gt;expert's advice&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Always declare checked exceptions individually, and document precisely the condition under which each one is thrown using the Javadoc @throws tag. .... While the language does not require programmers to declare unchecked exceptions that a method is capable of throwing, it is wise to document them as carefully as the checked Exceptions.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Unfortunately, the expert's advice didn't work in my co-worker's case. Should I say in most cases? He is with the sad majority of developers, that don't ready javadocs - not even on public API methods. Maybe I should have listened to &lt;a href="http://dlinsin.blogspot.com/2008/06/does-your-api-docs-leave-users-in-dark.html?showComment=1214837340000#c4776475304015970181"&gt;people telling me&lt;/a&gt; this:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;I kind of disagree with your example; documenting everything in every tiny detail may be a requirement for widely used public APIs (like the JDK), but IMHO a more relaxed approach is useful for the rest of us. Like "configuration by exception" is considered a good idea, there should also be "documentation by exception". That is, don't document every tiny detail but instead follow some higher level conventions. Many people do that intuitively, but unfortunately forget to document those conventions.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Like &lt;a href="http://unmaintainable.wordpress.com/"&gt;Matthias&lt;/a&gt;, my co-worker argued, that he thinks conventions should define what happens if e.g. you pass &lt;em&gt;null&lt;/em&gt; to a method or which Exceptions are being thrown from an API method. I do agree, conventions are a great tool to define this kind of behavior. The problem with conventions are: How do you get the whole team to agree on certain conventions and more important - how do you manage those convetions?&lt;br /&gt;&lt;br /&gt;Getting a team of strongly opinionated individuals to even agree on minor details, e.g. how to name interfaces, is almost impossible. Believe me, I have been there! After more than a year, we still can't agree on wether to use Eclipse's notation of &lt;em&gt;IService&lt;/em&gt; or my preference - simply &lt;em&gt;Service&lt;/em&gt;. I cannot imagine how hard it will be to agree on really important topics like &lt;a href="http://dlinsin.blogspot.com/2008/10/thoughts-on-api-design.html"&gt;passing &lt;em&gt;null&lt;/em&gt; to methods&lt;/a&gt; and wether to throw &lt;em&gt;IllegalArgumentException&lt;/em&gt; or &lt;em&gt;NullPointerException&lt;/em&gt; in that case. &lt;br /&gt;&lt;br /&gt;The second issue with conventions is how to manage them. Who is responsible to maintain those agreements? Do you put those conventions on a wiki page, which nobody updates and nobody reads anyways? I argue, that for us developers code and eventually the IDE is where we live, thus I think that's the place those conventions should live as well. Code is the common single point of truth for us and hence javadocs are in my opinion the best way to document any code related conventions. &lt;br /&gt;&lt;br /&gt;I guess you can see where this is going. It's a trade-off, as always in software development. However, it's a trade-off with a catch. I think it's simply not enough to "just have conventions", they need to be documented and managed in the code and my weapon of choice for doing that is javadocs. &lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-4151301823886425333?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/4151301823886425333/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=4151301823886425333' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/4151301823886425333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/4151301823886425333'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/07/when-unchecked-exceptions-go-wrong.html' title='When Unchecked Exceptions Go Wrong'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-3523813092165285099</id><published>2009-07-03T07:27:00.001+02:00</published><updated>2009-07-03T07:27:07.980+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='hibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='out&apos;n about'/><title type='text'>Java Forum Stuttgart</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://picasaweb.google.com/lh/photo/RBMplqKi5UjZWGdYPLExKg?authkey=Gv1sRgCKXY3MiLxprXDQ&amp;feat=embedwebsite"&gt;&lt;img style="float:left;margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://lh3.ggpht.com/_myUhtr_A51Y/Sk2P0Fh15KI/AAAAAAAAPMk/qzJ79c42r_U/s288/logo.jpg" border="0" alt=""id="" /&gt;&lt;/a&gt;Yesterday, I was &lt;a href="http://picasaweb.google.com/dlinsin/JavaForumStuttgart2009#"&gt;attending&lt;/a&gt; the &lt;a href="http://www.java-forum-stuttgart.de/"&gt;12. Java Forum Stuttgart&lt;/a&gt; and compared to the &lt;a href="http://picasaweb.google.com/dlinsin/JavaforumStuttgart2005#"&gt;last time&lt;/a&gt; I went, which was &lt;a href="http://dlinsin-archives.blogspot.com/2005/07/java-forum-stuttgart.html"&gt;in 2005&lt;/a&gt;, the event has really fledged. &lt;br /&gt;&lt;br /&gt;The quality of the sessions was good and the hallway was filled with &lt;a href="http://www.olivergierke.de/"&gt;familiar faces&lt;/a&gt;. The theme of the conference for me, was JPA and O/R mappers. There were a couple of really &lt;a href="http://rockingcode.blogspot.com/"&gt;great talks&lt;/a&gt; about it and it seems like there's a lot of going on in that area at the moment. &lt;br /&gt;&lt;br /&gt;I'm definitely gone be there again next year and I would love for the conference to be extended to a 2-3 days event. &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-3523813092165285099?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/3523813092165285099/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=3523813092165285099' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/3523813092165285099'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/3523813092165285099'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/07/java-forum-stuttgart.html' title='Java Forum Stuttgart'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_myUhtr_A51Y/Sk2P0Fh15KI/AAAAAAAAPMk/qzJ79c42r_U/s72-c/logo.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-8918968127412450371</id><published>2009-06-29T06:03:00.000+02:00</published><updated>2009-06-29T06:03:01.261+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='spring'/><category scheme='http://www.blogger.com/atom/ns#' term='out&apos;n about'/><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><title type='text'>Wrapping-up Jazoon09</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://picasaweb.google.com/lh/photo/3X27U9TvyYhi8rWZLnecAw?authkey=Gv1sRgCKXY3MiLxprXDQ&amp;feat=embedwebsite"&gt;&lt;img style="float:left;margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://lh4.ggpht.com/_myUhtr_A51Y/SjqfDd3Q9HI/AAAAAAAAN_Y/-cN2utCGfFg/s288/jazoon-logo.gif" border="0" alt=""id="" /&gt;&lt;/a&gt; I was &lt;a href="http://dlinsin.blogspot.com/2009/06/jazoon-2009.html"&gt;attending Jazoon09&lt;/a&gt; in Zurich, Switzerland last week. As with &lt;a href="http://dlinsin.blogspot.com/2009/05/springone-2009-recap.html"&gt;springOne 2009&lt;/a&gt;, I wasn't really satisfied with this content of the conference. &lt;br /&gt;&lt;br /&gt;The problem was, that there were only a few really good speakers and thus only a couple of great talks. The keynotes were average, only &lt;a href="http://jazoon.com/en/conference/presentationdetails.html?type=sid&amp;detail=9280"&gt;Adrian Colyer's presentation&lt;/a&gt; on the last day was standing out. Even James Gosling's presentation or Danny Cowards talk were both not that exciting.&lt;br /&gt;&lt;br /&gt;However, instead of telling you what sucked, I rather want to highlight, that the organization of the conference was great! The food was really good! There was an vegetarian alternative every day and the coffee was delicious. Jazoon took place in a movie theater, just like &lt;a href="http://devoxx.com/display/DV09/Home"&gt;Devoxx&lt;/a&gt;, thus it was easy to get there by train and the seats were nice and comfy. Kudos to the organizers.&lt;br /&gt;&lt;br /&gt;There were a couple of great talks I want to highlight: Neal Ford's "&lt;a href="http://jazoon.com/en/conference/presentations/istr/9440"&gt;Smithying in the 21st Century&lt;/a&gt;" as well as Ed Burns' "&lt;a href="http://jazoon.com/en/conference/presentationdetails.html?type=sid&amp;detail=8000"&gt;Secrets of the Rockstar Programmers&lt;/a&gt;" were really awesome and I can only commend listening to them, in case they come up on the schedule of another conference. &lt;br /&gt;&lt;br /&gt;I'm not too sure if I'll come back to Jazoon next year, although I think it could be a really cool conference and a great alternative to Devoxx, which takes place in Antwerp. &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-8918968127412450371?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/8918968127412450371/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=8918968127412450371' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/8918968127412450371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/8918968127412450371'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/06/wrapping-up-jazoon09.html' title='Wrapping-up Jazoon09'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_myUhtr_A51Y/SjqfDd3Q9HI/AAAAAAAAN_Y/-cN2utCGfFg/s72-c/jazoon-logo.gif' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17885082.post-6950717746196154845</id><published>2009-06-21T10:58:00.000+02:00</published><updated>2009-06-21T11:02:21.163+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web development'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='out&apos;n about'/><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Jazoon 2009</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://picasaweb.google.com/lh/photo/3X27U9TvyYhi8rWZLnecAw?authkey=Gv1sRgCKXY3MiLxprXDQ&amp;feat=embedwebsite"&gt;&lt;img style="float:left;margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://lh4.ggpht.com/_myUhtr_A51Y/SjqfDd3Q9HI/AAAAAAAAN_Y/-cN2utCGfFg/s288/jazoon-logo.gif" border="0" alt=""id="" /&gt;&lt;/a&gt; I'll be at &lt;a href="http://jazoon.com/en.html"&gt;Jazoon 2009&lt;/a&gt;, which is starting next week on Monday with a &lt;a href="http://jazoon.com/en/workshop5.html"&gt;Glassfish Day&lt;/a&gt;. It's going to be my first time in Zurich this year and I'm really excited, because they have a great line up of &lt;a href="http://jazoon.com/en/conference/speakers.html"&gt;speakers&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Among others, there's gonna be the father of Java himself &lt;a href="http://jazoon.com/en/conference/speakerdetails.html?type=author&amp;detail=James_Gosling"&gt;Mr. James Gosling&lt;/a&gt;. For me it's always something special to listen to a keynote of him. &lt;br /&gt;&lt;br /&gt;There's gonna be sessions on a wide range of topics, e.g. "&lt;a href="http://jazoon.com/en/conference/presentations/tl/8760"&gt;Concurrency and Performance Reloaded&lt;/a&gt;" with Kirk Pepperdine, "&lt;a href="http://jazoon.com/en/conference/presentations/tl/9140"&gt;Development for the iPhone&lt;/a&gt;" or "&lt;a href="http://jazoon.com/en/conference/presentations/tl/6421"&gt;Design Patterns in Dynamic Languages&lt;/a&gt;" with Neal Ford, to name only a few of the first conference day.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17885082-6950717746196154845?l=dlinsin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dlinsin.blogspot.com/feeds/6950717746196154845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17885082&amp;postID=6950717746196154845' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/6950717746196154845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17885082/posts/default/6950717746196154845'/><link rel='alternate' type='text/html' href='http://dlinsin.blogspot.com/2009/06/jazoon-2009.html' title='Jazoon 2009'/><author><name>David Linsin</name><uri>http://www.blogger.com/profile/12280104990941617395</uri><email>dlinsin@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07781195754465103091'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_myUhtr_A51Y/SjqfDd3Q9HI/AAAAAAAAN_Y/-cN2utCGfFg/s72-c/jazoon-logo.gif' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry></feed>