Here is some code:
1.
#GetMapping(path = "/register", produces = MediaType.TEXT_HTML_VALUE)
public String register(#RequestParam("name") String name,
RedirectAttributes redirectAttributes) {
// call to service
redirectAttributes.addAttribute("name", name);
return "redirect:/success";
}
This endpoint gets hit first and registers the user with provided name and redirects to the success page. It also supplies the user name.
2.
#GetMapping(value = "/success", produces = MediaType.TEXT_HTML_VALUE)
public String success(#ModelAttribute("name") String name, Model model) {
model.addAttribute("name", name);
return "success";
}
This endpoint changes the path in browser URL tab to /success and displays success.html template. It also sets the username in model so that on we can show on UI that ${name} registered successfully.
success.html is a template in /templates folder, which we want to show once this operation is over on /success page.
Everything works as expected. The problem? name of the use shows up in URL on /success page.
So after registration, while we expect the URL to be just /success, it actually is /success?name=John. It is possible to hide the request parameter part? Or to send the data in body somehow rather than request parameter.
Thanks in advance, let me know if any other detail is required.
Sure. It can be done for example by using redirectAttributes.addFlashAttribute("name", name) instead of redirectAttributes.addAttribute("name", name) in the first controller.
You can get more info here.
Related
I am working on a project using hibernate and Spring MVC architecture.
My problem is that I am using (*.htm) url pattern in my web application , in this case when I sent a product's id to controller for editing, the product's id is shown in url for eg.
"localhost:8080/MyApp/editProduct.htm?productId=03".
But I don't want this . I just want
"localhost:8080/MyApp/editProduct.htm?productId" or "localhost:8080/MyApp/editProduct.htm/productId/03"
and I am unable to use #PathVariable Annotation in my controller because of my url pattern(*.htm) and using of #PathVariable Annotation the JSP page never load properly.
Any Suggestions . Thanks in Advance.
Controller:-
#RequestMapping(value = "/{sId}/deleteState.htm")
public ModelAndView deleteState(#PathVariable("sId") int sId ){
ModelAndView mav = new ModelAndView();
try{
stateDAO.deleteById(sId);
mav.addAllObjects(prepapareModel());
mav.addObject("msg", "State Deleted Succesdfully");
mav.setViewName("admin/viewState");
return mav;
}catch(Exception e){
e.printStackTrace();
mav.addAllObjects(prepapareModel());
mav.addObject("err", "Failed to Delete State");
mav.setViewName("admin/viewState");
return mav;
}
}
public Map prepapareModel(){
Map map = new HashMap();
map.put("states", stateDAO.findAll());
return map;
}
Url after deleting the State from database:-
http://localhost:8080/PujaInBox/10/deleteState.htm
I think the Id of State is creating the problem . 10 is Id of state.
If you want to make use of #PathVariable annoation, then URL should be
/MyApp/productId/03/editProduct.htm - ending with your extension and your controller mapping should be like this
#RequestMapping(value="/productId/{id}/editProduct")
public String editProduct(#PathVariable String id, Model model) {
}
One more change to note here is that I mentioned a relative URL instead of absolute URL like localhost:8080/MyApp/productId/03/editProduct.htm including host name and port. This won't work when you deploy your application in an actual server because localhost always refers to your current machine but your application is deployed on some other host.
Hope that makes sense :)
Change servlet default url pattern to:
<servlet-mapping>
<servlet-name>servlet_name</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
But in this situation better option is to manage your #PathVariables in the middle part of URL, like:
/myapp/product/{productId}/edit.html
I am doing an assignment in a class.
I am guessing the first step is to use wildcard (*) to map your URL. In your pages, you can use whatever the URL you prefer.
Then you can invoke the method getPathInfo() in your servlet.
String action = request.getPathInfo();
Or you can call getHeader("referer") to get your URL then manipulate your string to get the information you need.
Finally, you can put the string in your if-else or switch statement.
All you have to do is create a form in your html page with method=post
<form method="post">
Then create fields inside this form and if you don't have any fields that should be displayed used input with type hidden.
<input type="hidden" name="parametername" id="parameterid" value="parametervalue">
This will do the trick, it won't show any parameter value in the URL and you can access the values as you already do.
Hope this helps....
My objective is to pass model attributes from controller to JSP page during a redirect and avoid the attribute being displayed in URL. The source code below is validating login from datastore using java data objects.
Controller:
#Controller
public class LoginController {
int count;
PersistenceManager pm = PMF.get().getPersistenceManager();
//Instance of data class
User user;
ModelAndView modelAndView=new ModelAndView();
#RequestMapping(value="/Login",method = RequestMethod.POST)
public ModelAndView loginValidate(HttpServletRequest req){
//Getting login values
String uname=req.getParameter("nameLogin");
String pswd1=req.getParameter("pswdLogin");
count=0;
user=new User();
//Generating Query
Query q = pm.newQuery(User.class);
q.setFilter("userName == userNameParam");
q.declareParameters("String userNameParam");
try{
List<User> results = (List<User>) q.execute(uname);
for (User u: results) {
String userName=u.getUserName();
if(userName.equals(uname)){
System.out.println(u.getPassword());
if(u.getPassword().equals(pswd1)){
count=count+1;
modelAndView.setViewName("redirect:welcome");
modelAndView.addObject("USERNAME",uname);
return modelAndView;
}
//rest of the logic
}
JSP:
<h1>Welcome ${USERNAME} </h1>
My current URL is /welcome?USERNAME=robin
My goal is to display it as /welcome
Also, my page is supposed to display "Welcome robin" whereas it displays only Welcome.
RedirectAttributes only work with RedirectView, please follow the same
#RequestMapping(value="/Login",method = RequestMethod.POST)
public RedirectView loginValidate(HttpServletRequest req, RedirectAttributes redir){
...
redirectView= new RedirectView("/foo",true);
redir.addFlashAttribute("USERNAME",uname);
return redirectView;
}
Those flash attributes are passed via the session (and are destroyed immediately after being used - see Spring Reference Manual for details). This has two interests :
they are not visible in URL
you are not restricted to String, but may pass arbitrary objects.
You need to be careful here because I think what are you trying to do is not supported for a good reason. The "redirect" directive will issue a GET request to your controller. The GET request should only retrieve existing state using request parameters, this is the method contract. That GET request should not rely on a previous interaction or on any object stored some where in the session as a result of it. GET request is designed to retrieve existing (persisted) state. Your original (POST) request should have persisted everything you need for you GET request to retrieve a state.
RedirectAttributes are not designed to support you in this case, and even if you managed to correctly use it it will only work once and then they will be destroyed. If you then refresh the browser you will get an application error because it cannot find your attributes anymore.
i would like to redirect a request something like this
localhost:8080 /firstSpringProject/{uniqueusername}
to a specific controller named 'profile':
#RequestMapping(value="/profile")
public String profiles(Model model){
based on the uniqueusername i would like to render a profile page
return "profile";
}
I am using spring mvc; how can I resolve this situation is there any other way to do this?
Spring documentation says on redirect view:
Note that URI template variables from the present request are
automatically made available when expanding a redirect URL and do not
need to be added explicitly neither through Model nor
RedirectAttributes. For example:
#RequestMapping(value = "/files/{path}", method = RequestMethod.POST)
public String upload(...) {
// ...
return "redirect:files/{path}";
}
Keep in mind that version lower than 3.1.4 are affected by a memory leak due to caching redirect views.
If you are using Spring 3.1.3 or lower and you are doing this
return "redirect : profile?username="+username;
you will see OutOfMemoryError sometime.
I think you may use spring path variable here. You have to create a controller method that will take username as per your URL requirement and will redirect to profile method with username parameter.
#RequestMapping(value="/{username}")
public String getUserName(Model model,#PathVariable("username") String username){
//process username here and then redirect to ur profile method
return "redirect : profile?username="+username;
}
#RequestMapping(value="/profile")
public String profiles(Model model,String username){
//have a username and render a profile page
return "profile";
}
Thank you
I am learning Spring MVC from Spring in Action 3rd Edition and came across usage of path variables. I was not clear on how it works based on the example given in the book, please help me in understanding the concept here:
#RequestMapping(method=RequestMethod.POST)
public String addSpitterFromForm(#Valid Spitter spitter, BindingResult bindingResult) {
if(bindingResult.hasErrors()){
return"spitters/edit";
}
spitterService.saveSpitter(spitter);
return "redirect:/spitters/" + spitter.getUsername();
}
As for the path that it’s redirecting to, it’ll take the form of /spitters/{username} where {username} represents the username of the Spitter that was just submitted. For example, if the user registered under the name habuma, then they’d be redirected to /spitters/habuma after the form submission.
In above statement, it says the request is redirected to /spitters/habuma where habuma is user name.
#RequestMapping(value="/{username}",method=RequestMethod.GET)
public String showSpitterProfile(#PathVariable String username, Model model){
model.addAttribute(spitterService.getSpitter(username));
return "spitters/view";
}
For example, if the request path is /username/habuma, then habuma will be passed in to showSpitterProfile() for the username.
and here it says the showSpitterProfile() method handles requests for /username/habuma which is contradicting with statement that is mentioned earlier.
It looks like the first statement itself is correct, but please tell me if the method showSpitterProfile handles both the URLs i.e /splitters/habuma and /username/habuma or /spitters/username/habuma?
There is no /username path component if the #RequestMapping on the class level (not shown in your question) is only #RequestMapping("/spitter"). There is probably a typo in the book. Correct sentence would be:
For example, if the request path is /spitter/habuma, then habuma will be passed in to showSpitterProfile() for the username.
I want to use a normal spring mvc controler and request mapping using path variables.
I do not want to forward or redirect, just change the string that user sees.
#RequestMapping(value = "/Foo/{id}/*", method = RequestMethod.GET)
public ModelAndView getFoo(#PathVariable final String friendlyUrl) {
//how can I rewite the url that user sees ?
}
(the same behaviour as when you change the title of an existing question on stackoverflow)
If you watch the traffic in wireshark, firebug or something you see, that stackoverflow sends a HTTP 301 Moved Permanently to the final URL.
You could do the same.
For this you need the HttpServletResponse, you can add it to the method signature to get it injected.
Set the permanent redirect:
String rightUrl = urlCompleter.complete(friendlyUrl);
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
response.setHeader("Location", rightUrl);
Where you need to implement urlCompleter on your own, eg. look in the database table of entries and locate the right url component.