JSON parserError while creating user in Openfire through spring boot application - spring-boot

In my project I have to create a chat box. For that I have to use Open-fire server. I am having the service for creating users in this server.
I am facing the problem when I am trying to access the openfire service from my spring boot application.
I am have created the model for the user also created the service and provided implementation to it.
This is my model class,
public class OpenFireUser {
private String firstname;
private String username;
private String password;
private String email;
<----getters and setters--->
}
This is my service,
public UserCreationResponse createOpenFireUser(String authorization,User createUser) {
OpenFireUser user= new OpenFireUser();
user.setEmail(createUser.getEmail());
user.setFirstname(createUser.getFirstname().toLowerCase());
user.setPassword("Passw0rd");
user.setUsername(createUser.getUsername().toLowerCase());
UserCreationResponse response=new UserCreationResponse();
RestTemplate restTemplate = new RestTemplate();
try{
MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
headers.add("Authorization", authorization);
headers.add("Content-Type", "application/json");
headers.add("Accept", "application/json");
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
HttpEntity<OpenFireUser> requestObject = new HttpEntity<OpenFireUser>(user, headers);
ResponseEntity<String> responseEntity=restTemplate.postForEntity(OPENFIRE_REST_ENDPOINT, requestObject,String.class);
int statusCode = responseEntity.getStatusCodeValue();
if(statusCode==201){
response.setResponseCode(statusCode);
return response;
}else{
response.setResponseCode(MessageConstant.ResponseCode.ProcessFail.value());}
return response;
}catch(HttpClientErrorException clientErr){
response.setUserMessage(clientErr.getMessage());
response.setResponseCode(clientErr.getStatusCode().value());
response.setResponseMessage(MessageConstant.CodeMessage.ProcessFail.value());
return response;
}
catch(Exception e)
{
response.setResponseCode(MessageConstant.ResponseCode.ProcessFail.value());
response.setResponseMessage(MessageConstant.CodeMessage.ProcessFail.value());
return response;
}
}
This is controller code for calling service,
#RequestMapping(value = "/createOpenFireUser", method = RequestMethod.POST, consumes = "application/json;charset=UTF-8",produces = "application/json;charset=UTF-8")
public UserCreationResponse createOpenFireUser(#RequestBody User createUser) {
logger.debug("Entering inside createOpenFireUser(#RequestBody OpenFireUser createUser) method");
//logger.debug("Create user request : {}" , createUserRequestEntity);
return userService.createOpenFireUser("authorizationKey",createUser);
}
while sending data from postman I am getting error like,
Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Can not deserialize instance of com.exelatech.printshop.model.User out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of com.exelatech.printshop.model.User out of START_ARRAY token
at [Source: java.io.PushbackInputStream#6c88daca; line: 1, column: 1]
2018-07-20 15:59:13.535 WARN 9988 --- [nio-9090-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Can not deserialize instance of model.User out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of model.User out of START_ARRAY token
at [Source: java.io.PushbackInputStream#6c88daca; line: 1, column: 1]
On postman I am getting response like,
"timestamp": 1532082553781,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.http.converter.HttpMessageNotReadableException",
"message": "JSON parse error: Can not deserialize instance of model.User out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of model.User out of START_ARRAY token\n at [Source: java.io.PushbackInputStream#6c88daca; line: 1, column: 1]",
Can anyone help me to solve my issue?

Error was in sending object through postman.
Previously I was sending request object like,
[
{
"firstname" : "Jyoti",
"username" : "JyotiNH",
"password":"Passw0rd",
"email" : "jyoti.kanor#exelaonline.com"
}
]
which is object.
But my method receiving parameter as array of strings,
So when I sent request with object like following structure, it successfully created the user.
{
"firstname" : "Jyoti",
"username" : "JyotiNH",
"password":"Passw0rd",
"email" : "jyoti.kanor#exelaonline.com"
}

Related

Why sending a request to controller using Postman runs fine but using RestTemplate throws 500 Internal Server Error?

Context
I have two controllers: /testParams and /callTestParams
Controller /testParams receives an object of type Example and I can call this controller from Postman without any problem.
Controller /callTestParams calls /testParams internally using RestTemplate but the response is a 500 Internal Server Error. I supose that the implementation of /callTestParams is equivalent to the call maded by Postman.
Here is the code:
#RequestMapping(value = "/testParams",
method = RequestMethod.POST, produces = "application/json", consumes = "application/json")
public ResponseEntity<Object> testParams(
#RequestBody Example credentials
) {
JSONObject params = new JSONObject( credentials );
System.out.println( params.get("clientId") + " from JSONObject");
System.out.println( credentials.getClientId() + " from GraphCredentials");
return new ResponseEntity<>(credentials,HttpStatus.OK);
}
#RequestMapping(value = "/callTestParams",
method = RequestMethod.POST, produces = "application/json", consumes = "application/json")
public ResponseEntity<Object> callTestParams() {
String url = "http://localhost:8080/GraphClient/testParams";
HttpHeaders headers = new HttpHeaders();
headers.set( HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE );
JSONObject params = new JSONObject();
params.put("clientId", "value1" );
RestTemplate restTemplate = new RestTemplate();
HttpEntity<?> entity = new HttpEntity<>(params,headers);
HttpEntity<Object> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
Object.class
);
return new ResponseEntity<>(response.getBody(), HttpStatus.OK);
}
This is the response from Postman for /testParams
Headers:
(Content-Type,application/json)
Request Body:
JSON (appplication/json)
{"clientId":"value1"}
Response:
{
"clientId": "value1",
"clientSecret": null,
"tenantId": null,
"scope": null,
"grantType": null,
"microsoftLoginBaseURL": "https://login.microsoftonline.com/"
}
This is the response from Postman for /callTestParams
{
"timestamp": "2022-01-09T03:39:06.878+0000",
"status": 500,
"error": "Internal Server Error",
"message": "500 Internal Server Error",
"path": "/GraphClient/callTestParams"
}
This is the error in the console>
Forwarding to error page from request [/testParams] due to exception [JSONObject["clientId"] not found.]: org.json.JSONException: JSONObject["clientId"] not found.
In the parameter of the body of the HttpEntity constructor you need to pass params as String
HttpEntity<?> entity = new HttpEntity<>(params.toString(),headers);

How to change WebClient behaviour concerning LocalDateTime?

I am using Spring Boot 2.4.5 and try to request a REST API of another application using WebClient. I know that the other application provides the requested information as a Collection.
When I use an Object[] to receive the response:
Object[] ob = (Object[]) webClient
.get()
.uri(endpoint)
// .bodyValue(criteria)
.exchangeToMono(response -> {
if (response.statusCode()
.equals(HttpStatus.OK)) {
return response.bodyToMono(Object[].class);
} else if (response.statusCode()
.is4xxClientError()) {
return Mono.just("Error response");
} else {
return response.createException()
.flatMap(Mono::error);
}
}).block();
I can see that I receive a LinkedHashMap with all the values including a field:
date_of_declaration -> 2020-03-02T08:43:10
However, if possible, I want to let WebClient immediately convert the response into the designated DTOs...
DeclarationDTO[] ob = (DeclarationDTO[]) webClient
.get()
.uri(endpoint)
// .bodyValue(criteria)
.exchangeToMono(response -> {
if (response.statusCode()
.equals(HttpStatus.OK)) {
return response.bodyToMono(DeclarationDTO[].class);
} else if (response.statusCode()
.is4xxClientError()) {
return Mono.just("Error response");
} else {
return response.createException()
.flatMap(Mono::error);
}
}).block();
...I get an exception when a LocalDateTime object shall be deserialized.
org.springframework.core.codec.DecodingException: JSON decoding error: Cannot deserialize value of type `java.time.LocalDateTime` from String "02-03-2020 01:20:00": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '02-03-2020 01:20:00' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {HourOfAmPm=1, NanoOfSecond=0, SecondOfMinute=0, MicroOfSecond=0, MinuteOfHour=20, MilliOfSecond=0},ISO resolved to 2020-03-02 of type java.time.format.Parsed; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.LocalDateTime` from String "02-03-2020 01:20:00": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '02-03-2020 01:20:00' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {HourOfAmPm=1, NanoOfSecond=0, SecondOfMinute=0, MicroOfSecond=0, MinuteOfHour=20, MilliOfSecond=0},ISO resolved to 2020-03-02 of type java.time.format.Parsed
at [Source: (io.netty.buffer.ByteBufInputStream); line: 1, column: 1438] (through reference chain: java.lang.Object[][0]->de.xxx.myportal.api.infrastructure.dto.MyDTO["a_person"]->de.xxx.myportal.api.infrastructure.dto.APersonDTO["foobar"])
I think WebClient has an internal ObjectMapper, so maybe it is possible to modify this ObjectMapper during WebClient instantiation? ...or is there a better way to tell Webclient how to handle LocalDateTime? ...maybe a WebClient customized by a configuration or...?
I can't explain but after removing any JsonFormat annotation it works out of the box. (Weird!)
This may help https://www.baeldung.com/spring-boot-formatting-json-dates
In your DeclarationDTO you can use something like:
#JsonFormat(pattern="yyyy-MM-dd'T'HH:mm:ss")
#JsonProperty("date_of_declaration")
private LocalDateTime dateOfDeclaration;

Unable to generate access token

I am getting exception while generating an Access Token using feign client. The same payload is working fine in the Postman.
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("grant_type", "client_credentials");
map.add("client_id", "67881e5b-f5d5-4085-8762-c35b7b6aeede");
map.add("client_secret", "D-85Pg3wN63dmznxa-puB_89Po~o5CsKhA");
map.add("scope", "https://graph.microsoft.com/.default");
AccessTokenResponse openIdTokenResponse = graphAPILoginFeignClient.getAccessIdToken("5494cc2e-fb14-4a2d-bb5e-bf164d9141cf",request);
Feignclient code:
#FeignClient(name = "GraphAPILoginFeignClient", url = "${graphApiLoginUrl}")
public interface GraphAPILoginFeignClient {
#PostMapping(value = "/{tenantID}/oauth2/v2.0/token",consumes = MediaType.APPLICATION_JSON_VALUE)
AccessTokenResponse getAccessIdToken(#PathVariable("tenantID") String tenantID,
#RequestBody MultiValueMap<String, Object> request);
}
Exception:
{
"timestamp": "2021-01-27T17:30:34.456+00:00",
"message": "[400 Bad Request] during [POST] to [https://login.microsoftonline.com/5494cc2e-fb14-4a2d-bb5e-bf164d9141cf/oauth2/v2.0/token] [GraphAPILoginFeignClient#getAccessIdToken(String,AuthorizationTokenRequest)]:
[{\"error\":\"invalid_request\",
\"error_description\":\"AADSTS900144: The request body must contain the
following parameter: 'grant_type'.\\r\\n
Trace ID: b8ef5f37-95f7-4427-8f0e-146a34b65000\\r\\n
Correlation ID: ... (503 bytes)]","details": "uri=/accessmanagement/allusers"
}
Same request payload working from Postman:
I had the same problem and the same code.
I was able to successfully execute the code by replacing the class method MultiValueMap::put with MultiValueMap::set.
In the LinkedMultiValueMap class, these methods are implemented differently.

RestTemplate including body in exception

Suppose I call a webservice with RestTemplate and it returns 500 status error with this body:
{
"timestamp": "2019-10-10T16:51:15Z",
"status": 500,
"error": "Internal Server Error",
"message": "Error occurred while retrieving entity with id: bb00b45c-9e17-4d75-a89a",
"path": "/api/service"
}
Currently RestTemplate exception message is something like:
Caused by: org.springframework.web.client.HttpServerErrorException$InternalServerError: 500 null
at org.springframework.web.client.HttpServerErrorException.create(HttpServerErrorException.java:79)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:124)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:102)
Is there any way to include the body of the response in the RestTemplate exception message without using a custom error handler?
Thanks!
May be something like this (without a Custom Error Handler)
ObjectMapper mapper;
try {
ResponseEntity<User> response = restTemplate.exchange(url,
HttpMethod.POST, requestEntity, User.class);
} catch (HttpStatusCodeException e) {
List<String> header = e.getResponseHeaders().get("x-app-err-id");
String errorMessageId = "";
if (header != null && !header.isEmpty()) {
errorMessageId = header.get(0);
}
// You can get the body, but deserialise it using mapper into a POJO
ErrorResponseBody errorResponseBody = mapper.readValue(e.getResponseBodyAsString(),
ErrorResponseBody.class);
// You can re-throw it if you want or use the response body
throw new CustomException(e, HttpStatus.INTERNAL_SERVER_ERROR);
}

Spring MVC Map Request Body to Primitive Type

I want to handle simple POST request by spring mvc. The request body contain only a single int value. Can anyone help me to write the action method. My code is below:
#PostMapping(value = "/update")
#ResponseBody
public ResponseEntity updateLogLevel(#RequestBody int level) {
try {
//process request
} catch (Exception ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
}
return ResponseEntity.ok(Constant.STATUS_SUCCESS);
}
But this code throw exception:
org.springframework.http.converter.HttpMessageNotReadableException",
"message":"JSON parse error: Can not deserialize instance of int out of START_OBJECT token;
nested exception is
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of int out of START_OBJECT token
My request body:
{
"level" : 100
}
You are sending in your payload an object not integer, just send the number
100

Resources