Blog posts
-
Principle of least surprise
gareth@logicalpractice.com (Gareth) Published: March 29, 2010So it's a pretty easy principle generally things (API's and the like) should generally do the least surprising thing. Reactions like 'What the f***' are a pretty good example of this principle being broken. Imagine my suprise when I found what the following groovy does:
-
screen scrapping using YQL
gareth@logicalpractice.com (Gareth) Published: October 31, 2009Just attended the Cambridge DevDay, which I really enjoyed.Christian Heilmann talked about the Yahoo query language, a very powerful tool for querying not only Yahoo dataset but arbitrary third party ones as well as a bit of URL fetching. The YQL stuff that Christian demo'd was pretty slick, but the bit that really caught my eye was the following little snippit:
select * from html where url="http://finance.yahoo.com/q?s=yhoo" and
xpath='//div[@id="yfi_headlines"]/div[2]/ul/li/a'Try it for your self over at the YQL console.So I thought I'd have a bit of a bash at screen scraping my SO profile page to see it I can my answer list on my site.
<c:import url="http://query.yahooapis.com/v1/public/yql" var="feed">
<c:param name="q">select * from html where url="http://stackoverflow.com/users/31480/gid" and
xpath='//div[@class="answer-summary"]'</c:param>
<c:param name="format" value="xml"/>
</c:import>
<x:parse var="xml">${feed}</x:parse>
<ul class="so-answers">
<x:forEach select="$xml/query/results/div[@class='answer-summary']" var="answer"
end="10" >
<li class="answer">
<x:set var="votes" select="$answer/div[contains(@class,'answer-votes')]"/>
<div class="<x:out select="$votes/@class"/>"
title="<x:out select="$votes/@title"/>">
<x:out select="$votes"/>
</div>
<x:set var="a" select="$answer//a[contains(@class,'answer-hyperlink')]"/>
<div class="answer-link">
<a href="http://stackoverflow.com/<x:out select="$a/@href"/>">
<x:out select="$a"/>
</a>
</div>
</li>
</x:forEach>
</ul>
Check it out runningIn theory it I could actually point the abovestatement directly at stackoverflow, but the rather picky xerces parser (used under the covers of the) complains bitterly about DTD's and all that jazz. The YQL fetch has the nice side effect of tidying up any html ugly ness and spits out easily parsable XML. -
0.10 of logicalpractice-collections released
gareth@logicalpractice.com (Gareth) Published: June 2, 2009No really major changes to note. Main reason for the release is a packaging change that makes the library available via it's own maven repo, see maven setup instructions.
-
Python is just a lovely thing
gareth@logicalpractice.com (Gareth) Published: March 21, 2009I've used quite a few dynamic scripting languages over the last couple of years including groovy, ruby and python, but I keep coming back to python. I think this time it's due to Peter Butler's (a guy I worked with a while ago) complete love of the language and I think I'm starting to see why.
-
Java assert - what I learnt today
gareth@logicalpractice.com (Gareth) Published: February 11, 2009I learnt something new today, the following I thought would be just fine:File f = new File("foo.txt");if( f.exists() )assert f.delete();That all looked good to me, right up to the point that I discovered that an assert expression isn't even evaluated if asserts are not enabled, had to change it to.if( f.exists() ){boolean deleted = f.delete();assert deleted;} -
running sureFire twice in a build
gareth@logicalpractice.com (Gareth) Published: February 8, 2008I've run into this a couple of times in my experience with maven2. A single module web project, nothing to complex, just some servlets and a simple data access layer. What I wanted to be able to do was run both unit tests and integration tests both written with JUnit. So initially I started with:
This seemed like at least half the solution. It moves the test run to integration-test, where both the unit test and integration tests run. Not so bad I figured, I worked with this for the last couple of months and it's been bugging me. Last week I came up with:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>integration-test</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<skip>false</skip>
</configuration>
</execution>
</executions>
</plugin>
It requires that the tests are named correctly, but that isn't such a big deal. So now the test phase runs just the unit tests (named *Test.java) and integration-test runs everything but in two phases, first "test" and second in integration-test.<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<skip>false</skip>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
</excludes>
</configuration>
</execution>
<execution>
<id>integration-test</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<skip>false</skip>
<includes>
<include>**/*IntegrationTest.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
-
a bit of fun with collections
gareth@logicalpractice.com (Gareth) Published: January 26, 2008A while ago a friend introduced me to hamcrest matchers and soon after that I started looking in to how I could start to use these to make working with collections. I've spent a little while working with dynamic languages such as groovy, ruby and python and they have got under my skin. In the java world you just don't have the flexiblity of fancy closures and chained method calls.
In order to satisfiy my craving for collection tools, what I really want to do is what this guy claims to be able to do. I first looked at Sam Newman's hamcrest-collections project, it's good, but it didn't do what I really wanted completely.
So in true if it wasn't invented here style I've written my own collections library.
http://code.google.com/p/logicalpractice-collections/
It's not 100% complete, but it does allow you to do some quite clever stuff:
smiths = select(from(people).getLastName(), equalToIgnoringCase("smith"));
Give it a go and let me know what you think.