<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Supple software</title>
    <link>http://supplesoftware.com/</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Supple software</description>
    <item>
      <title>Tilting the platform</title>
      <description>&lt;p&gt;Ok, prepare for this, cause this is the most psychological I&amp;#8217;ve ever been on this blog, but I am going to write it, just for the hell of it and because I keep seeing it in my real work life. Picture this: You and your girlfriend have lost/left your keys. You sit in front of your house. Imagine this exchange:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I can&amp;#8217;t believe it&amp;#8217;s happened again! We should leave a set of keys with our neighbour!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Yeah, but what happens if she&amp;#8217;s away right when we lose our keys??&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And you do nothing. This is unhelpful. You should have thought before having a girlfriend who starts most of her sentences with &amp;#8220;But&amp;#8230;&amp;#8221; or even worse, &amp;#8220;Yes, but&amp;#8230;&amp;#8221; And yet, it&amp;#8217;s not her fault. She&amp;#8217;s preserving the status. If you gave a key to your neighbour, this would tilt the relationship between you, your girlfriend and your neighbour.&lt;/p&gt;

&lt;p&gt;Well, sadly, this happens a lot at work, and that&amp;#8217;s why a lot of bad stuff (software, habits, mentalities, you name it) never changes. If you need to know more about this whole thing and how it works on psycho-level, read Impro for Storytellers by Keith Johnstone. It&amp;#8217;s rather amazing and, in a bizarre way, explains a lot of the daily going-ons in a development team.&lt;/p&gt;</description>
      <pubDate>Sun, 10 Aug 2008 12:46:19 PDT</pubDate>
      <guid>http://supplesoftware.com/articles/2008/08/10/tilting-the-platform</guid>
      <link>http://supplesoftware.com/articles/2008/08/10/tilting-the-platform</link>
      <trackback:ping>http://supplesoftware.com/articles/trackback/66</trackback:ping>
    </item>
    <item>
      <title>Persistence not supported for this MBean</title>
      <description>&lt;p&gt;I was getting an MBeanException with this message when I used jconsole to call a Spring exported MBean method called load(). Other methods (both attributes and operations) seemed to work fine. I may still be totally wrong, but I think that was because of the name of the method. I tried a lot of things for almost half a day, cleared the body of the method, changed attributes, changed the Spring config in many ways, changed names of beans and all sorts of other things - nothing worked. Eventually I stumbled upon this - &lt;a href="http://www.codase.com/search/smart?join=class+javax.management.modelmbean.RequiredModelMBean" &gt;piece of seemingly irrelevant code&lt;/a&gt;. It struck me though that the method that does nothing but throw an exception with a strangely matching message (this string yields only six matches in google) is called load(). I changed the method name and it worked.&lt;/p&gt;

&lt;p&gt;So, what goes on inside is beyond me at this time, and I can&amp;#8217;t be bothered to investigate right now, but if you&amp;#8217;re going to export a @ManagedOperation through Spring do not call the method load().&lt;/p&gt;</description>
      <pubDate>Sat,  7 Jun 2008 15:04:00 PDT</pubDate>
      <guid>http://supplesoftware.com/articles/2008/06/07/persistence-not-supported-for-this-mbean</guid>
      <link>http://supplesoftware.com/articles/2008/06/07/persistence-not-supported-for-this-mbean</link>
      <trackback:ping>http://supplesoftware.com/articles/trackback/65</trackback:ping>
    </item>
    <item>
      <title>Do you really want to use proprietary app servers?</title>
      <description>&lt;p&gt;If someone needs a proof that proprietary app servers must die (that&amp;#8217;s if the hours you spend dealing with annoying little problems isn&amp;#8217;t enough proof), have a look at this piece of code that somehow has appeared in the open source space, but is also used by BEA&amp;#8217;s ejbgen under a different package structure.&lt;/p&gt;

&lt;p&gt;Have a look at the &lt;a href="http://fisheye.codehaus.org/browse/~raw,r=10/annogen/annogen/trunk/jam/core/src/org/codehaus/jam/internal/javadoc/JavadocClassloadingException.java"&gt;JavaClassLoadingException&lt;/a&gt; and &lt;a href="http://fisheye.codehaus.org/browse/~raw,r=34/annogen/annogen/tags/release-0_1_0/jam/core/src/org/codehaus/jam/internal/javadoc/JavadocRunner.java"&gt;JavadocRunner&lt;/a&gt; classes. Especially the use of the JavadocException - with the static method call and all the rest that is going on. I bet the rest of BEA code is full of idiotic use of exceptions and all sorts of other rubbish. Which is why it is a pain&amp;#8230; It&amp;#8217;s just low quality code, especially compared to the constantly reviewed and improved stuff that comes from the open-source projects that last.&lt;/p&gt;

&lt;p&gt;Now, I understand this was done in 2004, but I&amp;#8217;ll argue that BEA&amp;#8217;s developers have not got any better with the years, if anything they&amp;#8217;ve probably done a fair bit of cost-cutting and migrated to using the grads who couldn&amp;#8217;t make it to a bank and paying them peanuts. &lt;/p&gt;</description>
      <pubDate>Wed, 14 May 2008 05:10:23 PDT</pubDate>
      <guid>http://supplesoftware.com/articles/2008/05/14/do-you-really-want-to-use-proprietary-app-servers</guid>
      <link>http://supplesoftware.com/articles/2008/05/14/do-you-really-want-to-use-proprietary-app-servers</link>
      <trackback:ping>http://supplesoftware.com/articles/trackback/64</trackback:ping>
    </item>
    <item>
      <title>How to win a pointless argument</title>
      <description>&lt;p&gt;By not trying&amp;#8230; Here&amp;#8217;s what Sir Christopher Wren did in Windsor. It&amp;#8217;s somewhat bizarre that I lived in Windsor and ran past that same building practically every morning and never knew about it.&lt;/p&gt;

&lt;p&gt;Christopher Wren was already one of the most respected architects in the country when some daft public servant questioned his design on safety basis, and asked for two additional columns to be built for extra support. Wren built them. Look here to see how - &lt;a href="http://inel.wordpress.com/2007/02/09/sir-christopher-wrens-joke-in-windsor-guildhall/"&gt;http://inel.wordpress.com/2007/02/09/sir-christopher-wrens-joke-in-windsor-guildhall/&lt;/a&gt;. They did not touch the ceiling. Many years later, they still don&amp;#8217;t touch the ceiling.&lt;/p&gt;

&lt;p&gt;As I mentioned earlier, I never knew that during the seven years I lived about half a mile away from this building. I&amp;#8217;ve just found this out, from a book, whose main subject is how to ruthlessly manipulate people&amp;#8230; Ah, well, you live and learn&amp;#8230;&lt;/p&gt;</description>
      <pubDate>Sun, 27 Apr 2008 15:38:44 PDT</pubDate>
      <guid>http://supplesoftware.com/articles/2008/04/27/how-to-win-a-pointless-argument</guid>
      <link>http://supplesoftware.com/articles/2008/04/27/how-to-win-a-pointless-argument</link>
      <trackback:ping>http://supplesoftware.com/articles/trackback/63</trackback:ping>
    </item>
    <item>
      <title>QCon talk by Peter Rodgers about REST</title>
      <description>&lt;p&gt;Actually, not just about REST. Those guys spent some time analysing the structure and workings of the web, and asked themselves why it was so efficient and malleable. While most other software was brittle, messy, and unreliable. They found some basic truths about the web, such as, the cost of change is much lower than the added value of that change, therefore it&amp;#8217;s worth changing the system.&lt;/p&gt;

&lt;p&gt;Anyway, they figured that it&amp;#8217;s the &amp;#8220;uniform well-observed address space&amp;#8221;, which allows the latest bleeding edge Firefox three to connect to some apache server which may have been running for twenty years. It is also the thing that allows resources to be cached in a way that is self-optimising, much like a system acting under the laws  ofthermodynamics (the guy&amp;#8217;s from a physics background). Incidentally, it is also the main premise behind REST. So apparently, they&amp;#8217;ve figured a way to build systems that have similar properties. Their thing is here - &lt;a href="http://www.1060research.com/"&gt;http://www.1060research.com/&lt;/a&gt;. It&amp;#8217;s very impressive in purely philosophical terms and in the implications it has for software developments as a whole.&lt;/p&gt;

&lt;p&gt;I reckon some of these concepts can be applied in practice without actually buying their product, NetKernel&amp;#8230; &lt;/p&gt;

&lt;p&gt;By the way more on this can be found in Roy Fielding&amp;#8217;s dissertation here - &lt;a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm"&gt;http://www.ics.uci.edu/~fielding/pubs/dissertation/rest&lt;em&gt;arch&lt;/em&gt;style.htm&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Sun, 16 Mar 2008 08:44:00 PDT</pubDate>
      <guid>http://supplesoftware.com/articles/2008/03/16/qcon-talk-by-peter-rodgers-about-rest</guid>
      <link>http://supplesoftware.com/articles/2008/03/16/qcon-talk-by-peter-rodgers-about-rest</link>
      <trackback:ping>http://supplesoftware.com/articles/trackback/62</trackback:ping>
    </item>
    <item>
      <title>Book: Psychology of Computer Programming</title>
      <description>&lt;p&gt;If you haven&amp;#8217;t read this, read it now - &lt;a href="http://www.bookdepository.co.uk/WEBSITE/WWW/WEBPAGES/showbook.php?id=0932633420"&gt;http://www.bookdepository.co.uk/WEBSITE/WWW/WEBPAGES/showbook.php?id=0932633420&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can not believe I have only found this book recently - it&amp;#8217;s been around for 25 years! How good is that for a computer book. I reckon that&amp;#8217;s because programming is not as much about technologies as it is about human behaviour, thought and self-awareness.&lt;/p&gt;

&lt;p&gt;Gerry Weinberg explains, in his extremely effective and efficient style, familiar from Secrets of Consulting, what this stuff is all about.&lt;/p&gt;

&lt;p&gt;Thanks to Ludo, on whose desk I spotted it. When you read it, pass it on - it can only do good to everyone who reads it and their immediate surrounding.&lt;/p&gt;</description>
      <pubDate>Sun, 17 Feb 2008 13:02:56 PST</pubDate>
      <guid>http://supplesoftware.com/articles/2008/02/17/book-psychology-of-computer-programming</guid>
      <link>http://supplesoftware.com/articles/2008/02/17/book-psychology-of-computer-programming</link>
      <trackback:ping>http://supplesoftware.com/articles/trackback/61</trackback:ping>
    </item>
    <item>
      <title>Java enums over IIOP</title>
      <description>&lt;p&gt;If you pass an enum argument over IIOP, the value in the deserialised object on the server has very strange properties. Here&amp;#8217;s what I observed (someEnum is the deserialised object on the server):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;pre&gt;
someEnum = null
someEnum.name() = null
someEnum.toString() = null
(someEnum == null) = false
&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Clearly a fairly useless instance for any possible purpose. It&amp;#8217;s null, but not quite. It has no value and can not be meaningfully compared.&lt;/p&gt;

&lt;p&gt;You can&amp;#8217;t work around it with Externalizable, because the immutable enum can not modify itself, and for the same (perfectly valid) reason write/readObject are useless. &lt;/p&gt;

&lt;p&gt;This was reported in May 2005 - here - &lt;a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6277781"&gt;http://bugs.sun.com/bugdatabase/view&lt;em&gt;bug.do?bug&lt;/em&gt;id=6277781&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last comment on that entry, made in Aug 2007 says: &amp;#8220;btw, is someone working on that?&amp;#8230;&amp;#8221;.&lt;/p&gt;

&lt;p&gt;Seems either people who use Java 5 and later do not use IIOP and vice versa, or you&amp;#8217;d have thought someone would have done something by now&amp;#8230;.&lt;/p&gt;

&lt;p&gt;Any super-clever ideas for a workaround are most welcome.&lt;/p&gt;

&lt;p&gt;&amp;#8220;Don&amp;#8217;t use enums&amp;#8221; and &amp;#8220;don&amp;#8217;t use IIOP&amp;#8221; do not count as super-clever on this occasion.&lt;/p&gt;</description>
      <pubDate>Sun, 17 Feb 2008 10:42:00 PST</pubDate>
      <guid>http://supplesoftware.com/articles/2008/02/17/java-enums-over-iiop</guid>
      <link>http://supplesoftware.com/articles/2008/02/17/java-enums-over-iiop</link>
      <trackback:ping>http://supplesoftware.com/articles/trackback/60</trackback:ping>
    </item>
    <item>
      <title>And more code (no need to wait)</title>
      <description>&lt;p&gt;Thanks to &lt;a href="http://yuri.baulsupp.com/"&gt;Yuri&lt;/a&gt; for pointing out that you don&amp;#8217;t need to wait until all the results are done to start processing them. Here, we&amp;#8217;ve only got integers, but in reality it is likely that the individual results will be big and meaningful and actually take some time to interpret or do something with. To start working on them as soon as each one is ready, we use CompletionService:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
public class ParallelCompletionCounter {
    public int countWordsAsSoonAsFileFinishes(List&lt;File&gt; files) {
        CompletionService&lt;Integer&gt; completionService = new ExecutorCompletionService&lt;Integer&gt;(Executors.newFixedThreadPool(4));
        for(final File file : files) {
            Callable&lt;Integer&gt; counter = new Callable&lt;Integer&gt;() {
                public Integer call() {
                    System.out.println("Starting file " + file.getName() + " at " + System.currentTimeMillis());
                    int time = 500;
                    if (file.getName().contains("304")) {
                        time = 5000;
                    }
                    try {
                        Thread.sleep(time);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    WordCounter counter = new WordCounter();
                    int count =  counter.count(file);
                    System.out.println("Done file " + file.getName() + " at " + System.currentTimeMillis());
                    return count;
                }
            };
            completionService.submit(counter);
        }
        try {
            int totalCount = 0;
            for (int i = 0; i&lt;4; i++) {
                totalCount += completionService.take().get();
                System.out.println("Added File Count");
            }
            return totalCount;
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        ParallelCompletionCounter counter = new ParallelCompletionCounter();
        List&lt;File&gt; files = new ArrayList&lt;File&gt;(args.length);
        for (String filename : args) {
            files.add(new File(filename));
        }
        System.out.println("Total word count is " + counter.countWordsAsSoonAsFileFinishes(files));
        System.out.println("Total elapsed time " + (System.currentTimeMillis() - start));
    }   
}
&lt;/code&gt;&lt;/pre&gt;</description>
      <pubDate>Fri, 23 Nov 2007 01:53:18 PST</pubDate>
      <guid>http://supplesoftware.com/articles/2007/11/23/and-more-code-no-need-to-wait</guid>
      <link>http://supplesoftware.com/articles/2007/11/23/and-more-code-no-need-to-wait</link>
      <trackback:ping>http://supplesoftware.com/articles/trackback/59</trackback:ping>
    </item>
    <item>
      <title>More code</title>
      <description>&lt;p&gt;I&amp;#8217;ve been exploring the java.util.concurrent package, and just thought I post some more code:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/p&gt;

&lt;pre&gt;
public class ParallelCounter {

    public int countWords1(List&lt;File&gt; files) {
        ExecutorService executorService = Executors.newFixedThreadPool(4);
        List&lt;Callable&lt;Integer&gt;&gt; counters = new ArrayList&lt;Callable&lt;Integer&gt;&gt;();
        for(final File file : files) {
            counters.add(new Callable&lt;Integer&gt;() {
                public Integer call() {
                    System.out.println("Starting file " + file.getName() + " at " + System.currentTimeMillis());
                    WordCounter counter = new WordCounter();
                    int count =  counter.count(file);
                    System.out.println("Done file " + file.getName() + " at " + System.currentTimeMillis());
                    return count;
                }
            });
        }
        try {
            List&lt;Future&lt;Integer&gt;&gt; results = executorService.invokeAll(counters);
            int totalCount = 0;
            for (Future&lt;Integer&gt; future : results) {
                totalCount += future.get();
            }
            return totalCount;
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        ParallelCounter counter = new ParallelCounter();
        List&lt;File&gt; files = new ArrayList&lt;File&gt;(args.length);
        for (String filename : args) {
            files.add(new File(filename));
        }
        System.out.println("Total word count is " + counter.countWords1(files));
        System.out.println("Total elapsed time " +
(System.currentTimeMillis() - start));
    }
}
&lt;/pre&gt;

&lt;p&gt;&lt;/code&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 22 Nov 2007 05:06:12 PST</pubDate>
      <guid>http://supplesoftware.com/articles/2007/11/22/more-code</guid>
      <link>http://supplesoftware.com/articles/2007/11/22/more-code</link>
      <trackback:ping>http://supplesoftware.com/articles/trackback/58</trackback:ping>
    </item>
    <item>
      <title>The five philosophers</title>
      <description>&lt;p&gt;Here&amp;#8217;s my little implementation of the five philosophers problem.&lt;/p&gt;

&lt;p&gt;The chopstick:
&lt;code&gt;&lt;/p&gt;

&lt;pre&gt;
package philosophers;

public class Chopstick {

    private int number;

    public Chopstick(int number) {
        this.number = number;
    }
    public int getNumber() {
        return number;
    }
}
&lt;/pre&gt;

&lt;p&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The philosopher:
&lt;code&gt;&lt;/p&gt;

&lt;pre&gt;
package philosophers;

public class Philosopher implements Runnable {

    private int number;

    private Chopstick leftChopstick;

    private Chopstick rightChopstick;

    public Philosopher(int number, Chopstick leftChopstick,
            Chopstick rightChopstick) {
        this.number = number;
        this.leftChopstick = leftChopstick;
        this.rightChopstick = rightChopstick;
    }

    private void eat(int time) {
        synchronized (leftChopstick) {
            System.out.println("Philosopher " + this.number
                    + " took chopstick " + leftChopstick.getNumber()
                    + " from the left.");
            synchronized (rightChopstick) {
                System.out.println("Philosopher " + this.number
                        + " took chopstick " + rightChopstick.getNumber()
                        + " from the right.");
                try {
                    System.out.println("Philosopher " + this.number
                            + " is eating...");
                    Thread.sleep(time);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    private void think(int time) {
        try {
            System.out.println("Philosopher " + this.number + " is thinking...");
            Thread.sleep(time);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public void run() {
        while (true) {
            think(1);
            eat(1);
        }
    }

}
&lt;/pre&gt;

&lt;p&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And, bringing them all together, the Table:
&lt;code&gt;&lt;/p&gt;

&lt;pre&gt;
package philosophers;

public class Table {

    /**
     * Chopstick 0 is on the left of phylosopher 0
     */
    private Chopstick[] chopsticks;

    private Philosopher[] philosophers;

    public void build(int numberOfSeats) {
        for (int i = 0; i &lt; numberOfSeats; i++) {
            chopsticks[i] = new Chopstick(i);
        }
        for (int i = 0; i &lt; numberOfSeats; i++) {
            philosophers[i] = new Philosopher(i, chopsticks[i],
                    chopsticks[i &lt; numberOfSeats - 1 ? i + 1 : 0]);
        }
    }

    public Table(int numberOfSeats) {
        chopsticks = new Chopstick[numberOfSeats];
        philosophers = new Philosopher[numberOfSeats];
        build(numberOfSeats);
    }

    public void start() {
        System.out.println("Chopstick 0 is on the left of philosopher 0");
        for (Philosopher philosopher : philosophers) {
            new Thread(philosopher).start();
        }
    }

    public static void main (String[] args) {
        new Table(5).start();
    }
}
&lt;/pre&gt;

&lt;p&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Deadlocks pretty quickly with the numbers as they are here.&lt;/p&gt;</description>
      <pubDate>Tue, 20 Nov 2007 01:54:00 PST</pubDate>
      <guid>http://supplesoftware.com/articles/2007/11/20/the-five-philosophers</guid>
      <link>http://supplesoftware.com/articles/2007/11/20/the-five-philosophers</link>
      <trackback:ping>http://supplesoftware.com/articles/trackback/57</trackback:ping>
    </item>
  </channel>
</rss>
