Spring RestTemplate : get with nullable paramaeter - java

I'm trying to make a true RestFull service and keeping to the documentation. However I'm stuck now with a problem I can't see a clear answer for. I want to use a filter to query some data from the webservice. The following path is defined on the controller of the webservice
#RequestMapping(value="/rest/postalcode/list/filter?lang={lang}&postalcode={postalcode}&country={country}&city={city}", method = RequestMethod.GET, produces="application/json")
public #ResponseBody JsonPostalCodeList findFilteredPostalCodes(#PathVariable("lang") String lang, #PathVariable("postalcode") String postalcode, #PathVariable("country") Long country, #PathVariable("city") String city, Model model) throws Exception {
}
Then I try to call it with the following method on client side
public JsonPostalCodeList findPostalCodes(
JsonPostalCodeSelectorData selectorData) {
String url = getWebserviceLocation()+"/rest/postalcode/list/filter?lang={lang}&postalcode={postalcode}&country={country}&city={city}";
MbaLog.debugLog(logger,"Calling webservice with url: " + url);
return getRestTemplate().getForObject(url, JsonPostalCodeList.class, selectorData.getContactLanguage(), selectorData.getPostalCode(), selectorData.getCountry(), selectorData.getCity());
}
now selectorData.getPostalCode() can be null for example because , the user didn't fill in a postalcode to filter on. Same can be true for country and city (lang is always filled in). But each time I run it I get an IOException not found (probably due to the null's). I tried once with everything filled in and I go perfectly in my method at service side. So how do you handle such a problem ?
I can solve it by throwing GET out of the window and just put everything in a POST body as a JSONobject mapped with Jackson and problem solved. But then I'm using a POST to fetch data while a GET should be used in pure REST to fetch data.
So RestTemplate and querying services with variable data how to go about it ?

Just took a cold shower and found it out myself :)
I don't have to use pathvariables I can just use request parameters.
#RequestMapping(value="/rest/postalcode/list/filter", method = RequestMethod.GET, produces="application/json")
public #ResponseBody JsonPostalCodeList findFilteredPostalCodes(#RequestParam("lang") String lang, #RequestParam("postalcode") String postalcode, #RequestParam("country") Long country, #RequestParam("city") String city, Model model) throws Exception {
}
and calling it with
#Override
public JsonPostalCodeList findPostalCodes(
JsonPostalCodeSelectorData selectorData) {
String url = getWebserviceLocation()+"/rest/postalcode/list/filter?lang={lang}&postalcode={postalcode}&country={country}&city={city}";
MbaLog.debugLog(logger,"Calling webservice with url: " + url);
return getRestTemplate().getForObject(url, JsonPostalCodeList.class, selectorData.getContactLanguage(), selectorData.getPostalCode(), selectorData.getCountry(), selectorData.getCity());
}

Related

Restful Webservice string response

I have an endpoint where it supposes to sends a string as a response. My question is do I need to use to response Entity to send string response or just return the string to the consumer?
#GetMapping(value = "/word")
public String getWord() {
String response = "webservice";
return response;
}
Second approach:
#GetMapping(value = "/word", produces ={MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<String> getWord() {
String response = "webservice";
return new ResponseEntity<>(response, HttpStatus.OK);
}
What is the correct approach to send just a string or use response entity?
What is the correct approach to send just a string or use response entity?
The Spring MVC documentation lists a number of types that can be returned from controller methods.
As I previously answered here and here, ResponseEntity<T> represents the entire HTTP response. Besides the body, its API allows you to set headers and a status code to the response.
Returning just a bean instance or a string is fine but doesn't give you much flexibility: In the future, if you need to add a header to the response or modify the status code, for example, you need to change the method return type.

#RequestParam in GET is always null when it's called using HTTPs

I have this method right now:
#RequestMapping(path = "/api2/rep/report_payment_grouped/{startDate}/{endDate}", method = RequestMethod.GET)
public #ResponseBody
ResponseEntity getPaymentsGroupedReport(HttpServletRequest request,
#PathVariable String startDate,
#PathVariable String endDate,
#RequestParam(required = false, value = "requestId") Integer requestId) {
This returns an object Report with two list, fieldsDefs, data, and the requestId received in the original request:
return ResponseEntity
.ok(new Report(fieldDefs, data, requestId));
This is the returned object client side(it's correct):
In the network data:
Now, the exact same request when the service is deployed in my AWS server, requestId is always null:
This is the response:
I have tried manually setting the requestId serverSide and the value is returned correctly in that case. So it's confirmed that requestId parameter is being received as null/empty.
I suspect your service on AWS isn't able to access the database. Have you looked at the error logs?

Spring Java - Possible to add query string to Redirect ModelAndView?

I'm trying to implement an external ModelAndView redirect from my Spring controller. However, whenever I try to add a query string to the URL, it appends a / to the end of the URL before the query string. So even if I set up my string to be:
return new ModelAndView("redirect:https://www.google.com?test=101")
It will show in my network traffic that I am trying to access https://www.google.com/?test=101. Should I be using ModelAndView?
It is dead simple, return a string.
#RequestMapping(value = "/foo", method = RequestMethod.GET)
public String redirectToFoo() {
return "https://www.google.com?test=101";
}
Should I be using ModelAndView?
Since you return an external URL, no internal Model or View is necessary any more. You shouldn't use ModelAndView.

Consume Post method Rest + SpringBoot

I have been searching all morning and i think i'm missing something .
i have a Spring boot controller with a method to save a client.
this is the method :
// ajouter un client
#RequestMapping(value="/AjoutClient/{clientData}", method=RequestMethod.POST)
public String AjoutClient(#PathVariable String clientData) {
Client c = new Client();
c.setNomClient(clientData.split(";")[0]);
c.setPrenomClient(clientData.split(";")[1]);
c.setAdresseClient(clientData.split(";")[2]);
c.setTelClient(clientData.split(";")[3]);
c.setEmailClient(clientData.split(";")[4]);
c.setCinClient(clientData.split(";")[5]);
client.save(c);
return "test";
}
i want to consume this method from another application with this method :
#RequestMapping(value="/ajoutClient", method=RequestMethod.POST)
public void ajout(#RequestParam("nom") String nom,#RequestParam("prenom") String prenom,#RequestParam("adr") String adr,#RequestParam("tel") String tel,#RequestParam("mail") String mail,#RequestParam("cin") String cin) {
String ClientData=nom+";"+prenom+";"+adr+";"+tel+";"+mail+";"+cin;
RestTemplate restTemplate = new RestTemplate();
HttpEntity<String> request = new HttpEntity<>(new String(ClientData));
ResponseEntity<String> response = restTemplate
.exchange("http://localhost:9093/AjoutClient/"+ClientData, HttpMethod.POST, request, String.class);
assertThat(response.getStatusCode(), is(HttpStatus.CREATED));
}
** explication : i get the values from a form and construct a string with those values, then try to send that string to my clientController.
PS: i can't send client object, i have to send the values one by one then create the client object in the clientController.
i'm feeling pretty lost because i can see that something is wrong but i don't know what is it.
First of all I would suggest you avoid using #PathVariable for passing the data like this.
You're already sending everything in the request body, so first step is to change:
public String AjoutClient(#PathVariable String clientData) {
to
public String AjoutClient(#RequestBody String clientData) {
and
restTemplate.exchange("http://localhost:9093/AjoutClient/" + ClientData, HttpMethod.POST, request, String.class);
to just
restTemplate.exchange("http://localhost:9093/AjoutClient", HttpMethod.POST, request, String.class);
Then if you're expecting 201 status then you have to return it:
public ResponseEntity<String> AjoutClient(#RequestBody String clientData) {
...
return ResponseEntity.created(null).body("test");
}
PS: Please pay attention to what #JB Nizet mentioned, cause he has a point here. Just research that keywords (google them) or read some tutorials e.g https://www.baeldung.com/java-url-encoding-decoding or https://www.baeldung.com/rest-template and you'll easily find out more about standard practices.

Bug: Required request body is missing

I'm trying spring framework.
I have RestController and function:
#RequestMapping(value="/changePass", method=RequestMethod.POST)
public Message changePassword(#RequestBody String id, #RequestBody String oldPass,
#RequestBody String newPass){
int index = Integer.parseInt(id);
System.out.println(id+" "+oldPass+" "+newPass);
return userService.changePassword(index, oldPass, newPass);
}
and code angularJS
$scope.changePass = function(){//changePass
$scope.data = {
id: $scope.userId,
oldPass:$scope.currentPassword,
newPass:$scope.newPassword
}
$http.post("http://localhost:8080/user/changePass/", $scope.data).
success(function(data, status, headers, config){
if(date.state){
$scope.msg="Change password seccussful!";
} else {
$scope.msg=date.msg;
}
})
.error(function(data, status, headers, config){
$scope.msg="TOO FAIL";
});
}
and when i run it.
Error Message :
Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public com.csc.mfs.messages.Message com.csc.mfs.controller.UserController.changePassword(java.lang.String,java.lang.String,java.lang.String)
Help me fix it, pls...
Issue is in this code.
#RequestBody String id, #RequestBody String oldPass,
#RequestBody String newPass
You cannot have multiple #RequestBody in same method,as it can bind to a
single object only (the body can be consumed only once).
APPROACH 1:
Remedy to that issue create one object that will capture all the relevant data, and than create the objects you have in the arguments.
One way for you is to have them all embedded in a single JSON as below
{id:"123", oldPass:"abc", newPass:"xyz"}
And have your controller as single parameter as below
public Message changePassword(#RequestBody String jsonStr){
JSONObject jObject = new JSONObject(jsonStr);
.......
}
APPROACH 2:
Create a custom implementation of your own for ArgumentResolver
You can't have request body for the GET method. If you want to pass username and password as part of request body then change RequestMethod type to POST/PUT.
If you want to use GET only then you will have to pass username and password as either path variables or request/query parameters - which is not best practice.
I would recommend changing RequestMethod and pass username & password as request body.

Categories

Resources