better way to feed a listbox - java

With ModelAttribute annotation, we can feed many thing like listbox.
Is it better to feed each lisbox with a different method in the controler or to use a form and have a list of object for every listbox?

If the controller class is used for different requests where some have this listboxes and some not, (for example the Controller handles the show, create and update functions for an entity, where only the create and update pages have that list boxes) then popluating the model with the #ModelAttribute annotated method would mean, that this methods will be executed even if there values are not needed. -- I my humble opinnion this would be bad.
I hope I understand your question right, if not please add a example for each of the two choises you want to compare.
#RequestMapping("/users")
#Controller
TheWayIPreferController() {
#RequestMapping(params = "form", method = RequestMethod.GET)
public ModelAndView createForm() {
ModelMap uiModel = new ModelMap();
uiModel.addAttribute("userCreateCommand", new UserCreateCommand());
uiModel.addAttribute("securityRoles", this.securityRoleDao.readAll()));
uiModel.addAttribute("salutations", this.salutationDao.readAll()));
uiModel.addAttribute("locales", this.localeDao.readAll());
return new ModelAndView("users/create", uiModel);
}
#RequestMapping(method = RequestMethod.POST)
public ModelAndView create(final #Valid UserCreateCommand userCreateCommand, final BindingResult bindingResult) {
...
}
#RequestMapping(value = "/{id}", method = RequestMethod.GET)
public ModelAndView show(#PathVariable("id") final User user) {
...
}
}
instead of:
#RequestMapping("/users")
#Controller
TheWayIDiscourageController(){
#ModelAttribute("securityRoles")
public List<SecurityRoles> getSecurityRoles(){
return this.securityRoleDao.readAll();
}
#ModelAttribute("salutations")
public List<SecurityRoles> getSalutations(){
return this.salutationDao.readAll());
}
#ModelAttribute("locales")
public List<SecurityRoles> getLocals(){
return this.localeDao.readAll();
}
#RequestMapping(params = "form", method = RequestMethod.GET)
public ModelAndView createForm() {
return new ModelAndView("users/create", "userCreateCommand", new UserCreateCommand());
}
#RequestMapping(method = RequestMethod.POST)
public ModelAndView create(final #Valid UserCreateCommand userCreateCommand, final BindingResult bindingResult) {
...
}
#RequestMapping(value = "/{id}", method = RequestMethod.GET)
public ModelAndView show(#PathVariable("id") final User user) {
...
}
}

Related

Hello,I want to know the exact scenerio where in we can declare same method as get and post?

I want to know the exact scenerio where in we can declare same method as get and post?
i have used the case but still not able to find right explaination
#RequestMapping(value =url, method = RequestMethod.POST)
public ModelAndView fetchLrmPart1(Model model, HttpServletRequest request)
{
return this.getPart1Page(request, model);
}
#RequestMapping(value = url, method = RequestMethod.GET)
public ModelAndView fetchLRMGet(Model model, HttpServletRequest request)
{
return this.getPart1Page(request, model);
}

Spring REST controller with different functions

I have a Spring #RestController for manipulating my Users and I want to have several functions:
/users : GET (returns all users)
/users/:id : GET (returns a user with given ID, default id=1)
/users : POST (inserts a user)
/users/:id : DELETE (deletes a user with given ID)
I started working on it but I'm not sure how to manage the "overlapping" URIs for the same method (e.g. first two cases). Here's what I came with so far:
#RestController
public class UserController {
#RequestMapping(value = "/users", method = RequestMethod.GET)
public List<User> getAllUsers() {
return UserDAO.getAll();
}
#RequestMapping(value = "/users", method = RequestMethod.GET)
public User getUser(#RequestParam(value = "id", defaultValue = "1") int id) {
return UserDAO.getById(id);
}
}
This won't work due to "ambiguous mapping" and it's pretty clear to me, but I don't know what to do. Should I change one of the URIs or there is some other way?
Edit:
I've also tried changing the second method to:
#RequestMapping(value = "/users/{id}", method = RequestMethod.GET)
public User getUser(#PathVariable("id") int id) {
return UserDAO.getById(id);
}
Still doesn't work.
Your current mapping:
#RequestMapping(value = "/users", method = RequestMethod.GET)
public User getUser(#RequestParam(defaultValue = "1") int id)
Would map to the /users?id=42 not the desired /users/42. If you want to create a mapping for /users/:id endpoint, use the following:
#RequestMapping(value = "/users/{id}", method = RequestMethod.GET)
public User getUser(#PathVariable int id) {
return UserDAO.getById(id);
}
Also, as of Spring Framework 4.3, you can use new meta annotations to handle GET, POST, etc. methods:
#RestController
#RequestMapping("/users")
public class UserController {
#GetMapping
public List<User> getAllUsers() {
return UserDAO.getAll();
}
#GetMapping("{id}")
public User getUser(#PathVariable int id) {
return UserDAO.getById(id);
}
}

pass JSON to jsp from Spring controller. How represent JSON?

I need to represent JSON in table. I get JSON from my controller and i don`t know what next...How can i pass JSON to exact jsp or i should not do it?Sorry, I m new in JSON.
And what should i do after method add(...)? What should i return.
Here is my controller code
#Controller
public class MainController {
#Autowired
private ClientLogManager clientLogManager;
#ResponseBody
#RequestMapping(value = "/api/getlog/{appId}", method = RequestMethod.GET)
public List<ClientLog> getAll(#PathVariable Integer appId, Model model) {
List clientLogs = clientLogManager.get(appId);
return clientLogs;
}
#ResponseBody
#RequestMapping(value = "/api/log", method = RequestMethod.POST)
public ClientLog add(#RequestBody ClientLog clientLog) {
clientLogManager.add(clientLog);
return clientLog;
}
}
u can get your json data via a simple html file ...
in your jsp file you can get this list with jQuery
$.getJSON('localhost:8080/api/getlog/12', function (clientlogs) {
for(clientlog : clientlogs){
console.log(clientlog.id);
}
});
if u have a save operation you had better use PUT method
#ResponseBody
#RequestMapping(value = "/api/log", method = RequestMethod.PUT)
public ClientLog add(#RequestBody ClientLog clientLog) {
clientLogManager.add(clientLog);
return clientLog;
}

Spring RequestMapping conflicts

I have a RequestMapping that displays a grid, and another one for loading objects in grid.
#RequestMapping(value = "/grid/{objType}", method = RequestMethod.GET)
public String displayGrid(Model model, #PathVariable("objType") String objType) {
// some code here
}
#RequestMapping(value = "/loadGrid", method = RequestMethod.GET)
public #ResponseBody String loadGrid(Model model) {
// returns a JSON
}
When i display the grid the url is like ../grid/User
The problem is that after the grid is created and a request loadGrid is made, the request is mapped to /grid/loadGrid which is resolved by the first method instead of the second one.
Is there any way to make a request for /grid with nothing after it ?
Or any way to resolve this conflict ?
The collision isn't a problem; spring resolves exact matches first. (see the source code of AbstractHandlerMethodMapping)
Your problem is that you've incorrectly defined your mappings. If you define a #RequestMapping at the class level, all the method #RequestMappings will be prefixed with the defined value.
The following maps three endpoints: /grid, /grid/{objType} and /grid/loadGrid. Note that the #RequestMapping for get() defines no value, only its method because it inherits from the class-level annotation.
#Controller
#RequestMapping(value = "/grid")
public class GridController {
#RequestMapping(method = RequestMethod.GET)
public String get(Model model) {
// ...
}
#RequestMapping(value = "/{objType}", method = RequestMethod.GET)
public String displayGrid(Model model, #PathVariable("objType") String objType) {
// ...
}
#ResponseBody
#RequestMapping(value = "/loadGrid", method = RequestMethod.GET)
public String loadGrid(Model model) {
// ...
}
}

Spring MVC - The #SessionAttributes and status.setComplete()

I'm facing a problem I don't really know how to solve.
I am developing a Bug Tracker (learning purposes only). I have a page to create a new issue and one page to edit an issue. Both, for now, have their own controllers.
EditIssueController.java
#Controller
#RequestMapping(value = "/issues/{issueId}")
#SessionAttributes("issuePackage")
public class EditIssueController {
#Autowired
private IssueService issueService;
[...]
#ModelAttribute("issuePackage")
public IssueTagEnvironment populateIssue (#PathVariable("issueId") Integer issueId) {
IssueTagEnvironment issueTagEnv = new IssueTagEnvironment();
issueTagEnv.setIssue(issueService.getIssueById(issueId));
return issueTagEnv;
}
#InitBinder
public void initBinder (WebDataBinder binder) {
[...]
}
#RequestMapping(value = "/edit", method = RequestMethod.GET)
public ModelAndView editIssue (#PathVariable("issueId") Integer issueId,
#ModelAttribute("issuePackage") IssueTagEnvironment issuePackage) {
ModelAndView mav = new ModelAndView("/issues/EditIssue");
[...]
IssueTagEnvironment issueTagEnv = new IssueTagEnvironment();
issueTagEnv.setIssue(issueService.getIssueById(issueId));
[...]
mav.addObject("issuePackage", issueTagEnv);
return mav;
}
#RequestMapping(value = "/edit", method = RequestMethod.POST)
public String updateIssue (#ModelAttribute("issuePackage") IssueTagEnvironment issuePackage,
BindingResult result) {
if (result.hasErrors() == true) {
return "redirect:/issues/{issueId}/edit";
}
issueService.updateIssue(issuePackage.getIssue());
return "redirect:/issues/{issueId}";
}
}
CreateIssueController.java
#Controller
#SessionAttributes("issuePackage")
public class CreateIssueController {
#Autowired
private IssueService issueService;
[...]
#ModelAttribute("issuePackage")
public IssueTagEnvironment populateNewIssue () {
return new IssueTagEnvironment();
}
#InitBinder
public void initBinder (WebDataBinder binder) {
[...]
}
#RequestMapping(value = "/issues/CreateIssue", method = RequestMethod.GET)
public ModelAndView createIssueGet (#ModelAttribute("issuePackage") IssueTagEnvironment issuePackage) {
ModelAndView mav = new ModelAndView("/issues/CreateIssue");
[...]
issuePackage.getIssue().setReporter(SecurityUtils.getCurrentUser());
return mav;
}
#RequestMapping(value = "/issues/CreateIssue", method = RequestMethod.POST)
public String createIssuePost (#ModelAttribute("issuePackage") IssueTagEnvironment issuePackage,
BindingResult result,
SessionStatus status) {
if (result.hasErrors() == true) {
return "redirect:/issues/CreateIssue";
}
[...]
issueService.createIssue(issuePackage.getIssue());
status.setComplete();
return "redirect:/issues/" + issuePackage.getIssue().getId();
}
}
So far everything seems correct (and in indeed works). But here are the dragons:
I am within an "edit" page changing data from an existing issue.
Instead of submitting the changes I decide to press the "Go Back" button from the navigator.
Right after that action (Go Back), I decide to create a new issue and... Here it is! The form to create a new issue isn't empty but filled with the information of the previous "edited-but-not-submitted" issue.
I understand what the problem is: The controller is not completing the session/status by executing status.setComplete().
My question here is, how to solve this problem?
Thanks in advance to the community!
For your current example, it is easy to fix , just change createIssueGet method to :
public ModelAndView createIssueGet () {
ModelAndView mav = new ModelAndView("/issues/CreateIssue");
IssueTagEnvironment issuePackage = new IssueTagEnvironment();
ModelAndView mav = new ModelAndView("/issues/CreateIssue");
mav.addAttribute("issuePackage", issuePackage);
[...]
[...]
}
That way you are sure that you always use a fresh IssueTagEnvironment object in that controller. And Spring will put it in session as you put it in model.
But the problem still remains : if you do not properly call status.setComplete(), you leave in session an object that should not be there, and like you said dragons may be there
I stopped using #SessionAttributes for that reason, and only use a hidden field (for the id) and a Converter from the id to a full object using the service layer, hoping it should be in cache and does not hit the database. Not really nice, but not really worse than that.

Categories

Resources