使用Camel CDI在Wildfly中用Java执行Grrovy脚本时无法解决类问题

使用Camel CDI在Wildfly中用Java执行Grrovy脚本时无法解决类问题,java,groovy,apache-camel,cdi,wildfly-10,Java,Groovy,Apache Camel,Cdi,Wildfly 10,背景: 我使用GrrovyShell调用Groovy脚本,如下所示 @GET @Path("/endpoint/{param}") public Response getEndpointService(@PathParam("param") String messageId) { String scriptPath = "/path/to/Grrovyfile.gsh"; Binding binding = new Binding(); binding.setProp

背景:

我使用GrrovyShell调用Groovy脚本,如下所示

@GET
@Path("/endpoint/{param}")
public Response getEndpointService(@PathParam("param") String messageId) {

    String scriptPath = "/path/to/Grrovyfile.gsh";

    Binding binding = new Binding();
    binding.setProperty("in", inParams);

    GroovyShell shell = new GroovyShell(binding);
    shell.evaluate(new File(scriptPath));

}
Groovy脚本文件:

def condition = "good"
def severity = "N/A"
def detail = ""

import net.sf.json.JSONObject
import java.util.Random

try{

    def detailMap = [
        condition: condition,
        success: false,
        severity: severity,
    ]

    JSONObject jsonObject = JSONObject.fromObject(detailMap)
    detail = jsonObject.toString()
}
在这场战争中有一个单独的camel路由器实现,它是用camel cdi初始化的

import javax.enterprise.context.ApplicationScoped;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.cdi.ContextName;

@ApplicationScoped
@ContextName("camel-cdi-context")
public class MiscRouter extends RouteBuilder {

    @Override
    public void configure() throws Exception {
      // router dsl
    }

}
问题:
当路由器使用camel cdi启动时,上面的groovy代码失败,下面的错误。但是,当对
@ApplicationScoped
@ContextName(“camel-cdi-context”)
行进行注释时,将成功执行,并且没有错误

12:47:28,108 ERROR [stderr] (default task-11) org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
12:47:28,109 ERROR [stderr] (default task-11) /path/to/Grrovyfile.gsh: 9: unable to resolve class net.sf.json.JSONObject
12:47:28,109 ERROR [stderr] (default task-11)  @ line 9, column 1.
12:47:28,109 ERROR [stderr] (default task-11)    import net.sf.json.JSONObject
12:47:28,109 ERROR [stderr] (default task-11)    ^
12:47:28,109 ERROR [stderr] (default task-11) 
12:47:28,109 ERROR [stderr] (default task-11) 1 error
12:47:28,109 ERROR [stderr] (default task-11) 
12:47:28,110 ERROR [stderr] (default task-11)   at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:310)
12:47:28,110 ERROR [stderr] (default task-11)   at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:958)
12:47:28,110 ERROR [stderr] (default task-11)   at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:605)
12:47:28,113 ERROR [stderr] (default task-11)   at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:554)
12:47:28,113 ERROR [stderr] (default task-11)   at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298)
12:47:28,113 ERROR [stderr] (default task-11)   at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268)
12:47:28,113 ERROR [stderr] (default task-11)   at groovy.lang.GroovyShell.parseClass(GroovyShell.java:688)
12:47:28,113 ERROR [stderr] (default task-11)   at groovy.lang.GroovyShell.parse(GroovyShell.java:700)
12:47:28,113 ERROR [stderr] (default task-11)   at groovy.lang.GroovyShell.evaluate(GroovyShell.java:584)
12:47:28,114 ERROR [stderr] (default task-11)   at groovy.lang.GroovyShell.evaluate(GroovyShell.java:632)
12:47:28,114 ERROR [stderr] (default task-11)   at TestGroovy.getEndpointService(TestGroovy.java:91)
12:47:28,114 ERROR [stderr] (default task-11)   at org.jboss.weld.proxies.TestGroovy$Proxy$_$$_WeldClientProxy.getEndpointService(Unknown Source)
我假设这是一个类加载问题,我正在尝试解决这个问题。这里需要一些帮助

已尝试:

def condition = "good"
def severity = "N/A"
def detail = ""

import net.sf.json.JSONObject
import java.util.Random

try{

    def detailMap = [
        condition: condition,
        success: false,
        severity: severity,
    ]

    JSONObject jsonObject = JSONObject.fromObject(detailMap)
    detail = jsonObject.toString()
}
  • 使用jboss-deployment-structure.xml将这些依赖JAR作为模块提供
  • 使用
    编译器配置中的
    ImportCustomizer
    提供了到
    GroovyShell
    的导入
  • 还尝试使用启动单例EJB加载此文件
  • 尝试使用单独的注入加载此
  • 试图在单独的静态类中加载JSONObject
注意:

  • 请注意,相关JAR已经在war文件(WEB-INF/lib)中
  • 对于其他第三方工件,如
    com.fasterxml.jackson.databind.node.ObjectNode
    com.fasterxml.jackson.databind.ObjectMapper
    ,也会出现同样的问题
  • 但是对于第三方工件,如
    org.apache.log4j.Logger
    ,这个问题不会发生。(可能它们已经通过wildfly加载)
更新:
我离答案又近了一步。正如所说,当JVM启动时,类加载器返回类路径上的所有类。 因此,我尝试手动添加相关工件,并使用类加载器而不是GroovyShell调用脚本。成功了!现在需要找到一种方法,在JVM启动时在这些工件中加载这些类/将它们添加到wildfly中的类路径

URL[] classLoaderUrls = new URL[] {
        new URL("file:///path/to/repo/net/sf/json-lib/json-lib/2.4/json-lib-2.4-jdk15.jar"),
        new URL("file:///path/to/repo/commons-beanutils-1.8.0.jar"),
        new URL("file:///path/to/repo/commons-collections-3.2.1.jar"),
        new URL("file:///path/to/repo/commons-lang-2.5.jar"),
        new URL("file:///path/to/repo/commons-logging-1.1.1.jar"),
        new URL("file:///path/to/repo/groovy-all-2.4.11.jar"),
        new URL("file:///path/to/repo/net/sf/json/main/ezmorph-1.0.6.jar") };

URLClassLoader urlClassLoader = new URLClassLoader(classLoaderUrls);

//GroovyClassLoader groovyClassLoader = new GroovyClassLoader(urlClassLoader);
GroovyClassLoader groovyClassLoader = new GroovyClassLoader();

Script script = InvokerHelper.createScript(groovyClassLoader.parseClass(new
        File(scripts)), binding);
System.out.println("getEndpointService().script : " + script);

Object responseObj = script.run();
版本:

  • Wildfly版本:10.1.0
  • Wildfly Camle补丁:4.9.0
  • Groovy版本:Groovy-all-2.4.7

    • 我自己找到了答案。
      当您使用GroovyClassLoader而不是GroovyShell时,这个问题可以得到解决。实际上,我通过反编译深入到GroovyShell中,我看到它也在其中使用。

      注意:如果类路径中的JAR不需要使用上面文章中提到的URLClassLoader手动导入

      因此,通过下面的实现,它现在可以正常工作

      GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
      
      Script script = InvokerHelper.createScript(groovyClassLoader.parseClass(new
              File(scriptPath)), binding);
      logger.info("getEndpointService().script : " + script);
      
      Object responseObj = script.run();
      
      logger.info("getEndpointService().responseObj : " + responseObj);
      

      此外,如果需要使用代码库之类的附加属性,也可以使用GroovyCodeSource

      GroovyCodeSource groovyCodeSource = new GroovyCodeSource(new File(scriptPath));
      
      GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
      
      Script script = InvokerHelper.createScript(groovyClassLoader.parseClass(groovyCodeSource), binding);
      logger.info("getEndpointService().script : " + script);
      
      Object responseObj = script.run();
      
      logger.info("getEndpointService().responseObj : " + responseObj);
      

      您不需要反编译任何Groovy,源代码完全可用。。!