Проверка нескольких полей, получение значения другого компонента приводит к NullPointerException

Я получаю javax.faces.FacesException: java.lang.NullPointerException, когда я набираю что-то в почтовом индексе и нажимаю «Отправить» со страной, установленной на нулевое значение по умолчанию. Если я выбираю страну, а затем что-то набираю, все работает. Я пробовал SubmittedValue, но он работает наоборот - с нулем работает и после этого выдает нулевое исключение.

@FacesValidator("zipV")
public class ZipValidator implements Validator {

LocaleBean Bean = new LocaleBean();
String language;
private static final String ZIP_PATTERN_BG = "\\d{4}";
private static final String ZIP_PATTERN_US = "\\d{5}";
private static final String ZIP_PATTERN_DEFAULT = "[A-Za-z0-9]*";
private String zip_pattern;
private Pattern pattern;
private Matcher matcher;
private String country;


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

    language = Bean.getLanguage();

    UIInput Input = (UIInput) component.getAttributes().get("country");
    country = Input.getValue().toString();
    String zip = (String) value;


    if (country == null || country.isEmpty()) {
        return; 
    }

    switch (country) {
        case "BGR":
            zip_pattern = ZIP_PATTERN_BG;
            break;
        case "USA":
            zip_pattern = ZIP_PATTERN_US;
            break;
        default:
            zip_pattern = ZIP_PATTERN_DEFAULT;
            break;
    }

    pattern = Pattern.compile(zip_pattern);

    matcher = pattern.matcher(value.toString());
    if (!matcher.matches()) {


        switch (language) {
            case "en": {
                FacesMessage msg = new FacesMessage("Invalid zip.");
                msg.setSeverity(FacesMessage.SEVERITY_ERROR);
                throw new ValidatorException(msg);
            }
            case "bg": {
                FacesMessage msg = new FacesMessage("Невалиден пощенски код.");
                msg.setSeverity(FacesMessage.SEVERITY_ERROR);
                throw new ValidatorException(msg);
            }
        }
    }
}
}

Вот вид:

<h:selectOneMenu id="country" value="#{account.country}" required="true" requiredMessage="#{msg['register.required']}" binding="#{country}">
<f:selectItem itemValue="#{null}" itemLabel="#{msg['register.countryQ']}"/>
<f:selectItems value="#{account.countries}"/>
<f:ajax listener="#{account.loadStates()}" render="state"/>
</h:selectOneMenu>

<h:inputText id="zipcode" required="true" requiredMessage="#{msg['register.required']}" value="#{account.zipcode}">
<f:validator validatorId="zipV"/>
<f:attribute name="country" value="#{country}"/>
</h:inputText>

person Pavel    schedule 06.09.2013    source источник
comment
является нулевым указателем на Input.getValue().toString() ?   -  person Jonathan Viccary    schedule 06.09.2013
comment
да, если я изменю его на SubmittedValue, он будет работать с нулевым значением и не будет работать после этого.   -  person Pavel    schedule 06.09.2013
comment
не могли бы вы объяснить, что вы подразумеваете под «после этого»? Вы имеете в виду, что если вы используете Input.getSubmittedValue().toString(), вы не получите нулевой указатель, но код не работает где-то после этой точки?   -  person Jonathan Viccary    schedule 06.09.2013
comment
Я ввожу значение в zip-форму и нажимаю «Отправить» — я не получаю нулевой указатель. Меняю страну, нажимаю отправить - получаю нулевой указатель.   -  person Pavel    schedule 06.09.2013
comment
getSubmittedValue() - неправильный подход. Его следует использовать только в том случае, если валидатор запускается до обработки компонента. Это не тот случай здесь. Валидатор запускается на компоненте zip после обработки компонента страны.   -  person BalusC    schedule 06.09.2013


Ответы (1)


Здесь,

country = Input.getValue().toString();

вы вообще не должны использовать toString(). Вы должны использовать его:

country = (String) Input.getValue();

В противном случае он выдаст NullPointerException, если getValue() вернет null. Как ясно сказано в его javadoc, NullPointerException будет выброшен среди других, когда вы попытаетесь вызвать метод экземпляра на null (как вы сделали с toString()).

Обратите внимание, что эта проблема технически не связана с JSF. Это просто базовая Java. Пакет java.lang исключения — очень хорошая подсказка в этом. Если вы получили исключение для пакета javax.faces (или javax.el), то мы можем говорить о настоящей проблеме JSF (или EL).

Смотрите также:


Не связанный с конкретной проблемой, я действительно уважаю Соглашения об именах Java. Имена переменных начинаются с нижнего регистра. Используйте input вместо Input. Также странно у вас ручное управление локализацией. Что делать, если вам когда-нибудь понадобится поддержка 10 языков? Вы расширяете переключатели по всему месту? Используйте встроенные средства локализации JSF с <resource-bundle> и ResourceBundle#getBundle().

person BalusC    schedule 06.09.2013
comment
спасибо это помогло. Как я могу заставить свой ResourceBundle#getBundle() получать пакет из com.program.messages вместо корневой папки. - person Pavel; 07.09.2013
comment
Просто передайте именно это значение в качестве базового имени. - person BalusC; 07.09.2013
comment
пробовал не работает. Работает только если в корне они называются messages.properties и значением messages. ResourceBundle.getBundle(сообщения, currentLocale). Я также пробовал com/program/messsages/messages... не работает - person Pavel; 07.09.2013
comment
Возможно, вы делаете/интерпретируете что-то неправильно. Это должно быть точно такое же значение, которое вы указали в <resource-bundle> в faces-config.xml. См. также stackoverflow.com/q/2668161. Если вы все еще застряли, нажмите [Ask Question], чтобы задать новый вопрос об этом. Эта часть не имеет отношения к конкретному заданному вопросу. На этот вопрос уже был дан ответ. Поскольку вы здесь впервые, не забудьте пометить ответ как принятый, если он помог (больше всего) понять и решить проблему. См. также Как работает принятие ответа? - person BalusC; 07.09.2013