• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Paul Clapham
  • Ron McLeod
  • Liutauras Vilda
  • Bear Bibeault
Sheriffs:
  • Jeanne Boyarsky
  • Tim Cooke
  • Devaka Cooray
Saloon Keepers:
  • Tim Moores
  • Tim Holloway
  • Piet Souris
  • salvin francis
  • Stephan van Hulst
Bartenders:
  • Frits Walraven
  • Carey Brown
  • Jj Roberts

How to set the URL name in a spring MVC controller?

 
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have a form with several fields and a save button.

When the save button is clicked, the form is submitted and the following spring mvc controller is executed.


The controller correctly saves the data and opens form2. It also correctly populates form2 fields with data from personobj.

The problem is that, at this point the url name should be http://localhost:8080/form2 because the content for form2 is being displayed. But instead, the url is displaying http://localhost:8080/saveform1.

How can I set the url name to be http://localhost:8080/form2?
 
Saloon Keeper
Posts: 22801
153
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
URLs don't have "names". A URL is a Uniform Resource Locator. Which is to say that it is the "address" from which a resource can be located. The navigation bar in a web browser is not so much a place for displaying URLs as it is an input control where the user can manually request a resource. The text is set automatically by the browser when the request is made, not when the response is received, which is why you see the URL referencing the form action (saveform1) not the currently displayed form.

If you think that's bad, the JavaServer Faces framework uses URLs more like "handles" to resources in a workflow than it uses them as absolute locators, so the URL in a user's browser navigation control may refer to a different page than expected.
 
Jf Okeeffe
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for your answer Tim.

Let's say I have a page called formtofill.html.

In this form there are several buttons. Each executing a different action.
One makes a calculation, another retrieves some info, other saves the form etc.
Each one of them need to execute a different operation on the server side.
So a controller needs to be called, the operation is executed on the server side and then formtofill.html is displayed again.
But I don't want that the url to be what is in the "value" field of RequestMapping because the value there doesn't represent what the user is seeing at the moment.
I want the url to always be "formfill.html" (with no parameters) regardless of which button is clicked or server side operation is executed.
I'm using Spring MVC, don't want to use JSF.
There's no way to do that with Spring MVC?
 
Tim Holloway
Saloon Keeper
Posts: 22801
153
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you want no parameters in a URL, then it has to be submitted by a form POST. To use the same URL mapping, you'd have to have one mapping action method that determined which operation actually needed to be performed, based (presumably) on the POST parameter values.
 
Bartender
Posts: 1979
13
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, jk fe
How about trying this:
 
Jf Okeeffe
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tim Holloway wrote:If you want no parameters in a URL, then it has to be submitted by a form POST. To use the same URL mapping, you'd have to have one mapping action method that determined which operation actually needed to be performed, based (presumably) on the POST parameter values.



That makes sense. If it's only one page with the same url always would probably work.
Doesn't solve for the situation in the original question of this post (when there are two forms with one url for each).
 
Jf Okeeffe
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Himai Minh wrote:Hi, jk fe
How about trying this:



Hi Himai,

Thanks for your suggestion.

I tried that code but didn't work.
If I add @RequestMapping(value="form2") at the class level, form1 doesn't open anymore.

Also, removing value = "/saveform1" from the RequestMapping at the method level I guess that method won't be found. Because the way it is found is because at the form level there's this code:
<form action="saveform1" method="post">
and at the method level there's this:
@RequestMapping(method = RequestMethod.POST, value = "/saveform1")

So not sure I understand what you mean.

Thanks again.
 
Tim Holloway
Saloon Keeper
Posts: 22801
153
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK, let's re-accent things. URL stands for Uniform Request locator. That is, a client sends a URL request to the server and the server sends back a response. Your URL is NOT what comes out, it's what goes IN.

If your forms are on an HTML template page rendered from the static HTML resource /formtofill.html, and there are 2 forms on that HTML template resource, each form has a METHOD (GET/POST) and an ACTION (the form action URL). There's nothing that says each of the forms has to have a unique action URL, and there's nothing that says that actually says that the action URL cannot be "formtofill.html".

There is a small problem, however, in that a URL can name a static resource or a dynamic resource (servlet or JSP), but not both. An incoming URL request can be routed by the server to only one resource. And static HTML pages have no logic capabilities to process the form data.

So you could map a servlet to URL /formtofill.html, but then it then the servlet would have to construct the HTML itself, even if it's just by locating a template form somewhere else and copying that form to the servlet response stream.

What you're describing actually sounds like a Single Page Application (SPA), which is a popular paradigm right now, but SPA's are usually built on some sort of framework such as REACT.
 
Jf Okeeffe
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Tim,

It's not a single page. I have two .htmls. Each one with a single form.

Let me place some more code here to make it more clear.

Form1.html



Controller1.java



Form2.html



This is how the flow goes:
1. The user types http://localhost:8080/form1 and clicks enter
2. start controller mapping method receives the request and returns form1.html to the user
3. The url "http://localhost:8080/form1" is correctly displayed to the user
4. User fills the form data and clicks save
5. savePerson controller mapping method receives the request, saves the data in the db and generates a modelandview to bind in form2
6. form2 is displayed to the user showing some of the info that comes from the object personobj (like person_id and person_name) from the modelandview. User could then fill this second form and save it as well.

That whole flow works like a charm. Except from one thing.
When form2 is displayed to the user (step6), the user is looking at the second form to fill. But if he looks at the url at the top, the url is http://localhost:8080/saveform1 (which is the value in the RequestMapping), when in fact I'd like it to show http://localhost:8080/form2, because he is looking at the fields from form2. So the url should reflect that. Just like it did on step 3 for form1.

Hope what I need is more clear now. Thank you.
 
Marshal
Posts: 26135
77
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

jk fe wrote:When form2 is displayed to the user (step6), the user is looking at the second form to fill. But if he looks at the url at the top, the url is http://localhost:8080/saveform1 (which is the value in the RequestMapping), when in fact I'd like it to show http://localhost:8080/form2, because he is looking at the fields from form2. So the url should reflect that. Just like it did on step 3 for form1.



Well, no. If the form is going to send a request to http://localhost:8080/form2, it makes no sense for that URL to appear in the browser's address bar. That URL should appear after the request is sent.

And anyway, users don't look at the address bar to see where the request is going to be sent to. For one thing the contents of the address bar don't tell you that. And more importantly, they look at the contents of the form to see what it's supposed to be sending. If you find they have to look at the address bar for more information then your form is seriously defective and needs to be fixed by providing useful information.
 
Jf Okeeffe
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Paul,

I respect your position. But I prefer to do it a little different.

Let's say form1.html is really called "adduserphones.html" and form2.html is called "addusereducation.html".

When the user is at form2(filling the fields from addusereducation.html) he should be looking at the url http://localhost:8080/addusereducation, not the url http://localhost:8080/saveuserphones.

It's what makes more sense in my understanding.

It should be as if http://localhost:8080/addusereducation was directly typed at the url and pressed enter.

I agree when you say that users shouldn't need to look at the url address bar. What is more important obviously is the page content. But I personaly like my address bar to reflect the content on the page. So, would like to design my app that way.

So the point here is just to ask if it is possible or not with spring mvc. And if it's possible, how to do it.
 
Jf Okeeffe
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But I'm new to spring mvc. So am open to learn how other seasoned spring mvc developers design their apps in this sense.

Would you guys leave http://localhost:8080/saveuserphones at the url in this case or would you prefer to do the same I'm trying to achieve (address bar show the url of the hmtl that is actually being displayed)?

Or is there any other better recommended design for this kind of thing?
 
Paul Clapham
Marshal
Posts: 26135
77
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

jk fe wrote:But I personaly like my address bar to reflect the content on the page. So, would like to design my app that way.



The address bar does indeed reflect the content on the page. It reflects where the page came from, that's how HTML works. If you want it to reflect where a form on the page is going to send you, then you'd have to contact the standards body who made it work the way it works now and argue your case with them. This is not just "my position" to be respected or not, that's how it works.

What would you like to see in the address bar for a page with more than one form? Perhaps the targets for all forms in the page separated by spaces or something? And a page which doesn't have any forms? A blank address bar? And if some Javascript code later changed the target for a form, should the address bar change to match that? I'm not asking you that because the standards body is going to fix it for you, I'm asking so that you can see why your idea doesn't work.
 
Paul Clapham
Marshal
Posts: 26135
77
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I should mention that when I first started writing web applications, I had the same confusion in my mind. There are HTML pages which appear in the browser, and there are components (servlets back then) which process the request from one HTML page and send out another HTML page. My brain kept trying to identify a servlet with an HTML page and it did take me a while to realize the right way to do that.

Think of it this way: a servlet may be requested by more than one HTML page. (You might have several pages with a "Change my profile" link for example.) But it can only output one HTML page. So you should be identifying your server components with the HTML page that they write, not with the HTML page that requests them. That makes the address bar unhelpful, it's true, but that's just the way it is.
 
Himai Minh
Bartender
Posts: 1979
13
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, Paul ,
Thanks for your clarification.
That means I can build multiple controllers using different paths
like these:

and

Spring MVC will dispatch our requests localhost:8080/login and localhost:8080/forums to the correct "C" (controller) and the correct get or post method.
Once the requested method has been executed, the "V" (view) of Spring MVC will display the "M" (model) .
It all happens behind the scene.
 
Jf Okeeffe
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Paul,

Thanks for your insights. They are very helpful.

I should mention I’m new to java/spring mvc but not new to web development.
I come from asp.net c#.

Paul Clapham wrote:The address bar does indeed reflect the content on the page. It reflects where the page came from, that's how HTML works.



I agree. And that is what I want. Don’t want to do nothing different than what http/html standards provide.

If we use simple html this is how it would work.

Form1.html
<form action="form2.html" method="post">
<input type="submit" value="Submit"/>

Form2.html
<body>
Form2.html is open and the url displayed is /form2.html
</body>

1. User types .../form1.html at the browser and clicks enter
2. form1.html content is displayed and url correctly is /form1.html (as that was the requested url).
3. User clicks the submit button
4. Form2.html content is opened and the url /form2.html is correctly displayed

The final outuput is the form2.html content and a matching url (http://localhost:8080/form2).
So it works just as I want.


The thing is that with Spring MVC, you add one additional step (the controller in the middle).
1. User types .../form1.html at the browser and clicks enter
2. form1.html content is displayed and url correctly is /form1.html (as that was the requested url).
3. User clicks the submit button.
4. Form action submits the form not to form2.html directly, but to a spring mvc controller on the server side. <form action="saveform1" method="post">.
5. Controller method that maps “saveform1” is called (controller method with the modelandview code I sent previously), processes code (saves data to db...), and finally calls form2.html with the following code:
ModelAndView modelAndView = new ModelAndView("form2");
6. Form2.html is correctly presented to the user, binding data from the object in the controller. But the url is what’s mapped in the controller (http://localhost:8080/saveform1), not the html that was called inside the controller (http://localhost:8080/form2).


So the additional spring mvc method (controller) makes the post request of the button make two calls instead of one (saveform1 first and form2 second).
And for it to have the same end result to the user(as it had on pure html) I think http://localhost:8080/form2 should be the final displayed url to the user (as that is what was lastly requested in this process and is what is being finally displayed).

So I understand this is a Spring MVC thing and how it is implemented, not a http/html thing that would need to be changed.

For instance, if we go to asp.net this is how the flow goes.

1. User types .../form1.aspx at the browser and clicks enter
2. form1.aspx content is displayed and url correctly is /form1.aspx (as that was the requested url).
3. User clicks the submit button.
4. A button onclick event is called on the server side to execute whatever you want. Just like you would do at the spring mvc controller (for instance, saving some data on the db). Then you can redirect the user to form2 with a Response.Redirect("/form2.aspx").
5. form2.aspx content is returned to the user and the url displayed is http://localhost:8080/form2.aspx (not a url in the middle like /saveform1).

I just want to do the same here.

And asp.net uses the same http protocol.
That’s why I understand this is more of a Spring MVC thing and how to use it, than a need to change html or http protocol.

Anyways, after some digging I’m glad to say I found out how to make this work on Spring MVC! I knew there should be a way to do it

In fact, it's pretty simple.

You just need to add a @ModelAttribute annotation to the controller method, add the saved object to that using addFlashAttribute and do a return "redirect:/form2". Then on Form2 controller retrieve the object from @ModelAttribute, bind to the form2.html and return form2. That will display form2 fields (filled with the object data) and also show form2 url (as it is supposed to since form2 is what was requested to the server). Gotcha!

Anyways, I appreciate you guys time and willingness to help.

As I said, I'm new to spring mvc and will certainly come back for more help from you guys in the future.

This was a great discussion. Appreciate anything else you have to add.

Best regards.
 
Tim Holloway
Saloon Keeper
Posts: 22801
153
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Paul Clapham wrote:The address bar does indeed reflect the content on the page. It reflects where the page came from, that's how HTML works.


NonononoNO! It's the request locator, not the response locator!

What you see in the navigation control is the URL that was last sent to the server. It is set in the following ways:

A) The user types in an explicit URL
B) Page logic (e.g., Javascript) assigns a value (URL string) to the page location property.
C) An HTML FORM submit is done.

Once set and triggered, that URL is sent to the server. And I guess I need to trot out that old maxim:

A web server is not a file server.

Every URL sent to a J(2)EE webapp server is a software service request. If the request maps to a servlet, the servlet receives the request verbatim. If the request maps to a JSP, the server locates the associated JSP, compiles it into a servlet, if necessary and then the JSP servlet receives the request verbatim. If the URL path maps to neither a servlet or a JSP, then a Default Servlet (built into the webapp server itself) extracts the resource path part of the URL, looks up that resource (for example, an HTML page template), and (if found) copies it to the HTTP response stream. The navigation control on the client side remains unaffected and, again, reflects, the request, not the response. Attempts to change the display by using a page-load JavaScript assignment to location will result in frustration, since doing so will trigger a submit. The location bar is an input control, not a display control.

Aside from that, let me caution that apps that contain their own login code should generally consider themselves as pre-hacked. Where possible, use the JEE standard login service, or failing that, something proven like Spring Security.
 
Ranch Hand
Posts: 65
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello
you can set URL name using bellow syntax

@RequestMapping(value = "/login", method = ResquestMethod.POST)
public String handleLogin([...]) {
   ...
   if (successful) {
       return "redirect:/welcome"
   }
}

I hope this will help you
 
Paul Clapham
Marshal
Posts: 26135
77
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It's true: If your code redirects to a different URL, then the response will come from that URL and that URL will appear in the browser's address bar above the contents of the response. And it looks like that's what JK wanted to do (I saw the word "redirect" in one of their posts). But it also looks like they have their (possibly more complicated) problem sorted out too.
 
Tim Holloway
Saloon Keeper
Posts: 22801
153
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That will indeed give the desired result. There is a cost, however.

Here, too, the URL indicates a request, not a response. What actually happens is that the server's response to a request is a 300-series HTTP Response Code value. I think in this particular case it's always a 303, which returns the new URL and tells the client to use it as an HTTP GET request.

That's the cost. Instead of one request/response cycle, you have 2: one to handle the form, one to GET the post-processing page. And with a 303, you cannot do POST, just GET.

That means that you want good throughput times on both network and server, since it's a double-request, and you'll want to make sure that there are no security considerations if the 303 response value gets hacked.

But it will display the desired text in the navigation bar, since it's a browser-internal equivalent of setting the page location property. And, again, it will send an HTTP request to the server for that URL and process a resp[onse, because, once and for all, the location control is an input control, not an output control.


One further note about the "redirect" directive. JEE standard security does not protect resources, it protects URLs. So if you have 2 different URLs, both of which return "supersecretplans.doc", and you only setup security restrictions to one of those URLs in your web.xml, then the other URL would provide unrestricted access to supersecretplans.doc. As I mentioned, in JavaServer Faces, the URL is not an absolute locator as much as it is a session handle, and it lags behind on requests, meaning that ordinarily a request from an unsecured URL (handle) would be able to access secured resources. In this case, one codes a redirect on the JSF navigation return value to force the client to request the secured URL instead.
 
Jf Okeeffe
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Ishan,

Yes, that's pretty much what I did, with the addition of @ModelAttribute to be able to pass the object to the second method controller. Worked as needed.

Thank you all for your contributions.
 
To avoid criticism do nothing, say nothing, be nothing. -Elbert Hubbard. Please critique this tiny ad:
the value of filler advertising in 2020
https://coderanch.com/t/730886/filler-advertising
reply
    Bookmark Topic Watch Topic
  • New Topic