2

一種の CMS プロジェクトで JSF 2.1 と Primefaces を使用してページを動的に生成しようとしている問題に苦しんでいます。私の問題は、カスタム 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>

ビューの数は不明であり、動的に作成されるため、ui:includes の醜いブロックを作成して条件付きでレンダリングすることはできません。

したがって、私が見ているのは、これを行っているときに ajax ベースのフォーム (たとえば p:commandButton を使用) が機能していないことです。Bean で実行されたアクションが表示されません。しかし、「#{publicBean.view}」から返されるビューをハードコーディングすると、常に同じビューが返され、すべてが機能します。したがって、ajax 呼び出し中に publicBean.view がおそらく null を返すか、私の場合は AgoraConstants.CUSTOM_VIEW_NOT_FOUND を返すと想定しています。これが私のバッキング Bean のコードです。

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とprimefacesでこれを希望どおりに機能させるにはどうすればよいですか? セッションでそれをスローすることもできますが、ユーザーが異なるビューを持つ 2 つのタブでサイトを開くと、混乱して正しく機能しなくなる可能性があります。基本的に、getView() が ajax リクエストに対して同じビューを返すことを確認できるように、リクエスト変数を保持するにはどうすればよいですか? この問題には簡単な解決策があるはずですが、助けていただければ幸いです。

** 編集 **

また、バッキング Bean をビュー スコープ (リクエストから) に変更しようとしましたが、それは役に立たなかったようです (理由はわかりません)。以下は、バッキング Bean コードの詳細です。@PostConstruct で Bean が作成されたときに呼び出される init メソッドを追加しました。

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;
} 
4

2 に答える 2

0

この状況ではビュースコープのBeanを使用する必要がありますが、ビュースコープと動的ui:includeを使用する場合は問題があります。たとえば、コンストラクターにブレークポイントを設定するなど、テストできます。各リクエストでBeanが作成されていることがわかります。たとえばc:ifまたはc:forを使用している場合にも、問題が発生します。

于 2012-12-29T17:46:50.743 に答える
0

私の問題全体は、ポストバックに ajax リクエストのリクエスト パラメータが含まれていなかったためでした。そのため、prettyfaces を使用して問題を回避しようとしています。きれいな顔で、ポストバックにリクエストパラメーターを含めるようにマッピングをセットアップし、問題を解決しました。これはすべての状況で機能するとは限りませんが、私にとってはうまく機能しているようです。

于 2012-12-30T14:25:41.550 に答える