2010-01-12 4 views
2

У меня есть следующий вид:Почему подача формы не работает?

<h:form> 
    <h:selectManyListbox value="#{reports.selectedCategories}" 
         converter="#{categoryConverter}"> 
     <f:selectItems value="#{reports.categories}"/> 
    </h:selectManyListbox> 
    <h:commandButton value="Submit" action="#{reports.action}" /> 
</h:form> 

Я использую пользовательский конвертер для преобразования категории в строку и наоборот:

public class CategoryConverter implements Converter { 

    @Autowired 
    private CategoryService categoryService; 

    public Object getAsObject(FacesContext context, UIComponent component, String value) { 
     System.out.println ("CONVERTER: GET AS OBJECT"); 
     return categoryService.findByName (value); 
    } 

    public String getAsString(FacesContext context, UIComponent component, Object value) { 
     System.out.println ("CONVERTER: GET AS STRING"); 
     return ((Category) value).getName(); 
    } 
} 

И, наконец, мой код защитный боба:

public class ReportsController { 

    private Category[] selectedCategories; 

    public void setSelectedCategories (Category[] categories) { 
     System.out.println ("SET CATEGORIES"); 
     this.selectedCategories = categories; 
    } 

    public Category[] getSelectedCategories() { 
     System.out.println ("GET CATEGORIES"); 
     return selectedCategories; 
    } 

    public void action() { 
     System.err.println ("ACTION"); 
    } 

    .... 
    //methods for accessing data 

} 

Когда я запустите мое приложение, я вижу правильный список с двумя элементами и кнопкой «Отправить». Но когда я нажимаю кнопку, ничего не происходит. Единственным выходом, который я вижу, является:

GET CATEGORIES 
CONVERTER: GET AS STRING 
CONVERTER: GET AS STRING 

Ни один метод SetSelectedCategories() и action() никогда не вызывается. И я не понимаю, почему. Какие-либо предложения?

UPD: проблема еще более глупа: когда я прокомментировал все материалы, относящиеся к классу категорий (например, мой selectManyListbox, мой конвертер, все связанные сеттеры и геттеры) и оставил действие только метода, он все равно не вызывается.

<h:form> 
    <h:commandButton value="Submit" action="#{reports.action}" /> 
</h:form> 

UPD2: вот выход из фазы слушателя

START PHASE RESTORE_VIEW 1 
END PHASE RESTORE_VIEW 1 
START PHASE APPLY_REQUEST_VALUES 2 
END PHASE APPLY_REQUEST_VALUES 2 
START PHASE PROCESS_VALIDATIONS 3 
END PHASE PROCESS_VALIDATIONS 3 
START PHASE UPDATE_MODEL_VALUES 4 
END PHASE UPDATE_MODEL_VALUES 4 
START PHASE INVOKE_APPLICATION 5 
END PHASE INVOKE_APPLICATION 5 
START PHASE RENDER_RESPONSE 6 
GET STR 
END PHASE RENDER_RESPONSE 6 

Кажется, что все фазы работали нормально, но на самом деле это не так. Я немного смущен.

+0

@ Roman - Вы пытались изменить подпись метода «действие» в соответствии с моими изменениями? – McDowell

+0

Да, я попытался вернуть нулевую, пустую строку и, наконец, строку «действие», которая отображается в навигационных правилах, и ничего не изменилось в результате (( – Roman

+0

Это не мой проект, и он уже содержит некоторые весенние вещи безопасности, возможно, проблема заключается в том, что я не знаю.Если я разработал проект с нуля, то код _all_ будет работать так, как ожидалось. – Roman

ответ

3

Когда форма JSF представить не удается, то вам необходимо убедиться в следующем:

  1. UICommand компоненты должны быть вложены в UIForm компонента.

    <h:form> 
        <h:commandButton value="submit" action="#{bean.submit}" /> 
    </h:form> 
    
  2. Вы не можете гнездо множественнымUIForm компоненты друг с другом, это запрещено спецификацией HTML. Следите за включенными страницами/подзаголовками, этими учетными записями в дереве компонентов! если jsp:include уже находится внутри h:form, вам необходимо удалить h:form со страницы включения!

    <h:form> 
        <h:form> 
         <h:commandButton value="this will not work" action="#{bean.fail}" /> 
        </h:form> 
    </h:form> 
    
  3. Нет проверки ошибок/преобразование должно быть место (использование h:messages, чтобы получить их все).

    <h:form> 
        <h:commandButton value="submit" action="#{bean.submit}" /> 
        <h:messages /> 
    </h:form> 
    
  4. Если UICommand компоненты вложены в UIData компонента (например, h:dataTable), быть уверенным, что в точности сохраняется та же DataModel (объект позади атрибута value). Самый простой способ проверить это - поместить компонент в область сеанса. Если это устраняет проблему, вам необходимо просмотреть логику загрузки данных.

  5. Атрибуты компонента и всех родительских компонентов не должны отрицательно оцениваться. Самый простой способ проверить это - поместить компонент в область сеанса. Если это устраняет проблему, вам необходимо просмотреть код, ответственный за это.

  6. Убедитесь, что номер PhaseListener или любой номер EventListener изменили жизненный цикл запроса, чтобы пропустить этап действия вызова.

  7. Убедитесь, что в той же цепочке запросов нет Filter/ одной и той же цепочкой запросов, что-то заблокировало запрос FacesServlet.

Что касается актуальности проблемы; вы не получили PropertyNotFoundException или аналогичные, и ваш PhaseListener выполнил все соответствующие фазы жизненного цикла, поэтому я думаю, что ваша проблема на самом деле вызвана 2. Вложенные формы.

+0

Я нашел проблему немного раньше, чем появился ваш ответ, но моя проблема описана в вашем 2-х позициях. В проекте есть шаблон, который добавляет форму-оболочку на каждую страницу. – Roman

+0

Ага, я думаю, это так? Пожалуйста. – BalusC

1

Потому что под «конвертер» вы должны указать название конвертера, как определено в лицах-config.xml:

<converter> 
    <converter-id>myConverter</converter-id> 
    <converter-class>com.example.converters.MyConverter</converter-class> 
</converter> 

также имеющий <h:messages/> в форме, как правило, полезно в этой ситуации, потому что вы видите, что пошло не так ,

+0

Но мой конвертер действительно найден, и его метод getAsString успешно вызван. – Roman

2

Когда форма JSF «не работает», это обычно указывает на то, что что-то (обычно компонент, валидатор или конвертер) инструктировало жизненный цикл, что некоторая часть ввода недействительна, и что она должна прекратить обработку и повторно -принять представление. Это предотвращает попадание нежелательных данных в вашу модель и прекращает работу вашей бизнес-логики от неправильного ввода.

alt text http://java.sun.com/javaee/5/docs/tutorial/backup/update3/doc/images/jsfIntro-lifecycle.gif Figure from JEE5 Tuorial

Это будет вниз некоторый путь к конфигурации вашего зрения и логики любого кода вы подключенного к нему. Как Slartibartfast says, добавление тега <h:messages /> к представлению часто будет информировать вас о том, какие компоненты вызвали этот ответ. Конфигурирование PhaseListener часто полезно при отладке, чтобы сообщить вам, какие этапы были выполнены во время запроса.


public void action() { 
    System.err.println ("ACTION"); 
} 

Этот action метод должен возвращать String:

public String action() { 
    System.err.println ("ACTION"); 
    return null; 
} 

Некоторые реализации переносят тип void возврата, но это противоречит спецификации.Атрибут action должен быть связан с действием приложения, как это определено в the spec:

действия Применение

...

  • метод должен быть публичным.
  • Метод не должен принимать никаких параметров.
  • Метод должен возвращать Object.

Метод может вызываться по умолчанию ActionListener Реализация, как описано в разделе 7.1.1 «ActionListener собственности» выше. Его обязанность заключается в том, чтобы выполнить желаемое приложение действия, а затем возвращают логическое «результат» (представлен в виде строки) , которые могут быть использованы в NavigationHandler для того, чтобы определить, какой вид должен быть оказывается рядом.

+0

Оба имплана, однако (к счастью) прощение в этом. Действия 'void' также разрешены, и это идеально, если вы хотите избежать всех проблем вокруг проблем с url-masking/backbutton/SEO/etc. Просто позвольте форме подчиняться себе и показать результат условно и использовать' GET '(outputlinks) только для простой навигации по ванилям. – BalusC

+0

@BalusC - ах, я не тестировал это недавно, если память служит, это вызвало ошибку. – McDowell

Смежные вопросы