سؤال

أريد استخدام قيم التعداد في <h:selectManyCheckbox>. ومع ذلك ، يتم ملء مربعات الاختيار بشكل صحيح ، عند تحديد بعض القيم وتقديمها ، نوع وقت التشغيل الخاص بها String, وليس التعداد. رمز بلدي:

<h:selectManyCheckbox value="#{userController.roles}" layout="pageDirection">
     <f:selectItems value="#{userController.rolesSelectMany}" />
</h:selectManyCheckbox>

فئة UserController (SecurityRole نوع التعداد):

public SelectItem[] getRolesSelectMany() {
    SelectItem[] items = new SelectItem[SecurityRole.values().length];

    int i = 0;
    for (SecurityRole role : SecurityRole.values()) {
        items[i++] = new SelectItem(role, role.toString());
    }
    return items;
}     

public List<SecurityRole> getRoles() {
     getCurrent().getRoles();
}

public void setRoles(List<SecurityRole> roles) {
     getCurrent().setRoles(roles);
}

عندما يستدعي JSF طريقة setRoles ، فإنه يحتوي على قائمة بسلسلة النوع ، وليس نوع التعداد. أيه أفكار؟ شكرًا!

هل كانت مفيدة؟

المحلول

هذه المشكلة لا ترتبط على وجه التحديد بالتعداد. سيكون لديك نفس المشكلة مع الآخرين List الأنواع التي قامت JSF بإنشائها المحولات ، على سبيل المثال List<Integer>, List<Double>, ، إلى آخره.

المشكلة هي أن EL تعمل وقت التشغيل وأن المعلومات العامة تضيع أثناء وقت التشغيل. في جوهرها ، لا يعرف JSF/EL أي شيء عن النوع المعلمات من List والافتراضيات ل String ما لم ينص على خلاف ذلك بواسطة صريح Converter. من الناحية النظرية ، كان من الممكن استخدام اختراقات الانعكاس السيئة بمساعدة ParameterizedType#getActualTypeArguments(), ، لكن مطورو JSF/EL قد يكون لديهم أسباب لعدم القيام بذلك.

تحتاج حقًا إلى تحديد محول لهذا الصريح. منذ JSF يشحن بالفعل مع مصممة EnumConverter (وهو أمر غير قابل للاستخدام في هذه الحالة بالذات لأنه يجب عليك تحديد نوع التعداد أثناء وقت التشغيل) ، يمكنك تمديده على النحو التالي:

package com.example;

import javax.faces.convert.EnumConverter;
import javax.faces.convert.FacesConverter;

@FacesConverter(value="securityRoleConverter")
public class SecurityRoleConverter extends EnumConverter {

    public SecurityRoleConverter() {
        super(SecurityRole.class);
    }

}

واستخدامه على النحو التالي:

<h:selectManyCheckbox value="#{userController.roles}" converter="securityRoleConverter">
    <f:selectItems value="#{userController.rolesSelectMany}" />
</h:selectManyCheckbox>

أو

<h:selectManyCheckbox value="#{userController.roles}">
    <f:converter converterId="securityRoleConverter" />
    <f:selectItems value="#{userController.rolesSelectMany}" />
</h:selectManyCheckbox>

سيكون الحل الأكثر عاما (والاختراق) هو تخزين نوع التعداد كسمة مكون.

package com.example;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.convert.FacesConverter;

@FacesConverter(value="genericEnumConverter")
public class GenericEnumConverter implements Converter {

    private static final String ATTRIBUTE_ENUM_TYPE = "GenericEnumConverter.enumType";

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if (value instanceof Enum) {
            component.getAttributes().put(ATTRIBUTE_ENUM_TYPE, value.getClass());
            return ((Enum<?>) value).name();
        } else {
            throw new ConverterException(new FacesMessage("Value is not an enum: " + value.getClass()));
        }
    }

    @Override
    @SuppressWarnings({"rawtypes", "unchecked"})
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        Class<Enum> enumType = (Class<Enum>) component.getAttributes().get(ATTRIBUTE_ENUM_TYPE);
        try {
            return Enum.valueOf(enumType, value);
        } catch (IllegalArgumentException e) {
            throw new ConverterException(new FacesMessage("Value is not an enum of type: " + enumType));
        }
    }

}

إنه قابل للاستخدام من جميع أنواع List<Enum> باستخدام معرف المحول genericEnumConverter. ل List<Double>, List<Integer>, ، إلخ ، كان يمكن للمرء أن يستخدم محولات بنيت javax.faces.Double, javax.faces.Integer وهلم جرا. محول التعداد المبني بالمناسبة غير مناسب بسبب عدم القدرة على تحديد نوع التعداد الهدف (أ Class<Enum>) من الجانب العرض على. مكتبة أدوات JSF omnifaces يقدم هذا المحول بالضبط خارج الصندوق.

لاحظ أنه بالنسبة للمعتاد Enum الممتلكات ، بنيت EnumConverter يكفي بالفعل. ستقوم JSF بتثبيته بشكل تلقائي مع نوع التعداد الهدف الصحيح.

نصائح أخرى

في بعض الحالات قائمة يمكن أن يكون كذلك صفيف بعض الانواع[, ، وفي هذه الحالة ، لا يلزم محول صريح.

كانت المحو العام وسيلة ذكية لوضع الأداء العام في اللغة دون كسر الأشياء القديمة ، لكننا الآن نعيش إلى الأبد مع عواقب هذا القرار ...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top