среда, 20 марта 2013 г.

j_security_check request и генерация идентификаторов контролов

Наткнулся на интересную ошибку (особенность?) работы JSF.
Честно говоря, особого желания нет копаться до истины и "а почему же всё-таки так", но случай интересный.

История возникновения
На странице, куда осуществляется редирект после некорректного логина было несколько контролов (в моём случае h:link на попробовать ещё раз и на страницу восстановления пароля). Страница очень простая, никаких аяксов, лишь эти 2 ссылки и статический текст о том, что авторизация не удалась.

Запускаем, вводим неверный пароль, вместо страницы ошибки входа видим в браузере internal server error 500, а в логе:
Caused by: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
 at java.util.ArrayList.RangeCheck(ArrayList.java:547)
 at java.util.ArrayList.get(ArrayList.java:322)
 at javax.faces.component.AttachedObjectListHolder.restoreState(AttachedObjectListHolder.java:165)
 at javax.faces.component.UIComponentBase.restoreState(UIComponentBase.java:1560)
А если не поленимся обновить страницу, то всё отобразится корректно.

Кто виноват и что делать?
Оказалось, всё дело в том, что стандартный j_security_check request обрабатывается напрямую веб-контейнером, а не JSF. Собственно, это не секрет, секрет в том, что из этого следует: на странице ошибки входа JSF не сгенерирует id-шников для контролов. Поэтому всё, что нужно, это явно указать идентификаторы:
...
    try login again
    restore your password


Почему после обновления страницы всё работает?
Потому что это будет обычный запрос "файла с хтмл" на сервере, а не j_security_check, поэтому его обработает движок JSF.

Почему такой странный лог restoreState : IndexOutOfBoundsException, если всё дело в идентификаторах контролов?
Не знаю, как раз в этом разбираться у меня желания не было. Надеюсь, разработчики это пофиксят со временем.

Комментариев нет:

Отправить комментарий