Domanda

So after a javax or hibernate validation fails the model variables are gone from the JSP.

Because I load codes for spring messages from the model like the fillowing:

<spring:message code="${editUser.role.rolename}"/>

I loose them after the validation fails and I get the following error:

javax.servlet.jsp.JspTagException: No message found under code '' for locale 'en_US'.

In this case the editUser is the model object manipulated by a form and the rolename property holds the code for translation used by spring messages tag.

My entity:

@Entity
@Table(name = "User")
public class BUser {

    @Id
    @GeneratedValue
    @Column(name = "id")
    private int id;

    @NotEmpty
    @NotBlank
    @Column(name = "username")
    private String username;

    ....

    @ManyToOne
    @JoinColumn(name = "role", unique = true)
    private BRole role;
}

Part of the controller:

    @Controller
    public class AccountController {

        @RequestMapping(value = "/secure/user/edit/{username}", method = RequestMethod.GET)
        public String editUser(Model model, @PathVariable String username) {
            BUser user = bUserService.getUserByUsername(username);
            if (user != null) {
                user.setPassword(null);
                model.addAttribute("editUser", user);
                model.addAttribute("roles", bUserService.getRoles(false));
                    return "editUser";
                } else {
                    return "404";
                }
        }

        @RequestMapping(value = "/secure/user/edit/{username}", method = RequestMethod.POST)
        public String editProcessUser(Model model, @PathVariable String username, @UserPrincipal BUser login, HttpSession session,
                @Valid @ModelAttribute("editUser") BUser editUser, BindingResult result) {

            if (result.hasErrors()) {
                return "editUser";
            }

        //some more code after that... never reached after validation error
        }
}

How is the correct way to deal with this kind of problem?

Thank you.

È stato utile?

Soluzione

Posted as an Answer on the behest of the OP...

You can set a Model Attribute as session scoped in the Controller using '@SessionAttribute'. Any time you set the value of the identified Model Attribute it will put it in session.

For example, if I had an attribute named "myBean" you could do something like:

@Controller
@RequestMapping("/myApp")
@SessionAttribute("myBean")
public class MyController {
   // ...
   @RequestMapping("/getMyBean")
   public String getMyBean(@ModelAttribute("myBean") MyBean myBean, Model uiModel) {
      uiModel.addAttribute("myBean", new MyBean());
   }
   // ...
}

In this simple example, the getMyBean() creates a new instance of MyBean everytime. This is not something you are likely to do, but do note that it also sets the "myBeam" in the model, which has the effect of putting the newly created MyBean in session scope. This has several results:

  1. Any changes made to "myBean" will be session wide
  2. Forms do not need to submit the entire bean to prevent the properties of that bean from being null since Spring will now update the existing session version and not create an empty on each time
  3. Any JSP or any code can now grab reference too and use the "myBean" in session.

Where this particularly becomes useful is when you have the need to provide a list or such globally, for instance when you need to drive the contents of a <select>. For example:

@Controller
@RequestMapping("/myApp")
@SessionAttribute({"myBean", "cities"})
public class MyController {
   // ...
   @RequestMapping("/getMyBean")
   public String getMyBean(@ModelAttribute("myBean") MyBean myBean, Model uiModel) {
      uiModel.addAttribute("myBean", new MyBean());
   }
   // ...
   @ModelAttribute("cities")
   private List<String> createCitiesList() {
      List<String> cities = new ArrayList<String>();
      cities.add("Jacksonville");
      cities.add("Orlando");
      cities.add("Miami");
      cities.add("Tampa");
      return cities;
   }
   // ...
}

In this example we create two @SessionAttributes, one for the "myBean" and the other for "cities". We also created a method marked with the @ModelAttribute that returns a List<String> of city names. The end result is that we will now auto-magically have a list of city names in session that we can drop into any of our handler methods OR use directly in our JSPs. This method can be used to build and populate anything you want, including your beans if needed.

You can read up more here:

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top