Spring Boot: Json Response is not Mapping to Entity - java

I am trying to map this Json response I consume through a secured RESTful API; however, the mapping is for some reason not happening correctly as I keep getting a NULL response instead of populated object.
This is my entity:
#JsonTypeName("order")
#JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT ,use = JsonTypeInfo.Id.NAME)
public class Order {
#JsonProperty("id")
private long customerd;
#JsonProperty("email")
private String customeEmail;
public long getCustomerd() {
return customerd;
}
public void setCustomerd(long customerd) {
this.customerd = customerd;
}
public String getCustomeEmail() {
return customeEmail;
}
public void setCustomeEmail(String customeEmail) {
this.customeEmail = customeEmail;
}
}
This is my service method:
public Order orderDetails (#RequestBody Order order){
String username = "username";
String password = "password";
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth(username, password);
// request url
String url = "https://test.myshopify.com/admin/orders/2013413015655.json";
RestTemplate restTemplate = new RestTemplate();
HttpEntity request = new HttpEntity(headers);
ResponseEntity<Order> response = restTemplate.exchange(
url, HttpMethod.GET, request, Order.class);
return order;
}
This is my Controller Method:
#GetMapping("/orderdetails")
#ResponseStatus(HttpStatus.FOUND)
public Order getBasicAut(Order order){
return basicAuth.orderDetails(order);
}

You should configure your REST to produce the JSON content
#GetMapping(path = "/orderdetails", produces = {MediaType.APPLICATION_JSON_VALUE})
Specifically, those codes below work well
#RestController
public class JsonController {
#GetMapping(path = "/orderdetails", produces = {MediaType.APPLICATION_JSON_VALUE})
#ResponseStatus(HttpStatus.FOUND)
public Order sendJsonBack() {
final Order order = new Order();
order.setCustomerd(123L);
order.setCustomeEmail("mail#gmail.com");
return order;
}
}
#Data
class Order implements Serializable {
private static final long serialVersionUID = -4258392267221190600L;
#JsonProperty("id")
private long customerd;
#JsonProperty("email")
private String customeEmail;
}

The issue was with what my methods were returning. They both have to return a ResponseEntity of type Order as in:
public ResponseEntity<Order> orderDetails (#RequestBody Order order){
String username = "username";
String password = "password";
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth(username, password);
// request url
String url = "https://test.myshopify.com/admin/orders/2013413015655.json";
RestTemplate restTemplate = new RestTemplate();
HttpEntity request = new HttpEntity(headers);
ResponseEntity<Order> response = restTemplate.exchange(
url, HttpMethod.GET, request, Order.class);
return response;
}
And my Controller to:
#GetMapping("/orderdetails")
#ResponseStatus(HttpStatus.FOUND)
public ResponseEntity<Order> getBasicAut(Order order){
return basicAuth.orderDetails(order);
}

Related

Spring RestTemplate PUT with parameters

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())

Using params in GetMapping in Spring results in ambiguous handler method for multiple parameters

I have the following REST endpoints in Spring boot
#GetMapping(value = "students", params = {"name"})
public ResponseEntity<?> getByName(#RequestParam final String name) {
return new ResponseEntity<>(true, HttpStatus.OK);
}
#GetMapping(value = "students", params = {"tag"})
public ResponseEntity<?> getByTag(#RequestParam final String tag) {
return new ResponseEntity<>(true, HttpStatus.OK);
}
The above handlers work fine for the following requests:
localhost:8080/test/students?name="Aron"
localhost:8080/test/students?tag="player"
However, whenever I try the following:
localhost:8060/test/students?name="Aron"&tag="player"
it throws java.lang.IllegalStateException: Ambiguous handler methods mapped and responds with an HTTP 500
How can I change this behavior? I want my app to respond only when I get either a tag query parameter or a name query parameter.
For anything else, I want it to ignore even if it's a combination of two parameters.
Why is it throwing the ambiguous error here and how can we handle that?
You can use #RequestParam(required = false):
#GetMapping(value = "students")
public ResponseEntity<?> get(
#RequestParam(required = false) final String name,
#RequestParam(required = false) final String tag) {
if ((name == null) == (tag == null)) {
return new ResponseEntity<>(false, HttpStatus.BAD_REQUEST);
}
return new ResponseEntity<>(true, HttpStatus.OK);
}
it seems you can use negations in params. Something like:
#GetMapping(value = "students", params = {"name", "!tag"})
public ResponseEntity<?> getByName(#RequestParam final String name) {
return new ResponseEntity<>(true, HttpStatus.OK);
}
#GetMapping(value = "students", params = {"tag", "!name"})
public ResponseEntity<?> getByTag(#RequestParam final String tag) {
return new ResponseEntity<>(true, HttpStatus.OK);
}
References: Advanced #RequestMapping options

Parse json with Objects to model Object - Java Spring

I have model:
public class StudyModel {
#Id
private String ID;
private boolean isStable;
private String LastUpdate;
private MainTest test;
public static class MainTest {
private String test1;
private String test2;
}
}
I want to parse it to my model.
It works correctly but when it goes to MainTest where on json file I have couple values it fails and I have null on the rest of fields.
How I can deal with it?
public StudyModel getStudyDetails(String studyId){
RestTemplate restTemplate = new RestTemplate();
String url = URL + "studies/" + studyId;
ResponseEntity<String> serverResponse = restTemplate.getForEntity(url, String.class);
Gson g = new Gson();
String json = serverResponse.getBody();
StudyModel study = g.fromJson(json, StudyModel.class);
return study;
}
RestTemplate can handle deserialization for you
ResponseEntity<StudyModel> serverResponse = restTemplate.getForEntity(url, StudyModel.class);
StudyModel studyModel = serverResponse.getBody();

JSON conversion error from java Pojo

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));

Using kafka as messaging queue

I am trying to use Kafka as a messaging queue in my controller (so task):
#RequestMapping("users")
#RestController
public class UserController extends BaseController {
private static final String KAFKA_TOPIC = "virto_users";
#Autowired
private KafkaTemplate<String, String> mKafkaTemplate;
#PutMapping(value = "{id}")
public ResponseEntity<String> put(#PathVariable UUID id,
#RequestBody String profile) {
String url = ServerConfig.USERS_HOST + "/users/" + id;
ResponseEntity<String> entity = request.put(url, profile);
HttpStatus status = entity.getStatusCode();
if (status == HttpStatus.CREATED || status == HttpStatus.NO_CONTENT) {
return entity;
}
JSONObject json = new JSONObject();
json.put("id", id);
json.put("profile", profile);
sendMessage(json.toString());
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
public void sendMessage(String msg) {
mKafkaTemplate.send(KAFKA_TOPIC, msg);
}
#KafkaListener(topics = KAFKA_TOPIC, groupId = KafkaConfig.GROUP_ID)
public void listen(String message) {
JSONObject json = new JSONObject(message);
UUID id = UUID.fromString(json.getString("id"));
String profile = json.getString("profile");
put(id, profile);
}
}
If my inner service is available and returned CREATED or NO_CONTENT then all is right and I can return result else I need to return the NO_CONTENT status and put this message in my queue to try again until it will be processed. I made it like above but it doesn't look like a good solution, imho. I wanted to ask just for a some advice how can I improve this solution or that it's normal.

Categories

Resources