<?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-9217713084069857387</id><updated>2012-02-13T05:49:57.461+11:00</updated><category term='Swing'/><category term='clone image'/><category term='Fedora'/><category term='Triggers'/><category term='Scene Graph'/><category term='iPhone'/><category term='iOS'/><category term='Dual Boot'/><category term='TimingFramework'/><category term='Java'/><category term='Linux'/><category term='VirtualBox'/><title type='text'>David Horton's blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://davidhorton100.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://davidhorton100.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>David Horton</name><uri>http://www.blogger.com/profile/13905138566602021377</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>12</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-9217713084069857387.post-3752222592386303426</id><published>2011-10-16T02:08:00.002+11:00</published><updated>2011-10-16T02:15:45.644+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iOS'/><title type='text'>iOS 5 on iPhone4</title><content type='html'>Last night I decided to upgrade to iOS 5 on my iPhone4.  I have to say that contrary to expectations, after reading and hearing of many issues that others have had (&lt;a href="http://thenextweb.com/apple/2011/10/12/apples-ios-5-upgrade-servers-are-slammed-causing-3200-or-internal-error-update-issues/"&gt;TNW&lt;/a&gt;), the process was pretty seamless.  Other than a few minutes where I was wondering whether the process had stalled (during the app restore stage) it went without a hitch.  I now have a shiny new OS on my phone.&lt;br /&gt;&lt;br /&gt;I haven't really spent that much time looking for the differences but some things are obviously different.  I'm still making up my mind about some of the changes most notably the new toggle buttons, call me a luddite but I think I preferred the old ones.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9217713084069857387-3752222592386303426?l=davidhorton100.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://davidhorton100.blogspot.com/feeds/3752222592386303426/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9217713084069857387&amp;postID=3752222592386303426' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/3752222592386303426'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/3752222592386303426'/><link rel='alternate' type='text/html' href='http://davidhorton100.blogspot.com/2011/10/ios-5-on-iphone4.html' title='iOS 5 on iPhone4'/><author><name>David Horton</name><uri>http://www.blogger.com/profile/13905138566602021377</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-9217713084069857387.post-6333469592693099981</id><published>2011-03-20T23:45:00.004+11:00</published><updated>2011-03-20T23:59:11.080+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='clone image'/><category scheme='http://www.blogger.com/atom/ns#' term='VirtualBox'/><title type='text'>VirtualBox - Cloning a VM</title><content type='html'>NOTE - This was done using VirtualBox 4.0.4 r70112 with a Windows 7 host.&lt;br /&gt;&lt;br /&gt;It needs to be fleshed out but this is just to capture the initial process.&lt;br /&gt;&lt;br /&gt;I've been using VirtualBox to host some VMs (mainly Linux).&lt;br /&gt;&lt;br /&gt;It's a bit of a pain to create a brand new VM each time and I like to have a relatively clean base image to start from when starting a new project.  So, I want to be able to clone an image relatively easily.&lt;br /&gt;&lt;br /&gt;Here's the steps I took to get a 'template' VM and working copies of it.  It may not be the most efficient but it worked for me and may work for you.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Create an initial template VM as for any guest machine.  Install the chosen OS and perform any base/initial configuration you want to be captured in the template itself.&lt;/li&gt;&lt;li&gt;Ensure the guest machine is powered off.&lt;/li&gt;&lt;li&gt;Clone the virtual disk for the VM.  You can't simply copy the virtual disk file (not if the guest will be used on the same machine) as VirtualBox will see that both images have the same UUID.  So, we need to use the clonehd function to copy the image and replace the UUID.&lt;br /&gt;C:\Program Files\Oracle\VirtualBox\VBoxManage clonehd&lt;soure&gt;&lt;dest&gt;&lt;br /&gt;This clones the virtual disk and gives it a new UUID&lt;/dest&gt;&lt;/soure&gt;&lt;/li&gt;&lt;li&gt;&lt;soure&gt;&lt;dest&gt;Create a new guest from within VirtualBox choosing the appropriate hardware settings.&lt;/dest&gt;&lt;/soure&gt;&lt;/li&gt;&lt;li&gt;&lt;soure&gt;&lt;dest&gt;When choosing disks, select to use an existing disk and select the copied image.&lt;/dest&gt;&lt;/soure&gt;&lt;/li&gt;&lt;li&gt;&lt;soure&gt;&lt;dest&gt;Boot the machine and it should start up with the exact same OS behaviour as the original image that was cloned.  Voila!&lt;br /&gt;&lt;/dest&gt;&lt;/soure&gt;&lt;/li&gt;&lt;/ol&gt;&lt;soure&gt;&lt;dest&gt;&lt;br /&gt;NOTE - Cloning the image also registers it with VirtualBox.  If you subsequently want to move/rename it then use the 'Virtual Media Manager' from the File menu within VirtualBox.&lt;br /&gt;&lt;br /&gt;NOTE - I'm not aware of an ability to clone the machine description itself (but I haven't actually tried).  This may well be possible rather than creating a new machine and setting the hardware settings manually.  The machine configuration appears to be held in XML files so it may be as simple as copying/editing these.  Whether that is supported is another matter...&lt;br /&gt;&lt;br /&gt;That's all for now.  I may clean up and add some screenshots at some point... Based on past experience, don't hold your breath! ;-)&lt;br /&gt;&lt;br /&gt;&lt;/dest&gt;&lt;/soure&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9217713084069857387-6333469592693099981?l=davidhorton100.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://davidhorton100.blogspot.com/feeds/6333469592693099981/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9217713084069857387&amp;postID=6333469592693099981' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/6333469592693099981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/6333469592693099981'/><link rel='alternate' type='text/html' href='http://davidhorton100.blogspot.com/2011/03/virtualbox-cloning-vm.html' title='VirtualBox - Cloning a VM'/><author><name>David Horton</name><uri>http://www.blogger.com/profile/13905138566602021377</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-9217713084069857387.post-3645437078499046749</id><published>2011-03-20T23:41:00.002+11:00</published><updated>2011-03-20T23:44:56.423+11:00</updated><title type='text'>Time flies</title><content type='html'>Well, it never really took off quite as quickly as I expected/hoped.  Life got in the way and blogging very much took a back seat.&lt;br /&gt;&lt;br /&gt;Anyway, hopefully there will be a few more posts on here soon.  Basically I've decided to use this as a staging post for any tidbits of info that I find as I'm conquering various (sometimes trivial) technical challenges.&lt;br /&gt;&lt;br /&gt;So, we'll see how we get on...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9217713084069857387-3645437078499046749?l=davidhorton100.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/3645437078499046749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/3645437078499046749'/><link rel='alternate' type='text/html' href='http://davidhorton100.blogspot.com/2011/03/time-flies.html' title='Time flies'/><author><name>David Horton</name><uri>http://www.blogger.com/profile/13905138566602021377</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></entry><entry><id>tag:blogger.com,1999:blog-9217713084069857387.post-1415843520801197174</id><published>2009-02-21T21:44:00.003+11:00</published><updated>2009-02-21T21:51:40.399+11:00</updated><title type='text'>Nortel Contivity VPN Client Issue with Belkin F5D8631-4 ADSL Router</title><content type='html'>I used to be able to connect to my company's VPN and work from home no problems.  Recently, I tried connecting and was unable to do so.  I was pretty sure the issue was on my end because I was able to connect to the VPN from the wireless network in the office.  Anyway, I have resolved the issues and all is now working again.&lt;br /&gt;&lt;br /&gt;It turns out that I hadn't attempted to use the VPN since my last router died and I had changed to the Belkin F5D8631-4.  Although this router claims to support VPN pass through it wasn't working for me.&lt;br /&gt;&lt;br /&gt;There's a compatibility issue between the 2.00.13 firmware and Nortel's Contivity VPN client.  There is a pre-release firmware version 2.00.18 available &lt;a href="http://www.belkin.com/uk/support/article/?lid=enu&amp;amp;pid=F5D8631uk4A&amp;amp;aid=9121&amp;amp;scid=314"&gt;here&lt;/a&gt; which resolves the issue.  As it's a pre-release firmware it won't be found by the auto update feature in the router itself and so you need to download it manually.&lt;br /&gt;&lt;br /&gt;It has resolved my VPN connectivity issues and I haven't yet come across any other issues with the firmware version.  So, if you're having similar VPN issues on this router, give this firmware a go.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9217713084069857387-1415843520801197174?l=davidhorton100.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://davidhorton100.blogspot.com/feeds/1415843520801197174/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9217713084069857387&amp;postID=1415843520801197174' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/1415843520801197174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/1415843520801197174'/><link rel='alternate' type='text/html' href='http://davidhorton100.blogspot.com/2009/02/nortel-contivity-vpn-client-issue-with.html' title='Nortel Contivity VPN Client Issue with Belkin F5D8631-4 ADSL Router'/><author><name>David Horton</name><uri>http://www.blogger.com/profile/13905138566602021377</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-9217713084069857387.post-5608505678298982152</id><published>2008-11-18T20:45:00.005+11:00</published><updated>2008-11-18T21:33:12.429+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dual Boot'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Fedora'/><title type='text'>Fedora 8 dual boot configuration with Windows XP and Acronis OS Selector</title><content type='html'>I've just been battling through getting an old desktop PC to dual boot Windows XP and Fedora 8.  It finally works so I figured I'd write up the details here in case it can be of any use to anyone.&lt;br /&gt;&lt;br /&gt;These are the results of trawling a number of fora and blogs to attempt to resolve the issues.  This was mostly at &lt;a href="http://www.linuxforums.org/"&gt;Linux Forums&lt;/a&gt;  TheGrub manual at &lt;a href="http://www.gnu.org/software/grub/manual/html_node/"&gt;http://www.gnu.org/software/grub/manual/html_node/&lt;/a&gt; was also very useful.&lt;br /&gt;&lt;br /&gt;Note - I'm only going to discuss the specifics of my installation and won't be going off onto tangents that may be required for differing configurations.  This is for a couple of reasons; firstly to keep the entry as succinct as possible; secondly to avoid confusion for anyone trying to follow from start to finish.  I expect that most people will be aware that they will need to change device names etc to match their specific circumstances.&lt;br /&gt;&lt;br /&gt;The existing configuration&lt;br /&gt;&lt;ul&gt;&lt;li&gt;3 physical drives&lt;/li&gt;&lt;li&gt;Windows XP installed on the first primary partition of the first hard drive&lt;/li&gt;&lt;li&gt;Acronis OS Selector installed on the MBR of the first hard drive.  By default it invokes NTLDR from the first primary partition on the same drive, booting Windows XP by default.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Desired configuration&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Use the free space in the third hard drive to install Fedora 8.  Leave the existing OS selector in place so do not put grub in the MBR of the first drive.&lt;/li&gt;&lt;li&gt;I planned to use a separate /boot partition for the kernel and grub and a Logical Volume (LVM) for the root (/) filesystem.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The process....&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Boot the PC from the Fedora 8 DVD&lt;/li&gt;&lt;li&gt;Configure the partitions as follows on the empty hard drive.  This was done using the partition editor included in the Anaconda installer&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;0-200MB             - /boot                      ext3 filesystem&lt;br /&gt;201-2000MB      - SWAP&lt;br /&gt;2001-20000MB - /                              ext3 filesystem&lt;br /&gt;(LVM device is /dev/VolGroup00/LogVol00)&lt;/blockquote&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Install Fedora 8 with the desired packages.  My install was approx 1200 packages and took 1.5 hours to complete.&lt;/li&gt;&lt;li&gt;Now, due to the existing boot loader installed on the Windows drive, I chose not to install Grub during the initial installation.  I now believe this was a mistake as it was a pain to figure out exactly what needed copying across to the boot partition in order to support Grub properly.&lt;br /&gt;&lt;br /&gt;I would advise installing Grub as part of the initial install, but making sure to choose to install it to the Linux /boot partition rather than the MBR of the first drive in the system&lt;/li&gt;&lt;li&gt;Due to the issue in 4 above, I was unable to boot Linux by default....so....&lt;/li&gt;&lt;li&gt;Reboot the machine with the installation/rescue CD in the drive.&lt;/li&gt;&lt;li&gt;Select the option to rescue an existing installation.  (I attempted to 'upgrade' an existing installation to copy the boot loader configuration but that failed).&lt;/li&gt;&lt;li&gt;Follow the prompts to set up keyboard, nework and language settings.&lt;/li&gt;&lt;li&gt;When the system is booted, it will detect the Linux installation and mount it under /mnt/sysimage.  We need to access it as the root image soexecute the following command&lt;br /&gt;&lt;blockquote&gt;chroot /mnt/sysimage&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;We now need to copy the Grub image files across to the boot partition&lt;br /&gt;&lt;blockquote&gt;mkdir /boot/grub&lt;br /&gt;cp /usr/share/grub/i386-redhat/*stage* /boot/grub&lt;/blockquote&gt;&lt;br /&gt;This copies the boot loader files (stage1, stage2 and the various stage1.5 files) to the boot partition.&lt;/li&gt;&lt;li&gt;Access the grub command line interface by executing the following command&lt;br /&gt;&lt;blockquote&gt;grub&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;We need to determine the root location from where Grub will boot Linux.  So (from within the Grub command line) we execute&lt;br /&gt;&lt;blockquote&gt;grub&gt; find /grub/stage1&lt;br /&gt;&lt;/blockquote&gt;NOTE - We do not specify /boot/grub/stage1 as we have a dedicated boot partition, so relative to the partition, the grub directory is in the root of the partition.&lt;br /&gt;&lt;br /&gt;Also note that the 'grub&gt; ' is the Grub command line prompt not part of the command to be entered&lt;br /&gt;&lt;br /&gt;This will tell us the name (in Grub parlance) of the partition.  In my case this was (hd2,0) which as expected is the first partition (0) of the third hard drive (hd2).&lt;/li&gt;&lt;li&gt;Now we have confirmed this, we need to install the Grub bootloader into the partition.  From the Grub command line exexcute&lt;br /&gt;&lt;blockquote&gt;grub&gt; setup (hd2,0)&lt;/blockquote&gt;This will install Grub into the boot sector of the partition&lt;/li&gt;&lt;li&gt;We now need to create the Grub configuration file which is used by Grub to boot the various operating systems.  Using a text editor create a file named grub.conf in /boot/grub/.  Below is the content of my file&lt;br /&gt;&lt;blockquote&gt;default=0&lt;br /&gt;timeout=10&lt;br /&gt;splashimage=(hd2,0)/grub/splash.xpm.gz&lt;br /&gt;&lt;br /&gt;title Fedora Core 8 - (2.6.23.1-42.fc8)&lt;br /&gt;  root (hd2,0)&lt;br /&gt;  kernel /vmlinuz-2.6.23.1-42.fc8 ro root=/dev/VolGroup00/LogVol00 rhgb&lt;br /&gt;  initrd /initrd-2.6.23.1-42.fc8.img&lt;/blockquote&gt;&lt;br /&gt;NOTE - The vmlinuz and initrd entries are not prefixed by /boot.  This is due to the fact that we have a dedicated /boot partition and these are relative to the root directory of that partition.&lt;br /&gt;&lt;br /&gt;Also note the device name for the root partition becuase we are using a logical volume for the root partition&lt;br /&gt;&lt;/li&gt;&lt;li&gt;This should be all the configuration that is required to boot Linux from within Grub.  However, it wasn't possible for me to successfully test this in isolation.  If I attempted to run grub from within the rescue environment and boot Fedora from the new config file I received errors regarding inconsistent filesystem types (Grub error 16).  I believe this may be due to the resuce environment not loading all necessary drivers (perhaps for logical volumes) but I haven't confirmed this.&lt;br /&gt;&lt;br /&gt;So, in order to test I had to configure Acronis OS Selector to chain into Grub.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Reboot, without the Fedora installation DVD in the drive.  Acronis OS Selector should boot as normal as it still exists in the MBR of the first drive.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;From Tools --&gt; OS Selector add a new operating system by locating the partition containing Grub.  Acronis OS Selector should detect the Linux boot loader if pointed at the correct partition.&lt;/li&gt;&lt;li&gt;Choose to boot the Linux OS.  Acronis will chain into Grub.  You should be presented with the Grub menu with the boot options specified earlier (Fedora 8 only in this case).&lt;/li&gt;&lt;li&gt;Choose to boot Fedora 8.  It should boot successfully.  The rhgb option we specified to the kernel parameters will use the graphical boot process for Fedora.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;I hope that makes sense.  I will add screenshots and tidy up the formatting shortly and answer any questions that people may have.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9217713084069857387-5608505678298982152?l=davidhorton100.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://davidhorton100.blogspot.com/feeds/5608505678298982152/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9217713084069857387&amp;postID=5608505678298982152' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/5608505678298982152'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/5608505678298982152'/><link rel='alternate' type='text/html' href='http://davidhorton100.blogspot.com/2008/11/fedora-8-dual-boot-configuration-with.html' title='Fedora 8 dual boot configuration with Windows XP and Acronis OS Selector'/><author><name>David Horton</name><uri>http://www.blogger.com/profile/13905138566602021377</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-9217713084069857387.post-7348180002541794344</id><published>2008-01-07T08:15:00.000+11:00</published><updated>2008-01-07T08:20:43.479+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TimingFramework'/><category scheme='http://www.blogger.com/atom/ns#' term='Swing'/><category scheme='http://www.blogger.com/atom/ns#' term='Scene Graph'/><title type='text'>No sooner do you learn one new trick...</title><content type='html'>...then someone comes along and trumps it.&lt;br /&gt;&lt;br /&gt;Chet Haase has blogged on the new animation features in the SceneGraph project being created at &lt;a href="https://scenegraph.dev.java.net/"&gt;https://scenegraph.dev.java.net/&lt;/a&gt;.  A new and improved version of the Timing Framework...and just as I thought I'd mastered the previous incarnation.&lt;br /&gt;&lt;br /&gt;Well, they say you can't stop progress...&lt;br /&gt;&lt;br /&gt;&lt;a href="http://weblogs.java.net/blog/chet/archive/2008/01/been_there_scen.html"&gt;Here's the link to Chet's blog entry&lt;br /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9217713084069857387-7348180002541794344?l=davidhorton100.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://davidhorton100.blogspot.com/feeds/7348180002541794344/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9217713084069857387&amp;postID=7348180002541794344' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/7348180002541794344'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/7348180002541794344'/><link rel='alternate' type='text/html' href='http://davidhorton100.blogspot.com/2008/01/no-sooner-do-you-learn-one-new-trick.html' title='No sooner do you learn one new trick...'/><author><name>David Horton</name><uri>http://www.blogger.com/profile/13905138566602021377</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-9217713084069857387.post-1458415054158309284</id><published>2007-12-04T21:02:00.000+11:00</published><updated>2007-12-04T21:31:17.028+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='TimingFramework'/><category scheme='http://www.blogger.com/atom/ns#' term='Swing'/><category scheme='http://www.blogger.com/atom/ns#' term='Triggers'/><title type='text'>Timing Framework (part 2) - Triggers</title><content type='html'>In the last blog, I showed a simple demonstration of how the Timing Framework can help reduce the amount of boilerplate code required to code animations.  In this entry I'll show how to use triggers to reduce this even further.&lt;br /&gt;&lt;br /&gt;In the last entry we used code like this to start an animation when a button was clicked.&lt;br /&gt;&lt;pre&gt;button.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;addActionListener&lt;/span&gt;(new &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;ActionListener&lt;/span&gt;() {&lt;br /&gt;public void &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;actionPerformed&lt;/span&gt;(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;ActionEvent&lt;/span&gt; e) {&lt;br /&gt;  Animator &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;anim&lt;/span&gt; = new Animator(2000, 5,&lt;br /&gt;      Animator.RepeatBehavior.REVERSE, new &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;ButtonTimingTarget&lt;/span&gt;());&lt;br /&gt;  anim.setAcceleration(0.4f);&lt;br /&gt;  anim.setDeceleration(0.4f);&lt;br /&gt;  &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;anim&lt;/span&gt;.start();&lt;br /&gt;}&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;The Timing Framework provides triggers which extend the basic functionality of the framework.  The framework provides a number of trigger classes which can trigger &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_7"&gt;animations&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;We can &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_8"&gt;simplify&lt;/span&gt; the above code using an action trigger which corresponds to &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;ActionEvents&lt;/span&gt; and so is perfect to use with a button.  The trigger may be instantiated directly by client code but of more convenience is the static &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;addTrigger&lt;/span&gt; method which also takes the object on which the trigger should operate.&lt;br /&gt;&lt;br /&gt;For example, to add an action trigger to the button we'd do the following:&lt;br /&gt;&lt;pre&gt;Animator &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;anim&lt;/span&gt; = new Animator(2000, 5,&lt;br /&gt;  Animator.RepeatBehavior.REVERSE, new &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;ButtonTimingTarget&lt;/span&gt;());&lt;br /&gt;anim.setAcceleration(0.4f);&lt;br /&gt;anim.setDeceleration(0.4f);&lt;br /&gt;&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;ActionTrigger&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;addTrigger&lt;/span&gt;(button, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;anim&lt;/span&gt;);&lt;br /&gt;&lt;/pre&gt;This may not seem like a huge reduction but it removes the boilerplate of the action listener implementation and removes the need for the anonymous inner class making the code arguably much more readable.&lt;br /&gt;&lt;br /&gt;Currently the framework provides four trigger implementations:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;ActionTrigger&lt;/span&gt; - as shown above, may be used on any component that fires action events.&lt;/span&gt;&lt;/li&gt;  &lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;FocusTrigger&lt;/span&gt; - may be used on components that fire focus events such as text fields&lt;/span&gt;&lt;/li&gt;  &lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;MouseTrigger&lt;/span&gt; - may be used on components that fire mouse events (pretty much every component) such as when the mouse enters or leaves a component&lt;/span&gt;&lt;/li&gt;  &lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;TimingTrigger&lt;/span&gt; - allows sequencing of different animations, for example starting an animation when another animation ends&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;The &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;ActionTrigger&lt;/span&gt; is the simplest of the triggers and takes no special parameters.  The more specialised triggers have a corresponding Event class (e.g. &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;FocusTriggerEvent&lt;/span&gt; for the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;FocusTrigger&lt;/span&gt; or &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;MouseTriggerEvent&lt;/span&gt; for the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;MouseTrigger&lt;/span&gt;) which specify the specific event(s) on which the trigger should operate.  The key point is that the trigger class handles the setting of the listeners on the component to fire the animation at the appropriate time.  All the developer needs to do is create the animation instance, set the trigger and let the framework ensure that the animation is fired appropriately.&lt;br /&gt;&lt;br /&gt;Next time I'll take this a step further and use a property setter to simplify the code even more.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9217713084069857387-1458415054158309284?l=davidhorton100.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://davidhorton100.blogspot.com/feeds/1458415054158309284/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9217713084069857387&amp;postID=1458415054158309284' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/1458415054158309284'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/1458415054158309284'/><link rel='alternate' type='text/html' href='http://davidhorton100.blogspot.com/2007/12/timing-framework-part-2-triggers.html' title='Timing Framework (part 2) - Triggers'/><author><name>David Horton</name><uri>http://www.blogger.com/profile/13905138566602021377</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-9217713084069857387.post-2295967609830842296</id><published>2007-12-01T10:49:00.000+11:00</published><updated>2008-12-10T23:29:13.380+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='TimingFramework'/><category scheme='http://www.blogger.com/atom/ns#' term='Swing'/><title type='text'>Timing Framework 101</title><content type='html'>One of the most important factors in computer animation is that it needs to be time based.  Otherwise the animation may be impacted by the performance of the underlying system when run on platforms with differing performance characteristics; what looks impressive and realistic on the development system may look terrible on a system with differing performance.  Time based animation removes this; the animation is given a duration and the state of the animation is interpolated based on the fraction of the duration that has passed.  This helps ensure that animations look consistent when run on different platforms.&lt;br /&gt;&lt;br /&gt;As of JSE6 there are 3 timer classes supplied; java.util.Timer, javax.swing.Timer and javax.management.Timer.  For Swing based applications, the most useful of these is the javax.swing.Timer class which ensures that all events it fires are fired on the Event Dispatch Thread.  This is important if the event is to subsequently update the state of the UI which is the case for UI animation.&lt;br /&gt;&lt;br /&gt;The Swing timer class fires instances of ActionEvent and so components register ActionListener instances with the timer which are informed of events.  This excerpt from the JSE6 javadoc illustrates one method of instantiating a timer which might be used for animation purposes.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;int delay = 1000; //milliseconds&lt;br /&gt;ActionListener taskPerformer = new ActionListener() {&lt;br /&gt;public void actionPerformed(ActionEvent evt) {&lt;br /&gt;    //...Perform a task...&lt;br /&gt;}&lt;br /&gt;};&lt;br /&gt;new Timer(delay, taskPerformer).start();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If the animation is fired in response to some other action such as a button click then the code rapidly becomes unwieldy.  The button fires an action event which has a listener that sets up a timer, which fires an action event of its own.  The listener for this event then performs the necessary animation.  In doing so, it must calculate the fraction of the animation duration that has passed in order for the animation to be properly time based.&lt;br /&gt;&lt;br /&gt;There's a large amount of boilerplate code that is required in order to set up the actions and timers and to calculate the animation fraction.  The timing framework helps to abstract this away from the developer so they may concentrate on the action of the animation itself.  The framework handles the setup of the timer and calculating the fraction of the animation.  It uses callbacks which the developer can use to perform the animation.&lt;br /&gt;&lt;br /&gt;The core class of the Timing Framework is the Animator class.  This is the class used to create and control animations.  It provides 3 constructors, one of which is shown below.  The others are simpler versions that use defaults for one or more of the options.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Animator(int duration,&lt;br /&gt;       double repeatCount,&lt;br /&gt;       Animator.RepeatBehavior repeatBehavior,&lt;br /&gt;       TimingTarget target)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The duration is the length of the animation; repeatCount specifies the number of times the animation should repeat; repeatBehaviour specifies the behaviour of the animation when it begins a new cycle, should it perform the previous cycle in reverse or loop back to the beginning and repeat; finally the target is the object that receives the animation events.&lt;br /&gt;&lt;br /&gt;Once the Animator instance has been created, further options may be specified by calling methods on the Animator.&lt;br /&gt;&lt;br /&gt;The animation is started by calling the start method.&lt;br /&gt;&lt;br /&gt;The final parameter in the above constructor is an instance of TimingTarget.  This object is used by the Animator to perform callbacks to perform the animation.  The TimingTarget interface specifies the following methods:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;begin()&lt;br /&gt;end()&lt;br /&gt;repeat()&lt;br /&gt;timingEvent(float fraction)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The begin, end and repeat methods are self explanatory and are called when the animation begins, ends and repeats a cycle respectively.  The key method is the timingEvent method.  As can be seen, this callback passes the fraction of the animation that has passed which is calculated by the framework.  This value, which is always between 0 and 1, is used to perform the appropriate animation.&lt;br /&gt;&lt;br /&gt;A simple example will help illustrate.  If we have a panel containing a button that we wish to animate along the x axis when it is clicked, we could do the following:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;button = new JButton("Click Me!");&lt;br /&gt;button.addActionListener(new ActionListener() {&lt;br /&gt; public void actionPerformed(ActionEvent e) {&lt;br /&gt;   Animator anim = new Animator(2000, 5,&lt;br /&gt;       Animator.RepeatBehavior.REVERSE,&lt;br /&gt;       new ButtonTimingTarget());&lt;br /&gt;   anim.start();&lt;br /&gt; }&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This specifies an animation of 2 seconds duration that repeats 5 times with each cycle reversing the previous cycle.  The ButtonTimingTarget which receives the callbacks is shown below:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class ButtonTimingTarget extends TimingTargetAdapter {&lt;br /&gt;  @Override&lt;br /&gt;  public void timingEvent(float fraction) {&lt;br /&gt;   // Calculate button location bounds...&lt;br /&gt;   ...&lt;br /&gt;   loc = ....&lt;br /&gt;   // Alter x location based on animation fraction.&lt;br /&gt;   button.setLocation(loc.x * fraction), loc.y);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The TimingTargetAdapter class is a convenience class that implements the TimingTarget interface with empty methods.&lt;br /&gt;&lt;br /&gt;Screenshots of this animation are below.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;1. Initial position&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_FPiI7D1x3PA/R1CvDpp1JrI/AAAAAAAAAAM/5_FLERbhK2w/s1600-R/pre-anim.PNG"&gt;&lt;img style="cursor: pointer;" src="http://2.bp.blogspot.com/_FPiI7D1x3PA/R1CvDpp1JrI/AAAAAAAAAAM/TTfamv5Cop0/s320/pre-anim.PNG" alt="" id="BLOGGER_PHOTO_ID_5138799652085507762" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;2. Mid way through the animation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_FPiI7D1x3PA/R1CvK5p1JsI/AAAAAAAAAAU/o_i89PmJ650/s1600-R/mid-anim.PNG"&gt;&lt;img style="cursor: pointer;" src="http://3.bp.blogspot.com/_FPiI7D1x3PA/R1CvK5p1JsI/AAAAAAAAAAU/j6UveHK79Cc/s320/mid-anim.PNG" alt="" id="BLOGGER_PHOTO_ID_5138799776639559362" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;3. After animation completion.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_FPiI7D1x3PA/R1CvPJp1JtI/AAAAAAAAAAc/B6ugiudDhfQ/s1600-R/post-anim.PNG"&gt;&lt;img style="cursor: pointer;" src="http://4.bp.blogspot.com/_FPiI7D1x3PA/R1CvPJp1JtI/AAAAAAAAAAc/KM6DTl5Kkes/s320/post-anim.PNG" alt="" id="BLOGGER_PHOTO_ID_5138799849654003410" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Although this is a simple example, it illustrates the simplicity of setting up an animation using the TimingFramework.&lt;br /&gt;&lt;br /&gt;However, there's still no small amount of boilerplate in this example.  We still have to add the action listener to the button in order to set up and start the animation.  We also calculate and set the new location of the button ourselves based on the fraction of the animation.  In the next blog I'll demonstrate the use of Triggers and PropertySetters to remove more of this boilerplate and make animations even simpler.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9217713084069857387-2295967609830842296?l=davidhorton100.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://davidhorton100.blogspot.com/feeds/2295967609830842296/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9217713084069857387&amp;postID=2295967609830842296' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/2295967609830842296'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/2295967609830842296'/><link rel='alternate' type='text/html' href='http://davidhorton100.blogspot.com/2007/12/timing-framework-101.html' title='Timing Framework 101'/><author><name>David Horton</name><uri>http://www.blogger.com/profile/13905138566602021377</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/_FPiI7D1x3PA/R1CvDpp1JrI/AAAAAAAAAAM/TTfamv5Cop0/s72-c/pre-anim.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9217713084069857387.post-3811773229675475215</id><published>2007-11-28T17:42:00.000+11:00</published><updated>2007-11-28T18:22:59.587+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Swing'/><title type='text'>Swingin' into '08</title><content type='html'>My first foray into the world of Java was back in 99-2000 when I was tasked with creating a rudimentary client/server app.  The app was Swing based with simple UIs for the client and server parts of the app.  I remember being struck at the time of how easy it was to create basic&lt;br /&gt;UIs; much more so than the C++ Win 32 UIs I had written previously.&lt;br /&gt;&lt;br /&gt;Since those days I've not really used Swing that much, my career since then has taken me more towards N-tier applications, generally with a web front end.  In those eight years, I've used a number of web MVC frameworks and through the years have seen a great improvement in developer productivity and ease of development/integration as new frameworks have come along.  In recent years, technologies such as AJAX have added a richer experience to the web client.&lt;br /&gt;&lt;br /&gt;So, when I decided to take another look at my old friend Swing, I was excited to see what had happened in the intervening years.  On initial inspection, not a whole lot seems to have changed.  There have been good performance improvements, which is always worthwhile.  One introduction in JSE6 (developed initially at SwingLabs) I've since used a lot is the SwingWorker class which helps offload long running tasks from the Event Dispatch Thread.  There have also been tweaks to the look and feels (esp the Windows L&amp;amp;F).&lt;br /&gt;&lt;br /&gt;However, I was surprised not to see more new features jumping out at me and begging to be tried.  Perhaps there are more gems lurking which I haven't yet discovered, I hope so.&lt;br /&gt;&lt;br /&gt;I think the main frustration in developing Swing apps is that although there is a wealth of supplied components; and it is relatively straightforward to create custom components; there's no centralised framework or patterns for laying out your application architecture.&lt;br /&gt;&lt;br /&gt;There's also a large amount of boilerplate that has to be created for all apps.  For example, how often have you written...&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public void static main(String[] args) {&lt;br /&gt; SwingUtilities.invokeLater(new Runnable() {&lt;br /&gt;   public void run() {&lt;br /&gt;     new MyAppFrame().setVisible(true);&lt;br /&gt;   }&lt;br /&gt; };&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;... or something similar, just to make sure that the app is created on the EDT.  I don't keep track (I'm not quite that geeky!) but it must be in the hundreds.&lt;br /&gt;&lt;br /&gt;I'm therefore excited by JSR296 which should hopefully standardise the main structure of a Swing app and help development teams get up to speed more quickly as there should be a common understanding of how common functions are performed.&lt;br /&gt;&lt;br /&gt;I'm also excited by JSR295 - Beans Binding which should simplify the process of binding the properties of GUI widgets to model properties removing yet more boilerplate for adding PropertyChangeListener instances.&lt;br /&gt;&lt;br /&gt;Hopefully both of these will make it into JSE7 (Dolphin) but early versions are available on java.net.&lt;br /&gt;&lt;br /&gt;I haven't had a chance to experiment with them yet but it's on the ToDo list.&lt;br /&gt;&lt;br /&gt;One area I've been getting into since my return to client apps is animation and I've been experimenting with the Timing Framework developed by Chet Haase of Sun (available at http://timingframework.dev.java.net).  It's fairly simple, only a handful of interfaces and classes.  It's this simplicity that makes it a really nice framework to use.  It's very easy to set up fairly sophisticated animations, quickly and easily with minimal coding required.&lt;br /&gt;&lt;br /&gt;In the next few blogs I'll be running through some Timing Framework examples, showing how it can really simplify the creation of animations in Swing applications.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9217713084069857387-3811773229675475215?l=davidhorton100.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://davidhorton100.blogspot.com/feeds/3811773229675475215/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9217713084069857387&amp;postID=3811773229675475215' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/3811773229675475215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/3811773229675475215'/><link rel='alternate' type='text/html' href='http://davidhorton100.blogspot.com/2007/11/swingin-into-08.html' title='Swingin&apos; into &apos;08'/><author><name>David Horton</name><uri>http://www.blogger.com/profile/13905138566602021377</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-9217713084069857387.post-4274203964823439474</id><published>2007-11-26T21:08:00.000+11:00</published><updated>2007-11-26T21:24:28.366+11:00</updated><title type='text'>Time for a 2nd opinion</title><content type='html'>One of my passions and something I claim to know more than a little about is the Oracle database.  I'm still learning and hopefully always will be.&lt;br /&gt;&lt;br /&gt;It probably comes as no surprise that one of the sources from which I've learned a tremendous amount of information is Tom Kyte of Oracle (&lt;a href="http://asktom.oracle.com/"&gt;http://asktom.oracle.com&lt;/a&gt;).  Now, Tom spends a large amount of time answering questions from us mere mortals on all topics Oracle.&lt;br /&gt;&lt;br /&gt;The other day I was browsing the site and saw that the 'Ask a question' button was available.  For those of you that read asktom regularly you'll know this is a fairly rare occurrance, as there's always a large number of questions awaiting Tom's attention.&lt;br /&gt;&lt;br /&gt;So, I thought I'd ask a question regarding a semi-hypothetical situation that had cropped up with a legacy application.  I'd been trying to figure out a way of reducing the serialisation time when trying to process records in a table (not a batch process - an online process where we need to process one at a time).  I did my research and came across a few things I didn't know previously - including the undocumented SKIP LOCKED clause on SELECT FOR UPDATE and some alternative procedural approaches.  So, I posed the question to Tom, was this a valid approach?&lt;br /&gt;&lt;br /&gt;To answer, Tom pointed me in the direction of something I hadn't even considered but which was built right for the purpose, Oracle AQ.  Fitted the problem domain exactly without requiring any of the workarounds I had thought of to cope with limitations of procedural approaches (all the what ifs...).  Now with the original idea for the question being a legacy app, there'd need to be some adjustment to get AQ in there but a whole lot less work than trying to cope with the error scenarios and making sure we catch them all.&lt;br /&gt;&lt;br /&gt;Moral of the story - It's reminded me it's always wise to get a second opinion on any design/idea you come up with for a particular situation.  We techies sometimes have a tendency to overlook the obvious and reinvent the wheel when the answer is often right under our noses...&lt;br /&gt;&lt;br /&gt;Thanks Tom!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9217713084069857387-4274203964823439474?l=davidhorton100.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://davidhorton100.blogspot.com/feeds/4274203964823439474/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9217713084069857387&amp;postID=4274203964823439474' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/4274203964823439474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/4274203964823439474'/><link rel='alternate' type='text/html' href='http://davidhorton100.blogspot.com/2007/11/time-for-2nd-opinion.html' title='Time for a 2nd opinion'/><author><name>David Horton</name><uri>http://www.blogger.com/profile/13905138566602021377</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-9217713084069857387.post-8228108419565018504</id><published>2007-11-26T18:15:00.000+11:00</published><updated>2007-11-26T18:50:05.803+11:00</updated><title type='text'>Kevin '07 - Rudd sweeps to victory in Australian election</title><content type='html'>Well, it was a long shot, and 10 minutes is not a long time to attract your first comment... Oh well.&lt;br /&gt;&lt;br /&gt;So, which option did I take???  I thought I'd start off with the extremely safe subject of politics.  No danger there of enflaming any passions....&lt;br /&gt;&lt;br /&gt;This was my first election in Australia having voted in the last two general elections in the UK and it was a &lt;span style="font-weight: bold;"&gt;very&lt;/span&gt; different experience.&lt;br /&gt;&lt;br /&gt;For the uninitiated, Saturday saw the federal election in Australia with all seats in the House of Representatives up for grabs.  In the blue corner, the government of the Liberal coalition led by John Howard who has been Prime Minister for the last 11 years.  In the red corner, the Labor party, led by Kevin Rudd for less than a year.  The final results in all seats are not yet counted but Labor have won a resounding victory, with Kevin Rudd set to take over as PM.  It's also likely that John Howard will lose his Bennelong seat, the first sitting PM to lose their seat in 78 years.&lt;br /&gt;&lt;br /&gt;So, what went wrong for the Liberals?  Or was it a case of Labor winning rather than the government losing?  Unfortunately I can't really comment as I don't know enough about the details but the overriding opinion seems to be that the government's controversial work choices policy was the main culprit.&lt;br /&gt;&lt;br /&gt;What I noticed most was the amount of advertising on television and print, much more so than back home in the UK.  Also, most of it tended to be negative advertising, bashing the opposition rather than promoting the policies of the advertising party.  That was my outsider's perception anyway.  Not that politics back home is any better; anyone's who's seen Prime Minister's questions on a Wednesday afternoon can testify to that.&lt;br /&gt;&lt;br /&gt;Australia has a policy whereby everyone who is eligible to vote, must vote; under penalty of a fine.  It could be said that Australia has a very active democracy and the people need no encouragement to vote.  However it could also mean that there is a large pool of people who, would not necessarily vote without the threat of a fine.  Whatever the case may be  there was a small army of volunteers around in Sydney canvassing.  It was refreshing in many ways, as someone ineligible to vote, being able to watch the spectacle knowing that I personally would bear no responsibility for the outcome.&lt;br /&gt;&lt;br /&gt;On polling day, I was driving through my suburb and passed several polling stations.  I was amazed at how many Labor supporters had gathered and were canvassing, right up to the end.  I saw a few from other parties, mainly the Greens, but no conspicuous Liberal presence.  Maybe that's the area I live in, but for a government many expected to lose, I was surprised not to see a larger Liberal presence.&lt;br /&gt;&lt;br /&gt;11 years in government is a long time and there is always the argument for a change.  So what happens now?  Labor have pledged to abolish work choices, ratify Kyoto and start an education revolution.  I'll await the outcomes and pass judgement in the future.  One thing that worries me slightly  is that I've never been a fan of unions and Labor is heavily union oriented.  Hopefully abolition of work choices will not stifle innovation and job creation but we'll have to wait and see on that one.&lt;br /&gt;&lt;br /&gt;Finally, since the election loss, the former Treasurer, Peter Costello and the deputy Liberal party leader have stood down from the front line of politics.  Hopefully there will not be a vacuum in the Liberal coalition which prevents a strong opposition to the Rudd government as in any democracy, the opposition is cruicial in keeping the government in check.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9217713084069857387-8228108419565018504?l=davidhorton100.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://davidhorton100.blogspot.com/feeds/8228108419565018504/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9217713084069857387&amp;postID=8228108419565018504' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/8228108419565018504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/8228108419565018504'/><link rel='alternate' type='text/html' href='http://davidhorton100.blogspot.com/2007/11/kevin-07-rudd-sweeps-to-victory-in.html' title='Kevin &apos;07 - Rudd sweeps to victory in Australian election'/><author><name>David Horton</name><uri>http://www.blogger.com/profile/13905138566602021377</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-9217713084069857387.post-2426637556260417774</id><published>2007-11-26T17:42:00.000+11:00</published><updated>2007-11-26T17:56:05.062+11:00</updated><title type='text'>The first of many inconsequential ramblings</title><content type='html'>Back in July 07, I decided to jump on the blogging bandwagon and registered for blogger...&lt;br /&gt;&lt;br /&gt;...and that's where my blogging adventure has stalled to date.&lt;br /&gt;&lt;br /&gt;So, on this glorious spring evening in Sydney, whilst waiting for a call to pick up my wife from the airport, I decided to tackle the task that has eluded my attention for some 5 months.&lt;br /&gt;&lt;br /&gt;Why the delay?  Is it a lack of ideas?  Or possibly a lack of time?  I'd like to think the latter but I'll let others be the judge of that.&lt;br /&gt;&lt;br /&gt;So, in the interests of democracy - there's a nice segue into one of the potential topics - I'm going to give you, the reader the opportunity to decide on the subject of the next inconsequential rambling.&lt;br /&gt;&lt;br /&gt;Here's the initial two options, as you can see, vastly different subjects:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Swing applications in the current world&lt;/li&gt;&lt;li&gt;Australia Election 2007&lt;/li&gt;&lt;/ul&gt;So, you have until I have finished making a cup of coffee, or grabbed a beer - haven't decided which yet - to comment on this post to let me know which you'd prefer.&lt;br /&gt;&lt;br /&gt;Yes, I know this is a shameless attempt to drive traffic to this inaugural posting but there you have it.&lt;br /&gt;&lt;br /&gt;Clock's ticking....&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9217713084069857387-2426637556260417774?l=davidhorton100.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://davidhorton100.blogspot.com/feeds/2426637556260417774/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9217713084069857387&amp;postID=2426637556260417774' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/2426637556260417774'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9217713084069857387/posts/default/2426637556260417774'/><link rel='alternate' type='text/html' href='http://davidhorton100.blogspot.com/2007/11/first-of-many-inconsequential-ramblings.html' title='The first of many inconsequential ramblings'/><author><name>David Horton</name><uri>http://www.blogger.com/profile/13905138566602021377</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>
