我正在开发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)?
答案 0 :(得分:0)
默认情况下,Tomcat只查看/ WEB-INF / classes和/ WEB-INF / lib(对于每个war文件)中的文件,因为它们包含在类路径中。你可以做很多事情......
我个人会修复/修改我如何构建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错误!