I am currently sending a resource to a client, I am using code that has been done already and I am modifying it, there is a line shown below in this code that I don't understand. Well I understand that I am sending or posting a resource, I understand this method takes the url of the client, that it takes the type of HTTP request for example in this case POST, but I dont understant why this method takes nService.getStringHttpEntityWithPayload(payLoad) and Resource.class? Also the response entity it is returning will it be a class only or a class with a status and a headers?
ResponseEntity<Resource> responseEntity = restTemplate.exchange(
eURL,
HttpMethod.POST,
nService.getStringHttpEntityWithPayload(payLoad),
Resource.class);
why this method takes nService.getStringHttpEntityWithPayload(payLoad) and Resource.class?
The method getStringHttpEntityWithPayload is returning a HttpEntity which is composed of a body and header data to be sent to a URL. The method is creating the request message by adding the content type header, letting the receiving service know that the body contains JSON data.
The parameter Resource.class is used to determine what class to deserialize the response body from the service into. It defines the generic type of the return value: ResponseEntity<Resource>.
Also the response entity it is returning will it be a class only or a class with a status and a headers?
I'm not sure what you mean by "class only". The ResponseEntity is similar to HttpEntity (in fact class ResponseEntity<T> extends HttpEntity<T>). The ResponseEntity class contains the response body and headers, as well as the HTTP Status code of the response.
Related
I want to make a GET request to my server that receives two parameters, uniqueConfig and commitHash. The code for this operation in my Controller class is as follows:
#GetMapping("/statsUnique")
public ResponseEntity<Object> hasEntry(#RequestParam("uniqueConfig") String uniqueConfig,
#RequestParam("commitHash") String commitHash) {
Optional<Stats> statsOptional =
codecService.findByUniqueConfigAndCommitHash(uniqueConfig, commitHash);
if (statsOptional.isPresent()) {
return ResponseEntity.status(HttpStatus.OK).body(true);
}
return ResponseEntity.status(HttpStatus.OK).body(false);
}
The issue is, when I try to make the GET request using Postman, the server returns a 400 - Bad Request with the following error message:
MissingServletRequestParameterException: Required request parameter 'uniqueConfig' for method parameter type String is not present]
my JSON on Postman looks like this:
{
"commitHash": "ec44ee022959410f9596175b9424d9fe1ece9bc8",
"uniqueConfig": "bowing_22qp_30fr_29.97fps_fast-preset"
}
Please note that those aren't the only attributes and I've tried making the same request with all of them on the JSON. Nonetheless, I receive the same error.
What am I doing wrong here?
A GET request doesn't (or at least shouldn't) have a body. Parameters defined by the #RequestParam annotations should be sent in the query string, not a JSON body, i.e., the request should be something like
http://myhost/statsUnique?commitHash=commitHash&uniqueConfig=bowing_22qp_30fr_29.97fps_fast-preset
I am using javax to create a REST service to send an Java Object from one system to another.
I send the data like follows:
WebTarget wt = client.target(baseUrl.toString()).path(restUrlSuffix);
response = wt.request(MediaType.APPLICATION_JSON).post(Entity.json(transferJSON));
I defined a method which should receive the entity as a JSON:
#POST
#Path("/post")
#Consumes("application/json")
#Produces("application/json")
public Response saveWorkflowDefinition(#Valid String json) {
.....
.....
String message = "Message to return";
Response res = Response.ok(message).build();
return res;
}
With this method everything is fine. Data arrives as JSON, colud be transformed back to my java class and I can work with the object again.
Also it seems, that the Response is correct.
If I debug my code, the response is properly filled.
But on the side where I want to receive this response and check it, the entity part is empty.
I have no idea why?
Screen 1 is my response before sending it:
Screen 2 is the response after receiving it:
I found a solution.
I had to add a "valid" readEntity to my WebTarget request.
I my case I have written a response object, maybe a String.class might work too. I need my response class later in my code to transfer some more detailed information.
response = wt.request(MediaType.APPLICATION_JSON).post(Entity.json(transferJSON)).readEntity(WFResponse.class);
I am trying to do a get call with request body(JSON) as the request parameter list exceeds the limit. I am able to send the request via postman/insomnia and request is reaching till controller without any error. But the "requstBody" is empty at controller. What i am missing here?
#GET
#Path("\path")
#Consumes(APPLICATION_JSON)
#Produces(APPLICATION_JSON)
public Response getResponse(String requestBody) throws IOException { }
When I replaced #GET with #POST, requestBody has value. For GET call do we need to add anything more?
I am trying to do a get call with request body(JSON) as the request parameter list exceeds the limit. I am able to send the request via postman/insomnia and request is reaching till controller without any error. But the "requstBody" is empty at controller. What i am missing here?
One thing you are missing is the fact that the semantics of a request body with GET are not well defined.
RFC 7231, Section 4.3.1:
A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.
There are two ways for sending parameters in an Http Get method. PathVariable and RequestParam. In this way, sent parameters are visible in the request URL. for example:
www.sampleAddress.com/countries/{parameter1}/get-time?city=someValues
In the above request, parameter1 is a path variable and parameter2 is a request parameter. So an example of a valid URL would be:
www.sampleAddress.com/countries/Germany/get-time?city=berlin
To access these parameters in a java controller, you need to define a specific name for the parameters. For example the following controller will receive this type of requests:
#GetMapping(value = "/countries/{parameter1}/get-time", produces = "application/json; charset=utf-8")
public String getTimeOfCities(
#PathVariable(value = "parameter1") String country,
#RequestParam(value = "city") String city
){
return "the method is not implemented yet";
}
You are able to send RequestBody through a Get request but it is not recommended according to this link.
yes, you can send a body with GET, and no, it is never useful
to do so.
This elaboration in elasticsearch website is nice too:
The HTTP libraries of certain languages (notably JavaScript) don’t allow GET requests to have a request body. In fact, some users are suprised that GET requests are ever allowed to have a body.
The truth is that RFC 7231—the RFC that deals with HTTP semantics and
content—does not define what should happen to a GET request with a
body! As a result, some HTTP servers allow it, and some—especially
caching proxies—don’t.
If you want to use Post method, you are able to have RequestBody too. In the case you want to send data by a post request, an appropriate controller would be like this:
#PostMapping(value = "/countries/{parameter1}/get-time", produces = "application/json; charset=utf-8")
public String getTimeOfCitiesByPost(
#PathVariable(value = "parameter1") String country,
#RequestParam(value = "city") String city,
#RequestBody Object myCustomObject
){
return "the method is not implemented yet";
}
myCustomObject could have any type of data you defined in your code. Note that in this way, you should send request body as a Json string.
put #RequestBody on String requestBody parameter
#RequestMapping("/path/{requestBody}")
public Response getResponse(#PathVariable String requestBody) throws IOException { }
I have a jersey client which calls an api whose return type is javax.ws.rs.core.Response as defined in the interface being used.
public Response getResponse(String id)
The response for a call has status as 'Server Error' but the client does not throw InternalServerException rather returns InboundJaxrsResponse.
On checking Jersey code I see that the JerseyInvocation class being used has the logic to check if response type is of javax.ws.rs.core.Response then to return an InboundJaxrsResponse object.
How can I get an appropriate exception as per the response status here?
PS: RestEasy client also has a similar logic.
With presume that you use <T> T get(Class<T> responseType) to get integer from an HTTP response body, exception that can be thrown if response status is not 2xx is WebApplicationException.
In your case, the second requirement of API contract is not fulfilled
WebApplicationException - in case the response status code of the
response returned by the server is not successful
and the specified response type is not Response.
This question already has an answer here:
How exactly works this REST method that handle a POST request in Spring?
(1 answer)
Closed 6 years ago.
I am studying for the Spring Core certification and I have the following doubt related how Spring MVC handle a controller method of a example Spring MVC webapp.
So, in my example, I have this method:
/**
* Creates a new Account, setting its URL as the Location header on the
* response.
*/
#RequestMapping(value = "/accounts", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
public HttpEntity<String> createAccount(#RequestBody Account newAccount,
#Value("#{request.requestURL}") StringBuffer url) {
Account account = accountManager.save(newAccount);
return entityWithLocation(url, account.getEntityId());
}
I know that this method create a new account into the DB.
So it handle POST Http Request (representing an insertion operation) toward the URL /accounts.
The createAccount() method take 2 parameters:
#RequestBody Account newAccount: I think that it extract the Account object from the body field of the request. It should be in JSON format and then it is automatically converted into a standard Java object (instance of Account class in this case).
#Value("#{request.requestURL}") StringBuffer url: I think that it is the same thing of do somtthing like to:
request.getRequestURL();
And it contains the URL used by the client to make the request. Is it true? But why it put it into a StringBuffer and not into a simple String?
Then the method simply use a DAO class to persist the object on the DB and finally it return an HttpEntity object as result.
This HttpEntity is created by the entityWithLocation() method definied in the same class, this one:
private HttpEntity<String> entityWithLocation(StringBuffer url,
Object resourceId) {
// Configure and return an HttpEntity object - it will be used to build
// the HttpServletResponse
HttpHeaders headers = new HttpHeaders();
headers.setLocation(getLocationForChildResource(url, resourceId));
return new HttpEntity<String>(headers);
}
From what I have understand reading the Spring official documentation in this case this object represents the HttpResponse entity that consist of consisting of headers and body.
My doubts are about this oject are:
In my case it is setted only the heder with the url value (the URL used by the client to make the request) and with the id of the new inserted object. The body field of this HttpResponse is empty?
Why have I to return this HttpResponse object? For what is used?
Tnx
#Value("#{request.requestURL}") StringBuffer url: I think that it is the same thing of do somtthing like to:
request.getRequestURL();
And it contains the URL used by the client to make the request. Is it true? But why it put it into a StringBuffer and not into a simple String?
Because the method HttpServletRequest.getRequestURL() returns a StringBuffer, and not a String.
The body field of this HttpResponse is empty?
Yes, it is, since the code doesn't populate it. You could simply use your browser to invoke this action and see the response returned.
Why have I to return this HttpResponse object? For what is used?
You don't have to. But you may choose to. That is up to you. You should know why you return what you return. The intention of the programmer here is to return a HTTP response with no body, with a Location header containing a URL, and a CREATED status. That's the conventional thing to return after a POST in a REST application: a POST is used to create a new resource, and it returns the status CREATED to signal that the resource has been created correctly, and the URL of the created resource, so that the client can get this resource and check what it contains.