Ошибка с расположением .class при построении WAR для Play! рамочное приложение - PullRequest
3 голосов
/ 12 октября 2011

Я работаю над 1.2 Play! приложение Framework, и у меня возникла проблема при его развертывании в качестве WAR на Tomcat 6.

На одной странице моего приложения отображается список информации. Эта информация извлекается из файла .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) и устанавливаю этот сгенерированный WAR на Tomcat (6.0). Когда сервер запущен и я пытаюсь получить доступ к соответствующей странице, я получаю следующую ошибку:

@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 голосов
/ 22 декабря 2011

Я наконец нашел ответ на эту проблему!

Парсер Yaml ( snakeyaml ) создает свой собственный ClassLoader для анализа файла .yml. Структура игры! Framework использует свой собственный ClassLoader, а скомпилированные классы находятся в каталоге WEB-INF/application/precompiled/java, который не является стандартом WAR. Из-за этого Yaml не смог получить классы, в частности MyClass.class.

Решением этой проблемы (кроме изменения WAR, например, с помощью Ant), является дать Play! ClassLoader для парсера Yaml . Вместо того чтобы писать это:

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! напрямую, без получения ошибки Yaml!

0 голосов
/ 05 ноября 2011

По умолчанию Tomcat просматривает только файлы в / WEB-INF / classes и / WEB-INF / lib (для каждого файла war), поскольку они включены в путь к классам.Есть несколько вещей, которые вы могли бы сделать ..

  • Поместите ваши классы в папку lib Tomcat, и они будут обрабатываться обычным загрузчиком, а не загрузчиком веб-приложений.(не рекомендуется, так как они будут доступны для других приложений)
  • Вы можете включить общий загрузчик в conf / catalina.properties и использовать любой каталог, который хотите.
  • добавить путь к переменной CLASSPATHв сценарии /bin/setclasspath.sh (или setclasspath.bat для Windows).

Лично я бы исправил / изменил способ создания файла war и убедился, что классы копируются в WEB-INF / classes вместо папки WEB-INF / application.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...