2015-06-22 2 views
0

У меня очень странная проблема с Spring MVC 4.0.6, размещенная на JBoss 7.2. При обновлении существующего пользователя представленная информация иногда передается методу контроллера POST RequestMapping (validateUpdate method ниже).Странное поведение: атрибуты Spring Session против ModelAttribute

UserController.java

@Controller 
@RequestMapping(value = "/security/user") 
@SessionAttributes(value = {"userForm", "user"}) 
public class UserController { 

    private final String CREATE_VIEW = "user/createOrUpdate"; 
    private final String READ_VIEW = "user/readOrDelete"; 
    private final String UPDATE_VIEW = CREATE_VIEW; 
    private final String DELETE_VIEW = READ_VIEW;  

    @Autowired 
    private LocationService locationService; 

    @Autowired 
    private SecurityService securityService; 

    @Autowired 
    private UserValidator userValidator; 

    @InitBinder("userForm") 
    protected void initBinder(WebDataBinder binder) { 
     binder.setValidator(userValidator); 
     binder.setDisallowedFields("strId"); 
    } 

    @ModelAttribute("regions") 
    public List<Region> populateRegions() { 

     Locale locale = LocaleContextHolder.getLocale(); 
     List<Region> regions = this.locationService.lstRegions(locale.getLanguage()); 

     return regions; 
    } 

    @RequestMapping(value = "/update/{intUserId}", method = RequestMethod.GET) 
    public String updateUser(@PathVariable Integer intUserId, Model model) { 

     User user = this.securityService.findUserByPk(intUserId); 

     if (user != null) { 
      UserForm userForm = new UserForm(); 
      userForm.setUser(user); 

      model.addAttribute(userForm); 
     } 

     return UPDATE_VIEW; 
    } 

    @RequestMapping(value = "/update/validate", method = RequestMethod.POST) 
    public String validateUpdate(@Valid @ModelAttribute("userForm") UserForm userForm, 
           BindingResult result, 
           Model model, 
           RedirectAttributes redirectAttributes, 
           SessionStatus status) { 

     return this.performCreateOrUpdateOperation(userForm, result, model, redirectAttributes, status); 
    } 

    private String performCreateOrUpdateOperation(
     UserForm userForm, 
     BindingResult result, 
     Model model, 
     SessionStatus status) { 

     if(result.hasErrors()) { 
      return UPDATE_VIEW; 
     } else { 

      User user = userForm.getUser(); 

      this.securityService.validateCreateOrUpdateUser(result, user); 

      if (result.hasErrors() == false) { 

       if (userForm.isNew()) { 
        this.securityService.addUser(user); 
       } else { 
        this.securityService.updateUser(user); 
       } 

       model.addAttribute(user); 

       status.setComplete(); 

       return "user/success"; 

      } else { 
       return UPDATE_VIEW; 
      } 
     } 
    } 
} 

Форма Bean

public class UserForm { 

    private String strUserIdToSearch = ""; 

    private String strId = "0"; 
    private String strUserId = ""; 
    private String strFirstName = ""; 
    private String strLastName = ""; 
    private String strEmail = ""; 

    private String strRegionId = "0"; 
    private boolean booArchived = false; 

    public User getUser() { 

     User user = new User(); 

     user.setIntId(Integer.valueOf(this.strId)); 
     user.setStrUserId(this.strUserId); 
     user.setStrFirstName(this.strFirstName); 
     user.setStrLastName(this.strLastName); 
     user.setStrEmail(this.strEmail); 

     Region region = new Region(Integer.valueOf(this.strRegionId)); 
     user.setRegion(region); 

     user.setBooArchived(this.booArchived); 

     return user; 
    } 

    public void setUser(User user) { 

     this.strUserIdToSearch = user.getStrUserId(); 

     this.strId = String.valueOf(user.getIntId()); 
     this.strUserId = user.getStrUserId(); 
     this.strFirstName = user.getStrFirstName(); 
     this.strLastName = user.getStrLastName(); 
     this.strEmail = user.getStrEmail(); 

     this.strRegionId = String.valueOf(user.getRegion().getIntId()); 
     this.booArchived = user.getBooArchived(); 
    } 

    ...getters and setters... 
} 

JSP (удален стиль для ясности) crudMethod является JSP тег возвращения "создать", "читать" , «обновить» или «удалить» в зависимости от $ {requestScope ['javax.servlet.forward.request_uri']}

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> 
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> 

    <spring:url var="userFormAction" value="/rest/security/user/${crudMethod}/validate" />  

<form:form id="userForm" modelAttribute="userForm" action="${userFormAction}" method="POST"> 

<form:hidden path="strId" /> 
<form:hidden path="strUserId" id="strUserId" /> 
<form:hidden path="strLastName" id="strLastName" /> 
<form:hidden path="strFirstName" id="strFirstName" /> 
<form:hidden path="strEmail" id="strEmail" /> 

<form:select id="strRegionId" path="strRegionId"> 
    <form:option value="0" label="${strSelectRegionLabel}" /> 
    <form:options items="${regions}" itemValue="intId" itemLabel="${strRegionLabel}" /> 
</form:select> 

</form:form> 

Итак, когда я отправляю форму и, например, изменяю регион на другой идентификатор в списке (скажем, от 1 до 6). Иногда это работает, иногда нет. Под «works» я имею в виду, что я ударил страницу успеха, затем возвращаюсь к пользователю снова. Иногда он остается на 1, иногда он изменился до 6.

Я нашел шаблон/обходной путь, который работает все время, чтобы воспроизвести проблему:

  1. Загрузите обновление формы (UserController> updateUser)
  2. Изменить регион от 1 до 6
  3. Нажмите «Сохранить». Форма отправляется, поэтому вызывается метод UserController.validateUser.
  4. Получил страницу успеха. На этой странице успеха я получил ссылку на операцию чтения для пользователя. Нажимая на эту ссылку, я понимаю, что регион не изменился (основная проблема). Существует ссылка для обновления пользователя на странице чтения.
  5. Повторите то же самое изменение, которое я сделал на шаге 2.
  6. Нажмите «Сохранить». Форма отправляется, и я получил представление страницы успеха.
  7. Снова прочитайте гиперссылку, и теперь я вижу, что сработало изменение.

Вопрос: ПОЧЕМУ? Я что-то упускаю??

Примечание: это не связано с бизнес-слоем. Я тестировал его, и он стабилен. Это, безусловно, связано с моим использованием Spring MVC Framework.

Браузер IE11.

Благодарим за помощь.

* UPDATE 2015-06-29 *

После нескольких поисков, я обнаружил, что:

  • , когда он не работает, значение заголовка Content-Length запроса 0.
  • когда он работает, есть значение (например: 146).
  • тело сообщения запроса всегда правильно, например, так:

    Strid = the_ID & strUserId = THE_USERID & strLastName = THE_LASTNAME & strFirstName = THE_FIRSTNAME & strEmail = THE_EMAILADDRESS & strRegionId = THE_REGIONID & booArchived = ложь

    Обратите внимание, что «THE_REGIONID» хорош каждый раз.

Близкие по теме ресурсы

+0

Это связано с вашим браузером и связано с кешированием. Я настоятельно рекомендую использовать шаблон post-redirect-get. После обновления сделайте перенаправление на страницу успеха, а не рендеринг. Поэтому вместо возврата 'user/success' return' redirect:/url/to/success.jsp-page'. Контроллер страницы успеха должен снова извлечь пользователя из базы данных (вместо того, чтобы добавлять его в модель), если вы действительно не хотите, чтобы пользователь в области флэш-памяти мог пережить перенаправление. –

+0

Сначала я использовал атрибут flash, но если пользователь по какой-либо причине обновляет страницу успеха, содержимое очищается, поэтому это не вариант. Попробует реализовать шаблон post-redirect-get, а затем перезагрузите элемент из базы данных, как вы предложили. Спасибо. –

+0

Наконец, я сомневаюсь, что это связано с кэшированием. Я добавил точку останова в методе «validateUpdate», чтобы сразу увидеть переданные значения. Даже в этот момент значение оставалось неизменным для региона. Если он работал, но не отображался должным образом, он придерживался вашей идеи кэширования ... но он даже не отправляется должным образом ... –

ответ

1
<form:select id="intRegionId" path="strRegionId"> 

Я думаю, что ID в форме: s избранный является виновником. Он не соответствует имени атрибута в UserForm, который является «strRegionId». И поэтому он не связывается. Измените значение id на strRegionId

+0

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

+0

Вы видите проблему только с regionId или для всех параметров? – praveenj

+1

Все параметры. Модель присваивается полностью. Это вызвано проблемой аутентификации (или функцией, как они говорят ...!) Только для IE. См. Здесь: http://blogs.msdn.com/b/ieinternals/archive/2010/11/22/internet-explorer-post-bodies-are-zero-bytes-in-length-when-authentication-challenges-are -expected.aspx? CommentPosted = истина # commentmessage% 20Challenge-отклика% 20Authentication% 20and% 20Zero длины% 20Posts –

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