PrimeFaces <p: fileUpload mode = "advanced" > валидатор не запущен

так как fileLimit не существует в прайс-листах 3.4. Я пытаюсь работать над внедрением валидатора, проблема в том, что проверка метода никогда не вызывается. Это мой валидатор:

@FacesValidator(value ="fileLimitValidator")
public class FileLimitValidator implements Validator {

    @Override
    public void validate(final FacesContext context, final UIComponent component,
            final Object value) throws ValidatorException {

        final String fileLimit = (String)component.getAttributes().get("fileLimit");
        final String size = (String)component.getAttributes().get("size");

        if (fileLimit!=null && size!=null) {
            if (Integer.valueOf(size) >= Integer.valueOf(fileLimit)) {
                FacesUtils.throwErrorExceptionFromComponent(component,"fichero_confidencialidad_error");
            }
        }
    }
}

и в моем лице я пробовал:

    <p:fileUpload id="#{id}FileUpload"
        fileUploadListener="#{bean[metodoTratarFichero]}" mode="advanced"
        multiple="true" allowTypes="#{allowTypes}" showButtons="false"
        update="#{id}ListaDocs #{id}MsgError" auto="true"
        label="#{fileuploadmsg.label_boton}"
        invalidFileMessage="#{fileuploadmsg.tipo_incorrecto}" >

        <f:validator validatorId="fileLimitValidator"/>
        <f:attribute name="fileLimit" value="#{fileLimit}"/>
        <f:attribute name="size" value="#{listaDocumentos.size}"/>
    </p:fileUpload>

и

    <p:fileUpload id="#{id}FileUpload"
        fileUploadListener="#{bean[metodoTratarFichero]}" mode="advanced"
        multiple="true" allowTypes="#{allowTypes}" showButtons="false"
        update="#{id}ListaDocs #{id}MsgError" auto="true"
        label="#{fileuploadmsg.label_boton}"
        invalidFileMessage="#{fileuploadmsg.tipo_incorrecto}" 
        validator="fileLimitValidator">

        <f:attribute name="fileLimit" value="#{fileLimit}"/>
        <f:attribute name="size" value="#{listaDocumentos.size}"/>
    </p:fileUpload>

и

    <p:fileUpload id="#{id}FileUpload"
        fileUploadListener="#{bean[metodoTratarFichero]}" mode="advanced"
        multiple="true" allowTypes="#{allowTypes}" showButtons="false"
        update="#{id}ListaDocs #{id}MsgError" auto="true"
        label="#{fileuploadmsg.label_boton}"
        invalidFileMessage="#{fileuploadmsg.tipo_incorrecto}" 
        validator="#{fileLimitValidator}">

        <f:attribute name="fileLimit" value="#{fileLimit}"/>
        <f:attribute name="size" value="#{listaDocumentos.size}"/>
    </p:fileUpload>

и

    <p:fileUpload id="#{id}FileUpload"
        fileUploadListener="#{bean[metodoTratarFichero]}" mode="advanced"
        multiple="true" allowTypes="#{allowTypes}" showButtons="false"
        update="#{id}ListaDocs #{id}MsgError" auto="true"
        label="#{fileuploadmsg.label_boton}"
        invalidFileMessage="#{fileuploadmsg.tipo_incorrecto}" 
        validator="#{fileLimitValidator.validate}">

        <f:attribute name="fileLimit" value="#{fileLimit}"/>
        <f:attribute name="size" value="#{listaDocumentos.size}"/>
    </p:fileUpload>

но метод проверки не вызывается. Каков правильный способ сделать это?

Ответ 1

В соответствии с FileUpload и FileUploadRenderer, валидатор вызывается только при использовании mode="simple" (обратите внимание: для этого требуется команда ajax="false"). В расширенном режиме не будет установлен загруженный файл в качестве переданного компонента, поэтому он останется null до тех пор, пока не будет вызван метод прослушивателя. Пока переданное значение null, валидаторы не вызываются.

Я не уверен, что это намеренно. Теоретически, можно установить UploadedFile в качестве представленного значения и заставить валидатор полагаться на него. Возможно, вы захотите создать отчет об улучшении в отслеживании проблем PrimeFaces.

Между тем, несмотря на то, что это была плохая практика, ваш лучший выбор действительно выполняет валидацию в методе fileUploadListener. Вы можете просто инициировать отказ в проверке с помощью сообщений face face через FacesContext следующим образом:

if (fail) {
    context.validationFailed();
    context.addMessage(event.getComponent().getClientId(context), new FacesMessage(
        FacesMessage.SEVERITY_ERROR, messageSummary, messageDetail));
}

В противном случае вам нужно создать собственный рендерер для <p:fileUpload>, который устанавливает переданное значение во время decode() (однако я не гарантирую, что он будет работать на практике, вы, возможно, наткнетесь на которая может оказаться причиной того, почему PrimeFaces изначально не реализовал ее).

Кстати, ваша первая и вторая попытки проверки правильны. Третья попытка работает только в том случае, если вы использовали @ManagedBean вместо @FacesValidator (, что часто делается, когда инъекция @EJB обязательна — которая невозможна в @FacesValidator). Четвертая попытка недействительна.

Ответ 2

Для проверки требуемой загрузки файлов в формате advanced (ajax) можно использовать следующее:

<f:metadata>
    <f:event listener="#{bean.processValidations()}" type="postValidate" />
</f:metadata>

Где реализация метода bean.processValidations() была бы чем-то вроде:

public void processValidations() {
        FacesContext context = FacesContext.getCurrentInstance();
        UIInput fileUploadComponent = fileUploadsBean.getFileUploadComponent();
        if (fileUploadComponent!=null && !isFileUploaded()) {
            fileUploadComponent.setValid(false);
            context.addMessage(fileUploadComponent.getClientId(context), new FacesMessage(FacesMessage.SEVERITY_ERROR, messageSummary, messageDetail));
            context.validationFailed();
        }
    }

Где fileUploadsBean будет CDID bean с запросом REQUEST (не будет работать со стандартными JSF ManagedBeans), который вы вводите в свой bean, который имеет метод processValidations(), метод fileUploadsBean.getFileUploadComponent() возвращает (например, для этого используется <p:fileUpload binding="#{fileUploadsBean.fileUploadComponent}" ...>). Метод isFileUploaded() будет определять, был ли файл загружен или нет (возможно, это просто нулевая проверка переменной-члена, которую вы заполняете из fileUploadListener).

Если вы хотите выделить кнопку загрузки файла, вы можете, конечно, условно добавить styleClass, который затем можно использовать для добавления красной границы, например.

styleClass="#{fileUploadsBean.fileUploadComponent.valid ? '' : 'validationFailed'}"

В результате будет выведено сообщение об ошибке с подтверждением для загрузки файлов в виде шрифтов вместе со всеми другими сообщениями проверки jsf. У вас может возникнуть проблема с поддержанием порядка сообщений проверки (всегда будет в конце), но он по-прежнему демонстрирует неудачную проверку файла загрузки после того, как пользователь обрабатывает все стандартные сообщения проверки jsf из разных полей и ваши действия в резервной копии bean наконец-то достигнут.