<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-117760846317593301</id><updated>2012-01-29T11:56:00.268+01:00</updated><title type='text'>Jamie Craane's Blog</title><subtitle type='html'>My views, thoughts and experiences about Enterprise Application Development.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>40</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-8232586181334846340</id><published>2012-01-23T20:48:00.002+01:00</published><updated>2012-01-23T20:48:18.845+01:00</updated><title type='text'>Monitoring an IBM JVM with VisualVM</title><content type='html'>&lt;br /&gt;&lt;div class="MsoNormal" style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;span lang="EN-GB" style="font-family: Verdana, sans-serif; font-size: 10pt;"&gt;JDK6 update 7 and onward include a tool called VisualVM. VisualVM is a visual tool with monitoring and profiling capabilities for the JVM. With VisualVM you can:&lt;u&gt;&lt;/u&gt;&lt;u&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-size: 13px;"&gt;&lt;/div&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-family: Verdana, sans-serif; font-size: 10pt;"&gt;Monitor heap usage&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: Verdana, sans-serif; font-size: 10pt;"&gt;Monitor CPU usage&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: Verdana, sans-serif; font-size: 10pt;"&gt;Monitor Threads&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: Verdana, sans-serif; font-size: 10pt;"&gt;Initiate garbage collections&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: Verdana, sans-serif; font-size: 10pt;"&gt;Profile CPU and memory&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: Verdana, sans-serif; font-size: 10pt;"&gt;And more…&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;u&gt;&lt;/u&gt;&lt;br /&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-size: 13px;"&gt;&lt;span style="font-family: Verdana, sans-serif;"&gt;&lt;u&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-size: 13px;"&gt;&lt;span style="font-family: Verdana, sans-serif;"&gt;&lt;u&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-size: 13px;"&gt;&lt;span style="font-family: Verdana, sans-serif;"&gt;&lt;u&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-size: 13px;"&gt;&lt;span style="font-family: Verdana, sans-serif;"&gt;&lt;u&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-size: 13px;"&gt;&lt;span style="font-family: Verdana, sans-serif;"&gt;&lt;u&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;span style="font-family: Verdana, sans-serif; font-size: 10pt;"&gt;Although VisualVM is distributed with the Oracle JDK, it can also be used to monitor IBM JVM’s. VisualVM is not able to connect to the IBM JVM locally. JMX must be used instead.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;span lang="EN-GB" style="font-family: Verdana, sans-serif; font-size: 10pt;"&gt;To enable JMX monitoring on the IBM JVM open the WebSphere administrative console and:&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-size: 13px;"&gt;&lt;/div&gt;&lt;ol&gt;&lt;li style="font-family: arial, sans-serif;"&gt;&lt;span style="font-family: Verdana, sans-serif; font-size: 10pt;"&gt;navigate to: Server -&amp;gt; Server Types -&amp;gt; WebSphere application servers -&amp;gt;[SERVER_NAME]&lt;/span&gt;&lt;/li&gt;&lt;li style="font-family: arial, sans-serif;"&gt;&lt;span style="background-color: transparent; font-family: Verdana, sans-serif; font-size: 10pt;"&gt;Expand &lt;b&gt;Java and Process Management&lt;/b&gt; and click &lt;b&gt;Process definition&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="font-family: arial, sans-serif;"&gt;&lt;span style="background-color: transparent; font-family: Verdana, sans-serif; font-size: 10pt;"&gt;Click &lt;b&gt;Java Virtual Machine&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="background-color: transparent; font-family: Verdana, sans-serif; font-size: 10pt;"&gt;In the &lt;b&gt;Generic JVM arguments&lt;/b&gt; field append the following properties: &lt;/span&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span style="background-color: transparent; font-size: 10pt;"&gt;-Djavax.management.builder.&lt;/span&gt;&lt;wbr style="background-color: transparent; font-size: 10pt;"&gt;&lt;/wbr&gt;&lt;span style="background-color: transparent; font-size: 10pt;"&gt;initial= -Dcom.sun.management.jmxremote -Dcom.sun.management.&lt;/span&gt;&lt;wbr style="background-color: transparent; font-size: 10pt;"&gt;&lt;/wbr&gt;&lt;span style="background-color: transparent; font-size: 10pt;"&gt;jmxremote.authenticate=false -Dcom.sun.management.&lt;/span&gt;&lt;wbr style="background-color: transparent; font-size: 10pt;"&gt;&lt;/wbr&gt;&lt;span style="background-color: transparent; font-size: 10pt;"&gt;jmxremote.ssl=false -Dcom.sun.management.&lt;/span&gt;&lt;wbr style="background-color: transparent; font-size: 10pt;"&gt;&lt;/wbr&gt;&lt;span style="background-color: transparent; font-size: 10pt;"&gt;jmxremote.port=1099&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="font-family: arial, sans-serif;"&gt;&lt;span style="background-color: transparent; font-family: Verdana, sans-serif; font-size: 10pt;"&gt;Restart the server&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;u&gt;&lt;/u&gt;&lt;br /&gt;&lt;u&gt;&lt;/u&gt;&lt;br /&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-size: 13px;"&gt;&lt;span style="font-family: Verdana, sans-serif;"&gt;&lt;u&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-size: 13px;"&gt;&lt;span style="font-family: Verdana, sans-serif;"&gt;&lt;u&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-size: 13px;"&gt;&lt;span style="font-family: Verdana, sans-serif;"&gt;&lt;u&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;span style="font-family: Verdana, sans-serif; font-size: 10pt;"&gt;To start monitoring the JVM with VisualVM start VisualVM by navigating to [JDK_HOME]\bin and start jvisualvm.exe (please note that when VisualVM is downloaded as a separate package the executable is called visualvm.exe instead). In VisualVM click &lt;b&gt;File&lt;/b&gt; -&amp;gt; &lt;b&gt;Add JMX Connection&lt;/b&gt;. Specify &lt;b&gt;localhost:1099&lt;/b&gt; in the connection field and click OK.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;span lang="EN-GB" style="font-family: Verdana, sans-serif; font-size: 10pt;"&gt;If everything went OK, you should see the localhost:1099 connection under the Local node in the tree on the left. Double-click this node to start monitoring. See the following screenshot for an example:&lt;u&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;span lang="EN-GB" style="font-family: Verdana, sans-serif; font-size: 10pt;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-ZPV0AFkItPU/Tx23umkSv2I/AAAAAAAACSE/pP4wiOPVEhg/s1600/visualvm.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="186" src="http://1.bp.blogspot.com/-ZPV0AFkItPU/Tx23umkSv2I/AAAAAAAACSE/pP4wiOPVEhg/s320/visualvm.PNG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;span lang="EN-GB" style="font-family: Verdana, sans-serif; font-size: 10pt;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;span style="font-family: Verdana, sans-serif; font-size: 10pt;"&gt;When using a JMX connection to monitor the JVM please be aware that not all functionality can be used compared to monitoring a local JVM. Profiling memory is for example not possible.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;span lang="EN-GB" style="font-family: Verdana, sans-serif; font-size: 10pt;"&gt;The above configuration was tested on:&lt;u&gt;&lt;/u&gt;&lt;u&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-size: 13px;"&gt;&lt;/div&gt;&lt;ul style="font-family: arial, sans-serif;"&gt;&lt;li&gt;&lt;span style="font-family: Verdana, sans-serif; font-size: 10pt;"&gt;Windows 7 64-bit&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: Verdana, sans-serif; font-size: 10pt;"&gt;IBM JDK1.6 64 bit&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: Verdana, sans-serif; font-size: 10pt;"&gt;WebSphere Application Server version 7.0&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;u&gt;&lt;/u&gt;&lt;br /&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-size: 13px;"&gt;&lt;span style="font-family: Verdana, sans-serif;"&gt;&lt;u&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-size: 13px;"&gt;&lt;span style="font-family: Verdana, sans-serif;"&gt;&lt;u&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-size: 13px;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;span lang="EN-GB" style="font-size: 10pt;"&gt;Note: Before JDK6 update 7, VisualVM can also be downloaded separately from&amp;nbsp;&lt;/span&gt;&lt;span lang="EN-GB"&gt;&lt;a href="http://visualvm.java.net/download.html" style="color: #1155cc;" target="_blank"&gt;http://visualvm.java.net/&lt;wbr&gt;&lt;/wbr&gt;download.html&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-size: 13px;"&gt;&lt;span lang="EN-GB"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Note: To actually test if port 1099 is listening for connections use (on Windows) the &lt;b&gt;netstat –a&lt;/b&gt; command and check wether the port is present and listening.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-8232586181334846340?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/8232586181334846340/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=8232586181334846340' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/8232586181334846340'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/8232586181334846340'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2012/01/monitoring-ibm-jvm-with-visualvm.html' title='Monitoring an IBM JVM with VisualVM'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-ZPV0AFkItPU/Tx23umkSv2I/AAAAAAAACSE/pP4wiOPVEhg/s72-c/visualvm.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-4295272127313599112</id><published>2011-12-28T20:05:00.001+01:00</published><updated>2011-12-29T14:41:05.231+01:00</updated><title type='text'>Improved IntelliJ keymap</title><content type='html'>At my current client the whole team recently switched from an Eclipse based IDE to IntelliJ. Although some of us have used IntelliJ for a long time, most had not. Switching from Eclipse to IntelliJ can be hard. It took me about three to four weeks before I was more productive with IntelliJ. Now I do not want to go back anymore.&lt;br /&gt;&lt;br /&gt;To make the transition more smooth I am looking into several ways to accomplish this. One of the things I made is a new keymap reference for IntelliJ. The default keymap reference contains a whole list of shortcuts but I find them sometimes hard to find. The new, improved, keymap should make the most used IntelliJ features really easy to find. The most used features are based upon my own experience and the IntelliJ productivity guide of my colleagues. The productivity guide shows which features of IntelliJ are used most often.&lt;br /&gt;&lt;br /&gt;To create the improved keymap reference I basically did the following:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Stripped about half of the features from the default keymap reference. The features present on the new keymap reference are the most used features.&lt;/li&gt;&lt;li&gt;Made a clearer distinction between the different types of functionality the features belong to.&lt;/li&gt;&lt;li&gt;In each feature group I made a distinction between individual features which belong together.&lt;/li&gt;&lt;li&gt;Used a larger font and more contrast to make things stand out more.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;The Windows keymap reference can be found here:&amp;nbsp;&lt;a href="http://www.capaxit.nl/docs/IntelliJKeymapWindows.pdf"&gt;IntelliJ Keymap Windows&lt;/a&gt;&lt;/div&gt;&lt;div&gt;The OSX keymap reference can be found here:&amp;nbsp;&lt;a href="http://www.capaxit.nl/docs/IntelliJKeymapOSX.pdf"&gt;IntelliJ Keymap OSX&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Hope you like it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you have any suggestions for the keymap reference please let me know.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-4295272127313599112?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/4295272127313599112/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=4295272127313599112' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/4295272127313599112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/4295272127313599112'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2011/12/improved-intellij-keymap.html' title='Improved IntelliJ keymap'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-760893781419494544</id><published>2011-08-02T20:21:00.002+02:00</published><updated>2011-08-03T19:34:51.816+02:00</updated><title type='text'>WebSphere Portal 6.x Locale Resolution</title><content type='html'>When developing applications for WebSphere Portal there will be some point in time that the application should support I18N. For every language an application supports a resource bundle is provided. If a given language is not supported the application falls back to its default resource bundle. To format currencies and dates the JSTL formatting tags can be used. Based on the locale selection process of WebSphere Portal, the translation of dates and currencies in the correct locale may not what be exactly what you expect/want. This article provides a portal wide solution to handle locales in a consistent and transparent way.&lt;br /&gt;&lt;br /&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;Language selection process&lt;/b&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;WebSphere Portal server 6.x uses the following language selection process taken from the portal documentation:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The language encoded in the URL takes highest priority. The portal does not encode a locale into the URL by default.&lt;/li&gt;&lt;li&gt;If the user has logged in, the portal displays in the preferred language selected and stored in the user repository by the user.&lt;/li&gt;&lt;li&gt;If no preferred user language can be found, the portal looks for the language defined in the user's browser. If the portal supports that language, it displays the content in that language. If the browser has more than one language defined, the portal uses the first language in the list to display the content.&lt;/li&gt;&lt;li&gt;If no browser language can be found, for example if the browser used does not send a language, the portal resorts to its own default language.&lt;/li&gt;&lt;li&gt;If the user has a portlet that does not support the language that was determined by the previous steps, that portlet is shown in its own default language.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;div&gt;&lt;div&gt;By looking at step 3, the portal should accept the browser language if it supports this language. The same is true for the portlet itself. Unfortunately, it is not clear how the portal determines if a given language is supported or not. The documentation is not clear about this either.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;By executing extensive tests (removing languages with XML access and removing the resource bundles of those specific language from portal) with different locales sent from the browser, the portal always took the language from the browser if the user did not have a specific language set in its user profile. This is not an issue with the resource bundles since the application falls back to its default resource bundle if the language is not supported. The JSTL tags however did not use the proper language which resulted in dates and currencies formatted in the locale of the browser. Since we wanted tight control of the language used, this behaviour was not an option for us.&amp;nbsp;We wanted a Portal wide solution which did not impact application design/implementation.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The portal documentation mentions something about a locale filter. Portal itself provides two implementations of this filter: ExtendedLocaleFilter and SortingLocaleFilter. It is also possible to implement a custom filter.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The code of the provided locale filters can be found in C:\IBM\WP61\PortalServer\base\wp.engine.impl\shared\app\wp.engine.impl.jar file.&lt;/div&gt;&lt;br /&gt;Decompiling those filters you can see that the implementation reflects the above language selection process. The filters use the Puma API to determine the user’s locale. Also, by looking at this implementation you get a good idea of how to efficiently build a custom locale filter.&lt;br /&gt;&lt;br /&gt;The following filter is an example filter which always fixes the locale to en_US regardless of the user profile or browser setting.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{ font-size: x-small; color: black; font-family: Consolas, "Courier New", Courier, Monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; FixedLocaleFilter implements Filter {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; init(final FilterConfig aFilterConfig) throws ServletException {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; doFilter(final ServletRequest aServletRequest, final ServletResponse aResponse, final FilterChain aFilterChain) throws IOException, ServletException {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (aServletRequest instanceof HttpServletRequest) {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;            aFilterChain.doFilter(&lt;span class="kwrd"&gt;new&lt;/span&gt; FixedLocaleHttpServletRequest((HttpServletRequest) aServletRequest), aResponse);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;        } &lt;span class="kwrd"&gt;else&lt;/span&gt; {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;            aFilterChain.doFilter(aServletRequest, aResponse);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;        }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; destroy() {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;}&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; FixedLocaleHttpServletRequest extends HttpServletRequestWrapper {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; final Locale EN = &lt;span class="kwrd"&gt;new&lt;/span&gt; Locale(&lt;span class="str"&gt;"en"&lt;/span&gt;, &lt;span class="str"&gt;"US"&lt;/span&gt;);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; final Vector&amp;lt;Locale&amp;gt; LOCALES = &lt;span class="kwrd"&gt;new&lt;/span&gt; Vector&amp;lt;Locale&amp;gt;() {{&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;        add(EN);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;    }};&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; final Vector&amp;lt;String&amp;gt; ACCEPT_LANGUAGE_EN_US = &lt;span class="kwrd"&gt;new&lt;/span&gt; Vector&amp;lt;String&amp;gt;() {{&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;        add(&lt;span class="str"&gt;"en-US"&lt;/span&gt;);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;    }};&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; FixedLocaleHttpServletRequest (HttpServletRequest request) {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;        super(request);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;    @Override&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; Locale getLocale() {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; EN;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;    @Override&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; Enumeration getLocales() {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; LOCALES.elements();&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  39:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  40:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  41:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; String getHeader(String header) {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  42:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (isAcceptLanguageHeader(header))&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  43:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"en-US"&lt;/span&gt;;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  44:  &lt;/span&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  45:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; super.getHeader(header);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  46:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  47:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  48:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; Enumeration getHeaders(String s) {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  49:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (isAcceptLanguageHeader(s))&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  50:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; ACCEPT_LANGUAGE_EN_US.elements();&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  51:  &lt;/span&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  52:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; super.getHeaders(s);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  53:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  54:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  55:  &lt;/span&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; boolean isAcceptLanguageHeader(String s) {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  56:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; s.intern() == &lt;span class="str"&gt;"Accept-Language"&lt;/span&gt; || s.equalsIgnoreCase(&lt;span class="str"&gt;"Accept-Language"&lt;/span&gt;);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  57:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  58:  &lt;/span&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;The above FixedLocaleFilter just wraps the incoming request in a FixedLocaleHttpServletRequest. The next step is to configure this filter in the web.xml of the Portal application web.xml. The web.xml can be found in wp_profile_root/config/cells/node-name/applications/wps.ear/deployments/wps/wps.war/WEB-INF.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;See the following example configuration:&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{ font-size: x-small; color: black; font-family: Consolas, "Courier New", Courier, Monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&amp;lt;filter&amp;gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;        &amp;lt;filter-name&amp;gt;Locale Filter&amp;lt;/filter-name&amp;gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;        &amp;lt;!--&amp;lt;filter-&lt;span class="kwrd"&gt;class&lt;/span&gt;&amp;gt;com.ibm.wps.engine.ExtendedLocaleFilter&amp;lt;/filter-&lt;span class="kwrd"&gt;class&lt;/span&gt;&amp;gt;--&amp;gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;        &amp;lt;filter-&lt;span class="kwrd"&gt;class&lt;/span&gt;&amp;gt;FixedLocaleFilter&amp;lt;/filter-&lt;span class="kwrd"&gt;class&lt;/span&gt;&amp;gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    &amp;lt;/filter&amp;gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Please note that the above sample code is just an example unless you want a fixed locale of en_US for the whole profile where the portal is deployed. A practical scenario would be a custom filter which uses the following language selection process:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;If the user has set a locale in its profile use that one.&lt;/li&gt;&lt;li&gt;If the user has not set a locale use the browsers locale if the locale is supported.&lt;/li&gt;&lt;li&gt;If the browser locale is not supported use the default locale of the portal.&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;The above steps can easily be implemented using a custom locale filter. You can also use init parameters to make the filter configurable.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Letting all applications in a WebSphere portal behave the same regarding locale resolution can be hard/impossible if you do not want to implement custom locale handling code within the applications itself. By using a custom locale filter in WebSphere portal, the locale resolution code is kept in one place. This makes locale resolution transparent and clear to all applications running in the portal.&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-760893781419494544?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/760893781419494544/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=760893781419494544' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/760893781419494544'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/760893781419494544'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2011/08/websphere-portal-6x-locale-resolution.html' title='WebSphere Portal 6.x Locale Resolution'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-5577935864446335728</id><published>2011-06-06T20:37:00.001+02:00</published><updated>2011-06-06T20:40:31.337+02:00</updated><title type='text'>search engine meta information</title><content type='html'>Microsoft, Google and Yahoo, the companies behind the three major search engines Bing, Yahoo and Google, have launched a new initiative to add meta data to an HTML document. This meta data is used by the aforementioned search engines to improve the displaying of search results.&lt;br /&gt;&lt;br /&gt;Consider the following example:&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;    &amp;lt;div class="product"&amp;gt;&lt;br /&gt;        &amp;lt;!-- product information comes here. --&amp;gt;&lt;br /&gt;    &amp;lt;div&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The reader of this HTML fragment immediately sees that this is something about product information. A computer program, like a search engine instead, cannot determine that this information is actually about products.&lt;br /&gt;&lt;br /&gt;To help search engines, and potentially other software, understand the meta information behind the information,&amp;nbsp;&lt;a href="http://www.schema.org/"&gt;http://www.schema.org&lt;/a&gt;&amp;nbsp;describes a shared vocabulary which can be used to add meta data to HTML tags.&lt;br /&gt;&lt;br /&gt;Consider the revisited example:&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;    &amp;lt;div class="product" itemscope itemtype="http://schema.org/Product"&amp;gt;&lt;br /&gt;        &amp;lt;!-- product information comes here. --&amp;gt;&lt;br /&gt;    &amp;lt;div&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;By adding the itemscope attribute, you are telling the information between the div element is about a particular item. The itemtype attribute narrows this item further as a Product. This way, search engine can potentially add this information to an online product catalog making your products easier to find. Other types are available as wel, for example:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Movie&lt;/li&gt;&lt;li&gt;Event&lt;/li&gt;&lt;li&gt;Organisation&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;I implemented this meta tags for a new webshop I am building. These attributes are part of the HTML5 standard and therefore cannot be used by an XHTML1.1 strict syntax without passing the W3C validation. To use these attributes, just declare your document as HTML5. You can then use the W3C validator to fix any validation errors which may arise. I think this is worth the exercise.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;One step further to the semantic web.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-5577935864446335728?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/5577935864446335728/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=5577935864446335728' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/5577935864446335728'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/5577935864446335728'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2011/06/search-engine-meta-information.html' title='search engine meta information'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-6560386556079892164</id><published>2011-01-21T21:31:00.005+01:00</published><updated>2011-01-21T21:34:56.248+01:00</updated><title type='text'>Deploying Hippo on JBoss 4.2.3GA and PostgresQL 8.3</title><content type='html'>For a client of us we developed a public website with the Hippo CMS. Hippo CMS is a Java based Content Management System based on the Content Repository API. Hippo runs standard on Apache Tomcat and Mysql. We wanted to deploy Hippo on JBoss 4.2.3GA with Postgres 8.3. Below is a step-by-step guide to deploy Hippo 7, the cms.war artifact, on Jboss with Postgres 8.3.&lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;br /&gt;&lt;div&gt;&lt;b&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/b&gt;&lt;/div&gt;&lt;b&gt;1. Create a PostgresQL database&lt;/b&gt;&lt;br /&gt;Before you can deploy the cms.war file a PostgresQL database must be created. Hippo demands a database encoding of Latin1. If your PostgresQL database server is installed with a different encoding, excluding C or POSIX, you may not be able to create a Latin1 encoded database. If this is the case you can do one of the following:&lt;br /&gt;&lt;ol&gt;&lt;ol&gt;&lt;li&gt;Re-install the database server with a Latin1, C or POSIX locale. By using the C or POSIX locale you can create a database with any encoding you like, including Latin1.&lt;/li&gt;&lt;li&gt;Create a database with an encoding the &lt;span class="Apple-style-span" style="font-family: inherit;"&gt;current &lt;/span&gt;database server supports, for example UTF-8, and change the encoding of the database with the following SQL statement&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;:&amp;nbsp;ALTER DATABASE dbX SET client_encoding TO latin1; Make sure you restart the database server.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt;&lt;b&gt;2. Add the postgress JDBC-driver to the &lt;jboss_install&gt;/server/default/lib&lt;/jboss_install&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;3. Create a datasource&lt;/b&gt;&lt;br /&gt;Create a datasource in Jboss by creating a postgres-ds.xml in the &lt;jboss_install&gt;/server/default/deploy directory with the following contents:&lt;br /&gt;&lt;/jboss_install&gt;&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;datasources&amp;gt;&lt;br /&gt;    &amp;lt;local-tx-datasource&amp;gt;&lt;br /&gt;        &amp;lt;jndi-name&amp;gt;jdbc/repositoryDS&amp;lt;/jndi-name&amp;gt;&lt;br /&gt;        &amp;lt;connection-url&amp;gt;jdbc:postgresql://localhost:5432/hippo&amp;lt;/connection-url&amp;gt;&lt;br /&gt;        &amp;lt;driver-class&amp;gt;org.postgresql.Driver&amp;lt;/driver-class&amp;gt;&lt;br /&gt;        &amp;lt;user-name&amp;gt;postgres&amp;lt;/user-name&amp;gt;&lt;br /&gt;        &amp;lt;password&amp;gt;postgres&amp;lt;/password&amp;gt;--&amp;gt;&lt;br /&gt;        &amp;lt;blocking-timeout-millis&amp;gt;5000&amp;lt;/blocking-timeout-millis&amp;gt; &lt;br /&gt;          &amp;lt;idle-timeout-minutes&amp;gt;5&amp;lt;/idle-timeout-minutes&amp;gt; &lt;br /&gt;     &amp;lt;prepared-statement-cache-size&amp;gt;50&amp;lt;/prepared-statement-cache-size&amp;gt;&lt;br /&gt;       &amp;lt;/local-tx-datasource&amp;gt;&lt;br /&gt;&amp;lt;/datasources&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;4. Add a resource-ref to the cms.war web.xml&lt;/b&gt;&lt;br /&gt;&lt;div&gt;&lt;b&gt;&lt;/b&gt;Add the following resource-ref to the web.xml of the cms.war file:&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt; &amp;lt;resource-ref&amp;gt;&lt;br /&gt;        &amp;lt;res-ref-name&amp;gt;jdbc/repositoryDS&amp;lt;/res-ref-name&amp;gt;&lt;br /&gt;        &amp;lt;res-type&amp;gt;javax.sql.DataSource&amp;lt;/res-type&amp;gt;&lt;br /&gt;        &amp;lt;res-auth&amp;gt;Container&amp;lt;/res-auth&amp;gt;&lt;br /&gt;    &amp;lt;/resource-ref&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;You can add this element just before the closing &amp;lt;/web-app&lt;span class="Apple-style-span" style="font-family: monospace; font-size: 12px; line-height: 14px; white-space: pre;"&gt;&amp;gt; &lt;/span&gt;element.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;b&gt;5. Add a jboss-web.xml file to root of the WEB-INF directory of the cms.war&lt;/b&gt;&lt;/div&gt;&lt;div&gt;The jboss-web.xml defines the mapping between the datasource and the resource-ref. This file should have the following contents:&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;jboss-web&amp;gt;&lt;br /&gt;&amp;lt;resource-ref&amp;gt;&lt;br /&gt;  &amp;lt;res-ref-name&amp;gt;jdbc/repositoryDS&amp;lt;/res-ref-name&amp;gt; &lt;br /&gt;  &amp;lt;jndi-name&amp;gt;java:/jdbc/repositoryDS&amp;lt;/jndi-name&amp;gt; &lt;br /&gt;&amp;lt;/resource-ref&amp;gt;&lt;br /&gt;&amp;lt;/jboss-web&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;6. Modify the location of the repository.xml in the web.xml of the cms.war&lt;/b&gt;&lt;/div&gt;&lt;div&gt;We have to create a custom repository.xml file which configures Hippo for using PostgresQL. The location of the repository path should be modified so that it can find out repository.xml file. Change the location of the repository.xml file in de web.xml file to the following:&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;&amp;lt;servlet&amp;gt;&lt;br /&gt;        &amp;lt;servlet-name&amp;gt;Repository&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;        &amp;lt;servlet-class&amp;gt;org.hippoecm.repository.RepositoryServlet&amp;lt;/servlet-class&amp;gt;&lt;br /&gt;        &amp;lt;init-param&amp;gt;&lt;br /&gt;            &amp;lt;param-name&amp;gt;repository-config&amp;lt;/param-name&amp;gt;&lt;br /&gt;            &amp;lt;param-value&amp;gt;repository.xml&amp;lt;/param-value&amp;gt;&lt;br /&gt;            &amp;lt;description&amp;gt;The location of the repository configuration file.&lt;br /&gt;                Unless the location&lt;br /&gt;                starts with file://, the location is retrieved from within the application&lt;br /&gt;                package as&lt;br /&gt;                resource.&amp;lt;/description&amp;gt;&lt;br /&gt;        &amp;lt;/init-param&amp;gt;&lt;br /&gt;        &amp;lt;load-on-startup&amp;gt;4&amp;lt;/load-on-startup&amp;gt;&lt;br /&gt;    &amp;lt;/servlet&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;b&gt;7. Add the customized repository.xml file to the cms.war file&lt;/b&gt;&lt;br /&gt;The following repository.xml file should be added to the the cms.war file in the directory: WEB-INF/classes/org/hippoecm/repository. The bundle-cache is enabled in the following repository.xml which greatly improves the performance of the Hippo cms system. The cache size is set to 256MB but can be altered when needed.&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE Repository PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 1.5//EN"&lt;br /&gt;      "http://jackrabbit.apache.org/dtd/repository-1.5.dtd"&amp;gt;&lt;br /&gt;&amp;lt;Repository&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;FileSystem class="org.apache.jackrabbit.core.fs.db.DbFileSystem"&amp;gt;&lt;br /&gt;        &amp;lt;param name="url" value="java:comp/env/jdbc/repositoryDS" /&amp;gt;&lt;br /&gt;        &amp;lt;param name="driver" value="javax.naming.InitialContext" /&amp;gt;&lt;br /&gt;        &amp;lt;param name="schemaObjectPrefix" value="repository_" /&amp;gt;&lt;br /&gt;        &amp;lt;param name="schema" value="postgresql" /&amp;gt;&lt;br /&gt;    &amp;lt;/FileSystem&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;Security appName="Jackrabbit"&amp;gt;&lt;br /&gt;        &amp;lt;SecurityManager class="org.hippoecm.repository.security.SecurityManager" /&amp;gt;&lt;br /&gt;        &amp;lt;AccessManager class="org.hippoecm.repository.security.HippoAccessManager" /&amp;gt;&lt;br /&gt;        &amp;lt;LoginModule class="org.hippoecm.repository.security.HippoLoginModule" /&amp;gt;&lt;br /&gt;    &amp;lt;/Security&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;Workspaces rootPath="${rep.home}/workspaces"&lt;br /&gt;        defaultWorkspace="default" /&amp;gt;&lt;br /&gt;    &amp;lt;Workspace name="${wsp.name}"&amp;gt;&lt;br /&gt;        &amp;lt;FileSystem class="org.apache.jackrabbit.core.fs.db.DbFileSystem"&amp;gt;&lt;br /&gt;            &amp;lt;param name="url" value="java:comp/env/jdbc/repositoryDS" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="driver" value="javax.naming.InitialContext" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="schemaObjectPrefix" value="${wsp.name}_" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="schema" value="postgresql" /&amp;gt;&lt;br /&gt;        &amp;lt;/FileSystem&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;PersistenceManager&lt;br /&gt;            class="org.apache.jackrabbit.core.persistence.bundle.PostgreSQLPersistenceManager"&amp;gt;&lt;br /&gt;            &amp;lt;param name="driver" value="javax.naming.InitialContext" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="url" value="java:comp/env/jdbc/repositoryDS" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="schemaObjectPrefix" value="${wsp.name}_" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="externalBLOBs" value="true" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="consistencyCheck" value="true" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="consistencyFix" value="true" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="bundleCacheSize" value="256"/&amp;gt;&lt;br /&gt;        &amp;lt;/PersistenceManager&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;SearchIndex&lt;br /&gt;            class="org.hippoecm.repository.FacetedNavigationEngineThirdImpl"&amp;gt;&lt;br /&gt;            &amp;lt;param name="indexingConfiguration" value="indexing_configuration.xml" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="indexingConfigurationClass"&lt;br /&gt;                value="org.hippoecm.repository.query.lucene.ServicingIndexingConfigurationImpl" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="path" value="${wsp.home}/index" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="useCompoundFile" value="true" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="minMergeDocs" value="1000" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="volatileIdleTime" value="10" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="maxMergeDocs" value="1000000000" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="mergeFactor" value="5" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="maxFieldLength" value="10000" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="bufferSize" value="1000" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="cacheSize" value="1000" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="forceConsistencyCheck" value="true" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="enableConsistencyCheck" value="true" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="autoRepair" value="true" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="analyzer"&lt;br /&gt;                value="org.apache.lucene.analysis.standard.StandardAnalyzer" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="queryClass" value="org.apache.jackrabbit.core.query.QueryImpl" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="respectDocumentOrder" value="false" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="resultFetchSize" value="2147483647" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="extractorPoolSize" value="0" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="extractorTimeout" value="100" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="extractorBackLogSize" value="100" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="textFilterClasses"&lt;br /&gt;                value="org.apache.jackrabbit.extractor.PlainTextExtractor,org.apache.jackrabbit.extractor.MsWordTextExtractor,org.apache.jackrabbit.extractor.MsExcelTextExtractor,org.apache.jackrabbit.extractor.MsPowerPointTextExtractor,org.apache.jackrabbit.extractor.PdfTextExtractor,org.apache.jackrabbit.extractor.OpenOfficeTextExtractor,org.apache.jackrabbit.extractor.RTFTextExtractor,org.apache.jackrabbit.extractor.HTMLTextExtractor,org.apache.jackrabbit.extractor.XMLTextExtractor" /&amp;gt;&lt;br /&gt;        &amp;lt;/SearchIndex&amp;gt;&lt;br /&gt;    &amp;lt;/Workspace&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;Versioning rootPath="${rep.home}/version"&amp;gt;&lt;br /&gt;        &amp;lt;FileSystem class="org.apache.jackrabbit.core.fs.db.DbFileSystem"&amp;gt;&lt;br /&gt;            &amp;lt;param name="url" value="java:comp/env/jdbc/repositoryDS" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="driver" value="javax.naming.InitialContext" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="schemaObjectPrefix" value="version_" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="schema" value="postgresql" /&amp;gt;&lt;br /&gt;        &amp;lt;/FileSystem&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;PersistenceManager&lt;br /&gt;            class="org.apache.jackrabbit.core.persistence.bundle.PostgreSQLPersistenceManager"&amp;gt;&lt;br /&gt;            &amp;lt;param name="driver" value="javax.naming.InitialContext" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="url" value="java:comp/env/jdbc/repositoryDS" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="schemaObjectPrefix" value="version_" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="externalBLOBs" value="true" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="consistencyCheck" value="true" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="consistencyFix" value="true" /&amp;gt;&lt;br /&gt;            &amp;lt;param name="bundleCacheSize" value="256"/&amp;gt;&lt;br /&gt;        &amp;lt;/PersistenceManager&amp;gt;&lt;br /&gt;    &amp;lt;/Versioning&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex"&amp;gt;&lt;br /&gt;        &amp;lt;param name="path" value="${rep.home}/repository/index" /&amp;gt;&lt;br /&gt;        &amp;lt;param name="forceConsistencyCheck" value="true" /&amp;gt;&lt;br /&gt;        &amp;lt;param name="enableConsistencyCheck" value="true" /&amp;gt;&lt;br /&gt;    &amp;lt;/SearchIndex&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;DataStore class="org.apache.jackrabbit.core.data.db.DbDataStore"&amp;gt;&lt;br /&gt;        &amp;lt;param name="url" value="java:comp/env/jdbc/repositoryDS" /&amp;gt;&lt;br /&gt;        &amp;lt;param name="driver" value="javax.naming.InitialContext" /&amp;gt;&lt;br /&gt;        &amp;lt;param name="databaseType" value="postgresql" /&amp;gt;&lt;br /&gt;        &amp;lt;param name="minRecordLength" value="1024" /&amp;gt;&lt;br /&gt;        &amp;lt;param name="maxConnections" value="5" /&amp;gt;&lt;br /&gt;        &amp;lt;param name="copyWhenReading" value="true" /&amp;gt;&lt;br /&gt;    &amp;lt;/DataStore&amp;gt;&lt;br /&gt;&amp;lt;/Repository&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;8. Optionally: change the heap and permsize settings of JBoss.&lt;/b&gt;&lt;/div&gt;&lt;div&gt;I use the following memory settings for my configuration. Modify this in the run.bat startup script:&amp;nbsp;set JAVA_OPTS=%JAVA_OPTS% -Xms256m -Xmx768m -XX:MaxPermSize=256m&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;/ol&gt;&lt;div&gt;Thats it!&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-6560386556079892164?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/6560386556079892164/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=6560386556079892164' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/6560386556079892164'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/6560386556079892164'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2011/01/deploying-hippo-on-jboss-423ga-and.html' title='Deploying Hippo on JBoss 4.2.3GA and PostgresQL 8.3'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-5036864635643190813</id><published>2011-01-12T11:43:00.000+01:00</published><updated>2011-01-12T11:43:32.878+01:00</updated><title type='text'>Second Swiz workshop</title><content type='html'>On February the 16th I will be giving the second Swiz workshop for the Dutch Flex User Group. The workshop has been upgraded to Swiz 1.0 instead of 0.6. In this workshop I will show you how to apply the MVC pattern to Flex applications using the Swiz framework. More information about Swiz can be found&amp;nbsp;&lt;a href="http://www.swizframework.org/"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Registration is still open since there are still some seats available. You can register&amp;nbsp;&lt;a href="http://www.flugr.nl/events/tweede-de-flexswiz-workshop/"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;See you there!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-5036864635643190813?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/5036864635643190813/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=5036864635643190813' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/5036864635643190813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/5036864635643190813'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2011/01/second-swiz-workshop.html' title='Second Swiz workshop'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-5639853050232184407</id><published>2011-01-04T11:04:00.000+01:00</published><updated>2011-01-04T11:04:46.970+01:00</updated><title type='text'>20 Useful development tools</title><content type='html'>In this post I will take a look at 20, mostly free, useful tools which I use during my day-to-day software development. I am not talking about IDE's (I use various ones) here but small useful tools to increase developer productivity. The tools are listed in no particular order.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;IETester&lt;br /&gt;IITester can be used to test websites in various versions of Internet Explorer. A lot of website still require IE6 which can be difficult to test under Windows Vista or Windows 7. IETester provides a viable alternative which let you test your website in IE5.5, 6, 7 and 8. IETester can be found &lt;a href="http://www.google.nl/url?sa=t&amp;amp;source=web&amp;amp;cd=1&amp;amp;ved=0CCEQFjAA&amp;amp;url=http%3A%2F%2Fwww.my-debugbar.com%2Fwiki%2FIETester%2FHomePage&amp;amp;rct=j&amp;amp;q=ietester&amp;amp;ei=lNciTcvFOo-38gP64eS0BQ&amp;amp;usg=AFQjCNF_tDLTJQgeAKXrbUKXwWtqRIiI8g&amp;amp;sig2=uJYYiS8fX-loXFWOdb8z5g"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;PuTTY&lt;br /&gt;&lt;span id="goog_1949691424"&gt;&lt;/span&gt;&lt;span id="goog_1949691425"&gt;&lt;/span&gt; PuTTY is an open source terminal emulator which can act as a client for SSH, Telnet and other protocols. Useful tool for the remote management of computers. PuTTY can be found &lt;a href="http://www.chiark.greenend.org.uk/%7Esgtatham/putty/download.html"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Notepad++&lt;br /&gt;Notepad++ is a free source and text file editor which I use daily for text file editing. I do not use Notpad++ as a source code editor but it does support syntax highlighting for various languages. I find this useful as I sometimes use Notepad++ to look at source files. Notepad++ supports various plugins and does also have a column editing mode. To enable column editing mode just hold the "Alt" key and select the text with your left mouse button. Notepad++ can be found &lt;a href="http://notepad-plus-plus.org/"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;ArgoSoft Mail Server&lt;br /&gt;ArgoSoft mail server is a mail server which you can use on your localhost to sent and receive mails using POP3 en SMTP. This is a very useful tool when testing e-mail functionality in any application. ArgoSoft mail server Freeware edition can be found &lt;a href="http://www.argosoft.com/rootpages/DownloadRequest.aspx"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;GEDIS Studio&lt;br /&gt;GEDIS studio is a test data generation tool. They also have a free community edition which you can use to generate test data. The community edition also comes with text files which contains useful testdata which you can use to generate your own test- data/files. GEDIS studio can be found &lt;a href="http://www.gedis-studio.com/downloads-evaluation-trial-data-generator"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;FileZilla client&lt;br /&gt;FileZilla client is a free FTP client which I use a lot to transfer files to other machines using FTP. The FTP client is available for multiple platforms and can be found &lt;a href="http://filezilla-project.org/"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;MySQL Workbench&lt;br /&gt;For some projects I use MySQL. When working with MySQL I usually use the MySQL workbench for SQL development and server administration. The tool can also be used for data modeling. MySQL workbench can be found &lt;a href="http://wb.mysql.com/"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;JRebel&lt;br /&gt;When doing Java development I find the time it takes to reload changes in Java source files to publish back to the server frustratingly slow. JRebel enables the changes you make in Java source files to immediately be reflected in the runtime environment for example Tomcat, JBoss or WebSphere. Although JRebel is not free the money is really worth it. JRebel can be found &lt;a href="http://www.zeroturnaround.com/jrebel/"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;VMWare player&lt;br /&gt;I mainly develop on Windows 7. Sometimes I need to check something in another operating system, for example Ubuntu. VMWare player is a useful tool to run other operating systems in an easy way. I also use VMWare player when I give workshops. Instead of installing the prerequisites on every client machine, I distribute a VMWare image which participants use during the workshop. This saves me a lot of setup time and frustration. VMWare player can be found&amp;nbsp;&lt;a href="http://www.vmware.com/products/player/"&gt;here&lt;/a&gt;. &lt;/li&gt;&lt;li&gt;Paint.NET/Gimp&lt;br /&gt;Although graphic design is not my primary expertise I sometimes have the need to edit images for my web projects. I use Paint.NET and Gimp for this depending on what I need to do. Paint.NET can be found &lt;a href="http://www.paint.net/"&gt;here&lt;/a&gt; and Gimp can be found &lt;a href="http://www.gimp.org/downloads/"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;SQLite Administrator&lt;br /&gt;SQLite Administrator is a powerful tool if you easily want to create, design or administrate SQLite database files. I use SQLite Administrator for example when I use SQLite with Adobe Air. SQLite Administrator can be found &lt;a href="http://sqliteadmin.orbmu2k.de/"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Selenium IDE/iMacro&lt;br /&gt;When testing certain functionality during web application development you often must perform a sequence of steps before you can test the actual functionality. Selenium and iMacro let you record these steps and automate this process. This saves you a lot of time when testing the same functionality several times. SeleniumIDE can be found &lt;a href="http://seleniumhq.org/projects/ide/"&gt;here&lt;/a&gt; and iMacro can be found &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/3863/"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Firebug&lt;br /&gt;Firebug is useful tool when doing web application development. This Firefox plugin enables you to inspect the HTML and modify it in real time and analyze network traffic. Firebug also has a JavaScript debugger. Firebug can be found in the Firefox add-on window.&lt;/li&gt;&lt;li&gt;Chrome&lt;br /&gt;Chome also has a lot of useful tools when doing web application development. The tools in Chrome I use most are the element inspector, JavaScript debugger and network analysis tool.&lt;/li&gt;&lt;li&gt;YSlow&lt;br /&gt;YSlow is a Firebug extension which analyzes a web application based on client side performance indicators developed by Yahoo. YSlow makes suggestions in how to optimize the client side performance of your web application. YSlow can be found in the Firefox add-on window.&lt;/li&gt;&lt;li&gt;PageSpeed&lt;br /&gt;PageSpeed is a similar tool as YSlow but PageSpeed is developed by Google. I use both YSlow and PageSpeed. PageSpeed can be found &lt;a href="http://code.google.com/speed/page-speed/download.html"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;SoapUI&lt;br /&gt;SoapUI is a Java based tool for testing web services. SoapUI has a basic version for free which can be found &lt;a href="http://www.eviware.com/soapUI/soapui-products-overview.html"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Tamper data&lt;br /&gt;Tamper data is Firefox plugin to view and modify HTTP/HTTPS header and modify POST parameters. I use this tool for inspecting traffic sent from the browser to the server and for testing the security of web applications. Tamper data can be found &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/966/"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;REST Client&lt;br /&gt;REST Client is a Firefox plugin to easily test REST services and can be found &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/9780/"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Fiddler&lt;br /&gt;Fiddler is a web debugging proxy which can be used inspect the traffic sent from your browser over the Internet. I use this tool a lot in analyzing the traffic between the web application under development and the backend. It also supports HTTPS. Fiddler can be found &lt;a href="http://www.fiddler2.com/fiddler2/"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;/ol&gt;&amp;nbsp;This list is not exhaustive so I would like to know which tools you use?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-5639853050232184407?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/5639853050232184407/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=5639853050232184407' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/5639853050232184407'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/5639853050232184407'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2011/01/20-useful-development-tools.html' title='20 Useful development tools'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-276772672493165664</id><published>2010-09-29T13:24:00.003+02:00</published><updated>2010-09-29T13:30:52.087+02:00</updated><title type='text'>JRebel rocks!</title><content type='html'>Today I installed &lt;a target="_blank" href="http://www.zeroturnaround.com/jrebel/"&gt;JRebel&lt;/a&gt; because I was tired of all the Republish stuff when working with JBoss in Eclipse. I am glad I did! I am not sure how much time it saved me exactly (when working for 4 hours) but looking at the JBoss server.log showed the following:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_oGu2ZdqTixM/TKMiluCac0I/AAAAAAAAB-Q/L6KUEMfxFog/s1600/jrebel.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 41px;" src="http://2.bp.blogspot.com/_oGu2ZdqTixM/TKMiluCac0I/AAAAAAAAB-Q/L6KUEMfxFog/s320/jrebel.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5522295599495017282" /&gt;&lt;/a&gt;&lt;br /&gt;Maybe a little too optimistic, but a republish costs one minute at minimum. At 40 redeploys, this saves me about 45 minutes. This is 1.5 hour for a full work day!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-276772672493165664?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/276772672493165664/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=276772672493165664' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/276772672493165664'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/276772672493165664'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2010/09/jrebel-rocks.html' title='JRebel rocks!'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_oGu2ZdqTixM/TKMiluCac0I/AAAAAAAAB-Q/L6KUEMfxFog/s72-c/jrebel.JPG' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-1288312816076562152</id><published>2010-09-27T10:20:00.005+02:00</published><updated>2010-09-27T10:29:44.640+02:00</updated><title type='text'>Flex4 DateField bug when using locale nl_NL</title><content type='html'>When porting a Flex 3 application to Flex 4 (4.1 SDK), I had a little issue with my DateField components. The selected date in the DateField component did not have any formatting applied to it and when accessing the selectedData property in Actionscript returned null. For example selecting 7th September 2010 resulted in '0709092010' but it should be '07/09/2010'.&lt;br /&gt;&lt;br /&gt;Some searching revealed that this is a known bug which is hopefully resolved in SDK4.5. See &lt;a target="_blank" href="http://forums.adobe.com/message/2834803"&gt;http://forums.adobe.com/message/2834803&lt;/a&gt; for more details.&lt;br /&gt;&lt;br /&gt;A quick workaround is to specify the formatString explicitly in the DateField component as in the following example:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;lt;mx:DateField id=&amp;quot;date&amp;quot; formatString=&amp;quot;DD/MM/YYYY&amp;quot;/&amp;gt;&lt;br /&gt;&amp;lt;s:Button click=&amp;quot;trace(date.selectedDate);&amp;quot;/&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-1288312816076562152?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/1288312816076562152/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=1288312816076562152' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/1288312816076562152'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/1288312816076562152'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2010/09/flex4-datefield-bug-when-using-locale.html' title='Flex4 DateField bug when using locale nl_NL'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-3529087221371505671</id><published>2010-09-24T20:37:00.002+02:00</published><updated>2010-09-24T20:40:41.358+02:00</updated><title type='text'>FlexCamp presentation</title><content type='html'>Wednesday 22nd of September, I gave a presentation for the Dutch Flex User Group at FlexCamp at Adobe in Amsterdam. You can find this presentation below:&lt;br /&gt;&lt;br /&gt;&lt;div style="width:425px" id="__ss_5278841"&gt;&lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/JamieCraane/structuring-your-flex-application-with-swiz" title="Structuring your flex application with swiz"&gt;Structuring your flex application with swiz&lt;/a&gt;&lt;/strong&gt;&lt;object id="__sse5278841" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=structuringyourflexapplicationwithswiz-100924133517-phpapp02&amp;stripped_title=structuring-your-flex-application-with-swiz&amp;userName=JamieCraane" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse5278841" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=structuringyourflexapplicationwithswiz-100924133517-phpapp02&amp;stripped_title=structuring-your-flex-application-with-swiz&amp;userName=JamieCraane" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="padding:5px 0 12px"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/JamieCraane"&gt;Jamie Craane&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-3529087221371505671?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/3529087221371505671/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=3529087221371505671' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/3529087221371505671'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/3529087221371505671'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2010/09/flexcamp-presentation.html' title='FlexCamp presentation'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-743390492944361585</id><published>2010-09-03T13:49:00.005+02:00</published><updated>2010-09-06T20:40:43.500+02:00</updated><title type='text'>Printing in Vaadin</title><content type='html'>In one of my recent projects for one of our clients, I have used the Vaadin framework to develop the application. One of the requirements of this application was to print certain content. I basically evaluated three possible solutions to implement this functionality:&lt;br /&gt;&lt;br /&gt;&lt;ol style="margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0;"&gt;&lt;li&gt;Create a new window with content specifically designed for printing and use the JavaScript print() method to print the contents of this window;&lt;/li&gt;&lt;li&gt;Create a PDF with the printable contents and open this PDF in a new browser window;&lt;/li&gt;&lt;li&gt;Create a PDF with the printable contents and use the Embedded and Window components to display the PDF.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;I found option 1 not compatible and consistent enough between browsers. To create a consistent look&amp;feel of the printable contents I used PDF. One way to display this PDF to the end-user is to open a new browser window. Unfortunately this was hindered by popup blockers which is not acceptable to end-users of the application.&lt;br /&gt;&lt;br /&gt;Option 3 involved using an Embedded component to display the PDF inside a native Vaadin popup window (which is a regular div). This way, the printable contents are always consistent (because PDF is used) and the popup with the PDF contents is not hindered by browser popup blockers because the popup is just a regular div. By using this method, the print window also integrated nicely with the visual appearance of the rest of the application. The following code demonstrates how to implement this functionality:&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;/**&lt;br /&gt;     * This class creates a PDF with the iText library. This class implements&lt;br /&gt;     * the StreamSource interface which defines the getStream method.&lt;br /&gt;     */&lt;br /&gt;    public class Pdf implements StreamSource {&lt;br /&gt;        private final ByteArrayOutputStream os = new ByteArrayOutputStream();&lt;br /&gt;&lt;br /&gt;        public Pdf() {&lt;br /&gt;            Document document = null;&lt;br /&gt;&lt;br /&gt;            try {&lt;br /&gt;                document = new Document(PageSize.A4, 50, 50, 50, 50);&lt;br /&gt;                PdfWriter.getInstance(document, os);&lt;br /&gt;                document.open();&lt;br /&gt;&lt;br /&gt;                document.add(new Paragraph(&amp;quot;This is some content for the sample PDF!&amp;quot;));&lt;br /&gt;            } catch (Exception e) {&lt;br /&gt;                e.printStackTrace();&lt;br /&gt;            } finally {&lt;br /&gt;                if (document != null) {&lt;br /&gt;                    document.close();&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        @Override&lt;br /&gt;        public InputStream getStream() {&lt;br /&gt;            // Here we return the pdf contents as a byte-array&lt;br /&gt;            return new ByteArrayInputStream(os.toByteArray());&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And the code for displaying a popup with the actual PDF viewer:&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Window window = new Window();&lt;br /&gt;        ((VerticalLayout) window.getContent()).setSizeFull();&lt;br /&gt;        window.setResizable(true);&lt;br /&gt;        window.setWidth(&amp;quot;800&amp;quot;);&lt;br /&gt;        window.setHeight(&amp;quot;600&amp;quot;);&lt;br /&gt;        window.center();&lt;br /&gt;        Embedded e = new Embedded();&lt;br /&gt;        e.setSizeFull();&lt;br /&gt;        e.setType(Embedded.TYPE_BROWSER);&lt;br /&gt;&lt;br /&gt;        // Here we create a new StreamResource which downloads our StreamSource,&lt;br /&gt;        // which is our pdf.&lt;br /&gt;        StreamResource resource = new StreamResource(new Pdf(), &amp;quot;test.pdf?&amp;quot; + System.currentTimeMillis(), this);&lt;br /&gt;        // Set the right mime type&lt;br /&gt;        resource.setMIMEType(&amp;quot;application/pdf&amp;quot;);&lt;br /&gt;&lt;br /&gt;        e.setSource(resource);&lt;br /&gt;        window.addComponent(e);&lt;br /&gt;        getMainWindow().addWindow(window);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A full, working example including PDF generation, can be found &lt;a target="_blank" href="http://code.google.com/p/jc-examples/"&gt;here&lt;/a&gt;. The example project demonstrates displaying the PDF with and without a popup.&lt;br /&gt;&lt;br /&gt;What is your experience with printable content in a Vaadin application?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-743390492944361585?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/743390492944361585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=743390492944361585' title='21 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/743390492944361585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/743390492944361585'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2010/09/printing-in-vaadin.html' title='Printing in Vaadin'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>21</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-3757634451501707897</id><published>2010-09-03T12:25:00.003+02:00</published><updated>2010-09-03T12:30:58.893+02:00</updated><title type='text'>FlashBuilderCamp</title><content type='html'>On September 22nd, the Dutch Flex User Group organizes FlashBuilderCamp at Adobe in Amsterdam, The Netherlands. I will be giving a session about presentation patterns and how to implement these patterns with the &lt;a target="_blank" href="http://www.flugr.nl/events/flashbuildercamp/"&gt;Swiz&lt;/a&gt; framework. Swiz is a micro-architecture and dependency injection framework for structuring Flex applications which I used in a couple of major Flex application.&lt;br /&gt;&lt;br /&gt;Make sure you attend the conference. Entrance and dinner is free. More information can be found at &lt;a target="_blank" href="http://www.flugr.nl/events/flashbuildercamp/"&gt;Flugr&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-3757634451501707897?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/3757634451501707897/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=3757634451501707897' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/3757634451501707897'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/3757634451501707897'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2010/09/flashbuildercamp.html' title='FlashBuilderCamp'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-2177312030071216200</id><published>2010-08-05T08:05:00.007+02:00</published><updated>2010-08-05T08:11:40.905+02:00</updated><title type='text'>Stream erorr 2032 in Flex using HttpService</title><content type='html'>Lately I developed an application for a workshop I was giving. The application was a Flex application which communicated with a SpringMVC 3.0 annonation based based web application using Xstream as XML serialization library. All seemed well until in specific browsers and operation systems I got a 'Error #2032: Streamfault'. I did not found a solution on the Internet other than verifying that my URL was correct and disable HTTP caching on the server. None of these solutions worked.&lt;br /&gt;&lt;br /&gt;When I executed this specific request in the browser, I got a HTTP 406 status code. The 406 status code says: &lt;blockquote&gt;The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers ().&lt;/blockquote&gt; Inspecting the request the browser sent, showed an accept-header of '*/*'. I compared this to the accept-header FireFox sent which was: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'.&lt;br /&gt;&lt;br /&gt;The solution turned out to set the accept-header explicitly on the HttpService. I used the following code for this:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;var httpService:HTTPService = new HTTPService();&lt;br /&gt;httpService.url = url + &amp;quot;/tasks&amp;quot;;&lt;br /&gt;httpService.requestTimeout = 10;&lt;br /&gt;// Set the content type expected by the server&lt;br /&gt;httpService.contentType = &amp;quot;application/xml&amp;quot;;&lt;br /&gt;// Explicitly set the accept header&lt;br /&gt;httpService.headers = { accept: &amp;quot;text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8&amp;quot; };&lt;br /&gt;httpService.resultFormat = &amp;quot;e4x&amp;quot;;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;As a sidenote, to disable HTTP caching on the server, you can use the following code:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;response.addHeader(&amp;quot;Pragma&amp;quot;, &amp;quot;no-cache&amp;quot;);&lt;br /&gt;response.addHeader(&amp;quot;Cache-Control&amp;quot;, &amp;quot;no-cache&amp;quot;);&lt;br /&gt;response.addHeader(&amp;quot;Cache-Control&amp;quot;, &amp;quot;no-store&amp;quot;);&lt;br /&gt;response.addHeader(&amp;quot;Cache-Control&amp;quot;, &amp;quot;must-revalidate&amp;quot;);&lt;br /&gt;response.addHeader(&amp;quot;Expires&amp;quot;, &amp;quot;Mon, 8 Aug 2006 10:00:00 GMT&amp;quot;);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-2177312030071216200?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/2177312030071216200/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=2177312030071216200' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/2177312030071216200'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/2177312030071216200'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2010/08/stream-erorr-2032-in-flex-using.html' title='Stream erorr 2032 in Flex using HttpService'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-1023651161515516381</id><published>2010-05-10T10:04:00.006+02:00</published><updated>2010-05-20T11:22:01.204+02:00</updated><title type='text'>Flex workshop</title><content type='html'>At Wednesday the 2nd of June I will be giving a Flex/Swiz workshop. During this workshop I will show you how to develop a Flex application with the &lt;a target="_blank" href="http://swizframework.org"&gt;Swiz&lt;/a&gt; framework. Swiz is a micro architecture and dependency injection framework for Flex. Swiz does not restrict you in any way which enables you to use Swiz in almost any application. by using Swiz and, for example the MVCS pattern, the application becomes better testable and maintainable.&lt;br /&gt;&lt;br /&gt;The application we are building is a simple contact/task management application based on experiences from clients when building complex Flex applications. The application communicates with a Java backend using BlazeDS and XML/HTTP. The full workshop contents are presented on a VMWare image. The only prerequisite from the attendee is a laptop with VMWare player and at least 8 GB of free hard disk space.&lt;br /&gt;&lt;br /&gt;Agenda:&lt;br /&gt;June 2nd, 2010&lt;br /&gt;15:00 – 15:30 Welcome and introduction&lt;br /&gt;15:30 – 18:30 workshop&lt;br /&gt;18:30 – 19:00 Conclusion and dinner&lt;br /&gt;&lt;br /&gt;Location:&lt;br /&gt;QNH Business Integration&lt;br /&gt;Driebergseweg 2&lt;br /&gt;3708 JB Zeist&lt;br /&gt;&lt;br /&gt;There are still &lt;a target="_blank" href="http://www.flugr.nl/events/flex-workshop-creating-a-flex-application-with-the-swiz-framework/"&gt;seats&lt;/a&gt; available so be quick!&lt;br /&gt;&lt;br /&gt;See you there!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-1023651161515516381?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/1023651161515516381/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=1023651161515516381' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/1023651161515516381'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/1023651161515516381'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2010/05/flex-workshop.html' title='Flex workshop'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-4839794437796306650</id><published>2010-02-25T09:14:00.005+01:00</published><updated>2010-03-15T11:27:44.488+01:00</updated><title type='text'>Flex Camp 2010</title><content type='html'>Update: The presentations are online and can be found &lt;a href="http://www.flugr.nl/index.cfm?pid=22"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The first Flex Camp 2010 is a fact and was a great success. Flex Camp is organized by the Dutch Flex User Group (FLUGR) and is a half-day Flex event with a variety of speakers and subjects. This time, the location of the event was Amsterdam. The following sessions were given:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Designer/Developer workflow with Flash Catalyst and Flash Builder&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This session was all about how Flash Catalyst and Flash Builder approach the designer /developer workflow. In a traditional development environment a design usually takes the form of a Photoshop document which is sliced by the developer and incorporated in the Flex application. Flash Catalyst takes a new approach in that this product is able to import and slice the design itself. When imported, Flash Catalyst is able to convert individual elements to read-to-use Flex components.&lt;br /&gt;&lt;br /&gt;One thing that is not incorporated in the product yet, is an iterative design/development cycle although this can partly be accomplished with the use of libraries.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Set your code on fire&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Flex developers with a Java background are always disappointed by the lack of features of Flex Builder compared to working with Java editors. Luckily there are alternatives for Flex Builder and one of the alternatives is FDT from Powerflasher. During the session, an application was developed to show a lot of the capabilities of FDT. Very impressive. Some of FDT’s features are:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Rename and move refactoring&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Extended use of code templates and quick fixes to:&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Generate classes&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Generate functions&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Generate fields with getters and setters&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Loop over arrays&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Etc.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;li&gt;Superb code navigation possibilities like type hierarchy, dependency structure, outline view with search capabilities.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Debugger&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Version 4 of FDT, which is coming in 2010, has even more features like a memory and performance profiler. To learn more about version 4 goto &lt;a href="http://fdt.powerflasher.de/fdt4comfort"&gt;http://fdt.powerflasher.de/fdt4comfort&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Flex Builder action script projects&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Flex Builder is not only good in Flex projects but also suitable for Action script only projects. The speaker showed how he developed a pure Action script only website with Flex Builder. During the session a lot of practical tips were given which he encountered during the development of the website. Unfortunately, the site is not yet live at the time of writing. To be continued.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Flex in a JEE environment&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In this session the speaker demonstrated a Flex application which is used to display information about geographical locations. The application integrates with the backend using web services and Blazeds and is deployed on a JBoss application server. The speaker showed how Maven is used to build and distribute the application and how the Flex application can be configured using server side services. It was a very practical and good session, especially for Java and Flex developers.&lt;br /&gt;&lt;br /&gt;When all presentations are online, I will post the link to these presentations here.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;Flex Camp 2010 was a big success. The subjects of the sessions were diverse enough to please everyone who attended Flex Camp. From Flex designer/developer to hardcore Java developer. On to the next Flex Camp!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-4839794437796306650?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/4839794437796306650/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=4839794437796306650' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/4839794437796306650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/4839794437796306650'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2010/02/flex-camp-2010.html' title='Flex Camp 2010'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-3583145156762505463</id><published>2009-10-30T08:38:00.009+01:00</published><updated>2010-02-01T14:08:34.652+01:00</updated><title type='text'>Flex: How to create a different rollover color for the header in a datagrid component?</title><content type='html'>&lt;div&gt;&lt;i&gt;Update 01-02-2010: &lt;/i&gt;Monkey patching the Flex framework does not work when RSL's are used. This is because the code of the RSL is loaded in the first frame wether the monkey patched code is instantiated in the second frame and hence does not override the RSL classes. This can be solved by instantiating the monkey patched class in a custom preloader as described &lt;a href="http://www.jamesward.com/2009/03/10/flex-monkey-patching-and-framework-rsls/"&gt;here&lt;/a&gt;. Depending on the size of the included classes, this can invalidate the choice to use RSL's in the first place, namely to reduce application size. To include the monkey patched class in a custom preloader depends solely on the patch itself and the increased download size. These two factors should be taken into account.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;In my current project I have the following requirement for styling a DataGrid component:&lt;br /&gt;&lt;br /&gt;The roll-over color of the header should be of a different color than the roll-over color of the datagrid rows. To make things even more interesting, the roll-over color must be a gradient instead of a solid color.&lt;br /&gt;&lt;br /&gt;Unfortunately there is no easy way to accomplish this. We can set the default background color of the header with the headerColors style, but this color is overwritten when the mouse hovers over the header. We can also disable the rollover highlighting with the useRollOver property but this does not prevent from changing the rollover color of the header! Even if we could disable the header rollover color this way, it is not a solution because we want a different rollover color for the header and the rows containing the data.&lt;br /&gt;&lt;br /&gt;After some digging in the Flex SDK source code, the solution I came up with is to provide a customized DataGridHeader class. Please note that I customized the Flex 3.2.0 SDK because I use the 3.2.0 SDK. If you use the Flex 3.4.0 SDK you should modify the DataGridHeader class of the 3.4.0 SDK instead. To customize the DataGridHeader class I did the following:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Created a mx.controls.dataGridClasses package in my own source folder&lt;/li&gt;&lt;li&gt;Copied the DataGridHeader.as file from the Flex 3.2.0 SDK to my own mx.controls.dataGridClasses package&lt;/li&gt;&lt;li&gt;Located the mouseOver- and mouseDownHandlers and replaced the drawHeaderIndicator method with my own drawGradientBackGround method.&lt;/li&gt;&lt;li&gt;Added two new style attributes to the DataGridHeader class, named: startColor and endColor which defines the start- and endcolor of the gradient fill. These attributes are queried in the drawGradientBackGround method. For simplicity I did not provide default values so the default color is black.&lt;/li&gt;&lt;li&gt;Declared the startColor and endColor attributes in css and gave them a color value.&lt;/li&gt;&lt;/ol&gt;A full working example can be downloaded from &lt;a href="http://code.google.com/p/jc-examples/"&gt;http://code.google.com/p/jc-examples/&lt;/a&gt; as a zip file or from the svn repository. The following picture is taken from the sample project which demonstrates the gradient header color when the mouse is over the header. The mouse is over the &lt;span style="font-weight: bold;"&gt;name &lt;/span&gt;column in this case. Please note that this example uses the Flex 3.2.0 SDK.&lt;b&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_oGu2ZdqTixM/SuqcuZ9GV0I/AAAAAAAAB3U/6OCpEVwWfgs/s1600-h/datagridheader.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 259px; height: 206px;" src="http://4.bp.blogspot.com/_oGu2ZdqTixM/SuqcuZ9GV0I/AAAAAAAAB3U/6OCpEVwWfgs/s320/datagridheader.jpg" alt="" id="BLOGGER_PHOTO_ID_5398299424412030786" border="0" /&gt;&lt;/a&gt;&lt;/b&gt;&lt;/b&gt;&lt;br /&gt;If there are more straightforward solutions to this problem please share them.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Resources&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal; "&gt; &lt;a href="http://code.google.com/p/jc-examples/"&gt;http://code.google.com/p/jc-examples/&lt;/a&gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal; "&gt; &lt;a href="http://jc-examples.googlecode.com/files/DataGridHeaderColor.zip"&gt;Sample code as a zip file&lt;/a&gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-3583145156762505463?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/3583145156762505463/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=3583145156762505463' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/3583145156762505463'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/3583145156762505463'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2009/10/flex-how-to-create-different-rollover.html' title='Flex: How to create a different rollover color for the header in a datagrid component?'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_oGu2ZdqTixM/SuqcuZ9GV0I/AAAAAAAAB3U/6OCpEVwWfgs/s72-c/datagridheader.jpg' height='72' width='72'/><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-2244605845182037819</id><published>2009-10-03T16:17:00.001+02:00</published><updated>2009-10-04T11:42:06.638+02:00</updated><title type='text'>To inject or not to inject</title><content type='html'>&lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Last week I was a couple of days at a client to look at some strange behavior in the application. The application was a calculator used by clients of the company to calculate services the client offers. The application was written in Java6 and used Tapestry for the view and a Spring/Hibernate/AspectJ combination for the backend which talked against an Oracle database. Tomcat was used as the runtime container for the application.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;The first problem that had to be tackled was that sometimes the dependency injection did not work properly. Sometimes dependencies were injected, and other times not. When I looked at the application I noticed that an aspect was responsible for injecting repositories into domain objects. As soon as a domain object is deserialized or instantiated, the AnnotationBeanConfigurerAspect injected the repository. At least that was the intention. But the injection did not always take place. I further discovered that load-time weaving was used to inject the aspect’s behavior. I looked at the configuration and did not see anything that was wrong. The proper class loader in Tomcat was used and the necessary Spring configuration was present. What was causing this awkward behavior? Because time was limited I decided to switch to compile-time weaving. We compiled the classes with the AspectJ compiler and redeployed the application. This time the dependency injection was working as expected. We did not further investigate why load-time weaving did not work properly. If you have any suggestions please mention them.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;The second problem was that after a specific amount of inactivity at the application side, the application crashed when it was first accessed. The stack trace revealed that it was a problem with the underlying database connection. The message indicated that the connection was already closed. What was happening was that Oracle closes all idle connections after a specific amount of time, in our case 30 minutes. This is configured in the sqlnet.ora file with a parameter called sqlnet.expire. To overcome this, we added the following configuration to the Commons DBCP connection pool:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;testOnBorrow=true&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;validationQuery=SELECT 1 FROM DUAL&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;The result of this configuration is that all connections returned from the pool are first tested with the specified validation query. If the test fails the connection is discarded from the pool and a new one is returned. This solved our problem. I must mention that this configuration can have a negative impact on performance because every returned connection is checked for validity. Because of this, the simplest Oracle query is used to test the connection. Since the application did not have many concurrent transactions, this setting was acceptable.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;If performance is an issue, I would recommend using an eviction strategy where a specified eviction policy periodically checks all idle connections for validity. See the Commons DBCP configuration guide for an explanation to configure this.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;I hope some of you may find these solutions helpful in your own projects.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-2244605845182037819?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/2244605845182037819/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=2244605845182037819' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/2244605845182037819'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/2244605845182037819'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2009/10/to-inject-or-not-to-inject.html' title='To inject or not to inject'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-5807011638500651170</id><published>2009-06-16T10:52:00.016+02:00</published><updated>2009-06-16T14:12:38.161+02:00</updated><title type='text'>Melody composition using genetic algorithms</title><content type='html'>&lt;span style="font-weight: bold;"&gt;&lt;span style="font-size:180%;"&gt;Introduction&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Several techniques exist to create computer generated musical melodies. One of those techniques is genetic algorithms. Because the diversity of melodies over a specific range of notes is so large, genetic algorithms are a good candidate to help in composing melodies. This article describes how genetic algorithms can be used to compose musical melodies. this is explained following the steps needed to apply a genetic algorithm. These steps are:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Define the genetical representation of the problem&lt;/li&gt;&lt;li&gt;Determine the fitness function&lt;/li&gt;&lt;li&gt;Determine the parameters used for the run&lt;/li&gt;&lt;li&gt;Determine the termination criteria&lt;/li&gt;&lt;/ol&gt;The implementation of the genetic algorithm is done using the JGAP framework, a Java-based framework for implementing genetic algorithms. The generated melody itself is converted to MIDI which can then be played by the internal MIDI device or by a musical instrument attached to the computer&lt;br /&gt;&lt;br /&gt;For more information about using genetic algorithms in Java please see my previous article which can be found here: &lt;a href="http://jcraane.blogspot.com/2009/02/introduction-to-genetic-algorithms-with.html"&gt;introduction to genetic algorithms.&lt;/a&gt; For more information about music theory which is applied in this article please refer to the excellent site &lt;a href="http://www.musictheory.net/"&gt;http://www.musictheory.net&lt;/a&gt;.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;Define the genetical representation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Before the genetic algorithm can do it's work, the genetical representation of the problem must be defined. To make things slightly less complicated the following constraints are introduced:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Only harmonic melodies are supported. This means that only one note is played at ones at any given time in the melody.&lt;/li&gt;&lt;li&gt;The generated melodies do not adhere to a specific measure. It is just a sequence of notes.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;In a future version these constraints could be loosened.&lt;br /&gt;&lt;br /&gt;A Melody can be seen as a composition of individual notes and rests. Those individual notes have properties which define how a certain note must be played. The following properties are used which are modified by the genetic algorithm:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Pitch&lt;br /&gt;The pitch determines which notes on the grand staff is played. Possible values are C,D,E,F,G,A and B and all possible variants using sharps (#) and flats (b).&lt;/li&gt;&lt;li&gt;Octave&lt;br /&gt;The octave determines in which octave a certain note is played. A piano has seven full octaves.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Duration&lt;br /&gt;The length determines how long a certain note is played. Possible values are, whole notes, half notes, quarter notes, eight notes, sixteenth notes.&lt;/li&gt;&lt;/ul&gt;Notes have more properties than pitch and duration alone. Velocity, for example, indicates how hard a note is played. These properties are not used in this article. Besides notes, there are also rests in a melody. Rests can only have a duration.&lt;br /&gt;&lt;br /&gt;A solution in the search space of melody generation is a melody consisting of individual notes. A solution is represented as a chromosome with a fixed number of genes. The genes in the chromosome represent the individual notes and rests, each with it's own characteristics. A note can be represented by using a composite gene with three integer gene's. The three integer gene's represent pitch, octave and duration. Integer gene's are chosen in favor of a custom gene implementation to make mutation easy and simple across the individual gene's. Each gene is described in detail here:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Pitch&lt;/i&gt;: The pitch can be represented as a number from 1 to 12. Since there are twelve semitones in an octave, each semitone can be represented by a number from 1 to 12. Every following number is equal to one semitone. The mapping of the notes is:&lt;br /&gt;&lt;style type="text/css"&gt;.nobrtable br { display: none }&lt;/style&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.mytable tr td {border: 1px solid}&lt;/style&gt;&lt;br /&gt;&lt;div class="nobrtable"&gt;&lt;br /&gt;&lt;table class="mytable" width="30%"&gt;&lt;br /&gt;&lt;tbody&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;b&gt;Value&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;b&gt;Note&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;1&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;C&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;2&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;C# or Db&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;3&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;D&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;4&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;D# or Eb&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;5&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;E&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;6&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;F&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;7&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;F# or Gb&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;8&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;G&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;9&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;G# or Ab&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;10&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;A&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;11&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;A# or Bb&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;12&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;B&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;0&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;rest&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Because all gene's are treated the same, a special case for the a rest in a melody is introduced. A rest has the value of 0 for the pitch. Since a rest is not associated with an octave, the octave property is ignored.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Octave: &lt;/i&gt;an octave can be represented by a number, the octave in which a certain note is played. The octave is indicated by a number from 1 to 7 where 1 represents the lowest octave on a piano keyboard and 7 the highest.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Duration: &lt;/i&gt;the duration can be represented by a number between 1 and 5. The mapping of the numbers are:&lt;br /&gt;&lt;style type="text/css"&gt;.nobrtable br { display: none }&lt;/style&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.mytable tr td {border: 1px solid}&lt;/style&gt;&lt;br /&gt;&lt;div class="nobrtable"&gt;&lt;br /&gt;&lt;table class="mytable" width="30%"&gt;&lt;br /&gt;&lt;tbody&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;b&gt;Value&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;b&gt;Note&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;1&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;Whole note&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;2&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;Half note&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;3&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;Quarter note&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;4&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;Eighth note&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;5&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;Sixteenth note&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The duration applies to both notes and rests. See the following code for the creation of the initial population of chromosomes:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;Configuration.reset();&lt;br /&gt;Configuration gaConf = new DefaultConfiguration();&lt;br /&gt;gaConf.resetProperty(Configuration.PROPERTY_FITEVAL_INST);&lt;br /&gt;gaConf.setFitnessEvaluator(new DeltaFitnessEvaluator());&lt;br /&gt;&lt;br /&gt;gaConf.setPreservFittestIndividual(true);&lt;br /&gt;gaConf.setKeepPopulationSizeConstant(false);&lt;br /&gt;&lt;br /&gt;gaConf.setPopulationSize(40);&lt;br /&gt;CompositeGene gene = new CompositeGene(gaConf);&lt;br /&gt;// Add the pitch gene&lt;br /&gt;gene.addGene(new IntegerGene(gaConf, 0, 12), false);&lt;br /&gt;// Add the octave gene&lt;br /&gt;gene.addGene(new IntegerGene(gaConf, 1, 7), false);&lt;br /&gt;// Add the length (from 3 - 5 is from quarter to sixteenth)&lt;br /&gt;gene.addGene(new IntegerGene(gaConf, 1, 5), false);&lt;br /&gt;&lt;br /&gt;// A size of 16 represent 16 notes&lt;br /&gt;IChromosome sampleChromosome = new Chromosome(gaConf, gene, 16);&lt;br /&gt;gaConf.setSampleChromosome(sampleChromosome);&lt;br /&gt;&lt;br /&gt;gaConf.setFitnessFunction(melodyFitnessFunction);&lt;br /&gt;&lt;br /&gt;return Genotype.randomInitialGenotype(gaConf);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;font-size:180%;" &gt;Determine the fitness function&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;The fitness function determines how good a specific melody is, relative to other melodies. The fitness function is the most complicated part of this problem since the fitness of a melody is subjective. Because of this nature, two approaches for fitness determination are presented.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Computer generated fitness&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;The computer generated fitness is purely based on certain algorithms to measure the fitness of a melody. Since there are a lot of different parameters, the fitness function combines the fitness value of several different strategies which can be easily added to the fitness function. Some of these parameters, but not limited to, are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;80% of the notes in a melody may not have more than than 7 semitones difference.&lt;/li&gt;&lt;li&gt;A melody may not span more than 2 octaves&lt;/li&gt;&lt;li&gt;A melody must be in C-major (or minor scale)&lt;/li&gt;&lt;li&gt;Only 10% of a melody may consist of rests&lt;/li&gt;&lt;li&gt;Two consecutive notes may not lie more than 5 semitones from each other&lt;/li&gt;&lt;li&gt;...&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;In the proof-of-concept implementation the following rules regarding the fitness of a melody are implemented. These rules are implemented as separate classes which all implement the MelodyFitnessStrategy interface. This makes it easy and straightforward to add more rules which measure the fitness of a melody.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;ScaleStrategy&lt;br /&gt;Calculates if a given melody adheres to a specific scale, for example C major. The scale can be set as a parameter on this class.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;IntervalStrategy&lt;br /&gt;Calculates if a given melody has one or more major and/or perfect intervals. The number of major and perfect intervals can be set as parameters on this class.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;GlobalPitchDistributionStrategy&lt;br /&gt;Calculates if the lowest and highest pitch of a given melody fall within the margins specified by this class. The margin is indicated as the number of semitones and a percentage about how much of the notes must fall between the given semitones. These values can be set as parameters on this class.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;RepeatingNotesStrategy&lt;br /&gt;Calculates if a given melody has repeating notes or rests. The maximum number of repeating notes and/or rests can be set as parameters on this class.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;PropertionRestAndNotesStrategy&lt;br /&gt;Calculates the proportion between the notes and rests in a given melody. The propertion of notes/rests can be set as parameter on this class.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;ParallelIntervalStrategy&lt;br /&gt;Calculates the number of parallel intervals in this melody. Some parallel intervals are supposed to sound good, like thirds and sixths. The number of good sounding parallel intervals can be set as a parameter on this class.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;A builder class exists which helps in the creation of a valid fitness function.&lt;br /&gt;&lt;br /&gt;Please note that all rules calculate the deviation between the generated melody and the specified rules. A lower fitness value means less deviation which means a better melody. In the future it is planned to add more strategies to calculate the fitness of a given melody. For example:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;ContourStrategy. Strategy which calculates if a given melody has a specific contour in the pitch of the individual notes.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Below is the implementation of the ScaleStrategy:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;public final class ScaleStrategy extends AbstractMelodyFitnessStrategy {&lt;br /&gt;  private static final int ERROR_COUNT_WHEN_NOTE_NOT_ON_SCALE = 1;&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  // The more difference between current note and note in scale the higher the error count&lt;br /&gt;  public double calculateErrors(IChromosome melody) {&lt;br /&gt;     double errors = 0.0D;&lt;br /&gt;     for (Gene gene : melody.getGenes()) {&lt;br /&gt;        Note note = GeneNoteFactory.fromGene((CompositeGene) gene);&lt;br /&gt;        if (Pitch.REST != note.getPitch() &amp;amp;&amp;amp; !super.scale.contains(note.getPitch())) {&lt;br /&gt;           errors += ERROR_COUNT_WHEN_NOTE_NOT_ON_SCALE;&lt;br /&gt;        }&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     // Adhering to a given scale is quite important so square the result&lt;br /&gt;     return (errors * errors) * 10;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public String toString() {&lt;br /&gt;     return "[ScaleStrategy[scale: " + this.scale + "]]";&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;A different approach&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;The above paragraph describes how the fitness of a melody can be computed based on the knowledge of music theory. Instead of using music theory to compute the fitness of a melody, a different approach can be used. This approach looks at the melody as audio data, an array of bytes, instead as a sequence of notes. From this audio data, different information can be extracted. For example, by using a Fast Fourier Transform (FFT), the audio data can be viewed in the frequency domain. By analyzing existing melodies using FFT, an algorithm can be constructed which measures the fitness of generated melodies based on this knowledge. A future version of the application may use the technique described here.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Human intervention based fitness&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Since melodies are very subjective it is hard to come up with a computer based mechanism to measure how good a specific melody is. Another approach which can be used is a human based intervention fitness function. In this approach the user is represented with a fixed set of melodies generated by the genetic algorithm. The user selects two or three melodies which participate in the next evolution. Although this approach is not implemented in the current version, expect a future release to use this approach.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:180%;" &gt;Determine the run parameters&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;When using a computer based fitness function, several parameters which affect the generated melody can be provided by the user. See the section about the computer generated fitness function which parameters can be supplied. Based on some sample runs, the number of evolutions to execute is 250. 250 evolutions seems like a good trade off between quality of the generated melody and computation time. The quality is measured in terms of the fitness value of the melody. With 250 evolutions, the fitness value of a 24-note melody almost always approaches zero.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:180%;" &gt;Determine the termination criteria&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;The run ends when 250 evolutions are executed.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:180%;" &gt;Some sample runs&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The program can be executed in two different ways:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;By executing the MelodyGeneratorMain class file from the command line. Modify and recompile this class to alter the parameters of the run, for example the fitness function.&lt;/li&gt;&lt;li&gt;Via the Swing UI. This is a very simple Swing UI build with Groovy's SwingBuilder. All of the parameters of the fitness function can be modified with this UI. Please note that this is a very simple UI implementation and not an example of how to write production quality Swing code.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;To generate a melody from the UI, just click the generate button. When finished, the application plays back the melody and gives the option to replay, save or generate a new melody. Just experiment with the different settings and listen to the various generated melodies. In the UI you can specify the path to write the MIDI files to. Make sure this path exists on disk.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:180%;" &gt;Conclusion&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;This article explains how genetic algorithms can be used to compose melodies. Genetic algorithms seem like a viable alternative for melody generation since they are very well suited to search for specific solutions in very large search spaces. In this case the search space are all possible combination of notes. The difficulty in generating melodies with genetic algorithms is the specification of the fitness function since this is very subjective.&lt;br /&gt;Although the melodies generated by this program are nowhere near hit melodies, they can be used as inspiration when composing melodies. The performance of the algorithm can be improved by writing additional (and more complex) strategies to measure the fitness of a melody.&lt;br /&gt;&lt;br /&gt;Let me know what ideas you have to measure the fitness of the generated melodies to improve the quality of the melodies.&lt;br /&gt;&lt;br /&gt;The full source code of this application can be found on Google code, see the resources.&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Resources&lt;/span&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/jc-examples/"&gt;http://code.google.com/p/jc-examples/&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.blogger.com/www.musictheory.net"&gt;www.musictheory.net&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-5807011638500651170?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/5807011638500651170/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=5807011638500651170' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/5807011638500651170'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/5807011638500651170'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2009/06/melody-composition-using-genetic.html' title='Melody composition using genetic algorithms'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-7621048394767610435</id><published>2009-04-20T12:50:00.004+02:00</published><updated>2009-04-20T13:07:09.640+02:00</updated><title type='text'>J-Spring 2009 part 2</title><content type='html'>&lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;The second keynote was given by Jos Warmer, a Model Driven Architecture evangelist. Jos has a lot of experience with MDA and you can see that from his talk. His talk was about &lt;a href="http://www.mod4j.org/"&gt;Mod4j&lt;/a&gt;. According to the website: “Mod4j (Modelling for Java) is an open source DSL-based environment for developing administrative enterprise applications.”&lt;o:p&gt;&lt;/o:p&gt;&lt;/insert&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;&lt;o:p&gt;&lt;/o:p&gt;Mod4j is an environment in which DSL’s are used to generate specific parts of a Java application. At the moment three DSL’s are implemented (and a fourth is on its way) which focuses on specific architectural layers of the application. These DSL’s are:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;ul style="margin-top: 0cm;" type="disc"&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style="" lang="EN-GB"&gt;Business Domain DSL&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style="" lang="EN-GB"&gt;Data Contract DSL&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style="" lang="EN-GB"&gt;Service DSL&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;&lt;o:p&gt;&lt;/o:p&gt;The&lt;i style=""&gt; business domain DSL&lt;/i&gt; implements the concepts to specify the business objects in your application. These are: business objects with properties, associations between business objects and constraints. Consider the following example:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;association Order order one -&amp;gt; many OrderLine orderLines ordered;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The above sample DSL generates a one-to-many association from the Order to the OrderLines class including the necessary Hibernate mapping files. A lot of boilerplate code is generated by using the business domain DSL.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;The &lt;i style=""&gt;Service DSL&lt;/i&gt; is used to specify services for your domain objects. Examples are the CRUD operations of a specific domain object and finder methods. The code generator for this DSL takes care of generating the required Java code. Consider the following code:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;from RecordShopDataContract import SimpleCustomerDto;&lt;br /&gt;create createCustomer for SimpleCustomerDto ;&lt;br /&gt;read readCustomer for SimpleCustomerDto ;&lt;br /&gt;update updateCustomer for SimpleCustomerDto ;&lt;br /&gt;delete deleteCustomer for SimpleCustomerDto ;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The preceding code generates the &lt;/span&gt;&lt;span style="" lang="EN-GB"&gt;CRUD &lt;/span&gt;&lt;span style="" lang="EN-GB"&gt;methods for the SimpleCustomerDto in the service class.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;What’s nice about Mod4j is that no visual models are used for code generation. Domain Specific Languages are used instead. The DSL’s can be put in a version control system where you are able to use the version control system’s merge and history abilities; something which is hard to implement when using visual models. There are also a lot of extension points to modify the generated code. But when you find yourself modifying too much of the generated code, you must ask yourself if the code generator should be modified instead. With mod4j this is possible because it is open source. What’s also nice is that there is an Eclipse plug-in to facilitate Mod4j development. With this plug-in you get code completion on the provided DSL’s.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;Although I am not a big fan of Model Driven Architecture tools, I like the concept and principles of Mod4j mainly because coding is central. When should you use Mod4j? I find this a difficult question. When working on a large multi-layered application in Java with technologies like Hibernate, Mod4j can make sure that a consistent architecture is used across all layers. New developers can be more easily brought up to speed.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;But when looking at the DSL’s used for generating code, I immediately thought of the Grails framework, based on Groovy. Grails uses a lot of DSL’s. Consider the following Grails example which creates an Author business object:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;class Author {&lt;br /&gt;   static hasMany = [ books : Book ]&lt;br /&gt;   String name&lt;br /&gt;   static constraints = {&lt;br /&gt;       name(size:5..15,blank:false)&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The above code is the Author business object in Grails with a one-to-many association to the Book class. It also implements a constraint on the name property. Because of the dynamic nature of Groovy, you get the &lt;/span&gt;&lt;span style="" lang="EN-GB"&gt;CRUD &lt;/span&gt;&lt;span style="" lang="EN-GB"&gt;operations, dynamic finders and the relationship handling for free. If you want to customize the mappings you can modify the Hibernate mapping files if you want.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;So the DSL Grails uses is what I call an executable DSL whereas the DSL’s that Mod4j uses are used to generate Java code. &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;Despite this there is still place for a technology like Mod4j. Not everyone is in the position to use Grails (or Rails) to facility high speed web development. When plain Java web development is used, Mod4j provides a viable alternative to speed-up this development. I will definitely keep an eye out for Mod4j!&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"&gt;&lt;b style=""&gt;&lt;span style="" lang="EN-GB"&gt;Service Oriented Architecture&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;    &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;The next session I went to was about Service Oriented Architectures from Tijs Rademakers. His presentation turned out to be a very practical session which included a lot of his own experiences when implementing Service Oriented Architectures. I like this approach very much. He clarified some misunderstandings when using ESB’s. When an ESB is used, often a lot of code has to be written inside the ESB. Think of transformation and routing logic. This code has to be maintained as well which is often underestimated.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;Tijs also talked about how to handle XML messages in a Service Oriented Architecture. I always thought that Groovy has superior XML handling capabilities compared to Java. Tijs mentioned Groovy as one of the most effective ways for handling XML. I agree! So when working with XML in Java (Service Oriented Architecture or not), consider using the Groovy language for the XML handling logic.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;      &lt;p class="MsoNormal"&gt;&lt;b style=""&gt;&lt;span style="" lang="EN-GB"&gt;Conclusion&lt;/span&gt;&lt;/b&gt;&lt;span style="" lang="EN-GB"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;Despite the economical situation, 4 people of my company (including me) went to the J-Spring. At &lt;a href="http://www.qnh-ads.nl"&gt;QNH&lt;/a&gt; we find it very important to continue to invest in knowledge. Individuals are the most important part of a company in which you should invest.&lt;o:p&gt;&lt;/o:p&gt;&lt;/insert&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;&lt;o:p&gt;&lt;/o:p&gt;I found the J-Spring 2009 a very good day with lots of good speakers and sessions with a great variety of subjects well worth the investment. If you’re a Dutch Java developer and was not part of J-Spring, make sure you will be at J-Fall later this year.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;Keep up the good work!&lt;br /&gt;&lt;span style="" lang="EN-GB"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-7621048394767610435?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/7621048394767610435/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=7621048394767610435' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/7621048394767610435'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/7621048394767610435'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2009/04/j-spring-part-2.html' title='J-Spring 2009 part 2'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-3762854151826385408</id><published>2009-04-17T14:26:00.008+02:00</published><updated>2009-04-20T13:05:58.950+02:00</updated><title type='text'>J-Spring 2009 part 1</title><content type='html'>&lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;April 15th I went to the Dutch Java user group conference named J-Spring. This is the first of two blog entries about this conference. The J-Spring is a popular 1 day conference about Java and related technologies. It is a good place to &lt;o:p&gt;&lt;/o:p&gt;get an overview about the current state of technology and meet fellow developers.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="" lang="EN-GB"&gt;&lt;o:p&gt;&lt;/o:p&gt;The introductory keynote was given by Sherali Karimov&lt;/span&gt;&lt;span style="" lang="EN-GB"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="" lang="EN-GB"&gt; &lt;/span&gt;&lt;span style="" lang="EN-GB"&gt;from Atlassian who talked about how agile is implemented at Atlassian.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;Two things in his presentation I found particular interesting. These were:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;ul style="margin-top: 0cm;" type="disc"&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style="" lang="EN-GB"&gt;The disturbed&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span style="" lang="EN-GB"&gt;Blitz tests&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;      &lt;p class="MsoNormal"&gt;&lt;b style=""&gt;&lt;span style="" lang="EN-GB"&gt;The disturbed&lt;/span&gt;&lt;/b&gt;&lt;span style="" lang="EN-GB"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;We are all familiar with it. Sometimes you and your team members get so many questions from different people that your own work suffers from it. At Atlassian they introduced the role: the disturbed. Whenever someone has the disturbed role, he/she is expected NOT to do any work but instead answer all questions from outside. The other team members can focus on delivering. The disturbed role is changed every week to another team member. Every week a new team member is responsible for answering questions from people outside the team. Besides shielding the team from outside questions, the disturbed role has another advantage. By switching team members to answer questions, gradually each team member gains the knowledge to answer those questions. It is an effective and practical way to share knowledge within the team.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;      &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;b style=""&gt;&lt;span style="" lang="EN-GB"&gt;Blitz tests&lt;/span&gt;&lt;/b&gt;&lt;span style="" lang="EN-GB"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;Another concept that was introduced is Blitz tests. Atlassian uses there own products inside there own company. Whenever a new release of a particular product is released, it is deployed on the company’s production environment. People from within the company can subscribe to test the new functionality. The experience at Atlassian was that a lot of people subscribed and were eager to test the new functionality. They gave a lot of good feedback to the development team which resulted in higher quality software. I believe you gain a lot when you have the possibility to test every new release by certain people in your own company before releasing the product to your customers.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;      &lt;p class="MsoNormal"&gt;&lt;b style=""&gt;&lt;span style="" lang="EN-GB"&gt;JEE and JavaFX&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="" lang="EN-GB"&gt;The next session I went to was from Paul Bakker. This session was about the future of web development with JEE6 and JavaFX. Paul gave a very complete overview about all the technologies involved in JEE6 and JavaFX. A couple of technologies used in JEE6 are JSF 2.0, JAX-RS and JPA 2.0. After giving a brief overview about every technology, Paul showed how to build a web application with JSF and JavaFX together. Basically, JavaFX was used for the highly interactive parts and JSF for the HTML forms. JavaScript was used to act as a bridge between the HTML page and the JavaFX applet. He also showed how to pass parameters between the applet and the HTML page and vice versa. This seems like an effective way to combine JavaFX with regular web development. JEE6 and JavaFX definitely look very promising!&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;&lt;o:p&gt;&lt;/o:p&gt;Look out for the second post of the J-Spring which will highlight some interesting points from the other sessions I attended.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-3762854151826385408?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/3762854151826385408/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=3762854151826385408' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/3762854151826385408'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/3762854151826385408'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2009/04/j-spring-2009-part-1.html' title='J-Spring 2009 part 1'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-8039241771236039651</id><published>2009-04-06T12:56:00.001+02:00</published><updated>2009-04-06T12:57:36.533+02:00</updated><title type='text'>J-Spring</title><content type='html'>&lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;Next week, April 15th, I am going to the Dutch Java User Group conference named J-Spring. This one-day conference is a good place in helping to keep your knowledge up-to-date. There are a lot of interesting sessions which you can attend and a lot of fellow developers to have discussions with. &lt;/span&gt;I Am planning to attend&lt;span style="" lang="EN-GB"&gt; the following sessions:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;            &lt;ol&gt;&lt;li&gt;&lt;span style="" lang="EN-GB"&gt;&lt;o:p&gt;&lt;/o:p&gt;Developing web applications of the future: Combining JavaFX &amp;amp; JEE 6&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="" lang="EN-GB"&gt;&lt;o:p&gt;&lt;/o:p&gt;Java Programming in a Multicore World&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="" lang="EN-GB"&gt;&lt;o:p&gt;&lt;/o:p&gt;SOA, it's a hard knock life&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="" lang="EN-GB"&gt;&lt;o:p&gt;&lt;/o:p&gt;REST, the web as the database?&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="" lang="EN-GB"&gt;&lt;o:p&gt;&lt;/o:p&gt;Hop on Board the Java Troubleshooting Platform&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;    &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;I will post my experience of the J-Spring next week.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-8039241771236039651?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/8039241771236039651/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=8039241771236039651' title='36 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/8039241771236039651'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/8039241771236039651'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2009/04/j-spring.html' title='J-Spring'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>36</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-7057024440520590393</id><published>2009-02-23T15:13:00.023+01:00</published><updated>2009-03-10T13:42:08.377+01:00</updated><title type='text'>Introduction to Genetic Algorithms with JGAP</title><content type='html'>Out of interest I am familiarizing myself in genetic algorithms, in short GA. My interest in GA came when I first heard about the JGAP project. As mentioned on the project's site "JGAP (pronounced "jay-gap") is a Genetic Algorithms and Genetic Programming component provided as a Java framework.". For a newcomer I found it difficult to get a good overview about all the concepts introduced in genetic algorithms. Before diving into JGAP, I think it is essential that these concepts are well understood. This post is an introduction to genetic algorithms (GA) with JGAP and is explained with a concrete example. In one of my next posts I will demonstrate solving a problem with genetic programming (GP).&lt;br /&gt;&lt;br /&gt;So what is a genetic algorithm? Given is the following definition from John R. Koza:&lt;br /&gt;&lt;br /&gt;&lt;cite style="text-align: center;"&gt;The genetic algorithm is a &lt;b&gt;probabilistic search algorithm&lt;/b&gt; that iteratively transforms a set (called a &lt;b&gt;population&lt;/b&gt;) of mathematical objects (typically fixed-length binary character strings), each with an associated &lt;b&gt;fitness value&lt;/b&gt;, into a new population of offspring objects using the Darwinian principle of &lt;b&gt;natural selection&lt;/b&gt; and using operations that are patterned after naturally occurring &lt;b&gt;genetic operations&lt;/b&gt;, such as &lt;b&gt;crossover&lt;/b&gt; (sexual recombination) and &lt;b&gt;mutation&lt;/b&gt;.&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;In genetic algorithms, a &lt;b&gt;potential solution&lt;/b&gt; is called a &lt;b&gt;chromosome&lt;/b&gt;. A chromosome consists of a fixed length of &lt;b&gt;genes&lt;/b&gt;. A gene is a distinct component of a potential solution. During the &lt;b&gt;evolution&lt;/b&gt; of the genetic algorithm, multiple solutions (chromosomes) are combined (&lt;b&gt;crossover&lt;/b&gt; and &lt;b&gt;mutation&lt;/b&gt;) to form, potentially, better solutions. The evolution is done over a population of solutions. The population of solutions is called a &lt;b&gt;genotype&lt;/b&gt; and consists of a fixed-length of chromosomes. During each evolution, &lt;b&gt;natural selection&lt;/b&gt; is applied to determine which solutions (chromosomes) make it to the next evolution. The input criteria for the selection process is the so-called &lt;b&gt;fitness&lt;/b&gt; of a potential solution. Solutions with a better fitness value are more likely to appear in the next evolution than solutions with a worse fitness value. The fitness value of a potential solution is determined by a &lt;b&gt;user-supplied fitness function&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Although it is possible to implement the above concepts yourself, JGAP already took care of this. Because the best way to learn is by example, let me first introduce the problem domain which I am going to solve with genetic algorithms. During the example, the concepts mentioned above are further clarified.&lt;br /&gt;&lt;br /&gt;Consider a moving company which is specialized in moving boxes (with things in it) from one location to another. These boxes have varying volumes. The boxes are put in vans in which the boxes are moved from location to location. To reduce transport costs, it is crucial for the moving company to use as minimal vans as possible. &lt;b&gt;Problem statement:&lt;/b&gt; given a number of boxes of varying volumes, what is the optimal arrangement of the boxes so that a minimal number of vans is needed? The following example shows how to solve this problem with genetic algorithms and JGAP.&lt;br /&gt;&lt;br /&gt;First: with the arrangement of the boxes I mean the following: consider 5 boxes with the following volumes (in cubic meters): 1,4,2,2 and 2 and vans with a capacity of 4 cubic meters. When the boxes are put in the vans based on the initial arrangement, the distribution of the boxes in the vans is like this:&lt;br /&gt;&lt;table style="border-width: 1px;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt;Van&lt;b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;Boxes&lt;b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;Space wasted&lt;b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Van 1&lt;/td&gt;&lt;td&gt;Box 1&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Van 2&lt;/td&gt;&lt;td&gt;Box 4&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Van 3&lt;/td&gt;&lt;td&gt;Box 2, Box 2&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Van 4&lt;/td&gt;&lt;td&gt;Box 2&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;Fitness value = 3+2 * 4 = 20. See section &lt;a href="http://jcraane.blogspot.com/2009/02/introduction-to-genetic-algorithms-with.html#fitness"&gt;fitness function&lt;/a&gt; for an explanation of the fitness function for this particular problem.&lt;br /&gt;&lt;br /&gt;A total of 4 vans is needed. But when the number of vans needed is calculated, which is the total volume of the boxes divided by the volume of the vans, the optimal number of vans is: 11 / 4 = 2.75. Because no partial vans can be used the optimal number of vans needed is 3. The optimal arrangement of the boxes is the following: 1,2,2,2,4. Based on this arrangement the distribution looks like this:&lt;br /&gt;&lt;table style="border-width: 1px;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt;Van&lt;b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;Boxes&lt;b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;Space wasted&lt;b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Van 1&lt;/td&gt;&lt;td&gt;Box 1, Box 2&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Van 2&lt;/td&gt;&lt;td&gt;Box 2, Box 2&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Van 3&lt;/td&gt;&lt;td&gt;Box 4&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;Fitness value of 1 * 3 = 3.&lt;br /&gt;&lt;br /&gt;Before implementing the actual solution, the following &lt;i&gt;preparatory steps&lt;/i&gt; must be taken. These preparatory steps are always needed if genetic algorithms is used to solve a particular problem.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Define the &lt;i&gt;genetical representation&lt;/i&gt; of the problem domain. The boxes which must be put in the vans are represented by an array of Box instances. The genetic algorithm must find the optimal arrangement in the array as how to put the boxes in the vans. A chromosome is a potential solution and consists of a fixed-length of genes. A potential solution in this example consists of a list of indexes where each index represents a Box in the box array. To represent such index, I use an IntegerGene. As mention earlier, a gene is a distinct part of the solution. In this example, a solution (chromosome) consists of as many genes as there are boxes. The genes must be ordered by the genetic program in such a way that it represents a (near) optimal arrangement. For example: if there are 50 boxes, a chromosome with 50 IntegerGene's is constructed, where each gene's value is initialized to an index in the box array, in this case from 0 to 49.&lt;/li&gt;&lt;li&gt;Determine the &lt;i&gt;fitness function&lt;/i&gt;. The fitness function determines how good a potential solution is compared to other solutions. In this problem domain, a solution is fitter when fewer vans are needed so less space is wasted.&lt;/li&gt;&lt;li&gt;Determine the &lt;i&gt;parameters&lt;/i&gt; used for the run. For the run I use a population size of 50 and a total number of 5000 evolutions. So the genotype (the population) initially consists of 50 chromosomes (potential solutions). These values are chosen based on some experimentation and can vary based on the specific problem.&lt;/li&gt;&lt;li&gt;Determine the &lt;i&gt;termination criteria&lt;/i&gt;. The program ends when 5000 evolutions are reached or when the optimal number of vans needed is reached. The optimal number of vans can be calculated by dividing the total volume of the boxes by the capacity of the vans and rounding the result up (because no partial vans can be used).&lt;/li&gt;&lt;/ol&gt;&lt;b&gt;Initialization&lt;/b&gt;&lt;br /&gt;The Box class has a volume. In this example 125 boxes are created with varying volumes between 0.25 and 3.00 cubic meters. The boxes are stored in an array. The following code creates the boxes:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;Random r = new Random(seed);&lt;br /&gt;this.boxes = new Box[125];&lt;br /&gt;for (int i = 0; i &amp;lt; 125; i++) {&lt;br /&gt; Box box = new Box(0.25 + (r.nextDouble() * 2.75));&lt;br /&gt; box.setId(i);&lt;br /&gt; this.boxes[i] = box;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Before we configure JGAP we must first implement a fitness function. The fitness function is the most important part in genetic algorithms as it determines which populations potentially make in to the next evolution. The fitness function for this problem looks like this:&lt;/div&gt;&lt;div&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;package nl.jamiecraane.mover;&lt;br /&gt;&lt;br /&gt;import org.jgap.FitnessFunction;&lt;br /&gt;import org.jgap.IChromosome;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* Fitness function for the Mover example. See this&lt;br /&gt;* {@link #evaluate(IChromosome)} for the actual fitness function.&lt;br /&gt;*/&lt;br /&gt;public class MoverFitnessFunction extends FitnessFunction {&lt;br /&gt;  private Box[] boxes;&lt;br /&gt;  private double vanCapacity;&lt;br /&gt;&lt;br /&gt;  public void setVanCapacity(double vanCapacity) {&lt;br /&gt;          this.vanCapacity = vanCapacity;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void setBoxes(Box[] boxes) {&lt;br /&gt;          this.boxes = boxes;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /**&lt;br /&gt;   * Fitness function. A lower value value means the difference between the&lt;br /&gt;   * total volume of boxes in a van is small, which is better. This means a&lt;br /&gt;   * more optimal distribution of boxes in the vans. The number of vans needed&lt;br /&gt;   * is multiplied by the size difference as more vans are more expensive.&lt;br /&gt;   */&lt;br /&gt;  @Override&lt;br /&gt;  protected double evaluate(IChromosome a_subject) {&lt;br /&gt;          double wastedVolume = 0.0D;&lt;br /&gt;&lt;br /&gt;          double sizeInVan = 0.0D;&lt;br /&gt;          int numberOfVansNeeded = 1;&lt;br /&gt;          for (int i = 0; i &amp;lt; boxes.length; i++) {&lt;br /&gt;                  int index = (Integer) a_subject.getGene(i).getAllele();&lt;br /&gt;                  if ((sizeInVan + this.boxes[index].getVolume()) &amp;lt;= vanCapacity) {&lt;br /&gt;                          sizeInVan += this.boxes[index].getVolume();&lt;br /&gt;                  } else {&lt;br /&gt;                          // Compute the difference&lt;br /&gt;                          numberOfVansNeeded++;&lt;br /&gt;                          wastedVolume += Math.abs(vanCapacity - sizeInVan);&lt;br /&gt;                          // Make sure we put the box which did not fit in this van in the next van&lt;br /&gt;                          sizeInVan = this.boxes[index].getVolume();&lt;br /&gt;                  }&lt;br /&gt;          }&lt;br /&gt;          // Take into account the number of vans needed. More vans produce a higher fitness value.&lt;br /&gt;          return wastedVolume * numberOfVansNeeded;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a name="fitness"&gt;&lt;/a&gt;The above fitness function loops through all the genes in the supplied potential solution (where each gene in the chromosome represents an index in the box array) and calculates how many vans are needed for this arrangement of boxes to fit in the vans. The fitness value is based on the space wasted in every van when a new van is needed, called the wasted volume. The total volume wasted is multiplied by the number of vans needed. This is done to create a much worse fitness value when more vans are needed. In the above, simplified, example the fitness value of the first solution is 20 and the fitness value of the second, optimal, solution is 3. One term deserves more explanation and that is allele. In the above code the getAllele method on the gene is called. Allele is just another word for the value of the gene. Because all genes all IntegerGene's, the value of each gene is of type Integer.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;Next it is time to setup JGAP:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;private Genotype configureJGAP() throws InvalidConfigurationException {&lt;br /&gt; Configuration gaConf = new DefaultConfiguration();&lt;br /&gt;// Here we specify a fitness evaluator where lower values means a better fitness&lt;br /&gt;Configuration.resetProperty(Configuration.PROPERTY_FITEVAL_INST);&lt;br /&gt;gaConf.setFitnessEvaluator(new DeltaFitnessEvaluator());&lt;br /&gt;&lt;br /&gt;// Only use the swapping operator. Other operations makes no sense here&lt;br /&gt;// and the size of the chromosome must remain constant&lt;br /&gt;gaConf.getGeneticOperators().clear();&lt;br /&gt;SwappingMutationOperator swapper = new SwappingMutationOperator(gaConf);&lt;br /&gt;gaConf.addGeneticOperator(swapper);&lt;br /&gt;&lt;br /&gt;// We are only interested in the most fittest individual&lt;br /&gt;gaConf.setPreservFittestIndividual(true);&lt;br /&gt;gaConf.setKeepPopulationSizeConstant(false);&lt;br /&gt;&lt;br /&gt;gaConf.setPopulationSize(50);&lt;br /&gt;// The number of chromosomes is the number of boxes we have. Every chromosome represents one box.&lt;br /&gt;int chromeSize = this.boxes.length;&lt;br /&gt;Genotype genotype;&lt;br /&gt;&lt;br /&gt;// Setup the structure with which to evolve the solution of the problem.&lt;br /&gt;// An IntegerGene is used. This gene represents the index of a box in the boxes array.&lt;br /&gt;IChromosome sampleChromosome = new Chromosome(gaConf, new IntegerGene(gaConf), chromeSize);&lt;br /&gt;gaConf.setSampleChromosome(sampleChromosome);&lt;br /&gt;// Setup the fitness function&lt;br /&gt;MoverFitnessFunction fitnessFunction = new MoverFitnessFunction();&lt;br /&gt;fitnessFunction.setBoxes(this.boxes);&lt;br /&gt;fitnessFunction.setVanCapacity(VOLUME_OF_VANS);&lt;br /&gt;gaConf.setFitnessFunction(fitnessFunction);&lt;br /&gt;&lt;br /&gt;// Because the IntegerGenes are initialized randomly, it is neccesary to set the values to the index. Values range from 0..boxes.length&lt;br /&gt;genotype = Genotype.randomInitialGenotype(gaConf);&lt;br /&gt;List chromosomes = genotype.getPopulation().getChromosomes();&lt;br /&gt;for (Object chromosome : chromosomes) {&lt;br /&gt;    IChromosome chrom = (IChromosome) chromosome;&lt;br /&gt;    for (int j = 0; j &amp;lt; chrom.size(); j++) {&lt;br /&gt;        Gene gene = chrom.getGene(j);&lt;br /&gt;        gene.setAllele(j);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;return genotype;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;In the above code we setup the JGAP library. The provided Javadoc should be self-explanatory. A population (genotype) of 50 potential solutions (chromosomes) is created where every chromosome consists of the same number of genes as there are boxes. Because in this example a lower fitness value is better, theDeltaFitnessEvaluator is used.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Next, it is time to evolve the population. The population is evolved 5000 times. When the optimal amount of vans is reached earlier, the run ends. The following code demonstrates the evolution of the problem solution:&lt;/div&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;private void evolve(Genotype a_genotype) {&lt;br /&gt;int optimalNumberOfVans = (int) Math.ceil(this.totalVolumeOfBoxes / VOLUME_OF_VANS);&lt;br /&gt;LOG.info("The optimal number of vans needed is [" + optimalNumberOfVans + "]");&lt;br /&gt;     &lt;br /&gt;double previousFittest = a_genotype.getFittestChromosome().getFitnessValue();&lt;br /&gt;numberOfVansNeeded = Integer.MAX_VALUE;&lt;br /&gt;for (int i = 0; i &amp;lt; NUMBER_OF_EVOLUTIONS; i++) {&lt;br /&gt;   if (i % 250 == 0) {&lt;br /&gt;       LOG.info("Number of evolutions [" + i + "]");&lt;br /&gt;   }&lt;br /&gt;   a_genotype.evolve();&lt;br /&gt;   double fittness = a_genotype.getFittestChromosome().getFitnessValue();&lt;br /&gt;   int vansNeeded = this.numberOfVansNeeded(a_genotype.getFittestChromosome().getGenes()).size();&lt;br /&gt;   if (fittness &amp;lt; previousFittest &amp;amp;&amp;amp; vansNeeded &amp;lt; numberOfVansNeeded) {&lt;br /&gt;       this.printSolution(a_genotype.getFittestChromosome());&lt;br /&gt;       previousFittest = fittness;&lt;br /&gt;       numberOfVansNeeded = vansNeeded;&lt;br /&gt;   }&lt;br /&gt;             &lt;br /&gt;   // No more optimal solutions&lt;br /&gt;   if (numberOfVansNeeded == optimalNumberOfVans) {&lt;br /&gt;       break;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;IChromosome fittest = a_genotype.getFittestChromosome();&lt;br /&gt;&lt;br /&gt;List&amp;lt;Van&amp;gt; vans = numberOfVansNeeded(fittest.getGenes());&lt;br /&gt;printVans(vans);&lt;br /&gt;this.printSolution(fittest);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Because we set the preserveFittest property on the JGAP configuration object to true, we have access to the most fittest chromosome with the getFittestChromosome() method. The fittest chromosome consists of 125 genes, the indexes of the boxes in the array, in the arrangement of how to put the boxes in the vans. The actual evolution is performed by JGAP. The fitness value determines which populations have the highest chance to make it to the next evolution. Eventually a (near) optimal solution is formed. This indicates the importance of a well chosen fitness function as it is used in the selection process of the chromosomes. Below is the output of a sample run:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;The total volume of the [125] boxes is [210.25989987666645] cubic metres.&lt;br /&gt;The optimal number of vans needed is [49]&lt;br /&gt;Number of evolutions [0]&lt;br /&gt;Fitness value [4123.992085987977]&lt;br /&gt;The total number of vans needed is [63]&lt;br /&gt;Fitness value [3458.197333300851]&lt;br /&gt;The total number of vans needed is [61]&lt;br /&gt;Fitness value [3138.2899569572887]&lt;br /&gt;The total number of vans needed is [60]&lt;br /&gt;Fitness value [2865.5105375433063]&lt;br /&gt;The total number of vans needed is [59]&lt;br /&gt;Fitness value [2562.282028584251]&lt;br /&gt;The total number of vans needed is [58]&lt;br /&gt;Fitness value [2267.7135196251966]&lt;br /&gt;The total number of vans needed is [57]&lt;br /&gt;Fitness value [1981.8050106661412]&lt;br /&gt;The total number of vans needed is [56]&lt;br /&gt;Fitness value [1704.5565017070858]&lt;br /&gt;The total number of vans needed is [55]&lt;br /&gt;Fitness value [1479.769464870246]&lt;br /&gt;The total number of vans needed is [54]&lt;br /&gt;Number of evolutions [250]&lt;br /&gt;Fitness value [1215.9278601031112]&lt;br /&gt;The total number of vans needed is [53]&lt;br /&gt;Fitness value [1002.6487336510297]&lt;br /&gt;The total number of vans needed is [52]&lt;br /&gt;Number of evolutions [500]&lt;br /&gt;Fitness value [774.5352329142294]&lt;br /&gt;The total number of vans needed is [51]&lt;br /&gt;Number of evolutions [750]&lt;br /&gt;Number of evolutions [1000]&lt;br /&gt;Fitness value [535.1696373214758]&lt;br /&gt;The total number of vans needed is [50]&lt;br /&gt;Number of evolutions [1250]&lt;br /&gt;Number of evolutions [1500]&lt;br /&gt;Number of evolutions [1750]&lt;br /&gt;Number of evolutions [2000]&lt;br /&gt;Number of evolutions [2250]&lt;br /&gt;Fitness value [307.8713731063958]&lt;br /&gt;The total number of vans needed is [49]&lt;br /&gt;Van [1] has contents with a total volume of [4.204196540671411] and contains the following boxes:&lt;br /&gt;Box:0, volume [2.2510465109421443] cubic metres.&lt;br /&gt;Box:117, volume [1.9531500297292665] cubic metres.&lt;br /&gt;Van [2] has contents with a total volume of [4.185233471369987] and contains the following boxes:&lt;br /&gt;Box:17, volume [1.0595047801111055] cubic metres.&lt;br /&gt;Box:110, volume [0.5031165156303853] cubic metres.&lt;br /&gt;Box:26, volume [2.6226121756284955] cubic metres.&lt;br /&gt;Van [3] has contents with a total volume of [4.312990612147265] and contains the following boxes:&lt;br /&gt;Box:91, volume [1.8897555340430203] cubic metres.&lt;br /&gt;Box:6, volume [2.423235078104245] cubic metres.&lt;br /&gt;...Further output omitted&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;As seen in the above output, the optimal number of vans is reached between 2250 and 2500 evolutions. The program also outputs the distribution of the boxes in the vans. The complete source code of the above example can be downloaded from &lt;a href="http://code.google.com/p/jc-examples/"&gt;http://code.google.com/p/jc-examples/&lt;/a&gt;. The down-loadable artifact is called ga-moving-example-1.0.jar.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Conclusion&lt;br /&gt;&lt;/b&gt;Genetic algorithms and programming is an exciting technology but with a lot of concepts which are hard to grasp if you are new to the field. This post is an introduction of the concepts for genetic algorithms and showed how to implement a GA solution with JGAP. In one of my next posts, genetic programming is explained with a concrete example.&lt;br /&gt;&lt;br /&gt;The silver bullet rule applies to genetic algorithms as well. To give you an impression, the following problems are good candidates to solve with GA:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Problems where it is hard to find a solution but once a solution is found, measure how good this particular solution is.&lt;/li&gt;&lt;li&gt;Problems where the search space is very large, complex or poorly understood.&lt;/li&gt;&lt;li&gt;Problems where a near optimal solution is acceptable.&lt;/li&gt;&lt;li&gt;Problems where no mathematical analysis is available.&lt;/li&gt;&lt;/ul&gt; Although I am not an expert on the subject, feel free to ask your questions and I will try to answer them as best as possible.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;b&gt;Resources&lt;/b&gt;&lt;br /&gt;[1] &lt;a href="http://www.gp-field-guide.org.uk/"&gt;Field guide to genetic programming&lt;/a&gt;&lt;br /&gt;[2] &lt;a href="http://jgap.sf.net/"&gt;http://jgap.sf.net&lt;/a&gt;&lt;br /&gt;[3] &lt;a href="http://en.wikipedia.org/wiki/Genetic_algorithm"&gt;http://en.wikipedia.org/wiki/Genetic_algorithm&lt;/a&gt;&lt;br /&gt;[5] &lt;a href="http://www.genetic-programming.org/"&gt;http://www.genetic-programming.org/&lt;/a&gt;&lt;br /&gt;[6] &lt;a href="http://code.google.com/p/jc-examples/"&gt;http://code.google.com/p/jc-examples/&lt;/a&gt;.&lt;br /&gt;[7] &lt;a href="http://en.wikipedia.org/wiki/Knapsack_problem"&gt;http://en.wikipedia.org/wiki/Knapsack_problem&lt;/a&gt;.&lt;br /&gt;[8] &lt;a href="http://en.wikipedia.org/wiki/Bin_packing_problem"&gt;http://en.wikipedia.org/wiki/Bin_packing_problem&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-7057024440520590393?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/7057024440520590393/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=7057024440520590393' title='40 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/7057024440520590393'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/7057024440520590393'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2009/02/introduction-to-genetic-algorithms-with.html' title='Introduction to Genetic Algorithms with JGAP'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>40</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-3098013398592852356</id><published>2009-01-28T21:41:00.004+01:00</published><updated>2009-01-28T21:59:18.022+01:00</updated><title type='text'></title><content type='html'>I finally found the time to finish my FolderVisualizer application. To recap: FolderVisualizer draws a Tree Map of a selected folder which makes it easy to see which folders/files take up the most space. You can also delete these folders from within the application. I started this project with a colleague to do a comparison between Adobe Air and JavaFX. &lt;br /&gt;&lt;br /&gt;Version 2.0.0RC1 is down-loadable from the project's website. The following screenshot gives an impression of the application:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_oGu2ZdqTixM/SYDDyoQDxWI/AAAAAAAABVc/nKkJTEZ9gpI/s1600-h/visualizer.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 254px;" src="http://4.bp.blogspot.com/_oGu2ZdqTixM/SYDDyoQDxWI/AAAAAAAABVc/nKkJTEZ9gpI/s320/visualizer.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5296448436353353058" /&gt;&lt;/a&gt;The application implements the following functionality:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Select a folder which must be visualized in the tree map&lt;/li&gt;&lt;br /&gt;&lt;li&gt;drill down to other folders&lt;/li&gt;&lt;br /&gt;&lt;li&gt;change the number (density) of the folders in the tree map&lt;/li&gt;&lt;br /&gt;&lt;li&gt;provide a breadcrumb navigation path for easy navigation&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Delete the selected folder/file&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Visual effects when changing view stacks&lt;/li&gt;&lt;br /&gt;&lt;li&gt;More appealing theme/colors than the previous version&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;Version 2 is a complete rewrite of the whole application. Because a lot of new functionality is added, I restructured the application to make it more maintainable and transparent. As a guideline, I used the principles of MVCS, which is basically a set of design guidelines to implement the Model View Controller Service architecture in Flex applications. It is NOT a framework unlike for example Cairngorm. I Used Cairngorm on another project but I had the impression that the framework gets in your way. I found myself writing to much boilerplate code like commands, custom events, controllers etc. I'm NOT saying that Cairngorm is a bad framework, but I found it to complicated for the task at hand: structuring a Flex application in a well defined matter.&lt;br /&gt;&lt;br /&gt;On the other hand, I really like the clarity and simplicity of the MVCS approach and the freedom to adapt the principles to your application's needs. The FolderVisualizer application consists of a couple controllers, a model class which contains references to the application's model objects, a FileService and components which make up the view. To handle user interaction, I used the event bubbling approach. In the event bubbling approach, when the user clicks on a button, a UIEvent is dispatched. This event "bubbles" up to the parent who handles it, usually a controller. This controller is responsible for handling the business logic associated with this specific user action. Consider the following example, taken from the FolderVisualizer application:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt;mx:HBox xmlns:mx=&amp;quot;http://www.adobe.com/2006/mxml&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;mx:Metadata&amp;gt;&lt;br /&gt;        [Event(name=&amp;quot;uiEvent&amp;quot;,type=&amp;quot;nl.foldervisualizer.events.UIEvent&amp;quot;)]&lt;br /&gt;    &amp;lt;/mx:Metadata&amp;gt;&lt;br /&gt;    &lt;br /&gt;    &amp;lt;mx:Script&amp;gt;&lt;br /&gt;        &amp;lt;![CDATA[&lt;br /&gt;           ... Some code omitted&lt;br /&gt;            &lt;br /&gt;            [Bindable]&lt;br /&gt;            public var model : Model;&lt;br /&gt;            &lt;br /&gt;            private function handleBack(event:Event):void {&lt;br /&gt;                dispatchEvent(new UIEvent(UIEventKind.BACK))&lt;br /&gt;            }&lt;br /&gt;            &lt;br /&gt;          ... Some code omitted&lt;br /&gt;        ]]&amp;gt;&lt;br /&gt;    &amp;lt;/mx:Script&amp;gt;&lt;br /&gt;    &lt;br /&gt;    &amp;lt;mx:Spacer width=&amp;quot;5&amp;quot;/&amp;gt;&lt;br /&gt;    &amp;lt;mx:Button label=&amp;quot;Back&amp;quot; click=&amp;quot;handleBack(event)&amp;quot;/&amp;gt;&lt;br /&gt;    ... Some code omitted&lt;br /&gt;&amp;lt;/mx:HBox&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;The above code is taken from the NavigationControlBar.mxml which implements the navigational actions a user can perform. When a user clicks on the back button, a UIEvent is dispatched of kind UIEventKind.BACK. Also note that this component defines an event "uiEvent" which parent containers can use to add an eventListener which listens for UIEvents. See the following code-snippet taken from FolderVisualizer.mxml, which is the parent container of the NavigationControlBar:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt;mx:HBox xmlns:mx=&amp;quot;http://www.adobe.com/2006/mxml&amp;quot;&lt;br /&gt;    xmlns:toolbox=&amp;quot;http://www.flextoolbox.com/2006/mxml&amp;quot;&lt;br /&gt;    xmlns:view=&amp;quot;nl.foldervisualizer.view.*&amp;quot; &lt;br /&gt;    xmlns:controller=&amp;quot;nl.foldervisualizer.controller.*&amp;quot;&lt;br /&gt;    xmlns:model=&amp;quot;nl.foldervisualizer.model.*&amp;quot;&lt;br /&gt;    creationComplete=&amp;quot;handleCreationComplete()&amp;quot;&amp;gt;&lt;br /&gt;    &lt;br /&gt;    ... Some code omitted&lt;br /&gt;            &lt;br /&gt;    &amp;lt;!-- Controllers used in the application, could also use dependency injection here (for example Prana) --&amp;gt;            &lt;br /&gt;    &amp;lt;controller:AppController id=&amp;quot;appController&amp;quot; model=&amp;quot;{model}&amp;quot;/&amp;gt;&lt;br /&gt;    &amp;lt;controller:NavigationController id=&amp;quot;navController&amp;quot; model=&amp;quot;{model}&amp;quot;/&amp;gt;&lt;br /&gt;    &lt;br /&gt;    &amp;lt;view:ControlBar width=&amp;quot;100&amp;quot; height=&amp;quot;100%&amp;quot; uiEvent=&amp;quot;appController.handleUIEvent(event);&amp;quot;/&amp;gt;&lt;br /&gt;        &lt;br /&gt;    &amp;lt;mx:VBox width=&amp;quot;100%&amp;quot; height=&amp;quot;100%&amp;quot; verticalGap=&amp;quot;0&amp;quot;&amp;gt;        &lt;br /&gt;        &amp;lt;view:NavigationControlBar height=&amp;quot;35&amp;quot; width=&amp;quot;100%&amp;quot; verticalAlign=&amp;quot;middle&amp;quot; horizontalAlign=&amp;quot;left&amp;quot; horizontalGap=&amp;quot;0&amp;quot; model=&amp;quot;{model}&amp;quot; uiEvent=&amp;quot;navController.handleUIEvent(event);&amp;quot;/&amp;gt;&lt;br /&gt;        ... Some code omitted&lt;br /&gt;    &amp;lt;/mx:VBox&amp;gt;&lt;br /&gt;&amp;lt;/mx:HBox&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;As you can see in the above code, the navController.handleUIEvent method handles all UIEvents dispatched from the NavigationControlBar. One way to handle the events in the handleUIEvent method is the use of a switch statement. For every UIEventKind which the controller must handle, a separate case in the switch statement is used which calls the correct method. Consider the following example:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;public function handleUIEvent(event:UIEvent) : void {&lt;br /&gt;    switch (event.kind) {&lt;br /&gt;        case UIEventKind.BACK:&lt;br /&gt;            // handle event&lt;br /&gt;        break;&lt;br /&gt;        case UIEvent.SHUTDOWN:&lt;br /&gt;            // Handle event&lt;br /&gt;        break;&lt;br /&gt;        default:&lt;br /&gt;            trace(&amp;quot;No event handler defined&amp;quot;)&lt;br /&gt;    }&lt;br /&gt;} &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;What I don't like about this implementation is the excessive amount of switch-case code to handle the events. For every controller in your application which must handle UIEvents, a switch block must be implemented. Instead of using a switch block, I used a different approach for handling UIEvents in controllers. I implemented a MultiActionController which acts as a base class of all controllers which must be able to handle UIEvents. The following code snippet comes from the MultiActionController (some code omitted):&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;public class MultiActionController extends BaseController&lt;br /&gt;{&lt;br /&gt;        /**&lt;br /&gt;        * Mappings between UIEvent.kind (see UIEventKind) to functions. Those functions are defined in&lt;br /&gt;         * the subclass.&lt;br /&gt;        */&lt;br /&gt;        protected var _handlerMappings:HashMap = new HashMap();&lt;br /&gt;        &lt;br /&gt;        public function MultiActionController()&lt;br /&gt;        {&lt;br /&gt;                super();&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        public function handleUIEvent(event:UIEvent) : void {&lt;br /&gt;                var funct:Function = _handlerMappings.getValue(event.kind)&lt;br /&gt;                if (funct==null) {&lt;br /&gt;                        trace(&amp;quot;No function for [&amp;quot; + event.kind + &amp;quot;] is defined in the handlerMappings. Make sure you define this event to function mapping in the constructor of you base class. See the ASDocs of the MultiActionController.&amp;quot;)&lt;br /&gt;                        throw new IllegalOperationError(&amp;quot;No function for [&amp;quot; + event.kind + &amp;quot;] is defined in the handlerMappings. Make sure you define this event to function mapping in the constructor of you base class. See the ASDocs of the MultiActionController.&amp;quot;)&lt;br /&gt;                }&lt;br /&gt;                funct.call(this, event)&lt;br /&gt;                event.stopPropagation()&lt;br /&gt;        }               &lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;The MultiActionController defines a _handlerMapping variable of type HashMap. This hashmap contains the mapping between UIEventKind and functions (functions are objects in ActionScript 3). When the handleUIEvent is called, this method looks up the function belonging to the UIEvent.kind property. If this function exists, it is called passing the UIEvent as a parameter and stops propagation for this event. Otherwise an IllegalOperationError is thrown. Now take a look at the NavigationController which extends MultiActionController:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;{&lt;br /&gt;    public class NavigationController extends MultiActionController&lt;br /&gt;    {&lt;br /&gt;            private var _model:Model;&lt;br /&gt;    &lt;br /&gt;            public function set model(model:Model):void {&lt;br /&gt;                    _model = model&lt;br /&gt;            }&lt;br /&gt;            &lt;br /&gt;            public function NavigationController()&lt;br /&gt;            {&lt;br /&gt;                    super();&lt;br /&gt;                    super._handlerMappings.put(UIEventKind.BACK, this.handleBack)&lt;br /&gt;                    super._handlerMappings.put(UIEventKind.DIRECT_LINK, this.handleDirect)&lt;br /&gt;                    super._handlerMappings.put(UIEventKind.DENSITY_CHANGE, this.handleDensityChanged)&lt;br /&gt;                    super._handlerMappings.put(UIEventKind.DRILLDOWN, this.handleDrilldown)&lt;br /&gt;            }&lt;br /&gt;            &lt;br /&gt;            private function handleBack(event:UIEvent):void {&lt;br /&gt;                    ... Do actual work here&lt;br /&gt;            }      &lt;br /&gt;            &lt;br /&gt;           ... Some code omitted &lt;br /&gt;                           &lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;The constructor of the NavigationController defines the mappings between the UIEvents this controller handles, and the corresponding functions to call. As you can see, there is no need to write blocks of switch statements in every controller to handle UIEvents. Just define the mapping between the UIEvents and functions in the constructor of the corresponding controller. One thing to be aware of is that all functions that are called by the MultiActionController accept a single argument of type UIEvent. This should not be a problem because the only way to call these functions is by dispatching a UIEvent. The UIEvent.payload property should contain all data required for the function to do its work.&lt;br /&gt;&lt;br /&gt;Note that this is NOT a framework but an implementation variant of the MVCS principle for handling UIEvents. Feel free to use this code in your own project.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Structuring and organizaing a Flex (and any other!) application gives you the following benefits:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;easier to maintain the application&lt;/li&gt;&lt;br /&gt;&lt;li&gt;easier to extend the application with new funcitonality&lt;/li&gt;&lt;br /&gt;&lt;li&gt;easier to test the application&lt;/li&gt;&lt;br /&gt;&lt;li&gt;easier to understand the application for new team members&lt;/li&gt;&lt;br /&gt;&lt;li&gt;...&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;Implementing the principles of the MVCS approach is an effective way of organizing and structuring Flex applications. The principles of MVCS are not restricted to a particular implementation. Instead, they can be implemented in various ways that best suites the needs of your application. In this post, I showed you a variation of handling UIEvents which reduces the amount of code necessary to handle these events. When you work on moderate to large Flex applications, have a look at the MVCS guidelines to structure the application. The time you invest does get pay back. The complete source code of the FolderVisualizer application can be found &lt;a href="http://code.google.com/p/folder-visualizer/"&gt;here.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;One final note: although I did not use a DI framework, for example Prana, using a DI framework can be an effective way to decrease the coupling between components and increase testability. At the moment, my DI framework of choice for Flex applications is Prana.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Resources&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/folder-visualizer/"&gt;Folder Visualizer&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.adobe.com/devnet/flex/articles/blueprint.html"&gt;MVCS&lt;/a&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/flex2treemap/"&gt;Tree map component&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-3098013398592852356?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/3098013398592852356/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=3098013398592852356' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/3098013398592852356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/3098013398592852356'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2009/01/i-finally-found-time-to-finish-my.html' title=''/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_oGu2ZdqTixM/SYDDyoQDxWI/AAAAAAAABVc/nKkJTEZ9gpI/s72-c/visualizer.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-424166519200894569</id><published>2009-01-20T15:48:00.003+01:00</published><updated>2009-01-20T15:55:28.087+01:00</updated><title type='text'>text-image-generator example</title><content type='html'>As a follow-up on my previous post, here is an example of how to use the text-image generation library. Consider the following code:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;        TextImage   testImage = new TextImageImpl(400, 250, new Margin(0, -5));&lt;br /&gt;    &lt;br /&gt;        // Declare or read the fonts you need&lt;br /&gt;        Font header = new Font(&amp;quot;Sans-Serif&amp;quot;, Font.BOLD, 15);&lt;br /&gt;        Font plain = new Font(&amp;quot;Sans-Serif&amp;quot;, Font.PLAIN, 12);&lt;br /&gt;        &lt;br /&gt;        // Read in any images you need&lt;br /&gt;        InputStream is = Test.class.getResourceAsStream(&amp;quot;/warning.jpg&amp;quot;);&lt;br /&gt;        Image warning = ImageIO.read(is);&lt;br /&gt;        // Put close() in try-finally block with production code! &lt;br /&gt;        is.close();&lt;br /&gt;        &lt;br /&gt;        // 1. specify font and write text with a newline&lt;br /&gt;        testImage.useFont(header).writeLine(&amp;quot;Example usage text-image-generator.&amp;quot;).newLine();&lt;br /&gt;        // 2. enabled the wrapping of text and write text which is automatically wrapped &lt;br /&gt;        testImage.useFont(plain).wrap(true).write(&amp;quot;This is an example of how to use the text-image generation library. With this library you can dynamically generated textbased content as images (png or jpeg). Notice how this sentence is automatically wrapped. See the code at http://code.google.com/p/textimagegenerator/ for more examples.&amp;quot;).newLine();&lt;br /&gt;        &lt;br /&gt;        // 3. Disable text-wrapping again. Write underlined text.&lt;br /&gt;        testImage.wrap(false).useColor(Color.BLUE).useFontStyle(Style.UNDERLINED).write(&amp;quot;This line of text is underlinedand blue.&amp;quot;).useFontStyle(Style.PLAIN).newLine();&lt;br /&gt;        testImage.writeLine(&amp;quot;You can also embed images in your generated image:&amp;quot;);&lt;br /&gt;        // 4. embed the actual image. Here we use absolute positioning&lt;br /&gt;        testImage.write(warning, 175, 175);&lt;br /&gt;        &lt;br /&gt;        // 5. Write the image as a png to a file&lt;br /&gt;        OutputStream os = new FileOutputStream(new File(&amp;quot;example.png&amp;quot;));&lt;br /&gt;        testImage.createPng(os);&lt;br /&gt;        os.close();&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The code above generates the following image:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_oGu2ZdqTixM/SXXlBz_ByPI/AAAAAAAABU8/MM50iwX76lI/s1600-h/example.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 200px;" src="http://4.bp.blogspot.com/_oGu2ZdqTixM/SXXlBz_ByPI/AAAAAAAABU8/MM50iwX76lI/s320/example.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5293388756341082354" /&gt;&lt;/a&gt;&lt;br /&gt;The text-image generation code can be downloaded at &lt;a href="http://code.google.com/p/textimagegenerator/"&gt;http://code.google.com/p/textimagegenerator/.&lt;/a&gt; Here you will find more examples of how to use this library. Hope you enjoy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-424166519200894569?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/424166519200894569/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=424166519200894569' title='17 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/424166519200894569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/424166519200894569'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2009/01/text-image-generator-example.html' title='text-image-generator example'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_oGu2ZdqTixM/SXXlBz_ByPI/AAAAAAAABU8/MM50iwX76lI/s72-c/example.png' height='72' width='72'/><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-3545742687138825853</id><published>2009-01-13T15:52:00.006+01:00</published><updated>2009-01-14T08:10:34.193+01:00</updated><title type='text'>Creating Dynamic Images with Java and GridGain</title><content type='html'>At my current client we have a requirement to dynamically create images with a specific text, for example an authorization code. These images are created in Java and encoded as a PNG file. For the generation of text based images I created a library which is available on Google Code, see [1]. These images are generated by a servlet of which the URL is embedded in the HTML as an image tag or in a background of a div element.&lt;br /&gt;&lt;br /&gt;During performance tests I saw that the generation of images is a very CPU intensive task. Because there are a lot of users who request a dynamically generated image, this functionality can cripple the CPU's which has a negative impact on the throughput and the stability of the system. Because this is a specific, CPU intensive task, it is a perfect candidate to off-load this process to another machine so the CPU intensive task is distributed over a number of machines.&lt;br /&gt;&lt;br /&gt;One way to distribute the processing of CPU intensive tasks is to use the open source grid computing platform GridGain. GridGain is "an open source computational grid framework that enables Java developers to improve general performance of processing intensive applications by splitting and parallelizing the workload." See also [3]. Image generation is a perfect candidate to distribute with GridGain.&lt;br /&gt;&lt;br /&gt;I have created the following setup to do some first tests with GridGain in this specific scenario:&lt;br /&gt;&lt;ol style="line-height:1.2em;"&gt;&lt;br /&gt;&lt;li style="padding: 0px;border: 0px;"&gt;Created a web application with a servlet which is called by clients. This servlet is responsible for executing the image generation task on the grid and streaming the result back to the client as a PNG.&lt;/li&gt;&lt;br /&gt;&lt;li style="padding: 0px;border: 0px;"&gt;Created a GridGain task which creates a job which is responsible for the actual image generation. This job can be executed on any of the nodes participating in the grid.&lt;/li&gt;&lt;br /&gt;&lt;li style="padding: 0px;border: 0px;"&gt;Used two physical nodes in my first setup, node 1: PentiumM 2 GHz with 2 GB's RAM, node 2: Pentium4 2.2 GHz with 1 GB RAM.&lt;/li&gt;&lt;br /&gt;&lt;li style="padding: 0px;border: 0px;"&gt;Used Apache JMeter to create a load test [4].&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;See the following diagram for an overview of my setup:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_oGu2ZdqTixM/SWyr2G2dXpI/AAAAAAAABUs/KqOQzHQyPgY/s1600-h/gridgaintest.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 138px;" src="http://4.bp.blogspot.com/_oGu2ZdqTixM/SWyr2G2dXpI/AAAAAAAABUs/KqOQzHQyPgY/s320/gridgaintest.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5290792608293805714" /&gt;&lt;/a&gt;&lt;br /&gt;I used 5 concurrent threads (users) in my JMeter script with a ramp-up time of 0ms which means all 5 users are active at once.&lt;br /&gt;&lt;ol style="line-height:1.2em;"&gt;&lt;br /&gt;&lt;li style="padding: 0px;border: 0px;"&gt;My first test run was used to create a baseline. This version did not use the grid at all and the image generation logic was implemented directly in the servlet. This test was run on node 1. With a couple of tests there was an average of 6.7 transactions per second.&lt;/li&gt;&lt;br /&gt;&lt;li style="padding: 0px;border: 0px;"&gt;My second test was used to determine the overhead of the grid. I expect the throughput to be a little less than in my first test. The same node was used as in 1. With a couple of tests there was an average of 6.5 transactions per second. Almost as good as without the grid. In this specific scenario the overhead of the grid is negligible. However, this can vary based on your specific situation.&lt;/li&gt;&lt;br /&gt;&lt;li style="padding: 0px;border: 0px;"&gt;In my third test I added a second node, node 2, to the grid. With a couple of tests there was an average of 9.5 transactions per second. This is a throughput increase of 46%. Pretty impressive. In my test, both nodes had 100% CPU utilization.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;This is really impressive considering the amount of work I had to install and configure GridGain, almost nothing. With the default configuration, GridGain uses IP multi-cast to discover all the grid nodes. I just had to start gridGain on the second node and this node automatically participated in the grid. Other strategies can be used to implement the discovery process, for example JMS topics. When a given task is executed for the first time on a given node, the grid takes care of deploying this task on that specific node. No need for manual deployment of tasks. Failover and load balancing of tasks to other nodes when a node has crashed is enabled by default. Everything is also well documented which really helps creating a consistent package.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;Distributing CPU intensive tasks across several physical machines is an effective way to increase the throughput and reducing the risk that this process will become a bottleneck or has a negative impact on the stability of the system as a whole. GridGain is a platform which enables (Java) developers to create a computing grid and execute tasks on this grid. When you have computational intensive tasks in your application, make sure you check out GridGain.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Resources&lt;/b&gt;&lt;br /&gt;[1] &lt;a href="http://code.google.com/p/textimagegenerator/"&gt;Image Text library&lt;/a&gt;&lt;br /&gt;[2] &lt;a href="www.gridgain.com"&gt;GridGain&lt;/a&gt;&lt;br /&gt;[3] &lt;a href="http://highscalability.com/gridgain-one-compute-grid-many-data-grids"&gt;Highscalability.com&lt;/a&gt;&lt;br /&gt;[4] &lt;a href="http://jakarta.apache.org/jmeter/"&gt;JMeter&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-3545742687138825853?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/3545742687138825853/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=3545742687138825853' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/3545742687138825853'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/3545742687138825853'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2009/01/creating-dynamic-images-with-java-and.html' title='Creating Dynamic Images with Java and GridGain'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_oGu2ZdqTixM/SWyr2G2dXpI/AAAAAAAABUs/KqOQzHQyPgY/s72-c/gridgaintest.JPG' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-9182526996702829174</id><published>2008-10-02T09:00:00.009+02:00</published><updated>2008-10-03T12:42:44.617+02:00</updated><title type='text'>Radrace impressions</title><content type='html'>On the 26th and 27th of September our company (QNH Application Development &amp; Solutions) held the second internal Rapid Application Development race. There were 15 teams each consisting of 2 people competing against each other. As you already have read, a variety of technologies were used. The technology of our choice was Grails and the IDE we used was IntelliJ. Here are my impressions.&lt;br /&gt;&lt;br /&gt;25th of September&lt;br /&gt;23:30: The final preparations for the game tomorrow were made. I double checked the setup on my laptop, from Subversion to IntelliJ and all possible documentation we might need. I also did a final check on our pre-build application to see if everything still worked as expected.&lt;br /&gt;&lt;br /&gt;26th of September, the first day&lt;br /&gt;09:00: There was a briefing of the application that had to be build. The application was about the registration of driver licences which contain points. Points are subtracted when a driver makes an offence, like speeding or drinking while driving. Points are added when the driver shows good behaviour like taking a practical exam.&lt;br /&gt;The functionality that was needed consisted of the following:&lt;br /&gt;&lt;ul style="line-height:1.2em;"&gt;&lt;br /&gt;&lt;li&gt;Login functionality for John Europe. John Europe must be able to see his driver licences and for each driver license the details. Details consist of his points left and the offences he made. He could also go into appeal for some of the offences. When a civilian goes into appeal, an amount of 100 Euro should be paid. A payment module with credit card check should be build.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Login functionality for the judge which treat appeals and determine if an appeal is valid or not. An e-mail is sent to the applicant of the appeal to inform him/her about the decision of the judge.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Login functionality for police officers which see an overview of all civilians which should have returned his/her driver license to the police.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Login functionality for insurance companies to determine the price of car insurance policies for civilians.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Business rules which state how and when points are subtracted and added to the points on a driver license.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Make use of the existing database which is a Microsoft access database. The number of records in this database was close to 40.000 and consisted of multiple tables with relationships between those tables.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A couple of reports which display the civilians who needed to take practical exams and eye tests.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;10:00: Let the games begin! We used the first 15 minutes to determine our strategy and made sure that we understood the functionality. After that we started working. I used the Mysql migration wizard to migrate the Access database to Mysql. We created a separate database for the original data and a new database for the application. Paul started working on the domain model and database and I started working on the authentication/authorization functionality. Whenever Paul had created a domain object and migrated the corresponding data, I started working on the controller and view for that functionality.&lt;br /&gt;&lt;br /&gt;12:00: Lunch. We already had the login functionality, the eye test report and the data model for the rules working. For the report functionality we used straight sql with Spring’s JDBC template. There was not anything that had yet gone wrong.&lt;br /&gt;&lt;br /&gt;13:00: We started coding again. I began working on the driver license information and the functionality for the judge and Paul continued to migrate the data. I used some Ajax to display the driver license details. We made sure we used the unique ids from the original data to maintain the relationships. Groovy scripts were used to migrate the data.&lt;br /&gt;&lt;br /&gt;19:00: We completed the functionality for John Europe and the Judge. Both reports were finished. There were some improvements left to be made which we did the next day. We decided not to do anything with the rules yet because there were no real deliverables regarding those rules. Our expectation was that the changes, which were issued the next day, were regarding those rules.&lt;br /&gt;&lt;br /&gt;20:00: We had a nice dinner with all of teams in a restaurant a talked a lot about this day. We tried to figure out what the rest of the teams were doing to measure our competition.&lt;br /&gt;&lt;br /&gt;27th of September, the second day&lt;br /&gt;08:00: We started with the optimizations of the use cases we finished the day before and made sure all functionality was working correctly. A total of three changes were issued. One of the changes was implementing the rules regarding speeding and parking in restricted areas. The rules were developed by me and Paul concentrated on completing the judge and police functionality. Some changes to the css were made to make the application a little more attractive than it already did.&lt;br /&gt;&lt;br /&gt;11:45: We made sure everything was checked in and did a final test to make sure everything worked as expected.&lt;br /&gt;&lt;br /&gt;12:00: Development time is over. We were pretty confident that we completed a lot of the functionality and scored a lot of points. However, we were not exactly sure if this would be enough to win the first prize. The jury began examining each application. Because of the huge amount of teams, the jury was divided in two so two teams could be judged at the same time to speed up the process.&lt;br /&gt;&lt;br /&gt;15:00: When the first jury round was over, the best three teams had to demonstrate their application for the grand jury. We were one of the three best teams! We passed the test script and almost all of the functionality worked as expected.&lt;br /&gt;&lt;br /&gt;16:00: Finally the awards. There were a couple of awards like the “best dressed award” which we did not win:). We already knew we were among the best three teams. When we heard we had not won the third prize we fell relieved. We could only be number one or two. The tension raised and eventually we heard that we came out first out of the total of 15 teams and both won a brand new Xbox 360 Elite console! All the preparations weren’t for nothing.&lt;br /&gt;&lt;br /&gt;17:00: It was a great day and had a lot of fun with everybody. Till next year!&lt;br /&gt;&lt;br /&gt;To see a video impression of the rad race check &lt;a target="_blank" href="http://nl.youtube.com/watch?v=jrVaBR0qpjo"&gt;You Tube&lt;/a&gt;&lt;br /&gt;Paul Bakker also wrote an impression which you can find &lt;a target="_blank" href="http://blogs.infosupport.com/blogs/paul_bakker/default.aspx"&gt;here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-9182526996702829174?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/9182526996702829174/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=9182526996702829174' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/9182526996702829174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/9182526996702829174'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2008/10/radrace-impressions.html' title='Radrace impressions'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-1962068889255263173</id><published>2008-09-23T19:47:00.003+02:00</published><updated>2008-10-02T08:06:33.147+02:00</updated><title type='text'>Our first Open Space session</title><content type='html'>Our first Open Space session was held on the 15th of September 2008. As you may have read, our internal RAD race is on the 26th and 27th of September. One of the open space subjects was how you can prepare yourself for the RAD race. This was the outcome:&lt;br /&gt;&lt;ul style="line-height:0.5em;"&gt;&lt;br /&gt;&lt;li&gt;Preparation is the most important thing&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Database setup&lt;/li&gt;&lt;br /&gt;&lt;li&gt;E-mail client/server&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Styling&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Authentication/Authorization module&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Print module&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Payment module&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Code generation&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Books, pdf’s&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Source Control System&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Networking equipment&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Working hardware&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Report generator&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;As you can see there is a lot you can do to prepare yourself for the RAD race. What is your opinion about the preparation for a Rapid Application Development race?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-1962068889255263173?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/1962068889255263173/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=1962068889255263173' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/1962068889255263173'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/1962068889255263173'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2008/09/our-first-open-space-session-was-held.html' title='Our first Open Space session'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-6687934498303089307</id><published>2008-09-12T09:19:00.003+02:00</published><updated>2008-09-24T07:47:09.637+02:00</updated><title type='text'>Internal QNH Rad Race 2008</title><content type='html'>26th and 27th of September, our company organizes the second internal Rad (Rapid Application Development) race. A Rad race is a competition in which several teams compete against each other to build an application in 1.5 days. The team which completes the most functionality wins. The teams consist of two people which work together and are responsible for creating their own development environment including version control, choice of IDE etc. They also choose their own technology to build the application in. It is your own responsibility to choose a technology you are familiar with. The technology we use to build the application is Grails and IntelliJ as our IDE. We find the Grails framework (and Groovy) very productive and a pleasure to work with (which is partly due to IntelliJ, one of the best IDE’s I have worked with).&lt;br /&gt;&lt;br /&gt;The competition is tough though. There are 12 other teams which use the following technology:&lt;br /&gt;&lt;ul style="line-height:0.5em;"&gt;&lt;br /&gt;&lt;li&gt;PHP / Ruby on Rails&lt;/li&gt;&lt;br /&gt;&lt;li&gt;.NET&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Oracle / APEX&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Flex, Spring&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Spring MVC&lt;/li&gt;&lt;br /&gt;&lt;li&gt;GWT, Spring and Hibernate&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Wicket, Spring and Hibernate&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Although several factors come into play which determine who is the winner, it is nice to see the pros and cons of each technology during the competition.&lt;br /&gt;&lt;br /&gt;We will keep you updated!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-6687934498303089307?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/6687934498303089307/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=6687934498303089307' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/6687934498303089307'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/6687934498303089307'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2008/09/internal-qnh-rad-race-2008.html' title='Internal QNH Rad Race 2008'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-213008424603381338</id><published>2008-07-28T09:20:00.002+02:00</published><updated>2008-07-28T09:22:42.321+02:00</updated><title type='text'>Support for image acquisition devices in Flex/Air</title><content type='html'>I would like to see support for image acquisition devices in Flex/Air. Currently there is no such support for image acquisition devices, like scanners that operate via the TWAIN API. However you can use sockets in combination with a Java application but this is far from an ideal scenario.&lt;br /&gt;&lt;br /&gt;I filed an issue request which you can see at &lt;a target="_blank" href="https://bugs.adobe.com/jira/browse/SDK-16239"&gt;https://bugs.adobe.com/jira/browse/SDK-16239&lt;/a&gt;. Please vote on this issue and we may see support for image acquisition devices in the future.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-213008424603381338?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/213008424603381338/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=213008424603381338' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/213008424603381338'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/213008424603381338'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2008/07/support-for-image-acquisition-devices.html' title='Support for image acquisition devices in Flex/Air'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-7943388986697121696</id><published>2008-07-18T08:05:00.004+02:00</published><updated>2008-09-24T07:47:25.591+02:00</updated><title type='text'>Open Space sessions</title><content type='html'>Upcoming august 2008 me and a colleague organize the first internal Open Space session for our company. Although the concept is not new, Open Space sessions date back from 1985, they gained momentum at Java Polis 2007. Here, Bruce Eckel held an excellent presentation about Open Space sessions.&lt;br /&gt;&lt;br /&gt;I think knowledge and/or experience sharing is a key point in our profession as a software developer/engineer/architect etc. We constantly seek new and effective methods to share our knowledge. The most effective method for sharing knowledge is the one with the best cost/benefit tradeoffs. Costs have the form of the amount of time invested to prepare a session and the benefit is the amount of knowledge and experience shared amongst other colleagues.&lt;br /&gt;&lt;br /&gt;The cost/benefit ratio of a traditional session/presentation is not very high. Usually, the preparation of a session costs far more than the benefit it gets. When this session is held multiple times, the cost/benefit ratio gets better. The format of a traditional session is of a very static nature. You have one or more presenters and a whole lot of attendees. The attendees do not know if the session is of any value for them. For some this may be the case and for others this may be not. Also, the attendees usually are not in the position to determine the subjects of the session.&lt;br /&gt;&lt;br /&gt;Open Space sessions try to address these shortcomings. In an Open Space session the subject is determined by the attendees. The attendees seek a space where they can discuss/contribute and learn about the subject. One thing to remember in an open space session is the 'Law of the two feet'. This means: if you feel you do not learn anything or cannot contribute something meaningful to the session, use your two feet and seek another session which may interest you. This way you and the other attendees get the most value from a session.&lt;br /&gt;&lt;br /&gt;I will post our experiences and the way we organize our Open Space session in the next month. Stay tuned...&lt;br /&gt;&lt;br /&gt;More information about Open Space sessions can be found at:&lt;br /&gt;&lt;ul style="line-height:0.5em;"&gt;&lt;br /&gt;&lt;li&gt;&lt;a target="_blank" href="http://www.openspaceworld.com/users_guide.htm"&gt;Open Space world&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a target="_blank" href="http://en.wikipedia.org/wiki/Open_Space_Technology"/&gt;Wikipedia&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-7943388986697121696?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/7943388986697121696/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=7943388986697121696' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/7943388986697121696'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/7943388986697121696'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2008/07/open-space-sessions.html' title='Open Space sessions'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-186138095568798478</id><published>2008-06-30T12:55:00.002+02:00</published><updated>2008-06-30T12:57:45.878+02:00</updated><title type='text'>JavaFX and Air: a brief comparison</title><content type='html'>&lt;a target="_blank" href="http://blogs.infosupport.com/blogs/paul_bakker/default.aspx"&gt;Paul Bakker&lt;/a&gt; has wrote an excellent post of our first impressions when developing the FolderVisualizer. Check it out and also don't forget to install and try both applications!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-186138095568798478?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/186138095568798478/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=186138095568798478' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/186138095568798478'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/186138095568798478'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2008/06/javafx-and-air-brief-comparison.html' title='JavaFX and Air: a brief comparison'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-2662443554628846310</id><published>2008-06-10T21:51:00.003+02:00</published><updated>2008-09-24T07:47:41.377+02:00</updated><title type='text'>Efficiently reclaim you disk space</title><content type='html'>We started a new project on Google code named FolderVisualizer.&lt;br /&gt;&lt;br /&gt;The application is able to visualize the relative size of files and folders below a given directory. With this tool it is easy to see which files and folders take up the most disk space which you then can use to efficiently clean your hard drive. See Olav Maassen's &lt;a href="http://agilejava.blogspot.com/2008/04/chopping-trees-efficiency-vs.html"&gt;post&lt;/a&gt; about efficiency :).&lt;br /&gt;&lt;br /&gt;Although such tool already exists, it is fun to see how different implementations compare to each other. At the moment, the following technologies are planned:&lt;br /&gt;&lt;ul style="line-height:0.5em;"&gt;&lt;br /&gt;&lt;li&gt;A Groovy implementation with a command line client&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A Java implementation with a command line client&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A JavaFX client&lt;/li&gt;&lt;br /&gt;&lt;li&gt;An Adobe AIR client&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;It is nice to see that the JavaFX client can make use of the Groovy implementation of the visualizer algorithm. For the AIR implementation we have to rewrite the algorithm in Action Script.&lt;br /&gt;&lt;br /&gt;The project can be found &lt;a href="http://code.google.com/p/folder-visualizer/"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-2662443554628846310?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/2662443554628846310/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=2662443554628846310' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/2662443554628846310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/2662443554628846310'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2008/06/efficiently-reclaim-you-disk-space.html' title='Efficiently reclaim you disk space'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-369625945659109188</id><published>2008-06-09T09:57:00.000+02:00</published><updated>2008-06-09T09:58:18.783+02:00</updated><title type='text'>Once again: Assumptions are the mother of all fuck ups!</title><content type='html'>Even the most obvious assumptions aren't all that obvious. Who believes that a software tester tests a new release in the production environment! This has actually happened. When a new release was installed in the acceptance environment, the acceptance tester was signalled.&lt;br /&gt;&lt;br /&gt;When he finished testing, a whole list of issues was reported via the issues tracker. We had absolutely no idea of what was going on until we asked for the URL and user accounts with which the tester had tested. The URL that was used was actually the URL of the production environment! After that it was totally clear to us what went wrong.&lt;br /&gt;&lt;br /&gt;Lesson learned: even if your assumption is obvious, do not assume!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-369625945659109188?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/369625945659109188/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=369625945659109188' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/369625945659109188'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/369625945659109188'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2008/06/once-again-assumptions-are-mother-of.html' title='Once again: Assumptions are the mother of all fuck ups!'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-7883487271052013966</id><published>2007-07-04T08:22:00.002+02:00</published><updated>2008-06-30T13:01:00.600+02:00</updated><title type='text'>Code review</title><content type='html'>During a code review I stumbled accross the following code:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;SomeObject someObject; &lt;br /&gt;if(o instanceof SomeObject) {&lt;br /&gt; someObject = (SomeObject)o;&lt;br /&gt;} else {&lt;br /&gt; throw new ClassCastException(&amp;quot;Cannot cast=[&amp;quot; + o.getClass() + &amp;quot;] to expected class=[&amp;quot;+ SomeObject.class + &amp;quot;]&amp;quot;);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Obviously the throwing of the ClassCastException is redundant. You can replace the above code with the following statement:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;SomeObject someObject = (SomeObject)o; &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This statement doas semantically the exact same thing! At runtime a ClassCastException is thrown when object o cannot be cast to SomeObject. By looking at the stacktrace you can figure out where in your code things go wrong.&lt;br /&gt;&lt;br /&gt;Moral of this story: use code reviews to improve the quality of your code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-7883487271052013966?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/7883487271052013966/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=7883487271052013966' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/7883487271052013966'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/7883487271052013966'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2007/07/code-review.html' title='Code review'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-273004831808981628</id><published>2007-06-27T14:58:00.001+02:00</published><updated>2008-06-27T09:11:24.582+02:00</updated><title type='text'>Using Spring elements and attributes in your custom namespace</title><content type='html'>With Spring 2 it is possible to define your own namespace and have your own custom elements which you can use in the application context. Sometimes, allthough I do not promote this, you want to use Spring elements and attributes on your custom elements. For example: suppose I have a custom element named "foo:myCustomFooElement" with one attribute named "text". By default, you can't write something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;lt; foo:mycustomfooelement text=&amp;quot;test&amp;quot; abstract=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;   &amp;lt; property name=&amp;quot;property&amp;quot; value=&amp;quot;value&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt; /foo:myCustomFooElement&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This is because the property element and abstract attribute are not defined in your xsd which describes your custom element. Following is the source of a sample application I wrote to demonstrate the use of Spring properties and attributes on custom elements. The reason I do not promote this, is because you will loose the encapsulation of implementation details which your custom element hides. So use it with care.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;public class Foo {&lt;br /&gt;    // This property gets injected by our custom FooParser&lt;br /&gt;    private String text;&lt;br /&gt;&lt;br /&gt;    // This property gets set by using Spring's &amp;lt; property&amp;gt; element&lt;br /&gt;    private Bar bar;&lt;br /&gt;&lt;br /&gt;    // getters and setters omitted&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We will write a custom element for the Foo class.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;public class Bar {&lt;br /&gt;    private int count;&lt;br /&gt;&lt;br /&gt;        // getter and setters omitted&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Bar is just a regular class that gets injected in Foo. Below is the xsd I wrote to define myCustomFooElement:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;lt; ?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt; xsd:schema xmlns=&amp;quot;http://www.mynamespace.com/foo&amp;quot;&lt;br /&gt;    xmlns:xsd=&amp;quot;http://www.w3.org/2001/XMLSchema&amp;quot;&lt;br /&gt;    xmlns:beans=&amp;quot;http://www.springframework.org/schema/beans&amp;quot;&lt;br /&gt;    targetNamespace=&amp;quot;http://www.mynamespace.com/foo&amp;quot;&lt;br /&gt;    elementFormDefault=&amp;quot;qualified&amp;quot; attributeFormDefault=&amp;quot;unqualified&amp;quot;&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt; xsd:import&lt;br /&gt;        schemaLocation=&amp;quot;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd&amp;quot;&lt;br /&gt;        namespace=&amp;quot;http://www.springframework.org/schema/beans&amp;quot; /&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt; xsd:element name=&amp;quot;myCustomFooElement&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt; xsd:complextype&amp;gt;&lt;br /&gt;            &amp;lt; xsd:complexcontent&amp;gt;&lt;br /&gt;                &amp;lt; xsd:extension base=&amp;quot;beans:identifiedType&amp;quot;&amp;gt;&lt;br /&gt;                    &amp;lt;!-- Here we re-use Spring elements and attributes --&amp;gt;&lt;br /&gt;                    &amp;lt; xsd:group ref=&amp;quot;beans:beanElements&amp;quot;&amp;gt;&lt;br /&gt;                    &amp;lt; xsd:attributegroup ref=&amp;quot;beans:beanAttributes&amp;quot;&amp;gt;&lt;br /&gt;                    &amp;lt; xsd:attribute name=&amp;quot;text&amp;quot; type=&amp;quot;xsd:string&amp;quot;&lt;br /&gt;                        use=&amp;quot;required&amp;quot; /&amp;gt;&lt;br /&gt;                &amp;lt; /xsd:extension&amp;gt;&lt;br /&gt;            &amp;lt; /xsd:complexContent&amp;gt;&lt;br /&gt;        &amp;lt; /xsd:complexType&amp;gt;&lt;br /&gt;    &amp;lt; /xsd:element&amp;gt;&lt;br /&gt;&amp;lt; /xsd:schema&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The XML file containing the bean definitions looks like this:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;lt; beans xmlns=&amp;quot;http://www.springframework.org/schema/beans&amp;quot;&lt;br /&gt;    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;    xmlns:foo=&amp;quot;http://www.mynamespace.com/foo&amp;quot;&lt;br /&gt;    xsi:schemaLocation=&amp;quot;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd&lt;br /&gt;    http://www.mynamespace.com/foo http://www.mynamespace.com/foo/foo.xsd&amp;quot;&amp;gt;&lt;br /&gt;   &lt;br /&gt;    &amp;lt; foo:mycustomfooelement id=&amp;quot;foo&amp;quot; text=&amp;quot;test&amp;quot; init=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;!-- Here we use a Spring property element inside our custom element --&amp;gt;&lt;br /&gt;        &amp;lt; property name=&amp;quot;bar&amp;quot;&amp;gt;&lt;br /&gt;            &amp;lt; bean class=&amp;quot;nl.sample.customnamespace.Bar&amp;quot;&amp;gt;&lt;br /&gt;                &amp;lt; property name=&amp;quot;count&amp;quot; value=&amp;quot;100&amp;quot;&amp;gt;&lt;br /&gt;            &amp;lt; /bean&amp;gt;&lt;br /&gt;        &amp;lt; /property&amp;gt;&lt;br /&gt;    &amp;lt; /foo:myCustomFooElement&amp;gt;&lt;br /&gt;&amp;lt; /beans&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;To parse the myCustomFooElement we must create a namespacehandler and register a beandefinition parser like this:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;public class FooNameSpaceHandler extends NamespaceHandlerSupport {&lt;br /&gt;    private static final String NAME_CUSTOM_FOO_ELEMENT = &amp;quot;myCustomFooElement&amp;quot;;&lt;br /&gt;&lt;br /&gt;    public void init() {&lt;br /&gt;        registerBeanDefinitionParser(NAME_CUSTOM_FOO_ELEMENT, new FooParser());&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    class FooParser extends AbstractBeanDefinitionParser  {&lt;br /&gt;        @Override&lt;br /&gt;        protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {&lt;br /&gt;            // Here we parse the Spring elements such as &amp;lt; property&amp;gt;&lt;br /&gt;            BeanDefinitionHolder holder = parserContext.getDelegate().parseBeanDefinitionElement(element);&lt;br /&gt;            BeanDefinition bd = holder.getBeanDefinition();&lt;br /&gt;            bd.setBeanClassName(Foo.class.getName());&lt;br /&gt;           &lt;br /&gt;            // Here we parse our custom attributes&lt;br /&gt;            String text = element.getAttribute(&amp;quot;text&amp;quot;);&lt;br /&gt;            bd.getPropertyValues().addPropertyValue(&amp;quot;text&amp;quot;, text);&lt;br /&gt;            parserContext.getRegistry().registerBeanDefinition(NAME_CUSTOM_FOO_ELEMENT, bd);&lt;br /&gt;            return (AbstractBeanDefinition) bd;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Don't forget to register the namespacehandler in a file called spring.handlers in the META-INF directory. The contents of de spring.handlers file looks like this:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;http\://www.mynamespace.com/foo=nl.sample.customnamespace.FooNameSpaceHandler&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Also, specify in the META-INF/spring.schemas file where Spring can find the foo.xsd:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;http\://www.mynamespace.com/foo/foo.xsd=nl/sample/customnamespace/foo.xsd&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Write a class to verify everything works:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;public class Driver {&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(&amp;quot;classpath:nl/sample/customnamespace/customelements.xml&amp;quot;);&lt;br /&gt;        Foo foo = (Foo) appContext.getBean(&amp;quot;foo&amp;quot;);&lt;br /&gt;        System.out.println(&amp;quot;foo.text = &amp;quot; + foo.getText());&lt;br /&gt;        System.out.println(&amp;quot;foo.bar.count = &amp;quot; + foo.getBar().getCount());&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Extensive documentation about extensible XML authoring can be found in the reference manual. Eriks Wiersma has also written an excellent piece on his [URL="http://erik.jteam.nl/?p=23"]blog[/URL] about implementing custom namespaces.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-273004831808981628?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/273004831808981628/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=273004831808981628' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/273004831808981628'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/273004831808981628'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2007/06/using-spring-elements-and-attributes-in.html' title='Using Spring elements and attributes in your custom namespace'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-2861468223978863635</id><published>2007-03-06T09:21:00.000+01:00</published><updated>2007-03-06T11:33:15.471+01:00</updated><title type='text'>Comparing two XML documents</title><content type='html'>&lt;span style=";font-family:arial;font-size:100%;"  &gt;&lt;span style=""&gt;When writing unit tests involving XML you often want to compare two XML documents. This can easily be done using a simple String compare as in: &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;    &lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;expectedXML.equals(responseXML);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;Where ‘expectedXML’ is the XML we expect to get back and ‘responseXML’ is the actual XML that is given as a response.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;The problem with this approach is that it not only compares the actual XML but also any unimportant whitespace, tabs etc. This is not the desired behavior because it breaks our test when, for example, whitespaces are added in de reponseXML.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;One solution to this problem is to use a handy utility class named DocumentComparator, which is part of the &lt;a href="http://jibx.sourceforge.net/"&gt;JIBX&lt;/a&gt; distribution. The javadoc of the DocumentComparator says the following:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;blockquote&gt;XML document comparator. This uses XMLPull parsers to read a pair of documents in parallel, comparing the streams of components seen from the two documents. The comparison ignores differences in whitespace separating elements, but treats whitespace as significant within elements with only character data content.&lt;/blockquote&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style=""&gt;&lt;span style="font-size:100%;"&gt;&lt;o:p&gt;&lt;/o:p&gt;This is exactly the functionality we need. With this class we can write the following code to compare two XML documents:&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;                &lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="background: white none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-size:10;color:black;"  &gt;ByteArrayOutputStream&lt;/span&gt;&lt;span style="background: white none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-size:10;" &gt; &lt;span style="color:black;"&gt;out&lt;/span&gt; &lt;span style="color:black;"&gt;=&lt;/span&gt; &lt;b&gt;&lt;span style="color: rgb(127, 0, 85);"&gt;new&lt;/span&gt;&lt;/b&gt; &lt;span style="color:black;"&gt;ByteArrayOutputStream();&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:10;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="background: white none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-size:10;" &gt;&lt;span style=""&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;DocumentComparator&lt;/span&gt; &lt;span style="color:black;"&gt;comp&lt;/span&gt; &lt;span style="color:black;"&gt;=&lt;/span&gt; &lt;b&gt;&lt;span style="color: rgb(127, 0, 85);"&gt;new&lt;/span&gt;&lt;/b&gt; &lt;span style="color:black;"&gt;DocumentComparator(&lt;/span&gt;&lt;b&gt;&lt;span style="color: rgb(127, 0, 85);"&gt;new&lt;/span&gt;&lt;/b&gt; &lt;span style="color:black;"&gt;PrintStream(out));&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:10;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="background: white none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-size:10;" &gt;&lt;span style=""&gt;&lt;/span&gt;&lt;b&gt;&lt;span style="color: rgb(127, 0, 85);"&gt;boolean&lt;/span&gt;&lt;/b&gt; &lt;span style="color:black;"&gt;result&lt;/span&gt; &lt;span style="color:black;"&gt;=&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:10;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="background: white none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-size:10;" &gt;&lt;span style=""&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;comp.compare(&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:10;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="background: white none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-size:10;" &gt;&lt;span style=""&gt;&lt;/span&gt;&lt;b&gt;&lt;span style="color: rgb(127, 0, 85);"&gt;new&lt;/span&gt;&lt;/b&gt; &lt;span style="color:black;"&gt;StringReader(responseXml), &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:10;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="background: white none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-size:10;" &gt;&lt;span style=""&gt;&lt;/span&gt;&lt;b&gt;&lt;span style="color: rgb(127, 0, 85);"&gt;new&lt;/span&gt;&lt;/b&gt; &lt;span style="color:black;"&gt;StringReader(expectedXml));&lt;/span&gt;&lt;/span&gt;&lt;span style=";font-size:10;color:black;"  &gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="background: white none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-size:10;color:black;"  &gt;assertEquals(out.toString(),&lt;/span&gt;&lt;span style="background: white none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-size:10;" &gt; &lt;b&gt;&lt;span style="color: rgb(127, 0, 85);"&gt;true&lt;/span&gt;&lt;/b&gt;&lt;span style="color:black;"&gt;,&lt;/span&gt; &lt;span style="color:black;"&gt;result);&lt;/span&gt;&lt;/span&gt;&lt;span style=";font-size:10;color:black;"  &gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal" style=""&gt;&lt;span style=";font-family:arial;font-size:10;color:black;"   &gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;span style="font-size:100%;"&gt;The DocumentComparator class uses the PrintStream to report any differences found when comparing the two documents.&lt;/span&gt;&lt;/span&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-2861468223978863635?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/2861468223978863635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=2861468223978863635' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/2861468223978863635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/2861468223978863635'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2007/03/comparing-two-xml-documents.html' title='Comparing two XML documents'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-7673837911362216969</id><published>2007-02-26T11:49:00.000+01:00</published><updated>2007-03-06T11:30:43.493+01:00</updated><title type='text'>Core Spring training experience</title><content type='html'>&lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style=""&gt;The training was given by Arjen Poutsma. Arjen works for Interface21 and is the lead developer of the Spring-WS sub project.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;o:p style="font-weight: bold;"&gt;&lt;/o:p&gt;&lt;span style="font-weight: bold;"&gt;Day 1, 20 february 2007&lt;/span&gt;&lt;b style=""&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;          &lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style=""&gt;Day 1 is all about the core concepts of the Spring framework like Inversion of Control and Dependency Injection. IOC and DI are essential parts to understanding Spring's architecture. Besides some basic subjects about IOC and DI there were also advanced concepts that were given attention: autowiring, life cycle callbacks, property editors, factory beans, post processors etc. The Lab's in day 1 were all about configuring application contexts. However there was also a bonus section which programmatically used AOP via ProxyFactory(s) with dynamic TargetSource(s).&lt;o:p&gt;&lt;br /&gt;&lt;/o:p&gt;&lt;br /&gt;If you already know Spring than the subjects in day 1 are familiar.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;Day 2, 21 february 2007&lt;/span&gt;&lt;b style=""&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style=""&gt;Day 2 was all about effective middle tier architecture with Spring. Subjects that got attention were: &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;            &lt;ul&gt;&lt;li  style="font-family:arial;"&gt;&lt;span style=""&gt;Persistence with Spring JDBC and ORM tools&lt;/span&gt;&lt;/li&gt;&lt;li  style="font-family:arial;"&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;Data Access Objects with Spring&lt;/span&gt;&lt;/li&gt;&lt;li  style="font-family:arial;"&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;Brief introduction about transaction management&lt;/span&gt;&lt;/li&gt;&lt;li  style="font-family:arial;"&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;Test Driven Development with Spring&lt;/span&gt;&lt;/li&gt;&lt;li  style="font-family:arial;"&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;Introduction to AOP&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=""&gt;&lt;o:p style="font-family: arial;"&gt;&lt;/o:p&gt;&lt;span style="font-family:arial;"&gt;Advanced data access concepts such as: batch updates, blob handling and stored procedures.&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style=""&gt;The labs were about using Spring in conjunction with Hibernate and using Spring utilities for creating integration tests.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;Day 3, 22 february 2007&lt;/span&gt;&lt;b style=""&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style=""&gt;After a brief introduction about transaction management in day 2, this day continued with the more advanced topics about transaction management. Specifically:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;        &lt;ul  style="font-family:arial;"&gt;&lt;li  style="font-family:arial;"&gt;&lt;span style=""&gt;local versus global transactions&lt;/span&gt;&lt;/li&gt;&lt;li  style="font-family:arial;"&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;declarative versus programmatic&lt;/span&gt;&lt;/li&gt;&lt;li  style="font-family:arial;"&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;transaction propagation&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;isolation levels&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;The rest of the day was about Spring-MVC including several labs covering handler mappings, input forms and interceptors.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style=""&gt;&lt;o:p style="font-family: arial;"&gt;&lt;/o:p&gt;&lt;span style="font-family:arial;"&gt;The last subject for this day was an introduction about Acegi security system for Spring.&lt;/span&gt;&lt;o:p style="font-family: arial;"&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;b style=""&gt;&lt;span style=""&gt;Day 4, 23 february 2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p  class="MsoNormal" style="font-family:arial;"&gt;&lt;span style=""&gt;For me, day 4 was most interesting. This was mainly because AOP got in depth-attention. Arjen focused on Spring 2's support for AOP with Spring and AspectJ. Some advanced concepts such as introductions also got attention.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style=""&gt;&lt;o:p style="font-family: arial;"&gt;&lt;/o:p&gt;&lt;span style="font-family:arial;"&gt;The remainder of the day was used to tell something about Spring's support for JMX and remoting. Arjens's project Spring-WS got little attention. The main point about Spring-WS is that it promotes contract-first development.&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style="font-family:arial;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;b style=""&gt;&lt;span style=""&gt;&lt;span style="font-family:arial;"&gt;Things to remember&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;      &lt;ul&gt;&lt;li  style="font-family:arial;"&gt;&lt;span style=""&gt;Spring 2.1 will not be compatible anymore with JDK 1.3&lt;/span&gt;&lt;/li&gt;&lt;li  style="font-family:arial;"&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;The upcoming new version of Spring IDE will support dependency listing for aspects build with Spring-AOP. With this feature you can view all aspects that are applied to a particular class.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=""&gt;&lt;o:p style="font-family: arial;"&gt;&lt;/o:p&gt;&lt;span style="font-family:arial;"&gt;Migrating from Spring-AOP to AspectJ is easier when using the @Aspect annotations in Java classes rather than using XML to configure aspects. This is because AspectJ understands these annotations.&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p class="MsoNormal" face="arial"&gt;&lt;span style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;b  style="font-family:arial;"&gt;&lt;span style=""&gt;Conclusion&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="font-family: arial;"&gt;&lt;span style=""&gt;Although I had experience with Spring before taking this training, I am glad I took it. A lot of concepts used in Spring were covered in detail. I can recommend this training to anyone who would like to gain more in depth knowledge of the Spring framework.&lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:arial;"&gt;When taking this training, I found it very helpful to have knowledge about enterprise application patterns, transactions, J2EE, TDD, DDD, Hibernate etc.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;p class="MsoNormal" face="arial"&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-7673837911362216969?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/7673837911362216969/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=7673837911362216969' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/7673837911362216969'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/7673837911362216969'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2007/02/core-spring-training-experiences.html' title='Core Spring training experience'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-4053743455416587032</id><published>2007-02-19T09:03:00.001+01:00</published><updated>2007-03-06T11:31:08.879+01:00</updated><title type='text'>Core Spring training</title><content type='html'>&lt;p class="MsoNormal"  style="font-family:arial;"&gt;&lt;span style=""&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;span style="font-size:11;"&gt;This week I am happy to attend the Core Spring training in &lt;st1:city st="on"&gt;&lt;st1:place st="on"&gt;Amsterdam&lt;/st1:place&gt;&lt;/st1:city&gt; given by Interface21. The Core Spring training is a full 4 day training covering all aspects on Spring from IOC and dependency injection to Spring MVC and testing with Spring. This week I will post my day-to-day experiences on this training. More information on this training can be found at: &lt;a target="_blank" href="http://www.interface21.com/"&gt;www.interface21.com&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-4053743455416587032?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/4053743455416587032/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=4053743455416587032' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/4053743455416587032'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/4053743455416587032'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2007/02/core-spring-training-this-week-i-am.html' title='Core Spring training'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-1446943763667430067</id><published>2007-02-16T16:06:00.000+01:00</published><updated>2007-03-06T11:31:28.358+01:00</updated><title type='text'>Service contracts</title><content type='html'>&lt;span style="font-family:arial;"&gt;XML is a common format for message exchange in Service Oriented Architectures. One of the most important things is to formalize the messages exchanged between systems. This can be done using XML schema definitions. XML schema defines the rules to which a XML message must conform when it is constructed. A well defined schema brings the following advantages:&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-family:arial;"&gt;Validate messages when they are constructed and thus &lt;span style="font-style: italic;"&gt;before &lt;/span&gt;they are sent.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:arial;"&gt;Generate Java classes from the XML schema for use in XML binding frameworks.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:arial;"&gt;Easily construct mock XML messages &lt;/span&gt;&lt;span style="font-family:arial;"&gt;with a tool like XMLSpy &lt;/span&gt;&lt;span style="font-family:arial;"&gt;for use in (unit)tests or mock implementations of services.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;With “well defined schema” I mean a schema definition which is constructed before the actual service is implemented so every element in the schema is well thought out. Another example: when some element’s value is an enumeration of some values, define this in the schema definition and not in a separate document (I,ve seen it happen). This way you restrict the values an element can contain and it becomes much easier to construct mock XML messages for testing purposes.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;The bottom line is: invest in the construction of well thought out service contracts.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;A good reference for designing XML schema definitions can be found &lt;a target="_blank" href="http://www.kohsuke.org/xmlschema/XMLSchemaDOsAndDONTs.html#avoid_notations"&gt;here&lt;/a&gt;.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-1446943763667430067?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/1446943763667430067/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=1446943763667430067' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/1446943763667430067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/1446943763667430067'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2007/02/service-contracts-xml-is-common-format.html' title='Service contracts'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-117760846317593301.post-4378983591277828723</id><published>2007-02-16T09:29:00.000+01:00</published><updated>2007-03-06T11:31:50.446+01:00</updated><title type='text'>Starting up...</title><content type='html'>&lt;p style="font-family: arial;" class="MsoNormal"&gt;Finally created my Blog today to post my ideas, thoughts and experiences about Enterprise Java development. Although Java is the primary field of interest, it is not the &lt;u&gt;only&lt;/u&gt; field of interest. For example, I will also post my latest experiences with &lt;a target="_blank" href="http://www.adobe.com/flex"&gt;Adobe Flex&lt;/a&gt; to build highly interactive user interfaces on top of Java backends. I Already can say that I am very impressed. But more on that in one of my next posts.&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;    &lt;p style="font-family: arial;" class="MsoNormal"&gt;The only thing for now I would like to say is: Happy reading!&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/117760846317593301-4378983591277828723?l=jcraane.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jcraane.blogspot.com/feeds/4378983591277828723/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=117760846317593301&amp;postID=4378983591277828723' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/4378983591277828723'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/117760846317593301/posts/default/4378983591277828723'/><link rel='alternate' type='text/html' href='http://jcraane.blogspot.com/2007/02/finally-created-my-blog-today-to-post.html' title='Starting up...'/><author><name>Jamie Craane</name><uri>https://profiles.google.com/110277633741436124029</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
