I'm adding a Path variableto receive value sent by URL. And this is my controller.
#Controller
#RequestMapping("/user")
public class UserController {
#RequestMapping(value = "/list/{field}", method = RequestMethod.GET)
public void userList(Model model, #PathVariable("field") String field) {
List<Users> userList = userDAO.searchAll();
System.out.println("Condition "+field);
model.addAttribute("userList", userList);
}
}
But I'm getting a 404 error.
And this is my folder structure for jsp.
Please help me to find out what is wrong here.
Thanks.
Edit : And also is there any chance that I can send empty path variable ex: http://localhost:8080/mvcquick/user/list and return to the same method?
system is looking for mvcquick/WEB-INF/jsp/user/list/n.jsp.
I dont see this file.
Please try this:
#Controller
#RequestMapping("/user")
public class UserController {
#RequestMapping(value = "/list/{field}", method = RequestMethod.GET)
public String userList(Model model, #PathVariable("field") String field) {
List<Users> userList = userDAO.searchAll();
System.out.println("Condition "+field);
model.addAttribute("userList", userList);
return "user/list"; // added line. Alos return type to String
}
Please try with below option.
#PathVariable(name="field",required=true)
Notice the error says n.jsp is not found. It means you're not returning the view name from the controller - I assume it's list.jsp. To change this, give a return value of String pointing to your list.jsp file. So try using
#RequestMapping(value = "/list/{field}", method = RequestMethod.GET)
public String userList(Model model, #PathVariable("field") String field) {
List<Users> userList = userDAO.searchAll();
System.out.println("Condition "+field);
model.addAttribute("userList", userList);
return "jsp/user/list.jsp"; // Path root must be from WEB-INF
}
I think it is looking for n.jsp inside your ".jsp" files. Please make sure that while sending id or attributes you are sending properly.
See this link for sending data(SO)
Related
I have a controller method as this:
#PostMapping("/view/{location}")
public ModelAndView view(#PathVariable("location") String location) {
ModelAndView modelAndView = new ModelAndView();
return modelAndView;
}
This method is capable of receiving requests like
"/view/a" or "/view/b" such that pathVariable location becomes a or b.
But I want this same method to receive all the requests having /view in their beginning, such that the pathVariable "location" holds the rest of the data.
for example
for a request as /view/a/b/c, the pathVariable location will become a/b/c.
like a file system hierarchy.
Please let me know if such a thing is possible in Spring MVC, and I am very new at this.
Check out this article
The idea is to map all the paths which start with /view to a single controller method by adding **, but you'll have to use HttpServletRequest instead of #PathVariable.
So, in your case, it'll be something like this:
#PostMapping("/view/**")
public ModelAndView view(HttpServletRequest request) {
String pathVariable = extractId(request);
ModelAndView modelAndView = new ModelAndView();
return modelAndView;
}
private String extractId(HttpServletRequest request) {
String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
return new AntPathMatcher().extractPathWithinPattern(bestMatchPattern, path);
}
Also, check out this question
You could go by the approach shared earlier,
#GetMapping(value = "blog/**")
public Blog show(HttpServletRequest request){
String id = (String)
request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
System.out.println(id);
int blogId = Integer.parseInt(id);
return blogMockedData.getBlogById(blogId);
}
Second way is to use RequestParam instead of Path variable.
you will call the api using :
http://localhost:8080/blog?input=nabcd/2/nr/dje/jfir/dye
controller will look like :
#GetMapping(value = "blog")
public Blog show(#RequestParam("input") String input){
If you are certain about the number of slash in your input, you could go with any approach mentioned here help
I'd like to know if there is a way I can forward a request from one controller to another without actually changing the URL in the browser.
#RequestMapping(value= {"/myurl"})
public ModelAndView handleMyURL(){
if(somecondition == true)
//forward to another controller but keep the url in the browser as /myurl
}
examples that I found online were redirecting to another url which was causing other controllers to handle that. I don't want to change the URL.
Try to return a String instead of ModelAndView, and the String being the forward url.
#RequestMapping({"/myurl"})
public String handleMyURL(Model model) {
if(somecondition == true)
return "forward:/forwardURL";
}
Instead of forwarding, you may just call the controller method directly after getting a reference to it via autowiring. Controllers are normal spring beans:
#Controller
public class MainController {
#Autowired OtherController otherController;
#RequestMapping("/myurl")
public String handleMyURL(Model model) {
otherController.doStuff();
return ...;
}
}
#Controller
public class OtherController {
#RequestMapping("/doStuff")
public String doStuff(Model model) {
...
}
}
As far as I know "forward" of a request will be done internally by the servlet, so there will not be a second request and hence the URL should remain the same. Try using the following code.
#RequestMapping(value= {"/myurl"})
public ModelAndView handleMyURL(){
if(somecondition == true){
return new ModelAndView("forward:/targetURL");
}
}
I am trying to retrieve some JSON data in my javascript by making a call to the controller. The controller returns a MappingJacksonJsonView ModelandView, but the .getJSON is always reporting a 404 at .../handhygiene.json.
Is there a problem with the way I am returning the ModelandView from the controller?
Controller
#RequestMapping(value = "/{room}/handhygiene.json", method = RequestMethod.GET)
public ModelAndView getHandHygienePageAsync(
#PathVariable(value = "room") String roomCode) {
ModelAndView mav = new ModelAndView(new MappingJacksonJsonView());
mav.getModelMap().addAttribute(blahblahblah); //adds some attributes
...
return mav;
}
Javascript
var currentURL = window.location;
$.getJSON(currentURL + ".json",
function(data) {
... //does stuff with data
}
If you're trying to get only an JSON object from Ajax request, you need to add #ResponseBody to your method, and make you result object as return from your method.
The #ResponseBody tells to Spring that he need to serialize your object to return to the client as content-type. By default, Spring uses JSON Serialization. ModelAndView will try to return an .JSP page. Maybe you don't have this jsp page on your resources so, the server return 404 error.
I Think this code should work for you:
#RequestMapping(value = "/{room}/handhygiene.json", method = RequestMethod.GET)
public #ResponseBody Room getHandHygienePageAsync(#PathVariable(value = "room") String roomCode) {
Room room = myService.findRoomByRoomCode(roomCode);
return room;
}
I'm assuming you're using the Room as your result object, but it may be another object or ArrayList, for example.
You cant take a look here for Spring example, and here for example and configuration.
I'm trying out Spring MVC 3.0 for the first time and like to make it RESTfull.
This is my controller:
#Controller
#RequestMapping(value = "/product")
#SessionAttributes("product")
public class ProductController {
#Autowired
private ProductService productService;
public void setProductValidator(ProductValidator productValidator, ProductService productService) {
this.productService = productService;
}
#RequestMapping(method = RequestMethod.GET)
public Product create() {
//model.addAttribute(new Product());
return new Product();
}
#RequestMapping(method = RequestMethod.POST)
public String create(#Valid Product product, BindingResult result) {
if (result.hasErrors()) {
return "product/create";
}
productService.add(product);
return "redirect:/product/show/" + product.getId();
}
#RequestMapping(value = "/show/{id}", method = RequestMethod.GET)
public Product show(#PathVariable int id) {
Product product = productService.getProductWithID(id);
if (product == null) {
//throw new ResourceNotFoundException(id);
}
return product;
}
#RequestMapping(method = RequestMethod.GET)
public List<Product> list()
{
return productService.getProducts();
}
}
I have 2 questions about this.
I'm a believer in Convention over Configuration and therefor my views are in jsp/product/ folder and are called create.jsp , list.jsp and show.jsp this works relatively well until I add the #PathVariable attribute. When I hit root/product/show/1 I get the following error:
../jsp/product/show/1.jsp" not found how do I tell this method to use the show.jsp view ?
If I don't add the RequestMapping on class level my show method will be mapped to root/show instead of root/owner/show how do I solve this ? I'd like to avoid using the class level RequestMapping.
add your 'product' to Model and return a String /product/show instead of Product. In your show.jsp, you can access the product object form pageContext
Check out the section in the manual about "Supported handler method arguments and return types".
Basically, when your #RequestMapping method returns just an object, then Spring uses this as a single model attribute, and, I'm guessing, attempts to use the request URL as the basis for the view name.
The easiest way to return the view and data you want from the same method is probably to just have the method return a ModelAndView, so you can explicitly specify the viewName and the model data.
I want to read a domain object (UserVO) from session scope.
I am setting the UserVO in a controller called WelcomeController
#Controller
#RequestMapping("/welcome.htm")
public class WelcomeController {
#RequestMapping(method = RequestMethod.POST)
public String processSubmit(BindingResult result, SessionStatus status,HttpSession session){
User user = loginService.loginUser(loginCredentials);
session.setAttribute("user", user);
return "loginSuccess";
}
}
I am able to use the object in jsp pages <h1>${user.userDetails.firstName}</h1>
But I am not able to read the value from another Controller,
I am trying to read the session attribute as follows:
#Controller
public class InspectionTypeController {
#RequestMapping(value="/addInspectionType.htm", method = RequestMethod.POST )
public String addInspectionType(InspectionType inspectionType, HttpSession session)
{
User user = (User) session.getAttribute("user");
System.out.println("User: "+ user.getUserDetails().getFirstName);
}
}
The code you've shown should work - the HttpSession is shared between the controllers, and you're using the same attribute name. Thus something else is going wrong that you're not showing us.
However, regardless of whether or not it works, Spring provides a more elegant approach to keeping your model objects in the session, using the #SessionAttribute annotation (see docs).
For example (I haven't tested this, but it gives you the idea):
#Controller
#RequestMapping("/welcome.htm")
#SessionAttributes({"user"})
public class WelcomeController {
#RequestMapping(method = RequestMethod.POST)
public String processSubmit(ModelMap modelMap){
User user = loginService.loginUser(loginCredentials);
modelMap.addtAttribute(user);
return "loginSuccess";
}
}
and then
#Controller
#SessionAttributes({"user"})
public class InspectionTypeController {
#RequestMapping(value="/addInspectionType.htm", method = RequestMethod.POST )
public void addInspectionType(InspectionType inspectionType, #ModelAttribute User user) {
System.out.println("User: "+ user.getUserDetails().getFirstName);
}
}
However, if your original code isn't working, then this won't work either, since something else is wrong with your session.
#SessionAttributes works only in context of particular handler, so attribute set in WelcomeController will be visible only in this controller.
Use a parent class to inherit all the controllers and use SessionAttributes over there. Just that this class should be in the package scan of mvc.
May be you have not set your UserVO as Serializable.