|
Groovy at JavaOne 2007
|
|
|
|
Posted on 14 May 2007
|
|
|
Here is a round up of bloggers feedback about Groovy from JavaOne2007
- Positive
- Bernard Ng
- Sausheong
- Ben Teese [1], [2]
- Charles Ditzel [1], [2]
- Demian
- Michael Kovacs
- Andres Almiray [1],
[2]
- Peter Pilgrim
- Chirag Mehta
- Matt Stine [1],
[2],
[3]
- Jason [1],
[2]
- Maryland Pok Guy
- Lucas Jellema [1],
[2]
- Michael Yuan
- Antoni Batchelli
|
- Neutral
- Keyur Shah
- Tony
- Cameron Purdy
- Frank Coyle
- Igor Minar
- Brendon Humphreys
- Negative
- Ola Bini [1],
[2]
- Cay Horstmann [1],
[2],
[3]
- Hani Suleiman
|
- Friends
- Geertjan Wielenga (Netbeans plugin)
- Graeme Rocher [1],
[2],
[3],
[4] (Grails Lead)
- Jason Rudolph [1]
[2]
[3]
- Ian Roughley (InfoQ)
|
- JavaFx
- Cedric Beust + comments
- Danno Ferrin
- Ron Hitchens
- Steve Giovannetti
|
It looks like we managed to enthuse some people about Groovy and we even
made it to the best seller list (#5)
Special thanks to Guillaume Laforge,
Dierk König,
Rod Cope,
Vladimir Vivien
Graeme Rocher
and anyone else who talked about Groovy at JavaOne, either on stage, or in the corridors. Nice one.
|
|
|
|
|
|
Third Groovy Developers Conference
|
|
|
|
Posted on 01 Feb 2007
|
|
|
|
|
Groovy 1.0 released!
|
|
|
|
Posted on 03 Jan 2007
|
|
|
Groovy 1.0 has finally been released.
It has been a long road, lasting over three years,
but at last I can recommend Groovy as a stable,
production proven and well documented programming
language for the Java platform.
(not to mention a very helpful and large user community)
This release coincides with the launch of the Manning
book Groovy in Action,
which gives an in depth reference to Groovy 1.0
[Full Disclosure: I'm a core committer for Groovy and I was a technical reviewer for this book]
Groovy 1.0 Highlights:
- A formal syntax based closely on Java 1.5, with added Groovy bits.
- Groovy can easily run source from the command line, ant, embedded in code
(simply place groovy-all-1.0.jar in your classpath)
- Close ties with Spring, Lucene and other real world Java products.
- Fantastic for reducing the verbosity of common tasks in Java
quick start: example installation to /usr/local
$ cd /usr/local
$ wget http://dist.codehaus.org/groovy/distributions/groovy-1.0.tar.gz
$ tar xvfz groovy-1.0.tar.gz
$ export GROOVY_HOME=/usr/local/groovy-1.0
$ export PATH=${GROOVY_HOME}/bin:$PATH
$ groovy -e "println 'hello world'"
To coincide with this release, I have also released version 0.0.2 of the JVM command line interpreter Grash.
I'll be giving a Talk about the Groovy Compiler on 25 Jan 2007 in London, please come along to that, and the pub afterwards, to discuss all things Groovy.
I will be at the Groovy Developers Conference in Paris (starts 29 Jan 2007)
to discuss the future direction of Groovy, in particular enhanced IDE support.
In May 2007 there will be a three day Groovy and Grails conference at the Barbican, which will be perfect for anyone interested in this language to meet the core developers, and discover the cutting edge progress in Groovy.
But most of all, Groovy 1.0 would not be where it is today without the work of the open source community. I'd like to thank each person for their work in making Groovy a fantastic language:
Committers:
Guillaume Laforge (glaforge), Jochen Theodorou (blackdrag), Jeremy Rayner (jez),
John Wilson (tug), Russel Winder (russel), James Strachan (jstrachan),
Dierk Koenig (dierk), Christian Stein (cstein), Paul King (paulk),
Joe Walnes (joe), Chris Stevenson (skizz), Jamie McCrindle (jamiemc),
Matt Foemmel (mattf), Sam Pullara (spullara), Kasper Nielsen (kasper),
Travis Kay (travis), Zohar Melamed (zohar), Bob McWhirter (bob),
Chris Poirier (cpoirier), Christiaan ten Klooster (ckl), Steve Goetze (goetze),
Bing Ran (bran), John Stump (jstump), Pilho Kim (phk), Mark Chu-Carroll (markcc),
Alan Green (alang), Edward Povazan (emp), Franck Rasolo (fraz),
John Rose (jrose), Graeme Rocher (graeme), Guillaume Alleon (galleon),
Antti Karanta (akaranta), Dave Kerber (davekerber), Hein Meling (hmeling),
Joachim Baumann (jbaumann), James E. Ervin (jervin), Scott Hickey (jshickey),
Martin C. Martin (mcspanky), Marc Guillemot (mguillem), Aslak Hellesoy (rinkrank),
Steven Devijver (sdevijver), Scott Stirling (sstirling), Yuri Schimke (yuri)
Contributors:
Joern Eyrich, Robert Kuzelj, Rod Cope,
James Birchfield, Robert Fuller, Sergey Udovenko
Hallvard Traetteberg, Peter Reilly, Brian McCallister
Richard Monson-Haefel, Brian Larson, Artur Biesiadowski
Ivan Z. Ganza, Arjun Nayyar, Mark Turansky, Jean-Louis Berliet,
Graham Miller, Marc Palmer, Tugdual Grall, and many many
many other contributors and organisations.
Thankyou All (and apologies if I missed anyone, so many people...) :-)
P.S. an improved java2groovy is now in the core distribution of groovy 1.0 :-)
|
|
|
|
|
|
java2groovy
|
|
|
|
Posted on 29 Dec 2006
|
|
|
Having just finished the first full run through of a groovy pretty printer,
I thought I'd flex it's muscles by creating a useful command line program...
java2groovy [file ...]
Description:
The java2groovy tool reads class and interface definitions, written in the
Java programming language, and converts them into groovy source files.
to do this...
- I took the original java.g grammar which groovy.g is based upon
- amended it to remove Java features not implemented in groovy.g
("do" keyword, Array Initialisers etc)
- Created a Java2GroovyMain which takes Java files and parses into a
Java like source AST
- Converted the Java like source AST into a one for one Groovy equivalant
- Applied a Groovifier, which applies common simplification tasks to
the AST (e.g. don't need public keyword if you have other modifiers)
- Then the resultant groovy AST is output using the "pretty printer"
(not in subversion yet RC3? post 1.0?)
So... job done, what's next :-)
Seriously though...
- java.g needs to be amended some more to use create() instead of #[],
otherwise line/col nums are lost
- Groovifier.java is an interesting step, lots of tiny refactorings,
at the source AST level, very powerful...
//----
// (e.g. don't need public keyword if you have other modifiers)
//
if (t.getType() == MODIFIERS) {
GroovySourceAST publicNode = t.childOfType(LITERAL_public);
if (t.getNumberOfChildren() > 1 && publicNode != null) {
// has more than one modifier, and one of them is public
// delete 'public' node
publicNode.setType(EXPR);
}
//----
- some minor changes to things like string literals (get a double double-quote each time at mo...)
- all pretty printer issues apply (no comments on AST etc)
java2groovy is now included in Groovy 1.0 (download here)
(very very beta) NO DOCS, NO WARRANTIES etc etc
Oh yes... a sample...
$ java2groovy src/test/groovy/lang/MockWriter.java
/*
Automatically Converted from Java Source
by java2groovy v0.0.1 Copyright Jeremy Rayner 2007
!! NOT FIT FOR ANY PURPOSE !!
'java2groovy' cannot be used to convert one working program into another
*/
package groovy.lang
class MockWriter
{
private String output
String getOutput() {
String answer = output
output = null
return answer
}
void setOutput(String
output) {
}
void println() {
setOutput(""println()"")
}
void println(Object
object) {
setOutput(""println("" + object + "")"")
}
void print(Object
object) {
setOutput(""print("" + object + "")"")
}
}
|
|
|
|
|
|
Second Groovy Conference
|
|
|
|
Posted on 28 Nov 2005
|
|
|
Starting out on a chilly November morning, with just a Burger King
breakfast for company, I found myself checking in for the Eurostar
to Paris. I boarded the train, and found I had two hours of my
own time (a rare thing these days) and therefore decided to bring
some of my projects up to speed with the latest Groovy release
(JSR-04)
First off was my pet wiki server called biscuit, which was a
simple affair needing changes only to variables not initialized
with a type or the 'def' keyword. As I finish this task before
arriving at the channel tunnel I decided to sink my teeth into
a meatier topic, and look into providing tab completion for my
Groovy shell called grash. The excellent jline library hooks
for completion, so I quickly hook this up to the 'ls' function
in grash and feel great as I navigate my object tree using
the same nifty functionality I know in my favourite unix shells.
I then started bringing grash up to the latest Groovy release,
but after the initial 'def' updates, I quickly realise that
something else is afoot. It appears that providing user defined
commands and attaching them to objects has broken. A quick debugging
session shows that for some reason the GroovyClassLoader is being
told to load two versions of the reflector for the same script.
At this point I get a phone call from James Strachan, it appears
that he caught the train by the skin of his teeth, and after fighting
his way down the carriages we meetup, just as we pull into Paris.
As we stand in the queue for the taxis, James and myself discuss
the xbean project and how to best integrate Groovy closures into
Springs template callback mechanisms. In order to prevent writing
wrapper classes over the top of every spring template, James suggests
adding functionality to groovy to allow single method interfaces to
be automatically implemented by Closures, in much the same way as
Listeners are implementable by Closures today. As James pulls out
his laptop and starts showing me where these hooks would reside, I
can tell that this is going to be a good JSR meeting, and one which
would justify using two days of my own holiday and the excessive
eurostar fares which I paid for.
We arrive, after a hairy taxi ride around the 'Arc de Triumphe'
at the Sun offices in Paris. Guillaume excitedly takes us up
to the 'Jupiter' room on the third floor, where I finally get
to meet blackdrag, our debugger extraordinaire, and Dierk who
has been writing Groovy in Action. We are delighted to find that
Sun have provided an internet connection, and Guillaume has
already uploaded photos to flickr for the watching world to see.
Having missed the morning session due to our travel, we are quickly
brought up to speed. Finally we will get to talk about name resolution
and scoping. The topic for the first day appears to be name resolution,
with most of the discussion centring around how best to cope with vanilla
names.
After a lunch paid for, very kindly, by Dierk, the discussion
soon turns into a heated debate over the treatment of vanilla names.
class MyScript {
String toString(){
return "foo"
}
void run() {
myList.each{
// does this call MyScript.toString() or myList.toString() ?
println(toString())
}
}
I believe that... Tug argues the enclosing object instance should
listen for and consume names prior to the lexical scope. (i.e. above
example would call myList.toString())
James argues that the default should be lexically bound to the current
context (i.e. above example would call myScript.toString()), and if
the object instance was needed to be referred to that some form of syntax
could be constructed to allow this, e.g. $toString() would be a dynamic
name that could be interpreted differently.
At least, with my laptop pointing at the wiki, and up on the
projector, I ensure that the examples and minutes are being captured
in the wiki and not on the whiteboard.
We appear not to reach a resolution as Vincent Massol arrives to
bring us to the Chinese restaurant for the evening. We all potter
down to the Metro, Guillaume and tug have kindly arranged metro tickets
for us delegates too laden with bags, and soon we arrive across town.
There we meet Xwiki's Ludovic Dubost and Erwan Arzur and Benjamin Mestrallet from eXoPlatform.
A very entertaining evening ensues, with chatter ranging from XWiki through
to 'flaming drunk prawns', and we all end up at Ludovics apartment nearby,
where Erwan introduces us to a bottle of Calvados that he had stowed
away for such occasions. At about 12:30 we stumble back on the last
metro and finally check in to our sleepy hotel. I feel glad to find
a towel in the room, and settle down to a restless Parisian slumber.
(thanks so much to Bob at Codehaus for funding the room)
I awake 5 hours later to the sound of my Blackberry playing 'The
Entertainer', and discover the delights of hot chocolate for breakfast
(no sign of tea, I think coffee is more popular here). We stumble back
to the Sun offices, again Guillaume and tug have the metro sorted.
Day Two starts out more productive, with discussion about opening
up the DefaultGroovyMethods for the layman and we get some agreement about the
'use' keyword and my 'enhances' proposal. However the discussion soon
gets round to the topic of Builders (a.k.a. Markup) and again the name
resolution and scoping bear comes up to bite us again.
We have Tug and Guillaume firmly on the side of Builders being in charge
of everything defined within the markup delimiters. James argues that
markup is fundamentally broken and some kind of syntactic clue that
we are suddenly entering a different 'markup world' where normal
resolution and scoping doesn't apply. For some reason, that I cannot
fathom, Tug and Guillaume both seem vehemently opposed to any indication
in the code that we are in a Builder section. This includes both
the suggestion of a 'with' keyword or .{ notation to indicate to the
reader of the code that something different is about to occur.
String toString() {
return "foo"
}
swingBuilder.frame() {
panel() {
button(toString())
}
}
We were all fairly happy that the Builder could be responsible for
name resolution inside it's own block (e.g. the swingBuilder instance
would be responsible for how it treats toString() inside), but what
seemed to really be a sticking point was the important fact that
due to the dynamic nature of the name resolution/scoping within this
block, some visual clue to the reader of the program was necessary.
James argued for, and I agree that, the use of some kind of syntactic
indication was vital to ensure that the Groovy language was sane,
predictable and maintainable. The above example would look something
like this... (note the .{ syntax indicating a different lexical construct)
swingBuilder.frame().{
panel() {
button(toString())
}
}
or the even clearer...
with (swingBuilder.frame()) {
panel() {
button(toString())
}
}
Thus implying to any compiler, IDE, or human reader that the block
of code was not a true lexical closure, but some other construct
which was dynamic in it's very nature, and thus warnings, code completion
and everything else specification related did not apply, as the
responsibility would lie with the implementation of the builder.
I'm sad to report that no agreement was reached on this matter.
Not so much which syntax would be useful, but actually whether we
should have any syntax denoting the difference between a true
lexical Closure and one of these Builder blocks. The
historical reasons go back to Builder blocks looking just like
Closures, and I'm afraid this long standing mistake must be
removed from the language before any true progress can be made, as
no sensible specification rules can be applied while the dichotomy
exists.
I headed back to London with a very disappointed James Strachan,
the language which has some of the finest minds, and most exciting
ideas now faces a pivotal point in its life, and I'll do everything
I can to ensure that clarity over dynamism wins the day.
My many thanks go to Guillaume for the meeting arrangements, to
Sun for the facilities, to XWiki,eXoPlatform and Vincent Massol for the
Chinese, Dierk for the Lunch, and Bob/GoogleAds for the hotel room.
|
|
|
|
|
|
Lucene and Groovy example
|
|
|
|
Posted on 22 Apr 2005
|
|
|
The Groovy code is used in the following manner, with my example
using some free classic books from Project Gutenberg
to search inside.
$ mkdir bookIndex
$ groovy -cp lucene-1.4.3.jar Indexer bookIndex ~/gutenberg
Indexing~/gutenberg/Bram Stoker/Dracula.txt
Indexing ~/gutenberg/H. G. Wells/The War of the Worlds.txt
Indexing ~/gutenberg/Mark Twain/Adventures of Tom Sawyer.txt
Indexing ~/gutenberg/Oscar Wilde/The Picture of Dorian Gray.txt
Indexing 4 files took 2320 milliseconds
$ groovy -cp lucene-1.4.3.jar Searcher bookIndex indefatigable
Found 1 document(s) (in 30 milliseconds) that matched query 'indefatigable':
/Users/j6wbs/gutenberg/H. G. Wells/The War of the Worlds.txt
$
|
The first example is a script that will build an inverted index
from text files on your hard disc.
Usage: groovy -cp lucene-1.4.3.jar Indexer <index.dir> <text.files.dir>
|
Indexer.groovy (download)
import org.apache.lucene.analysis.standard.StandardAnalyzer
import org.apache.lucene.document.Document
import org.apache.lucene.document.Field
import org.apache.lucene.index.IndexWriter if (args.size() != 2 ) {
throw new Exception(
"Usage: groovy -cp lucene-1.4.3.jar Indexer <index dir> <data dir>")
}
def indexDir = new File(args[0])
def dataDir = new File(args[1]) def start = new Date().time
def numIndexed = index(indexDir, dataDir)
def end = new Date().timeprintln "Indexing $numIndexed files took ${end - start} milliseconds"def index(indexDir, dataDir) {
if (!dataDir.exists() || !dataDir.directory) {
throw new IOException("$dataDir does not exist or is not a directory")
}
def writer = new IndexWriter(
indexDir, new StandardAnalyzer(), true)
writer.useCompoundFile = false dataDir.eachFileRecurse {
if (it.name =~ /.txt$/) {
indexFile(writer,it)
}
}
def numIndexed = writer.docCount()
writer.optimize()
writer.close()
return numIndexed
}void indexFile(writer, f) {
if (f.hidden || !f.exists() || !f.canRead() || f.directory) { return } println "Indexing $f.canonicalPath"
def doc = new Document()
doc.add(Field.Text("contents", new FileReader(f)))
doc.add(Field.Keyword("filename",f.canonicalPath)) writer.addDocument(doc)
}
The second example builds upon the first by providing a command line tool to search the index of text files.
Usage: groovy -cp lucene-1.4.3.jar Searcher <index.dir> <your.query>
|
Searcher.groovy (download)
import org.apache.lucene.analysis.standard.StandardAnalyzer
import org.apache.lucene.queryParser.QueryParser
import org.apache.lucene.search.IndexSearcher
import org.apache.lucene.store.FSDirectory if (args.size() != 2) {
throw new Exception(
"Usage: groovy -cp lucene-1.4.3.jar Searcher <index dir> <query>")
}
def indexDir = new File(args[0])
def q = args[1] if (!indexDir.exists() || !indexDir.directory) {
throw new Exception("$indexDir does not exist or is not a directory")
}def fsDir = FSDirectory.getDirectory(indexDir, false)
def is = new IndexSearcher(fsDir) def query = QueryParser.parse(q, "contents", new StandardAnalyzer())
def start = new Date().time
def hits = is.search(query)
def end = new Date().timeprintln "Found ${hits.length()} document(s) "
println "(in ${end - start} milliseconds) that matched query '$q':"for ( i in 0 ..< hits.length() ) {
println(hits.doc(i)["filename"])
}
Further improvements to these scripts could be made in the future by providing groovy wrappers around common Lucene activities.
This would allow you to supply the domain specific work inside a closure to convenience methods, e.g.
Here is an idea of what it could look like (the following will not work... yet)
...
def index(indexDir, dataDir) {
if (!dataDir.exists() || !dataDir.directory) {
throw new IOException(
"$dataDir does not exist or is not a directory")
}
def lucene = Lucene.newInstance()
def numIndexed = lucene.write(indexDir) {writer->
dataDir.eachFileRecurse {file->
if (file.name =~ /.txt$/) {
indexFile(writer,file)
}
}
}
return numIndexed
}
...
My thanks to Erik and Otis for allowing me to make their examples more Groovy.
|
|
|
|
|
|
Turn your build.xml into a pretty picture using Groovy
|
|
|
|
Posted on 02 Dec 2004
|
|
|
Inspired by Sam Newman (magpiebrain), I decided to see if it was possible to do a quick XSLT style transform using groovy on an ant build.xml file, so that it could be loaded up in FreeMind.
The example diagram below is the result of running groovy antmap.g > build.mm over the build.xml for my groovy shell called grash
A code snippet is below, which I've added to the groovy examples bundle (which is full of cool stuff b.t.w.)
#!/bin/env groovy
#
# convert an ant build file into a format
# suitable for http://sf.net/projects/freemind
#
# by Jeremy Rayner - 2 Dec 2004
# inspired by Sam Newman
# ( http://www.magpiebrain.com/archives/2004/12/02/antgui )
#
# usage: groovy antmap.g > build.mm
import groovy.util.XmlParser
import java.io.File
buildFileName = "build.xml" // default
// handle command line params
if (args.length > 0) {
buildFileName = args[0]
}
// header
println "<map version='0.7.1'>"
project = new XmlParser().parse(buildFileName)
name = project['@name']
println "<node TEXT='${name}'>"
level = 0
printChildren(project,level)
def void printChildren(node,level) {
level++
node.each {
name = huntForName(it)
if (name != null) {
if (level > 1) {
println "<node TEXT='${name}' POSITION='right'>"
} else if (it.name() == 'property' || it.name() == 'path' ) {
if (it.children().size() > 0) {
println "<node TEXT='${name}' POSITION='left' FOLDED='true'>"
} else {
println "<node TEXT='${name}' POSITION='left'>"
}
} else if (it.children().size() > 0) {
println "<node TEXT='${name}' POSITION='right' FOLDED='true'>"
} else {
println "<node TEXT='${name}' POSITION='right'>"
}
}
if (it.children().size() > 0) printChildren(it,level)
if (name!=null)println "</node>"
}
}
// footer
println "</node></map>"
def String huntForName(node) {
preferNodeNames = ["junitreport"]
if (node == null) return null
if (preferNodeNames.contains(node.name())) return node.name()
if (node['@name'] != null) return node['@name']
if (node['@todir'] != null) return node['@todir']
if (node['@dir'] != null) return node['@dir']
if (node['@refid'] != null) return node['@refid']
return node.name()
}
|
|
|
|
|
|
Some more Groovy notes
|
|
|
|
Posted on 17 Nov 2004
|
|
|
Here are some more notes from GC1 (Groovy Conference no.1), some of them might be inaccurate, subsequently changed or just plain wrong, but I might as well share what notes I did take...
Ideas for the specification
whitespace?
whitespace is significant, but it is significant as it applies to 'no dumb expression statement (NDES)' rule
macros?
macros are going to be implemented under the covers, but may not be exposed to user in first syntax spec, indeed 'while' might even be implemented as a macro under the covers...
builders?
builders have turned into lovely things :-)
builders are now intended to be included within the EBNF
this seems to have been achieved by changing the words around :-)
with (MyBuilder) { myPanel { myThing }}
or something
parens?
parens are optional, but again before you leave the planet... only on simple statements, not on expressions
escaping nested closures?
escaping nested closures involved break / return keywords
break without label would break out of tightest closure
break with label would treat closure just like while statement break (+ same with continue)
return would always return from the method (that the closure was called from?)
not sure I remember discussions about breaking with a value..?
I have published jstrachan's scribblings here
here are a few of my favourite things...
'with' keyword
with myFoo.bar.mooky { wibble = 12; wobble = 13}
equiv to...
myFoo.bar.mooky.wibble = 12; myFoo.bar.mooky.wobble=13;
and reused for builder syntax
with myFoo { bar { mooky {new Weeble()}}}
(syntax probably not quite like that)
'?.' operator
foo?.bar
equiv to
(foo != null) ? foo.bar : null
the question mark indicates that foo is questionable, i.e. it could be null, it could be any type etc... (i.e. no compile time errors if property bar doesn't exist on foo)
Anyway, just gives you an idea of some of the topics under discussion, none of it is set in stone. Look forward to comments :-)
|
|
|
|
|
|
First Groovy Conference
|
|
|
|
Posted on 16 Nov 2004
|
|
|
I've just got back from a very interesting two day conference held to
discuss both the Groovy language and JSR 241 which is aiming to
standardize the language.
James spent the first morning outlining his original vision for Groovy
and the direction in which he'd like to take it forward. ( mp3, powerpoint)
|
Groovy is trying to provide a high level language (like Ruby, Python or Dylan)
that maps cleanly to Java bytecode.
It needs to works with Java objects, and the root of all the object trees is
java.lang.Object.
The syntax will be Java friendly, but doesn't have to be backwards compatible.
Groovy will sit on top of J2SE
|
After lunch I walked everyone through the story so far, from the conception
of Groovy back in Aug 2003, up till the present day. (powerpoint)
Guillaume then took us through the user feedback we collected, including the main issues of the moment (powerpoint) which appear to be optionals, documentation, visibility, scoping, debugging, class loading, speed and security.
We then dicussed the roadmap for the Groovy JSR, particularly which key deliverables are
necessary to reach a community release of Groovy.
Key Deliverables for Groovy JSR Community Release
- Specification
- A formal grammar (using similar to EBNF)
- GLS - semantic rules expressed as a diff of the Java Language Specification
- Limited references to groovy.* interfaces
- Reference Implementation
- Test Compatiblity Kit
- Test cases following the GLS chapter by chapter
- A subset of the JCK:Java 'language' tests or similar (e.g. Jacks)
We have so much material from the two days (I recorded 15 hours of audio), it's going to take a while for all the details to surface.
|
|
|
|
|
|
|
October 2007 |
Sun | Mon | Tue | Wed | Thu | Fri | Sat |
|
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
Prev
| Today |
Next
|
rss:subscribe (Groovy)
What I'm reading
my feed aggregator ->box
My websites
London Java Meetups
Programming Projects
Elite in Java
megg
Blogmento
Jez's Photos
Fantasy Stock Market
Cool Saxophonist
Doctor Who Audios
Pisces Audios
Other Blogs
Mike Cannon-Brookes
James Strachan
Joe Walnes
Sam Dalton
Simon Brown
Cameron Purdy
Mike Roberts
Erik C. Thauvin
John Martin
Manfred Riem
B5 d++ t++ k s+ u- f
i+ o+ x-- e+ l- c--
|