为Play构建WAR时,.class位置出错!框架应用

时间:2011-10-12 06:49:11

标签: java tomcat playframework

我正在开发1.2 Play!框架应用程序,在Tomcat 6上将其部署为WAR时遇到问题。

我的应用程序的一页显示了一个信息列表。 这些信息是从.yml文件中检索的。 所以我有一个控制器从这个Iterable<Object>文件中生成.yml,如下所示:

public static void myFunction() {
    Constructor constructor = new Constructor(MyClass.class); // org.yaml.snakeyaml.constructor.Constructor
    constructor.addTypeDescription(new TypeDescription(MyClass.class));
    Yaml yaml = new Yaml(constructor);
    Iterable<Object> listOfInfo = yaml.loadAll(Application.class.getResourceAsStream("/my-file.yml"));
    render("Application/my-page.html", listOfInfo);
}

重点是MyClass位于app/my/company/my-app/包裹中(my.company.my-app.MyClass)。

当我使用play run运行我的应用程序时,没有问题。

现在,我构建WAR包(使用play war -o some/dir --zip),然后在Tomcat(6.0)上安装此生成的WAR。 服务器启动后,尝试访问相应的页面,我收到以下错误:

@683lh76fn
Internal Server Error (500)

Template execution error (In /app/views/Application/my-page.html around line 9)
Execution error occured in template /app/views/Application/my-page.html. Exception raised was ConstructorException : null; Can't construct a java object f
or tag:yaml.org,2002:my.company.my-app.MyClass; exception=Class not found: my.company.my-app.MyClass.

play.exceptions.TemplateExecutionException: null; Can't construct a java object for tag:yaml.org,2002:my.company.my-app.MyClass; exception
=Class not found: my.company.my-app.MyClass
        at play.templates.BaseTemplate.throwException(BaseTemplate.java:84)
        at play.templates.GroovyTemplate.internalRender(GroovyTemplate.java:252)
        at play.templates.Template.render(Template.java:26)
        at play.templates.GroovyTemplate.render(GroovyTemplate.java:184)
        at play.mvc.results.RenderTemplate.<init>(RenderTemplate.java:24)
        at play.mvc.Controller.renderTemplate(Controller.java:659)
        at play.mvc.Controller.renderTemplate(Controller.java:639)
        at play.mvc.Controller.render(Controller.java:694)
        at controllers.Application.myFunction(Application.java:311)

如果我查看爆炸的战争,我会看到my.company.my-app.MyClass位于目录WEB-INF/application/precompiled/java/my/company/my-app/目录中。

如果我将此目录移动到WEB-INF/classes,那么我不会再出现此错误。

为什么会出现此错误?我有什么选择让它工作(不用手动修改WAR)?

2 个答案:

答案 0 :(得分:0)

默认情况下,Tomcat只查看/ WEB-INF / classes和/ WEB-INF / lib(对于每个war文件)中的文件,因为它们包含在类路径中。你可以做很多事情......

  • 将您的类放在Tomcat lib文件夹中,它们将由公共加载器而不是webapp加载器处理。 (不推荐,因为它们可用于其他应用程序)
  • 您可以在conf / catalina.properties中启用共享加载程序,并使用您想要的任何目录。
  • 在'/bin/setclasspath.sh'脚本(或setclasspath.bat)中添加CLASSPATH变量的路径 视窗)。

我个人会修复/修改我如何构建war文件,并确保将类复制到WEB-INF / classes而不是WEB-INF / application文件夹。

答案 1 :(得分:0)

我终于找到了这个问题的答案!

Yaml解析器(snakeyaml)创建自己的ClassLoader以解析.yml文件。 Play的结构! framework使用自己的ClassLoader,编译的类位于WEB-INF/application/precompiled/java目录中,而不是WAR标准。 因此,Yaml无法检索类,特别是MyClass.class

解决此问题的解决方案(例如,使用Ant修改WAR除外)是give the Play! ClassLoader to the Yaml parser。而不是写那个:

Constructor constructor = new Constructor(MyClass.class);
constructor.addTypeDescription(new TypeDescription(MyClass.class));

我写道:

CustomClassLoaderConstructor constructor = new CustomClassLoaderConstructor(MyClass.class, MyController.class.getClassLoader());
constructor.addTypeDescription(new TypeDescription(MyClass.class));

使用这个,我可以使用Play创建的WAR!直接没有得到Yaml错误!