Hi all,
I'm trying to use a Groovy class marked with @Immutable, from a Java class.
As you might imagine, this is leading to some strange behavior, especially
when using Eclipse and Gradle.
First, here's build.gradle:
apply plugin:'groovy'
repositories {
mavenCentral()
}
sourceSets {
main {
java { srcDirs = [] }
groovy { srcDir 'src' }
}
test {
java { srcDirs = [] }
groovy { srcDir 'tests' }
}
}
dependencies {
groovy group:'org.codehaus.groovy', name:'groovy-all', version:'1.7.2'
testCompile group:'org.spockframework', name:'spock-core',
version:'0.4-groovy-1.7'
testCompile group:'junit', name:'junit', version:'4.8.1'
}
I find this custom mapping of the source sets to be very helpful when mixing
Java and Groovy code. As you can see, I'm basically just using the Groovy
compiler for both Groovy and Java files.
Here's my immutable class:
@Immutable
class ImmutablePoint {
double x
double y
}
>From Groovy, I have the following Spock test, stored in the 'tests' tree:
import groovy.lang.ReadOnlyPropertyException;
import spock.lang.Specification;
class ImmutablePointSpockTest extends Specification {
def "map-based constructor"() {
when:
def p = new ImmutablePoint(x:3,y:4)
then:
p.x == 3
p.y == 4
}
def "regular constructor"() {
when:
def p = new ImmutablePoint(3,4)
then:
p.x == 3
p.y == 4
}
def "can not change x"() {
when:
def p = new ImmutablePoint(x:3,y:4)
p.x = 5
then:
thrown(ReadOnlyPropertyException)
}
def "can not change y"() {
when:
def p = new ImmutablePoint(x:3,y:4)
p.y = 5
then:
thrown(ReadOnlyPropertyException)
}
}
That's all good and expected, and works when using Gradle 0.9-rc1. Here's a
similar test, this time in Java using JUnit 4, also in the test tree:
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class ImmutablePointJUnitTests {
private ImmutablePoint p;
@Test
public void testConstructor() {
p = new ImmutablePoint(3,4);
assertEquals(3.0, p.getX(), 0.0001);
assertEquals(4.0, p.getY(), 0.0001);
}
}
Believe it or not, that too works just fine. It confuses the heck out of
the Groovy Eclipse plugin, which underlines the ImmutablePoint constructor
as an error but doesn't flag the class as having an error in the Package
Explorer, but I can live with that.
Everything is fine until I use the same constructor in actual Java code in
the 'src' tree:
public class UsePoint {
public static void main(String[] args) {
// ImmutablePoint p = new ImmutablePoint(3,4);
// System.out.println(p);
}
}
If I remove the comments and run this as a regular Java application in
Eclipse, I get:
ast.ImmutablePoint(3.0, 4.0)
which is fine. If I do the "gradle build", however, I get:
:compileJava UP-TO-DATE
:compileGroovy
org.codehaus.groovy.control.MultipleErrorsException: startup failed:
Compile error during compilation with javac.
c:\...\UsePoint.java:5: cannot find symbol
symbol : constructor ImmutablePoint(int,int)
location: class ast.ImmutablePoint
etc. In other words, I can use that constructor in a JUnit test in the
tests tree, but as soon as I use it in the source tree in a Java class, the
build fails.
I'm sure getting Groovy Eclipse and Gradle to deal with AST Transformations
is quite a task (no pun intended), but still, this is pretty strange
behavior. Any idea what's going on?
Thanks,
Ken
--
Kenneth A. Kousen
President
Kousen IT, Inc.
Email: [email protected]
Site: http://www.kousenit.com
Blog: http://kousenit.wordpress.com
Twitter: @kenkousen