2010-12-29 11 views
0

私のプログラムにBeanを動的にロードする際に問題があります。私はこのような私のfaceletテンプレートを持っています:JSF BeanをFaceletテンプレートに動的にロードする

<ui:define name="content"> 
     <f:loadBundle var="Application" basename="start" /> 
     <f:loadBundle var="Messages" basename="#{ApplicationController.bundleName}" /> 
     <h:panelGroup rendered="#{ApplicationController.chosenBean.hasAccess}"> 
      <h:form> 
       <h:outputText value="Error: #{ApplicationController.chosenBean.errorMessage}" id="outputErrorMessage2" /><br /> 
        <h:outputText value="Report running: #{ApplicationController.chosenBean.runningReport}" /><br /> 
        <ui:insert name="application-content" /> 
        <h:commandButton action="#{ApplicationController.chosenBean.actionRunReport}" value="Create report"/> 
       </h:form> 
      </h:panelGroup> 
      <h:panelGroup rendered="#{!ApplicationController.chosenBean.hasAccess}"> 
      <h:outputText value="Err" /> 
     </h:panelGroup> 
</ui:define> 

私はApplicationControllerが使いたいJavabeanを決定したいと思っています。これは、次のコードで行われます。

ApplicationController.java 
public ReportWeb getChosenBean() { 
    String reportName = getReportNameFromServletPath(); 
    //Make first character upper case 
    String beanName = reportName.substring(0, 1).toUpperCase() + reportName.substring(1); 
    logger.log(Level.INFO, "Loading bean with name : {0}", BEAN_PACKET_NAME + beanName); 
    try { 
     if (Class.forName(BEAN_PACKET_NAME + beanName).newInstance() instanceof ReportWeb) { 
      chosenBean = (ReportWeb) Class.forName(BEAN_PACKET_NAME + beanName).newInstance(); 
     } 
    } catch (ClassNotFoundException ex) { 
     Logger.getLogger(ApplicationController.class.getName()).log(Level.SEVERE, null, ex); 
    } catch (InstantiationException ex) { 
     Logger.getLogger(ApplicationController.class.getName()).log(Level.SEVERE, null, ex); 
    } catch (IllegalAccessException ex) { 
     Logger.getLogger(ApplicationController.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    return chosenBean; 
} 

すべての私のJavaBeansは、アクセスロジックと他の便利なメソッドを含む抽象クラスですReportWebクラスをサブクラス化。最も重要な方法は、

public abstract String actionRunReport(); 

です。すべてのレポートでこれを実装しています。

<h:commandButton action="#{ApplicationController.chosenBean.actionRunReport}" value="Create report"/> 

は、私は何のエラーメッセージを受け取るていないが、それだけでは動作しません。しかし、私のテンプレートで、私はこれを行うことによって、このメソッドを呼び出すことはできません。

<h:commandButton action="#{AntallHenvendelser.actionRunReport}" value="Create report"/> 

なぜ私の技術がうまくいかないのですか?

EDIT: このメソッドは、動的にBeanをロードするアクションボタンから呼び出されることはありません。

+1

問題の原因はわかりませんが、ELによるすべてのgetter呼び出しが**別の**インスタンスのBeanを返し、JSFによって管理されているものでもないことを認識していますか?これは非効率的な衝撃的なことです...問題のトラブルシューティングに関して、どのように「うまくいかない」と結論づけましたか?とにかく 'actionRunReport()'メソッドは呼び出されていますか? – BalusC

+0

ありがとうございますBalusC。私はこの方法が非効率的であることを知らなかった。あなたは、マネージドBeanをどのように受け取ることができるかについての推奨事項はありますか?すべての私の豆は要求範囲にありますが、それでも私はあなたのポイントを得る:) –

+0

私は答えを掲載しました。ちなみに、 '@ nickname'を使って、自分以外の投稿のコメント返信について他の人に通知します。 http://meta.stackexchange.com/questions/43019/how-do-comment-replies-workを参照してください。そうでなければ、ポストを振り返る気にかかっています。 – BalusC

答えて

1

アクションコンポーネント(または少なくとも1つの親)のrendered属性がフォーム送信の要求中にfalseと評価されたため、原因が考えられます。この方法では、アクションは呼び出されません。フォーム提出の要求が処理される間に、rendered属性がfalseを評価しないようにする必要があります。

また、呼び出されないアクションコンポーネントの考えられる原因の概要については、this answerも参照してください。


これまでの方法は、これまでのところ説明したように、単純に非効率的です。これは缶(

public class ApplicationController { 

    private ReportWeb chosenBean; 

    public ApplicationController() { 
     chosenBean = findBean(getReportNameFromServletPath(), ReportWeb.class); 
    } 

    public static <T> T findBean(String managedBeanName, Class<T> beanClass) { 
     FacesContext context = FacesContext.getCurrentInstance(); 
     return beanClass.cast(context.getApplication().evaluateExpressionGet(context, "#{" + managedBeanName + "}", beanClass); 
    } 

    // ... 
} 

ではなくゲッターを呼び出している EL式あたり少なくとも一度の要求ごとに一度だけロードされ、この方法は:私はApplicationController要求がスコープにすると次のように選択したBeanをロードしたいですrendered属性の中で使用された場合、少なくとも2倍になります)。

この方法では、実際にゲッターの中に手動で(2回!)作成するのではなく、実際にというJSFによって管理されるbeanをつかんでいます。 JSFがすでにインスタンスを作成している場合は、このインスタンスが返されます。 JSFがまだ作成していない場合は、新しいものが作成され、返される前にスコープに入れられます。

+0

これはうまくいきました!あなたのメソッドはFacesContextを通じてBeanをロードするので、Beanを通じてアクションを実行することもできます!この作業を行うために自分のプログラムで行った唯一の変更は、.newInstance()の代わりにfindBeanメソッドを採用することでした。 ありがとうございます! –

関連する問題