1

私はJSF(Mojarra 2.2およびGlassfish 4)から始めて、現在、クライアントとその注文をDBに保存するWebアプリケーションで練習しています。

新しい Order を作成するとき、JSF から既存のクライアントを選択できる機能が 1 つあります<h:selectOneMenu>。Order エンティティは、他の属性の中で Client エンティティを格納します...

<h:selectOneMenu>DB から a を事前設定することに関する BalusC の優れた回答( here ) に従い、熱心な ApplicationScoped ManagedBean に格納されているデータから自分のデータを正常に設定しましたが、バッキング Bean で選択した項目を複雑なオブジェクトとして取得することはできません。常にヌルです。

これは私を怒らせています。あなたの助けが本当に感謝されます! 関連するコード スニペットは次のとおりです。

@ManagedBean(eager = true)
@ApplicationScoped
public class Data implements Serializable {

    private static final long serialVersionUID = 1L;

    @EJB
    private ClientDao clientDao;

    private List<Client> clients;

    @PostConstruct
    private void init() {
        clients = clientDao.lister();
    }

    public List<Client> getClients() {
        return clients;
    }

}

注文作成 Bean (注:「コマンド」は注文を意味します;)

@ManagedBean
@RequestScoped
public class CreerCommandeBean implements Serializable {
    private static final long serialVersionUID = 1L;
    private Commande commande;

    private String choixNouveauClient = "nouveauClient";

    @EJB
    private CommandeDao commandeDao;

    public CreerCommandeBean() {
        commande = new Commande();
    }

    public void inscrire() {

        System.out.println("client : " + commande.getClient()); // prints **NULL**
            // ... orderService to store in DB
    }
... getters and setters

クライアント コンバーター:

@FacesConverter(value = "clientConverter", forClass = Client.class)
public class ClientConverter implements Converter {

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (value == null) {
            return null;
        }

        Data data = context.getApplication().evaluateExpressionGet(context, "#{data}", Data.class);
        for (Client c : data.getClients()) {
            if (c.getId().toString().equals(value)) {
                return c;
            }
        }
        throw new ConverterException(new FacesMessage(String.format("Cannot convert %s to Client", value)));
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        return (value instanceof Client) ? String.valueOf(((Client) value).getId()) : null;
    }
}

Facelet の抜粋:

<p:outputPanel id="gridContainerAncienClient">
            <p:selectOneMenu value="#{creerCommandeBean.commande.client}"
                rendered="#{creerCommandeBean.choixNouveauClient == 'ancienClient'}">
                <f:converter converterId="clientConverter" />
                <f:selectItems value="#{data.clients}" var="cli"
                    itemValue="#{cli}" itemLabel="#{cli.prenom} #{cli.nom}" />
            </p:selectOneMenu>
        </p:outputPanel>
4

2 に答える 2

1

CreerCommandeBeanです@RequestScoped。つまり、1 つの要求に対してのみ存続します。
割り当てられるクライアントを選択するときは#{creerCommandeBean.commande.client}、リクエストによってこれを行います。#{creerCommandeBean.commande.client}が選択されたクライアントになりました。その後、リクエストは終了し、Bean は破棄され、「変更」は失われます。
そのデータを取得しようとするときは、もう一度要求によってそれを行います。 の新しいインスタンスが作成され、コンストラクターはプロパティに の新しいインスタンスをCreerCommandeBean割り当てます。そのプロパティはおそらくです。 commandeCommandeclientnull

解決策:
より広い範囲を使用してください。たとえば@ViewScoped、同じビューにとどまっている限り、Bean を「ライブ」にします。リクエストの数に関係ありません。

ヒント: BalusC の投稿Communication is JSF 2.0 を読んでください。JSF 2.2 では一部が若干異なる場合がありますが、それでも優れた包括的な紹介です。

于 2013-10-19T23:02:47.267 に答える
0

オブジェクトに equals() および hashCode() メソッドを実装するのを忘れていたことに気付きました。この場合のクライアント クラス。

BalusC のブログの説明をスキップしたことは自分のせいです。

Object#equals()「...実装に注意してください。これはJSFにとって非常に重要です。変換後、選択されたアイテムをリスト内のアイテムと比較します。requireObject#equals()もそうであるようObject#hashCode()に、これも実装されています....」

于 2014-04-29T15:31:32.497 に答える