JSR-199 Compiler API loses runtime annotations when run under grails-run app

View: New views
4 Messages — Rating Filter:   Alert me  

JSR-199 Compiler API loses runtime annotations when run under grails-run app

by Dave Doty-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I have a project in which I am sending source code to a grails server to be compiled using the Java Compiler API, JSR-199. I am having problems implementing it, and have boiled the problem down to the following: When compiling a file under "normal circumstances" (running a java program with java, or running JUnit tests, for instance), the JSR-199 compiler preserves runtime annotations, but executing the exact same code when running grails run-app, the runtime annotations are not preserved by compilation. I have no idea what could account for the difference, or if this is a Grails issue, or a JSR-199 issue, or a bit of both. To reproduce the effect, do the following (using JDK 6, since JSR-199 was introduced in version 6):

1) Create a grails project by executing "grails create-app Test"
2) Download JUnit 4 and place the file junit-4.4.jar in Test/lib/
3) Create a package clientpackage under Test/src/java/, and in that package, create a file ExampleTest with the following code:

ExampleTest.java begin:
------------------------------------------------------------------------------------

package clientpackage;

import org.junit.Before;

public class ExampleTest {
  @Before
  public void setUp() {}
}

------------------------------------------------------------------------------------
ExampleTest.java end


4) Edit conf/BootStrap.groovy to contain the following code:

Bootstrap.groovy begin:
------------------------------------------------------------------------------------

import javax.tools.*
import javax.tools.JavaCompiler.CompilationTask

class BootStrap {

  def destroy = {}

  def init = {servletContext ->
    testCompiling()
  }

  def testCompiling() {
    println '\n*****************************************\n'

    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler()
    StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null)
    Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects('src/java/clientpackage/ExampleTest.java')
    StringWriter errorLog = new StringWriter()
    File outputDir = new File("bin/")
    outputDir.mkdir()
    List<String> options = Arrays.asList("-cp", "lib/junit-4.4.jar", "-d", outputDir.toString())
    CompilationTask task = compiler.getTask(errorLog, fileManager, null, options, null, compilationUnits)

    if (task.call()) {
      println 'compilation succeeded'
      URL[] urls = [outputDir.toURL()]
      URLClassLoader classLoader = new URLClassLoader(urls);
      Class<?> compiledClass;
      try {
        compiledClass = classLoader.loadClass('clientpackage.ExampleTest')
      } catch (ClassNotFoundException e) {
        throw new AssertionError("should not reach here if compilation succeeded")
      }
      println compiledClass.getMethod('setUp').getDeclaredAnnotations()
    } else {
      println "compilation failed:\n\n${errorLog.toString()}"
    }

    println '\n*****************************************\n'
  }

}

------------------------------------------------------------------------------------
Bootstrap.groovy end


5) Create a Groovy script (for instance, in the root directory of the project) named CompileExampleTest.groovy, that contains the same code between the println '\n*****************************************\n' statements above, and the same two import statements.
6) Run the script CompileExampleTest.groovy (with working directory set to the Test project root directory) and you should see the following output:

    compilation succeeded
    {@org.junit.Before()}

indicating that the method setUp() is annotated, at runtime, with the org.junit.Before annotation. Now run grails run-app, and you should see the following output when BootStrap.groovy runs:

    compilation succeeded
    {}

indicating that the org.junit.Before annotation was lost during compilation (or during class loading).

I have no idea what could explain the difference in behavior between these two seemingly identical pieces of code.

Thank you in advance,
Dave

Re: JSR-199 Compiler API loses runtime annotations when run under grails-run app

by Graeme Rocher-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

This is more of a Groovy problem, I would post it on that list

Cheers

On Tue, Jul 8, 2008 at 6:40 AM, Dave Doty <ddoty@...> wrote:

> I have a project in which I am sending source code to a grails server to be
> compiled using the Java Compiler API, JSR-199. I am having problems
> implementing it, and have boiled the problem down to the following: When
> compiling a file under "normal circumstances" (running a java program with
> java, or running JUnit tests, for instance), the JSR-199 compiler preserves
> runtime annotations, but executing the exact same code when running grails
> run-app, the runtime annotations are not preserved by compilation. I have no
> idea what could account for the difference, or if this is a Grails issue, or
> a JSR-199 issue, or a bit of both. To reproduce the effect, do the following
> (using JDK 6, since JSR-199 was introduced in version 6):
>
> 1) Create a grails project by executing "grails create-app Test"
> 2) Download JUnit 4 and place the file junit-4.4.jar in Test/lib/
> 3) Create a package clientpackage under Test/src/java/, and in that package,
> create a file ExampleTest with the following code:
>
> ExampleTest.java begin:
> ------------------------------------------------------------------------------------
>
> package clientpackage;
>
> import org.junit.Before;
>
> public class ExampleTest {
>   @Before
>   public void setUp() {}
> }
>
> ------------------------------------------------------------------------------------
> ExampleTest.java end
>
>
> 4) Edit conf/BootStrap.groovy to contain the following code:
>
> Bootstrap.groovy begin:
> ------------------------------------------------------------------------------------
>
> import javax.tools.*
> import javax.tools.JavaCompiler.CompilationTask
>
> class BootStrap {
>
>   def destroy = {}
>
>   def init = {servletContext ->
>     testCompiling()
>   }
>
>   def testCompiling() {
>     println '\n*****************************************\n'
>
>     JavaCompiler compiler = ToolProvider.getSystemJavaCompiler()
>     StandardJavaFileManager fileManager =
> compiler.getStandardFileManager(null, null, null)
>     Iterable<? extends JavaFileObject> compilationUnits =
> fileManager.getJavaFileObjects('src/java/clientpackage/ExampleTest.java')
>     StringWriter errorLog = new StringWriter()
>     File outputDir = new File("bin/")
>     outputDir.mkdir()
>     List<String> options = Arrays.asList("-cp", "lib/junit-4.4.jar", "-d",
> outputDir.toString())
>     CompilationTask task = compiler.getTask(errorLog, fileManager, null,
> options, null, compilationUnits)
>
>     if (task.call()) {
>       println 'compilation succeeded'
>       URL[] urls = [outputDir.toURL()]
>       URLClassLoader classLoader = new URLClassLoader(urls);
>       Class<?> compiledClass;
>       try {
>         compiledClass = classLoader.loadClass('clientpackage.ExampleTest')
>       } catch (ClassNotFoundException e) {
>         throw new AssertionError("should not reach here if compilation
> succeeded")
>       }
>       println compiledClass.getMethod('setUp').getDeclaredAnnotations()
>     } else {
>       println "compilation failed:\n\n${errorLog.toString()}"
>     }
>
>     println '\n*****************************************\n'
>   }
>
> }
>
> ------------------------------------------------------------------------------------
> Bootstrap.groovy end
>
>
> 5) Create a Groovy script (for instance, in the root directory of the
> project) named CompileExampleTest.groovy, that contains the same code
> between the println '\n*****************************************\n'
> statements above, and the same two import statements.
> 6) Run the script CompileExampleTest.groovy (with working directory set to
> the Test project root directory) and you should see the following output:
>
>     compilation succeeded
>     {@org.junit.Before()}
>
> indicating that the method setUp() is annotated, at runtime, with the
> org.junit.Before annotation. Now run grails run-app, and you should see the
> following output when BootStrap.groovy runs:
>
>     compilation succeeded
>     {}
>
> indicating that the org.junit.Before annotation was lost during compilation
> (or during class loading).
>
> I have no idea what could explain the difference in behavior between these
> two seemingly identical pieces of code.
>
> Thank you in advance,
> Dave
>



--
Graeme Rocher
Grails Project Lead
G2One, Inc. Chief Technology Officer
http://www.g2one.com

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Re: JSR-199 Compiler API loses runtime annotations when run under grails-run app

by Dave Doty-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Both of my examples are Groovy programs, running the exact same Groovy code. The only difference that I can observe is that in one case, grails run-app is running, and in the other case, it is not.

My original email had misleading wording, when I stated

When compiling a file under "normal circumstances" (running a java program with java, or running JUnit tests, for instance), ...

I should have instead stated,

When compiling a file under "normal circumstances" (running a *groovy* program with the JVM, or running *GroovyTest unit tests*, for instance), ...

since that is what my example, being a groovy program itself, demonstrates.

If you still think it is a Groovy issue, I will post it on that list. But I don't see how that would be the case, since both examples are Groovy code compiled with groovyc, and the only difference between them appears to be Grails.

Thank you,
Dave

On Tue, Jul 8, 2008 at 2:47 AM, Graeme Rocher <graeme@...> wrote:
This is more of a Groovy problem, I would post it on that list

Cheers

On Tue, Jul 8, 2008 at 6:40 AM, Dave Doty <ddoty@...> wrote:
> I have a project in which I am sending source code to a grails server to be
> compiled using the Java Compiler API, JSR-199. I am having problems
> implementing it, and have boiled the problem down to the following: When
> compiling a file under "normal circumstances" (running a java program with
> java, or running JUnit tests, for instance), the JSR-199 compiler preserves
> runtime annotations, but executing the exact same code when running grails
> run-app, the runtime annotations are not preserved by compilation. I have no
> idea what could account for the difference, or if this is a Grails issue, or
> a JSR-199 issue, or a bit of both. To reproduce the effect, do the following
> (using JDK 6, since JSR-199 was introduced in version 6):
>
> 1) Create a grails project by executing "grails create-app Test"
> 2) Download JUnit 4 and place the file junit-4.4.jar in Test/lib/
> 3) Create a package clientpackage under Test/src/java/, and in that package,
> create a file ExampleTest with the following code:
>
> ExampleTest.java begin:
> ------------------------------------------------------------------------------------
>
> package clientpackage;
>
> import org.junit.Before;
>
> public class ExampleTest {
>   @Before
>   public void setUp() {}
> }
>
> ------------------------------------------------------------------------------------
> ExampleTest.java end
>
>
> 4) Edit conf/BootStrap.groovy to contain the following code:
>
> Bootstrap.groovy begin:
> ------------------------------------------------------------------------------------
>
> import javax.tools.*
> import javax.tools.JavaCompiler.CompilationTask
>
> class BootStrap {
>
>   def destroy = {}
>
>   def init = {servletContext ->
>     testCompiling()
>   }
>
>   def testCompiling() {
>     println '\n*****************************************\n'
>
>     JavaCompiler compiler = ToolProvider.getSystemJavaCompiler()
>     StandardJavaFileManager fileManager =
> compiler.getStandardFileManager(null, null, null)
>     Iterable<? extends JavaFileObject> compilationUnits =
> fileManager.getJavaFileObjects('src/java/clientpackage/ExampleTest.java')
>     StringWriter errorLog = new StringWriter()
>     File outputDir = new File("bin/")
>     outputDir.mkdir()
>     List<String> options = Arrays.asList("-cp", "lib/junit-4.4.jar", "-d",
> outputDir.toString())
>     CompilationTask task = compiler.getTask(errorLog, fileManager, null,
> options, null, compilationUnits)
>
>     if (task.call()) {
>       println 'compilation succeeded'
>       URL[] urls = [outputDir.toURL()]
>       URLClassLoader classLoader = new URLClassLoader(urls);
>       Class<?> compiledClass;
>       try {
>         compiledClass = classLoader.loadClass('clientpackage.ExampleTest')
>       } catch (ClassNotFoundException e) {
>         throw new AssertionError("should not reach here if compilation
> succeeded")
>       }
>       println compiledClass.getMethod('setUp').getDeclaredAnnotations()
>     } else {
>       println "compilation failed:\n\n${errorLog.toString()}"
>     }
>
>     println '\n*****************************************\n'
>   }
>
> }
>
> ------------------------------------------------------------------------------------
> Bootstrap.groovy end
>
>
> 5) Create a Groovy script (for instance, in the root directory of the
> project) named CompileExampleTest.groovy, that contains the same code
> between the println '\n*****************************************\n'
> statements above, and the same two import statements.
> 6) Run the script CompileExampleTest.groovy (with working directory set to
> the Test project root directory) and you should see the following output:
>
>     compilation succeeded
>     {@org.junit.Before()}
>
> indicating that the method setUp() is annotated, at runtime, with the
> org.junit.Before annotation. Now run grails run-app, and you should see the
> following output when BootStrap.groovy runs:
>
>     compilation succeeded
>     {}
>
> indicating that the org.junit.Before annotation was lost during compilation
> (or during class loading).
>
> I have no idea what could explain the difference in behavior between these
> two seemingly identical pieces of code.
>
> Thank you in advance,
> Dave
>



--
Graeme Rocher
Grails Project Lead
G2One, Inc. Chief Technology Officer
http://www.g2one.com

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

   http://xircles.codehaus.org/manage_email





--
Dave

Re: JSR-199 Compiler API loses runtime annotations when run under grails-run app

by Dave Doty-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I tried the same example, but using a runtime-retained annotation from the Java standard API instead of an annotation in junit (the annotation I used was java.lang.Deprecated). The problem goes away in this circumstance; the compilation preserves the java.lang.Deprecated annotation even when run under Grails.

The code I posted previously manually attaches junit-4.4.jar to the CompilationTask by passing the "-cp junit-4.4.jar" option to the JavaCompiler.getTask method. This is a fix that is necessary under Grails, but not needed when running a plain Groovy script in the same project, because the JSR-199 compiler is apparently only aware of jar files that are on the classpath, and not those attached to the Grails rootLoader. I suspect this is related to the cause of the lost annotations, since java.lang.Deprecated is an annotation on the classpath, but org.junit.Before is not.

But I am so completely ignorant of how Grails handles classpath issues that I don't have any idea how to fix this. I have tried manually loading the org.junit.Before class before compiling, and it loads successfully. Whether org.junit.Before is loaded or not when the JSR-1-99 compiler is called, the compiler is "aware enough" of the org.junit.Before annotation to allow the program to compile (it would not compile successfully if it did not know what the org.junit.Before annotation was). But *something* is different between running Grails and running a plain old Groovy script, because in one case the annotation is still there after compilation, and in the other case it is not.

Dave

On Tue, Jul 8, 2008 at 10:17 AM, Dave Doty <ddoty@...> wrote:
Both of my examples are Groovy programs, running the exact same Groovy code. The only difference that I can observe is that in one case, grails run-app is running, and in the other case, it is not.

My original email had misleading wording, when I stated

When compiling a file under "normal circumstances" (running a java program with java, or running JUnit tests, for instance), ...

I should have instead stated,

When compiling a file under "normal circumstances" (running a *groovy* program with the JVM, or running *GroovyTest unit tests*, for instance), ...

since that is what my example, being a groovy program itself, demonstrates.

If you still think it is a Groovy issue, I will post it on that list. But I don't see how that would be the case, since both examples are Groovy code compiled with groovyc, and the only difference between them appears to be Grails.

Thank you,
Dave

On Tue, Jul 8, 2008 at 2:47 AM, Graeme Rocher <graeme@...> wrote:
This is more of a Groovy problem, I would post it on that list

Cheers

On Tue, Jul 8, 2008 at 6:40 AM, Dave Doty <ddoty@...> wrote:
> I have a project in which I am sending source code to a grails server to be
> compiled using the Java Compiler API, JSR-199. I am having problems
> implementing it, and have boiled the problem down to the following: When
> compiling a file under "normal circumstances" (running a java program with
> java, or running JUnit tests, for instance), the JSR-199 compiler preserves
> runtime annotations, but executing the exact same code when running grails
> run-app, the runtime annotations are not preserved by compilation. I have no
> idea what could account for the difference, or if this is a Grails issue, or
> a JSR-199 issue, or a bit of both. To reproduce the effect, do the following
> (using JDK 6, since JSR-199 was introduced in version 6):
>
> 1) Create a grails project by executing "grails create-app Test"
> 2) Download JUnit 4 and place the file junit-4.4.jar in Test/lib/
> 3) Create a package clientpackage under Test/src/java/, and in that package,
> create a file ExampleTest with the following code:
>
> ExampleTest.java begin:
> ------------------------------------------------------------------------------------
>
> package clientpackage;
>
> import org.junit.Before;
>
> public class ExampleTest {
>   @Before
>   public void setUp() {}
> }
>
> ------------------------------------------------------------------------------------
> ExampleTest.java end
>
>
> 4) Edit conf/BootStrap.groovy to contain the following code:
>
> Bootstrap.groovy begin:
> ------------------------------------------------------------------------------------
>
> import javax.tools.*
> import javax.tools.JavaCompiler.CompilationTask
>
> class BootStrap {
>
>   def destroy = {}
>
>   def init = {servletContext ->
>     testCompiling()
>   }
>
>   def testCompiling() {
>     println '\n*****************************************\n'
>
>     JavaCompiler compiler = ToolProvider.getSystemJavaCompiler()
>     StandardJavaFileManager fileManager =
> compiler.getStandardFileManager(null, null, null)
>     Iterable<? extends JavaFileObject> compilationUnits =
> fileManager.getJavaFileObjects('src/java/clientpackage/ExampleTest.java')
>     StringWriter errorLog = new StringWriter()
>     File outputDir = new File("bin/")
>     outputDir.mkdir()
>     List<String> options = Arrays.asList("-cp", "lib/junit-4.4.jar", "-d",
> outputDir.toString())
>     CompilationTask task = compiler.getTask(errorLog, fileManager, null,
> options, null, compilationUnits)
>
>     if (task.call()) {
>       println 'compilation succeeded'
>       URL[] urls = [outputDir.toURL()]
>       URLClassLoader classLoader = new URLClassLoader(urls);
>       Class<?> compiledClass;
>       try {
>         compiledClass = classLoader.loadClass('clientpackage.ExampleTest')
>       } catch (ClassNotFoundException e) {
>         throw new AssertionError("should not reach here if compilation
> succeeded")
>       }
>       println compiledClass.getMethod('setUp').getDeclaredAnnotations()
>     } else {
>       println "compilation failed:\n\n${errorLog.toString()}"
>     }
>
>     println '\n*****************************************\n'
>   }
>
> }
>
> ------------------------------------------------------------------------------------
> Bootstrap.groovy end
>
>
> 5) Create a Groovy script (for instance, in the root directory of the
> project) named CompileExampleTest.groovy, that contains the same code
> between the println '\n*****************************************\n'
> statements above, and the same two import statements.
> 6) Run the script CompileExampleTest.groovy (with working directory set to
> the Test project root directory) and you should see the following output:
>
>     compilation succeeded
>     {@org.junit.Before()}
>
> indicating that the method setUp() is annotated, at runtime, with the
> org.junit.Before annotation. Now run grails run-app, and you should see the
> following output when BootStrap.groovy runs:
>
>     compilation succeeded
>     {}
>
> indicating that the org.junit.Before annotation was lost during compilation
> (or during class loading).
>
> I have no idea what could explain the difference in behavior between these
> two seemingly identical pieces of code.
>
> Thank you in advance,
> Dave
>



--
Graeme Rocher
Grails Project Lead
G2One, Inc. Chief Technology Officer
http://www.g2one.com

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

   http://xircles.codehaus.org/manage_email





--
Dave



--
Dave
LightInTheBox - Buy quality products at wholesale price