2013-10-02 1 views
1

ПРИМЕЧАНИЕ. В конечном итоге моя цель - просто изменить полученный URL из «/ public/academy/register? Param = blah» на настроенный URL-адрес SEO-ified, как показано в коде. Если я ошибаюсь, пытаясь отказаться от возвращения JSP-представления успеха в сопоставлении POST вместо использования post-redirect-get (что в любом случае является хорошей практикой), я открыт для предложений.Весной 3.2, действительно ли атрибуты RedirectAttributes сами передают атрибуты? Потеря элементов

Ниже приведены два метода: сопоставление запроса POST для получения регистрационной формы и обработки его, а также метод сопоставления страницы успеха. Я добавляю атрибут flash для перенаправления, который имеет форму POSTed для первого метода.

Форма имеет иерархию свойств Form -> Schedule -> Course -> Content -> Vendors, где каждый представляет собой свой собственный объект класса, за исключением того, что Поставщики являются SortedSet<Vendor>. Когда я загружаю страницу успеха, я получаю исключение Hibernate, указывающее, что поставщики не могут быть лениво инициализированы. Почему это так вниз по цепочке, что она перестает загружаться, или, что более важно, почему она утрачивает эту ценность? Когда я устанавливаю точку останова перед возвратом, объект RedirectAttributes имеет продавцов, заполненных в форме, которую я передал ей. Что дает?

@RequestMapping(value = "/public/academy/register", method = RequestMethod.POST) 
public String processSubmit(Site site, Section section, User user, 
     @ModelAttribute @Valid AcademyRegistrationForm form, 
     BindingResult result, Model model, RedirectAttributes redirectAttributes) { 
    validator.validate(form, result); 

    if (site.isUseStates() 
      && StringUtils.isBlank(form.getBooker().getState())) { 
     result.rejectValue("booker.state", 
       "gui.page.academy.attendee.state"); 
    } 

    if (result.hasErrors()) { 
     LOG.debug("Form has errors: {}", result.getAllErrors()); 
     return "common/academy-registration"; 
    } 

    // Form is valid when no errors are present. Complete the registration. 
    AcademyRegistration registration = form.toAcademyRegistration(); 
    academyService.performRegistration(registration, site); 

    redirectAttributes.addFlashAttribute(form); 

    String redirectUrl = "redirect:/public/academy/register/" 
     + registration.getSchedule().getCourse().getContent().getSeoNavTitle() 
     + "-completed"; 

    return redirectUrl; 
} 

@RequestMapping(value="/public/academy/register/**-completed", method=RequestMethod.GET) 
public String displayRegistrationSuccess(@ModelAttribute("academyRegistrationForm") final AcademyRegistrationForm form) 
{ 
    SortedSet<Vendor> dummy = form.getSchedule().getCourse().getContent().getVendors(); 
    return "common/academy-registration-success"; 
} 

Вот исключение:

Oct 2, 2013 2:11:31 PM org.apache.catalina.core.ApplicationDispatcher invoke 
SEVERE: Servlet.service() for servlet jsp threw exception 
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.horn.cms.domain.Content.vendors, could not initialize proxy - no Session 
+0

Пожалуйста, отправьте исключение спящего режима. –

+0

Done Sotirios, спасибо за напоминание. –

ответ

1

Вот что я предполагаю, что происходит (до тех пор, пока обновление с деталями):

AcademyRegistration registration = form.toAcademyRegistration(); 
academyService.performRegistration(registration, site); 

делает несколько запросов Hibernate и получает некоторые persisten объекты лениво, то есть. они не были инициализированы. Погрузка, которая произошла, вероятно, произошла в некоторых Hibernate Session (у вас есть @Transactional где-нибудь?). Session закрыт и не связан с лениво загруженным объектом.

Затем вы добавляете объект form, у которого есть некоторая вложенная ссылка на лениво загружаемый объект (он будет спящим прокси), на RedirectAttributes. Это само по себе не проблема, потому что все, что вы делаете, это передача ссылки.

Обработка запроса завершается отправкой ответа 302. Ваш клиент будет сделать новый запрос, который обрабатывается displayRegistrationSuccess() и ударяется этой линия

SortedSet<Vendor> dummy = form.getSchedule().getCourse().getContent().getVendors(); 

Здесь form объекта таким же, как был добавлен в предыдущем запросе. Одним из объектов этой ссылочной цепочки является ваш прокси-сервер Hibernate, который был лениво инициализирован. Поскольку объект больше не связан с Session, Hibernate жалуется, и вы получаете исключение, которое вы получаете.

Не рекомендуется передавать объекты (по всем границам запроса), которые зависят от постоянного состояния. Вместо этого вы должны передать идентификатор, который вы используете для извлечения объекта. Альтернативой является полная инициализация вашего объекта внутри вашего метода academyService.

+0

Делает большой смысл. Я начал использовать Hibernate.initialize() для поставщиков, а затем должен был продолжить длинную строку инициализации свойств, пока не решил, что вы правы, делая один дополнительный вызов БД для получения информации AcademyRegistration из базы данных. не нужно углубляться в иерархию объектов. Получил объект из метода displayRegistrationSuccess и работает как шарм. Благодаря! –

+0

@ Эрик Добро пожаловать. Подумайте об использовании 'FetchType.EAGER'. –