пятница, 27 января 2012 г.

Spring Roo: 400 Bad Request из-за неправильного формата даты по умолчанию

Недавно используя Spring Roo для генерации админки столкнулся со следующей проблемой.
В БД имеется сущность. У нее множество разных полей, в том числе поля типа Date. Есть необходимость сделать выборку по дате. Как оказалось, при запуске автоматического сгенерированного кода для поиска по дате, я получил ошибку 400 Bad Request.

Для поиска по полям сущностей Spring Roo предоставляет замечательный инструмент - автоматическую генерацию "файндера". Добавляется этот файндер  следующей командой:

finder add --finderName findUserByRegistrationBetween
В результате генерится код во всех слоях приложения: в модель добавляется метод findUserByRegistrationBetween, аналогичные методы добавляются в контроллер и в представление.

Запускаю сервер, попадаю на страницу поиска по дате. Ввожу дату с помощью компонента календарь (дата отображается в формате dd.mm.yyyy), жму поиск.

После нажатия на поиск я попадаю на следующую страницу.
Страница гласит:

HTTP ERROR 400

Problem accessing /admin/users. Reason:
    Bad Request


Powered by Jetty://


Такая ошибка может возникать, когда входные данные сервлета не прошли валидацию.
Если вглядеться в адрес страницы, можно увидеть, что он имеет следующий вид:
http://localhost:8080/admin/users?find=ByRegistrationDateBetween&minRegistrationDate=2012-01-27&maxRegistrationDate=2012-01-28
То есть дата представлена в формате ISO.
Отправляемся в код, сгенерированный Roo, в файл UserController_Roo_Controller_Finder.aj
Видим:

public String findUsersByRegistrationDateBetween(
@RequestParam("minRegistrationDate") @DateTimeFormat(style = "M-") Date minRegistrationDate,
@RequestParam("maxRegistrationDate") @DateTimeFormat(style = "M-") Date maxRegistrationDate,
Model uiModel) {

На входные данные наложены ограничения по формату аннотацией DateTimeFormat. Параметр style = "M-" означает, что используется "средний" формат даты (M = medium), без указания времени (- вместо времени). Этот формат подгружается из текущей локали и в моем случае представляет собой формат "dd.mm.yyyy". Естественно, дата вида 2012-01-27 этому формату не соответствует.

Для исправления этой ошибки я заменил формат входных данных на формат ISO с помощью одноименного параметра.
Код обработчика стал выглядеть следующим образом:
public String findUsersByRegistrationDateBetween(
@RequestParam("minRegistrationDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Date minRegistrationDate,
@RequestParam("maxRegistrationDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Date maxRegistrationDate,
Model uiModel) {

В результате сервер нормально обрабатывал входные данные в формате ISO и успешно проводил поиск по дате.

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

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