groovy
  1. groovy
  2. GROOVY-3707

I wish i could parse a class using eval function of JSR223

    Details

    • Type: Wish Wish
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Duplicate
    • Affects Version/s: 1.6.4
    • Fix Version/s: None
    • Component/s: JSR / TCK / GLS
    • Labels:
      None
    • Testcase included:
      yes
    • Number of attachments :
      0

      Description

      Verbose version of the test passes, but it is a little ugly.

          public static final String FOO_CLASS = "class Foo { int getResult() { return 1; } } ; Foo.class";
          public static final String FOO = "class Foo { int getResult() { return 1; } }";
      
          public void testClassEvalVerbose() throws ScriptException {
              ScriptEngineManager factory = new ScriptEngineManager();
              ScriptEngine engine = factory.getEngineByName("groovy");
              assertEquals("Foo", ((Class) engine.eval(FOO_CLASS)).getCanonicalName());
          }
      
          public void testClassEvalBrief() throws ScriptException {
              ScriptEngineManager factory = new ScriptEngineManager();
              ScriptEngine engine = factory.getEngineByName("groovy");
              assertEquals("Foo", ((Class) engine.eval(FOO)).getCanonicalName());
          }
      

      Brief version throws:
      javax.script.ScriptException: javax.script.ScriptException: org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack: No signature of method: Foo.main() is applicable for argument types: ([Ljava.lang.String values: [[]]
      at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:119)
      at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:247)
      at com.jtstand.TestStepScriptTest.testClassEvalBrief(TestStepScriptTest.java:42)
      Caused by: javax.script.ScriptException: org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack: No signature of method: Foo.main() is applicable for argument types: ([Ljava.lang.String values: [[]]
      at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:307)
      at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:113)
      ... 28 more
      Caused by: org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack: No signature of method: Foo.main() is applicable for argument types: ([Ljava.lang.String values: [[]]

      Why?
      Is this what JSR223 specifies to do?
      To sad if yes!

        Issue Links

          Activity

          Hide
          blackdrag blackdrag added a comment -

          I think it says to execute the script whatever this means. The main method is called from within Groovy code. InvokerHelper#createScript is responsible for it in the end. But here basically is a problem. Should a class be executed? or should the class be returned? A script is a class to. It behaves a bit different, but it is in fact a class, one with a run method, that will be called directly. The current code does anything that is no script in a script, that executes a main method of the wrapped class. Well, maybe wrapper is so good not, proxy is probably better.

          What for example if your class is a junit test. Do you expect it to be executed, or the class being returned? Executing it means to run the test, returning the class means not executing it. You probably say the script returns a class, but there is no script, just the class. The script is a short form of creating a certain kind of class. So for Groovy the basic concept is the class, not the script. From that point of view it behaves absolutely correct.

          Show
          blackdrag blackdrag added a comment - I think it says to execute the script whatever this means. The main method is called from within Groovy code. InvokerHelper#createScript is responsible for it in the end. But here basically is a problem. Should a class be executed? or should the class be returned? A script is a class to. It behaves a bit different, but it is in fact a class, one with a run method, that will be called directly. The current code does anything that is no script in a script, that executes a main method of the wrapped class. Well, maybe wrapper is so good not, proxy is probably better. What for example if your class is a junit test. Do you expect it to be executed, or the class being returned? Executing it means to run the test, returning the class means not executing it. You probably say the script returns a class, but there is no script, just the class. The script is a short form of creating a certain kind of class. So for Groovy the basic concept is the class, not the script. From that point of view it behaves absolutely correct.
          Hide
          Roshan Dawrani added a comment -

          If I want to see how groovy gets JSR223 enabled, what code can I look at? Is that part of the core groovy codebase?

          Show
          Roshan Dawrani added a comment - If I want to see how groovy gets JSR223 enabled, what code can I look at? Is that part of the core groovy codebase?
          Hide
          Albert Kurucz added a comment -

          If I look at FOO as a script, it is a single statement which defines a Class type Object with the name Foo, and it (the Class!) should be returned by the evaluator, just like in this example i is returned:

              public static final String I = "Integer i = 1";
          
              public void testClassI() throws ScriptException {
                  ScriptEngineManager factory = new ScriptEngineManager();
                  ScriptEngine engine = factory.getEngineByName("groovy");
                  assertEquals(1, engine.eval(I));
              }
          

          Every Class is an Object. Right?
          See:
          http://java.sun.com/javase/6/docs/api/java/lang/Class.html

          Show
          Albert Kurucz added a comment - If I look at FOO as a script, it is a single statement which defines a Class type Object with the name Foo, and it (the Class!) should be returned by the evaluator, just like in this example i is returned: public static final String I = "Integer i = 1"; public void testClassI() throws ScriptException { ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine engine = factory.getEngineByName("groovy"); assertEquals(1, engine.eval(I)); } Every Class is an Object. Right? See: http://java.sun.com/javase/6/docs/api/java/lang/Class.html
          Hide
          Albert Kurucz added a comment -

          Regarding "You probably say the script returns a class, but there is no script, just the class."

          Would you say BAR is not a script, just classes?

              public static final String FOOBAR = "class Foo { int getResult() { return 1; } } ; class Bar extends Foo { int getResult() { return super.getResult() + 1; } } ; Bar b = new Bar(); b.getResult()";
              public static final String BAR = "class Foo { int getResult() { return 1; } } ; class Bar extends Foo { int getResult() { return super.getResult() + 1; } }";
          
              public void testFooBar() throws ScriptException {
                  ScriptEngineManager factory = new ScriptEngineManager();
                  ScriptEngine engine = factory.getEngineByName("groovy");
                  assertEquals(2, engine.eval(FOOBAR));
              }
          
              public void testBar() throws ScriptException {
                  ScriptEngineManager factory = new ScriptEngineManager();
                  ScriptEngine engine = factory.getEngineByName("groovy");
                  assertEquals("Bar", ((Class) engine.eval(BAR)).getCanonicalName());
              }
          

          From my point of view BAR is a script with two statements, both are Class definitions. The last one should be returned: the Bar Class.
          Instead of trying to execute the non-existent main method of Foo, resulting

          javax.script.ScriptException: javax.script.ScriptException: org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack: No signature of method: Foo.main() is applicable for argument types: ([Ljava.lang.String;) values: [[]]
                  at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:119)
                  at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:247)
                  at com.jtstand.TestStepScriptTest.testBar(TestStepScriptTest.java:34)
          Caused by: javax.script.ScriptException: org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack: No signature of method: Foo.main() is applicable for argument types: ([Ljava.lang.String;) values: [[]]
                  at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:307)
                  at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:113)
                  ... 28 more
          Caused by: org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack: No signature of method: Foo.main() is applicable for argument types: ([Ljava.lang.String;) values: [[]]
          
          Show
          Albert Kurucz added a comment - Regarding "You probably say the script returns a class, but there is no script, just the class." Would you say BAR is not a script, just classes? public static final String FOOBAR = "class Foo { int getResult() { return 1; } } ; class Bar extends Foo { int getResult() { return super .getResult() + 1; } } ; Bar b = new Bar(); b.getResult()" ; public static final String BAR = "class Foo { int getResult() { return 1; } } ; class Bar extends Foo { int getResult() { return super .getResult() + 1; } }" ; public void testFooBar() throws ScriptException { ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine engine = factory.getEngineByName( "groovy" ); assertEquals(2, engine.eval(FOOBAR)); } public void testBar() throws ScriptException { ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine engine = factory.getEngineByName( "groovy" ); assertEquals( "Bar" , (( Class ) engine.eval(BAR)).getCanonicalName()); } From my point of view BAR is a script with two statements, both are Class definitions. The last one should be returned: the Bar Class. Instead of trying to execute the non-existent main method of Foo, resulting javax.script.ScriptException: javax.script.ScriptException: org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack: No signature of method: Foo.main() is applicable for argument types: ([Ljava.lang.String;) values: [[]] at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:119) at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:247) at com.jtstand.TestStepScriptTest.testBar(TestStepScriptTest.java:34) Caused by: javax.script.ScriptException: org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack: No signature of method: Foo.main() is applicable for argument types: ([Ljava.lang.String;) values: [[]] at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:307) at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:113) ... 28 more Caused by: org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack: No signature of method: Foo.main() is applicable for argument types: ([Ljava.lang.String;) values: [[]]
          Hide
          Albert Kurucz added a comment -

          Regarding
          "What for example if your class is a junit test.
          Do you expect it to be executed, or the class being returned?
          Executing it means to run the test, returning the class means not executing it.
          "

              public static final String MY_THREAD = "class MyThread extends Thread { void run() { System.out.println(\"Hi there!\") } } ";
          
              public void testMyThread() throws ScriptException {
                  ScriptEngineManager factory = new ScriptEngineManager();
                  ScriptEngine engine = factory.getEngineByName("groovy");
                  engine.eval(MY_THREAD);
              }
          

          If the class is a Thread, Groovy should not try to execute it through its main method, resulting

          javax.script.ScriptException: javax.script.ScriptException: org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack: No signature of method: MyThread.main() is applicable for argument types: ([Ljava.lang.String;) values: [[]]
                  at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:119)
                  at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:247)
                  at com.jtstand.TestStepScriptTest.testMyThread(TestStepScriptTest.java:29)
          Caused by: javax.script.ScriptException: org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack: No signature of method: MyThread.main() is applicable for argument types: ([Ljava.lang.String;) values: [[]]
                  at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:307)
                  at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:113)
                  ... 28 more
          Caused by: org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack: No signature of method: MyThread.main() is applicable for argument types: ([Ljava.lang.String;) values: [[]]
          

          What if the Class is a Thread but it also has a static void main(String[] args)?
          Which kind of execution is the most correct kind?

          I think it would be easier to just return the Class.

          Show
          Albert Kurucz added a comment - Regarding "What for example if your class is a junit test. Do you expect it to be executed, or the class being returned? Executing it means to run the test, returning the class means not executing it. " public static final String MY_THREAD = "class MyThread extends Thread { void run() { System .out.println(\" Hi there!\ ") } } " ; public void testMyThread() throws ScriptException { ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine engine = factory.getEngineByName( "groovy" ); engine.eval(MY_THREAD); } If the class is a Thread, Groovy should not try to execute it through its main method, resulting javax.script.ScriptException: javax.script.ScriptException: org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack: No signature of method: MyThread.main() is applicable for argument types: ([Ljava.lang.String;) values: [[]] at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:119) at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:247) at com.jtstand.TestStepScriptTest.testMyThread(TestStepScriptTest.java:29) Caused by: javax.script.ScriptException: org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack: No signature of method: MyThread.main() is applicable for argument types: ([Ljava.lang.String;) values: [[]] at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:307) at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:113) ... 28 more Caused by: org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack: No signature of method: MyThread.main() is applicable for argument types: ([Ljava.lang.String;) values: [[]] What if the Class is a Thread but it also has a static void main(String[] args)? Which kind of execution is the most correct kind? I think it would be easier to just return the Class.
          Hide
          blackdrag blackdrag added a comment -

          Would I say BAR is not a script, just classes? yes.
          What if the Class is a Thread but it also has a static void main(String[] args)? It would execute the main method.

          What if the class you write extends Script? in Current Groovy the class would be executed through its run method. In your version it should return the class too. The problem now is, that at that point we don't know the difference between a written class and a normal script anymore.

          Show
          blackdrag blackdrag added a comment - Would I say BAR is not a script, just classes? yes. What if the Class is a Thread but it also has a static void main(String[] args)? It would execute the main method. What if the class you write extends Script? in Current Groovy the class would be executed through its run method. In your version it should return the class too. The problem now is, that at that point we don't know the difference between a written class and a normal script anymore.
          Hide
          Albert Kurucz added a comment -

          Yes, this is how Groovy Script is designed.
          I think JSR223 should specify the ScriptEngine's behavior to either yours or to mine.
          You agree?

          Show
          Albert Kurucz added a comment - Yes, this is how Groovy Script is designed. I think JSR223 should specify the ScriptEngine's behavior to either yours or to mine. You agree?
          Hide
          blackdrag blackdrag added a comment -

          I can't agree, since letting the class being returned means the language must have a concept of a class. Anything we specify here would be specific to Groovy and only Groovy.

          Show
          blackdrag blackdrag added a comment - I can't agree, since letting the class being returned means the language must have a concept of a class. Anything we specify here would be specific to Groovy and only Groovy.
          Hide
          Albert Kurucz added a comment -

          I agree that part: JSR223 should not allow those Engines to return a class which has no such concept as Class.
          But how about the others?

          Show
          Albert Kurucz added a comment - I agree that part: JSR223 should not allow those Engines to return a class which has no such concept as Class. But how about the others?
          Hide
          blackdrag blackdrag added a comment -

          You got me wrong. I said the JSR223 spec cannot require returning a class, because there might be no concept of a class. Therefore it is a language or script engine decision. If you try to execute your BAR script using the groovy command on the command line, then it won't work too. Doing it different for the script engine would mean to have it different than GroovyShell and other places.

          Show
          blackdrag blackdrag added a comment - You got me wrong. I said the JSR223 spec cannot require returning a class, because there might be no concept of a class. Therefore it is a language or script engine decision. If you try to execute your BAR script using the groovy command on the command line, then it won't work too. Doing it different for the script engine would mean to have it different than GroovyShell and other places.
          Guillaume Laforge made changes -
          Field Original Value New Value
          Link This issue is duplicated by GROOVY-3816 [ GROOVY-3816 ]
          Guillaume Laforge made changes -
          Resolution Duplicate [ 3 ]
          Assignee Guillaume Laforge [ guillaume ]
          Status Open [ 1 ] Closed [ 6 ]

            People

            • Assignee:
              Guillaume Laforge
              Reporter:
              Albert Kurucz
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: