2012-04-25 4 views
4

Я знаю, что я должен делать что-то просто мертвое, глупое, чтобы это не сработало, но я в ситуации, когда хочу динамически загружать поведение в работающий сервер , Я выбрал отличный инструмент для этого. Поведение должно будет ссылаться на классы на пути к классу сервера, такие как мои объекты модели, а также сторонние библиотеки, такие как Freemarker.Groovy, встроенный в Java, перезвонив на Java

Я бросил вместе этот глупый POC, чтобы показать выполнимость. Я не могу заставить groovy-скрипт разрешать классы Java «ThingyDoodle» и «Fooable», несмотря на то, что я устанавливаю родительский путь класса GroovyClassPath как текущий.

public class GroovyTest 
{ 
    public static void main (String [ ] argv) throws Throwable 
    { 
      // Setting parent classloader! 
      // also tried plain old "GroovyTest.class.getClassLoader()" as well 
     GroovyClassLoader gcl = new GroovyClassLoader (Thread.currentThread().getContextClassLoader()) ; 
     String src = 
       "class Arf implements Fooable { 
       public String foo () { 
        return new ThingyDoodle().doStuff('Arf');}}" ; 
     Class clazz = gcl.parseClass(src, "AppleSauce.groovy"); 
     Object aScript = clazz.newInstance(); 
     Fooable myObject = (Fooable) aScript; 
     System.out.println (myObject.foo()) ; 
    } 

    public static interface Fooable { public String foo () ; } 

    public static class ThingyDoodle 
    { 
     public String doStuff (String input) 
     { 
      return "Hi Worlds" ; 
     } 
    } 
} 

Что, черт возьми, я делаю неправильно здесь?

Exception in thread "main" org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: 
AppleSauce.groovy: 1: unable to resolve class Fooable 
@ line 1, column 1. 
    class Arf implements Fooable { public String foo () { return new ThingyDoodle().doStuff('Arf');}} 
^

AppleSauce.groovy: 1: unable to resolve class ThingyDoodle 
@ line 1, column 63. 
    ublic String foo () { return new Thingy 
            ^

ответ

3

Проблема в вашем коде заключается в том, что Интерфейс Fooable и Класс ThingyDoodle не может быть найден потому, что они оба являются внутренними l классы и должны быть квалифицированы с указанием имени класса, то есть GroovyTest. Я квалифицировал оба имени во встроенном скрипте (и фиксировал кавычки вокруг скрипта), и он работал как ожидалось.

import groovy.lang.GroovyClassLoader; 

public class GroovyTest 
{ 

    public static void main (String [ ] argv) throws Throwable 
    { 
      // Setting parent classloader! 
      // also tried plain old "GroovyTest.class.getClassLoader()" as well 
     GroovyClassLoader gcl = new GroovyClassLoader (Thread.currentThread().getContextClassLoader()) ; 
     String src = 
       "class Arf implements GroovyTest.Fooable { " + 
       "public String foo () { " + 
        "return new GroovyTest.ThingyDoodle().doStuff('Arf');}}" ; 
     Class clazz = gcl.parseClass(src, "AppleSauce.groovy"); 
     Object aScript = clazz.newInstance(); 
     Fooable myObject = (Fooable) aScript; 
     System.out.println (myObject.foo()) ; 
    }  
    public static interface Fooable { public String foo () ; } 

    public static class ThingyDoodle 
    { 
     public String doStuff (String input) 
     { 
      return "Hi Worlds" ; 
     } 
    } 


} 
+0

Хорошо, это было неловко :) – billmill

+0

Спасибо! Это то, что мне нужно. – billmill

+2

Не потейте. Я преуспел в том, чтобы придираться к [ошибкам] в других, но слепым к моим собственным [ошибкам] .... :) – Nicholas

2

Не знаю, как вы собираете ... Я попытался это (используя Gradle в качестве инструмента сборки), и он работает ...

./build.gradle

apply plugin:'application' 

repositories { 
    mavenCentral() 
} 

dependencies { 
    compile group: 'org.codehaus.groovy', name: 'groovy', version: '1.8.6' 
} 

mainClassName = 'org.timyates.GroovyTest' 

./src/main/java/org/timyates/Fooable.java

package org.timyates ; 

public interface Fooable { 
    public String foo() ; 
} 

./src/main/java/org/timyates/ThingyDoodle.java

package org.timyates ; 

public class ThingyDoodle { 
    public String doStuff(String input) { 
    return String.format("Hi %s", input) ; 
    } 
} 

./src/main/java/org/timyates/GroovyTest.java

package org.timyates ; 

import groovy.lang.GroovyClassLoader ; 

public class GroovyTest { 
    public static void main(String[] args) throws Exception { 
    GroovyClassLoader gcl = new GroovyClassLoader(GroovyTest.class.getClassLoader()) ; 
    String src = "import org.timyates.*\n" + 
       "class Arf implements Fooable {\n" + 
       " public String foo() {\n" + 
       " new ThingyDoodle().doStuff('tim')\n" + 
       " }\n" + 
       "}" ; 
    Class clazz = gcl.parseClass(src, "AppleSauce.groovy") ; 
    Fooable myObject = (Fooable)clazz.newInstance() ; 
    System.out.println(myObject.foo()) ; 
    } 
} 

Затем, когда я вхожу gradle run в командной строке, я получаю выход:

$ gradle run 
:compileJava 
:processResources UP-TO-DATE 
:classes 
:run 
Hi tim 

BUILD SUCCESSFUL 
+0

Я компилирую его встроенный, во время выполнения, на сервере J2EE. Если бы я использовал град, это бы побеждало цель этого упражнения. Спасибо, в любом случае! – billmill

+0

Достаточно честный, рад, что он отсортирован :-) Внесение такого рода информации в вопрос может сэкономить время в следующий раз ;-) Удачи вам! –