I am trying to share data from one server(8081) to another(8082) in Spring Boot using ResponseEntity, but I am not able to built the body.
Here is the code which I have written,
Server 1-
#GetMapping("/redirect")
public ResponseEntity<Void> redirectPgServer(#RequestParam("txnId") String txnId,
#RequestParam("amount") String amount) {
// Redirect to server 2
ProductDetails ref=new ProductDetails();
ref.setTxnId("txnId");
ref.setAmount("amount);
HttpHeaders head = new HttpHeaders();
String url = "http://localhost:8082/redirect-server";
System.out.println(url);
head.setLocation(URI.create(url));
return new ResponseEntity<Void>(ref, head, HttpStatus.FOUND);
}
Server2-
#GetMapping(value = "/redirect-server")
public String validateData(#RequestBody ProductDetails ref)
{
//Server 2 receive data
System.out.println(ref.getAmount());
//Does not gives any output since it throws error Request Body Missing, also if I mention
post mapping above it throws error Request method 'GET' not supported]
return "index"; //Using Thymeleaf for displaying html page.
}
I am able to share the data using only header by manipulating the url and using PathVariable but I want to use Post Mapping as I want to hide the parameters in the Url which are visible to User at Browser. Also I have tried using RestTemplate which brings me back to Server 1 and it throws error- Spring rest template cannot convert from text/html utf8.
My suggestion is to annotate both methods with #PostMapping, in both remove just the #RequestBody Annotation. In the first server you should respond with a 307 HTTP Code (which is the temporary redirect) basically this tells to the browser, to retry the call to another endpoint(which is given into the Location header).
Something like this :
Server 1
#PostMapping(value = "/redirect", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ResponseEntity redirect(Product product) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setLocation(URI.create("http://localhost:8082/product"));
return new ResponseEntity(httpHeaders, HttpStatus.TEMPORARY_REDIRECT);
}
Server 2
#PostMapping(value = "/product", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public void redirect(Product prod) {
System.out.println(prod.getId());
//do your stuff
}
HTML Page
<html>
<body>
<form action="http://localhost:8081/redirect" method="POST">
<input name="id">
<input name="name">
<button type="submit">Send</button>
</form>
</body>
</html>
If you don't use a form, instead you use some kind of async call you MUST specify the url form encoding. Otherwise you will get a 405.
I've tried the code with postman and with a html page it does work correctly. (Tried with Firefox)
If something it's not clear don't esitate to ask.
I have found a similar question where i took inspiration from
A good way to redirect with a POST request?
My issue:
Having a form in a simple HTML, with action="/myController".
I need to send the form data to my Controller and from there I need to make another POST to an external Controller.
<form method="post" action="/myController">
<textarea name="data"></textarea>
</form>
And my Spring Controller looks something like this:
#RequestMapping(method = RequestMethod.GET, value = "/myController")
#ResponseBody
public String myController(#RequestBody MultiValueMap<String, String[]> formData) {
RestTemplate rest = new RestTemplate();
ResponseEntity<String> response = rest.postForEntity("urlPath", formData, String.class);
String manipulatedResult = manipulateResult(response.getBody());
return manipulatedResult;
}
I need to pass form data, to my controller, it should send form data further to the "urlPath" and recieve a response. I need to manipulate that response and return a result.
My question is, how to send the form data further, without manipulating the request?
Thanks in advance.
Your Response doesn't need to be a String it can be a well formed java object. In this case i do not see any issue returning ResponseEntity object without converting this into String.
#ResponseBody will convert returned java object to JSON/Xml based response to outside world.
you can use ModelAndView class.
Refer the following link: http://docs.spring.io/spring-framework/docs/2.5.6/api/org/springframework/web/portlet/ModelAndView.html
I am unable to get the ModelAttribute for second request.
My first request is initForm() method I prepared Command object and able to display the command in jsp.
Through initForm() I am populating command and that command I want in editForm when I will do ajax call.
Here is my spring form
<form:form method="POST" action="addstudentdetails.htm" commandName="command">
Ignore what is inside this
Name: Shoaib Age:23 edit
</form:form>
My ajax request:
function editStudentDetails(studentId,index){
$.ajax(
{url:"editstudentdetails.htm",
method:"GET",
data:{"action":"edit","id":studentId,"index":index},
success: function(data) {
jQuery("#studentDetailsDiv").html(data)
}
}
)
}
In editStudentDetails() method I have method ajax call to go editForm() of the controller.
Here is my controller:
#Controller
public class StudentDetailsController {
#Autowired
private StudentDetailsDAO studentDetailsDAO;
#RequestMapping(value="/studentdetails.htm",method = RequestMethod.GET)
public String initForm(HttpServletRequest request,ModelMap map){
String action=request.getParameter("action");
StudentDetailsCommand command=new StudentDetailsCommand();
System.out.println("in controller"+action);
command.setStudents(studentDetailsDAO.findAll());
map.addAttribute("command", command);
return "studentdetails";
}
#RequestMapping(value="/editstudentdetails.htm",method = RequestMethod.GET)
public String editForm(ModelMap map,HttpServletRequest request){
map.addObject("index", request.getParameter("index"));
StudentDetailsCommand command=(StudentDetailsCommand)map.get("command");
System.out.println(command);
System.out.println(command.getStudents());//NullPointerException here.
map.addObject("command", command);
return "studentdetails";
}
}
Even tried #ModelAttribute("studentDetailsCommand") but didn't worked.
I am new to Spring 3.0 and I followed all solutions which are given here but nothing worked.Can anyone help me out please?
Model attributes only exist during the life cycle of one HttpServletRequest. Consider reading my answer here.
In your initForm method, you do the following
map.addAttribute("command", command);
this add an attribute named command to the model attributes. This attribute will eventually find its way into the HttpServletRequest attributes and be available to your JSP. In here
<form:form [...] modelAttribute="studentDetailsCommand" commandName="command">
first of all, modelAttribute and commandName have the same purpose, ie. to find an attribute in the model. If you remove commandName you will get an Exception because there is no model attribute named studentDetailsCommand. Here your commandName's value is overwriting your modelAttribute's value.
When the Servlet container is finished rendering your JSP, the rendered content is sent as the body of the HTTP response. At this point, the request has been handled and the HttpServletRequest and the model attributes are garbage collected.
When you send your new request through AJAX, there is no longer any model attribute named studentDetailsCommand (there actually never was).
Consider using Flash Attributes.
Related:
How to read flash attributes after redirection in Spring MVC 3.1?
Spring RedirectAttributes: addAttribute vs addFlashAttribute
Use of getFlashAttributes() in Spring's RedirectAttributes
This seems to be a common issue. I have gone all the answers given in SO but could not make it work.I am trying to integrate Spring MVC+Freemarker in already existing web application. It works fine for the GET request and Freemarker Template reads java object provided by Controller without any issue.
But Form submission is not able to hit Controller method. Finally I made log4j work. Here is the error I am getting:
Error
HandlerMethod details:
Controller [application.entry.controller.UserController]
Method [public void application.entry.controller.UserController.handleSave(java.lang.String)]
org.springframework.web.bind.MissingServletRequestParameterException:
Required String parameter 'action' is not present
Freemarker:
<form method="POST" action="save.html">
------------
<input type="submit" class="btnnew" name="saveWithoutValidation" value="Save Without Validation"></input>
<input type="submit" class="btnnew" name="submit" value="Submit"></input>
</form>
context-root is PORTAL.
spring-servlet.xml
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="cache" value="true"/>
<property name="prefix" value=""/>
<property name="suffix" value=".ftl"/>
web.xml
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Controller
#RequestMapping(value="/save", method=RequestMethod.POST)
public void handleSave(#RequestParam String action){
if( action.equals("submit") ){
System.out.println("Damn! You clicked submit");
}
else if( action.equals("saveWithoutValidation") ){
System.out.println("Sweet! You want no string attached.");
}
}
For logs I have tried to add log4j.logger.org.springframework.web=DEBUG to my existing log4j.properties but it didn't work.
I also had this issue and my solution was different, so adding here for any who have similar problem.
My controller had:
#RequestMapping(value = "/setPassword", method = RequestMethod.POST)
public String setPassword(Model model, #RequestParameter SetPassword setPassword) {
...
}
The issue was that this should be #ModelAttribute for the object, not #RequestParameter. The error message for this is the same as you describe in your question.
#RequestMapping(value = "/setPassword", method = RequestMethod.POST)
public String setPassword(Model model, #ModelAttribute SetPassword setPassword) {
...
}
The #RequestParam String action suggests there is a parameter present within the request with the name action which is absent in your form. You must either:
Submit a parameter named value e.g. <input name="action" />
Set the required parameter to false within the #RequestParam e.g. #RequestParam(required=false)
Another possible cause is to have the wrong order of RequestMapping attributes.
As spring doc says:
An #RequestMapping handler method can have a very flexible signatures.
The supported method arguments and return values are described in the
following section. Most arguments can be used in arbitrary order with
the only exception of BindingResult arguments. This is described in
the next section.
If you scroll down the doc, you will see that the BindingResult has to be immediatelly after the model attribute, since we can have multiple model objects per request and thus multiple bindings
The Errors or BindingResult parameters have to follow the model object
that is being bound immediately as the method signature might have
more than one model object and Spring will create a separate
BindingResult instance for each of them so the following sample won’t
work:
Here are two examples:
Invalid ordering of BindingResult and #ModelAttribute.
#RequestMapping(method = RequestMethod.POST) public String
processSubmit(#ModelAttribute("pet") Pet pet, Model model,
BindingResult result) { ... } Note, that there is a Model parameter in
between Pet and BindingResult. To get this working you have to reorder
the parameters as follows:
#RequestMapping(method = RequestMethod.POST) public String
processSubmit(#ModelAttribute("pet") Pet pet, BindingResult result,
Model model) { ... }
I was facing a similar issue and found that a few fields like Date were not getting a concrete value, once given the values things worked fine. Please make sure you do not have date or any other field present on the form which needs a concrete value.
Based on the error:
Required String parameter 'action' is not present
There needs to be a request parameter named action present in the request for Spring to map the request to your handler handleSave.
The HTML that you pasted shows no such parameter.
Controller trying to find the "action" value in bean but according to your example you have not set any bean name of "action".
try to do name="action".
#RequestParam always find in the bean class.
My problem was the lack of BindingResult parameter after my model attribute.
#RequestMapping(method = RequestMethod.POST, value = "/sign-up", consumes = "application/x-www-form-urlencoded")
public ModelAndView registerUser(#Valid #ModelAttribute UserRegistrationInfo userRegistrationInfo
HttpServletRequest httpRequest,
HttpSession httpSession) { ... }
After I added BindingResult my controller became
#RequestMapping(method = RequestMethod.POST, value = "/sign-up", consumes = "application/x-www-form-urlencoded")
public ModelAndView registerUser(#Valid #ModelAttribute UserRegistrationInfo userRegistrationInfo, BindingResult bindingResult,
HttpServletRequest httpRequest,
HttpSession httpSession) { ..}
Check answer #sashok_bg
#sashko_bg Mersi mnogo
Your request mapping is /save, but your POST is to /save.html. Changing the POST to /save should fix it.
#CookieValue(value="abc",required=true) String m
when I changed required from true to false,it worked out.
Please keep your
<form method="POST" action="XYZ">
#RequestMapping(value="/XYZ", method=RequestMethod.POST)
public void handleSave(#RequestParam String action){
Your form action attribute value must match to value of #RequestMapping, So that Spring MVC can resolve it.
Also, as you told it is giving 404 after changing, for this, can you please check whether control is entering inside handleSave() method.
I think, as you are not returning any thing from handleSave() method, you have to look at it.
if it still not work, can you please post your spring logs.
Also, make sure that your request should come like
/PORTAL/save
if there is anything between like PORTAL/jsp/save the mention in #RequestMapping(value="/jsp/save")
Add BindingResult parameter in your method. For reference please my code below.
save(#ModelAttribute Employee employee,BindingResult bindingResult)
I am studying the Spring MVC Showcase example downlodable from the STS dashboard.
Now I am trying to understand the Message Converters section.
In my view I have the following link:
<li>
<a id="writeString" class="textLink" href="<c:url value="/messageconverters/string" />">Write a String</a>
</li>
This link generate an HTTP Request towards the URL: /messageconverters/string
This request is handled by the following method of my controller class:
#RequestMapping(value="/string", method=RequestMethod.GET)
public #ResponseBody String writeString() {
return "Wrote a string";
}
This method simply return a String inside the body field of the HTTP Response...this is very simple
The problem is that I am not understanding why this example is inside the Message Converter section...
What connects this to the message converts topics?
The main thing to note in the example is #ResponseBody method parameter annotation.
This annotation can be put on a method and indicates that the return type should be written straight to the HTTP response body (and not placed in a Model, or interpreted as a view name). Spring converts the returned object to a response body by using an HttpMessageConverter