Showing posts with label groovy. Show all posts
Showing posts with label groovy. Show all posts

Wednesday, January 14, 2009

Cool Code Snippet Tool

Simple post for my own memory:

The best online code snippet posting tool that I've found is at http://pastebin.com/. It has great syntax highlighting for a variety of languages (including Groovy) and it is very easy to use.

Friday, January 18, 2008

DRY Groovy, How To Get Groovy To Import A Class Into a Script

UPDATE: Read to the bottom to see another way to tackle this problem

Each time you repeat yourself in code, you may as well leave a bear trap by your desk. In fact, the bear trap is probably safer for me. Whenever I see repeated code, I want to poke my eyes out. I do my best to keep my code dry whenever reasonable.

So, when I started writing Groovy scripts, it became obvious pretty quickly that I had some utility classes waiting to break out. The only problem was, I couldn't find the technique for importing a Groovy class from another file into the current script. Thanks go to Peter Niederwieser for the solution.

Here's the setup:

Two Groovy files:
c:\tools\groovy\myscript.groovy
c:\tools\groovy\MyClass.groovy

The content of MyClass.groovy:

class MyClass {
def howdy() {
println 'Howdy'
}
}

The content of myscript.groovy:
new MyClass().howdy()


Super simple. However, no matter how I tried to run myscript, I got this error message:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed,
c:\tools\groovy\myscript.groovy: 1: unable to resolve class MyClass

What gives? The files were right next to each other, but stupid Groovy couldn't find them. That's when Peter reminded me that groovy will look in the classpath to resolve classes.

There are two ways (that I know of) to tell Groovy what your classpath is. You can either indicate it on the command line as in:
groovy -cp c:\tools\groovy myscript.groovy

Or, you can set the CLASSPATH environment variable to include the path where the collaborating class (in this case, MyClass.groovy) lives.

Using the classpath, you don't even have to keep your script and its dependencies in the same directory. I simply set my CLASSPATH, and now I'm off to the races. Now, I keep all my scripts in c:\tools\groovy (which is on my PATH), and my classes in c:\tools\groovy\classes (which is on my CLASSPATH).

WARNING: For all of you Windows users out there, the name of the Groovy file IS CASE SENSITIVE! So, if you want Groovy to find class MyClass, it had better be in something like, %CLASSPATH%\MyClass.groovy. %CLASSPATH%\myclass.groovy did NOT work for me. This would make complete sense to me if I were in a Unix environment. However, I am used to my Windows machines being mostly case insensitive. This is a bit odd, but understandable I guess.

UPDATE: Jochen Theodorou has pointed me in the right direction for another solution that I like better. You don't have to modify the classpath to cause groovy to find the classes that you are importing. Instead, you can add load information to your %GROOVY_HOME%\conf\groovy-starter.conf file. Mine now has these extra lines:
# load classes for local scripts
load c:/tools/groovy/classes

Now, I don't have to keep the CLASSPATH environment variable set and worry about how that interacts with Java.

There you have it. Now, you can keep your scripts dry.

Monday, January 14, 2008

Mocking Groovy Objects with EasyMock in Java

I mentioned before that I needed to do some unit testing of a class that I was targeting in Groovy with come unit tests in Java. In Java, I am using EasyMock to mock out the collaborators. I am dealing with one collaborator, an interface, that looks like this (Groovy):


interface FileSystem {
...
def uploadFile(inputStream, destinationPath)
...
}

For the purposes of this unit test, I didn't care what got returned, so I setup the expectation like this (Java):

desintationFileSystem.uploadFile(streamForFile1, "someDir\\someOtherDir\\file1.jpg");

Running the test, I was greeted with this message:

java.lang.IllegalStateException: missing behavior definition
for the preceeding method call
uploadFile(EasyMock for class java.io.FileInputStream,
"someDir\someOtherDir\file1.jpg")
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:27)
...

That's when I remembered something fundamental to groovy... the 'def' type means variable return type. For Java, that translates into Object. To make the test run, I either needed to explicitly change the return type on the interface to be void, or simply setup the EasyMock expectation to return a value. Since I didn't want to change the interface, I chose to specify the return value in the expectation.

Sunday, January 13, 2008

How to Cure a Groovy Headache with Java

There was a time during my college years when I was a full-on caffeine addict. I remember once during finals consuming around 10 cans of Dr. Pepper per day. When I decided that I needed to come off the caffeine, I had to use some java (coffee) along the way to avoid the nasty headaches.

Fast forward a few years, and I've once again use some Java to cure a headache. However, today's headache was caused by a mixture of concrete classes and Groovy's seeming inability to mock concrete classes. I wish I knew the Groovy life cycle a bit better to explain exactly why it is that I couldn't mock out java.io.FileInputStream. Suffice to say, Groovy didn't let me substitute in a closure, I didn't want to use mockFor because there was enough else going on. Additionally, Groovy didn't want to cooperate with the EasyMock classextension for reasons I never could quite figure out.

In comes the Java. Since Java and Groovy compile down to the same byte code, testing Groovy with Java is pretty easy. The final solution that I came up with was writing the implementation in Groovy like I wanted to, and writing the test in Java. I simply used org.easymock.classextension.EasyMock to do the mocking, and away we went. This was a nice proof of Java and Groovy living right next to each other and working together. One of the nice things about having the ability to do the test in Java was proving that, indeed, I had all of the project dependencies that I needed and Groovy just did not like mocking out the class.

Watch here soon, and I am going to post a cool little tool that I am working on for spiking the project structure for a setup like this. It's much more stripped down from what Grails will give you. But, if your looking for directory structure and a simple build.gant, then this may be something to look at.

Now, where's my decaf coffee?

Friday, October 26, 2007

How To Pass Command Arguments With a File Type

UPDATE: This issue appears to be fixed with the Groovy 1.5 Windows install package. However, this is still good general information to know about passing command arguments with file associations in Windows.

I just upgraded my groovy install to the latest RC for 1.1, and it quit recognizing command arguments. I tried debugging all kinds of older scripts that I knew worked, and none of them were working anymore. That's when Steve reminded me that the Groovy install messes up the Windows file extension association. So, it installed the .groovy file association like this:

"C:\groovy\bin\groovy.exe" "%1"

And it needed to be changed to this:

"C:\groovy\bin\groovy.exe" "%1" %*

This will allow the other command arguments to be passed when the groovy script is kicked off.

To change the file association (in XP),

* Open My Computer
* Tools -> Folder Options...
* Click the "File Types" tab
* Find the file type you want to change, ".groovy" in this case, and click it
* Click the "Advanced" button
* Click the "open" action
* Click the "Edit..." button
* Edit the content of the text box under, "Application used to perform action:"
* OK / Close your way out of the dialogs.


Obviously, this will work for other file associations. This method, while it forces you through a few windows, allows you to avoid mucking with the registry directly.

Monday, August 13, 2007

Using Groovy to grep XML

After attending some compelling presentations by Scott Davis at No Fluff Just Stuff, I have been playing with Groovy here and there when I've gotten the chance. At work, we've been working with a some software that's currently producing a pretty massive log file. We tried using Chainsaw to slice and dice it, but it wasn't giving us the functionality that we wanted. So, this was a perfect time to play with some Groovy.

Our input looks something like this:

<root>
<entry level="ERROR">
<message>
An error has occurred while parsing column FOO with value of BAR 23 in row 234
</message>
</entry>
<entry level="ERROR">
<message>
An error has occurred while parsing column FOO with value of BAR 52 in row 234
</message>
</entry>
<entry level="ERROR">
<message>
An error has occurred while parsing column FOO with value of FOOBAR 34 in row 234
</message>
</entry>
<entry level="ERROR">
<message>
An error has occurred while parsing column FOO with value of FOO52 in row 234
</message>
</entry>
</root>


Of course, the file is too massive to read through. For this particular error, we were interested in the unique values of FOO that we weren't handling. Here is the groovy to pop open the XML file and find the unique values


def findUniqueEntries(String inputPath, String search, String extract) {
def uniqueMatches = new HashMap()

//Input all of the XML
def root = new XmlParser().parse(new File(inputPath))

//All the child nodes of the root node will be elements
for (entry in root.children()) {

//Assumes each has exactly one child
text = entry.message[0].text()

//Do a substring search first
if (text.contains(search)) {

//Strip out the failing value with a Regular Expression
def matcher = text =~ extract
uniqueValue = matcher[0][1]

//For values we've seen before, increment the count
if (uniqueMatches[uniqueValue] != null) {
uniqueMatches[uniqueValue] += 1
}

//For a new value, initialize the count
else {
uniqueMatches[uniqueValue] = 1
}
}
}

//Print the values along with their occurance count
for (match in uniqueMatches) {
println match
}

//Print the number of unique matches, and the number of total matches.
def uniqueMatchCount = uniqueMatches.size()
def totalMatchCount = uniqueMatches.values().sum()
println ('\nFound ' + uniqueMatchCount + ' unique matches in '
+ totalMatchCount + ' total matches.\n')
}


There are a couple of interesting things that made this really fun code to write:

1 - Navigating XML with Groovy is easy, and the syntax reads quite well. The code communicates the structure of the XML document as well as could be expected, I think.

2 - Groovy makes it really easy to work with Regular Expressions. No more pattern compiling.

3. The Groovy sum() extension means that we don't need to track the total number of matches, nor do we need to iterate through the HashMap at the end.

All in all, I'm enjoying playing with Groovy at the moment. I've found the barrier to entry to be pretty low. It will be interesting to see how we continue to use Groovy in the future.