Problem with getting data from external source by Rest Template - java

I have some problem with getting response from external resources with RestTemplate.
What I want to get is data from PokemonApi: https://pokeapi.co/api/v2/type/
I thought about creating 2 Classes that will contain that data(Not using Object and headers)
My 2 classes are like:
#JsonIgnoreProperties(ignoreUnknown = true)
public class MainResponse {
#JsonProperty("typeList")
private List<PokemonType> pokemonTypes;
}
#JsonIgnoreProperties(ignoreUnknown = true)
public class PokemonType {
#JsonProperty("name")
private String pokemonType;
}
What problem I got is that I can't extract any data from my RestTemplate class:
public MainResponse response() {
Optional<MainResponse> search = Optional.ofNullable(
restTemplate.getForObject("https://pokeapi.co/api/v2/type", MainResponse.class)
);
return search.orElseGet(MainResponse::new);
}
I'm not sure why its not working right. I can't get any response and everything is ending in errors when I try get response. Please someone look at that and give me some pointers.
It will be surely eyeopener for all RestTemplates in the future for me :) Thanks alot.

Related

Can not Send POST request to #RequestBody in Spring, error 415

I am working currently on a project and I need to send a POST request to spring. I looked or several hours already for a solution and didn't find one to work. The request worked when I developed that part. The problem is that after creating some new functionalities(2 new endpoint in another controller) the POST requests for creating or updating the entities stopped working without changing code in the specific area.
The Controller:
#RestController
#CrossOrigin
#RequestMapping
public class SensorController {
#PostMapping(value = "/createSensor", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<UUID> insertSensor(#RequestBody SensorDto sensorDto){
UUID sensorId = sensorService.createSesor(sensorDto);
return new ResponseEntity<>(sensorId,HttpStatus.CREATED);
}
}
The part with consumes and produces wasn't there originally, I tried it because saw on other posts but doesn't helped the situation.
The SensorDto:
public class SensorDto extends RepresentationModel<SensorDto> {
private UUID id;
private String description;
private Integer maxValue;
private Device device;
The call from POSTMAN:
image
The headers: headers
Can someone help me to get it to work again?
EDIT: The code asked from the other controller
#PostMapping("/addSensorToDevice")
public ResponseEntity<UUID> addSensor(#RequestBody DeviceSensorLinkDto deviceSensorLinkDto){
System.out.println("OOO: " + deviceSensorLinkDto.toString());
if(deviceService.addSensor(deviceSensorLinkDto)){
return new ResponseEntity<>(deviceSensorLinkDto.getDeviceId(), HttpStatus.OK);
}else {
return new ResponseEntity<>(deviceSensorLinkDto.getDeviceId(), HttpStatus.EXPECTATION_FAILED);
}
}
#PostMapping("/addClientToDevice")
public ResponseEntity<UUID> addClient(#RequestBody DeviceClientLinkDto deviceClientLinkDto){
System.out.println("OOO: " + deviceClientLinkDto.toString());
if(deviceService.addClient(deviceClientLinkDto)){
return new ResponseEntity<>(deviceClientLinkDto.getDeviceId(), HttpStatus.OK);
}else {
return new ResponseEntity<>(deviceClientLinkDto.getDeviceId(), HttpStatus.EXPECTATION_FAILED);
}
}
And this one works and also the requests for deleting a Sensor entity.
It seems that you have multiple #JsonBackReference and #JsonManagedReference in your application and as a consequence, you must provide a name for all pairs as follows:
#JsonBackReference(value = "something")
#JsonManagedReference(value = "something")
#JsonBackReference(value = "something-else")
#JsonManagedReference(value = "something-else")
You can find some information about this in the reference documentation:
Logical have for the reference property pair; used to link managed and
back references. Default name can be used if there is just single
reference pair (for example, node class that just has parent/child
linkage, consisting of one managed reference and matching back
reference).

How to send extra fields with an entity object in request body spring mvc?

I am creating a spring boot app where I have a post route which post the course details.
Course.java
public class course{
String name;
String days;
}
Now while sending a post request to post it,I have to add few extra fields like:
sort_order,page_size
My Post Mapping looks like this:
public course postcourse (#RequestBody course c)
{
}
In the above function the request body will be:
{
"name":"Java",
"duration":"12"
}
but I want my request to be:
{
"name":"Java",
"duration":"12",
"page_size":10,
"sort_order":"reverse"
}
I can't add sort_order and page_size in entity object as its not a good practice.
Can someone help? Thanks
A local class could help you to resolve this
public course postcourse (#RequestBody course c) {
class postCourse extends course {
int page_size;
String sort_order;
}
course yourCourse = new postCourse();
…
return yourCourse;
}
Hope this work.

Java #requestBody doesn't work, dto empty

For some reason java can't map DTO with requestBody and all values are default ones, as for request it works, with payload for ex. "{"productId":1,"commitment":6,"returnMonths":"2"}"
DTO
#Data
public class Request {
private int productId;
private int commitment;
private String returnMonths;
// contructers
}
Controller :
#PostMapping(value = "/calculate", consumes = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public String calculatePrice(#RequestBody Request request) {
productService.calculatePrice(request);
return "Success";
}
front request:
submit: async function() {
let request = {
productId: this.productSelected,
commitment: this.optionSelected,
returnMonths: this.input
};
let data = await getCalculation(request);
console.log(data);
}
DTO maps as:
productId : 0
commitment : 0
returnMonths : null
Tried an exact copy of your code and it worked when tested with Postman. This makes me think it's either something to do with the FE or maybe some issue in the service. I'd check if the Frontend really sends the data.
Try to annotation Request class with #AllArgsConstructor like:
#AllArgsConstructor
#Data
public class Request {
private int productId;
private int commitment;
private String returnMonths;
}
If your request body contains properties that is date such as LocalDateTime, make sure to format it in your DTO using #JsonFormat(pattern="") respecting the input value.

How to encode url string with object in request parameters spring [duplicate]

This question already has answers here:
Using RestTemplate in Spring. Exception- Not enough variables available to expand
(6 answers)
Closed 3 years ago.
I.m trying to do request with the object as a request parameter in my Spring application.
new RestTemplate().getForObject("http://127.0.0.1:8080/items?filter={\"level\":\"BIG\"}", Item.class);
But get error:
As I discovered, the problem occurs when UriBuilder parses the string with url. I.e. new URI(...) gives the error. When I do the same request with Postman I get a desirable response. How I can properly encode url? I`m tried to use java.net.URLEncoder but this gives "IllegalArgumentException: URI is not absolute" error.
UPDATE:
Filter class in the request is used to do parameterized query ( Query() ) in mongodb in the remote server. Filter class:
#Getter
#NoArgsConstructor
public class Filter {
private Map<String, String> criteria;
#JsonAnySetter
public void add(String key, String value) {
if (criteria == null) {
criteria = new HashMap<>();
}
criteria.put(key, value);
}
}
Item object class:
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class Item {
private String id;
private String name;
private Instant timestamp;
}
i have problem like yours and i solve it using following snippet code
UriComponentsBuilder renewURIBuilder= UriComponentsBuilder.fromHttpUrl("http://127.0.0.1:8080").path("/items").queryParam("filter", "{'level':BIG}");
UriComponents uriComponent=renewURIBuilder.build(true);
URI uri=uriComponent.toUri();
then call your resttemplate like the following
new RestTemplate().getForObject(uri, Item.class);
hope it help you

Extracting parameters from URL with POST method

I have something like this :
#RestController
#RequestMapping("/prop")
public class PropController {
#RequestMapping(method = RequestMethod.POST)
public Prop getProp(#ModelAttribute PropForm propForm) {
//calling methods and stuff using propForm
}
}
My PropForm class :
#Data
public class PropForm {
private String att1;
private String att2;
private String att3;
}
Now I am calling this URL :
http://localhost:8080/prop?att1=blabla&att2=blob&att3=test
I want to extract the parameters from the URL and put them in my propForm.
I've tried replacing #ModelAttribute by #RequestBody and then by #RequestParam. It's still not working, I always get a NullPointerException when running the application.
Please, note that I need to use POST method. I already have it working using GET method
FIRST Make sure you have getters and setters in your PropForm class...
Then, you need to put into your model the Form entity:
model.put("NAME", propForm);
And declare method like this:
#RequestMapping(method = RequestMethod.POST)
public Prop getProp(
#ModelAttribute PropForm propForm
#Valid #ModelAttribute("NAME") PropForm propForm)
// ^ you're missing the name!
{
// do your stuff....
return (Prop) propForm;
}
I think you controller and mapping is ok.
But the problem is you are expecting a post request in the mapping, and you are calling
http://localhost:8080/prop?att1=blabla&att2=blob&att3=test
Now this will generate a GET request Not Post. You cannot send a post request using only url.
If you cant use a form for sending the request then you need to use any 3rd party to generate a POST request
like you can use jquery $.post()
And also att1 att2 will not help unless you bind the object with the model attribute.

Categories