Как модулировать приложение JSF / Facelets / Spring с OSGi? - PullRequest
26 голосов
/ 04 апреля 2010

Я работаю с очень большими приложениями JSF / Facelets, которые используют Spring для управления DI / bean-компонентами. Мои приложения имеют модульную структуру, и в настоящее время я ищу подходы для стандартизации модульности.

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

  • Классы;
  • Статические ресурсы (изображения, CSS, скрипты);
  • Шаблоны Facelet;
  • Управляемые bean-компоненты - контексты приложений Spring, с запросами, сессиями и bean-областями приложений (альтернатива - управляемые bean-компоненты JSF);
  • Материал API сервлетов - сервлеты, фильтры, прослушиватели (это необязательно).

Чего я хотел бы избежать (почти любой ценой), так это необходимости копировать или извлекать ресурсы модуля (например, шаблоны Facelets) в WAR или расширять web.xml для сервлетов, фильтров и т. Д. Модуль должен достаточно добавить модуль (JAR, bundle, artifact, ...) в веб-приложение (WEB-INF/lib, bundles, plugins, ...), чтобы расширить веб-приложение с помощью этого модуля.

В настоящее время я решаю эту задачу с помощью специального модульного решения, основанного на использовании ресурсов classpath:

  • Специальный сервлет ресурсов обслуживает статические ресурсы из ресурсов classpath (JAR).
  • Специальный распознаватель ресурсов Facelets позволяет загружать шаблоны Facelet из ресурсов classpath.
  • Spring загружает контексты приложения через шаблон classpath*:com/acme/foo/module/applicationContext.xml - это загружает контексты приложения, определенные в JAR модуля.
  • Наконец, пара делегирующих сервлетов и фильтров делегирует обработку запросов к сервлетам и фильтрам, настроенным в контекстах приложения Spring из модулей.

В последние дни я много читал об OSGi и думал о том, как (и если) я мог бы использовать OSGi в качестве стандартизированного подхода к модульности. Я думал о том, как можно решить отдельные задачи с помощью OSGi:

  • Статические ресурсы - пакеты OSGi, которые хотят экспортировать статические ресурсы, регистрируют ResourceLoader экземпляров в контексте пакета. Центральный ResourceServlet использует эти загрузчики ресурсов для загрузки ресурсов из пакетов.
  • Шаблоны Facelet - как и выше, центральный ResourceResolver использует сервисы, зарегистрированные в пакетах.
  • Управляемые компоненты - Я не знаю , как использовать такое выражение, как #{myBean.property}, если myBean определено в одном из пакетов.
  • Материал API сервлетов - используйте что-то вроде WebExtender / Pax Web для регистрации сервлетов, фильтров и т. Д.

Мои вопросы:

  • Я изобретаю здесь велосипед? Существуют ли стандартные решения для этого? Я нашел упоминание о Spring Slices, но не смог найти много документации об этом.
  • Как вы думаете, OSGi - подходящая технология для описанной задачи?
  • Является ли мой эскиз приложения OSGI более или менее правильным?
  • Как должны обрабатываться управляемые bean-компоненты (особенно область запроса / сеанса)?

Я был бы в целом благодарен за ваши комментарии.

Ответы [ 5 ]

13 голосов
/ 13 апреля 2010

То, что вы хотите сделать, звучит выполнимо, с несколькими оговорками:

Слой вида: Во-первых, ваш слой вида звучит немного перегруженным. Существуют и другие способы модуляции компонентов JSF с использованием пользовательских компонентов, которые позволяют избежать головной боли, связанной с попыткой создать нечто столь же драматичное, как управляемые bean-компоненты с поздним связыванием.

Сами модули: Во-вторых, ваши модули не кажутся особенно модульными. Ваш первый маркированный список звучит так, как будто вы пытаетесь создать совместимые веб-приложения, а не модули как таковые. Моя идея модуля заключается в том, что каждый компонент имеет четко определенную и более или менее дискретную цель. Например, как ex лежит в основе vi . Если вы идете по маршруту OSGi, то мы должны определить модульное, как это: Модульное, ради этого обсуждения, означает, что компоненты могут быть заменены в горячем режиме, то есть их можно добавить и удалено без нарушения работы приложения.

Зависимости: Меня немного беспокоит ваше описание модулей как "возможно зависящих друг от друга". Возможно, вы (я надеюсь) уже знаете это, но ваши зависимости должны сформировать ориентированный ациклический граф. После того, как вы введете круговую зависимость, вы попросите обидеть мир с точки зрения возможной ремонтопригодности приложения. Одним из самых больших недостатков OSGi является то, что он не не предотвращает циклические зависимости, так что вам решать, как это сделать. В противном случае ваши зависимости будут расти как кудзу и постепенно душат остальную часть экосистемы вашей системы.

Сервлеты: Fuhgeddaboudit. Вы не можете позднее связывать сервлеты с веб-приложением, пока не будет запущена спецификация Servlet 3.0 (как указал Паскаль). Чтобы запустить отдельный служебный сервлет, вам нужно поместить его в собственное приложение.


ОК, очень много предостережений. Давайте подумаем о том, как это может работать:

Вы определили свой собственный модуль JSF, чтобы делать ... что именно? Давайте дадим ему определенную, довольно тривиальную цель: экран входа в систему. Итак, вы создаете свой экран входа в систему, позднее связываете его с помощью OSGi в своем приложении и ... что дальше? Как приложение узнает о функциональности входа в систему, если вы не определили ее на своей странице .jspx? Как приложение узнает, что оно находится там, где оно не может знать?

Есть способы обойти это с помощью условных включений и тому подобного (например, <c:if #{loginBean.notEmpty}>), но, как вы сказали, вещи становятся немного затруднительными, когда ваш управляемый loginBean существует в другом модуле, который, возможно, даже не был представлен в приложение еще. Фактически, вы получите исключение сервлета, если этот loginBean не существует. Так что ты делаешь?

Вы определяете API в одном из ваших модулей. Все управляемые bean-компоненты, которые вы собираетесь совместно использовать между модулями, должны быть указаны как интерфейсы на этом уровне API. И все ваши модули должны иметь реализации по умолчанию любого из этих интерфейсов, которые они намерены использовать. И этот API должен быть общим для всех совместимых модулей. Затем вы можете использовать OSGi и Spring, чтобы связать вместе указанные компоненты с их реализацией.

Мне нужно уделить время, чтобы указать, что я не подхожу к этой проблеме. Не за что. Учитывая что-то вроде простой страницы входа в систему или даже такой сложной, как график акций, я лично предпочел бы создать собственный компонент JSF. Но если требование «я хочу, чтобы мои управляемые bean-компоненты были модульными (т. Е. С возможностью горячей замены и т. Д.)», Это единственный известный мне способ заставить его работать. И я даже не совсем уверен, что будет работать. Этот обмен электронной почтой предполагает, что это проблема, над которой разработчики JSF только начали работать.

Обычно я рассматриваю управляемые bean-компоненты как часть уровня представления, и поэтому использую их только для логики представления и делегирую все остальное на уровень обслуживания. По моему мнению, создание управляемых bean-компонентов с поздним связыванием - это продвижение их из уровня представления в бизнес-логику. Есть причина, по которой все эти учебные пособия сосредоточены на службах: потому что большую часть времени вы хотите подумать о том, что потребуется приложению для запуска «без головы», и насколько легко было бы «убрать» ваш взгляд, если, для Например, вы хотели, чтобы он работал со всеми его функциями на телефоне Android.

Но, похоже, многое из того, с чем вы работаете, это сама логика представления - например, необходимость поменять местами другой шаблон представления. OSGi / Spring должна быть в состоянии помочь, но вам нужно что-то в вашем приложении, чтобы выбирать между доступными реализациями: почти то, для чего был создан OSGi Service Registry.

Это оставляет статические ресурсы. Вы можете модулировать их, но помните, что вам нужно определить интерфейс для извлечения этих ресурсов, и вам нужно будет обеспечить реализацию по умолчанию, чтобы ваше приложение не задыхалось, если они отсутствуют. Если i18n является соображением, это может быть хорошим способом. Если вы хотите быть действительно предприимчивым, то вы можете поместить свои статические ресурсы в JNDI. Это сделало бы их полностью горячей заменой и избавило бы вас от необходимости пытаться решить, какую реализацию использовать программно, но есть некоторые недостатки: любой неудачный поиск приведет к тому, что ваше приложение вызовет исключение NamingException. И это излишне. JNDI обычно используется в веб-приложениях для конфигурации приложений.

Что касается оставшихся вопросов:

Я изобретаю здесь велосипед? Существуют ли стандартные решения для этого?

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

Как вы думаете, OSGi - подходящая технология для описанной задачи?

Если вам нужна горячая замена модулей, тогда вы можете выбрать OSGi и облегченный интерфейс ServiceLocator.

Является ли мой эскиз приложения OSGI более или менее правильным?

Я не могу сказать, не зная больше, где находятся границы ваших компонентов. На данный момент, похоже, вы заставляете OSGi делать больше, чем он способен.

Но не верьте мне на слово. I найдено прочее материалы для чтения в этих местах.

И поскольку вы спрашиваете о Spring Slices, этого должно быть достаточно, чтобы вы начали . Вам понадобится Git-клиент, и, похоже, вы будете изучать приложение, просматривая исходный код. И это очень ранний прототип кода.

3 голосов
/ 22 ноября 2010

Я сталкиваюсь с такими же проблемами в моем текущем проекте. На мой взгляд, OSGi является лучшим и самым чистым решением с точки зрения стандартов и будущей поддержки, но в настоящее время вы можете столкнуться с некоторыми проблемами, если попытаетесь использовать его в веб-приложении:

  1. пока что нет хорошо интегрированного решения между Web-контейнером и платформой OSGi.
  2. OSGi может быть слишком много для пользовательского веб-приложения, которое просто ищет простую модульную архитектуру. Я хотел бы рассмотреть OSGi, если мой проект должен поддерживать сторонние расширения, которые не находятся под нашим 100-процентным контролем, если проект нуждается в горячих повторных развертываниях, строгих правилах доступа между плагинами и т. Д.

Мне кажется, что мне подходит подходящее решение, основанное на загрузчиках классов и фильтрах ресурсов. В качестве примера вы можете изучить исходный код Hudson или проект Java Plug-in Framework (JPF) (http://jpf.sourceforge.net/).

Что касается расширения web.xml, нам может повезти со спецификацией Servlet 3.0 (http://today.java.net/pub/a/today/2008/10/14/introduction-to-servlet-3.html#pluggability-and-extensibility).

2 голосов
/ 10 апреля 2010

Здесь неплохо было бы использовать «фрагмент дескриптора развертывания веб-модуля» (он же web-фрагмент.xml), представленный в спецификации Servlet 3.0 .Спецификация определяет его следующим образом:

Веб-фрагмент представляет собой логическое разбиение веб-приложения таким образом, что фреймворки, используемые в веб-приложении, могут определять все артефакты, не запрашивая разработчиков или редакторов.добавить информацию в web.xml.

Java EE 6, возможно, сейчас не вариант для вас.Тем не менее, это будет стандартное решение.

1 голос
/ 10 апреля 2010

Enterprise OSGi - это довольно новый домен, поэтому не думайте, что вы получите решение, которое напрямую удовлетворяет ваши потребности. Тем не менее, одна из вещей, которые я обнаружил отсутствующими в Equinox (движок osgi за Eclipse и, следовательно, с самой большой базой пользователей!), - это согласованная конфигурация / сервис DI. Недавно в моем проекте возникли аналогичные потребности, и мы завершили создание простой службы конфигурации osgi.

Одна из проблем, которая будет присуща модульным приложениям, связана с DI, поскольку видимость модуля может в некоторых случаях препятствовать доступу к классу. Мы обошли это, используя политику зарегистрированных друзей, которая не слишком идеальна, но работает.

Помимо конфигурации, вы можете взглянуть на недавно выпущенную книгу Equinox для получения инструкций по использованию OSGi в качестве основы для создания модульных приложений. Примеры могут быть специфичными для Equinox, но принципы будут работать с любой средой OSGi. Ссылка - http://equinoxosgi.org/

0 голосов
/ 05 апреля 2010

Вам следует взглянуть на Spring DM Server (он переводится на Eclipse Virgo, но еще не выпущен).В последней корпоративной спецификации OSGi, которая также только что была выпущена, есть много хорошего.

Некоторые из учебных пособий Spring DM помогут, я думаю.Но да, можно загружать ресурсы и классы извне веб-пакета, используя стандартную модульность.В этом, это хорошо подходит.

Что касается контекста сеанса - он обрабатывается так, как вы ожидаете в сеансе.Однако вы можете столкнуться с проблемами при совместном использовании этого сеанса между веб-пакетами до такой степени, что не будете уверены, что это вообще возможно.

Вы также можете использовать один веб-пакет, а затем использовать, например, реестр расширений Eclipse для расширения возможностей вашего веб-приложения.

...