I am working through the Spring Guides Tutorial: Building Rest services with Spring.
I have followed along the text and entered the code in the tutorial.
I get to the part where I start the service (on local machine) and test using CURL commands.
GET works fine:
Curl -v localhost:8080/employees
returns the expected list
[{"id":1,"name":"Bilbo Baggins","role":"burglar"},{"id":2,"name":"Frodo Baggins","role":"thief"}]
However when I execute:
curl -X POST localhost:8080/employees -H 'Content-type:application/json' -d '{"name": "Samwise Gamgee", "role": "gardener"}'
I get:
{"timestamp":"2018-11-08T20:55:49.844+0000","status":415,"error":"Unsupported Media Type","message":"Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported","path":"/employees"}
Here is the Controller Code
package com.mainsworth.payroll;
import java.util.List;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
#RestController
class EmployeeController {
private final EmployeeRepository repository;
EmployeeController(EmployeeRepository repository) {
this.repository = repository;
}
#GetMapping("/employees")
List<Employee>all() {
return repository.findAll();
}
#PostMapping("/employees")
Employee newEmployee(#RequestBody Employee newEmployee) {
return repository.save(newEmployee);
}
//Single item
#GetMapping("/employees/{id}")
Employee one(#PathVariable Long id) {
return repository.findById(id)
.orElseThrow(()-> new EmployeeNotFoundException(id));
}
#PutMapping("/employees/{id}")
Employee replaceEmployee(#RequestBody Employee newEmployee,
#PathVariable Long id ) {
return repository.findById(id)
.map(employee -> {
employee.setName(newEmployee.getName());
employee.setRole(newEmployee.getRole());
return repository.save(employee);
})
.orElseGet(() -> {
newEmployee.setId(id);
return repository.save(newEmployee);
});
}
#DeleteMapping("/employees/{id}")
void deleteEmployee(#PathVariable Long id) {
repository.deleteById(id);
}
}
I followed Karol's and Jesper's advice. Thanks to both for the quick response. My new Curl is:
curl -X POST localhost:8080/employees -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{"name": "Samwise Gamgee","role": "gardener"}'
and my new response is:
{"timestamp":"2018-11-08T22:49:01.900+0000","status":415,"error":"Unsupported Media Type","message":"Content type 'application/x-www-form-urlencoded;charset=UTF-8'
not supported","path":"/employees"}application
curl: (6) Could not resolve host: application
curl: (6) Could not resolve host: Samwise Gamgee,role
curl: (3) [globbing] unmatched close brace/bracket in column 9
It was happening also on my side during the tutorial:
https://spring.io/guides/tutorials/rest/
What was strange that on Linux OS it not happened. I double check on Linux and everything was perfectly fine.
Solution (example):
Instead:
curl -X POST localhost:8080/employees -H 'Content-type:application/json' -d '{"name": "Samwise Gamgee", "role": "gardener"}'
Use:
curl -X POST localhost:8080/employees -H "Content-type:application/json" -d "{\"name\": \"Samwise Gamgee\", \"role\": \"gardener\"}"
Summarizing:
Change all ' to " and in body add \ before each "
I hope it helps!
Funfell
Specify both Content-Type: application/json and Accept: application/json request headers as your endpoint is both consuming and producing the data.
curl -H 'Content-Type: application/json' -H 'Accept: application/json' ...
In addition to the above answers that do work, I'd like to make people aware of a slight error in that tutorial code when it relates to Springboot 2.
I was getting a 405 after following the curl advisories described here.
I discovered that a tiny tweak to the annotation was needed:
#PostMapping(value="/employees",produces = "application/json")
Employee newEmployee(#RequestBody Employee newEmployee) {
return repository.save(newEmployee);
}
Note that the produced flag is needed to make it react properly to not be given the 405. When combined with the curl command:
curl -i -H "Content-Type: application/json" -H "Accept: application/json" -X POST -d "{\"name\": \"Samwise Gamgee\", \"role\": \"gardener\"}" http://localhost:8080/employees
Related
I am testing some code that has an annotation I haven't used before and reading the documentation seems like I should not even send any parameter to call it, but I might.
The endpoint looks like this:
#POST
#Path("/hello")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public void postHello(
#Suspended final AsyncResponse asyncResponse,#QueryParam("dtd") String name, String obj) {
...
}
So by now I am using Postman or cURL and sending this:
curl -X POST \
'http://localhost:9000/hello?name=John' \
-H 'Accept: */*' \
-H 'Content-Type: application/json' \
-H 'Host: localhost:8080' \
-d '{}'
Unfortunately, I get an error 400 Bad Request
Any idea what header I am missing? or might be #Produces/#Consumes?
I want to customize the input text box in swagger ui and test the rest service ,but while sending the request parameter in input text box the request parameter is not appended with service ulr ,
for example
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' 'http://localhost:8765/COMMONAPI/V2.0/gameList' the piece of request param is not added and due to this I am getting null pointer exception
enter image description here
enter image description here
I want exact request as below
curl -X POST "http://localhost:8765/COMMONAPI/V2.0/gameList" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"timeStamp\": \"2019-03-18T05:11:15\", \"hashKey\": \"c0849bbf6eb17e48a72b92aa8f67650f\", \"apiKey\": \"72uyhsu87sf3\", \"apiId\": 6, \"sessionKey\": \"SdPpZI4LFTlux\"}"
In you SwaggerConfiguration you can define globalOperationParameters for passing paramaters. Something like below.
#Bean
public Docket productApi() {
return new Docket(DocumentationType.SWAGGER_2)
.globalOperationParameters(Arrays.asList(new ParameterBuilder()
.name("token")
.description("Authentication token obtained after authentication.")
.modelRef(new ModelRef("string"))
.parameterType("header")
.required(true)
.build()))
.select()
.apis(RequestHandlerSelectors.basePackage("com.mypackage"))
.build();
}
I have a problem with processing params from curl request to my spring-boot app.
My controller post method:
#RequestMapping(value = "/cat", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ResponseEntity addCat(#Valid #ModelAttribute NewCatRequest newCatRequest, BindingResult bindingResult) {
System.out.println( newCatRequest);
if (bindingResult.hasErrors()) {
return ResponseEntity.badRequest().body(bindingResult.getFieldError().getDefaultMessage());
}
int rowsAffected = catsRepository.saveCat(newCatRequest.getName(), newCatRequest.getColor(), newCatRequest.getTail_length(), newCatRequest.getWhiskers_length());
if (rowsAffected == 1) {
return ResponseEntity.ok().body(newCatRequest);
} else {
return ResponseEntity.badRequest().body("There was an unexpected error while trying to create cat for you :(");
}
}
And the problem is: when i'm trying to send this with curl:
curl -X POST http://localhost:8080/cat \
-d "{\"name\": \"Tihon\", \"color\": \"red & white\", \"tail_length\": 15, \"whiskers_length\": 12}"
I have all null params in 'newCatRequest':
NewCatRequest{name='null', color='null', tail_length=0, whiskers_length=0}
BUT when i'm trying to do the same with Postman (POST method, x-www-form-urlencoded in body with my params) i have a valid result:
Result from Postman
Help me pls to understand what's the problem.
curl -X POST http://localhost:8080/cat \
-d "{\"name\": \"Tihon\", \"color\": \"red & white\", \"tail_length\": 15, \"whiskers_length\": 12}"
The above curl request has a JSON body, whereas your request processing method
#RequestMapping(value = "/cat", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
consumes/accepts: application/x-www-form-urlencoded. Therefore, you should either convert your method to consume/accept application/json or change your curl request to:
curl -X POST http://localhost:8080/cat \
-d 'name=Tihon&color=red%20%26%20white&tail_length=15&whiskers_length= 12' \
-H 'Content-Type: application/x-www-form-urlencoded'
EDIT 1
Please note that the default Content-Type for curl is application/x-www-form-urlencoded. To use JSON, change your request to:
curl -X POST http://localhost:8080/cat \
-d "{\"name\": \"Tihon\", \"color\": \"red & white\", \"tail_length\": 15, \"whiskers_length\": 12}" \
-H 'Content-Type: application/json'
Try this:
curl -X POST \
http://localhost:8080/cat \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'name=Thidon&color=red%20%26%20white&tail_length=15&whiskers_length=12'
You forgot the header application/x-www-form-urlencodedand the body should not be in json format.
you can use the code option below send button in postman to generate the exact curl request which will work for you https://i.stack.imgur.com/hbk8M.png
in code drop down menu search for curl and it will generate a neat and clean curl request for you .
Hope this helps
The backend is coded like this:
#POST
#Path("/resource")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response dailyBilling(
final List<String> students)
throws Exception {
....
}
How should I send curl data, which would me accepted as a List on backend ?
Using the following curl i get 400:
curl --digest -u ameya379+beet#gmail.com:credentials\
-H 'Content-Type: application/json'\
-X POST -d '{"student1", "student2"}'\
http://localhost:8080/api/somepath/resource
Error:
{
"detail":"Received JSON does not match expected format.",
"error":400,
"errorCode":"INVALID_JSON",
"parameters":[],
"reason":"Bad Request"
}
Arrays are encoded between [] in JSON.
curl --digest -u ameya379+beet#gmail.com:credentials -H 'Content-Type: application/json' -X POST -d '["student1", "student2"]' http://localhost:8080/api/somepath/resource
I defined a google cloud end point using java. the class method annotations looks like:
#Api(
name = "instaSmartApi",
version = "v1",
)
public class InstaSmartSvc {
#ApiMethod(name = "analyzeImage")
public Message analyzeImage(#Named("imgURL") String imgURL) {
...
}
I call it using curl which works is:
curl -H "Content-Type: application/json" -X POST -d '{"imgUrl" : "www.google.com"}' https://instasmarttagger.appspot.com/_ah/api/instaSmartApi/v1/analyzeImage/abc.jpg
this works fine except it ignores what i passed in request body.
The way I was expecting it to work:
curl -H "Content-Type: application/json" -X POST -d '{"imgUrl" : "www.google.com"}' https://instasmarttagger.appspot.com/_ah/api/instaSmartApi/v1/analyzeImage
But this returns not found. I am not sure why i have to append the method parameter in the end to make it work. Ideally i should pass that in the body. Please advise