1

テストのために rich:pickList を selectManyListbox に置き換えました。値をサーバーに送信すると、「検証エラー: 値が無効です」というエラーが表示されます。StaffConverter (getAsobject) をデバッグするブレークポイントも設定しましたが、システムはそれを呼び出しません。私のコンバーターが呼び出されなかった理由をいくつか教えてください。これを修正する方法を提案してください。ありがとう

xhtml ファイル:

<h:selectManyListbox value="#{reportController.selectedStaffList}" converter="staffConverter">
   <f:selectItems value="#{reportController.staffList}" 
                  var="item" itemValue="#{item}" itemLabel="#{item.name}" />
</h:selectManyListbox>

<rich:pickList value="#{reportController.selectedStaffList}" converter="staffConverter" sourceCaption="Available flight" targetCaption="Selected flight" listWidth="195px" listHeight="100px" orderable="true">
   <f:selectItems value="#{reportController.staffList}" var="item" itemValue="#{item}" itemLabel="#{item.name}" />
</rich:pickList>

私のコンバーター:

@FacesConverter(forClass = Staff.class)
public static class StaffConverter implements Converter {

    public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
        if (value == null || value.length() == 0) {
            return null;
        }
        StaffController controller = StaffController.getInstance();
        return controller.facade.find(Staff.class, getKey(value));
    }

    java.lang.Integer getKey(String value) {
        java.lang.Integer key;
        key = Integer.valueOf(value);
        return key;
    }

    String getStringKey(java.lang.Integer value) {
        StringBuffer sb = new StringBuffer();
        sb.append(value);
        return sb.toString();
    }

    public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
        if (object == null) {
            return null;
        }
        if (object instanceof Staff) {
            Staff o = (Staff) object;
            return getStringKey(o.getStaffCode());
        } else {
            throw new IllegalArgumentException("object " + object + " is of type " + object.getClass().getName()
                    + "; expected type: " + StaffController.class.getName());
        }
    }
}

Staff に equals メソッドを実装しました。

@Override
public boolean equals(Object object) {
    if (!(object instanceof Staff)) {
        return false;
    }
    Staff other = (Staff) object;
    return (this.staffCode == other.staffCode);
}
4

2 に答える 2

2

私のように、Googleやstackoverflowで開発の問題の解決策を探すのが好きな人のために、どこかに投稿するだけです...

コンバーターで使用していた pojo の種類に応じて、この問題が何度か発生しました... 最後に、洗練された解決策を見つけたと思います。私の場合、DTO レイヤーを保存したかったので、JPA エンティティ クラスを直接使用します。まあ、いくつかのエンティティでは rich:pickList が機能しましたが、他のエンティティでは機能しませんでした... equals メソッドまで追跡しました。たとえば、以下の例では、userGroupConverter Bean では機能しませんでした。

私の解決策は、単純に equals メソッドをインラインで上書きすることです。そのため、エンティティ (私はしばしばロンボクを使用します) からのものは変更されず、まったく変更する必要はありません! したがって、以下のコンバーターでは、名前フィールドのみを等号で比較します。

xhtml:

    <rich:pickList id="pickListUserGroupSelection"
        value="#{usersBean.selectedUserGroups}" switchByDblClick="true"
        sourceCaption="Available user groups" targetCaption="Groups assigned to user"
        listWidth="365px" listHeight="100px" orderable="false"
        converter="#{userGroupConverter}"
        disabled="#{!rich:isUserInRole('USERS_MAINTAIN')}">

        <f:validateRequired disabled="true" />
        <rich:validator disabled="true" />

        <f:selectItems value="#{usersBean.userGroups}" var="userGroup"
            itemValue="#{userGroup}"
            itemLabel="#{userGroup.name}" />

        <f:selectItems value="#{usersBean.selectedUserGroups}" var="userGroup"
            itemValue="#{userGroup}"
            itemLabel="#{userGroup.name}" />

    </rich:pickList>
    <rich:message for="pickListUserGroupSelection" />

コンバータ:

package ...;

import ...

/**
 * JSF UserGroup converter.<br>
 * Description:<br>
 * JSF UserGroup converter for rich:pickList elements.<br>
 * <br>
 * Copyright: Copyright (c) 2014<br>
 */
@Named
@Slf4j
@RequestScoped // must be request scoped, as it can change every time!
public class UserGroupConverter implements Converter, Serializable {

    /**
     *
     */
    private static final long serialVersionUID = 9057357226886146751L;

    @Getter
    Map<String, UserGroup> groupMap;

    @Inject
    MessageUtil messageUtil;

    @Inject
    UserGroupDao userGroupDao;

    @PostConstruct
    public void postConstruct() {

        groupMap = new HashMap<>();

        List<UserGroup> userGroups;
        try {
            userGroups = userGroupDao.findAll(new String[] {UserGroup.FIELD_USER_ROLE_NAMES});

            if(userGroups != null) {

                for (UserGroup userGroup : userGroups) {

                    // 20150713: for some reason the UserGroup entity's equals method is not sufficient here and causes a JSF validation error
                    // "Validation Error: Value is not valid". I tried this overridden equals method and now it works fine :-)
                    @SuppressWarnings("serial")
                    UserGroup newGroup = new UserGroup() {

                        @Override
                        public boolean equals(Object obj){
                            if (!(obj instanceof UserGroup)){
                                return false;
                            }

                            return (getName() != null)
                                 ? getName().equals(((UserGroup) obj).getName())
                                 : (obj == this);
                        }
                    };
                    newGroup.setName(userGroup.getName());

                    groupMap.put(newGroup.getName(), newGroup);
                }
            }

        } catch (DaoException e) {

            log.error(e.getMessage(), e);

            FacesContext fc = FacesContext.getCurrentInstance();
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Error initializing user group converter!", null);
            fc.addMessage(null, message);
        }
    }

    /*
     * (non-Javadoc)
     * @see javax.faces.convert.Converter#getAsObject(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.String)
     */
    @Override
    public UserGroup getAsObject(FacesContext context, UIComponent component,
            String value) {

        UserGroup ug = null;

        try {

            ug = getGroupMap().get(value);
        } catch (Exception e) {

            log.error(e.getMessage(), e);

            FacesContext fc = FacesContext.getCurrentInstance();
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Error converting user group!", null);
            fc.addMessage(null, message);
        }

        return ug;
    }

    /*
     * (non-Javadoc)
     * @see javax.faces.convert.Converter#getAsString(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.Object)
     */
    @Override
    public String getAsString(FacesContext context, UIComponent component,
            Object value) {

        String name = ((UserGroup) value).getName();

        return name;
    }

}

楽しんでください!

于 2015-07-13T11:03:27.700 に答える
0

Brian と BalusC の助けに感謝します。selectManyListbox & rich:picklist 内に名前付きコンバーターを追加して問題を解決し、うまく動作するようにしました。ただし、通常は @FacesConverter(forClass = Staff.class) のみを使用し、jsf に名前付きコンバーターを追加する必要がないため、selectManyListbox と rich:picklist を除いて正常に動作します。

于 2012-10-17T02:53:58.173 に答える