Trouble with getting form data using Spring - java

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.

Related

Consistent error: Neither BindingResult nor plain target object for bean name 'flow' available as request attribute

I'm using Thymeleaf and Spring Boot to try and send data to a server, but I can't even load the page because any instance of th:field results in that error.
HTML form template is here:
<form action="#" method="post" th:action="#{/flow}" th:object="${flow}" id="myForm">
<input type="text" name="mouseX" th:field="*{xpos}"id="mouseX" value="0">
<input type="text" name="mouseY" th:field="*{ypos}" id="mouseY" value="0">
<button type="submit">submit</button>
</form>
Controller is here:
public class MainController {
#GetMapping("flow")
public String generateImg(Model model, BindingResult br) {
model.addAttribute("Flow", new Flow());
return "flow";
}
#PostMapping("flow")
public String imgGen( #ModelAttribute("flow") Flow flow, Model model, BindingResult br) {
return "flow";
}
}
I've tried a couple different things, adding and removing parameters, renaming my object, changing form action, and none seem to have any effect.

Form data to rest PUT method in 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

Spring MVC, make a button, upon click, return a string value

I am still relatively new to springMVC, I currently have some code, that will take an input from a <form:input> on a jsp page, and create different lists depending on the input(providing I enter the correct String). I would like to transition this into a button instead, so I could have four buttons that will return a different String, for example "one", "two", "three" and "four". That way there is no typing needed from the user.
I see that there is a <form:button> available but I do not know how I could return the String value from this. Also I have looked into angularJS and seen that you can call a function onClick. But again, I don't know what the implementation would have to be to tie it into my Controller. I am just not really sure how I can implement this. Any help would be appreciated.
This is what I have being implemented at the moment :
<form:form commandName="input">
<label>Enter Value</label>
<form:input path="listType" class="inputbox" />
<br>
<input type="submit" class="button" value="Enter" />
</form:form>
This takes the input and stores it in an object :
#Controller
#SessionAttributes("input")
public class EventController {
#RequestMapping(value = "/event", method= RequestMethod.GET)
public String displayEvent (Model model) {
AccessInput userInput = new AccessInput();
model.addAttribute("input", userInput);
System.out.println("finished get method");
return "event";
}
#RequestMapping(value = "/event", method= RequestMethod.POST)
public String processEvent(#ModelAttribute("input")AccessInput userInput) {
System.out.println(userInput.getListType()); //just so I know what value it has
return "redirect:results.html";
}
This is the controller that creates my list based on the string that I pass through to the object
#RestController
#SessionAttributes("input")
public class ReportController {
#RequestMapping(value="/events")
public List<Appliance> getEvents(#ModelAttribute("input")AccessInput userInput) {
List<Appliance> events = new ArrayList<>();
events = ProcessChoice.ofList(userInput.getListType());
System.out.println(userInput.getListType());
return events;
}
}
Edit:
Just to note I have resolved this, I followed the example given by Vipin Dubey, I had to change my controller. I removed the POST method and added in a #RequestParam as a parameter, and redirected the buttons on the event.jsp to "results.html?input=one" then took this value and added it to my model to store it in the session.
#Controller
#SessionAttributes("URLparam")
public class ResultController {
#RequestMapping(value = "/results.html", method = RequestMethod.GET)
public String buttonSelect(Model model, #RequestParam("input")String input) {
model.addAttribute("URLparam", input);
System.out.println(input);
return "result";
}
}
You have two options :
1. Short and recommended way :
Use a link and style it as a button and you can directly call your controller
<a class="btn" href="/events?input=one">One</a>
<a class="btn" href="/events?input=two">two</a>
<a class="btn" href="/events?input=three">three</a>
<a class="btn" href="/events?input=four">four</a>
2. Use jQuery or JavaScript to submit the form based on clicked button using a hidden input field in your form
<!-- Buttons with classes -->
<div id="target">
<button class="one">One</button>
<button class="two">two</button>
<button class="three">three</button>
<button class="four">four</button>
</div>
<!-- Your form -->
<form:form commandName="input" id="myForm">
<input type="hidden" name="inputbox" id="inputbox" value=""/>
</form:form>
// You will have to do this for each of the button which is not a recommended way
$( ".one" ).click(function() {
$('input[name="inputbox"]').val("one");
//var a = $('input[name="inputbox"]').val();
//alert(a);
$( "#myForm" ).submit();
});

How to retrieve input text from thymeleaf?

I am trying to get a value from thymeleaf input into my java class.
Simple script from thymeleaf
<h1>Form</h1>
<form action="#" th:action="#{index}" th:object="${emails}" method="post">
<p>Emails: <input id="emailbox" type="text" th:field="*{email}"
placeholder="Enter e-mails: eg; Foo#gmail.com, Bar#yahoo.com"/></p>
<p><input type="submit" value="Submit"/> <input type="reset" value="Reset"/></p>
</form>
How would I be able to retrieve the inputted text into my java class?
Controller
#Controller
public class IndexController {
#RequestMapping(value = "/index", method = RequestMethod.GET)
public ModelAndView getdata() throws IOException {
ModelAndView model = new ModelAndView("index");
model.addObject("emails", new MailModel());
return model;
}
#PostMapping("/index")
public String emailSubmit(#ModelAttribute MailModel emails) {
System.out.println(emails.getEmail());
return "index";
}
I am able to run my application and see thymeleaf view. When I enter some text into the text box and hit submit. I receive an error.
Error Message
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'emails' available as request attribute
My Application is created with Springboot, Java, and Thymeleaf. What am I doing wrong? Is it possible that ModelandView does not work with PostMapping? I also followed https://spring.io/guides/gs/handling-form-submission/ and I got that sample working, but when I tried to follow the logic and implement into my project. It did not work.
In your HTML, change th:action="#{index}" to th:action="#{/index}". This will allow Thymeleaf to resolve it properly.

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.

Categories