I have been unable to make the Yielder work correctly in a Maven2
application.
Here is the error message I am getting at the moment:
class: com/mycompany/App$1, method: yieldNextCore signature: ()V)
Incompatible argument to function"
type="java.lang.VerifyError">java.lang.VerifyError: (class: com/
mycompany/App$1, method: yieldNextCore signature: ()V) Incompatible
argument to function
at com.mycompany.App.getMyIterable(App.java:22)
at com.mycompany.AppTest.testApp(AppTest.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
at java.lang.reflect.Method.invoke(Method.java:597)
at
org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:
99)
at
org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:
81)
at
org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:
34)
at
org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:
75)
at
org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:
45)
at
org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:
66)
at
org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:
35)
at org.junit.internal.runners.TestClassRunner
$1.runUnprotected(TestClassRunner.java:42)
at
org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:
34)
at
org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:
52)
at
org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:
62)
at
org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:
138)
at
org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:
125)
at org.apache.maven.surefire.Surefire.run(Surefire.java:132)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
at java.lang.reflect.Method.invoke(Method.java:597)
at
org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:
290)
at
org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:
818)
Here is my test code:
// App.java
package com.mycompany;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import com.infomancers.collections.yield.Yielder;
public class App {
public Iterable<String> getMyIterable() {
final List<String> mystrings = Arrays.asList(new String[] {"a",
"b", "c", "d", "e", "f"});
// return new Iterable<String>() {
// public Iterator<String> iterator() {
// return mystrings.iterator();
// }
// };
return new Yielder<String>() {
protected void yieldNextCore() {
for (String mystring : mystrings) {
System.out.println("in getMyIterable, yield return: " +
mystring);
yieldReturn(mystring);
}
System.out.println("in getMyIterable, yield break");
yieldBreak();
}
};
}
}
Here is my calling JUnit test:
// AppTest.java
package com.mycompany;
/**
* Unit test for simple App.
*/
public class AppTest {
@org.junit.Test
public void testApp() {
App app = new App();
System.out.println("Comes here");
Iterable<String> myiterable = app.getMyIterable();
System.out.println("Comes here 2");
for (String mystring : myiterable) {
System.out.println("in caller, mystring=" + mystring);
}
}
}
And here is my maven2 pom.xml file:
<project xmlns="
http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://
www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany</groupId>
<artifactId>itertest</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>itertest</name>
<url>
http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>asm</groupId>
<artifactId>asm-all</artifactId>
<version>3.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.infomancers.collections</groupId>
<artifactId>yielder</artifactId>
<version>0.2.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.3.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.3</version>
<configuration>
<argLine>-javaagent:/home/sujit/.m2/repository/com/
infomancers/collections/yielder/0.2.2/yielder-0.2.2.jar</argLine>
<useSystemClassLoader>true</useSystemClassLoader>
</configuration>
</plugin>
</plugins>
</build>
</project>
I read somewhere that there may be asm issues, so the asm-all is
downloaded from the yielder svn repository. Also Spring (which I
normally always have as a dependency in my apps and which use asm) has
been stripped out for this test.
In the surefire-plugin, I have to set the useSystemClassLoader setting
because otherwise I get this error:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
at java.lang.reflect.Method.invoke(Method.java:597)
at
sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:
323)
at
sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:
338)
Caused by: java.lang.NoClassDefFoundError: org/objectweb/asm/
ClassVisitor
at
com.infomancers.collections.yield.AgentMain.premain(AgentMain.java:46)
... 6 more
FATAL ERROR in native method: processing of -javaagent failed
If I execute the commented block instead of the Yielder block in
App.java (where I build a List rather than generate using Yielder) the
test works fine, so the returning of an Iterable part is valid. Not
sure if its ok to use the Yielder in this way, please let me know if
its not correct.
For a while, I was using this setting for maven-surefire-plugin (where
I suspect the instrumentation was not happening at all):
<configuration> <maven.junit.jvmargs>-javaagent:/home/
sujit/.m2/repository/com/infomancers/collections/yielder/0.2.2/
yielder-0.2.2.jar</maven.junit.jvmargs>
</configuration>
and I was getting this output from my test:
Comes here
Comes here 2
in getMyIterable, yield return: a
in getMyIterable, yield return: b
in getMyIterable, yield return: c
in getMyIterable, yield return: d
in getMyIterable, yield return: e
in getMyIterable, yield return: f
in getMyIterable, yield break
So the loop in the getNextCore() was being executed completely before
returning and the caller was not looping at all. But I think this is
because the -javaagent setting was not being activated.
I am not sure if I am doing something wrong in the code (perhaps the
Yielder is not supposed to be used this way), or if I haven't set up
the maven-surefire-plugin correctly to use the javaagent call. I am
thinking its the former based on the error message I am currently
getting.
Thanks in advance for any help you can provide,
Sujit