サーブレット関連クラスのJSF管理Beanを名前で取得します


101

@ManagedBeans名前で参照するカスタムサーブレット(AJAX / JSON用)を記述しようとしています。私はマッピングしたいと思っています:

http://host/app/myBean/myProperty

に:

@ManagedBean(name="myBean")
public class MyBean {
    public String getMyProperty();
}

通常のサーブレットから名前でBeanをロードすることは可能ですか?私が使用できるJSFサーブレットまたはヘルパーはありますか?

私はこれがすべて明白すぎる春に甘やかされているようです。


これらの新しいアノテーションをJSF / ELの外部で使用できるかどうかはわかりませんが
McDowell

同様の問題で問題が発生している他の人も、bpcatalog.dev.java.net / ajax / jsf-ajaxを確認できます(AJAXに関連し、マッピング/処理を要求し、名前でBeanを取得しない)
Konrad Garus

回答:


263

サーブレットベースのアーティファクトなどでは@WebServlet@WebFilter@WebListener、あなたは「プレーン・バニラ」JSFをつかむことができる@ManagedBean @RequestScopedことで:

Bean bean = (Bean) request.getAttribute("beanName");

そして@ManagedBean @SessionScoped

Bean bean = (Bean) request.getSession().getAttribute("beanName");

そして@ManagedBean @ApplicationScoped

Bean bean = (Bean) getServletContext().getAttribute("beanName");

これには、BeanがJSFによって事前に自動作成されている必要があることに注意してください。それ以外の場合は戻りnullます。次に、手動でBeanを作成して使用する必要がありますsetAttribute("beanName", bean)


@NamedJSF 2.3が非推奨になって以来、CDIの代わりにCDIを使用できる場合@ManagedBean、特にBeanを手動で作成する必要がなくなるため、さらに簡単になります。

@Inject
private Bean bean;

これは仕事、あなたが使用しているではないことに注意してください@Named @ViewScopedBeanが唯一のJSFビュー状態で識別することができますので、いつにのみ利用可能ですFacesServlet呼び出されました。したがって、その前に実行されるフィルターでは、@Injected にアクセスする@ViewScopedと常にがスローされContextNotActiveExceptionます。


あなたが中@ManagedBeanにいるときだけ、あなたは使うことができます@ManagedProperty

@ManagedProperty("#{bean}")
private Bean bean;

これは、@Namedまたは@WebServletその他のアーティファクト内では機能しないことに注意してください。それは本当に内部で@ManagedBeanのみ機能します。


の中にいなくても@ManagedBean、がFacesContextすぐに利用できる(つまり、FacesContext#getCurrentInstance()が返されないnull)場合は、次も使用できますApplication#evaluateExpressionGet()

FacesContext context = FacesContext.getCurrentInstance();
Bean bean = context.getApplication().evaluateExpressionGet(context, "#{beanName}", Bean.class);

これは次のように便利です。

@SuppressWarnings("unchecked")
public static <T> T findBean(String beanName) {
    FacesContext context = FacesContext.getCurrentInstance();
    return (T) context.getApplication().evaluateExpressionGet(context, "#{" + beanName + "}", Object.class);
}

次のように使用できます。

Bean bean = findBean("bean");

以下も参照してください。


9
豆を注入することについての2番目の提案は、私が完全に見落としていた驚くほど簡単でした。いつものように、あなたの応答は完全に要点です。SOでの作業に感謝します。
jnt30

2
それまでの間(JSF 2.2以降)、evaluateExpressionGetメソッドが、予想されるクラスを指定できるようにする3番目のパラメーターで拡張されたため、キャストが不要になったようです。 PostBean bean = context.getApplication().evaluateExpressionGet(context, "#{beanName}", PostBean.class);
Marc Juchli 2014年

1
@Marc:最初から入っています。コピーペーストの間違いからの残り物だったと思います。回答が修正されました。お知らせありがとうございます。
BalusC 2014年

FacesContextstaticユーティリティメソッドfindBean()がプレーンJavaクラス内で定義されている場合でも使用できます。JSFによって管理されていないプレーンJavaクラスでどのように利用できますか?
小型

1
@Tiny:同じスレッド内のJSFアーティファクトによって呼び出されます。
BalusC、2015

11

次の方法を使用します。

public static <T> T getBean(final String beanName, final Class<T> clazz) {
    ELContext elContext = FacesContext.getCurrentInstance().getELContext();
    return (T) FacesContext.getCurrentInstance().getApplication().getELResolver().getValue(elContext, null, beanName);
}

これにより、返されたオブジェクトを型付きの方法で取得できます。


3
これは、現在受け入れられている回答ですでにカバーされており、さらに便利な方法でさえカバーされていClassます(つまり、この構成では引数は不要です)。
BalusC、

3

このリンクのようなアプローチを試しましたか?createValueBinding()まだ利用可能かどうかはわかりませんが、このようなコードには、古い古いサーブレットからアクセスできます。これは、Beanがすでに存在している必要があります。

http://www.coderanch.com/t/211706/JSF/java/access-managed-bean-JSF-from

 FacesContext context = FacesContext.getCurrentInstance();  
 Application app = context.getApplication();
 // May be deprecated
 ValueBinding binding = app.createValueBinding("#{" + expr + "}"); 
 Object value = binding.getValue(context);

これはおそらく通常のサーブレットでは機能しません。FacesContextは、JSFライフサイクル(通常はFacesServlet)によって設定されるリクエストごとのスレッドローカルアーティファクトです。
McDowell

7
ValueBindingは、JSF 1.2以降4年以上前に廃止されました。
BalusC 2010

@BalusC:それは私がどれだけ最新であるかを示しています笑。余談ですが、検索エンジンを使用して手法を研究することは、そこにあるすべての古い情報に対して逆効果であることが判明しています。@McDowell:それは実際に理にかなっています。何が起こるかを確認するためだけにテストを行います。
James P.

3

名前を渡すことで、管理対象Beanを取得できます。

public static Object getBean(String beanName){
    Object bean = null;
    FacesContext fc = FacesContext.getCurrentInstance();
    if(fc!=null){
         ELContext elContext = fc.getELContext();
         bean = elContext.getELResolver().getValue(elContext, null, beanName);
    }

    return bean;
}

サーブレットからこれを実行しようとしましたが、機能しません。
Fernando Pie

0

同じ要件がありました。

以下の方法で取得しました。

セッションスコープのBeanがありました。

@ManagedBean(name="mb")
@SessionScopedpublic 
class ManagedBean {
     --------
}

以下のコードをサーブレットのdoPost()メソッドで使用しました。

ManagedBean mb = (ManagedBean) request.getSession().getAttribute("mb");

それは私の問題を解決しました。


どのようなサーブレットを使用していますか?メイト
フェルナンドパイ

1
HttpServletです。
Anil、2016

-1

私はこれを使います:

public static <T> T getBean(Class<T> clazz) {
    try {
        String beanName = getBeanName(clazz);
        FacesContext facesContext = FacesContext.getCurrentInstance();
        return facesContext.getApplication().evaluateExpressionGet(facesContext, "#{" + beanName + "}", clazz);
    //return facesContext.getApplication().getELResolver().getValue(facesContext.getELContext(), null, nomeBean);
    } catch (Exception ex) {
        return null;
    }
}

public static <T> String getBeanName(Class<T> clazz) {
    ManagedBean managedBean = clazz.getAnnotation(ManagedBean.class);
    String beanName = managedBean.name();

    if (StringHelper.isNullOrEmpty(beanName)) {
        beanName = clazz.getSimpleName();
        beanName = Character.toLowerCase(beanName.charAt(0)) + beanName.substring(1);
    }

    return beanName;
}

そして、次を呼び出します:

MyManageBean bean = getBean(MyManageBean.class);

このようにして、コードをリファクタリングし、使用状況を問題なく追跡できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.