Pages

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

Wednesday, July 15, 2015

Custom configuration script ASTs

Nikolay Totomanov asked on the Groovy mailing list how one could add a default constructor (if it doesn't already exist) to all classes. I realized there were no examples on the internet (that I could find anyway) of
  1. How to pass parameters into an AST in a configuration script
  2. How to use a custom AST in a configuration script
So I decided to try to remedy that with this post.

1. AST parameters in a configuration script
Let's say you wanted to do
@groovy.transform.TupleConstructor(includes=['foo'])
in a configuration script. How do you pass the includes? Use a map. The equivalent configuration script would be
withConfig(configuration) {
    ast(groovy.transform.TupleConstructor, includes:['foo'])
}

2. Custom AST in a configuration script
If you wanted to create your own AST and use it in a configuration script, I suggest looking at Groovy as a starting point. Here, I'll use groovy.transform.TupleConstructor and org.codehaus.groovy.transform.TupleConstructorASTTransformation as an example to solve Nikolay's problem. Here is the result
import java.lang.annotation.ElementType
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
import java.lang.annotation.Target
import org.codehaus.groovy.ast.ASTNode
import org.codehaus.groovy.ast.AnnotatedNode
import org.codehaus.groovy.ast.ClassNode
import org.codehaus.groovy.ast.ConstructorNode
import org.codehaus.groovy.ast.Parameter
import org.codehaus.groovy.ast.stmt.BlockStatement
import org.codehaus.groovy.control.CompilePhase
import org.codehaus.groovy.control.SourceUnit
import org.codehaus.groovy.transform.AbstractASTTransformation
import org.codehaus.groovy.transform.GroovyASTTransformation
import org.codehaus.groovy.transform.GroovyASTTransformationClass

@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
public class DefaultConstructorASTTransformation extends AbstractASTTransformation {
    public void visit(ASTNode[] nodes, SourceUnit source) {
        init(nodes, source)
        AnnotatedNode parent = (AnnotatedNode) nodes[1]
        if (parent instanceof ClassNode) {
            ClassNode cNode = (ClassNode) parent
            // doesn't already have a default constructor
            if (!cNode.getDeclaredConstructor(new Parameter[0])) {
                cNode.addConstructor(new ConstructorNode(
                    ACC_PUBLIC, new Parameter[0], cNode.EMPTY_ARRAY, new BlockStatement()))
            }
        }
    }
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@GroovyASTTransformationClass("DefaultConstructorASTTransformation")
public @interface DefaultConstructor {}

withConfig(configuration) {
    ast(DefaultConstructor)
}

Wednesday, June 2, 2010

GMaven & source encodings

I'm re-posting this because I made some more discoveries after I had initially posted it.

I discovered apparently SourceEncoding is completely broken in GMaven. I tried on Linux where the platform default encoding is UTF-8 and on Windows XP where the platform default encoding is Windows-1252. In both cases, it used ISO-8859-1 as the encoding of the class file it generated, despite the fact the source was encoded in the platform default encoding. I tested this with version 1.2 of the plugin and Groovy 1.7.0. Why this is happening makes no sense to me; I could understand if it used the platform default...but why always ISO-8859-1? I think this is the Jira for this: http://jira.codehaus.org/browse/GMAVEN-13.
I find it shockingly disappointing that a 'critical' issue can go unassigned for almost an entire year. I wonder if it is working in Ant. Their documentation seems to suggest that it does. If that's true, it might tell us something about where the Groovy team's priorities are.

In practice, this often is not problem, since if you're only using ASCII characters in your source code, the first 128 bytes have identical mappings in UTF-8, ISO-8859-1, and Windows-1252, so it won't matter which of those the plugin tries to use. However, I view this as a major obstacle to Groovy's gaining dominance, as it should support Maven (since for better or worst it's become the leading standard) and it should support encodings to support global growth.

Am I missing something? Any good workarounds? I'm also happy to share my experiment project with anyone who wants to play with it.

I've also discovered yet another way in which GMaven's documentation is fail. I was trying to get my project to work with the latest version of Groovy, when I came across this unrelated StackOverflow discussion which use the new 1.2 version of the plugin (which isn't in the archetype or anywhere documented as released -- I thought the artifacts were released by mistake since nothing has even been tagged in their repository for 1.1 or 1.2, although IntelliJ already supports it, plus nabble and some blogs talk about it so I guess it is released). Here are the needed bits from the pom:
<dependencies>
    <dependency>
        <groupId>org.codehaus.gmaven.runtime</groupId>
        <artifactId>gmaven-runtime-1.7</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.groovy</groupId>
        <artifactId>groovy-all</artifactId>
        <version>1.7.0</version>
    </dependency>
<dependencies>
<plugins>
    <plugin>
        <groupId>org.codehaus.gmaven</groupId>
        <artifactId>gmaven-plugin</artifactId>
        <version>1.2</version>        
        <configuration> 
            <providerSelection>1.7</providerSelection>         
        </configuration>
        <executions>
            <execution>
                <goals>
                    <goal>generateStubs</goal>
                    <goal>compile</goal>
                    <goal>generateTestStubs</goal>
                    <goal>testCompile</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.3</version>
        <configuration>
            <source>1.6</source>
            <target>1.6</target>
        </configuration>
    </plugin>
</plugins>

Update: According to this Jira, this is fixed in the 1.3 release. And it appears from my tests that this is the case.

Monday, January 11, 2010

More Groovy Bugs

While trying to add some sorting to my ValidateMe script, I discovered a Groovy bug that someone else reported on Thursday. It appears that although inner classes are supposed to be supported in the new Groovy 1.7, calling methods on enums inside a class do not. I've also created another suggestion for a reverse() method on Maps. I did add the changes I wanted to ValidateMe without these Jiras being addressed. What I did for the reverse was do something like
theMap.reverse{it.value}

Wednesday, December 30, 2009

A Couple Of GroovyConsole Jiras

I find myself relying more and more on the GroovyConsole for testing out Java and Groovy stuff (especially regular expressions and xml processing), for writing scripts it basically is my IDE. There's a few irritations for which I opened a couple of Jiras for today, as I didn't see comments on them. All pretty minor, the first two deal with the open/save dialogs, the third deals with process management and output. We'll see what happens. If they're open to the changes, but don't have the time, a couple might be something even I could do. Anyway, here they are:

http://jira.codehaus.org/browse/GROOVY-3961
http://jira.codehaus.org/browse/GROOVY-3962
http://jira.codehaus.org/browse/GROOVY-3963

Monday, December 21, 2009

Gettin' Groovy with xml validation

So, I wanted to be able to tell learn some things about the validity of a particular xml document I was working with a few days ago. If you use something like XMLSpy or the xml plugin for Notepad++, they will display only the first validation error. So, I wrote a Groovy script to let me control the amount of errors reported, and collect some statistics about the document. I call it ValidateMe. And now, I'm sharing it with you. You can get the script off its Google Code page. As usual, it's MIT licensed, so you can do pretty much whatever you want with it. It's usage is described by running 'groovy validateMe.groovy help'. It's pretty straightforward, about 130 lines or so, but I think it's pretty slick.

As a result of doing this, I also learned that you can have multiple classes in the same .groovy script file, as long as the class with the main method is first.

Wednesday, December 16, 2009

Launching a GroovyConsole Without a cmd window

I run Groovy 1.7 from the .zip files (which doesn't yet have the native launchers built for it), and I love the line numbering, and many other things about it. The one thing that was irritating is that a new cmd window would have to be opened every time I launched the groovyConsole.bat. I now have a workaround. Create a new .vbs file in the bin folder of your groovy with the following contents:
Set WshShell = WScript.CreateObject("WScript.Shell")
obj = WshShell.Run("groovyconsole.bat", 0)
set WshShell = Nothing
You can then put a shortcut to this wherever, and even make it pretty by setting the icon to this. Oh, and make sure you have your GROOVY_HOME set up.

Actually, this can be used to run any batch script in the background, as long as you don't need to be able to let the user pass in arguments. My thanks to Koushik Biswas from Yahoo Answers for the tip.

Friday, December 11, 2009

Which Child Am I?

I don't know if this is worth blogging home about, but I've needed this solution a couple times, and I found myself referencing this blog entry draft, so I'll put it out there and maybe someone else will find it useful. The problem is I have an xml node, and I want to know the order it is (as an index integer) in relation to its siblings. You may have to modify this of course, if the children you are comparing are deeper down than 1.

def CAR_RECORDS = '''
<records>
  <car name='HSV Maloo' make='Holden' year='2006'>
    <country>Australia</country>
    <record type='speed'>Production Pickup Truck with speed of 271kph</record>
  </car>
  <car name='P50' make='Peel' year='1962'>
    <country>Isle of Man</country>
    <record type='size'>Smallest Street-Legal Car at 99cm wide and 59 kg in weight</record>
  </car>
  <car name='Royale' make='Bugatti' year='1931'>
    <country>France</country>
    <record type='price'>Most Valuable Car at $15 million</record>
  </car>
</records>'''

def records = new XmlSlurper().parseText(CAR_RECORDS)
def record = records.car[2].country

int index = 0
Boolean found = false
record.parent().parent().children().each {
  if (it == record.parent()) {
    found = true
  } else if (!found) {
    index++
  }
}
assert index == 3
return index

Monday, December 7, 2009

Using Groovy from the .zip file

I had always had trouble launching groovysh or groovyConsole from the .zip releases of groovy, and always waited until they released the installer for Windows, never knowing why. There is a simple fix, but one that didn't occur to me right away. The cause is that the GROOVY_HOME variable needs set before startGroovy.bat tries to add it to the classpath, so just add

set GROOVY_HOME=..\
to startGroovy.bat (anywhere before the classpath gets set), and let the good times roll...
This also, of course, overrides whatever you have set as system or user variables, so you can safely play with other versions from the .zips without needing to change anything (or needing admin rights).

Monday, November 23, 2009

My First Wave Bot

I finally got my Wave invite, and I immediately got interested in coding with it. I recently finished creating a bot for it that allows you to search WorldCat from inside Wave. The main servlet is in Groovy, the profile is in Java. Their tutorial pretty much works, though one of the methods was renamed:
getRobotProfileUrl() should be called getRobotProfilePageUrl() (there's a request filed to fix this). Google's plugin for Eclipse also works very well. JetBrains also has a plugin for IDEA, though I didn't test this. In their sample project SpringSource has a build script that uses AntBuilder, which I modified to use the folder structure that was already created by the Eclipse plugin. I successfully built with this and deployed the app using appcfg.cmd from the SDK. I used straight html for the bot's profile page, but in their sample SpringSource shows how you could use the MarkupBuilder in groovlets.

Anyway, the app is deployed on the Google App Engine here, it's homepage (where the sourcecode is also available) is here. You can add it to your waves by adding worldcat-bot@appspot.com. For even more bots, check out the list. Mine's listed too. There is another list out there, but it doesn't seem used as much.

Some gotchas:
  1. You cannot test robots without deploying them to the Google App Engine, this makes you waste some of the number of deployments you have on the free account (currently you get 1000).
  2. Wave caches its bots, so you have to change the version in appengine-web.xml (I don't think you have to change the version in capabilities.xml too unless the capabilities have also changed, but I've been changing both to match). They tell you this, but you have to be careful because even though you may have deleted the old version if you reuse a version descriptor text Wave may still try to call the old version and you will get a ServletUnavailable exception and waste another deployment. You have to wait for the re-caching to occur.
  3. If you are using Groovy, you have to upload the groovy-all jar in the war/WEB-INF/lib directory (the war folder can be a different name, but that is the convention used by the Eclipse plugin).
For those who haven't heard about Wave, it's basically a kind of collaborative IM (I once jokingly described it as an MMIM - Massively Multiperson Instant Messaging). But it isn't quite accurate to describe it as a kind of IM. The text is live, you can see it as the person is typing it, but whether its treated as an IM or more like an email is fluid. It depends only on if other people are there at the same time. So, it can be viewed as a kind of mashup between email, IM, and collaborative documents and is more concurrent than traditional email. LifeHacker has some use cases, which make for good propaganda.
Anyone in the conversation (called a Wave) can edit any of the messages (blips). Side conversations can occur in the same stream, these side conversations are called wavelets. APIs exist to have bots in a conversation that automate tasks (such as links for searches, posting the conversation to a blog, bringing in text from a feed, or converting everyone's text to pirate talk) and for gadgets that let you put different kinds content inside the conversation, such as documents, polls, etc. Google plans to open source most of Wave once it's finished, allowing other 'federated' servers to become Wave providers, and they plan to make the protocol they use the predominant protocol on the internet. The Google Wave Federation Protocol is itself built off XMPP (the same protocol Jabber and GoogleTalk use). They have bindings for Python and Java currently (I've heard the Python API is not as polished as the Java one, but I don't know that for sure and I'm sure it will improve), and will probably be adding more languages in the future to support their goal of making their protocol #1. Wikipedia has a pretty good article on Wave as well.

I still have Wave invites left for my friends, if you're interested.

Wednesday, November 11, 2009

Groovy - Sometimes you still need a semicolon

I Was ploughing through my overly-large blogroll the other night when this article caught my eye.
http://groovy.dzone.com/articles/groovy-sometimes-you-still
I gave it a read, because I wanted to know all the cases where you had to have a semicolon.

He gives two examples, the first of which he’s wrong about, it works fine in 1.6.5 and I believe it works for anything >= 1.6.
def list = [1,2,3] as List<Integer>
println list

This second one (not the exact same example he used) does need a semicolon
{-> assert true == true }()
{-> assert false == false }()

Should be
{-> assert true == true }();
{-> assert false == false }()

This is only the case if you have two closure calls next to each other with nothing in between.
{-> assert true == true }()
println ""
{-> assert false == false }()
works fine.

Are there other times when you need a semicolon at the end of the line (assuming only one statement per line)?

Friday, November 6, 2009

Groovy 1.7 Beta 2 Available

It’s a bit of old news, but I don’t remember seeing anything about it until today.
It was available 12 Oct, and Windows installer binaries were available 18 Oct. Get yourshere.

A draft of the current features is available at http://docs.codehaus.org/display/GROOVY/(draft)+Groovy+1.7+release.  This release is mostly bug fixes, with two notable improvements.  They have added the ability to alter the meaning of Groovy Truth.  This lets you add some truth to your own class by adding the asBoolean method:

class Foo {
  String value
  boolean asBoolean() { value == "something true" }
}
assert new Foo(value: "something true")
assert !new Foo(value: "teh cake is a lie")

And of course, using ExpandoMetaClass, you can alter the behavior for Groovy classes that already have a Groovy Truth defined:
Integer.metaClass.asBoolean { int value ->
  return value > 0
}
Integer foo = 7
assert foo.asBoolean()

They’ve also added stylish outputs for assertion failures (I guess taken from the Spock testing framework):
int foo = 0
int bar = 1
assert foo == bar
will display:
Assertion failed:
assert foo == bar
       |   |  |
       0   |  1
         false

Friday, October 16, 2009

Java vs Groovy: Polymorphism

While doing some studying for SCJP, I was tinkering with some stuff in the Groovy console as a way of testing some stuff in Java and I found they actually behave differently.

class Person {
  protected String name
  protected int age
  
  public Person() {
    name = "secret"
    age = -1
  }
}

class John extends Person {
  int favoriteNumber
  
  public John() {
    name = "nobody special"
    age = 0
    favoriteNumber = 7
  }
  
  public String doNothing() {
    return "junk"
  }
}

Person p = new John()
println p.doNothing()

If you do this in Java (splitting the classes out to their own files of course), it won't compile. Java looks at the reference type for available methods, so you will get a NoSuchMethodException. In Groovy, however, it looks at the type of the object, not the type of the reference so the method is found at runtime. And this is probably what you would want, so I can refer to John or Mary as a generic Person, but they still do the things they do in a John or Mary way.

Java vs Groovy: Overriding static methods

The Java equivalent of below will not compile, but in Groovy it works fine. Groovy supports overriding static methods, whereas Java does not.

class Person {
  protected String name
  protected int age
  
  public Person() {
    name = "secret"
    age = -1
  }
  
  public static String doNothing() {
    return "junk"
  }
}

class John extends Person {
  int favoriteNumber
  
  public John() {
    name = "nobody special"
    age = 0
    favoriteNumber = 7
  }
  
  public String doNothing() {
    return "more junk"
  }
}

Person p = new John()
println p.doNothing()

I don't think this would be a problem. You might want each inherited class to have its own (maybe static) version of a method, but for every instance of the class to only have one in memory. If you don't want the children overriding the method, you should just make them final.

Thursday, October 15, 2009

Boolean.flip()

Recently I needed a Boolean in a groovy project I was working on to alternate back and forth (for row highlighting with Apache POI). I thought it would be slick to metaclass a flip() method (something I've always thought should be there) into Boolean. It turns out, this is not possible. I browsed the Java source and learned that all primitive wrapper classes are immutable. I'm not completely sure why they did this. My guess is to protect programmers from hurting themselves by mutating objects in a collection and possibly creating unexpected behavior or a race condition.  I could have created my own boolean wrapper class, of course, or use Apache Commons MutabeBoolean. In the end, I decided not to be fancy and just reference a new object like

Boolean foo = false
foo = !foo
But boy, it would have been pretty & nice to have
Boolean foo = true
foo.flip()

Monday, September 14, 2009

The Not So Answered Variables in GPathResult

A while ago, I posted that I had gotten the answer on how to get the number of records in an xml file using XMLSlurper (or XMLParser) by passing a variable. It turns out, it was not so answered. This only worked for elements that are immediate children of the root. It seems XMLSlurper and XMLParser can't get longer paths from a single String, it needs to be broken up. (Not sure why it was implemented this way). Fortunately, our own brilliant, Jonathan Baker noticed this and suggested the solution below. It's not complicated once you figure out that the String has to be broken up:

def xmltxt = """
<file>
  <something>
    <record>
      <name>nakina</name>
    </record>
    <record>
      <name>buaboe</name>
    </record>
  </something>
</file>"""
 
def xml = new XmlSlurper().parseText(xmltxt)
def fullPath = 'file.something.record'

def pathElements = fullPath.tokenize('.')
pathElements -= xml.name()
def root = xml
pathElements.each {node ->
    root = root."$node"
}
return root.size()

You could also use split, as John Wagenleitner suggested in response to my comment on his answer on StackOverflow:
def xmltxt = """
<file>
  <something>
    <record name="some record" />
    <record name="some other record" />
  </something>
</file>"""
def xml = new XmlSlurper().parseText(xmltxt)
String foo = "something.record"

def aNode = xml
foo.split("\\.").each {
  aNode = aNode."${it}"
}
return aNode.size()

My thanks to you both.

After talking with Josh, I understand why the Groovy people had to do what they did. Dots (.) are still legal in XML element names, as long as the name doesn't start with a dot. (Actually, other punctuation is allowed as well, though it is not recommended). I don't think they could use forward slashes as XPath does because of how Groovy has overloaded the operators and dots had to be allowable, so this is what we're stuck with. Maybe they should have used spaces instead, since those aren't legal in element names. I don't know the impact this would have on other classes.

Friday, September 11, 2009

Bad GString! Bad! --- Wait, My Bad

I was trying to write a test for a method that inserted some stuff into a StringBuilder that was modified as a GString and was frustrated to find that my stubbed method was never called!

Initially I got mad, blamed Groovy for making my life more difficult with its ridiculous automagical boxing. Then Josh pointed out that StringBuilder is actually a CharSequence. It's not a Groovy thing, I'm just dumb. Fire up your GroovyConsole and observe:

StringBuilder.metaClass.insert = {int arg0, Object arg1 ->
  println "FOOO"
}
StringBuilder.metaClass.insert = {int arg0, String arg1 ->
  println "BARR"
}
StringBuilder.metaClass.insert = {int arg0, CharSequence arg1 ->
  println "I'M HERE!!!"
}

StringBuilder sb = new StringBuilder()
def foo = "ROGER"
def bar = "$foo"
sb.insert 0, bar
The result is "I'M HERE!!!". All I had to do was stub the right method.

If you're experiencing String vs GString issues, like I thought I was, you may find this helpful.

Friday, September 4, 2009

Unit Testing Struggles

So, over the last 1.5 weeks or so I've been having a bit of an identity crisis with unit tests. Sure, I got the basic idea of writing tests for each method in college but like most never used it much while in school. Now that I'm at OCLC and unit testing is expected, I'm trying to develop my own philosophy on the matter and get a feel for it.

I felt like I should bring code coverage up on the project I was working on, but for purely religious reasons. Now, granted, this project is heavy in IO (it's the same project I mentioned previously). So perhaps I'd see less benefit from unit tests on this project than others, but despite the fact I now have >70% coverage (up from 0%), I haven't found a single bug by using unit tests, only with integration tests. The results might also have been different had I used TDD or my home-brewed syncretic TOD approach.

Despite these facts, I don't argue that Unit Testing used with CI can help as a tool for preventing software regressions and as up-to-date documentation for the code (though I still don't find it a very natural read except for BDD approaches like EasyB). It's also useful for finding the root cause of a problem. Whereas an integration test might only be able to say "something blew up" a unit test might be able to tell "here is what blew up". However, the value of the unit tests I've created I think remains to be seen. Meanwhile, it did deliver value as a learning platform.

Groovy has served as an excellent testing platform for me. This particular project was written in Groovy, but I think this would work well with Java projects as well (there is, however, the slight overhead of the additional dependency). I was able to do everything I wanted (still a few kinks to work out) with stubbing using the wonderful, magical, ExpandoMetaClass. There are a few tests I have yet to do where I may have to use their mocking framework.

A couple gotchas:
// getters cannot be overridden using just the property name, even though they can be called that way
class Foo {
  int bar
}

Foo.metaClass.getBar {->
  return 44
}
foo1 = new Foo()
assert foo1.bar == 44  // this passes

GroovySystem.metaClassRegistry.removeMetaClass Foo
Foo.metaClass.bar {->
  return 42
}
Foo foo1 = new Foo()
assert foo1.bar == 42  // this does not

I wanted to send some precanned input to a method that uses BufferedReader to get its input. The constructor from it eventually constructs a File to get the data. I can't extend File or create a new interface with all the File stuff for a test, because that would require modifying BufferedReader and Reader classes to match these changes. I've not found a way around this.

Another problem was a method that takes a String path of a file that contains filepaths of input files to process and adds the string and a BufferedReader to that file to a collection (not sure why that decision was made). So, I tried to mock out eachline(). But there is a problem...
// you cannot metaclass constructors, therefore, this code doesn't work. I've still got to figure out a way of faking a file, since File cannot use map coercion because it has no default constructor
String aPath = "a/path/to/file"
String fakeData = "some\nfake\nstuff\n"

File.metaClass.init {String filePath ->
  def mock = [eachLine: {return "${fakeData}"}, exists: {return true}] as File
  return mock
}

File f = new File(aPath)  // doesn't work

There are still some larger questions I have that maybe I'll never get THE ANSWER to. One question in particular I've been struggling with is "How simple is too simple to break?" The JUnit authors suggest this is a never-ending source of pain:
becomeTimidAndTestEverything
while writingTheSameThingOverAndOverAgain
    becomeMoreAggressive
    writeFewerTests
    writeTestsForMoreInterestingCases
    if getBurnedByStupidDefect
        feelStupid
        becomeTimidAndTestEverything
    end
end
And it's still very easy for me to lose sight of what I'm actually testing in the midst of all the mocking, stubbing, and so forth. More than a few times this last week I've looked down and realized that what I've written is so paranoid that it is really testing stuff that can only fail if the compiler or JVM fails or cosmic rays come down and change my data.

Just as important as making sure your tests pass is making sure they fail. I struggled with this the most when I started this process. I thought "wonderful, everything works." When it turns out that the code didn't work quite the way I thought it did and my tests were actually written in such a way that they would NEVER fail. All those green bars might not actually mean much. That't not to say they're worthless, just maybe not as valuable as you might initially think.

And this leads to my greatest fear: How do you know when something is thoroughly tested? And can some sort of confidence be associated with your tests? Clearly, code coverage doesn't cut it. I'm still new to all this, but I'm not taking much comfort from unit tests. I feel a bit better when integration tests return exactly the result I'm expecting and I test several possible scenarios. Still, even with this, you cannot test all possible scenarios and when do you know you've got enough? I guess when something blows up and you didn't find it. (>_<)

P.S. by 'Mein Kampf' I just meant the literal 'my struggle' it has nothing to do with Hitler or his work.

Friday, August 28, 2009

Why My GroovyConsole Wouldn't Open

For a few weeks now, I've been wondering why I couldn't launch the pretty version of GroovyConsole on my home computer, but could on my work computer. It turns out this is a bug: http://jira.codehaus.org/browse/GROOVY-3655. Groovy needs the 32 bit JDK to launch. Nore more batch hack, I can now launch the GroovyConsole.exe directly. (Though they still haven't built this for the updated versions -- I assume they're holding off for the 1.7 release).

Problem was, at work I need to use HermesJMS which needs JAVA_HOME to be the 64 bit version (doesn't make sense, but it works). What to do? Fortunately, HermesJMS uses a batch file for its invocation, so just add
JAVA_HOME=C:\Progra~2\Java\jdk1.6.0_16
to line 23 (or anywhere in the beginning, really). Done.

Thursday, August 27, 2009

Answered: Using variables in XmlSlurper’s GPath

Yesterday I asked this question about using variables with XmlSlurper. I got an answer that works (although I don't see it anywhere in the documentation or the book Groovy in Action. Below is the example the answerer gave
def xmltxt = """
<file>
<record name="some record" />
<record name="some other record" />
</file>
"""

def xml = new XmlSlurper().parseText(xmltxt)
String foo = "record"
return xml."${foo}".size()

Friday, August 7, 2009

Groovy & CXF JAXB

I was working on making an existing application a mule service, when I ran into the snag that Groovy classes, when exposed as an parameter to the service method, which throws an error when JAXB attempts to deserialize the object to xml (for creating the wsdl). Every Groovy object possesses a property called metaclass that cannot be serialized because it is an interface. At the time, I solved this problem by wrapping the Groovy stuff with Java, to expose only what I wanted. Another way I could have done it would have been to have the Groovy class implement a Java class.

I later found out a third method, when I attended a brown bag session where a colleague gave a talk about using JAXB. Today, I found this link, which describes exactly that. Annotations can be used to override the default JAXB behavior to exclude that messy Groovy stuff. I haven't experimented with this yet (since I've already got my service working and there was no compelling reason to do it in Groovy instead of Java), but I wonder which of these three solutions would be the cleaner solution. I don't have a really strong opinion on this, but its probably preferable to have extra annotations than to have extra classes. Extra wrapping classes just result in more boilerplate code for the next guy down the road to wade through, at least annotations would only add a few lines (one line I believe in the case of CXF). Allegedly, just adding the annotation
   
@XmlAccessorType(XmlAccessType.FIELD)
to your class will resolve the issue. Has anyone else done this? How did you resolve the issue?