<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' version='2.0'><channel><atom:id>tag:blogger.com,1999:blog-11993899</atom:id><lastBuildDate>Wed, 23 Jul 2008 12:50:09 +0000</lastBuildDate><title>Richard's technical notes</title><description/><link>http://blog.spiralarm.com/richard/</link><managingEditor>noreply@blogger.com (Richard)</managingEditor><generator>Blogger</generator><openSearch:totalResults>52</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-6651171266646417314</guid><pubDate>Wed, 23 Jul 2008 06:06:00 +0000</pubDate><atom:updated>2008-07-23T09:52:26.046+01:00</atom:updated><title>Scala London Coding Dojo</title><description>&lt;a href="http://www.flickr.com/photos/d6y/2689665763/" title="Gareth is at the keyboard by d6y, on Flickr"&gt;&lt;img src="http://farm4.static.flickr.com/3199/2689665763_276ff4ce28.jpg" width="500" height="375" alt="Gareth is at the keyboard" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://upcoming.yahoo.com/event/812966/"&gt;Monday&lt;/a&gt; was the first &lt;a href="http://www.nabble.com/-scala--LSUG-ThoughtWorks-Code-Dojo-on-21-July-p18112754.html"&gt;Scala London User Group meeting&lt;/a&gt; that was held around a keyboard. &lt;a href="http://www.linkedin.com/pub/2/100/4aa"&gt;Robert Rees&lt;/a&gt; arranged for a room, food, and drink at &lt;a href="http://www.thoughtworks.com/"&gt;ThoughtWorks&lt;/a&gt;, &lt;a href="http://sygneca.com/"&gt;Jamie Webb&lt;/a&gt; kindly gave an intro to Scala talk, and Aaron Roth provided print outs of a &lt;a href="http://blogs.sun.com/sundararajan/entry/scala_for_java_programmers"&gt;Scala for Java Programmers cheat sheet&lt;/a&gt;...and so we spent time working on the &lt;a href="http://codekata.pragprog.com/2007/01/code_kata_one_s.html"&gt;supermarket problem&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I counted 19 people (of which 3 were Brighton based), of mixed abilty (from functional people or Java people who had never touched Scala, all the way to expert Scala-heads), and we had working, unit tested, software by 10pm. Which—given that coding dojos &lt;a href="http://www.codingdojo.org/cgi-bin/wiki.pl?WhatIsCodingDojo"&gt;sound a bit mad&lt;/a&gt;—is pretty good going.&lt;br /&gt;&lt;br /&gt;Dojos are probably not going to be the way forward for this group, but I think it did a good job as an ice-breaker: an inclusive activity; a task that's not daunting, that anyone can have a crack at. I definitely learnt stuff: testing using &lt;a href="http://code.google.com/p/specs/"&gt;Specs&lt;/a&gt;, and need to understand the Scala patterns, such as &lt;a href="http://scala.sygneca.com/patterns/component-mixins"&gt;Cake&lt;/a&gt; for dependency injection, and I have to stop putting off looking at &lt;a href="http://liftweb.net/"&gt;Lift&lt;/a&gt;. Perhaps the most important thing for me was to learn that the Eclipse Scala plugin is going to be able to do mixed compilation of Java and Scala source in a project.&lt;br /&gt;&lt;br /&gt;There was video of Jamies talk. I'll add a link if it's posted any place. At the moment there's no web site for lsug but &lt;a href="http://www.spiralarm.com/view/contactUs"&gt;get in touch&lt;/a&gt; if you'd like the mailing list email address.&lt;br /&gt;&lt;br /&gt;There are more &lt;a href="http://www.flickr.com/photos/tags/lsug/"&gt;photos on Flickr tagged with lsug.&lt;/a&gt;</description><link>http://blog.spiralarm.com/richard/2008/07/scala-london-coding-dojo.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-3391925623791450728</guid><pubDate>Sat, 14 Jun 2008 10:09:00 +0000</pubDate><atom:updated>2008-07-23T09:59:03.540+01:00</atom:updated><title>Comparing closures in Java, Groovy and Scala</title><description>On &lt;a href="http://www.goulbourn.com"&gt;Paul&lt;/a&gt;'s return from JavaOne this year, we spoke about &lt;a href="http://gafter.blogspot.com/"&gt;Neal Gafter&lt;/a&gt;'s Closures Cookbook talk.  From what I understood, this was a look at the &lt;a href="http://www.javac.info/"&gt;BGGA closures proposal&lt;/a&gt;, and contained an example that pushed hard on some of the tougher closure issues for Java.  I thought it might be fun to look at the Java example from the talk, and covert it to &lt;a href="http://www.scala-lang.org/"&gt;Scala&lt;/a&gt; and &lt;a href="http://groovy.codehaus.org/"&gt;Groovy&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Why those languages?  Because they are the three &lt;a href="http://en.wikipedia.org/wiki/Java_Virtual_Machine"&gt;JVM&lt;/a&gt; languages I'm most interested in.  I suppose I could also have compared the closure support in &lt;a href="http://www.jython.org/Project/"&gt;Jython&lt;/a&gt;, &lt;a href="http://jruby.codehaus.org/"&gt;JRuby&lt;/a&gt; or... well, there are &lt;a href="http://en.wikipedia.org/wiki/JVM_Languages"&gt;a few to choose from&lt;/a&gt;, but this blog is going to be plenty long enough with just three. &lt;br /&gt;&lt;br /&gt;Let's start with the Java example that was given, remembering that this is a proposed syntax, that may or may not make it to Java 7 or later.  As I understood the example it was this: imagine you want to add the ability to time a block of code, and you wanted to do it in a way that would look almost like a new keyword has been added to the language; and you wanted to pass in a parameter to name what you were timing; and the block you're timing returns a result, or might throw an exception.  So, quite an involved case.  &lt;br /&gt;&lt;br /&gt;Here's how the current Java proposal looks:&lt;br /&gt;&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;// Here's a method that uses the time call:&lt;br /&gt;int f() throws MyException { &lt;br /&gt;  time("opName", {=&gt; &lt;br /&gt;    // some statements that can throw MyException &lt;br /&gt;  }); &lt;br /&gt;  time("opName", {=&gt; &lt;br /&gt;    return ...compute result...; &lt;br /&gt;  }); &lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;So we're timing a couple of operations, and we're doing this inside a method, &lt;code&gt;f&lt;/code&gt;, that returns an integer.  The implementation would be....&lt;br /&gt;&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;interface Block&lt;R, throws X&gt; { &lt;br /&gt;  R execute() throws X; &lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;public &lt;R, throws X&gt; R time( &lt;br /&gt;    String opName, Block&lt;R, X&gt; block) throws X { &lt;br /&gt;  long startTime = System.nanoTime(); &lt;br /&gt;  boolean success = true; &lt;br /&gt;  try { &lt;br /&gt;    return block.execute(); &lt;br /&gt;  } catch (final Throwable ex) { &lt;br /&gt;    success = false; &lt;br /&gt;    throw ex; &lt;br /&gt;  } finally { &lt;br /&gt;    recordTiming( &lt;br /&gt;      "opName", System.nanoTime() - startTime, success); &lt;br /&gt;  } &lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;As you can see, &lt;code&gt;time&lt;/code&gt; takes an arbitrary text label and a block of code, runs the block and tells you how long the block took to run and if it succeeded or not. &lt;br /&gt;&lt;br /&gt;That's the example that was given at JavaOne.  Now for the same thing in Groovy...&lt;br /&gt;&lt;br /&gt;To make runnable code for Groovy (and for Scala), I had to decided to time something.  So I'm timing a block of code that randomly throws an exception or returns something.  And then timing a block of code that just returns a number.  In Groovy that would be:&lt;br /&gt;&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;def time(opname, block)&lt;br /&gt;{ &lt;br /&gt; long start_time = System.nanoTime()&lt;br /&gt; boolean success = true&lt;br /&gt; try {&lt;br /&gt;  return block()&lt;br /&gt; } catch (Throwable ex) {&lt;br /&gt;  success = false;&lt;br /&gt;  throw ex&lt;br /&gt; } finally {&lt;br /&gt;  diff = System.nanoTime() - start_time&lt;br /&gt;  println "$opname $diff $success"&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int f() throws Exception {&lt;br /&gt; time("a") { &lt;br /&gt;  Random r = new Random()&lt;br /&gt;  if (r.nextInt(100) &gt; 50)&lt;br /&gt;   throw new IOException("Boom")&lt;br /&gt;  else&lt;br /&gt;   return 42&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt; time("b") {&lt;br /&gt;  return 7&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;println f()&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;An example of running the code:&lt;br /&gt;&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;$ groovy time.groovy &lt;br /&gt;a 37116000 true&lt;br /&gt;b 69000 true&lt;br /&gt;7&lt;br /&gt;&lt;br /&gt;$ groovy time.groovy &lt;br /&gt;a 39998000 false&lt;br /&gt;Caught: java.io.IOException: Boom&lt;br /&gt; at time$_f_closure1.doCall(time.groovy:21)&lt;br /&gt; at time$_f_closure1.doCall(time.groovy)&lt;br /&gt; at time.time(time.groovy:6)&lt;br /&gt; at time.f(time.groovy:18)&lt;br /&gt; at time.run(time.groovy:31)&lt;br /&gt; at time.main(time.groovy)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Note that the Java example is typed in that it uses a generic type, &lt;code&gt;R&lt;/code&gt;, for the return value which gives you some compile-time checks. That is, when you run &lt;code&gt;time&lt;/code&gt; and use the result, the compiler will enforce that your declaration of the result has the same type as the return type of the block you're timing.  &lt;br /&gt;&lt;br /&gt;Although &lt;a href="http://groovy.codehaus.org/Generics"&gt;Groovy does support generics&lt;/a&gt;, I've not used them here, and as a result the Groovy example doesn't have that type-safety.  I think that's the way one would typically write Groovy code.&lt;br /&gt;&lt;br /&gt;UPDATE: as was pointed out to me in the comments on the &lt;a href="http://java.dzone.com/articles/comparing-closures-java-groovy"&gt;Java Lobby version of this blog post&lt;/a&gt;, this isn't the same as the Java version.  In the Java version a &lt;code&gt;return&lt;/code&gt; in the closure returns out of the enclosing block.&lt;br /&gt;&lt;br /&gt;Now a look at the same code in Scala:&lt;br /&gt;&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;def time[R](opname: String)(block: =&gt; R) = {&lt;br /&gt; val start_time = System.nanoTime()&lt;br /&gt; var success = true&lt;br /&gt; try {&lt;br /&gt;  block&lt;br /&gt; } catch {&lt;br /&gt;  case ex: Throwable =&gt; {&lt;br /&gt;   success = false;&lt;br /&gt;   throw ex&lt;br /&gt;   }&lt;br /&gt; } finally {&lt;br /&gt;  val diff = System.nanoTime() - start_time&lt;br /&gt;  println(opname + " " + diff + " "+success)&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def f():Integer = {&lt;br /&gt;&lt;br /&gt; val answer = time("a") {&lt;br /&gt;  val r = new Random()&lt;br /&gt;  if (r.nextInt(100) &gt; 50)&lt;br /&gt;   throw new java.io.IOException("Boom")&lt;br /&gt;  else&lt;br /&gt;       "42" &lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; println ("the answer, "+answer+" is of type "+&lt;br /&gt;      answer.getClass())&lt;br /&gt;&lt;br /&gt; val seven:Integer = time("b") {&lt;br /&gt;  7&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; println ("seven is of type "+seven.getClass())&lt;br /&gt; &lt;br /&gt; return seven &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;f()&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;I'm still not using Scala day-to-day, so this might be a little awkward: thank you to the London Scala User Group for helping me clean up my syntax, but all the mistakes are mine.  &lt;br /&gt;&lt;br /&gt;This code has the same properties as the Java code (type safety via the &lt;code&gt;R&lt;/code&gt; generic type), but seems a little shorter and neater.  Additionally, the thing I like about the Scala code (and the Groovy code) is that the languages return the value of the last statement in a block, and that the syntax allows a clean &lt;code&gt;time("thing") { ... }&lt;/code&gt; format.&lt;br /&gt;&lt;br /&gt;One observation: I've used the &lt;code&gt;Integer&lt;/code&gt; class, which is deprecated, in order to be able to print out the class of the return type in the function &lt;code&gt;f()&lt;/code&gt;.  Without the &lt;code&gt;:Integer&lt;/code&gt; declaration I was getting weird compile errors.  As I said, my understanding of Scala and type inference isn't there yet.&lt;br /&gt;&lt;br /&gt;The output from running the code:&lt;br /&gt;&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;a 913000 true&lt;br /&gt;the answer, 42 is of type class java.lang.String&lt;br /&gt;b 13000 true&lt;br /&gt;seven is of type class java.lang.Integer&lt;br /&gt;&lt;br /&gt;a 936000 false&lt;br /&gt;java.io.IOException: Boom&lt;br /&gt; at Main$$anonfun$1.apply((virtual file):26)&lt;br /&gt; at Main$$anonfun$1.apply((virtual file):23)&lt;br /&gt; at Main$.time$1((virtual file):8)&lt;br /&gt; at Main$.f$1((virtual file):23)&lt;br /&gt; at Main$.main((virtual file):44)&lt;br /&gt; at Main.main((virtual file))&lt;br /&gt;// rest of stack trace removed&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;There's no conclusions here.  It's just an exercise in comparing closures code in three different languages.  I've probably missed some of the nuances of the Java example, but hey... it's a starting point.</description><link>http://blog.spiralarm.com/richard/2008/06/comparing-closures-in-java-groovy-and.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-5653980799438730368</guid><pubDate>Tue, 13 May 2008 08:34:00 +0000</pubDate><atom:updated>2008-05-13T13:25:26.805+01:00</atom:updated><title>Mobile Monday: Monetisation through Advertising</title><description>&lt;a href="http://www.flickr.com/photos/d6y/2489464226/" title="Mobile Monday by d6y, on Flickr"&gt;&lt;img src="http://farm4.static.flickr.com/3274/2489464226_6c8688fa34_m.jpg" width="240" height="164" alt="Mobile Monday" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Last night I was at &lt;a href="http://mobilemonday.org.uk/"&gt;Mobile Monday London&lt;/a&gt; to catch four presentations.  The topic: advertising on mobile. The summary: there's a need for better measurement.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.linkedin.com/pub/3/820/896"&gt;Claire Valoti&lt;/a&gt; from Mindshare was up first, giving the agency view of mobile advertising.  She split the appeal of mobile in a media plan in to two parts: as a delivery mechanic (to extended reach, getting to a winder audience in a different mode); and as a platform (for couponing, or video uploads).  She then went on to describe some issues and themes... and standardization and measurement were pretty much top of the list.  That is, there's currently no good standard measure of reach, sessions, traffic or users for mobile advertising.  And even if there was, it needs to be integrated into existing web buying systems, rather than via a mobile-specific system. &lt;br /&gt;&lt;br /&gt;Claire had a good observation on social networking, and the importance for mobile.  The m:metrics numbers quoted showed that the 18-24 and 25-34 age groups were more likely to be using social networking from the mobile, compared to 13-17 age group.  It's not just about a youth market.&lt;br /&gt;&lt;br /&gt;Another good point was made that events drive handset usage, as does "the right handset".  An example given: at the end of the football (soccer) season, there's a drop in usage; during the season people are out and about and will use the mobile internet to look up news.   As for "the right device", just look at &lt;a href="http://arstechnica.com/journals/apple.ars/2008/03/18/iphone-crushes-competition-in-smartphone-usage"&gt;the figures&lt;/a&gt; for internet usage on the iPhone compared to anything else....&lt;br /&gt;&lt;br /&gt;Obviously mobile advertising has to be used in the context of the whole campaign, and it has to be relevant content: don't go taking an ad made for TV and slapping it on a mobile.   Use the right techniques to get reach (banners, SMS, bluetooth), use location information to make it relevant, use coupons and free content to make it useful to the customer.  And the user experience needs to be more streamlined: don't issue mobile coupons without telling your retail staff how to handle them.&lt;br /&gt;&lt;br /&gt;Aside from measurement, another barrier to growing advertising budgets is the number of people involved in setting up a mobile campaign.  The buying experience needs to be more streamlined.&lt;br /&gt;&lt;br /&gt;Mobile advertising challenges were summarized as: speed, reach, cost, ROI, standards, and measurement.  As examples of reach issues: Claire was interested in QR codes, but only 10% of mobile devices have a reader installed;   buying from Blyk or similar to get an audience was described as having "limited reach" at the moment;  mobile search  needs to scale up as, right now, it's hard to spend the budget.&lt;br /&gt;  &lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.linkedin.com/pub/1/5b4/a7a"&gt;Shan Henderson&lt;/a&gt; from Vodafone kicked off his presentation by saying that it's the metrics that matter.  Click rate is not the full story, but it's often the headline.  Also audience demographic, behaviour, session length, frequency and reach are all important because "money follows measurement in media".  He showed the "measurement gap" graph.  I'm sure the slides will be available soon, but for now I've done a shaky recreation:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/d6y/2489490412/" title="measurement gap by d6y, on Flickr"&gt;&lt;img src="http://farm4.static.flickr.com/3090/2489490412_6a26c07bd5.jpg" width="500" height="375" alt="measurement gap" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;(I'm guessing &lt;a href="http://www.edwardtufte.com/tufte/"&gt;Edward Tufte&lt;/a&gt; would not approve).  So, we all agree it seems: we need better standards for measurement and more efficency in the buying and selling of advertising in order for the market to grow.&lt;br /&gt;&lt;br /&gt;To address this, Shan went on to describe the &lt;a href="http://www.gsmworld.com/news/press_2008/press08_11.shtml"&gt;GSMA Metrics Study&lt;/a&gt; which aims to make it easy to plan and measure mobile media. Later this year it's going to produce (one or more of): guidelines, best practices, definitions, technical standards, responsible ad practices, content standards. This will all be via an as yet unnamed ABC-like trusted independent organization.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.linkedin.com/in/russellbuckley"&gt;Russell Buckley&lt;/a&gt; took the stage to talk about Admob, a self-serve and full-service ad network, shifting 2.bn ads a month, in 160 countries via 3000 mobile web sites.  They select mobile sites, put ads on them, and share the revenue with the site.    He described mobile advertising as good for: bands; to promote mobile websites; for operators to monetize their sites; and content owners to have access to a new marketing channel.&lt;br /&gt;&lt;br /&gt;There was then a page of logos of who's advertising, and it showed that the US is generally ahead in terms of adopting mobile advertising.  In fact, ad requests by country (to March) showed 47% of ads were for the USA.  Other figures were: India (9.8%); UK (6.7%); South Africa (5.3%); Indonesia (4.7%); Romania (1.9%); Canada (1.3%); Philippines (1.3%); France (1%); Israel (1%); RoW (20.1%).  By handset, Nokia were the top, although they are dropping: something that's not yet reflected in their market share.&lt;br /&gt;&lt;br /&gt;Russell presented some case studies.  MTV wanted to drive traffic to an awards site, and using text adverts they had a 300% traffic boost and 400% increase in downloads. Land Rover USA saw 23% of users interacting with an advertised landing page, with 3% going on to click the link to make a call to a dealer. Adidas saw a CTR of "well above 3%".  Coca-Cola saw a CTR of 1.31%, but 130% watched a mobile video that was being promoted (some people watched it more than once).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bango.com"&gt;Ray Anderson from Bango&lt;/a&gt; described the basic model for using advertising as: select a channel, measure response, look at user purchases,   analyse ROI, then... repeat.&lt;br /&gt;&lt;br /&gt;He made some great observations on the issues of search.  Depending on the combinations of search provider and operator, you may find you get very different results from the advertising spend (especially if the content is transcoded).  But he had a graph that compared the revenue Bango customers had received over time from Orange and Vodafone: the doubling (or more) in the graphs when the operators introduced a search page was impressive.&lt;br /&gt;&lt;br /&gt;After the talks there was a brief panel session.  All good stuff.  And held in a great building.&lt;br /&gt;&lt;br /&gt;Photos: &lt;a href="http://www.flickr.com/photos/route79/tags/momolondon/"&gt;from Route79&lt;/a&gt;, &lt;a href="http://www.flickr.com/photos/torgo/"&gt;from appelquist&lt;/a&gt;, &lt;a href="http://www.flickr.com/photos/alexcraxton/sets/72157605031653604/"&gt;from Alex Craxton&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Video and audio: usual appear on the &lt;a href="http://mobilemonday.org.uk/"&gt;Mobile Monday web site&lt;/a&gt; after a little while, so check there.</description><link>http://blog.spiralarm.com/richard/2008/05/mobile-monday-monetisation-through.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-6332708407287992362</guid><pubDate>Sun, 13 Apr 2008 11:48:00 +0000</pubDate><atom:updated>2008-04-23T19:32:34.492+01:00</atom:updated><title>Decrypting JetS3t Files</title><description>This post is going to be a bit niche.  The scenario is that you've used &lt;a href="http://jets3t.s3.amazonaws.com/index.html"&gt;JetS3t&lt;/a&gt; to backup data to &lt;a href="http://www.amazon.com/gp/browse.html?node=16427261"&gt;Amazon S3&lt;/a&gt; via the &lt;a href="http://jets3t.s3.amazonaws.com/applications/synchronize.html"&gt;synchronize&lt;/a&gt; tool, and in particular you've used the &lt;code&gt;-c&lt;/code&gt; option to encrypt the data.  But you've downloaded the file with another tool, such as &lt;a href="http://www.binarynights.com/"&gt;ForkLift&lt;/a&gt; or &lt;a href="http://people.no-distance.net/ol/software/s3/"&gt;S3 Browser&lt;/a&gt;.  How do you decrypt the downloaded file?&lt;br /&gt;&lt;br /&gt;The default encryption is PBEWithMD5AndDES, and with that knowledge you may be able to find a tool that can decrypt it for you.  I went a different way, and just hooked straight into the encryption utilities inside JetS3t:&lt;br /&gt;&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;// Apache 2 license &lt;br /&gt;public static void main(final String... args) &lt;br /&gt;    throws GeneralSecurityException, IOException&lt;br /&gt;    {&lt;br /&gt;      &lt;br /&gt;        if (args.length != 4 &amp;&amp; args.length != 2)&lt;br /&gt;        {&lt;br /&gt;            System.err.println(&lt;br /&gt;              "Usage: Decrypt [-alg algorithm] KEY FILE");&lt;br /&gt;            System.exit(1);&lt;br /&gt;        }&lt;br /&gt;   &lt;br /&gt;        final String alg;&lt;br /&gt;        final String key;&lt;br /&gt;        final File encryptedFile;&lt;br /&gt;        &lt;br /&gt;        if (args.length == 4)&lt;br /&gt;        {&lt;br /&gt;            alg = args[1];&lt;br /&gt;            key = args[2];&lt;br /&gt;            encryptedFile = new File(args[3]);&lt;br /&gt;        }&lt;br /&gt;        else // use defaults for algorithm:&lt;br /&gt;        {&lt;br /&gt;            alg = "PBEWithMD5AndDES";&lt;br /&gt;            key = args[0];&lt;br /&gt;            encryptedFile = new File(args[1]);&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        final EncryptionUtil eu = new EncryptionUtil(&lt;br /&gt;                key, alg, EncryptionUtil.DEFAULT_VERSION);&lt;br /&gt;        &lt;br /&gt;        CipherInputStream decrypt=null;&lt;br /&gt;        BufferedOutputStream outStream=null;&lt;br /&gt;        try&lt;br /&gt;        {&lt;br /&gt;            decrypt = eu.decrypt(&lt;br /&gt;                 new FileInputStream(encryptedFile));&lt;br /&gt;            IOUtils.copy(decrypt, System.out);&lt;br /&gt;        }&lt;br /&gt;        finally&lt;br /&gt;        {&lt;br /&gt;            IOUtils.closeQuietly(decrypt);&lt;br /&gt;            IOUtils.closeQuietly(System.out);&lt;br /&gt;        }&lt;br /&gt;               &lt;br /&gt;    }&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;So with a bit of fiddling you can copy, paste and compile that (you'll need the JetS3t library and supporting JARs, plus &lt;a href="http://commons.apache.org/io/"&gt;Commons IO&lt;/a&gt;).  Or you can download &lt;a href="http://download.spiralarm.com/blog/richard/2008/04/jets3t-decrypt-dist.zip"&gt;jets3t-decrypt-dist.zip&lt;/a&gt;, which contains the source and the reqired libraries.  Once inside the ZIP you can run:&lt;br /&gt;&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt; java -jar Jets3tDecrypt.jar password encrypted.file &lt;br /&gt;                 &amp;gt; decrypted.file&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The libraries and the &lt;code&gt;Jets3tDecrypt.jar&lt;/code&gt; was packaged automatically by &lt;a href="http://www.netbeans.org/"&gt;Netbeans 6.1&lt;/a&gt;, which is a lovely touch from an IDE.</description><link>http://blog.spiralarm.com/richard/2008/04/decrypting-jets3t-files.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-5236164491613658880</guid><pubDate>Sun, 16 Mar 2008 16:18:00 +0000</pubDate><atom:updated>2008-03-16T16:47:59.477Z</atom:updated><title>QuickTime for Java</title><description>A few months ago I was experimenting with &lt;a href="http://developer.apple.com/quicktime/qtjava/"&gt;QuickTime for Java&lt;/a&gt;.  It's the binding between Apple's QuickTime "stuff" and the Java language, allowing a Java developer to invoke QuickTime on the Mac (and presumably also on Windows).  The reason this appeals is that we do Java, and have accumulated a fair amount of &lt;a href="http://www.apple.com/xserve/"&gt;Mac hardware&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;To cut a long story short, my limited experienced shows that QuickTime, when compared to the standard Java image libraries, produced smaller images of higher quality, faster.  It's unusual to get all three benefits together (smaller, faster, better).  Too good to be true, even, which leads me to think I've screwed up someplace, but I've not spotted it yet.  &lt;br /&gt;&lt;br /&gt;The particular test that interested me was was taking a camera phone photo, resizing it and rotating it.  Here's an example original:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/d6y/1168459141/" title="Jack: Wet dog by d6y, on Flickr"&gt;&lt;img src="http://farm2.static.flickr.com/1305/1168459141_17c8225b74.jpg" width="375" height="500" alt="Jack: Wet dog" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here's the rotation using tried-and-trusted &lt;a href="http://java.sun.com/j2se/1.4.2/docs/api/java/awt/geom/AffineTransform.html"&gt;AffineTransform&lt;/a&gt; plus &lt;a href="http://java.sun.com/j2se/1.4.2/docs/api/javax/imageio/ImageIO.html"&gt;ImageIO&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/d6y/2337987708/" title="javax.2d Dog by d6y, on Flickr"&gt;&lt;img src="http://farm4.static.flickr.com/3054/2337987708_93931dd8fe_o.jpg" width="320" height="240" alt="javax.2d Dog" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And here's the same transformation run through QuickTime for Java using the &lt;code&gt;GraphicsImporter&lt;/code&gt; and &lt;code&gt;Matrix&lt;/code&gt; objects:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/d6y/2337151889/" title="QT4J Dog by d6y, on Flickr"&gt;&lt;img src="http://farm4.static.flickr.com/3157/2337151889_4bb7049166_o.jpg" width="320" height="240" alt="QT4J Dog" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now, it's subtle but the QT4J image looks to have sharper colours, and seems to be a better representation of the original input.  It's also 20k compared to the 76k using the Java 2D libraries, and the code runs 1.7 times faster.  The downside: you need Apple hardware.  &lt;br /&gt;&lt;br /&gt;A few conclusions: it seems the Java 2D code doesn't just fall through to QuickTime on the Apple platform in any simple sense (which, I suppose I might have naively expected).  Second, I suspect there's a lot of tuning that can be done in the Java 2D client usage to improve the quality, but QT4J seems to have good defaults.  &lt;br /&gt;&lt;br /&gt;(Before you ask, the dog's name is Jack.)</description><link>http://blog.spiralarm.com/richard/2008/03/quicktime-for-java.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-4884598867884658748</guid><pubDate>Sun, 03 Feb 2008 14:44:00 +0000</pubDate><atom:updated>2008-02-05T18:04:31.404Z</atom:updated><title>Getting Started with Scala</title><description>Friday night was the first London &lt;a href="http://en.wikipedia.org/wiki/Scala_%28programming_language%29"&gt;Scala&lt;/a&gt; User Group meet-up, so it seems like the right time to say what I've learned so far about &lt;a href="http://www.scala-lang.org/"&gt;the language&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I'm not a functional programming person.  My background, pre-Java and C, was dominated by &lt;a href="http://en.wikipedia.org/wiki/POP-11"&gt;POP-11&lt;/a&gt; so it's fair to say I'm more comfortable with &lt;a href="http://en.wikipedia.org/wiki/Imperative_programming"&gt;imperative coding&lt;/a&gt; than anything else.  But that's kind of why Scala's a serious consideration for me: it doesn't force the functional stuff down your throat, but rather it's all there, object and functional, so you can pick and choose.&lt;br /&gt;&lt;br /&gt;Other compelling aspects of the language are: it runs on the JVM, which has had a huge engineering investment to make it as fast as it is today; has Java-like features, but looks like it lets you get your work done with less lines of code; and it's strongly typed. In other words, it's comfy for a Java person, while putting you in a position to use the funky actors and functional stuff, and maybe make even better use of those multi-core machines. &lt;br /&gt;&lt;br /&gt;Here's an example of less-lines-of-code thing.  In Java, the type-safe idiom for iterating over a map is:&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;final Map&amp;lt;String, String&amp;gt; map &lt;br /&gt;    = new HashMap&amp;lt;String, String&amp;gt;();&lt;br /&gt;map.put("dog", "woof");&lt;br /&gt;map.put("cat", "meow");&lt;br /&gt;&lt;br /&gt;for(Map.Entry&amp;lt;String, String&amp;gt; entry : map.entrySet())&lt;br /&gt;{&lt;br /&gt;  final String name = entry.getKey();&lt;br /&gt;  final String value = entry.getValue();&lt;br /&gt;  // do something with name and value here&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The same code, just as strongly typed, in Scala is:&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;val map = Map[String,String]("dog" -&gt; "woof", "cat" -&gt; "meow")&lt;br /&gt;for( (name,value) &lt;- map)&lt;br /&gt;{&lt;br /&gt; // do something with name and value here&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Or, if you wanted that last part could be: &lt;code&gt;map.foreach( (pair) =&gt; ...do something with pair._1 and pair._2 here.. )&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;If you're interested in getting into this stuff, I found it useful to start with &lt;a href="http://www.scala-lang.org/docu/files/ScalaTutorial.pdf"&gt;A Scala Tutorial for Java programmers PDF&lt;/a&gt;, then listen to &lt;a href="http://www.se-radio.net/podcast/2007-07/episode-62-martin-odersky-scala"&gt;Episode 62 of Software Engineering Radio&lt;/a&gt;, an interview with Martin Odersky on Scala (thanks to &lt;a href="http://happygiraffe.net/blog/"&gt;Dom&lt;/a&gt; for pointing that out to me).&lt;br /&gt;&lt;br /&gt;After that, I think the best place to go is into your wallet and buy a copy of &lt;a href="http://www.artima.com/shop/forsale"&gt;Programming in Scala: A comprehensive step-by-step guide&lt;/a&gt;.  It's a pre-print, with quite a few errors, but I'm pretty sure they'll get cleaned up soon and it'll be a great text.&lt;br /&gt;&lt;br /&gt;Tags: &lt;a rel="tag" href="http://technorati.com/tag/scala"&gt;scala&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;UPDATE: oops, I forgot to escape the &amp;lt; and &amp;gt; tags in the Java example above, which hid the generic types of the map. Fixed now.</description><link>http://blog.spiralarm.com/richard/2008/02/getting-started-with-scala.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-3936565180501618156</guid><pubDate>Wed, 02 Jan 2008 09:16:00 +0000</pubDate><atom:updated>2008-01-02T15:23:51.223Z</atom:updated><title>Android Developer Workshop</title><description>&lt;a href="http://www.flickr.com/photos/d6y/2117882768/" title="At android thing in London by d6y, on Flickr"&gt;&lt;img src="http://farm3.static.flickr.com/2232/2117882768_76e8e0d5c4.jpg" width="375" height="500" alt="At android thing in London" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Half-day workshops are great: you get away from distractions; get to ask questions and get quick answers to cover off those things that are bugging you; you're more-or-less forced to spend more time hands-on with a technology;  you get a sense of the buzz around something and which bits are good and bad; and... it's only half a day gone if it doesn't turn out that way.    For  those and other reasons I attended the Android Developer Workshop at Google London on 17th December 2007, hosted by &lt;a href="http://javaposse.com/"&gt;Dick Wall&lt;/a&gt;.  It did a fine job of highlighting the current state of Android and which areas are the important ones to focus on.&lt;br /&gt;&lt;br /&gt;The first thing that's very clear: you can get a lot done in Android in not a lot of code. &lt;br /&gt;&lt;br /&gt;If you're a Mac user the other thing you notice is that you can develop on a Mac without jumping through hoops.  It's almost like Google are treating the Mac as a first class citizen, and I can't tell you how convenient and wonderful that is.&lt;br /&gt;&lt;br /&gt;I've been playing around with some of the APIs and finding it all well documented already, and quite fun.  For my own reference, useful pages include: the &lt;a href="http://code.google.com/android/toolbox/optional-apis.html"&gt;optional APIs&lt;/a&gt; home page, the &lt;a href="http://code.google.com/android/reference/glossary.html"&gt;glossary&lt;/a&gt;, the &lt;a href="http://code.google.com/android/reference/classes.html"&gt;class index&lt;/a&gt;, the &lt;a href="http://code.google.com/android/intro/lifecycle.html"&gt;application lifecycle&lt;/a&gt;, and the &lt;a href="http://code.google.com/android/reference/android/app/Activity.html"&gt;activity lifecycle&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;It's new, so there are gaps in the documentation.  For example, when putting together an LBS application, you discover that the emulator supports mock data sources, but you need to dig around the mailing list to find out how to register them.  Say you have a KML file you want to use as a location provider called "brighton".  Call the file "kml"  then load that into the emulator from your shell with: &lt;code&gt;$ adb push kml /data/misc/location/brighton/kml&lt;/code&gt; and then restart the emulator.&lt;br /&gt;&lt;br /&gt;There's a lot that's not done yet or not figured out.  One nice idea is that there may be support for an XMPP-like server push.  That is, your Android app can listen out for server-generated Jabber-ish messages and do something.  How will that work in practice across the networks?  How will mobile clients be looked up and discovered?  We can guess at these things, but we don't yet know the answers.&lt;br /&gt;&lt;br /&gt;So, early days. For now we only have emulators, so we won't get much of a feel for how this will all pan out until there are at least a couple of handsets out there.  But it's powerful, well thought-out stuff.  If you're thinking about this space, I'd say it's at least worth spending a day working through the tutorial application.&lt;br /&gt;&lt;br /&gt;The event was recorded so I'd expect the video to show up somewhere on &lt;a href="http://www.youtube.com/AndroidDevelopers"&gt;YouTube&lt;/a&gt; one day.</description><link>http://blog.spiralarm.com/richard/2008/02/android-developer-workshop.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-6172350787188585472</guid><pubDate>Fri, 07 Dec 2007 11:24:00 +0000</pubDate><atom:updated>2007-12-07T15:58:51.446Z</atom:updated><title>Silverlight</title><description>I'm impressed with what I've heard about &lt;a href="http://silverlight.net/"&gt;Silverlight&lt;/a&gt;.   Microsoft put on an evening event in Brighton, bought a few beers, and tried to show Silverlight.  I say "tried" because it turned into an evening of question answering. Which was fine: I could have done with seeing more, but I guess I can find that online. &lt;br /&gt;&lt;br /&gt;Judging by the numbers, there are a lot of people interested in learning about the technology.  So what is it?  We were told it's not a "Flash killer", but you know what...  the differentiation between Silverlight and Flash is subtle, so comparisons to Flash are going to be difficult to avoid.  It's probably fair to say it's not a Flash killer yet, as Flash will have the edge in experience and capabilities for a while.   But beyond that, it's probably not a Flash killer because I suspect Silverlight doesn't care about Flash or competition from Flash.&lt;br /&gt;&lt;br /&gt;As of 1.0, Silverlight has gone after the prominent use case of Flash: video.  Microsoft are talking to content partners to create compelling stuff, which will lead to more downloads the plugin, which means a bigger market, which means more content produced, which means more downloads of the plugin, which means...spotted the pattern?  Good.&lt;br /&gt;&lt;br /&gt;With 2.0 (or is it 1.1?) Silverlight will be more capable, supporting development in the .NET languages.  This is the only differentiator from Flash that I heard all night: &lt;a href="http://aralbalkan.com/"&gt;Aral&lt;/a&gt; asked the question, and the answer was that Silverlight was going to appeal to the corporate developer, where Silverlight + .NET are going to be a natural fit for them.&lt;br /&gt;&lt;br /&gt;It looks like Microsoft have done a great job on the &lt;a href="http://www.microsoft.com/expression/"&gt;tooling&lt;/a&gt; (I've not actually tried the tools myself).  The workflow seems to be going from Illustrator or Expressions Design to XAML then adding behaviour via Expression Blend or Visual Studio and back to XAML for presentation.   The demo of the tools, although brief, hit the mark.  Sure you can only run them on Windows, but the point was made that you can fall back on editing the text (ouch).  Or third parties could work on editors for other platforms. &lt;br /&gt;&lt;br /&gt;This leads to some envy here, because over in the Java world we're still waiting to see the tooling, fast and light consumer VM, and plugins for &lt;a href="http://www.sun.com/software/javafx/index.jsp"&gt;JavaFX&lt;/a&gt;.   The Java GUI people have been producing some great UI content&amp;#8212;tellingly, the kind you don't normally associate with Java&amp;#8212;and they've been making all this easier. And yes, the Java Media people are initially targeting  (can you guess?) video playback.  So that's all great, and will presumably all be open source, although it'll be interesting to see how that plays out with the various patent issues over video . Still, as our glorious pony-tailed leader &lt;a href="http://blogs.sun.com/jonathan/entry/when_not_where"&gt;puts it&lt;/a&gt;: "this was the original vision behind the Java platform".  But it's frustrating watching a game of catch-up.  Whatever gets delivered is going to have to be very good: Adobe and Microsoft have set the standard.&lt;br /&gt;&lt;br /&gt;The overall impression is that Silverlight is well executed.  "What's the catch?" was one question.  I can only speculate at why Silverlight exists and what warning signs there might be:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Silverlight could be all about pushing Microsoft video formats.  So, for example, if you want to do properly controlled streaming, you're going to need to pay and use the Windows streaming products.  That's a shame as other streaming tools exist, other video formats exist, and would actually make Silverlight more compelling. &lt;/li&gt;&lt;li&gt;Silverlight is going to run on Vista, XP, Mac OS 10 and all the major Linux distributions via the Mono team's &lt;a href="http://en.wikipedia.org/wiki/Moonlight_%28runtime%29"&gt;Moonlight&lt;/a&gt; project.  That's a great intention, but be worried when you hear of any stories of delays to a release on a particular OS or spats between OS vendors because someone changed something, leading to finger pointing about why Silverlight doesn't work somewhere.&lt;/li&gt;&lt;li&gt;Content: this could be all about bringing RIAs and compelling content to Microsoft developers. In that case it's just breaking a Flash monopoly (no bad thing, and btw, it's not like it's a strong-armed kind of monopoly there: it's just that nothing else is as good as Flash at what it does). &lt;/li&gt;&lt;li&gt;Open source: Silverlight isn't, and that's important.  Not because of cost, but because of transparency and trust and standards.  It's easier to get screwed over when the product is directed and developed behind closed doors.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;But that speculation aside, it's striking in what's been achieved: a technology to watch and noodle with.  Hats off to &lt;a href="http://www.joshrussell.com/"&gt;Josh&lt;/a&gt; for organizing a great &lt;a href="http://upcoming.yahoo.com/event/322716/"&gt;event&lt;/a&gt;.</description><link>http://blog.spiralarm.com/richard/2007/12/silverlight.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-6338696225890414964</guid><pubDate>Thu, 22 Nov 2007 18:17:00 +0000</pubDate><atom:updated>2007-12-07T13:09:47.137Z</atom:updated><title>Future of Mobile, 2007</title><description>&lt;a href="http://www.flickr.com/photos/d6y/tags/futureofmobile/" title="Richard's future of mobile photos"&gt;&lt;img src="http://farm3.static.flickr.com/2104/2017938498_ed1f422b09.jpg" width="375" height="500" alt="Daniel Appelquist" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I was at a one-day conference last week, &lt;a href="http://www.future-of-mobile.com/"&gt;Future of Mobile&lt;/a&gt;, held at the IMAX at Waterloo, London.  Great idea to have a conference in a cinema: huge screen, good sound, comfy seats, cup holders.&lt;br /&gt;&lt;br /&gt;What follows are the remarks or thoughts I noted down...&lt;br /&gt;&lt;h4&gt;Consumers&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Mobile phone users are not consumers, but creators.  Phone calls, text messages are made up of a create and consume pair.  I've heard this a great deal lately, especially in the context of the iPhone.  There's clearly some truth in it, but I wonder for how long: if my phone has a music player in it, that's more consumption that creation.  If I'm browsing the web, that's consumption. If I'm updating a social networking site from my phone, or uploading a photo to Flickr, sure, that creating, but it's not unique to the phone.  Email and IM can also be a create and consume pair, and that's something you can do on the desktop or the handset.  I'm not sure the whole &lt;a href="http://dailybuzz.mobuzz.tv/shows/apple_vs_nokia_in_touch_phone"&gt;active v. passive consumers&lt;/a&gt; meme is terribly useful.&lt;/li&gt;&lt;li&gt;Mobile's combination of location plus attention is a unique advertising opportunity.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;Content creation&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;"Vodafone UK and Novarra are breaking the mobile web". (See &lt;a href="http://uk.techcrunch.com/2007/09/21/vodafone-in-mobile-web-storm/"&gt;TechCrunch&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;If you're anti One Web, Luca Passani's alternative to the W3C's &lt;a href="http://www.w3.org/TR/mobile-bp/"&gt;Mobile Web Best Practices&lt;/a&gt; will be something you'll want to read: &lt;a href="http://www.passani.it/gap/"&gt;Global Authoring Practices for the Mobile Web&lt;/a&gt;&lt;/li&gt;&lt;li&gt;One Web is about &lt;a href="http://www.w3.org/TR/mobile-bp/#tc"&gt;thematic consistency&lt;/a&gt;: "Ensure that content provided by accessing a URI yields a thematically coherent experience when accessed from different devices." &lt;/li&gt;&lt;li&gt;WURFL has 3,000 developers, and WALL (Wireless abstraction library - a markup system to help automatically output the right kind of markup for different devices) is going into a new version: WNG.  &lt;a href="http://www.slideshare.net/carsonified/luca-passani"&gt;Slides are available&lt;/a&gt; for that announcement.&lt;/li&gt;&lt;li&gt;.Mobi exists to "help the mobile web grow".  The Device Description Repository (DDR) &lt;a href="http://www.w3.org/2005/MWI/Activity"&gt;API&lt;/a&gt; is due in Dec 2007/Jan 2008, but isn't based on &lt;a href="http://wurfl.sourceforge.net/"&gt;WURFL&lt;/a&gt;.  The reason is that .mobi want to "add trust" and "add industry" to the API, protecting companies against possible royalty payments, and to provide confidence via a brand.&lt;/li&gt;&lt;li&gt;Google mobile search is currently terrible.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;Mobile AJAX&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Daniel Appelquist: Mobile Ajax will replace a class of application currently written in Java, will reduce time to market, open up the space to more developers, and result in more apps.&lt;/li&gt;&lt;li&gt;Challenges for mobile Ajax: access to device hardware, consequences of privacy control, need for developer guidelines.&lt;/li&gt;&lt;li&gt;Charles McCathieNevile: &lt;a href="http://www.ecmascript.org/"&gt;ECMAScript 4&lt;/a&gt; is a "proper programming language", which might help reduce the amount of battery power that Javascript consumes.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;Android&lt;/h4&gt;There was lots of interest in Android.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It's a full-stack mobile solution, and open source. Based on Linux 2.6, plus a hardware spec, apps, and Java.&lt;/li&gt;&lt;li&gt;Android exists to promote openness, build a loyal developer base, grow Google experience, and make handsets cheaper (software is 10% of the handset BOM).&lt;/li&gt;&lt;li&gt;Each application is a separate Linux process, and all apps are equal to the operating system.  It will include two-way synchronization (it'll be interesting to see how they've solved that problem).&lt;/li&gt;&lt;li&gt;Google are not worried about writing specs, and just wanted to write it and get the code out. &lt;/li&gt;&lt;li&gt;The architecture does allow for support of MIDP applications alongside Android applications. The Java implementation is &lt;a href="http://en.wikipedia.org/wiki/Dalvik_virtual_machine"&gt;Dalvik&lt;/a&gt;, plus a collection of useful Java &lt;a href="http://code.google.com/android/reference/packages.html"&gt;packages&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;The claim is that the richer APIs provided give more control compared to MIDP.&lt;/li&gt;&lt;li&gt;The system will be completely open source as soon as the first handset shipped. This isn't expected until late 2008.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Some of presentations have started to &lt;a href="http://www.slideshare.net/carsonified/slideshows"&gt;appear on SlideShare&lt;/a&gt;.</description><link>http://blog.spiralarm.com/richard/2007/11/future-of-mobile-2007.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-6384720290450965591</guid><pubDate>Mon, 22 Oct 2007 09:19:00 +0000</pubDate><atom:updated>2007-12-07T13:11:36.925Z</atom:updated><title>Watching Production Logs</title><description>I've always believed that production application error logs should be empty.  I've also implicitly assumed that any errors in live application logs are rare, freakish, occurrences, and on the whole of little relevance.  But... what would it take to get an empty error log? Or at least an error log that only contained truly anomalous events?&lt;br /&gt;&lt;br /&gt;You know what I mean, right? You sprinkle your code with &lt;code&gt;log.error("a bad thing happened", exception)&lt;/code&gt;, and during development and testing maybe you see them.  On your production machines you might be lucky enough to have someone who knows and watches the logs, or perhaps you occasionally look at the logs yourself: but on the whole they are ignored unless someone starts jumping up and down&amp;#8212;and then you take a look at the logs.&lt;br /&gt;&lt;br /&gt;Well, that's going to change for me.  I've now become addicted to having production application error messages sent to me by email (before you offer, no thanks: you can keep your own errors to yourself).   It's quite instructive to see messages in your mailbox the moment something odd happens in production.  &lt;br /&gt;&lt;br /&gt;Here's an trivial example of what you might see:&lt;div class="sourcecode"&gt;&lt;br /&gt;From:    whoever&lt;br /&gt;Subject:  [SMTPAppender] richard@toto error message&lt;br /&gt;Date:  19 October 2007 19:43:10 BDT&lt;br /&gt;To:    someone&lt;br /&gt;&lt;br /&gt;[2007-10-19 19:43:10,290]&lt;br /&gt;&lt;br /&gt;ERROR&lt;br /&gt;&lt;br /&gt;Test&lt;br /&gt;&lt;br /&gt;Caught an exception&lt;br /&gt;&lt;br /&gt;java.lang.NumberFormatException: For input string: "Hello world"&lt;br /&gt; at java.lang.NumberFormatException.forInputString&lt;br /&gt;   (NumberFormatException.java:48)&lt;br /&gt; at java.lang.Integer.parseInt(Integer.java:447)&lt;br /&gt; at java.lang.Integer.parseInt(Integer.java:497)&lt;br /&gt; at Test.main(Test.java:30)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The kinds of things we've seen so far are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A couple of spiders hitting URLs that that don't exist, but must once have been incorrectly published. &lt;/li&gt;&lt;li&gt;A user calling an action but not passing any parameters.  I'm thinking they've bookmarked something that ought to be bookmarkable, but isn't (what can I say: we didn't write all the code that we support).&lt;/li&gt;&lt;lI&gt;A plain good-old straight-forward bug in some background task that no-one would ever know was failing, but is now going to get fixed.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;I'm not telling you anything new here. I'm just saying that it's worthwhile trying.&lt;br /&gt;&lt;br /&gt;Setting this up with log4j is pretty straightforward. There's a good article over at &lt;a href="http://www.onjava.com/pub/a/onjava/2004/09/29/smtp-logging.html"&gt;ONJava.com&lt;/a&gt; that explains it.  All you need to do is configure the appender in log4j.xml (if you're using the .properties version, migrate to the .xml version first).  Here's an example:&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8" ?&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"&amp;gt;&lt;br /&gt;&amp;lt;log4j:configuration&amp;gt;&lt;br /&gt;    &amp;lt;appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"&amp;gt;&lt;br /&gt;        &amp;lt;param name="Target" value="System.out" /&amp;gt;&lt;br /&gt;        &amp;lt;layout class="org.apache.log4j.PatternLayout"&amp;gt;&lt;br /&gt;            &amp;lt;param name="ConversionPattern"&lt;br /&gt;              value="[%d{ISO8601}] %-5p %c %m %n" /&amp;gt;&lt;br /&gt;        &amp;lt;/layout&amp;gt;&lt;br /&gt;        &amp;lt;filter class="org.apache.log4j.varia.LevelRangeFilter"&amp;gt;&lt;br /&gt;            &amp;lt;param name="LevelMin" value="DEBUG"/&amp;gt;&lt;br /&gt;            &amp;lt;param name="LevelMax" value="INFO"/&amp;gt;&lt;br /&gt;        &amp;lt;/filter&amp;gt;&lt;br /&gt;    &amp;lt;/appender&amp;gt;&lt;br /&gt;    &amp;lt;appender name="STDERR"  class="org.apache.log4j.ConsoleAppender"&amp;gt;&lt;br /&gt;        &amp;lt;param name="Target" value="System.err" /&amp;gt;&lt;br /&gt;        &amp;lt;layout class="org.apache.log4j.PatternLayout"&amp;gt;&lt;br /&gt;            &amp;lt;param name="ConversionPattern"&lt;br /&gt;              value="[%d{ISO8601}] %-5p %c %m %n" /&amp;gt;&lt;br /&gt;        &amp;lt;/layout&amp;gt;&lt;br /&gt;        &amp;lt;filter class="org.apache.log4j.varia.LevelRangeFilter"&amp;gt;&lt;br /&gt;            &amp;lt;param name="LevelMin" value="ERROR"/&amp;gt;&lt;br /&gt;            &amp;lt;param name="LevelMax" value="FATAL"/&amp;gt;&lt;br /&gt;        &amp;lt;/filter&amp;gt;&lt;br /&gt;    &amp;lt;/appender&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;appender name="email"  class="org.apache.log4j.net.SMTPAppender"&amp;gt;&lt;br /&gt;        &amp;lt;param name="BufferSize" value="10" /&amp;gt;&lt;br /&gt;        &amp;lt;param name="SMTPHost" value="your host here" /&amp;gt;&lt;br /&gt;        &amp;lt;param name="SMTPUsername" value="optional username" /&amp;gt;&lt;br /&gt;        &amp;lt;param name="SMTPPassword" value="password if you need it" /&amp;gt;&lt;br /&gt;        &amp;lt;param name="From" value="whoever@blah" /&amp;gt;&lt;br /&gt;        &amp;lt;param name="To" value="someone@blah" /&amp;gt;&lt;br /&gt;        &amp;lt;param name="Subject" value="[SMTPAppender] &lt;br /&gt;             ${user.name}@${hostname} error message" /&amp;gt;&lt;br /&gt;        &amp;lt;layout class="org.apache.log4j.PatternLayout"&amp;gt;&lt;br /&gt;            &amp;lt;param name="ConversionPattern"&lt;br /&gt;              value="[%d{ISO8601}]%n%n%-5p%n%n%c%n%n%m%n%n" /&amp;gt;&lt;br /&gt;        &amp;lt;/layout&amp;gt;&lt;br /&gt;        &amp;lt;filter class="org.apache.log4j.varia.LevelRangeFilter"&amp;gt;&lt;br /&gt;            &amp;lt;param name="LevelMin" value="ERROR"/&amp;gt; &lt;br /&gt;            &amp;lt;param name="LevelMax" value="FATAL"/&amp;gt;&lt;br /&gt;        &amp;lt;/filter&amp;gt;&lt;br /&gt;    &amp;lt;/appender&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;root&amp;gt;&lt;br /&gt;        &amp;lt;level value="all" /&amp;gt;&lt;br /&gt;        &amp;lt;appender-ref ref="STDOUT"/&amp;gt;&lt;br /&gt;        &amp;lt;appender-ref ref="STDERR"/&amp;gt;&lt;br /&gt;    &amp;lt;appender-ref ref="email"/&amp;gt;&lt;br /&gt; &amp;lt;/root&amp;gt;&lt;br /&gt;&amp;lt;/log4j:configuration&amp;gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Yeah, yuck to look at, but it's pretty simple.  The part you want is the &lt;code&gt;SMTPAppender&lt;/code&gt; bit in the middle. Leave out the username and password param tags if your SMTP server doesn't require authentication. &lt;br /&gt;&lt;br /&gt;The XML above is almost the exact example from the ONJava.com article, except for a couple of items I needed.  The first is that I wanted the name of the user the application was running under, and also the hostname of the box the application was running on.   To do that, I've used a feature the fine log4j people included: environment properties substitution.  You'll see &lt;code&gt;${user.name}&lt;/code&gt; in the subject line, which is a standard &lt;a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/System.html#getProperties()"&gt;Java system property&lt;/a&gt;.  The &lt;code&gt;${hostname}&lt;/code&gt; is a property I provided to the application by starting it with &lt;code&gt;-Dhostname=`uname -n`&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;If you want to you can also dynamically modify the SMTP Appender at run time by iterating over the root logger, checking for an instance of SMTPAppender and then changing what you want.  If you do that, though, the clue you need is to call &lt;code&gt;appender.activateOptions()&lt;/code&gt; when you're done modifying the appender.</description><link>http://blog.spiralarm.com/richard/2007/10/watching-production-logs.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-8710027169277507672</guid><pubDate>Sat, 15 Sep 2007 15:36:00 +0000</pubDate><atom:updated>2007-12-07T13:10:43.935Z</atom:updated><title>BarCamp Brighton 2007</title><description>&lt;img src="http://farm2.static.flickr.com/1166/1351383687_e07bac362a.jpg?v=0" alt="Playing CSS Specificity Snap at BarCamp Brighton" width="375" height="500" /&gt;&lt;br /&gt;&lt;br /&gt;Tick... I've now attended a BarCamp.  I absolutely loved it: many topics + small groups = a great opportunity to learn and chat about &lt;a href="http://barcampbrighton.backnetwork.com/schedule/"&gt;lots of stuff&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;Some of the stuff I managed to sit in on, included:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;CSS Selectivity Snap.  Earlier in the day I'd jotted a reminder: "must learn more CSS properly", and then &lt;a href="http://binarytales.co.uk/"&gt;Jon Linklater-Johnson&lt;/a&gt; (pictured above, right) steps in with a fantastic crash course in selectivity. Huge fun. &lt;/li&gt;&lt;li&gt;&lt;a href="http://blog.snipperoo.com/"&gt;Jay Caines-Gooby&lt;/a&gt; chatting about backups.  Nice idea: grab a NAS drive, stick Linux on it, and then schedule syncing to S3.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.slideshare.net/tristanr/qrcodes"&gt;QR (quick response)&lt;/a&gt; codes, from &lt;a href="http://www.cogapp.com/home/tristan-roddis.html"&gt;Tristan Roddis&lt;/a&gt;.  I didn't know &lt;a href="http://en.wikipedia.org/wiki/QR_Code"&gt;QR codes&lt;/a&gt; were an ISO standard or that there were different variants.  I hope Tristan's laptop has recovered from the water spill :-( &lt;/li&gt;&lt;li&gt; An enlightening presentation called "Take my wallet but don't hurt my face: Teenagers &amp; the social web"  by Daniel Morris. Another presentation I learned a hell of a lot from: teenagers don't use mobile internet, don't send MMSs, and visit a bunch of web sites I've never heard of (of course). &lt;/li&gt;&lt;li&gt; "Building a recommendation engine from tagged content": it was great to see the inside of an application exposed in terms of how &lt;a href="http://www/worldreviewer.com"&gt;worldreviewer.com&lt;/a&gt; is handling user recommendations.  They're taking the tag cloud for users and for activities, and computing a &lt;a href="http://en.wikipedia.org/wiki/Dot_product"&gt;dot product&lt;/a&gt; to get a measure. The problem is that if you want to do this real-time the calculations get expensive quickly.  The solution being explored is to reduce the space to a fixed-size vector (manually at the moment, but they're looking to do some form of proper &lt;a href="http://en.wikipedia.org/wiki/Dimensionality_reduction"&gt;feature extraction&lt;/a&gt;). &lt;/li&gt;&lt;li&gt;Matthew Somerville's &lt;a href="http://www.dracos.co.uk/talks/barcamp-brighton/"&gt;Is Cornwall Part of England?&lt;/a&gt; talk was superb.  Turns out Cornwall probably has a case for an independent government, but best not to mention it.  &lt;a href="http://www.statutelaw.gov.uk/"&gt;Statutelaw.gov.uk&lt;/a&gt; looks a fun place to spend a few hours.&lt;/li&gt;&lt;li&gt;Behaviour driven development (BDD), which is "TDD done well".  Appears to be a good way to structure and express unit tests, and I need to go and check out &lt;a href="http://www.jdave.org/"&gt;JDave&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;I spoke about Mac OS X Server, which is something no-one seems to use.  I'll maybe write up my presentation at some point.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://www.madgex.com/"&gt;hosts&lt;/a&gt; and sponsors were enormously generous, and the organizers really pulled it all together well.  Thank you, &lt;a href="http://www.paulsilver.co.uk/"&gt;Paul&lt;/a&gt;, &lt;a href="http://www.businessbricks.co.uk/"&gt;Matt&lt;/a&gt;...well, so many people seemed to be making it happen.  Check out the &lt;a href="http://www.barcampbrighton.org/"&gt;blog&lt;/a&gt; and the &lt;a href=" http://barcamp.org/BarCampBrighton"&gt;wiki&lt;/a&gt; to get an idea of how many people were involved.&lt;br /&gt;&lt;br /&gt;The one particular memory I have is, surprisingly, not of the &lt;a href="http://www.flickr.com/photos/adactio/1347523232/"&gt;Champagne jelly&lt;/a&gt;. It's of sitting in a presentation on a warm summer's night. Through  the window drifted sounds of the young and beautiful people of Brighton starting their evening of partying, while inside a group of 10 or so geeks sat around discussing dating and how it could all be "fixed" with a large and elaborate XML schema.&lt;br /&gt; &lt;br /&gt;Label: &lt;a rel="tag" href="http://technorati.com/tag/barcampbrighton"&gt; barcampbrighton&lt;/a&gt;</description><link>http://blog.spiralarm.com/richard/2007/09/barcamp-brighton-2007.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-8975191161017514564</guid><pubDate>Wed, 12 Sep 2007 19:46:00 +0000</pubDate><atom:updated>2007-12-07T13:12:16.171Z</atom:updated><title>d.Construct 2007</title><description>&lt;img src="http://farm2.static.flickr.com/1304/1348419386_7e4a19f7e3.jpg?v=0" alt="Photo from Jane" width="500" height="335" /&gt;&lt;br /&gt;&lt;br /&gt;Fun and fulfilling is my quick review of &lt;a href="http://2007.dconstruct.org/"&gt;d.Construct&lt;/a&gt; this year.  No, wait. Cheap, fun and fulfilling. That's better. Sure, there are other ways to spend £85 in Brighton, but I doubt you'd get 8 hours of hot &lt;a href="http://en.wikipedia.org/wiki/User_experience"&gt;user experience&lt;/a&gt; action elsewhere.&lt;br /&gt;&lt;br /&gt;We've heard the gist plenty of times: &lt;a href="http://en.wikiquote.org/wiki/Jef_Raskin"&gt;As far as the customer is concerned, the interface is the product&lt;/a&gt;. Sitting in a room and hearing it in a variety of different ways can only do good.  And as it was less technical than &lt;a href="http://blog.spiralarm.com/richard/2005/11/dconstruct-2005.html"&gt;the previous d.Construct I attended&lt;/a&gt;, I could sit back and soak up the speaker's words.  &lt;br /&gt;&lt;br /&gt;As far as specifics go, the highlights for me were:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Having a vision statement, or an experience vision, for a &lt;i&gt;product&lt;/i&gt; is a good idea: it helps direct you, it helps measure progress, it helps guide you when having to make trade-offs. &lt;/li&gt;&lt;li&gt;Give up competing on features and technology, and instead compete on the experience.  That's my reading of Peter Merholz's &lt;a href="http://www.core77.com/reactor/06.07_merholz.asp"&gt;presentation&lt;/a&gt;. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Jane has a more complete &lt;a href="http://jane.dallaway.com/blog/2007/09/dconstruct-07.html"&gt;write-up of the day&lt;/a&gt;, and you'll find &lt;a href="http://www.flickr.com/photos/tags/dconstruct07/"&gt;all the photos&lt;/a&gt; in the usual place.&lt;br /&gt;&lt;br /&gt;Labels: &lt;a rel='tag' href="http://technorati.com/posts/tag/dconstruct07"&gt;dconstruct07&lt;/a&gt;</description><link>http://blog.spiralarm.com/richard/2007/09/dconstruct-2007.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-1863411568396314214</guid><pubDate>Fri, 17 Aug 2007 08:29:00 +0000</pubDate><atom:updated>2007-08-17T11:18:03.878+01:00</atom:updated><title>A Comment on Static Typing</title><description>There's a line of thought &lt;a href="http://memeagora.blogspot.com/2007/05/strong-typing-is-communist-bureaucracy.html"&gt;put forward by Neal Ford&lt;/a&gt; to help Java developers get over any hang-ups they may have with dynamic typing.  If you like compile-type checking of your types, maybe you're worried "that utter chaos would reign if we discard typing".  Neil's argument is that: (a) unit testing is good; (b) 100% code coverage is good; therefore static typing buys you nothing:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;"If you have pervasive testing, &lt;i&gt;static typing == more typing&lt;/i&gt;. The static typing is nothing but a requirement to type extraneous code to satisfy a compiler that isn't telling you anything interesting anymore."&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;It's a compelling argument ("[a]fter all, it's the tests that tell you if your code [is] correct or not"), but I think it hides more that it reveals.  My main concern is that the argument assumes there's the same amount of testing in both the dynamic and static cases.  That doesn't seem to be true: if the compiler is catching cases that you need to test for in a dynamic language, then that's more unit tests that need to be written.  &lt;br /&gt;&lt;br /&gt;Let me phrase this another way:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;If you have static typing, &lt;i&gt;dynamic typing == more testing&lt;/i&gt;. The dynamic typing is a requirement to type extraneous code to satisfy a code coverage tool that would otherwise have been caught by the compiler.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;That's not to knock dynamic languages (I know first-hand how damn productive Perl is): I'll use dynamic languages some times, and static languages other times and admire them for what each can do for me in different situations.  And it's not to support the idea that 100% code coverage is an achievable goal in practice.  It's just that Neal Ford's in principle argument doesn't work for me.</description><link>http://blog.spiralarm.com/richard/2007/08/comment-on-static-typing.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-1435056454613141016</guid><pubDate>Thu, 19 Jul 2007 11:11:00 +0000</pubDate><atom:updated>2007-12-07T13:12:52.506Z</atom:updated><title>Java Caching APIs</title><description>Last month I &lt;a href="http://upcoming.yahoo.com/event/186293/"&gt;attended&lt;/a&gt; a superb &lt;a href="http://skillsmatter.com/jboss-cache-manik-surtani"&gt;presentation on JBoss Cache&lt;/a&gt; by the project lead, &lt;a href="http://blogs.jboss.com/blog/manik/"&gt;Manik Surtani&lt;/a&gt;.   Luckily only six people showed up, so were were able to chat to Manik, and really pick his brains on this stuff.  Talking to Manik gave me a huge amount of confidence in the JBoss Cache product.&lt;br /&gt;&lt;br /&gt;Some background to all of this: we've all probably kept something that's frequently used, and infrequently changing, in memory to save a trip to a database.  That's one of the things you can use a cache like JBoss Cache for, but that are other benefits too: the preference for code that's been written elsewhere (many eyes etc); a smart way to do invalidation; a way to distribute a cache between servers; reporting tools... and so on. &lt;br /&gt;&lt;br /&gt;JBoss Cache isn't the only solution out there.  There are a bunch of APIs you can use to add caching into your application, and maybe one day the &lt;a href="http://jcp.org/en/jsr/detail?id=107"&gt;Java Temporary Caching API (JSR 107)&lt;/a&gt; standard will mean you can use one API across all the implementations.  I was wondering... how do they compare.  I decided to have  quick look at performance for three of the popular ones.&lt;br /&gt;&lt;br /&gt;I'm looking at:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; &lt;a href="http://labs.jboss.com/jbosscache/"&gt;JBoss Cache&lt;/a&gt;, version 2.0.0 RC3. LGPL license.&lt;/li&gt;&lt;li&gt; &lt;a href="http://jakarta.apache.org/jcs"&gt;JCS: Java Caching System&lt;/a&gt;, version 1.3. Apache license.&lt;/li&gt;&lt;li&gt; &lt;a href="http://ehcache.sourceforge.net/"&gt;Ehcache&lt;/a&gt;, version 1.3. Apache license.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;I have a scenario in mind, where there are a lot of cache hits and only a few cache stores.  In particular I wanted to know how the implementations perform under concurrent access, such as a heavily loaded web site: what happens to the cache performance as load increases.  &lt;br /&gt;&lt;br /&gt;To set the stage here's a graph showing the performance of a work load when using the ye olde synchronized &lt;code&gt;Hashtable&lt;/code&gt;, the spanky new &lt;code&gt;ConcurrentHashMap&lt;/code&gt; and a "noop" implementation that neither stores nor returns anything.  The idea here is just to provide a sanity check of how my laptop performs under increasing load.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://farm3.static.flickr.com/2096/2049224793_4d6137f7c5_o.jpg" alt="Throughput for hashmaps" width="645" height="319" /&gt;&lt;br /&gt;&lt;br /&gt;Here's what you're looking at.  Along the x-axis is the number of threads concurrently accessing the cache.  The y-axis is showing normalized throughput (so bigger is better on the y-axis), averaged over 5 runs.   What I've done is create a worker that picks a random number, looks in the cache to see if it's there, and if it's not it associates a list against the number.  There are only 400 numbers to pick from, and the worker tries this 40,000 times (weird numbers, but it's relevant to the application I have in mind).  Each thread equates to one worker, and all the workers share the same cache instance.  You can &lt;a href="http://blog.spiralarm.com/richard/2007/07/caching-compared-src.zip"&gt;download the source code for this&lt;/a&gt;, if you want the details.&lt;br /&gt;&lt;br /&gt;So focus on the orange curve in the middle first, which is the graph for my "noop" cache.  It's doing pretty much what you'd expect.  As the number of threads increases, the machine is able to perform more operations in the same amount of time, up to around 32 threads.  After that, performs starts to fall off.    &lt;br /&gt;&lt;br /&gt;The purple line tells you that you don't want to use a &lt;code&gt;Hashtable&lt;/code&gt; for concurrent access. There's a lot of synchronization and waiting happening (probably) as threads compete to access the shared object.&lt;br /&gt;&lt;br /&gt;The green line shows you that the concurrent APIs in Java have come a long long way since &lt;code&gt;Hashtable&lt;/code&gt;.  The &lt;code&gt;ConcurrentHashMap&lt;/code&gt; implementation is blazing fast and doesn't seem to suffer too badly under increasing load. In fact, it has a better throughput than my noop code (possibly because noop always causes both a get and a put on the cache).&lt;br /&gt;&lt;br /&gt;So much for the baseline measurements.  Now let's see what happens with the Java caching implementations:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://farm3.static.flickr.com/2258/2050011022_6f0a4e0fcb_o.jpg" alt="Throughput for Java cache APIs" width="637" height="283" /&gt;&lt;br /&gt;&lt;br /&gt;The first thing I need to say is that these tests are for local, non-replicated, non-transactional caching. I.e., it's the simplest case. I've also only done the bare minimum configuration on the caches to make them work. I'm sure they are tweekable.   Also note that the y-axis values are an order of magnitude lower than the baseline graph.&lt;br /&gt;&lt;br /&gt;It looks like JCS have really tuned the single thread case, but after that there's not a lot to choose between that and EHcache in terms of performance.  Neither seem to suffer under increasing thread load.  On the whole, I prefer the JCS API to the EHcahce one.  &lt;br /&gt;&lt;br /&gt;Don't be overly put off by the JBoss performance curve. Sure it looks a lot lower, but we're talking a total of 300ms difference at 4 threads for a total of 160,000 cache requests: there are bigger considerations that those performance measures.&lt;br /&gt;&lt;br /&gt;So the conclusion from all of this is... they're all pretty good. I was hoping one would run so badly I could rule it out, but that's not the case, and I'm going to have to look at features.   &lt;br /&gt;&lt;br /&gt;For the simple case, I'm going to opt for JCS based on these numbers; but beyond that the numbers tell you nothing of use.  For example, if you need transactional support, or want an object cache, then it has to be JBoss as that's the only one with those features.  Or you may prefer one API other the others in terms of style.&lt;br /&gt;&lt;br /&gt;As a final comment, do not trust these curves for replicated or distributed caches: the issues there in measuring performance add a lot of complexity.</description><link>http://blog.spiralarm.com/richard/2007/07/java-caching.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-3204470468938927585</guid><pubDate>Thu, 05 Jul 2007 11:43:00 +0000</pubDate><atom:updated>2007-07-05T13:13:24.275+01:00</atom:updated><title>Comments for Logging</title><description>Logging can become quite verbose.  I found myself writing a method in which most of the lines were logging related, which really clutters the code:&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;if (source == null)&lt;br /&gt;{&lt;br /&gt;   if (log.isDebugEnabled())&lt;br /&gt;   {&lt;br /&gt;      log.debug("No copy required as no source provided (dest \&lt;br /&gt;               was "+dest.getAbsolutePath()+")");&lt;br /&gt;   }&lt;br /&gt;   return;&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Possibly I'm over-logging, to try to avoid ever running a debugger.  But I was wondering if it'd be possible to do something so that I could turn on &lt;i&gt;logging of comments&lt;/i&gt; for a given method, class, package or whatever.  So if I'd written....&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;if (source == null)&lt;br /&gt;{&lt;br /&gt;    // No need to copy as no source directory provided when copying to dest&lt;br /&gt;    return;&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;...and there was some way to say "show me the comments as you execute", that would be as useful as my four lines of debugging.  You could even imagine this hypothetical tool could spot references in comments to variables in scope and do a &lt;code&gt;toString&lt;/code&gt; on them.&lt;br /&gt;&lt;br /&gt;This wouldn't replace logging (you'd still want error, info, fatal, etc), but it might be a useful piece of ease-of-use.   From what I can tell Java doesn't preserve comments in the bytecode, so it's not something easy to do.  But we have annotations and reflection and AOP and static analysis and assertions and all sorts of stuff, so there's probably some way to make it happen.</description><link>http://blog.spiralarm.com/richard/2007/07/comments-for-logging.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-4864927444750744367</guid><pubDate>Tue, 19 Jun 2007 09:20:00 +0000</pubDate><atom:updated>2007-12-07T13:13:38.328Z</atom:updated><title>Google Developer Day 2007</title><description>I was in London for the &lt;a href="http://code.google.com/events/developerday/uk-home.html"&gt;GD Day 2007&lt;/a&gt;.  I sat in on some pretty interesting sessions:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; &lt;a href="http://code.google.com/apis/gears/"&gt;Gears&lt;/a&gt; does indeed look impressive.  I was on the edge of my seat waiting to hear how they'd solved online-to-offline synchronization, but they explicitly backed out of that one: "What we've chosen to do for this initial release is not tackle the synchronization problem [...] overtime maybe there will be something that works for the 80% case, and if that happens I think it's going to come from the community". I can understand that, and it's probably a great opportunity for anyone who can solve that problem.  Worth catching &lt;a href="http://youtube.com/watch?v=HsODVUvgvdk"&gt;the video&lt;/a&gt;.  I'll also add that because it's open source, I wouldn't be surprised if the plugin was ported to mobile devices (Safari, after all, is already supported, so how far away can a mobile &lt;a href="http://webkit.org/"&gt;WebKit&lt;/a&gt; version be?). &lt;/li&gt;&lt;li&gt; Google have opened up their geolocation API.  I think this is absolutely huge for the UK, but right now it returns an error message for any UK address.  I learned that (a) it's going to be OK, it's just the post office dragging their feet over the legals; and (b) if you need the data, there's a hack to get it out of Google Local Search.&lt;/li&gt;&lt;li&gt; There was a presentation on porting a JSP site to GWT. The lesson seems to be that you start from scratch, but I did learn you can use Java to implement impressive Javascript behaviors (drag and drop, for example,) without writing any Javascript. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Go &lt;a href="http://youtube.com/googledeveloperday"&gt;watch the videos&lt;/a&gt;.</description><link>http://blog.spiralarm.com/richard/2007/06/google-developer-day-2007.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-7167386389231072476</guid><pubDate>Fri, 08 Jun 2007 09:03:00 +0000</pubDate><atom:updated>2007-11-20T11:40:18.189Z</atom:updated><title>Google London Open Source Jam 3</title><description>A couple of weeks ago I was over at the &lt;a href="http://www.red-bean.com/ospowiki/LondonOpenSourceJam03"&gt;Google London Open Source Jam 3&lt;/a&gt;, which was focused on Java.  I wasn't sure what to expect, but it turned out to be a series of five minute &lt;a href="http://www.red-bean.com/ospowiki/LondonOpenSourceJam03Talks"&gt;talks&lt;/a&gt;.  I'm not sure if that's normal or not for the Open Source Jam series.&lt;br /&gt;&lt;br /&gt;If I had to pick out one thing, I'd say take a look at the &lt;a href="http://jez.blip.tv/file/245696/"&gt;closures talk&lt;/a&gt;.  I'd thought closures for Java was on it's way to being sorted, but it turns out there are three proposals with pros and cons:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; &lt;a href="http://www.javac.info/"&gt;BGGA&lt;/a&gt; (Bracha, Gafter, Gosling, Ahe) &lt;/li&gt;&lt;br /&gt;&lt;li&gt; &lt;a href="http://crazybob.org/2006/10/java-closure-spectrum.html"&gt;CICE&lt;/a&gt; (Concise Inner Class Expressions) &lt;/li&gt;&lt;br /&gt;&lt;li&gt; &lt;a href="http://docs.google.com/View?docid=ddhp95vd_0f7mcns"&gt;FCM&lt;/a&gt; (First Class Method) &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;So more stuff to read and think about, then.&lt;br /&gt;&lt;br /&gt;A really good evening of listening and chatting to some good people, so thanks to those behind it.  I think most people were &lt;a href="http://www.ourlocalstyle.com/images/uploadImages/2006/05/03/cnhVerbingWeirdsLanguage.gif"&gt;weirded&lt;/a&gt; by attending an open source jam and signing an NDA :-/  But let's face it, no-one was going to not sign.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://farm3.static.flickr.com/2056/2050010924_fc358e129e_o.jpg" width="458" height="252"  alt="Open Source, non-disclosure"  /&gt;</description><link>http://blog.spiralarm.com/richard/2007/06/google-london-open-source-jam-3.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-6810261782064306058</guid><pubDate>Sat, 19 May 2007 09:19:00 +0000</pubDate><atom:updated>2007-12-07T13:14:28.401Z</atom:updated><title>JavaOne 2007</title><description>For the impatient: impressive Seam and JRuby/NetBeans demos; JavaFX doesn't look that crazy after all; performance improvements show promise; quality of the talks were consistently high and better than I recall from previous years; need to look at Groovy and Grails more.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://farm3.static.flickr.com/2230/2050010786_a3e0054e08_o.jpg" width="353" height="420" alt="Paul, Richard, Jono with Duke at JavaOne 2007. Sorry, had to do it." /&gt;&lt;br /&gt;&lt;br /&gt;I don't like to make too much fuss about these events, but when I go into the first keynote on the first day of JavaOne, look around and see the size of the place (space for just 15,000 attendees &lt;a href="http://www.sun.com/aboutsun/media/presskits/javaone2007/index.jsp"&gt;this year&lt;/a&gt;), look at the huge screens on stage, with &lt;a href="http://www.anon-music.com/"&gt;DJ Anon&lt;/a&gt; doing her thing, and then the big numbers come out: 6 million developers, 2 billion mobile devices, 11 million TVs, Java on 91% of desktops.  I have to admit to being somewhat awed by the event. They do a good show.  It's not Steve Jobs, but it's pretty good.&lt;br /&gt;&lt;br /&gt;The big announcement this year was &lt;b&gt;JavaFX&lt;/b&gt;.  This is a blanket term covering authoring tools for "content professionals", an environment for mobile and a scripting language. The authoring tools don't exist yet. &lt;b&gt;JavaFX Script&lt;/b&gt; does, and used to be called F3&amp;#8212;a technology I've previously described as "nuts". We first heard about F3 at the London Sun Tech Days, and we couldn't understand why it existed when SVG looked to do the same thing in a similar way.  &lt;br /&gt;&lt;br /&gt;This time, we had &lt;a href="http://blogs.sun.com/chrisoliver/"&gt;Chris Oliver&lt;/a&gt;, the author of the language, on hand to explain it.  His talk kicked off by asking why Java applications looked so different to Flash applications.  Java has the capability to produce all the effects you see in Flash, but they're harder to get at.  Step in JavaFX Script which is component scripting of Java 2D and Swing.  &lt;br /&gt;&lt;br /&gt;And why not SVG?  Well, there are lots of similarities between SVG and JavaFX Script (indeed, there's a &lt;a href="http://blogs.sun.com/chrisoliver/entry/f3_and_svg&lt;br /&gt;openjfx.org"&gt;converter&lt;/a&gt;), but the dynamic stuff in SVG is a pain. That's something I can confirm from experience.   &lt;br /&gt;&lt;br /&gt;In JavaFX Script you can do the dynamic stuff with Java (naturally), but the language also has a data binding feature (&lt;a href="http://en.wikipedia.org/wiki/Functional_reactive_programming"&gt;functional reactive programming&lt;/a&gt;, apparently).  As I understood it, elements of the view are bound to elements of the model. This means there's no listening code to write: the model changes, the view updates.  There are demos, downloads and documentation over at &lt;a href="http://openjfx.org"&gt;openjfx.org&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;So maybe not so nuts after all.  To get that into the browser, though, needs some work.  Right now you need to add about 700k to an applet download. The Java Plugin needs some work to make this better (but see the demos over at &lt;a href="http://swinglabs.org/"&gt;swinglabs.org&lt;/a&gt;; I must get round to trying out &lt;a href="http://swinglabs.java.sun.com/iris/"&gt;Iris&lt;/a&gt;). Chris Oliver wasn't taking questions on this area.  In fact, we had the impression that he had perhaps been under a bit of pressure recently: after all, the technology had a different name a month or so ago, was a side demo at London Tech Days, and now was pushed way up the conference agenda.&lt;br /&gt;&lt;br /&gt;In related news, there is going to be a &lt;b&gt;consumer JVM&lt;/b&gt;, presumably targeting RIA, scheduled for early 2008.  The focus is on performance, both runtime and download time. There's also work going on to modularize Java (super packages in development terms; super JARs in deployment terms).&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;JavaFX Mobile&lt;/b&gt; &lt;a href="http://www.sun.com/software/javafx/mobile/index.jsp&lt;br /&gt;"&gt;announcement&lt;/a&gt; is that Sun have a complete mobile stack which is being offered to OEMs: it's the SavaJe technology on top of Linux.  We saw a demo running on a Neo1973, the SavaJe device, and a Nokia N800.  Meh... we'll see what comes of it. &lt;br /&gt;&lt;br /&gt;While on the subject of mobile, just two notes: I was disappointed to see only one prototype MSA device (SE &lt;a href="http://developer.sonyericsson.com/site/global/products/phonegallery/z750/p_z750.jsp"&gt;Z50i&lt;/a&gt;), given that &lt;a href="http://jcp.org/en/jsr/detail?id=248"&gt;MSA&lt;/a&gt; has been talked about for a long time; but I had a look at the &lt;a href="http://www.youtube.com/watch?v=0NcKPD66EiY"&gt;Nokia 6110 Navigator&lt;/a&gt;, and that has a great deal of promise as a phone for location, although no WLAN and only a single processor.&lt;br /&gt;&lt;br /&gt;Anyway, JavaFX Mobile is being placed on the cusp between ME and SE:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://farm3.static.flickr.com/2269/2049224669_cc0bd839e9_o.jpg" width="476" height="339" alt="Diagram showing an overview of JavaFX across devices" /&gt;&lt;br /&gt;&lt;br /&gt;Probably the other headline news was the support for Ruby and Rails via the &lt;b&gt;JRuby&lt;/b&gt; implementation.  If you're developing in Ruby (and/or using Rails), you'll want to check out the Toy Show Part 2 from the &lt;a href="http://java.sun.com/javaone/sf/sessions/general/index.jsp#GS2"&gt;Friday keynote&lt;/a&gt; or take a look at one of the &lt;a href="http://www.netbeans.org/download/flash/jruby_editing/jruby_editing.html"&gt;online demos&lt;/a&gt;.  Either way, you should try out &lt;a href="http://www.netbeans.org/community/releases/60/index.html"&gt;NetBeans 6&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Going into the conference I was wondering which scripting language I should be putting effort into: Ruby or &lt;b&gt;Groovy&lt;/b&gt;.  Both look to be very capable. After attending the &lt;a href="http://www.nofluffjuststuff.com/groovygrailsmeetup/registration/register"&gt;Groovy/Grails One Meet-up&lt;/a&gt;, and gaining some confidence from hearing the people behind the language, I think that Groovy might be more useful to me. It has the edge on integration with Java right now.  What I didn't get was an intro to &lt;a href="http://grails.codehaus.org/"&gt;Grails&lt;/a&gt;.  Something I'll have to try out.&lt;br /&gt;&lt;br /&gt;Another thing that demands attention is &lt;b&gt;GWT&lt;/b&gt;.  It has a reasonable widget set,  fast client development, they've worked on cross-browser and performance issues and browser memory leak issues.  Paul &lt;a href="http://www.goulbourn.demon.co.uk/2007/05/clues-on-getting-started-with-gwt-under.html"&gt;blazed the trail&lt;/a&gt;, and we managed to hack on a GWT app for a while, getting it all working, including client-to-server serialization. I've not seen anything that puts me off it yet.  (Interesting to hear from Google that they think a page load time of 300ms is the threshold for users to be happy.  That's the start up time they target.) &lt;br /&gt;&lt;br /&gt;Gavin King's &lt;b&gt;Seam&lt;/b&gt; demo was just perfect for getting a feel for what &lt;a href="http://www.jboss.com/products/seam"&gt;Seam&lt;/a&gt; is about.  The demo nicely contrasted the assumption that EJB is heavy by having a containter that starts up in the IDE in less than a second. He then continued by developing a Seam web application without the need to restart the container once. Another technology worth checking out.&lt;br /&gt;&lt;br /&gt;From other sessions...&lt;ul&gt;&lt;li&gt; The &lt;a href="http://search.hibernate.org"&gt;Hibernate integration with Lucene&lt;/a&gt; looks like a no-brainer if you need to add text search to an application.&lt;/li&gt;&lt;li&gt; The API for restful web services looks good. I'll take another look when they finish the &lt;a href="http://jcp.org/en/jsr/detail?id=311"&gt;spec&lt;/a&gt;.&lt;/li&gt;&lt;li&gt; I was at a session on deploying and scaling massive digital archive repositories.  It turned out to be a vendor pitch to go buy a &lt;a href="http://www.sun.com/storagetek/disk_systems/enterprise/5800/"&gt;StorageTek 5800&lt;/a&gt;, but it was interesting to learn about the APIs they are building into the disk storage, with hints about this becoming an open standard.  Forget files. (This could be related to &lt;a href="http://en.wikipedia.org/wiki/Project_Honeycomb"&gt;Project Honeycomb&lt;/a&gt;.)&lt;/li&gt;&lt;li&gt; NASDAQ do 100k transactions/second on the Java platform. They're looking to use &lt;a href="http://java.sun.com/javase/technologies/realtime/index.jsp"&gt;Java Real Time&lt;/a&gt;. Presumably for predictability.&lt;/li&gt;&lt;li&gt; Mark Harriman of Ericsson said they're basing their IMS products on Glassfish.  Possibly to be called the Sun Java System Communication Application Server. &lt;/li&gt;&lt;li&gt; When running the Glassfish application server, you can write your site in Ruby, Javascript, PHP and Java. Probably other languages too, via the scripting plugin spec. &lt;/li&gt;&lt;li&gt; I understand that &lt;a href="http://jchav.blogspot.com/"&gt;JChav&lt;/a&gt; was mentioned in one session. Fantastic. &lt;/li&gt;&lt;li&gt; The only session I was disappointed with was a Jini one.  While the language has been changing and going forward, Jini seems (to an outsider like me) relatively unchanged since the first version.  Right now to use Jini, you really need to want to use Jini.&lt;/li&gt;&lt;li&gt; The Neal Gafter presentation on closures for the languages was great to sit through. Each time I hear about the proposal I understand a little bit more about it.&lt;/li&gt;&lt;li&gt; The Effective Java Reloaded session (Josh Bloch again) was superb. Note to self: need to understand wildcard capture in generics, and remember that arrays and generics don't play so well together. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;So: quite an emphasis on scripting, language changes and richer UIs.</description><link>http://blog.spiralarm.com/richard/2007/05/javaone-2007.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-6236694635020077738</guid><pubDate>Mon, 30 Apr 2007 11:19:00 +0000</pubDate><atom:updated>2007-04-30T15:10:42.511+01:00</atom:updated><title>Container Services</title><description>You don't need to use all of &lt;a href="http://en.wikipedia.org/wiki/Java_Platform,_Enterprise_Edition"&gt;Java EE&lt;/a&gt; to build an enterprise application.  Partly because of that I've always been nervous of big EE application servers such as JBoss, Glassfish, OC4J, WebLogic, WebSphere, and instead I've preferred mixing and matching open source libraries and stand-alone components.  Or maybe I just don't need &lt;a href="http://java.sun.com/javaee/overview/faq/javaee_faq.jsp#benefits"&gt;the features&lt;/a&gt;, or I've not run into scalability or transaction control that containers help manage, or maybe I'm not convinced on the benefits of a "single solution".  So although I have ended up using them for some projects, I'm not sold on the need and I've never really thought they make life easier. &lt;br /&gt;&lt;br /&gt;But lately I've started to come round to handing some responsibilities off to containers.  One responsibility is web user authentication (a.k.a. login).  It's a great example of saving time and improving quality, by leaving those aspects to tried-and-tested implementations provided by the application server.  Unfortunately, &lt;a href="http://www.onjava.com/lpt/a/1024"&gt;form based authentication&lt;/a&gt; in the EE spec isn't flexible enough.  Most people I know end up rolling their own solutions, which is a shame.  Maybe it'll be usable one day...&lt;br /&gt;&lt;br /&gt;There is one good example I've found where you can leave something to the container.  If you have an application to deploy, and you want to deploy it on a test machine and a production machine, it's very convenient to leave the database configuration to the container.  That is: you build you application (say, a WAR file) and then you can drop it into a container on a QA machine and it'll pick up the connection settings for the QA database; drop it into the live environment and it'll pick up the live database settings. The configuration is in the container (once), not the application (each build), and so &lt;a href="http://www.bbc.co.uk/comedy/blackadder/epguide/two_head.shtml"&gt;Mr Cock-Up&lt;/a&gt; is less likely to visit. &lt;br /&gt;&lt;br /&gt;Here's how you do it with Tomcat 5.5 and Hibernate 3.0.x:&lt;br /&gt;&lt;ol&gt; &lt;li&gt; Copy your JDBC driver and your connection pool into &lt;code&gt;$TOMCAT/common/lib/&lt;/code&gt;  e.g., &lt;code&gt;mysql-connector-java-3.0.14-production-bin.jar&lt;/code&gt; and &lt;code&gt;c3p0-0.9.0.4.jar&lt;/code&gt; for example. &lt;/li&gt;&lt;br /&gt;&lt;li&gt; In Tomcat's &lt;code&gt;server.xml&lt;/code&gt;, in the &lt;code&gt;&amp;lt;GlobalNamingResources&amp;gt;&lt;/code&gt; section add: &lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;&amp;lt;Resource name="jdbc/MYPROJECT-database"&lt;br /&gt;   description="My Project Database Connection"&lt;br /&gt;   driverClass="com.mysql.jdbc.Driver"&lt;br /&gt;   maxPoolSize="25"&lt;br /&gt;   minPoolSize="2"&lt;br /&gt;   acquireIncrement="1"&lt;br /&gt;   auth="Container"&lt;br /&gt;   maxStatements="50"&lt;br /&gt;   idleConnectionTestPeriod="3600"&lt;br /&gt;   testConnectionOnCheckin="true"&lt;br /&gt;   automaticTestTable="connection_test"&lt;br /&gt;   maxIdleTime="21600"&lt;br /&gt;   factory="org.apache.naming.factory.BeanFactory"&lt;br /&gt;   type="com.mchange.v2.c3p0.ComboPooledDataSource"&lt;br /&gt;   jdbcUrl="jdbc:mysql://localhost:3306/MYPROJECT?useUnicode=true&amp;&lt;br /&gt;          amp;characterEncoding=UTF-8&amp;amp;autoReconnect=true"&lt;br /&gt;   user="myproj" password="trustno1" /&amp;gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Adjust parameters to taste.  What's going on here, is that the Apache &lt;code&gt;BeanFactory&lt;/code&gt; is creating an instance of &lt;code&gt;ComboPooledDataSource&lt;/code&gt; and then trying to call &lt;code&gt;setX&lt;/code&gt; methods&lt;br /&gt;on the instance from the attributes in this XML snippet.  So check the API for your connection pool implementation to see what you can set. &lt;/li&gt;&lt;br /&gt;&lt;li&gt; Create the &lt;code&gt;webapp/META-INF/context.xml&lt;/code&gt; (or similar) with this content: &lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;&amp;lt;Context&amp;gt;&lt;br /&gt;  &amp;lt;ResourceLink name="jdbc/MYPROJECT-database" &lt;br /&gt;     global="jdbc/MYPROJECT-database" &lt;br /&gt;     type="javax.sql.DataSource" /&amp;gt;&lt;br /&gt;&amp;lt;Context&amp;gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;That tells Tomcat that this web application wants to access a global Tomcat resource called jdbc/MYPROJECT-database.  &lt;br /&gt;When Tomcat deploys the WAR this file is copied to &lt;code&gt;TOMCAT/conf/Catalina/localhost/YOUR-WAR-NAME.xml&lt;/code&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt; If you're using Hibernate, modify the config file to ask the container for the connection: &lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;   &amp;lt;property name="dialect"&amp;gt;&lt;br /&gt;       org.hibernate.dialect.MySQLDialect&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;   &amp;lt;property name="hibernate.connection.datasource"&amp;gt;&lt;br /&gt;       java:comp/env/jdbc/MYPROJECT-database&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;...ensuring that all the other database connection stuff (username etc) are removed. &lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;That's it.  Then when you run, if Hibernate needs a connection it asks Tomcat for jdbc/MYPROJECT-database and Tomcat gives back whatever the instance is set up to provide.  Looks like it's doable in &lt;a href="http://docs.codehaus.org/display/JETTY/JNDI"&gt;Jetty&lt;/a&gt; too.</description><link>http://blog.spiralarm.com/richard/2007/04/container-services.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-707193053977131734</guid><pubDate>Thu, 05 Apr 2007 07:29:00 +0000</pubDate><atom:updated>2007-04-19T12:26:15.915+01:00</atom:updated><title>Microformats</title><description>Last night's &lt;a href="http://sussex.geekdinner.co.uk/"&gt;Sussex Geek dinner&lt;/a&gt; featured &lt;a href="http://www.glennjones.net/about/" rel="met colleague"&gt;Glenn Jones&lt;/a&gt; with a presentation on Microformats.   I learned a lot in a short space of time.   &lt;br /&gt;&lt;br /&gt;My previous impression of microformats was that it was a kludgy way to piggyback contact and event details into HTML&amp;#8212;clever and useful, admittedly, but a kludge nonetheless.  But I was totally wrong.  I recommend grabbing &lt;a href="http://www.glennjones.net/downloads/MicroformatsHTMLtoAPI.pdf"&gt;the PDF presentation&lt;/a&gt; and taking a look for yourself, but it turns out the attributes used to mark-up XHTML with contact details and the like are, for want of a better word, legitimate.   For example, using the &lt;code&gt;class&lt;/code&gt; attribute to identify a name of a person is fine: the &lt;a href="http://www.w3.org/TR/xhtml2/mod-core.html"&gt;XHTML spec&lt;/a&gt; describes &lt;code&gt;class&lt;/code&gt; as good for pretty much any use: "The class attribute can be used for different purposes in XHTML, for instance as a style sheet selector (when an author wishes to assign style information to a set of elements), and for general purpose processing by user agents." Ah, so it's not just for CSS. Ok.&lt;br /&gt;&lt;br /&gt;Adding to that are a couple more appealing features: the specs are short, look pretty straightforward to start using, and are based on existing standards such as vcard.  The details are over at &lt;a href="http://microformats.org/"&gt;microformats.org&lt;/a&gt;.   I'll add "&lt;a href="http://microformats.org/wiki/hreview"&gt;hReview&lt;/a&gt;-ifying &lt;a href="http://www.dallaway.com/reading/current.xml"&gt;book write-ups&lt;/a&gt;" to my to do list...one day....&lt;br /&gt;&lt;br /&gt;For me the most interesting part of the talk was idea of designing URLs so they look like API calls.  The example given was along the lines of: &lt;code&gt;http://somesite/tag/creative&lt;/code&gt; can be thought of as &lt;code&gt;somesite.tags.getList("creative")&lt;/code&gt;.    That works for me, and is probably a good rule of thumb for designing URLs.  The tricky part comes with queries: how to incorporate do ANDs, ORs, ranges, etc.  One option might be to use a &lt;a href="http://en.wikipedia.org/wiki/Builder_pattern"&gt;builder pattern&lt;/a&gt;, such as &lt;code&gt;/tags/creative/startingWith/c&lt;/code&gt; interpreted as &lt;code&gt;tags.getList("creative").startingWith("c")&lt;/code&gt;.  Another option would be convention where by the order of the elements of the URL have a meaning and you just need to know it. The example there would be &lt;a href="http://traintimes.org.uk/brighton/london/08:30"&gt;http://traintimes.org.uk/brighton/london/08:30&lt;/a&gt; means "list trains from Brighton to London, leaving Brighton at 08:30".  Stuff to ponder.&lt;br /&gt;&lt;br /&gt;Indeed, the evening left me with plenty of stuff to ponder: How does this relate to RSS?  How does this tie up with RESTful web services.  Stuff to ponder is a good sign, BTW.  &lt;br /&gt;&lt;br /&gt;Now we all need to go play with the &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/4106"&gt;Operator plugin for Firefox&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;UPDATE: 19 April 2007, via &lt;a href="http://twitter.com/adactio"&gt;Jeremy's twitterings&lt;/a&gt;, &lt;a href="http://microformats.org/wiki/picoformats"&gt;Picoformats&lt;/a&gt; look interesting.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;Disclaimer: &lt;a href="http://www.glennjones.net/about/" rel="met colleague"&gt;Glenn Jones&lt;/a&gt; is the Creative Director at &lt;a href="http://www.madgex.com/"&gt;Madgex&lt;/a&gt;, which is &lt;br /&gt;&lt;a href="http://jane.dallaway.com/about.html" rel="spouse"&gt;Jane&lt;/a&gt;'s new employer.&lt;br /&gt;&lt;/i&gt;</description><link>http://blog.spiralarm.com/richard/2007/04/microformats.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-2395312828094939821</guid><pubDate>Fri, 16 Mar 2007 12:44:00 +0000</pubDate><atom:updated>2007-12-07T13:15:07.911Z</atom:updated><title>Sun Tech Days London 2007</title><description>&lt;img src="http://farm3.static.flickr.com/2154/2049224525_6f2abb65d9_o.png" alt="Photo of James Gosling speaking at Sun Tech Days 2007, London" width="355" height="465" /&gt;&lt;br /&gt;&lt;br /&gt;I caught the middle day of the three-day &lt;a href="http://uk.sun.com/sunnews/events/2007/mar/revolution/techdays07/index.html"&gt;Sun Tech Days&lt;/a&gt; in London.  Compared to &lt;a href="http://blog.spiralarm.com/richard/2006/04/javauk06.html"&gt;last year&lt;/a&gt;, it was busier and felt to me like there was less in-depth technical content.   There was too much "Hello London! Are you ready to rock?" and not enough to get rocking about.  &lt;br /&gt;&lt;br /&gt;Note to the organizers: yes, maybe we are a tougher crowd than the Japanese, but if your idea of crowd foreplay is just lobbing out a beach ball, you've got to try harder.  Also: we need better coffee, make sure all the presentations actually match their titles and descriptions... I could go on...  to gauge how unimpressed I was with the whole event I left before the free booze came out.  And that's obviously a phrase I never thought I'd have to use. &lt;br /&gt;&lt;br /&gt;But I like these events. Forget the coffee, forget the cheerleading, and forgive some of the content.  What you get is time to think about the tech with like-minded people, and to look and hear about things you don't normally give yourself the change to think about. It's a good thing, and I'd recommend it to anyone. &lt;br /&gt;&lt;br /&gt;For me "London's own" &lt;a href="http://blogs.sun.com/simonri/"&gt;Simon Ritter&lt;/a&gt; was the star.   I caught his presentation on Java 6 and 7 (&lt;a href="http://cz.sun.com/techdays/prague/prezentace/Day1_Track2/FY07TD_JavaSE_TodayTomorrow_Prague.pdf"&gt;PDF&lt;/a&gt;) which was useful for the explanation of the bounded wildcard stuff in generics. &lt;br /&gt;&lt;br /&gt;His demo on music similarity was the best thing I saw all day.  It looks to be the &lt;a href="http://research.sun.com/spotlight/2006/2006-06-28_search_inside_music.html"&gt;Search inside the Music project&lt;/a&gt; and the basic idea is to extract features from music so that you can cluster tracks by similarity.  Reading from "&lt;a href="http://www.hindawi.com/GetArticle.aspx?doi=10.1155/2007/24602"&gt;A model-based approach to constructing music similarity functions&lt;/a&gt;" (which is a good review of the field) it looks like they  extract features from MP3 data and then use a learning algorithm to classify a track by genre.  What you get out is 10 genre likelihood numbers which you can plot by reducing from 10D to 3D (using &lt;a href="http://en.wikipedia.org/wiki/Multidimensional_scaling"&gt;MDS&lt;/a&gt;, which tries to reduce the dimensions in such as  way that points that are close in 10D space are mostly close in 3D space too. I'd expect &lt;a href="http://en.wikipedia.org/wiki/Karhunen-Loève_transform"&gt;PCA&lt;/a&gt; to work too.  In other words, don't ask what the labels on the axis are, because there's no easy way to say).  Once plotted you can see the clusters of genre and sub-genre, and then take journeys from one genre to another.  Cute.&lt;br /&gt;&lt;br /&gt;What else...&lt;ul&gt;&lt;li&gt; Netbeans 6 looks like it's getting to be usable day-to-day soon.  The profiler looks excellent: so thanks to the guy on the stand who demoed that to us. &lt;/li&gt;&lt;li&gt; I learned a little bit about &lt;a href="http://developers.sun.com/javadb/"&gt;Java DB&lt;/a&gt; (a.k.a. &lt;a href="http://db.apache.org/derby/"&gt;Derby&lt;/a&gt;, a.k.a Cloudscape):  Mostly I learned (&lt;a href="http://cz.sun.com/techdays/prague/prezentace/Day1_Track1/JavaDB_TechDays_FY06-v3.pdf"&gt;PDF&lt;/a&gt;) that it's a proper database.&lt;/li&gt;&lt;li&gt; I don't think I need to worry about BPEL and JBI.&lt;/li&gt;&lt;li&gt; The main features of Java 6 seem to be: Visa L&amp;F; SystemTray stuff; access via Desktop to email, browser; splash screen support; scripting engine; ability to discover available disk space. All dull, but worthy.&lt;/li&gt;&lt;li&gt; Java 7 looks to be up for lots of ease-of-development changes: maybe &lt;a href="http://gafter.blogspot.com/2006/08/closures-for-java.html"&gt;closures&lt;/a&gt;, syntax for list and hash creation, properties. Stuff people have been banging on about for ages. Due mid 2008.&lt;/li&gt;&lt;li&gt; &lt;a href="http://blogs.sun.com/chrisoliver/entry/f3"&gt;F3&lt;/a&gt;...looks nuts. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The event was held in at &lt;a href="http://upcoming.org/venue/43184/"&gt;Central Hall Westminster&lt;/a&gt;. Nice building. It somehow seems right that events like this are held in places of worship.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://farm3.static.flickr.com/2372/2050010672_ccc09373c0_o.png" alt="Photo of inside Tech Days 2007, London" width="354" height="255" /&gt;</description><link>http://blog.spiralarm.com/richard/2007/03/sun-tech-days-london-2007.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-7752598994602686895</guid><pubDate>Thu, 08 Feb 2007 12:42:00 +0000</pubDate><atom:updated>2007-03-13T13:26:47.476Z</atom:updated><title>Mac OS 10.4, Apache, Subversion</title><description>I recently set up a Subversion server on my Mac OS 10.4 MacBook Pro.  It was, amongst other things, a test-run for installing SVN on an &lt;a href="http://www.apple.com/xserve/"&gt;XServe&lt;/a&gt;. It was somewhat involved, so here's my reminder on how to do this.  Hopefully &lt;a href="http://upcoming.org/event/149426/"&gt;when 10.5 ships&lt;/a&gt; a lot of this will just go away.&lt;br /&gt;&lt;br /&gt;The goal is to: install subversion, convert an existing CVS repository to SVN, set up Apache to access the repository, set up some access restrictions, and get it running over HTTPS.  The starting point is that 10.4 ships with Apache 1.3, and I'd already installed a SVN client from a &lt;code&gt;.dmg&lt;/code&gt;,  but you need Apache 2 and to install Subversion from source to get the Apache SVN module compiled up, so that really doesn't matter (the Mac OS 10.4 server, BTW, ships with an Apache 2.0 instance for "&lt;a href="http://docs.info.apple.com/article.html?path=ServerAdmin/10.4/en/c5ws8.html"&gt;evaluation purposes&lt;/a&gt;", but I'm going to ignore that as we want the latest and greatest Apache really). &lt;br /&gt;&lt;br /&gt;My plan: install Apache in to &lt;code&gt;~/Applications/apache/2.2.4/&lt;/code&gt; and SVN into &lt;code&gt;~/Applications/svn/1.4.3/&lt;/code&gt; and to convert the CVS repository into a SVN one in &lt;code&gt;~/Developer/svn/BIG_PROJECT&lt;/code&gt; (obviously, adjust to your own tastes).&lt;br /&gt;&lt;br /&gt;Here we go...&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 0:&lt;/b&gt; You need the Apple Developer tools installed.&lt;br /&gt;&lt;br /&gt;The next five steps are all concerned with &lt;code&gt;cvs2svn&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 1:&lt;/b&gt; Install &lt;a href="http://darwinports.opendarwin.org/"&gt;DarwinPorts&lt;/a&gt; (or is it &lt;a href="http://www.macports.org/"&gt;MacPorts&lt;/a&gt; now?).  Ports provides a way to download, compile and install open source projects into &lt;code&gt;/opt&lt;/code&gt;.  The &lt;a href="http://darwinports.opendarwin.org/getdp/"&gt;DarwinPorts instructions&lt;/a&gt; are pretty clear: grab the Tiger &lt;code&gt;.dmg&lt;/code&gt; installer and do the &lt;code&gt;sudo port selfupdate&lt;/code&gt; thing.  One gotcha here: the installer adds &lt;code&gt;/opt/local/bin&lt;/code&gt; to your &lt;code&gt;$PATH&lt;/code&gt; by adding a line to &lt;code&gt;.profile.&lt;/code&gt;  If you've got a &lt;code&gt;.bash_profile&lt;/code&gt; already, you may find the &lt;code&gt;.profile&lt;/code&gt; file being ignored, so adjust however you like so that &lt;code&gt;/opt/local/bin:/opt/local/sbin&lt;/code&gt; ends up at the start of your &lt;code&gt;$PATH.&lt;/code&gt;  An &lt;code&gt;echo $PATH&lt;/code&gt; will tell you if you're good or not after install and starting a new shell.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 2:&lt;/b&gt; Install Berkeley DB, which you need for cvs2svn later.  If you want you can skip this step and discover later if you need it, but I needed it.  The command to perform this install is: &lt;code&gt;sudo port install db42&lt;/code&gt;.   Two confessions at this point.  DarwinPorts understands dependencies and will go and get any additional packages required by db42, but I don't know how many that will be for you because I'd already used Ports to install the latest version of Ruby which downloaded lots of packages.  The second confession is that at the time I ran the above command, Ports wasn't responding to my proxy configurations and it couldn't download the package from the shell.  To get around this I manually downloaded the package (&lt;code&gt;db-4.2.52.tar.gz&lt;/code&gt;) in my browser and put it in &lt;code&gt;/opt/local/var/db/dports/distfiles/db4/&lt;/code&gt;.  If you have problems like this, running the port command with &lt;code&gt;-v&lt;/code&gt; can help.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 3&lt;/b&gt;: Add Berkley DB support to Python, which is something required by cvs2svn as &lt;a href="http://blog.plasticsfuture.org/2006/03/04/install-cvs2svn-on-mac-os-x-1042/"&gt;described by plasticfuture&lt;/a&gt;.  The steps here are to grab the &lt;a href="http://pybsddb.sourceforge.net/"&gt;Python Berkeley DB bindings source&lt;/a&gt; (&lt;code&gt;bsddb3-4.5.0.tar.gz&lt;/code&gt; for me), extract it and run:  &lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;$ python setup.py build --berkeley-db-libdir=/opt/local/lib/db42&lt;br /&gt;      --berkeley-db-incdir=/opt/local/include/db42&lt;br /&gt;&lt;br /&gt;$ python setup.py install --berkeley-db-libdir=/opt/local/lib/db42&lt;br /&gt;      --berkeley-db-incdir=/opt/local/include/db42&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Step 4:&lt;/b&gt; You're now set to &lt;a href="http://cvs2svn.tigris.org/cvs2svn.html"&gt;download and set up cvs2svn&lt;/a&gt;.  I had a tar.gz of an existing CVS repository, which I unpacked to &lt;code&gt;~/Developer/oldcvs/BIG_PROJECT&lt;/code&gt;.  You need to create a &lt;code&gt;cvs2svn.options&lt;/code&gt; file to set up the conversion.  I was going to create a new SVN repository, and you can &lt;a href="http://blog.spiralarm.com/richard/2007/02/cvs2svn.options"&gt;download the cvs2svn.options&lt;/a&gt; I used (more or less... search for &lt;code&gt;[CHANGE ME]&lt;/code&gt; in that file and fix it up for your own usage).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 5&lt;/b&gt;: Run the conversion with: &lt;code&gt;cvs2svn-1.5.1/cvs2svn --options PATH_TO/cvs2svn.options&lt;/code&gt;.  If you have a "big project" this may take a while, so while it's running you might want to type the following to be told when it's done: &lt;code&gt;say Conversion Complete&lt;/code&gt;.  I had a handful of errors about files existing in the repository and also in the Attic. I &lt;code&gt;rm&lt;/code&gt;-ed the Attic versions of the files and re-ran the command.&lt;br /&gt;&lt;br /&gt;Now that we have a converted CVS repository as a SVN repository we can continue and set up the server.  Before that, I just did a sanity check with &lt;code&gt;svn co file:///Users/richard/Developer/svn/BIG_PROJECT&lt;/code&gt; into /tmp or wherever to ensure there were no problems with the conversion (remember: I already had the SVN client installed, but if you don't you'll be able to do a test checkout around step 7, below).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 6:&lt;/b&gt; Install Apache.  There's a pretty nice &lt;a href="http://developer.apple.com/tools/subversionxcode.html"&gt;Apple Developer article on Subversion and Apache&lt;/a&gt; which is worth a read.  All I did in the end was to &lt;a href="http://httpd.apache.org/"&gt;download Apache&lt;/a&gt;, unpack it, and run:&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;$ ./configure  --prefix=/Users/richard/Applications/apache/2.2.4 &lt;br /&gt;     --enable-mods-shared=most --enable-ssl --with-mpm=worker&lt;br /&gt;     --without-berkeley-db --enable-proxy&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The &lt;code&gt;--without-berkeley-db&lt;/code&gt; is ironic after the BDB hoops we've jumped through above.  The usual &lt;code&gt;make&lt;/code&gt; and &lt;code&gt;sudo make install&lt;/code&gt; and you're done.  Start apache with &lt;code&gt;sudo ./apachectrl start&lt;/code&gt; from the &lt;code&gt;~/apache/2.2.4/bin&lt;/code&gt; directory and check that &lt;a href="http://127.0.0.1/"&gt;http://127.0.0.1/&lt;/a&gt; is running and then stop Apache. (Warning: if you just run &lt;code&gt;apachectrl&lt;/code&gt; you'll pick up the Apple-installed Apache 1.3 instance, so remember to use the &lt;code&gt;./&lt;/code&gt; or use the full path to the &lt;code&gt; apachectrl&lt;/code&gt; for the Apache you've installed).&lt;br /&gt;&lt;br /&gt;I ran into a few segmentation faults (or bus errors, depending on which user you run as) when starting up Apache.  It turns out there are a couple of modules that fail to load or other issues in the configuration file.  One useful way to see how far Apache is getting is to validate the configuration with debugging on: &lt;code&gt;sudo bin/httpd -t -e DEBUG&lt;/code&gt;.  &lt;br /&gt;&lt;br /&gt;We'll configure Apache later, but first...&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 7:&lt;/b&gt;  Install subversion.  Again, the Apple Developer document above is helpful here.  I downloaded the subversion source from &lt;a href="http://subversion.tigris.org/"&gt;subversion.tigris.org&lt;/a&gt; and ran...&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;$ ./configure --prefix=/Users/richard/Applications/svn/1.4.3  --with-ssl &lt;br /&gt;     --with-apxs=/Users/richard/Applications/apache/2.2.4/bin/apxs &lt;br /&gt;     --with-zlib --enable-swig-bindings=no --without-berkeley-db &lt;br /&gt;     --with-apr=/Users/richard/Applications/apache/2.2.4/ &lt;br /&gt;     --with-apr-util=/Users/richard/Applications/apache/2.2.4/&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;...followed by &lt;code&gt;make&lt;/code&gt; and &lt;code&gt;sudo make install&lt;/code&gt;.  If you don't already have a Subversion client on your &lt;code&gt;$PATH,&lt;/code&gt; you can add &lt;code&gt;~/Appliations/1.4.3/bin&lt;/code&gt; now.&lt;br /&gt;&lt;br /&gt;If you're going to go on to install Continuum or anything else that might require http or https support from the Subversion client, you'll want to also download the Neon library as documented by &lt;a href="http://www.latke.net/blog/punkengineer/archive/000046.html"&gt;The Punk Engineer&lt;/a&gt; and indeed also by the Subverison &lt;code&gt;INSTALL&lt;/code&gt; text file.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 8&lt;/b&gt;: Configure Apache.  Now comes the Apache voodoo to turn on SVN access.  Edit &lt;code&gt;~/Applications/apache/2.2.4/conf/httpd.conf&lt;/code&gt;.  (BTW, &lt;a href="http://macromates.com/"&gt;TextMate&lt;/a&gt; is quite nice for all of this, partly because it recognizes and colours Apache configuration, but also because from the shell you can run &lt;code&gt;mate .&lt;/code&gt; to open all files in a nice folder view.)   At the bottom of the Apache config add the following:&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;&amp;lt;IfModule dav_svn_module&amp;gt;&lt;br /&gt;&amp;lt;Location /repos&amp;gt;&lt;br /&gt;DAV svn&lt;br /&gt;SVNPath /Users/richard/Developer/svn/BIG_PROJECT&lt;br /&gt;&amp;lt;/Location&amp;gt;&lt;br /&gt;&amp;lt;/IfModule&amp;gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Start Apache and in your browser you can hit &lt;a href="http://127.0.0.1/repos"&gt;http://127.0.0.1/repos&lt;/a&gt; to browse the source.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 10&lt;/b&gt;: Add authentication.  Go back to &lt;code&gt;httpd.conf&lt;/code&gt; and add in some form of authentication and access control.  Here's what I did...&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;&amp;lt;IfModule dav_svn_module&amp;gt;&lt;br /&gt;&amp;lt;Location /repos&amp;gt;&lt;br /&gt;DAV svn&lt;br /&gt;SVNPath /Users/richard/Developer/svn/BIG_PROJECT&lt;br /&gt;AuthzSVNAccessFile conf/svn-access.conf&lt;br /&gt;&lt;br /&gt;Require valid-user&lt;br /&gt;AuthType Basic&lt;br /&gt;AuthName &amp;quot;Subversion Access&amp;quot;&lt;br /&gt;AuthUserFile /Users/richard/Developer/svn/svn-pwd-file&lt;br /&gt;&amp;lt;/Location&amp;gt;&lt;br /&gt;&amp;lt;/IfModule&amp;gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;There are two changes here.  The first is a &lt;code&gt;svn-access.conf&lt;/code&gt; file that controls what users or groups can do to parts of the repository. This file looks like this:&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;[groups]&lt;br /&gt;dev = paul, gareth, richard, andrew, jono&lt;br /&gt;&lt;br /&gt;[/]&lt;br /&gt;@dev = rw&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;It's saying there's a group of users call "dev" to have read+write access to the "/" path in the repository (i.e., the lot).  I wasn't able to find a great deal of documentation on this, but thank you to Richard Tesh for spotting the &lt;a href="http://wiki.archlinux.org/index.php/Subversion_Setup#Apache_Installation"&gt;archlinux.org&lt;/a&gt; guide.&lt;br /&gt;&lt;br /&gt;The second part of the Apache configuration is the basic authentication part, which is straight-forward non-weird Apache stuff.  The command you need is &lt;code&gt;htpasswd&lt;/code&gt;: run it with &lt;code&gt;-c&lt;/code&gt; the first time only to create the &lt;code&gt;svn-pwd-file&lt;/code&gt;.  Use this to create a username and password for each of your "dev" users.&lt;br /&gt;&lt;br /&gt;Quit your browser, restart Apache, and try to hit the repository again: This time you'll be prompted to login.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 11:&lt;/b&gt; Set up permissions on SVN repository.  A gotcha here is that the Apache user (daemon, group daemon) needs write access to the repository, so you need to decide what you're going to do there.  One option is to &lt;code&gt;chmod&lt;/code&gt; the repository, which is what I did.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 12:&lt;/b&gt; Finally you'll want all of this to run over HTTPS, and so you'll need to set up a certificate for Apache.  I'm using a self-signed certificate.  There's some great documentation for this, including the ever-useful &lt;a href="http://www.macosxhints.com/article.php?story=20041129143420344"&gt;macosxhints.com&lt;/a&gt;.  I created a folder in my home directory called &lt;code&gt;keys&lt;/code&gt;, and from there I ran the following:&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;$ /System/Library/OpenSSL/misc/CA.pl -newca&lt;br /&gt;$ openssl genrsa -des3 -out webserver.key 1024&lt;br /&gt;$ openssl rsa -in webserver.key -out webserver.nopass.key&lt;br /&gt;$ openssl req -config /System/Library/OpenSSL/openssl.cnf -new &lt;br /&gt;     -key webserver.key -out newreq.pem -days 3650&lt;br /&gt;$ /System/Library/OpenSSL/misc/CA.pl -signreq&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;You'll get prompted to enter a bunch of information. Use your hostname as the common name.&lt;br /&gt;&lt;br /&gt;When those commands are done, you'll have a set of files and a subdirectory in &lt;code&gt;~/keys&lt;/code&gt;.  Now to configure Apache, by adding the following the &lt;code&gt;httpd.conf&lt;/code&gt;:&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;&amp;lt;IfModule mod_ssl.c&amp;gt;&lt;br /&gt;Listen 80&lt;br /&gt;Listen 443&lt;br /&gt;&lt;br /&gt;&amp;lt;VirtualHost _default_:443&amp;gt;&lt;br /&gt;SSLEngine on&lt;br /&gt;ServerName 127.0.0.1&lt;br /&gt;SSLRequireSSL&lt;br /&gt;&lt;br /&gt;SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM: \ &lt;br /&gt;     +LOW:+SSLv2:+EXP:+eNULL&lt;br /&gt;SSLCertificateFile /Users/richard/keys/newcert.pem&lt;br /&gt;SSLCertificateKeyFile /Users/richard/keys/webserver.nopass.key&lt;br /&gt;SSLCACertificateFile /Users/richard/keys/demoCA/cacert.pem&lt;br /&gt;SSLCARevocationPath /Users/richard/keys/demoCA/crl&lt;br /&gt;&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/IfModule&amp;gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Restart Apache and you can now hit &lt;code&gt;https://127.0.0.1/repos/BIG_PROJECT&lt;/code&gt; or enter that into whatever tool you use to access subversion, such as an &lt;a href="http://subclipse.tigris.org/"&gt;Eclipse plugin&lt;/a&gt;.  You'll be told the certificate isn't recognized, but just "continue" or "OK" or "accept" your way past that.  BTW, if you try to hit the non-HTTPS URL, you'll be forbidden.&lt;br /&gt;&lt;br /&gt;Aaaaaaaaand we're done.  Apart from backups, more sensible security, better file naming, multiple repositories, automated builds....&lt;br /&gt;&lt;br /&gt;Thank you: &lt;a href="http://www.goulbourn.com/"&gt;Paul&lt;/a&gt;, &lt;a href="http://www.amazon.co.uk/dp/0977616657?tag=richarddallaway&amp;camp=1406&amp;creative=6394&amp;linkCode=as1&amp;creativeASIN=0977616657&amp;adid=0GP0G2BKXGZSB9F4V27J&amp;"&gt;Pragmatic Version Control Using Subversion&lt;/a&gt; and all the HOW TOs I've not mentioned.</description><link>http://blog.spiralarm.com/richard/2007/02/mac-os-104-apache-subversion-ssl.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-4855778182080743310</guid><pubDate>Sun, 21 Jan 2007 17:03:00 +0000</pubDate><atom:updated>2007-01-22T07:28:36.299Z</atom:updated><title>OpenStreetMap</title><description>&lt;a href="http://brainoff.com/weblog/"&gt;Mikel Maron&lt;/a&gt;'s fireside-style talk at the &lt;a href="http://sussex.geekdinner.co.uk/"&gt;Sussex Geek Dinner&lt;/a&gt; was a great introduction to &lt;a href="http://www.openstreetmap.org/"&gt;OpenStreetMap&lt;/a&gt;: "providing free geographic data such as street maps to anyone who wants them".  If you need to know anything about this area, Mikel is clearly the person to talk to.  &lt;br /&gt;&lt;br /&gt;&lt;a href="http://jane.dallaway.com/blog/2007/01/sussex-geek-dinner.html"&gt;Jane&lt;/a&gt;'s blogged about the talk, so I'll skip that and just mention that the talk inspired me to take another look at the Bluetooth GPS unit we have.  Turns out it's easy to get the GPS unit running with a MacBook &lt;a href="http://discussion.forum.nokia.com/forum/archive/index.php/t-54630.html"&gt;via the terminal&lt;/a&gt;: pair with the device, and then in Bluetooth Preferences, select the device and check the serial ports. In my case, I didn't have to do anything, as the Mac had already set it up as a serial device.   From the shell, you can then connect to the device...&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;$ screen /dev/tty.BT-GPS-3404F4-BT-GPSCOM-1 &lt;br /&gt;&lt;/div&gt; &lt;br /&gt;...and it starts spewing data:&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;$GPGSA,A,3,20,01,11,17,,,,,,,,,2.6,2.4,1.0*34&lt;br /&gt;$GPRMC,164654.000,A,5049.4955,N,00008.8944,W,0.06,87.03,180107,,*2C&lt;br /&gt;$GPGGA,164655.000,5049.4957,N,00008.8945,W,1,04,2.4,26.0,M,47.0,M,,0000*71&lt;br /&gt;$GPGSA,A,3,20,01,11,17,,,,,,,,,2.6,2.4,1.0*34&lt;br /&gt;$GPRMC,164655.000,A,5049.4957,N,00008.8945,W,0.09,24.77,180107,,*2B&lt;br /&gt;$GPGGA,164656.000,5049.4959,N,00008.8946,W,1,04,2.4,26.3,M,47.0,M,,0000*7C&lt;br /&gt;$GPGSA,A,3,20,01,11,17,,,,,,,,,2.6,2.4,1.0*34&lt;br /&gt;&lt;/div&gt; &lt;br /&gt;These sentences aren't too scary, once you have the &lt;a href="http://aprs.gids.nl/nmea/"&gt;NMEA&lt;/a&gt; descriptions.  And as it's Bluetooth and a serial connection, you can imagine it's &lt;a href="http://www.google.com/search?q=java+nmea+parser"&gt;not too bad&lt;/a&gt; to get that data live on a phone, without the need for &lt;a href="http://jcp.org/en/jsr/detail?id=179"&gt;JSR-179&lt;/a&gt; or &lt;a href="http://jcp.org/en/jsr/detail?id=293"&gt;JSR-293&lt;/a&gt;.  Great fun.&lt;br /&gt;&lt;br /&gt;But back to the talk, I should mention that the big thing OpenStreetMap has is a great refresh rate.  Compared to other mapping organizations, OpenStreetMap contributors can, for example, spot new streets in their area as they are being built, meaning the OpenStreetMaps maps can be years ahead of the other players.  On the other hand, organizations like the Ordnance Survey have a great advantage in precision.  But what you need depends on what you want to do, and for OpenStreetMap the focus (I think) is about navigation.  &lt;br /&gt;&lt;br /&gt;Links to follow up: &lt;a href="http://www.npemap.org.uk/"&gt;New Popular Edition&lt;/a&gt; (OS maps out of copyright); &lt;a href="http://www.oreilly.com/catalog/neogeography/"&gt;Neogeography&lt;/a&gt;; &lt;a href="http://www.freethepostcode.org/"&gt;Free The Postcode&lt;/a&gt;; &lt;a href="http://earth.google.com/kml/"&gt;KML&lt;/a&gt;; &lt;a href="http://www.geonames.org/"&gt;Geonames&lt;/a&gt;; &lt;a href="http://www.ordnancesurvey.co.uk/oswebsite/gps/information/coordinatesystemsinfo/guidecontents/index.html"&gt;OS information&lt;/a&gt;; &lt;a href="http://www.gpsbabel.org/"&gt;GPSBabel&lt;/a&gt;; &lt;a href="http://www.opengeodata.org/?p=120"&gt;Yahoo! allows satellite imagery in OpenStreetMaps&lt;/a&gt;.</description><link>http://blog.spiralarm.com/richard/2007/01/openstreetmap.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-116603691356545698</guid><pubDate>Wed, 13 Dec 2006 19:03:00 +0000</pubDate><atom:updated>2006-12-14T22:28:38.656Z</atom:updated><title>Generics in Comments</title><description>For a project I'm involved in that is stuck using JDK 1.4, I've found doing this soothing:&lt;br /&gt;&lt;div class="sourcecode"&gt;&lt;br /&gt;  List/*&amp;lt;Stuff&amp;gt;*/ getStuff(); &lt;br /&gt;&lt;/div&gt; &lt;br /&gt;It's documentation, and gives me the hope that one day I can remove the comments for this particular project.</description><link>http://blog.spiralarm.com/richard/2006/12/generics-in-comments.html</link><author>noreply@blogger.com (Richard)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-11993899.post-116530677584968377</guid><pubDate>Tue, 05 Dec 2006 20:10:00 +0000</pubDate><atom:updated>2006-12-05T18:45:56.250Z</atom:updated><title>Next Net</title><description>Thanks to &lt;a href="http://www.ewansilver.com/blog/"&gt;Ewan Silver&lt;/a&gt; and others for organizing the &lt;a href="http://upcoming.org/event/128413/"&gt;Next Net&lt;/a&gt; meet up.  It's sort of a London Jini Group, but more general: a gathering of people interested in distributed (utility computing, grid computing, massively scalable, resilient) systems.  &lt;br /&gt;&lt;br /&gt;I unfortunately missed a large chunk of &lt;a href="http://www.jroller.com/page/dancres/Weblog"&gt;Dan Creswell&lt;/a&gt;'s &lt;a href="http://www.lonecrusader.co.uk/talks/ec2_pres.pdf"&gt;presentation on Utility Computing with Amazon EC2&lt;/a&gt;.  What I could figure out rekindled my interest in these technologies.&lt;br /&gt;&lt;br /&gt;For example: On my way over to the meeting I was wondering about how best to distribute database load &lt;a href="http://www.oreilly.com/catalog/hpmysql/"&gt;somehow&lt;/a&gt; or &lt;a href="http://blog.spiralarm.com/richard/2006/12/billion-hits-a-day-ebay-javaone.pdf"&gt;other&lt;/a&gt;.   When I walked into the meeting, the presentation was discussing doing-away with things like relational databases to obtain big scalability, and shifting mindsets away from Java EE. Ah. So think different.&lt;br /&gt;&lt;br /&gt;Why would you bother?  I think I'm finally starting to get utility computing.  If you've worked in an environment where budgets for hardware involve a lot of hoop-jumping, it suddenly makes sense to be able to call on a dynamic network of resources at the moment you need it.  What's more, it's looking like it's &lt;a href="http://www.amazon.com/b?ie=UTF8&amp;node=201591011&amp;me=A36L942TSJ2AJA#ecc16"&gt;cheap&lt;/a&gt;.  There's effort in building systems that take advantage of that kind of an environment, but if the cost savings are there, the pressure will come to build them that way.&lt;br /&gt;&lt;br /&gt;It's interesting stuff, and now I have a larger-than-usual reading list as a result: &lt;a href="http://labs.google.com/papers/mapreduce.html"&gt;MapReduce&lt;/a&gt;, &lt;a href="http://labs.google.com/papers/bigtable.html"&gt;Bigtable&lt;/a&gt;, &lt;a href="http://labs.google.com/papers/chubby.html"&gt;Chubby&lt;/a&gt;, &lt;a href="http://labs.google.com/papers/gfs-sosp2003.pdf"&gt;Google File System&lt;/a&gt;, &lt;a href="http://wiki.apache.org/lucene-hadoop/"&gt;Hadoop&lt;/a&gt; the&lt;br /&gt;&lt;a href="http://www.jini.org/wiki/10th_JCM_Sessions"&gt;10th Jini Community Meeting&lt;/a&gt; papers and the Amazon &lt;a href="http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=84"&gt;Web Services Developer Connection&lt;/a&gt; docs.&lt;br /&gt;&lt;br /&gt;The next Next Net will be Thur 18 Jan 2007 at Brunel.</description><link>http://blog.spiralarm.com/richard/2006/12/next-net.html</link><author>noreply@blogger.com (Richard)</author></item></channel></rss>