I'm using spring mvc. And I can't get param from url when method = post. But when I change method to GET, so I can get all param.
This is my form:
<form method="POST" action="http://localhost:8080/cms/customer/create_customer" id="frmRegister" name ="frmRegister" enctype="multipart/form-data">
<input class ="iptRegister" type="text" id="txtEmail" name="txtEmail" value="" />
<input class ="iptRegister" type="password" id="txtPassword" name="txtPassword" value="" />
<input class ="iptRegister" type="text" id="txtPhone" name="txtPhone" value="" />
<input type="button" id="btnRegister" name="btnRegister" value="Register" onclick="" style="cursor:pointer"/>
</form>
This is my controller:
#RequestMapping(value= "/create_customer", method = RequestMethod.POST)
#ResponseBody
public String createCustomer(HttpServletRequest request,
#RequestParam(value="txtEmail", required=false) String email,
#RequestParam(value="txtPassword", required=false) String password,
#RequestParam(value="txtPhone", required=false) String phone){
ResultDTO<String> rs = new ResultDTO<String>();
rs.setStatus(IConfig.SHOW_RESULT_SUCCESS_ON_MAIN_SCREEN);
try{
Customer c = new Customer();
c.setEmail(email);
c.setPassword(password);
c.setPhone(phone);
customerService.insert(c);
rs.setData("Insert success");
}catch(Exception ex){
log.error(ex);
rs.setStatus(IConfig.SHOW_RESULT_ERROR_ON_MAIN_SCREEN);
rs.setData("Insert failure");
}
return rs.toString();
}
How can I resolved this?
Spring annotations will work fine if you remove enctype="multipart/form-data".
#RequestParam(value="txtEmail", required=false)
You can even get the parameters from the request object .
request.getParameter(paramName);
Use a form in case the number of attributes are large. It will be convenient. Tutorial to get you started.
Configure the Multi-part resolver if you want to receive enctype="multipart/form-data".
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="250000"/>
</bean>
Refer the Spring documentation.
It also works if you change the content type
<form method="POST"
action="http://localhost:8080/cms/customer/create_customer"
id="frmRegister" name="frmRegister"
enctype="application/x-www-form-urlencoded">
In the controller also add the header value as follows:
#RequestMapping(value = "/create_customer", method = RequestMethod.POST, headers = "Content-Type=application/x-www-form-urlencoded")
When I want to get all the POST params I am using the code below,
#RequestMapping(value = "/", method = RequestMethod.POST)
public ViewForResponseClass update(#RequestBody AClass anObject) {
// Source..
}
I am using the #RequestBody annotation for post/put/delete http requests instead of the #RequestParam which reads the GET parameters.
You should use #RequestParam on those resources with method = RequestMethod.GET
In order to post parameters, you must send them as the request body. A body like JSON or another data representation would depending on your implementation (I mean, consume and produce MediaType).
Typically, multipart/form-data is used to upload files.
Related
I am beginner for Java and REST API. I have a problem passing form data from HTML to rest PUT method. When I google about this, most solutions available are for POST method, that recommended to use FormParam. In my case, it shows below error:
The method received in the request-line is known by the origin server but not supported by the target resource.
Even I use PathParam, same error is returned:
The method received in the request-line is known by the origin server but not supported by the target resource.
And some solution for Spring Boot. But I did not use that.
PUT method:
#PUT
#Path("/update")
#Produces(MediaType.TEXT_HTML)
public String updCard(#PathParam("cardNo") String cardNo,
#PathParam("reportId") int reportId
) throws SQLException {
Card c = new Card(cardNo, reportId);
System.out.println(cardNo + reportId);
return "";
}
Form:
<form method="PUT" action="rest/card/update">
<label for = "cardNo">Card No: </label> <input type="text" name = "cardNo" id = "cardNo"><br/>
<label for = "reportId">Report Id:</label> <input type="text" name = "reportId" id = "reportId"> <br/>
<button type="submit">Update</button>
So, how do I get the form data in PUT method in Jersey?
As mentioned by many in Using PUT method in HTML form, PUT is not currently supported by the HTML standard. What most frameworks will do is offer a workaround. Jersey has such a workaround with its HttpMethodOverrideFilter. What you must do is use a POST method and add a _method=put query parameter and the filter will switch the POST to a PUT.
You first need to register the filter. If you are using a ResourceConfig just do
#ApplicationPath("api")
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
...
register(HttpMethodOverrideFilter.class);
}
}
If you are using a web.xml, then do
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.server.filter.HttpMethodOverrideFilter</param-value>
</init-param>
Then in your HTML, you will just add the _method=put query param to the URL. Below is an example I used to test
<form method="post" action="/api/form?_method=put">
<label>
Name:
<input type="text" name="name"/>
</label>
<label>
Age:
<input type="number" name="age"/>
</label>
<br/>
<input type="submit" value="Submit"/>
</form>
And in your resource method you will use #PUT and #FormParams for the paramters
#PUT
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response form(#FormParam("name") String name,
#FormParam("age") String age,
#Context UriInfo uriInfo) {
URI redirectUri = UriBuilder
.fromUri(getBaseUriWithoutApiRoot(uriInfo))
.path("redirect.html")
.queryParam("name", name)
.queryParam("age", age)
.build();
return Response.temporaryRedirect(redirectUri).build();
}
private static URI getBaseUriWithoutApiRoot(UriInfo uriInfo) {
String baseUri = uriInfo.getBaseUri().toASCIIString();
baseUri = baseUri.endsWith("/")
? baseUri.substring(0, baseUri.length() - 1)
: baseUri;
return URI.create(baseUri.substring(0, baseUri.lastIndexOf("/")));
}
It should work from what I tested
I have some input fields in my jsp page,l want to know is it possible for values passed in those fields to be passed as URL.
I tried using #RequestParam and #PathVariable on same variable to try to retrive it and put it as URI but it didnt work
This is my jsp page form:
<body>
<form action="welcome/" method="post">
<input type="text" name="name" value="">
<input type="submit" value="go">
</form>
</body>
And this is my Controller handler method:
#PostMapping(value = "/welcome/{name}")
public String welcomeAgain(#PathVariable #RequestParam("name")String name){
return "welcome";
}
Just use #PathVariable("name") annotation. Exclude the #RequestParam annotation from your function.
I hope it helps.
To get the value passed in URL you can use #PathVariable normally with GET request.
http://localhost:8080/user/101
#RequestParam normally used with POST request for accessing the query parameter values
http://localhost:8080/user/101?param1=10¶m2=20
#PostMapping(value = "/welcome/{name}")
public String welcomeAgain(#PathVariable("name") String name){
return "welcome " + name;
}
i've a spring MVC application and when i try to upload a multipart file, a null value is passed to the controller. all the other text parameters are passed properly only the file input is passed as null. I've included the MultipartResolver bean and commons-io plus commons-fileupload dependencies in my project. i've checked it's passed in the browser's request but it's not bound in the modelAttribute.
here is a snippet code from my view
<form:form method="post" enctype="multipart/form-data" action="${pageContext.request.contextPath}/profile/secure/saveIdentity" commandName="profileModel">
<span><b>Upload your passport photo</b></span>
<form:input path="passportPhotograph" type="file" id="passportPhoto"/>
</form:form>
and here is a snippet from my controller method
#RequestMapping(value = "/secure/saveIdentity", method = RequestMethod.POST)
public ModelAndView saveIdentity(#ModelAttribute("profileModel") #Valid ProfileModel profileModel,HttpServletRequest request){
MultipartFile photo = profileModel.getPassportPhotograph();
if(photo != null){ do something.... }
}
here is my ProfileModel.java class snippet
public class ProfileModel{
private MultipartFile passportPhotograph;
public MultipartFile getPassportPhotograph() {
return passportPhotograph;
}
public void setPassportPhotograph(MultipartFile passportPhotograph) {
this.passportPhotograph = passportPhotograph;
}
............
}
And in my dispatcher-servlet file I have declared MultipartResolver bean:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="99999999999"/>
</bean>
and finally in my build.gradle file i added these dependencies
compile('commons-io:commons-io:2.0.1')
compile('commons-fileupload:commons-fileupload:1.3.1')
after all this it's passing null to my controller even though it's included in the HttpServletRequest. what should i do to fix this. Thanks in advance for you help.
you need to use #RequestMapping(value = "/secure/saveIdentity", method = RequestMethod.POST, headers = ("content-type=multipart/*"), produces = "application/json", consumes = "image/*").
Solved my issue by using the StandardServletMultipartResolver which comes with the spring web framework. But you have to use Servlet version 3.0+ for this to work.
This sample code. point is input tag name binding file in model. maybe you need library json and file. ex) commons-io, commons-fileupload and jackson, gson use to parsing in controller.
HTML
<form:form method="post" enctype="multipart/form-data" action="${pageContext.request.contextPath}/profile/secure/saveIdentity">
<span><b>Upload your passport photo</b></span>
<form:input type="file" name="file"/>
</form:form>
Controller
#RequestMapping(value = "test", method = RequestMethod.POST)
public String testFormData(FileAndContentModel model) {
// break point and check model.
return "success";
}
Model
public class FileAndContentModel {
private MultipartFile file;
public FileAndContentModel () {
}
// getter, setter
}
This is not the solution, I just type here because is easier to read than a comment. Please try the minimum requeriment, just upload a file and verify if works.
Form:
<form:form method="post" enctype="multipart/form-data" action="${pageContext.request.contextPath}/profile/secure/saveIdentity">
<span><b>Upload your passport photo</b></span>
<input name="file" type="file" id="passportPhoto"/>
</form:form>
Controller:
#RequestMapping(value = "/secure/saveIdentity", method = RequestMethod.POST)
public void saveIdentity(#RequestParam("file") MultipartFile file) {
//please verify here if the file is null
I am getting the following warning:
Request method 'POST' not supported.
Controller method:
#Controller
public class UserServiceController {
#RequestMapping(value = "/login", method = RequestMethod.POST)
#Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public String login(#RequestParam Map<String,String> requestParams) throws Exception{
System.out.println(requestParams.values());
loginService.userAuthentication(requestParams.get("loginuname"), requestParams.get("loginpassword"));
System.out.println("Before return");
return "static/profile.html";
}
}
Dispatcher-servlet.xml
<mvc:resources mapping="/static/**" location="/WEB-INF/static/" />
index.html
<script language="javascript" type="text/javascript">
function submitForm(){
document.login.submit();
}
</script>
<div id="login" class="login">
<form action="http://localhost:8080/SampleApp/login" name="login" method="post">
<input type="text" value = "Email" name="loginuname" id="loginuname" class="loginbasetxt">
<input type="text" value="Password" name="loginpassword" id="loginpassword" class="loginbasetxt">
<img src="static/img/tb-login-button.png" onclick="submitForm()"/>
</form>
</div>
However, if i would change the method=RequestMethod.GET and correspondingly at login page then it would work.
Please note, problem is at return "static/profile.html";
FYI location of profile.html is WEB-INF/static/
Thanks!!
When you POST a form to an HTTP server, the form's contents aren't sent as query parameters; instead, the form is (usually) uploaded as an entity of type application/x-www-form-urlencoded. Instead of using #RequestParam in your method, define a Java class that has fields corresponding to the form fields, and use #ModelAttribute FormClass form.
you should try this:
return "forward:/static/profile.html";
Im getting this error: HTTP Status 405 - Request method 'POST' not supported
What I am trying to do is make a form with a drop down box that get populated based on the other value selected in another drop down box. For example when I select a name in the customerName box the onChange function in the .jsp page should be run and the page submitted then loaded again with the corresponding values in the customerCountry box.
however I'm getting this HTTP Status 405 error. I have searched the internet for a solution but haven't been able to find anything that helped. Here is the relevant parts of my code:
part of jsp page
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<style>
.error { color: red; }
</style>
<script>
function repopulate(){
document.deliveryForm.submit();
}
function setFalse(){
document.getElementById("hasId").value ="false";
document.deliveryForm.submit();
// document.submitForm.submit(); (This was causing the error)
}
</script>
</head>
<body>
<h1>Create New Delivery</h1>
<c:url var="saveUrl" value="/test/delivery/add" />
<form:form modelAttribute="deliveryDtoAttribute" method="POST" action="${saveUrl}" name="deliveryForm">
<table>
<tr>
<td><form:hidden id="hasId" path="hasCustomerName" value="true"/></td>
</tr>
<tr>
<td>Customer Name</td>
<td><form:select path="customerName" onChange="repopulate()">
<form:option value="" label="--- Select ---" />
<form:options items="${customerNameList}" />
</form:select>
</td>
<td><form:errors path="customerName" cssClass="error" /></td>
</tr>
<tr>
<td>Customer Country</td>
<td><form:select path="customerCountry">
<form:option value="" label="--- Select ---" />
<form:options items="${customerCountryList}" />
</form:select>
</td>
<td><form:errors path="customerCountry" cssClass="error" /></td>
</tr>
</form:form>
<form:form name="submitForm">
<input type="button" value="Save" onClick="setFalse()"/>
</form:form>
</body>
</html>
part of controller:
#RequestMapping(value = "/add", method = RequestMethod.GET)
public String getDelivery(ModelMap model) {
DeliveryDto deliveryDto = new DeliveryDto();
model.addAttribute("deliveryDtoAttribute", deliveryDto);
model.addAttribute("customerNameList",
customerService.listAllCustomerNames());
model.addAttribute("customerCountryList", customerService
.listAllCustomerCountries(deliveryDto.getCustomerName()));
return "new-delivery";
}
// I want to enter this method if hasId=true which means that a value in the CustomerName
// drop down list was selected. This should set the CountryList to the corresponding values
// from the database. I want this post method to be triggered by the onChange in the jsp page
#RequestMapping(value = "/add", method = RequestMethod.POST, params="hasCustomerName=true")
public String postDelivery(
#ModelAttribute("deliveryDtoAttribute") DeliveryDto deliveryDto,
BindingResult result, ModelMap model) {
model.addAttribute("deliveryDtoAttribute", deliveryDto);
model.addAttribute("customerNameList",
customerService.listAllCustomerNames());
model.addAttribute("customerCountryList", customerService
.listAllCustomerCountries(deliveryDto.getCustomerName()));
return "new-delivery";
}
// This next post method should only be entered if the save button is hit in the jsp page
#RequestMapping(value = "/add", method = RequestMethod.POST, params="hasCustomerName=false")
public String postDelivery2(
#ModelAttribute("deliveryDtoAttribute") #Valid DeliveryDto deliveryDto,
BindingResult result, ModelMap model) {
if (result.hasErrors()) {
model.addAttribute("deliveryDtoAttribute", deliveryDto);
model.addAttribute("customerNameList",
customerService.listAllCustomerNames());
model.addAttribute("customerCountryList", customerService
.listAllCustomerCountries(deliveryDto.getCustomerName()));
return "new-delivery";
} else {
Delivery delivery = new Delivery();
//Setters to set delivery values
return "redirect:/mis/home";
}
}
How come I get this error? Any help would be much appreciated! Thanks
EDIT: Changed hasId to hasCustomerName. I still get the HTTP Status 405 - Request method 'POST' not supported error though.
EDIT2: Commented out the line in the setFalse function that was causing the error
// D
I am not sure if this helps but I had the same problem.
You are using springSecurityFilterChain with CSRF protection. That means you have to send a token when you send a form via POST request. Try to add the next input to your form:
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
Check if you are returning a #ResponseBody or a #ResponseStatus
I had a similar problem. My Controller looked like that:
#RequestMapping(value="/user", method = RequestMethod.POST)
public String updateUser(#RequestBody User user){
return userService.updateUser(user).getId();
}
When calling with a POST request I always got the following error:
HTTP Status 405 - Request method 'POST' not supported
After a while I figured out that the method was actually called, but because there is no #ResponseBody and no #ResponseStatus Spring MVC raises the error.
To fix this simply add a #ResponseBody
#RequestMapping(value="/user", method = RequestMethod.POST)
public #ResponseBody String updateUser(#RequestBody User user){
return userService.updateUser(user).getId();
}
or a #ResponseStatus to your method.
#RequestMapping(value="/user", method = RequestMethod.POST)
#ResponseStatus(value=HttpStatus.OK)
public String updateUser(#RequestBody User user){
return userService.updateUser(user).getId();
}
You might need to change the line
#RequestMapping(value = "/add", method = RequestMethod.GET)
to
#RequestMapping(value = "/add", method = {RequestMethod.GET,RequestMethod.POST})
The problem is that your controller expect a parameter hasId=false or hasId=true, but you are not passing that. Your hidden field has the id hasId but is passed as hasCustomerName, so no mapping matches.
Either change the path of the hidden field to hasId or the mapping parameter to expect hasCustomerName=true or hasCustomerName=false.
I found the problem that was causing the HTTP error.
In the setFalse() function that is triggered by the Save button my code was trying to submit the form that contained the button.
function setFalse(){
document.getElementById("hasId").value ="false";
document.deliveryForm.submit();
document.submitForm.submit();
when I remove the document.submitForm.submit(); it works:
function setFalse(){
document.getElementById("hasId").value ="false";
document.deliveryForm.submit()
#Roger Lindsjö Thank you for spotting my error where I wasn't passing on the right parameter!
I was getting similar problem for other reason (url pattern test-response not added in csrf token)
I resolved it by allowing my URL pattern in following property in config/local.properties:
csrf.allowed.url.patterns = /[^/]+(/[^?])+(sop-response)$,/[^/]+(/[^?])+(merchant_callback)$,/[^/]+(/[^?])+(hop-response)$
modified to
csrf.allowed.url.patterns = /[^/]+(/[^?])+(sop-response)$,/[^/]+(/[^?])+(merchant_callback)$,/[^/]+(/[^?])+(hop-response)$,/[^/]+(/[^?])+(test-response)$
In my case the url was ending with /
paymentUrl(old)= /get-details/
i just removed the trailing /
paymentUrl(new)= /get-details
and it worked