I am currently racking my head as to why including a parameter #RequestBody Car car breaks my end point.
I am very new to Spring boot and and trying to post a json string to my rest controller.
Here's my controller:
#RestController
#RequestMapping("/v1/car")
#EnableWebMvc
public class CarController {
private static final Log LOGGER = LogFactory.getLog(CarController.class);
#Autowired
private CarService carService;
#RequestMapping(value="/{accountId}", method = RequestMethod.POST, consumes={"text/plain", "application/*"})
ResponseEntity<?> start(#PathVariable final Integer accountId, #RequestBody Car car) {
System.out.println("E: "+accountId);
final long tid = Thread.currentThread().getId();
final Boolean status = this.smarterWorkFlowService.startWorkFlow(accountId, car);
return new ResponseEntity<Car>(new Car(), HttpStatus.ACCEPTED);
}
}
I am using jackson as my json parser too. I looked for hours and have found nothing that can help me explain why I am getting a response of 415 back.
{
"timestamp": 1425341476013,
"status": 415,
"error": "Unsupported Media Type",
"exception": "org.springframework.web.HttpMediaTypeNotSupportedException",
"message": "Unsupported Media Type",
"path": "/v1/experiences/12"
}
Thanks for any help!!
First, in spring boot #EnableWebMvc is not needed. Then, if your REST service need to produce json or xml use
#RequestMapping(value = "properties", consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}, method = RequestMethod.POST)
Test your service
HttpHeaders headers = new HttpHeaders();
headers.add("Content-type", header);
headers.add("Accept", header);
UIProperty uiProperty = new UIProperty();
uiProperty.setPassword("emelendez");
uiProperty.setUser("emelendez");
HttpEntity entity = new HttpEntity(uiProperty, headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange("http://localhost:8080/properties/1", HttpMethod.POST, entity,String.class);
return response.getBody();
Replace header by application/json or application/xml. If you are usin xml, add this dependency
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
If you're using JSON, remove the consumes={...} part of your #RequestMapping, make sure you're actually POSTing JSON and set the Content-type to application/json.
Related
I have the POST request api call to accept the json body request parameters and multipart file from client side(postman or java client).
I want to pass both the json data and multipart file in single request.
I have written the code like below.
#RequestMapping(value = "/sendData", method = RequestMethod.POST, consumes = "multipart/form-data")
public ResponseEntity<MailResponse> sendMail(#RequestPart MailRequestWrapper request) throws IOException
But, i could not accomplish it using postman rest client.
I'm using spring boot on server side.
Could anyone suggest me on this question.
Thanks in advance,
You cat use #RequestParam and Converter for JSON objects
simple example :
#SpringBootApplication
public class ExampleApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleApplication.class, args);
}
#Data
public static class User {
private String name;
private String lastName;
}
#Component
public static class StringToUserConverter implements Converter<String, User> {
#Autowired
private ObjectMapper objectMapper;
#Override
#SneakyThrows
public User convert(String source) {
return objectMapper.readValue(source, User.class);
}
}
#RestController
public static class MyController {
#PostMapping("/upload")
public String upload(#RequestParam("file") MultipartFile file,
#RequestParam("user") User user) {
return user + "\n" + file.getOriginalFilename() + "\n" + file.getSize();
}
}
}
and postman:
UPDATE
apache httpclient 4.5.6 example:
pom.xml dependency:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.6</version>
</dependency>
<!--dependency for IO utils-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
service will be run after application fully startup, change File path for your file
#Service
public class ApacheHttpClientExample implements ApplicationRunner {
private final ObjectMapper mapper;
public ApacheHttpClientExample(ObjectMapper mapper) {
this.mapper = mapper;
}
#Override
public void run(ApplicationArguments args) {
try (CloseableHttpClient client = HttpClientBuilder.create().build()) {
File file = new File("yourFilePath/src/main/resources/foo.json");
HttpPost httpPost = new HttpPost("http://localhost:8080/upload");
ExampleApplication.User user = new ExampleApplication.User();
user.setName("foo");
user.setLastName("bar");
StringBody userBody = new StringBody(mapper.writeValueAsString(user), MULTIPART_FORM_DATA);
FileBody fileBody = new FileBody(file, DEFAULT_BINARY);
MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
entityBuilder.addPart("user", userBody);
entityBuilder.addPart("file", fileBody);
HttpEntity entity = entityBuilder.build();
httpPost.setEntity(entity);
HttpResponse response = client.execute(httpPost);
HttpEntity responseEntity = response.getEntity();
// print response
System.out.println(IOUtils.toString(responseEntity.getContent(), UTF_8));
} catch (Exception e) {
e.printStackTrace();
}
}
}
console output will look like below:
ExampleApplication.User(name=foo, lastName=bar)
foo.json
41
You can use both of them.
#RequestPart : This annotation associates a part of a multipart request with the method argument, which is useful for sending complex multi-attribute data as payload, e.g., JSON or XML.
In other words Request Part parse your json string object from request to your class object. On the other hand, Request Param just obtain the string value from your json string value.
For example, using Request Part:
#RestController
#CrossOrigin(origins = "*", methods= {RequestMethod.POST, RequestMethod.GET,
RequestMethod.PUT})
#RequestMapping("/api/api-example")
public class ExampleController{
#PostMapping("/endpoint-example")
public ResponseEntity<Object> methodExample(
#RequestPart("test_file") MultipartFile file,
#RequestPart("test_json") ClassExample class_example) {
/* do something */
}
}
and postman would be configured like:
#RequestParam : Another way of sending multipart data is to use #RequestParam. This is especially useful for simple data, which is sent as key/value pairs along with the file, as I said, just key/value. Also is used to get value from query params, I think that is its main goal.
I was stuck with this problem for past few hours
So I came across this question.
Summary:
Use #ModelAttribute instead of #RequestBody.
#ModelAttriute will work just like other normal(without multipart property in entity) Entity mapping.
You have two options -
Send a MultipartFile along with json data
public void uploadFile(#RequestParam("identifier") String identifier, #RequestParam("file") MultipartFile file){
}
OR
Send Json data inside a MultipartFile and then parse Multipart file as mentioned below and thats it.
public void uploadFile(#RequestParam("file") MultipartFile file){
POJO p = new ObjectMapper().readValue(file.getBytes(), POJO.class);
}
I explain all here in answer part:
enter link description here
I'm querying a PhraseApp API to get translations and setting the content type on the headers as appplication/json:
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
But the API sends a response as attachment with content type text/json; charset=UTF-8. And Spring raises the error:
org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class java.lang.String] and content type [text/json;charset=UTF-8]
The response I get is in the following form:
{
"some.key.a": "some translation for a",
"some.key.b": "some translation for b",
"some.key.c": "some translation for c"
...
}
I expected to assign the response to a String variable and parse it later.
Any idea on what is going wrong here ? Thank you.
according to the JSON-specification the content type of JSON should always be "application/json".
One possible fix would be to edit the request and set the correct content type.
Fortunately I am from the PhraseApp Team and could simply fix this on our side ;)
You should be able to use it with your original code now!
If you need further help, send me a PN or an email at vincent#phraseapp.com
I had to use the following steps to get it works:
Use /api/v2/projects/{projectId}/locales/{localeId}/download
Create a custom converter as follows:
public class PhraseTextJsonConverter extends MappingJackson2HttpMessageConverter {
public PhraseTextJsonConverter() {
setSupportedMediaTypes(initMediaTypes());
}
private List<MediaType> initMediaTypes() {
return Arrays.asList(new MediaType("text", "json", DEFAULT_CHARSET));
}
}
Add converters to the template:
protected static RestTemplate createRestTemplateWithConverter() {
final RestTemplate restTemplate = new RestTemplate();
final List<HttpMessageConverter<?>> httpMessageConverters = new ArrayList<>();
httpMessageConverters.add(new MappingJackson2HttpMessageConverter());
httpMessageConverters.add(new ByteArrayHttpMessageConverter());
restTemplate.setMessageConverters(httpMessageConverters);
return restTemplate;
}
and later a custom one:
private void addPhraseTextJsonConverter() {
restTemplate.getMessageConverters().add(new PhraseTextJsonConverter());
}
To be able to get all the translations as a Map, I had to use ParameterizedTypeReferenceas follows:
protected ResponseEntity<HashMap<String, String>> requestPhraseApp(final HttpEntity<Object> requestEntity, final URI uri) {
ParameterizedTypeReference<HashMap<String, String>> typeRef = new ParameterizedTypeReference<HashMap<String, String>>() {};
...
return restTemplate.exchange(uri, HttpMethod.GET, requestEntity, typeRef);
...
}
Do not forget to init the request parameters to get all the translations in a Map:
List urlParameters = new ArrayList<>();
urlParameters.add(new BasicNameValuePair("file_format", "simple_json"));
That's it.
I try to return a JSONObject when a GET request is sent.
The method
#RequestMapping(value = "/{businessId}/{orderId}/{reportId}", method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public ResponseEntity<JSONObject> getReport(#PathVariable("businessId") String businessId,
#PathVariable("orderId") String orderId,
#PathVariable("reportId") Long reportId) throws JSONException {
return new ResponseEntity<JSONObject>(reportService.getReportJSON(), HttpStatus.OK);
}
I get json from a file. The is a single json object there. In one line. I parse it to JSONObject like this
fs = FileSystem.get(uri, conf);
BufferedReader reader = null;
reader = new BufferedReader(new InputStreamReader(fs.open(path)));
line = reader.readLine();
while (line != null) {
jsonObjectList = new JSONObject(line);
line = reader.readLine();
}
return jsonObjectList;
This is what my file looks like.
{"reportId":"1","description":"СегментацияпоПоливозраст","orderId":"357","businessId":"НашКлиент№1","tables":[{"name":"Мужчины","fields":[{"name":"0-17","type":"number"},{"name":"18-24","type":"number"},{"name":"25-34","type":"number"},{"name":"35-44","type":"number"},{"name":"45-54","type":"number"},{"name":"45-54","type":"number"},{"name":"45-54","type":"number"}],"data":[2571,5287,4587,7705,3675,3743,7423]},{"name":"Женщины","fields":[{"name":"0-17","type":"number"},{"name":"18-24","type":"number"},{"name":"25-34","type":"number"},{"name":"35-44","type":"number"},{"name":"45-54","type":"number"},{"name":"45-54","type":"number"},{"name":"45-54","type":"number"}],"data":[7552,3107,6477,4967,9106,7859,9060]},{"name":"Мужчиныиженщины","fields":[{"name":"0-17","type":"number"},{"name":"18-24","type":"number"},{"name":"25-34","type":"number"},{"name":"35-44","type":"number"},{"name":"45-54","type":"number"},{"name":"45-54","type":"number"},{"name":"45-54","type":"number"}],"data":[7552,3107,6477,4967,9106,7859,9060]}]}
I use postman to check my methods. This is the error I get
{
"timestamp": 1504020107350,
"status": 406,
"error": "Not Acceptable",
"exception": "org.springframework.web.HttpMediaTypeNotAcceptableException",
"message": "Not Acceptable",
"path": "/audpro/report/1/1/1"
}
I tried to create a jsonobject by hand and pass it, but got the same error
JSONObject response = new JSONObject();
response.put("id", 555);
response.put("message", "Provision successful!");
return new ResponseEntity<>(response, HttpStatus.OK);
This is the library I use.
import org.codehaus.jettison.json.JSONObject;
Why can't I return a jsonobject?
Turns out I don't actually need JSONObject to get a json. I can return a String and it will be parsed as json. In the controller
public ResponseEntity<String> getReport(#PathVariables) throws JSONException {
return new ResponseEntity<>(reportService.getReportJSON(), HttpStatus.OK);
}
And in the service I do
String json = line;
return json;
I'm still not sure about why returning a JSONObject is a no go though.
Instead of returning direct JSONObject in RestController class, you can set the objects in one POJO class and return in RestController class.
MediaType.APPLICATION_JSON_VALUE in the annotation level will take care of conversion.In Future if you want to send both xml and json, simply you can extend more MediaTypes in annotation level, so that it can support Multi MediaTypes. Just follow this example.
Also make sure your including below dependency for HttpMessageConversions:
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.10</version>
</dependency>
I want to build a small RESTful Service, send a PUT request with an Object of a class I created (MyObject), and getting a response with only status.
My controler:
#RestController
public class MyControler {
#RequestMapping(path = "/blabla/{id}", method = RequestMethod.PUT)
#ResponseBody
public ResponseEntity<String> putMethod (#PathVariable("id") Long id,
#RequestBody MyObject t) {
/*todo*/
return new ResponseEntity<String>(HttpStatus.OK);
}
My Test App
#SpringBootApplication
public class App {
public String httpPut(String urlStr) {
MyObject myObject = new MyObject(p,p,....);
URI url = null;
HttpEntity<MyObject> requestEntity;
RestTemplate rest = new RestTemplate();
rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
HttpHeaders headers = new HttpHeaders();
List<MediaType> list = new ArrayList<MediaType>();
list.add(MediaType.APPLICATION_JSON);
headers.setAccept(list);
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Content-Type", "application/json");
requestEntity = new HttpEntity<Transaction>(t, headers);
ResponseEntity<String> response =
rest.exchange(url, HttpMethod.PUT, requestEntity, MyObject.class);
return response.getStatusCode().getValue();
}
Im getting an HttpClientErrorException: 400 Bad Request
Where is my mistake? What I want is for Spring to automaticly serialize the MyObject. MyObject class is implementing serializable.
What do I miss?
}
Maybe you're doing to much?
Did you try to put the object as json via postman or something similar? If so what is the response?
Nevertheless i created a minimal example for consuming a service via Springs RestTemplate.
This is all needed code for getting a custom object AND putting a custom object via RestTemplate
public void doTransfer(){
String url = "http://localhost:8090/greetings";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Greeting> greeting = restTemplate.getForEntity(url, Greeting.class);
LOGGER.info(greeting.getBody().getValue());
Greeting myGreeting = new Greeting();
myGreeting.setValue("Hey ho!");
HttpEntity<Greeting> entity = new HttpEntity<Greeting>(myGreeting);
restTemplate.exchange(url, HttpMethod.PUT, entity, Greeting.class);
}
I've provided a sample project with a sender (maybe not a good name .. it is the project with the greetings endpoint) and a receiver (the project which consumes the greetings endpoint) on Github
Try to do this:
ResponseEntity<MyObject> responseSerialized =
rest.exchange(url, HttpMethod.PUT, requestEntity, MyObject.class);
I am working with Spring MVC using JSON objects. while I am tring to send JSON Object from RESTClient, I am getting
HTTP Status 400 - The request sent by the client was syntactically incorrect ().
This is my controller
ObjectMapper mapper=new ObjectMapper();
#RequestMapping(value = "/addTask", method = RequestMethod.GET)
public ModelAndView addTask(#RequestParam("json") String json) throws JsonParseException, JsonMappingException, IOException
{
System.out.println("Json object from REST : "+json);
Task task=(Task) mapper.readValue(json, Task);
service.addService(task);
return new ModelAndView("Result");
}
My request URL : http://localhost:8080/Prime/addTask
My Json Object :
{"taskName":"nothing","taskId":1234,"taskDesc":"nothing doing"}
Also i tried specifying "Content-Type: application/json" in RESTClient but still am getting the same error
I ran into a similar situation using a JSON string in the request body recently, and using a very similar Spring setup as yours. In my case I wasn't specifying a String parameter and deserialising it myself though, I was letting Spring do that:
#RequestMapping(value = "/myService/{id}", method = RequestMethod.POST)
#ResponseBody
public void myService(#PathVariable(value = "id") Long id, #RequestBody MyJsonValueObject request) {
..
}
I was getting an HTTP error 400 "The request sent by the client was syntactically incorrect" response. Until I realised that there wasn't a default constructor on the #RequestBody MyJsonValueObject so there were problems deserialising it. That problem presented in this way though.
So if you are using POST and objects, and getting errors like this, make sure you have a default constructor! Add some JUnit to be sure you can deserialise that object.
Note: I'm not saying this is the only reason you get this error. The original case used just String (which does have a default constructor !) so it's a little different. But in both cases it appears the request URI appears to have been mapped to the right method, and something has gone wrong trying to extract parameters from the HTTP request.
Try this
Change
#RequestParam("json") String json
To
#RequestBody Task task
If you are not interested in POST method you can try this
change your Controller method from
#RequestMapping(value = "/addTask", method = RequestMethod.GET)
public ModelAndView addTask(#RequestParam("json") String json)
to
#RequestMapping(value = "/addTask/{taskName}/{taskId}/{taskDesc}", method = RequestMethod.GET)
public ModelAndView addTask(#RequestParam("taskName") String taskName,
#RequestParam("taskId") String taskId,#RequestParam("taskDesc") String taskDesc)
and change your URL to
http://localhost:8080/Prime/addTask/mytask/233/testDesc
My problem was due to the incorrect mapping of the #RequestBody object.
My Request Body looks like this
{data: ["1","2","3"]}
I had the following code in my controller
#RequestMapping(value = "/mentee", method = RequestMethod.POST)
public #ResponseBody boolean updateData(#RequestBody List<Integer> objDTO, HttpSession session) {
...
}
This give me HTTP 400 because Spring doesn't know how to bind my Json data to a List.
I changed the RequestBody object to the following
#RequestMapping(value = "/mentee", method = RequestMethod.POST)
public #ResponseBody boolean updateData(#RequestBody ObjectiveDto objDTO, HttpSession session) {
...
}
and defined ObjectiveDto as followed
#ToString
public class ObjectiveDto {
#Getter #Setter
private List<Integer> data;
}
This resolved the HTTP 400 error.