Form data to rest PUT method in java - java

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

Related

How to put RequestParam value as URL

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&param2=20
#PostMapping(value = "/welcome/{name}")
public String welcomeAgain(#PathVariable("name") String name){
return "welcome " + name;
}

Spring MVC - How do I call the same URL with different mapping annotations

I have set up a Controller with two methods. The URL mappings are exactly the same, and the only difference is the mapping annotation method. One is #PostMapping and the other #DeleteMapping written in that order. However, when I try to call the #DeleteMapping method, the #PostMapping method is called.
Note that even though variables in the two URL forms are different, they have the same values. They are just from different HTML pages.
The question is how to call the desired method each time.
#PostMapping method
#Secured({"ROLE_ADMIN", "ROLE_STUDENT"})
#PostMapping("students/{username}/internships/{id}")
public String addInternship(Model model, #PathVariable("username") String username, #PathVariable("id") int id) {
/* DOES SOME STUFF
Student student = userService.getUser(username).getStudent();
Internship internship = userService.getInternship(id);
StudentInternship studentInternship = new StudentInternship(internship, student, "Sent");
internship.setNumberOfPositions(internship.getNumberOfPositions() - 1);
userService.updateInternship(internship);
student.setApplicationNumber(student.getApplicationNumber() + 1);
userService.updateStudent(student);
userService.addStudentInternship(studentInternship);
*/
return "redirect:/internships";
}
#DeleteMapping method
#Secured({"ROLE_ADMIN", "ROLE_STUDENT"})
#DeleteMapping("students/{username}/internships/{id}")
public String removeInternship(Model model, #PathVariable("username") String username, #PathVariable("id") int id) {
/* DOES SOME STUFF
Student student = userService.getUser(username).getStudent();
Internship internship = userService.getInternship(id);
int studentInternshipID = userService.getStudentInternshipByParams(student, internship).getId();
internship.setNumberOfPositions(internship.getNumberOfPositions() + 1);
userService.updateInternship(internship);
student.setApplicationNumber(student.getApplicationNumber() - 1);
userService.updateStudent(student);
userService.removeStudentInternship(studentInternshipID);
*/
return "redirect:/students/" + username + "/internships";
}
HTML
<form:form action="${pageContext.request.contextPath}/students/${username}/internships/${tempInternship.id}" method="POST">
<input type="submit" value="Request" ${disabled}/>
</form:form>
<form:form action="${pageContext.request.contextPath}/students/${tempStudentInternship.student.username}/internships/${tempStudentInternship.internship.id}" method="DELETE">
<input type="submit" value="Dismiss" />
</form:form>
Browsers only support GET and POST as http request methods. The solution is to send your form with the POST method and inject a hidden field inside the same html form called _method with your desired method as a value, in your case here, it is just DELETE. For the case of POST, just write your form as usual.
Example :
<form:form action="${pageContext.request.contextPath}/students/${tempStudentInternship.student.username}/internships/${tempStudentInternship.internship.id}" method="POST">
<input type="hidden" name="_method" value="DELETE"/>
<input type="submit" value="Dismiss" />
</form:form>
Please, have a look at this answer for creating the spring bean and then applying the mentioned form attribute inside spring:form html forms.
Only GET and POST are allowed from a FORM. You need to use AJAX to specify additional types of the request.
Hi you need to use javascript and XMLHttpRequest in order to specify the type of the request.
Here is one example I took randomly from internet:
// Delete a user
var url = "http://localhost:8080/api/v1/users";
var xhr = new XMLHttpRequest();
xhr.open("DELETE", url+'/12', true);
xhr.onload = function () {
var users = JSON.parse(xhr.responseText);
if (xhr.readyState == 4 && xhr.status == "200") {
console.table(users);
} else {
console.error(users);
}
}
xhr.send(null);

Parameters not being passed in POST method REST Java

So, i am developing a web service where when i call api/update action on form submit, two of my inputs from my jsp, "data" and "id" are supposed to pass, on which i want to perform operations in the POST method block.
here is the form calling the method:
<form id="myForm" action="api/update" method="post">
id: <input type="text" id="id" name="id">
<br/>
<textarea id="data" name="data" rows="30" cols="100" placeholder="Empty File"></textarea>
<br/>
<button id="submit" type="submit">Submit</button>
</form>
Here is the REST code:
#Path("update")
public class UpdateResource {
#Context
private UriInfo context;
public UpdateResource() {
}
#Context
private HttpServletRequest request;
#POST
public void putHtml() {
String data = request.getParameter("data");
String id = request.getParameter("id");
System.out.println(id); //<---- line1
System.out.println(data); //<---- line2
//further operations
}
}
The problem is that line1 and line2 gives null as output, means somehow data is not being passed. Am i doing something wrong?
Here is the Header file captured from network tab of chrome browser:
Instead of trying to get the parameters from the HttpServletRequest, use #FormParam
#POST
public void putHtml(#FormParam("id") String id,
#FormParam("data") String data) {
}
The reason is that the entity body is already being read, resulting in the parameters being empty in the HttpServletRequest.

Trouble with getting form data using Spring

I am super new to front end development. I have a simple webapp where you can submit a form, and I want to be able to get the form data in a REST endpoint. I am using Spring boot which contains Spring MVC.
The HTML:
<div class="modal-header modal-header-info">
<button type="button" class="close" data-dismiss="modal"
aria-hidden="true">×</button>
<h4 class="modal-title">Add Entity</h4>
</div>
<div class="modal-body">
<form role="form" method="post" action="/createEntity">
<div class="form-group">
<label for="name">Name:</label> <input type="text"
class="form-control" id="name">
</div>
<button type="submit" class="btn btn-info">Submit</button>
</form>
</div>
The Java:
#RequestMapping(value = "/createEntity", method = RequestMethod.POST)
public void createEntity(#RequestBody String payload) {
System.out.println("Hello world!");
System.out.println(payload);
}
I get this error back:
Failed to read HTTP message:
org.springframework.http.converter.HttpMessageNotReadableException:
Required request body is missing: public void main.java.info.spring.data.neo4j.controllers.CreateEntityController.createEntity(java.lang.String)
How do I get the "name" value from the form? The "hello world" attribute prints out if I take out the #RequestBody part.
Edit: my configuration per request:
#EnableTransactionManagement
#Import(RepositoryRestMvcConfiguration.class)
#EnableScheduling
#EnableAutoConfiguration
#ComponentScan(basePackages = { "main.java.info.spring.data.neo4j.services",
"main.java.info.spring.data.neo4j.controllers" })
#Configuration
#EnableNeo4jRepositories(basePackages = "main.java.info.spring.data.neo4j.repositories")
public class MyNeo4jConfiguration extends Neo4jConfiguration {
public static final String URL = System.getenv("NEO4J_URL") != null ? System.getenv("NEO4J_URL")
: "http://localhost:7474";
#Override
public Neo4jServer neo4jServer() {
return new RemoteServer(URL, "neo4j", "LOL my pass");
}
#Override
public SessionFactory getSessionFactory() {
return new SessionFactory("main.java.info.spring.data.neo4j.domain");
}
}
Problem 1: HTML form controls are missing the name attribute
HTML forms are submitted in name-value pairs. Form controls that do not have a name attribute cannot be submitted because their names are not known. The id attribute is only for referencing controls on the client-side.
<input type="text" class="form-control" id="name">
is missing the name attribute. It should be:
<input type="text" class="form-control" id="name" name="name"/>
This will submit the control as a form parameter in the HTTP request body, something like:
name: [the value you specify for the control]
Problem 2: #RequestBody as a controller method argument will give you the entire HTTP request body
public void createEntity(#RequestBody String payload)
means that you want the entire HTTP request body to be passed as a String to the controller method createEntity. If your HTML form is indeed what you have posted, you will get the following value for payload (after you have addressed problem 1):
name: [the value you specify for the control]
If this is what you want, keep the #RequestBody annotation, but I suspect that you are only interested in the value of the name request parameter. If that is the case, you need to change your method declaration to (after you have addressed problem 1):
public void createEntity(#RequestParam String name)
This will map the HTTP request parameter name to the controller method argument name.
Problem 3: Having void as the return type for a controller method will force Spring MVC to look for a view with the same name as the method name
Since you have the controller method declared as:
public void createEntity(#RequestBody String payload)
Spring MVC will look for a view named createEntity after this method exits. If you have a view with that name, well and good. Otherwise, once you have fixed problems 1 and 2, you will get a 404 - Resource not found error.

how to get param in method post spring mvc?

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.

Categories