JSF <ui: include /> где src является динамическим и простые
Я борюсь с проблемой, когда я пытаюсь динамически генерировать страницы, используя JSF 2.1 и Primefaces для своего рода проекта CMS. Моя проблема заключается в том, что я пытаюсь динамически включить страницу, которая находится в базе данных, с помощью пользовательского ResourceResolver (эта часть прекрасно работает). Проблема в том, что я использую параметр запроса, чтобы определить, какую страницу обслуживать (например: http://xxx.xxx.com/context/public/?p=2). Это работает нормально, пока я не захочу использовать Ajax или, более конкретно, Primefaces (в моем случае компонент расписания, где мне нужно использовать actionListeners). Я обнаружил, что мое представление не разрешается при выполнении запроса AJAX, вероятно, из-за того, что это область действия запроса. Ниже немного кода:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:composition template="/WEB-INF/view/public/templates/public-template.xhtml">
<ui:define name="body">
<p:outputPanel autoUpdate="false" rendered="#{empty publicBean.site}">
<div>No site found!</div>
</p:outputPanel>
<p:outputPanel autoUpdate="false" rendered="#{! empty publicBean.page and empty publicBean.page.pageTemplate}">
<div>No valid page template found!</div>
</p:outputPanel>
<ui:include src="#{publicBean.view}" />
</ui:define>
</ui:composition>
</html>
Количество представлений неизвестно и создается динамически, поэтому я не могу просто сделать некрасивый блок пользовательского интерфейса: затем включает и условно отображает.
Поэтому я вижу, что мои формы на основе ajax (например, с использованием p: commandButton) не работают, когда я делаю это. Я никогда не вижу действия, выполняемые на моих бобах. Но если я жестко закодирую представление, возвращаемое из "#{publicBean.view}", чтобы оно всегда возвращало одно и то же представление, все работает. Поэтому я предполагаю, что во время вызова ajax publicBean.view, вероятно, возвращает ноль или в моем случае AgoraConstants.CUSTOM_VIEW_NOT_FOUND. Вот код в моем бобе поддержки:
public String getView()
{
// If this below is uncommented, the form with ajax/primefaces works
//if ( 1 == 1 )
//{
// return "/X-AGORA-VIEW/districtOfficeCalendarTemplate.xhtml";
//}
if ( page != null && page.getPageTemplate() != null )
{
return AgoraConstants.CUSTOM_VIEW_PREFIX + page.getPageTemplate().getName() + ".xhtml";
}
else if ( site != null && site.getLandingPage() != null && site.getLandingPage().getPageTemplate() != null )
{
return AgoraConstants.CUSTOM_VIEW_PREFIX + site.getLandingPage().getPageTemplate().getName()+".xhtml";
}
return AgoraConstants.CUSTOM_VIEW_NOT_FOUND;
}
Итак, вот мой вопрос, как я могу сохранить параметр запроса, чтобы я мог работать так, как я хочу, с ajax и простыми лицами? Я мог бы бросить это в сеансе, но тогда, если пользователь открывает сайт в двух вкладках с различными представлениями, вещи могут запутаться и работать неправильно. По сути, как я должен хранить переменные запросов, чтобы я мог убедиться, что getView() возвращает то же самое представление для запросов ajax? Кажется, что должно быть простое решение этой проблемы, но я не вижу никакой помощи, которая будет принята с благодарностью.
** Редактировать **
Я также попытался изменить свой поддерживающий компонент для просмотра области (из запроса), но это, похоже, не помогло (но я не знаю почему). Ниже приведен более подробный код компонента. Я добавил метод init, который вызывается при создании компонента с помощью @PostConstruct.
public void init()
{
site = null;
page = null;
logger.info("Loading public view...");
if ( getFacesContext().getExternalContext().getRequestParameterMap().containsKey(AgoraConstants.PUBLIC_PAGE_REQUEST_VAR) )
{
logger.info("Restoring Page...");
long value = parseLong((String)getFacesContext().getExternalContext().getRequestParameterMap().get(AgoraConstants.PUBLIC_PAGE_REQUEST_VAR));
if ( value >= 0 )
{
logger.info("Attempting to restore: {}", value);
try
{
page = pageService.getItem(value);
if ( page != null )
{
if ( ! page.isEnabled() )
{
page = null;
}
}
}
catch(Exception e)
{
logger.warn("Failed to load site: {}", e.getLocalizedMessage());
}
}
}
if ( page == null && getFacesContext().getExternalContext().getRequestParameterMap().containsKey(AgoraConstants.PUBLIC_SITE_REQUEST_VAR) )
{
logger.info("Restoring Site...");
long value = parseLong((String)getFacesContext().getExternalContext().getRequestParameterMap().get(AgoraConstants.PUBLIC_SITE_REQUEST_VAR));
if ( value >= 0 )
{
logger.info("Attempting to restore: {}", value);
try
{
site = siteService.getItem(value);
}
catch(Exception e)
{
logger.warn("Failed to load site: {}", e.getLocalizedMessage());
}
}
}
if ( page != null && page.getSite() != null)
{
site = page.getSite();
}
if ( site == null )
{
site = siteService.getDefaultSite();
}
}
public String getView()
{
// if ( 1 == 1 )
// {
// return "/X-AGORA-VIEW/districtOfficeCalendarTemplate.xhtml";
// }
if ( page != null && page.getPageTemplate() != null )
{
logger.info("a" + AgoraConstants.CUSTOM_VIEW_PREFIX + page.getPageTemplate().getName() + ".xhtml");
return AgoraConstants.CUSTOM_VIEW_PREFIX + page.getPageTemplate().getName() + ".xhtml";
}
else if ( site != null && site.getLandingPage() != null && site.getLandingPage().getPageTemplate() != null )
{
logger.info("b" + AgoraConstants.CUSTOM_VIEW_PREFIX + site.getLandingPage().getPageTemplate().getName()+".xhtml");
return AgoraConstants.CUSTOM_VIEW_PREFIX + site.getLandingPage().getPageTemplate().getName()+".xhtml";
}
logger.info("c");
return AgoraConstants.CUSTOM_VIEW_NOT_FOUND;
}
2 ответа
В общем, моя проблема заключалась в том, что постбэк не включал параметры запроса для запросов ajax, поэтому я работаю над этой проблемой, используя симпатичные лица. С красивыми лицами я настроил отображение, чтобы включить параметры запроса на post-back, и это решило мою проблему. Это может не сработать для каждой ситуации, но, похоже, мне это подходит.
В этой ситуации вы должны использовать bean-объект области видимости, но есть проблема при использовании области видимости и динамического интерфейса:include. Вы можете проверить это, например, поставить точку останова в вашем конструкторе, и вы увидите, что bean-компонент создается в каждом запросе. Проблема также существует, если вы используете, например, c:if или c:for.