1

スクリーンショットでわかるように、プロパティ「member.city」でJSF の暗黙的な値の検証エラーが発生しています。目的は、 ajax を使用して、前の国選択メニューで国を選択した後、都市選択ワン メニューに入力することです。これは、selectOneMenu 変更リスナーajaxを使用して、都市のリストを表示するコンポーネントを更新することによって実現されます。ただし、検証エラーが発生し、フォームが送信されません。

検証エラーのスクリーンショット

(hascode および equals メソッド) の有無にかかわらずエンティティを試してみましたが、無駄でした。分離された Managed Bean ViewScopedを使用して、フィルター処理されたリストを取得しましたが、無駄でした。**

<f:selectItems value="#{cityBean.citiesByCountry}" />フィルター処理された都市のリストを、すべての都市を取得するリストに置き換えると (xhtml フォームで に置き換え<f:selectItems value="#{cityBean.all}" />ます)、検証エラーは発生せず、フォームは正常に送信されます。

** コードは次のとおりです。

形:

<p:outputLabel for="country" value="#{i18n.country}" />
                    <p:selectOneMenu valueChangeListener="#{cityBean.selectCountry}" rendered="true" id="country" value="#{newMember.country}" converter="#{countryBean.converter}" 
                        style="width:160px;text-align:left;border:thin solid gray;"
                        required="true" requiredMessage="#{i18n.required}">                     
                        <f:selectItems value="#{countryBean.all}" var="countryname" itemLabel="#{countryname.name}"/>
                        <p:ajax event="change" update="city" />
                    </p:selectOneMenu>
                    <p:message for="country" />

                    <p:outputLabel for="city" value="#{i18n.city}" />
                    <p:selectOneMenu rendered="true" id="city" value="#{newMember.city}" converter="#{cityBean.converter}" converterMessage="Conversion error!"
                        style="width:160px;text-align:left;border:thin solid gray;"
                        required="true" requiredMessage="#{i18n.required}">                                         
                        <f:selectItems value="#{cityBean.citiesByCountry}" var="cityname" itemLabel="#{cityname.cityname}"/>                        
                    </p:selectOneMenu>
                    <p:message for="city" />

市長:

@XmlRootElement
@Entity
@Table(name = "city", schema = "public")
@NamedQueries({
        @NamedQuery(name = "City.findAll", query = "SELECT c FROM City c"),
        @NamedQuery(name = "City.findById", query = "SELECT c FROM City c WHERE c.id = :id"),
        @NamedQuery(name = "City.findByCountry", query = "SELECT c FROM City c WHERE c.country = :country"),
        @NamedQuery(name = "City.findByCountryOrderedByName", query = "SELECT c FROM City c WHERE c.country = :country ORDER BY c.cityname ASC") })
@NamedNativeQueries({ @NamedNativeQuery(name = "City.findCountryNativeSQL", query = "select * from city c where c.countrybeta = :country.betacode", resultClass = City.class) })
public class City implements java.io.Serializable {

    private static final long serialVersionUID = 3364735938266980295L;
    private int id;
    private Integer version;
    private Country country;
    private String cityname;
    private String district;
    private int population;
    private Set<Member> members = new HashSet<Member>(0);

    public City() {
    }
// ...remainder of entity code (contructors and fields..)

豆:

@Named
@Stateful
@ConversationScoped
public class CityBean implements Serializable {

    private static final long serialVersionUID = 1L;
    private City city;
    private List<City> cityList;

    public City getCity() {
        return this.city;
    }

    private Country selectedCountry;

    @Inject
    private Conversation conversation;

    @PersistenceContext(type = PersistenceContextType.EXTENDED)
    private EntityManager entityManager;
// remainder of code....

// The List that works fine with Select one Menu
public List<City> getAll() {

        CriteriaQuery<City> criteria = this.entityManager.getCriteriaBuilder()
                .createQuery(City.class);
        return this.entityManager.createQuery(
                criteria.select(criteria.from(City.class))).getResultList();
    }

    @PostConstruct
    public void init() {
        setCityList(getCitiesByCountry());
    }

    public List<City> getCityList() {
        return cityList;
    }

    public void setCityList(List<City> cityList) {
        this.cityList = cityList;
    }

    /**
     * The List That triggers a jsf value validation error
     * @return List of Cities by Country ordered by city name
     */
    public List<City> getCitiesByCountry() {
        TypedQuery<City> query = this.entityManager.createNamedQuery(
                "City.findByCountryOrderedByName", City.class);
        query.setParameter("country", selectedCountry);
        return query.getResultList();
    }

    // The Select One Menu Listener
    public void selectCountry(ValueChangeEvent event) {

        if (event != null) {
            selectedCountry = (Country) event.getNewValue();
        }
        }

        // getters and setters....

ENV: - JSF 21 - 休止状態 - JBoss AS 7.1 - PrimeFaces 3.5 - Linux 3.5 / Firefox 18.0.2

4

1 に答える 1

4

会話を開始していないため、具体的な問題が発生している@PostConstructため、Bean はスコープ指定されたリクエストのように動作します。このように、都市のリストは、フォーム送信の処理中に非互換的に変更され、空になります (したがって、選択されたアイテムが利用可能なアイテムのリストに見つからなかったため、この検証エラーが発生します)。

で会話を開始する必要があり@PostConstructます。

conversation.begin();

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


具体的な問題とvalueChangeListenerは関係ありませんが、ゲッター メソッドでビジネス ロジックを使用して実行することは、間違ったアプローチです。ゲッター メソッドでビジネス ロジックを実行するべきではありません。これは明らかに非効率的です。それらは、すでに準備された Bean プロパティのみを返す必要があります。

ロジックを次のように書き換えます。

<p:selectOneMenu value="#{bean.country}" ...>
    <f:selectItems value="#{bean.countries}" />
    <p:ajax listener="#{bean.updateCities}" update="city" />
</p:selectOneMenu>

<p:selectOneMenu id="city" value="#{bean.city}" ...>                                         
    <f:selectItems value="#{bean.cities}" />
</p:selectOneMenu>

private Country country;
private List<Country> countries;
private City city;
private List<City> cities;

@PostConstruct
public void init() {
    countries = service.listCountries();

public void updateCities() {
    cities = service.listCities(country);
}

// Add/generate normal!! getters/setters.

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

于 2013-02-15T16:56:47.797 に答える