Wednesday 25 July 2007

java.lang.IllegalAccessError: tried to access method junit.framework.TestCase.()V

Seems this error happens when running ANT 1.7 and JUnit 3.8.1. The quick solution is upgrade junit to 3.8.X.

The cause as i can make out at this time is this. The junit task in the ant script forks a new jvm which creates a new classloader, this correctly picks up the junit 3.7.1 jar. Between 3.7 and 3.8.1 junit changed the default method name for getting the test name, from name() to getName(). ANT 1.7 in this case, first checks the junit version and then attempts to use reflection to call the correct test name method, but since the Task class has a protected constuctor method and there is a new classloader this IllegalAccessError is thrown.

The method name change is correct, the reflection stuff is correct but the classloader stuff is probally smack.


C:\Develop\UIClaims50_PeriodicBuilder\UI\UITools\components\cruisecontrol\projects\build-ant.xml:94: The following error occurred while executing this line:
C:\Develop\UIClaims50_PeriodicBuilder\UI\EJBServer\ant\uiclaims.junit.xml:43: java.lang.IllegalAccessError: tried to access method junit.framework.TestCase.()V from class org.apache.tools.ant.taskdefs.optional.junit.JUnitTaskMirrorImpl$VmExitErrorTest
at org.apache.tools.ant.ProjectHelper.addLocationToBuildException(ProjectHelper.java:541)
at org.apache.tools.ant.taskdefs.Ant.execute(Ant.java:418)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
at sun.reflect.GeneratedMethodAccessor170.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
...
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:104)
Caused by: C:\Develop\UIClaims50_PeriodicBuilder\UI\EJBServer\ant\uiclaims.junit.xml:43: java.lang.IllegalAccessError: tried to access method junit.framework.TestCase.()V from class org.apache.tools.ant.taskdefs.optional.junit.JUnitTaskMirrorImpl$VmExitErrorTest
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:115)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:357)
at org.apache.tools.ant.Target.performTasks(Target.java:385)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1329)
at org.apache.tools.ant.helper.SingleCheckExecutor.executeTargets(SingleCheckExecutor.java:38)
at org.apache.tools.ant.Project.executeTargets(Project.java:1181)
at org.apache.tools.ant.taskdefs.Ant.execute(Ant.java:416)
... 16 more
Caused by: java.lang.IllegalAccessError: tried to access method junit.framework.TestCase.()V from class org.apache.tools.ant.taskdefs.optional.junit.JUnitTaskMirrorImpl$VmExitErrorTest
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTaskMirrorImpl$VmExitErrorTest.(JUnitTaskMirrorImpl.java:80)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTaskMirrorImpl.addVmExit(JUnitTaskMirrorImpl.java:55)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.logVmExit(JUnitTask.java:1446)

Friday 13 July 2007

Google Syntax Highlighter

I'm just going to outline the three steps that are needed to enable the google syntax highlighter within blogger.com sites. A patched version of the 'shCore.js' script has been made available by Wctang, which corrects Issue 18 : Syntaxhighlighter doesn't work on blogger.com. In your template file

1 : Reference the wctang 'shCore.js'






2: Reference the 'svn/tags/1.5.0' version of the code scripts.









3 : Don't reference the 'SyntaxHighlighter.css'.

The '.dp-highlighter .tools' section needs to be patched to enable the syntax high lighter in firefox. Copy the content of the 'SyntaxHighlighter.css' to your template file, and make sure to update the correct section.


/* Styles for the tools */
.dp-highlighter .tools
{
padding: 3px 8px 3px 10px;
font: 9px Verdana, Geneva, Arial, Helvetica, sans-serif;
color: silver;
background-color: #f8f8f8;
/* text-align: right; */
padding-bottom: 10px;
border-left: 3px solid #6CE26C;
}


The final result ....


public class HelloSyntaxHighlighter
{
public HelloSyntaxHighlighter()
{
}

private void xx()
{
}

protected boolean static getXX()
{
return null;
}
}

Extending ANT JUnitTask

I needed to run the JUnitTask from code (since i needed to create a custom FileSet for the BatchTest). I started out with a plan Task, but while the code below runs the classpath details that the task uses are incorrect.


public class JunitTestExistsTask extends Task {

private void runAntJUnitTests()
throws BuildException {

try
{
JUnitTask jUnitTask = new JUnitTask();
jUnitTask.setOutputToFormatters(true);
jUnitTask.setProject(getProject());
jUnitTask.setShowOutput(true);
jUnitTask.setFork(true);

FormatterElement formatterElement = new FormatterElement();
TypeAttribute typeAttribute = new TypeAttribute();
typeAttribute.setValue("xml");
formatterElement.setType(typeAttribute);
jUnitTask.addFormatter(formatterElement);

BatchTest batchtest = super.createBatchTest();
File results = new File(getProject().getProperty("dir.test.results"));
batchtest.setTodir(results);
batchtest.addFileSet(createFileSet());

log("runAntJUnitTests --> execute()");
jUnitTask.execute();
}
catch(Throwable e)
{
e.printStackTrace();
throw new BuildException(e);
}
}
}


I wanted to avoid having to set the classpath in code, so i took another aproach to the issue. I decided my Task would extend from the JUnitTask, this allows me to keep that majority of the task config in xml, and reuse the default handling of classpaths and jvm args.


public class JunitTestExistsTask extends JUnitTask {

/**
* Add the test files to a BatchTest and start the JUnit process.
* @throws BuildException
*/
private void runAntJUnitTests()
throws BuildException {
try {
BatchTest batchtest = super.createBatchTest();
File results = new File(getProject().getProperty("dir.test.results"));

batchtest.setTodir(results);
batchtest.addFileSet(createFileSet());
super.execute();
} catch (Exception e) {
throw new BuildException(e);
}
}
}


The xml for this command



name="junitTestsExist"
classname="curam.uic.tools.policing.junit.JunitTestExistsTask"
classpathref="junit.target.cp"/>