I am trying to do a simple post request from React (client side) to Java server side. Here is my controller below.
package com.va.med.dashboard.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import com.va.med.dashboard.services.VistaServiceImpl;
import gov.va.med.exception.FoundationsException;
#RestController
#RequestMapping("/dashboard")
public class DashboardController {
#Autowired
private VistaServiceImpl vistaService;
#RequestMapping("/main")
String home() {
return "main route";
}
#RequestMapping("/rpc")
String test() throws FoundationsException {
vistaService.myAuth();
return "this is rpc route";
}
#RequestMapping(method = RequestMethod.POST, produces =
"application/json", value = "/vista")
#ResponseStatus(value = HttpStatus.ACCEPTED)
public String getVistaConnection(#RequestBody String ipString, #RequestBody String portString, #RequestBody String accessPin,
#RequestBody String verifyPin) {
System.out.println(ipString);
System.out.println(portString);
System.out.println(accessPin);
System.out.println(verifyPin);
vistaService.connect(ipString, portString, accessPin, verifyPin); // TO-DO populate with serialized vars
if (vistaService.connected) {
return "Connected";
} else {
return "Not Connected";
}
}
}
Below is my react axios post request
axios.post('/dashboard/vista', {
ipString: this.state.ipString,
portString: this.state.portString,
accessPin: this.state.accessPin,
verifyPin: this.state.verifyPin
})
.then(function (response){
console.log(response);
})
.catch(function (error){
console.log(error);
});
This is also the error that I am getting.
Failed to read HTTP message:
org.springframework.http.converter.HttpMessageNotReadableException:
Required request body is missing:
Can anyone please shed some light on this error message? I'm coming from a pure JavaScript background so a lot of things I just don't know for Java because it is automatically implemented inside of JavaScrips language.
Thanks again in advance!
You're doing it wrong.
Instead of
public String getVistaConnection(#RequestBody String ipString, #RequestBody String portString, #RequestBody String accessPin,RequestBody String verifyPin)
You should wrap those parameters in a class:
public class YourRequestClass {
private String ipString;
private String portString;
....
// Getter/setters here
}
and your controller method will look like:
public String getVistaConnection(#RequestBody YourRequestClass request)
From #Rajmani Arya:
Since RestContoller and #RequestBody suppose to read JSON body, so in your axios.post call you should put headers Content-Type: application/json
Try to replace all #RequestBody annotations with #RequestParam
public String getVistaConnection(#RequestParam String ipString, #RequestParam String portString, #RequestParam String accessPin, #RequestParam String verifyPin)
Related
I have been working with Spring MVC controllers and now I landed on a problem. So basically what I want to do is if I send a POST request with whatever the input is, I should get the exact same response what the input was.
I have just this one controller and tried to do the following:
import lombok.Data;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
#RestController
public class Controller {
#Data
public class DataField {
public String content;
}
#GetMapping("/echo")
public void sayHello() {
}
#PostMapping("/echo")
public String postHello(#RequestBody DataField data) {
System.out.println("post: " + data);
DataField content = data;
return content.content;
}
If I post something i.e
String inputJson = """
{"a":1,"b":2,"c":3}""";
how am I able to get the same response input back from the same address?
Current error:
Expected: "{\"a\":1,\"b\":2,\"c\":3}"
but: was ""
#RequestMapping(value="/postdata", method= RequestMethod.POST, consumes="application/json")
public String postdata(#RequestBody String test, #RequestBody String data) {
logger.info("password reset Request " + requestbody.get("test"));
logger.info("password reset Request " + data);
return "Hello";
}
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public java.lang.String mail.controller.EmailNotifictaionController.postdata(java.lang.String,java.lang.String)]
My Input in the SOAPUI is
{
"test":"my",
"data":"god"
}
You are using two #RequestBody which is not the correct way as one request can only have one request body.
You can either combine both the request bodies into single request body or you can build a wrapper class having both the test and data variables like:
public class Body {
public String test;
public String data;
// You can also keep them private and have getters/setters.
}
and use this class in the API method argument
#RequestMapping(value="/postdata", method= RequestMethod.POST, consumes="application/json")
public String postdata(#RequestBody Body body) {
logger.info("password reset Request " + body.test);
logger.info("password reset Request " + body.data);
return "Hello";
}
You can try this way, it should work.
I have a Feign client to access to an createUser endpoint that requires two headers: username and password. I know how to add one header, but how do I add two headers to the request?
#FeignClient(name = "client", url = "https://abc.abc.com/user/", configuration = FeignClientConfig.class)
public interface MyFeignClient {
#Headers("username_header: {username}") // how do I add "password" here.
#PostMapping(value = "v1/users")
void createUser((#Param("username") String username, User userRequest);
}
Update: Now based on the answer below, I changed the interface body to:
#Headers({"username_header: {username}", "password_header: {password}"})
#PostMapping(value = "v1/users")
void createUser(#Param("username") String username,
#Param("password") String password,
User userRequest);
And the code that calls it is:
feignClient.createUser("me", "123", userObj);
Then I am getting an error:
org.springframework.beans.factory.BeanCreationException: Error creating bean,
nested exception is java.lang.IllegalStateException: Method has too many Body parameters:
feignClient.createUser(java.lang.String,java.lang.String, User)
I know it may be late but I am hopping to help others.
What has worked for me:
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
#PostMapping(path = "${service-uri}", consumes = MediaType.APPLICATION_JSON_VALUE)
String callService(#RequestBody MyBodyClass body, #RequestParam Integer param01, #RequestParam String param02, #RequestHeader Map<String, String> headerMap);
The solution proposed with #HeaderMap doesn't work, apparently because this class is from feign package (import feign.HeaderMap).
Headers accepts String[] for value ... So
#Headers({ "username: {username}", "password: {password}" })
Should do the trick
#RequestLine("POST /v1/users")
#Body("{userBody}")
Response createUser(#HeaderMap Map headerMap, #Param(value = "userBody") String userBody);
Updated
#RequestLine("POST /v1/users")
Response createUser(String userBody, #HeaderMap Map headerMap);
I am trying to get simple string from request body but keep getting errors
Handler:
#RestController
public class GreetingHandler {
public Mono<ServerResponse> hello(ServerRequest request) {
String contentType = request.headers().contentType().get().toString();
String body = request.bodyToMono(String.class).toString();
return ServerResponse.ok().body(Mono.just("test"), String.class);
}
}
Router:
#Configuration
public class GreetingRouter {
#Bean
public RouterFunction<ServerResponse> route(GreetingHandler greetingHandler) {
return RouterFunctions
.route(RequestPredicates.POST("/hello"),greetingHandler::hello);
}
}
Request works i can see the contenType (plainTexT) and i get the response in postman but no way i cant get to request body. The most common error i get is MonoOnErrorResume. How do i convert the body from request into String?
You will have to block to get to the actual body string:
String body = request.bodyToMono(String.class).block();
toString() will just give you the string representation of your Mono object.
Here is what block does:
https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html#block--
Update:
I wasn't aware that blocking on the http thread is not possible (anymore?).
Here is an adapted version of your hello controller method that prints "Hello yourInput" on the console and also returns that string in the response.
public Mono<ServerResponse> hello(ServerRequest request) {
Mono<String> requestMono = request.bodyToMono(String.class);
Mono<String> mapped = requestMono.map(name -> "Hello " + name)
.doOnSuccess(s -> System.out.println(s));
return ServerResponse.ok().body(mapped, String.class);
}
Can you use #RequestBody annotation?
public Mono<ServerResponse> hello(#RequestBody String body, ServerRequest request) {
String contentType = request.headers().contentType().get().toString();
return ServerResponse.ok().body(Mono.just("test"), String.class);
}
I have this class DemoController. In this class I want to send a message along with REST request.
How can I send it? Suppose M sending http://localhost:8080/sendmessage...
How can I send a message along with this request?
#RestController
#EnableAutoConfiguration
public class DemoController {
#Autowired
DemoPublisher demopublisher;
#Autowired
DemoConsumer democonsumer;
#RequestMapping(value="/sendmessage", method= {RequestMethod.POST})
#ResponseBody
public String messageSenderController(#RequestParam String message, Model model){
try {
demopublisher.demoPublishMessage(message);
} catch (JMSException e) {
e.printStackTrace();
}
return message;
}
}
QueryParam
url: /sendMessage?msg=HelloWorld!
#RequestMapping(value="/sendmessage",method= {RequestMethod.POST})
#ResponseBody
public String messageSenderController(#QueryParam("msg") String message,Model model){
}
UrlParam
url: /sendMessage/HelloWorld!
#RequestMapping(value="/sendmessage/{message}",method= {RequestMethod.POST})
#ResponseBody
public String messageSenderController(#PathVariable String message,Model model){
}
When you are posting data to the server, you can also send data in the body parameter too. I recommend you use this for when you have a form or other data you want to send to the server.
RequestBody
url: /sendMessage
body (RAW in postman or other rest client, accept need to be application/xml):
{
"my message"
}
controller
#RequestMapping(value="/sendmessage",method= {RequestMethod.POST})
#ResponseBody
public String messageSenderController(#RequestBody String message,Model model){
}