Как создать модульное приложение JSF 2.0?

У меня есть приложение с четко определенным интерфейсом. Он использует CDI для разрешения модулей (в частности, он использует точки внедрения Instance <> на интерфейсах API для разрешения модулей) и без проблем передает различные данные обратно и четвертое через интерфейсы. Я намеренно сохранил API и реализацию отдельно, и модули наследуются только от API, чтобы избежать тесной связи, а приложение знает о модулях только через зависимости времени выполнения и передачу данных через API. Приложение отлично работает без модулей, которые можно добавить, просто перетащив jar в папку WEB-INF / lib и перезапустив сервер приложений.

Я сталкиваюсь с проблемами, потому что хочу, чтобы модули создавали файл часть представления, и поэтому я хочу вызвать переносимым способом либо компонент JSF, либоили выполните включение из модуля, чтобы он отобразил свое представление. Я уже решил, какой модуль я хочу вызвать, и готов ссылки на интерфейс модуля. Первоначально я думал сделать это с помощью ui: include, который просит модуль предоставить, где находится его шаблон представления, но я понятия не имею, как ответить на этот запрос осмысленным образом, поскольку разрешение представления выполняется из приложения root, а не корень библиотеки.

Краткое изложение состоит в том, что я понятия не имею, как перейти от приложения к библиотеке с помощью JSF для файлов .xhtml (шаблон / компонент).

Использование CC было бы неплохо, но как мне указать, что мне нужен конкретный экземпляр CC во время выполнения, вместо того, чтобы жестко закодировать его на странице?

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

Я бы предпочел избежать принуждения разработчиков модулей к если возможно, используйте сверхмощный подход UIComponent, что означает либо динамический способ выполнения ui: include (или некоторый эквивалент), либо динамический способ вызова CC. (Я не против кодировать подход UIComponent ОДИН РАЗ в приложении, если это то, что нужно, чтобы облегчить жизнь разработчикам модулей)

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

25
задан skaffman 20 June 2011 в 13:23
поделиться

2 ответа

Я понимаю, что ваш вопрос в основном сводится к Как я могу включить представления Facelets в JAR?

Вы можете сделать это, разместив пользовательский ResourceResolver в банке.

public class FaceletsResourceResolver extends ResourceResolver {

    private ResourceResolver parent;
    private String basePath;

    public FaceletsResourceResolver(ResourceResolver parent) {
        this.parent = parent;
        this.basePath = "/META-INF/resources"; // TODO: Make configureable?
    }

    @Override
    public URL resolveUrl(String path) {
        URL url = parent.resolveUrl(path); // Resolves from WAR.

        if (url == null) {
            url = getClass().getResource(basePath + path); // Resolves from JAR.
        }

        return url;
    }

}

Настройте это в веб-приложении web.xml следующим образом:

<context-param>
    <param-name>javax.faces.FACELETS_RESOURCE_RESOLVER</param-name>
    <param-value>com.example.FaceletsResourceResolver</param-value>
</context-param>

Представьте, что у вас есть /META-INF/resources/foo/bar.xhtml в random.jar, тогда вы можете просто включить его обычным способом

]
<ui:include src="/foo/bar.xhtml" />

или даже динамически

<ui:include src="#{bean.path}" />

Примечание: начиная с Servlet 3.0 и более новых версий JBoss / JSF 2.0, весь подход ResourceResolver не нужен, если вы храните файлы в /META-INF/resources папка. Вышеуказанное ResourceResolver является обязательным только в Servlet 2.5 или более ранних версиях JBoss / JSF, поскольку в них есть ошибки в разрешении ресурса META-INF.

См. Также:

33
ответ дан 28 November 2019 в 21:15
поделиться

Между прочим ... вы можете избежать реализации своего собственного распознавателя ресурсов, когда используете припой для шва (в настоящее время интегрируемый в apache deltaspike), который является действительно полезной библиотекой, дополняющей CDI (ваша типичная компонентная модель Java EE 6)

Я тоже экспериментировал с модульностью в приложениях jsf. По сути, я построил интерфейс шаблона с панелью инструментов, которая заполняется кнопками каждого модуля. Обычно вы делаете это, предоставляя список строк в виде именованного объекта:

@Produces
@SomethingScoped
@Named("topMenuItems")
public List<String> getTopMenuItems(){
return Arrays.asList("/button1.xhtml", "/button2.xhtml", "/button3.xhtml");
}

Обратите внимание на то, как каждая из кнопок может происходить из отдельного модуля приложения jsf. Интерфейс шаблона содержит панель, где

вы можете использовать ее в своей разметке следующим образом (на свой страх и риск;)):

....
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
....
<xy:toolbar>
  <xy:toolbarGroup>
    <c:forEach items="#{topMenuItems}" var="link">
      <ui:include src="#{link}" />
    </c:forEach>
  </xy:toolbarGroup>
</xy:toolbar>
<xy:panel>
  <ui:include src="#{contentPath}"/>
</xy:panel>

Это была панель инструментов и панель контента.

простое определение кнопки или вида может выглядеть следующим образом:

<ui:composition ...>
    <xy:commandButton actionListener="#{topMenuController.switchContent()}"
        value="Test" id="testbutton" />
</ui:composition>

позволяет назвать этот артефакт view1.xhtml

Когда эта кнопка нажата (которая не срабатывает обратная передача с использованием actionListener, мы хотим перезагрузить содержимое с помощью ajax) switchContentMethod в вашем контроллере может изменить строку, возвращаемую getContentPath:

public void switchContent(){
    contentPath = "/view1.xhtml";
}

@Produces
@SomethingScoped
@Named("contentPath")
public String getContentPath(){
    return contentPath;
}

теперь вы можете изменить представление, отображаемое на панели, с помощью кнопки в строке меню, которая дает вам навигацию без перезагрузки страницы.

Несколько советов (или «что я выучил»):

  1. Вы можете выбрать большую область действия для метода getTopMenuItems
  2. Дон ' Вложите тег: включите тег. К сожалению, это невозможно (например, ваш view1.xhtml не может включать другую композицию). Мне бы очень хотелось, чтобы что-то подобное было возможным, поскольку вы можете создавать действительно модульные представления jsf с помощью этого, вроде только портлетов без портлетов .. = D
  3. с помощью пользовательского интерфейса: включение в компоненты контейнера, такие как tabviews, также проблематично ,
  4. Как правило, не рекомендуется смешивать JSTL (c: forEach) и JSF. Тем не менее я обнаружил, что это единственный способ работать с пользовательским интерфейсом: повтор оценивается слишком поздно , например. Ваш включенный контент не появляется.
2
ответ дан 28 November 2019 в 21:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: