2012-05-03 2 views
4

Мы столкнулись с проблемой использования Spring Portlet MVC 3.1 при использовании нескольких классов контроллеров и DefaultAnnotationHandlerMapping.Как портлет MVC 3.1 Spring определяет, какой аннотированный метод визуализировать с несколькими контроллерами?

фон

  • Мы используем Spring Portlet MVC 3.1 с аннотациями для визуализации & действий фазы
  • Мы используем JBoss EPP 5.1.1

Выпуск

  • Для визуализации портлета запрос с Params, неправильная страница отображается в окне портала

Причина

  • Spring Portlet MVC использует другой метод @RenderMapping, чем ожидаемый метод с правильные аннотации

Технический анализ

  1. Все наши контроллеры содержат аннотации @RenderMapping и @ActionMapping, и у всех есть аргументы «params», чтобы гарантировать, что ожидаемый метод вызывается на основе набора параметров в наших URL-адресах портлета. Для рендеринга по умолчанию у нас есть метод с аннотацией @RenderMapping без аргумента «params», который мы используем для визуализации пустого JSP, когда запрос не содержит параметров.

  2. Основываясь на чтении главы 7 и 8 в вашей книге, мы узнали, что портлет диспетчера пытается получить соответствующее сопоставление обработчика для входящего запроса и отправить его соответствующему методу в настроенном компоненте контроллера. Наше предположение заключалось в том, что аннотация по умолчанию @RenderMapping (без параметров) вызывается только после того, как она проверила, что в контроллерах нет других методов с аннотацией, которая соответствует конкретным параметрам запроса.

  3. Однако мы отлаживались, чтобы понять, что это предположение неверно. Кажется, что DefaultAnnotationHandlerMapping пересекает доступный список аннотаций в компонентах Controller в некотором заданном порядке. Это означает, что если в списке появится компонент контроллера с аннотацией по умолчанию @RenderMapping (без параметров), в этом случае будет вызван метод с аннотацией по умолчанию @RenderMapping (без параметров), а не с правильным, что дальше по списку ,

Проявленная Ошибка

Мы разрабатываем в среде Windows, и развертывания в среде Linux. В Windows мы видим, что обработчик циклически перебирает компоненты контроллера в алфавитном порядке, поэтому мы сначала решили нашу проблему, добавив аннотированный метод @RenderMapping без каких-либо параметров в контроллере с именем bean, ближайшим к «Z».

В Linux, однако, похоже, что компоненты контроллера обнаружены в другом порядке. Я приложил журналы Spring ниже, чтобы выделить проблему. Аннотации no params @RenderMapping находятся в контроллере YourDetailsController, и, как вы можете видеть в журнале Windows, он отображается последним в списке, тогда как в Linux это не так. Это означает, что, если мы попытаемся получить доступ к одному из контроллеров, который появляется после этого в списке, то вместо этого вместо этого вы попадаете в аннотацию no params в YourDetailsController.

Вопросы

  1. Является ли наше предположение неверно?
  2. Означает ли наш диагноз ожидаемое поведение? Или это ошибка с Spring Portlet MVC?
  3. Есть ли другой способ получить аннотации, отсканированные для составления списка компонентов списка ручной работы?
  4. Будет ли использовать xml-конфигурацию (вместо аннотаций) удалить нашу проблему?
  5. Можем ли мы определить множественное отображение и порядок обработки, чтобы сопоставление обработчика по умолчанию являлось последним отображением обработчика, используемым портлетом диспетчера?

Любые мысли или советы, которые у вас есть по этой проблеме, будут очень признательны.

+0

Чья книга? Какие журналы? – beerbajay

+0

Портлеты в действии Ашиш Сарин. – user1372549

+0

JBoss сервер журналы – user1372549

ответ

0

Ответ получен из Ашиша зарин:

Hi Mike,

Хотя я не проверял, точно такой же сценарий, что вы следуете в проекте, но я могу сказать, что это Безразлично» t выглядят как правый подход для определения ваших контроллеров. Если ваши контроллеры используют только аннотаций @RenderMapping и @ActionMapping, то разработчикам может быть сложно определить точный контроллер , отвечающий за обработку входящего запроса портлета. Я бы рекомендую вам использовать @RequestMapping на уровне уровня до запрос портлета карты конкретному контроллеру и использовать параметры запроса для дальнейшего сужения запроса к определенному методу в контроллере.

Дайте мне знать, если у вас по-прежнему возникают проблемы с этим подходом.

0

Mike, Ваше описание - это точно та же проблема, с которой мы сталкиваемся. В Windows мы реализовали одно и то же обходное решение (префикс контроллера с рендерингом по умолчанию с Z), и это решило его. Этот же код в среде Linux имеет те же проблемы, что и ваши. Похоже, что это был вопрос о выпуске временного штампа, как методы, которые не собирались выбраться, но не повезло в этом маршруте.

Я предполагал, что это была ошибка весны.

Я думаю, что подход здесь в порядке - мы хотим, чтобы разные контроллеры обрабатывали разные функции, но нам нужен контроллер по умолчанию.

Я только что нашел одно обходное решение. Я переместил контроллер с методом рендеринга по умолчанию в другой пакет, поэтому он не включен в компонентное сканирование.

Я добавляю этот контроллер вручную (в файле portletname-portlet.xml) после строки компонента-сканирования, поэтому он добавляет это как последний контроллер.

+0

Привет, Уолтер, хорошо знать, что мы не одиноки! Порядок, в котором Spring циклически проходит через классы контроллера, чтобы найти подходящую аннотацию, является причиной проблемы - является ли она ошибкой или мы неправильно истолковали, как она должна работать, открыта для обсуждения. Мы ожидали, что Spring найдет аннотированный метод, который наиболее точно соответствует запросу - на самом деле он использует первое совпадение, которое он находит (что в нашем случае и ваше отличие в Windows и Linux). Ваше предложение поместить контроллер по умолчанию в отдельный пакет кажется хорошим. – user1372549

1

Mike. У меня такая же проблема. Я использую JDK 7, Spring 3.1.1.RELEASE и Hibernate 4.1.3.Final. Я разрабатываю Linux (Fedora) и развертываю на Linux (Fedora и SL).

Я был застрял, потому что я был уверен, что части (контроллеры) работают по одному, но вместе вызов запроса на визуализацию был случайным образом проигнорирован. Иногда изменение чего-то заставило бы все снова работать на запрос визуализации, но они никогда не работали вместе.

Как предложил Уолтер, когда я изолировал контроллер, содержащий только запрос рендеринга по умолчанию в своем собственном пакете, оставил в нем только запрос рендеринга по умолчанию (до того, как я получил запросы на удаление/просмотр) и отделил проверку контроллеров в портлет XML-конфигурации в два с проверкой контроллера по умолчанию после других, внезапно все работает как шарм.

Было бы интересно посмотреть, если это ошибка в весеннем трекере ...

+0

@ craig-edwards, Крейг, спасибо за ваш анализ. В моем случае он не работал в Tomcat. Но, как я сказал, решение разделения действия по умолчанию работает нормально. Я должен добавить, что я нашел другое, по-видимому, странное поведение (перед более глубоким анализом): если вы используете \ @RequestMapping вместо \ @RenderMapping и \ @ActionMapping во всех методах контроллера с действием по умолчанию, проблема, похоже, исчезает. Вы можете использовать аннотации сопоставления запросов и действий во всех других контроллерах. – Andrea

1

я был укушен этой проблемой в последнее время, так, что я хотел бы добавить некоторую дополнительную информацию, основанную на том, что я нашел.

В моем случае, мой контроллер по умолчанию (с пустыми @Controller и @ActionMapping аннотациями) всегда получать вызывается, хотя были более конкретно аннотированный контроллеры/действия (например, @Controller(XXXX) или @ActionMapping(YYYY)). Что сделало мой случай более странным, так это то, что он работал нормально в Tomcat/Pluto, но не в WAS/WebSphere Portal Server.

Как оказалось, в 3.1.x Spring имеется ошибка, которая означает, что обработчики аннотаций не отсортированы должным образом. См. https://jira.springsource.org/browse/SPR-9303 и https://jira.springsource.org/browse/SPR-9605. По-видимому, это зафиксировано в 3.1.3.

Большая загадка для меня была причиной того, что она работала в Tomcat, но не в WebSphere? Основная причина в том, что Pluto (2.0.3) использует Sun JRE 1.6.0, тогда как WebSphere использует IBM JRE 1.5.0. Два JRE имеют разную реализацию Collections.sort(), что приводит к другому порядку вывода при упорядочении элементов массива, которые сообщают, что они равны (то есть результат функции compareTo()). Из-за вышеупомянутой ошибки Spring (которая сообщает, что некоторые обработчики являются равными, когда это не должно), это означает, что упорядочение обработчиков не было детерминированным по двум JRE.

Итак, в моем случае IBM JRE просто случайно поставил контроллер по умолчанию в качестве самого первого элемента, и поэтому он будет подбираться каждый раз. Один из способов повлиять на упорядочение «равных» обработчиков (где «equal» является изворотливым определением из-за ошибки Spring) заключается в том, чтобы изменить порядок, который они обнаруживают Spring, - который влияет на порядок ввода в сортировку рутина. Вот почему на приведенные выше сообщения перемещение контроллера из сканирования компонентов в явном виде указано в настройках XML. В моем случае достаточно было сделать пакет контроллера по умолчанию последней записью в моем сканировании компонентов. Мне не нужно было переместить его в конфигурацию XML.

В любом случае, надеюсь, что это поможет пролить немного больше света на то, что происходит.

0

Мы используем контекст: component-scan (in nnn-portlet.xml), чтобы разделить отображения рендеринга контроллеров по умолчанию между портлетами.