I have two classes:
public class Person {
private String Name;
private Integer Age;
private String Surname;
// getters and setters
}
public class Animal {
private String Name;
private Integer Age;
// getters and setters
}
And the thing I wanna do - post Animal.class and receive response in Person.class format. (On the client side).
For this purpose I'm using REST Template:
RestTemplate restTemplate = new RestTemplate();
Person result = restTemplate.postForObject("http://url.com", HttpMethod.POST, Animal.class, Person.class);
I know that passing Animal.class this way is not right, but I cannot set Name and Age parameters manually in this page. The main requirement to use POST method.
So what I have to do to make it work?
I believe what you are looking for is:
RestTemplate restTemplate = new RestTemplate();
HttpEntity<Animal> request = new HttpEntity<>(animal); //populated object
ResponseEntity<Person> response = restTemplate.
exchange(url, HttpMethod.POST, request, Person.class);
Related
I want to call another spring boot on spring boot
I read a lot of articles
Spring RestTemplate GET with parameters
Spring RestTemplate
Many more...
Temporary methods that I can currently use
final String uri = "http://127.0.0.1:8888/key";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(uri)
.queryParam("id", "1234")
.queryParam("model", "model")
.queryParam("name", "name")
.queryParam("description", "description")
.queryParam("status", 0)
.queryParam("mode", 1)
.queryParam("creationDate", "2021/05/24 12:34:56")
.queryParam("updatedDate", "2021/05/24 12:34:56");
HttpEntity<?> entity = new HttpEntity<>(headers);
HttpEntity<String> response = restTemplate.exchange(
builder.toUriString(),
HttpMethod.PUT,
entity,
String.class);
I want to be able to use the class directly instead of slowly entering all the parameters
public class DataDto {
private String id;
private String model;
private String name;
private String description;
private int status;
private int mode;
private String creationDate;
private String updatedDate;
...
}
How can I use the entire class as a parameter at once?
I have tried many similar things, but there are no parameters on my server:
logger.info("getId:" + dataDto.getId());
final String uri = "http://127.0.0.1:8888/key";
RestTemplate restTemplate = new RestTemplate();
restTemplate.put(uri, DataDto.class, dataDto);
Try something like below.
Override toString() method for DataDto
#Override
public String toString() {
return String.format("id=%s&" +
"model=%s&" +
"name=%s&" +
"description=%s&" +
"status=%s&" +
"mode=%s&" +
"creationDate=%s&" +
"updatedDate=%s", id, model, name, description, status, mode,
creationDate, updatedDate);
}
Formulate URL like below,
final String uri = String.format("%s?%s", "http://127.0.0.1:8888/key", dataDto.toString())
I did a get request to a external RESTful api and receive as response a json object with this structure:
{
"data": {
"id": 1,
"name": "John Doe",
"email": "doe#john.com",
"urlPicture": "urlPicture.com/82819",
"address": {
"street": "My street",
"number": "29",
"city": "Nurnberg",
"country": "Germany"
}
}
}
I don't need all stuff of this response, I want only some fields to save in a database.
My POJO classes are similar to this pseudocode:
public class Data{
private User user;
// getters and setters
}
public class User{
private int id;
private String name;
private String urlPicture;
private String country;
// getters and setters
}
But, when I try to extract fields that I want, I receive null in this fields
public void testResponse(){
RestTemplate restTemplate = new RestTemplate();
Data data = new Data();
User user = new User();
Gson gson = new Gson();
String response = restTemplate.getForObject(
"https://apifrommyrequest.com/user/{id}",
String.class,
73442);
user = gson.fromJson(response, User.class);
System.out.println(user);
}
```
My output:
22:20:57.641 [main] DEBUG org.springframework.web.client.RestTemplate - HTTP GET https://apifrommyrequest.com/user/73442
22:20:57.672 [main] DEBUG org.springframework.web.client.RestTemplate - Accept=[text/plain, application/json, application/*+json, */*]
22:20:58.243 [main] DEBUG org.springframework.web.client.RestTemplate - Response 200 OK
22:20:58.247 [main] DEBUG org.springframework.web.client.RestTemplate - Reading to [java.lang.String] as "application/json;charset=UTF-8"
Data(id=0, name=null, urlPicture=null, country=null)
I really don't know how to do anymore.
Try out the below code. You can't directly access the country, it is a value placed in a nested object. And also since response body returns as data you can't convert it to a User object. first, you need to convert it to a Data object.
public class User {
private int id;
private String name;
private String urlPicture;
private Address address;
// getters and setters
}
public class Address {
private String country;
// getters and setters
}
public void testResponse(){
RestTemplate restTemplate = new RestTemplate();
Data data = new Data();
User user = new User();
Gson gson = new Gson();
String response = restTemplate.getForObject(
"https://apifrommyrequest.com/user/{id}",
String.class,
73442);
data = gson.fromJson(response, Data.class);
System.out.println(data);
}
If you want, you can design your POJO like this too(to reduce nested POJOs):
public class Data {
private User data;
//getters and setters
}
public class User {
private int id;
private String name;
private String urlPicture;
private String country;
#JsonProperty("address")
private void unpackNested(Map<String,String> elements)
{
this.country = elements.get("country");
}
//getters and setters
}
Then finally deserialize on Data class
you dont really need to do the conversion from string to object, resttemplate already use jackson that do it for u , just have to
YourObject response = restTemplate.getForObject(
"https://apifrommyrequest.com/user/{id}",
YourObject.class,
73442);
then it is going to do the mapping to your pojo objects, u dont really need gson in this scenario.
In my Spring Boot application I am creating a REST API, which is calling some other external REST API. I created User class, which is a object that is received by my Rest API downloaded from the external API. My user model looks like:
#JsonIgnoreProperties(ignoreUnknown = true)
public class User {
private String fullName;
private String department;
#JsonGetter("fullName")
public String getFullName() {
return fullName;
}
#JsonSetter("full_name")
public void setFullName(String fullName) {
this.fullName = fullName;
}
#JsonGetter("department")
public String getDepartment() {
return department;
}
#JsonSetter("department")
public void setDepartment(String department) {
this.department = department;
}
}
I am using JsonGetter and JsonSetter properties, because I would like to have my json properties in response returned in camelCase, but the properties given in external API are returned with underscore:
External API Response:
{
"full_name": "User A",
"department": "A",
}
My API Response:
{
"fullName": "User A",
"department": "A",
}
And everything seems to be working fine (hitting my API with Postman gives proper responses) until I started to create some Http request tests. In tests I receive assertion error that fullName property is null, while doing the same request in postman is responding with proper responses.
My test class:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HttpRequestTest {
#LocalServerPort
private int port;
#Autowired
private TestRestTemplate restTemplate;
#Test
public void shouldReturnUserFullName() throws Exception {
assertThat(this.restTemplate.getForObject("http://localhost:" + port + "/users/a",
User.class)).extracting(User::getFullName)
.contains("User A");
}
}
My controller method:
#GetMapping("users/{name}")
public ResponseEntity<User> getSpecificUserByName(#PathVariable("name") String name) {
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
HttpEntity<?> entity = new HttpEntity<>(headers);
ResponseEntity<User> response = restTemplate.exchange(createUriString(name), HttpMethod.GET, entity, User.class);
return response;
}
Test result:
java.lang.AssertionError:
Expecting:
<[null]>
to contain:
<["User A"]>
but could not find:
<["User A"]>
I would appreciate any help with this issue :)
#JsonSetter("full_name") expects your API response to contain a property full_name during deserialzation. Since #JsonGetter("fullName") converts full_name to fullName, field private String fullName; is never set.
You should change #JsonSetter("full_name") to #JsonSetter("fullName").
Let us take an example
Suppose your REST API returns below Object of User class
User reponse = new User();
response.setFullName("User A");
response.setDepartment("A");
So, when we call your REST API, the JSON response would look like as below
{
"fullName":"User A",
"department":"A"
}
Now, When you pass this JSON to convert into User class, Jackson will look for methods with the name setFullName and setDepartment.
In your test case, something similar is happening,
for code
this.restTemplate.getForObject("http://localhost:" + port + "/users/a",User.class)
First, it calls your API to get the User object Serialized and then it Deserialized it to User class. While Deserializing, it looks for a method named
setFullName without any
#Setter
#JsonProperty
#JsonAlias
annotations
or will look for any setter method with
#Setter("fullName")
#JsonProperty("fullName"),
#JsonAlias("fullName")
but in your case, the fullName setter is treated as
public void setFull_name(String fullName) {
this.fullName = fullname;
}
So, setter for fullName is not found but since you marked your User class as
#JsonIgnoreProperties(ignoreUnknown = true)
hence any exception is not thrown but fullName for your Response JSON is ignored, so fullName is never set, which remains null and your Test case is failing.
So, either change your test case or mark your setter with
#JsonAlias("fullName")
annotation.
i.e. Your User class will look like as below
#JsonIgnoreProperties(ignoreUnknown = true)
public class User {
private String fullName;
private String department;
#JsonGetter("fullName")
public String getFullName() {
return fullName;
}
#JsonAlias({"fullName","full_name"})
public void setFullName(String fullName) {
this.fullName = fullName;
}
#JsonGetter("department")
public String getDepartment() {
return department;
}
#JsonSetter("department")
public void setDepartment(String department) {
this.department = department;
}
}
I have userDTO like below, and
I am trying to convert userDTO to json string and calling rest API endpoint from my Controller, but the called rest API end point throws error as "data" is not valid JSONobject
public class UserDTO {
private String userId;
private String firstname;
private String lastname;
private List<Order> orders;
some more data member plus // setter / Getters
}
My controller class:- [converting userDTO to json string]
public class OrderController {
UserDTO userRecord = new UserDTO ();
// userRecord some values here
final HttpStatus httpStatus;
HttpEntity<?> httpEntity;
final HttpHeaders headers = new HttpHeaders();
final ObjectMapper mapper = new ObjectMapper();
headers.setContentType(MediaType.APPLICATION_JSON);
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
String jsonInput;
// I guess this is the point creating that issue. May be Im doing in wrong way....
jsonInput = mapper.writeValueAsString(new JSONObject().put("data",userRecord ));
httpEntity = new HttpEntity<Object>(jsonInput, headers);
// calling the rest API endpoint
ResponseEntity<String> responseEntity = restTemplate.exchange(
URL, HttpMethod.POST, httpEntity,
String.class,someId);
}
Server Sinippet:-
public MicroserviceResponse createOrder(#PathVariable("cId") final String cId, #RequestBody final String requestBody) throws Exception {
ObjectMapper mapper = new ObjectMapper();
requestJSON = new JSONObject(requestBody).getJSONObject("data");
final String jsonData = requestJSON.toString();
UserDTO orderSource = mapper.readValue(jsonData,
UserDTO .class);
}
Problem:-
Called API [server] throws "data is not valid JSONObject. Am i missing something here ? please guide me.
Trying to send below kind of JSON format
{
"data":{
"username":"test",
"orderId": "123097R",
"firstName":"xydz",
"lastName":"xyzd",
"email":"xx#gmail.com"
}
}
As there are no detailed server logs provided - I assume that the mentioned error is happening at the REST layer.
Please try this - create a payload Java class:
public class RestPayload implements java.io.Serializable {
private UserDTO data;
public UserDTO getUserDTO (){
return this.data;
}
public void setUserDTO(UserDTO data){
this.data = data;
}
}
And then modify your current rest operation to :
#POST
public MicroserviceResponse createOrder(#PathVariable("cId") final String cId, #RequestBody final RestPayload restPayload ) throws Exception {
UserDTO orderSource = restPayload.getUserDTO();
}
UPDATE:
You can also play with the raw JSON and modify the values according to your needs.
Try this - the below code shows how to add "data" as a parent object to the UserDTO :
Gson gson = new Gson();
JsonElement userDtoJsonElement = gson.toJsonTree(userDTO);
JsonObject dataObject = new JsonObject();
dataObject.add("data", userDtoJsonElement);
System.out.println(gson.toJson(dataObject));
I have a Json like the following.
{"person":[{"name":"asd","age":"22"},{"name":"asd","age":"22"}]}
but it could also be:
{"person":[{"name":"asd","age":"22"},{"name":"asd","age":"22"}],"city":["NewYork"],"student":"false"}
How can I receive it in a Spring Boot Controller?
You should use #RequestBody annotation.
#RequestMapping("/api/example")
public String example(#RequestBody String string) {
return string;
}
Later, add some validations and business logic.
You can generate custom class with http://www.jsonschema2pojo.org/. Once generated you can expect your custom class instead of String.
For further instructions, I find this tutorial interesting.
You can receive the json like below, Spring Boot will convert your json into model(For example "Comment" model below) which you defined.
#RequestMapping(value = "/create", method = RequestMethod.POST)
public ResultModel createComment(#RequestBody Comment comment) {...}
1) You need to difine your rest controllers. Example
#Autowired
UserService userService;
#RequestMapping(value = "/user/", method = RequestMethod.GET)
public ResponseEntity<List<User>> listAllUsers() {
List<User> users = userService.findAllUsers();
if (users.isEmpty()) {
return new ResponseEntity(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<List<User>>(users, HttpStatus.OK);
}
2) Define your pojo: Example
public class User {
String name;
String age;
public User(String name, String age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
}
3) Define a service
#Service
public class UserService {
public List<User> findAllUsers(){
// Those are mock data. I suggest to search for Spring-data for interaction with DB.
ArrayList<User> users = new ArrayList<>();
User user = new User("name", "5");
users.add(user);
return users;
}
}
You can follow this tutorial. If you want to just send a json message to a spring boot rest controller you can use a rest client like postman.