Friday, September 4, 2009

Grapes of Wrath

Groovy Grape comes standard now with Groovy 1.6.x. I am not going to go in to what Grape is for in this article, but suffice to say think of a dynamic, runtime version of Maven.

I was trying to set up a Groovy run script that would download and run my application using Grapes, but hit on a problem that some of you might find useful to know about: When I tried to instantiate one of my classes from the run script, it could not find the class' dependencies.

This is a bit of a doozy. When I searched Jira about a bug, I came across this issue. In my own script it was a bit more complex than this, but suffice to say the issues were the same. I will use the example from Jira to explain what is happening. Consider this code:


import groovy.sql.Sql;
import groovy.grape.Grape;


Grape.grab(group:'mysql', module:'mysql-connector-java', version:'5.1.6' )

def sql=Sql.newInstance("jdbc:mysql://localhost/test","root","",
"com.mysql.jdbc.Driver");

println sql.firstRow("SELECT now( )");

This will fail with a ClassNotFoundException. But why?

Let me try to explain about what's going on here. Grape resolves and adds the dependencies to the current classes classloader, and classloaders work in tree formations. Classloaders further up the tree cannot see dependencies further down (or on different "branches").It turns out the SQL static newInstance method uses a different classloader higher up the tree from the run script.

You can check this by printing the dependencies on the current and system classloaders by passing them to the listDependencies method of Grape:


println Grape.listDependencies(ClassLoader.systemClassLoader)
println Grape.listDependencies(this.class.classLoader)


The first is empty, the second has all your dependencies.

So how do we work round this? The Grab method allows you to specify the classLoader to use for adding the dependencies on:


import groovy.sql.Sql;
import groovy.grape.Grape;


Grape.grab(group:'mysql', module:'mysql-connector-java', version:'5.1.6', classLoader:ClassLoader.systemClassLoader)


def sql=Sql.newInstance("jdbc:mysql://localhost/test","root","", "com.mysql.jdbc.Driver");

println sql.firstRow("SELECT now( )");


Thanks to Mr Haki (see the comments below) for the correct solution!

Wednesday, August 19, 2009

Building a VI clone with Groovy pt 2

Ok so, here's the beef. My main issue at the moment with my vi clone is that I think my assumptions about the way I was using a StringBuilder* were initially incorrect. I actually think I now need to store each line separately in a list. This way, I can keep track of the caret, and know exactly which line I am on as well:

def buffers = new File(argstr).getText().tokenize('\n').collect{ new StringBuilder(it) }

With that sorted, I find myself with a number of requirements:
  1. Moving the cursor should be done with the arrow keys.
  2. Deleting stuff (x) should remove the character at the right x, y position.
  3. Do not pass the screen boundary, scroll the file down.
  4. When at the end of the file, do not move the cursor further.
  5. When I am in append mode, text should be added to the end of the line no matter where in the line I am. The cursor should be moved as well.
  6. When I hit escape, a number of things can happen: If I am in edit mode, I drop back to movement mode; If I am in movement mode, I leave the editor (for now, saving the file will be automatic, rather than explicit for simplicity).
  7. If I am in Append Mode or in Edit Mode I should be able to type text in to the correct buffer, and have it appear on my screen. Also, pressing enter should move on to a new line inbetween the current line and the next.
  8. Do not wrap text on the screen for the time being.

Requirement eight I am a little reticent about. I am not sure if it would be harder to work out whether we have wrapped the text on a line (could be stored as a boolean on an object wrapping the StringBuilder) or whether it is better to scroll the whole file with the cursor at the screen boundary. I guess both are valid solutions, and in the future the user could be given an option to do either.

Encapsulating the StringBuilder in a decorator class of it's own does make sense though, because I might be able to add extra information to the line (like, last know caret position) as well as whether it has wrapped or not. I realise that the string length could be calculated every time to work this out, but encapsulating this functionality would be better I feel.


* I have switched to StringBuilder because I forgot I was using Java 5 :O



*

Sunday, August 16, 2009

Persisting class with metaclass

The metaclass object on a Groovy object is marked transient, and with good reasons: I don't event want to think about actually persisting the entire thing.

However, I'd like to be able to persist closures that belong to the class, since I spent the energy actually scripting the additional methods I would like them to be loaded when I need them?

Has anyone got any clues?

Thursday, August 13, 2009

GREclipse Plugin V2

Before I forget, I really aught to plug version 2 of the GREclipse plugin. It is far far superior to the old one, and I entirely recommend updating to it.

Gone are the silly builders and having to have the output on your classpath woes, V2 does some very good things to make up for all the awfulness of the old one. JUnit tests run like a breeze, and although buggy, code completion is there.

If you are using the old one, uninstall it first and get rid of any fluff on the classpath. Something else to watch out for is that you might need to uncheck the Groovy Libraries entry on the "order and export" tab on the project's preferences.

Check it out, I highly recommend it as a replacement
.

Monday, August 10, 2009

Building a VI clone with Groovy

The great thing about online spaces is they tend to be able to build themselves. Give enough decent tools for the users of a space, and they can make some kickass things. And bizarre things too. And very very garish things :(

Anyway, MUDS also allow this sort of thing, but in a more controlled fashion. MUDS generally have some sort of hierarchy to prevent the idiots from changing bits of the game that are really cool and ruining it for others. Called "creators", these hand picked super users can change parts of the game to make it more exciting, add depth and new content as often as required.

So I need some tools for the creators in my MUD to go about editing the groovy scripts and other files. Which brings me to the problem: there are no telnet based text editors written in either Java or Groovy that can do this. Guess I'll have to build my own? GroovyMud already has a command loop type shell implementation, but adding an entire shell for this sort of thing is a little overkill. With GroovyMud I am able to run scripts as commands (remember last time?) in the MUD by just typing the name, and the CommandInterpreter invokes the GroovyScriptEngine to run it. I can leverage this behaviour nicely :D

I will be logging my progress in creating this editor here when I can, so keep tuned to find out how I get on.

So to start, I struck on having a vi type editor for the interface. For those of you not familiar with vi, (get out now!! :D just kidding), it is a very simple *nix text editor with a lot of very cool functions. There are no menus, just a number of commands that can put you into different states in order to do stuff with the text.

For example, start up vi and push "i", and you enter "input" mode. Enter characters to add text to the file, and then push escape. You return back to movement mode, where you can move around the text file using the arrow keys. In movement mode, you can not only move the caret around, but delete characters with 'x' and lines by pressing 'd' and 'd' again. The default mode is movement, so you can move to where ever you need to add stuff in your file.

So an enum for these states would be useful, with our default:


enum Mode {
INSERT, APPEND, MOVE
}
Mode currentMode = Mode.MOVE


Obviously we would also need to store the position of our caret in the text file, so Groovy's StringBuffer and file manipulation api extensions should help me here:


int xPos = 0
int yPos = 0

StringBuffer fileContents = new StringBuffer(new File(argstr).getText())


In GroovyMud land, the player that is performing the edit is passed into the script as a paramter called "source". They have a very nice handy telnet ExtendedTerminalIO object to play with, which for these purposes acts just like any other kind of stream (except I can read lines with it with readln). So I can get a handle on this to manipulate their IOStream to their telnet prompt like this:


ExtendedTerminalIO stream = source.terminalOutput
stream.eraseToBeginOfScreen() // nifty function to clear the screen
stream.write(fileContents) // write out the file contents
stream.moveCursor(xPos, yPos) // move the cursor to the beginning of the file.


This is good, I now have a screen full of file with my cursor at the start. But how would I work within the framework of the script to provide the command interface? Then I hit on the idea of using a map to hold the actions for each key press:


def commandMap = ["i": {currentMode = INSERT},
"a" : {currentMode = APPEND},
"x" : { ... perform some delete function ...},

]


Ok so far so good. We also need some kind of input loop, to trap the users input until we exit. So setting up a while loop here would probably be a good thing:


boolean exit = false

while(!exit){
char ch = stream.read()
//perform the command in the map first
}


Ok this is as far as I have got. In theory I should be able to call the command in the map with the character that I read in. The closures there will handle the movement of the caret, the deletion of the chars in the string and any other functions, depending on the MODE I am in. I also want to add more funky stuff too, like code completion, colourization and other stuff like that.

More next time.

Wednesday, July 22, 2009

another bug bites the dust

Another beauty of a bug bites the dust in Groovy 1.7-beta-1: GroovyScriptEngine fails to load mutually dependant classes.

This had been a big pain for me in the past, because I would have to watch out how I wrote my code. In the beginning, I hadn't got rid of the habit of statically typing my data, so doing something like this:


IBar.groovy:

package test

import test.Foo

public interface IBar{
public void doStuff(Foo foo);
}

Foo.groovy:

package test

import test.IBar;

public class Foo{
public void doSomeFoo(IBar obj){
out.print("foo!");
}
}




... and use the GSE to load one of the objects, things would fail with an infinite lookup loop.

Now I hardly use interfaces its not such a problem, but it's still good to get it fixed. My thanks to Jochen (again ;))

Wednesday, July 8, 2009

Bottled it.. why?

Darn...

I had the perfect opportunity to use Groovy today on a work project. And I bottled it.

Why? I love Groovy. It's useful, concise and powerful. Yet here I am, slogging away at the solution in Java, and cursing every time I have to put a semicolon in.

I've been wanting to use Groovy for a long time now in my day job. I have had my reservations. These are mainly to do with:

1. No one else in my department understands Groovy
2. The architect has expressed reservations about it (well, not so much about Groovy as implementing new things without training)
3. Even though I was using the maven plugin to generate my project, I had reservations about how I would go about deploying it.
4. Mainly, I was confused about whether it really needed to be Groovy or not.

These things panicked me, and I lost my bottle. Maybe next time... :(