JSON decoding error: Invalid UTF-8 start byte 0xb0 - java

I have a problem when I run the Junit for this method:
public ResponseEntity<InputStreamResource> xlsexp(#RequestHeader MultiValueMap<String, String> headerMap,
#RequestBody ExRequest request) {
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "attachment; filename=example.xls");
return ResponseEntity
.ok()
.headers(headers)
.body(exportatorService.exportToXls(request));
}
And the test is:
public void testing_01() {
this.webClient.post()
.uri("/xlsexp")
.accept(MediaType.APPLICATION_JSON_UTF8)
.header(...., ....)
.
.
.body(BodyInserters.fromValue(request))
.exchange()
.expectStatus().isEqualTo(HttpStatus.OK)
.expectBody(ResponseEntity.class);
}
And the exception is:
org.springframework.core.codec.DecodingException: JSON decoding error: Invalid UTF-8 start byte 0xb0; nested exception is com.fasterxml.jackson.core.JsonParseException: Invalid UTF-8 start byte 0xb0
at [Source: (org.springframework.core.io.buffer.DefaultDataBuffer$DefaultDataBufferInputStream); line: 1, column: 12]
at org.springframework.http.codec.json.AbstractJackson2Decoder.processException(AbstractJackson2Decoder.java:242)
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ Body from POST /xlsexp [DefaultClientResponse]
Stack trace:
at org.springframework.http.codec.json.AbstractJackson2Decoder.processException(AbstractJackson2Decoder.java:242)
at org.springframework.http.codec.json.AbstractJackson2Decoder.decode(AbstractJackson2Decoder.java:198)
at org.springframework.http.codec.json.AbstractJackson2Decoder.lambda$decodeToMono$1(AbstractJackson2Decoder.java:179)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:125)
at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107)
at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onNext(FluxMapFuseable.java:295)
at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:337)
My intention is test with Junit the method for export to Excel. Do you have any idea what could be happening?
Thanks

Related

Handling long string with IOUtils

I want to handle MethodArgumentNotValidException in a Springboot application. My entry point is expecting a valid JSON object. I do intercept the error message correctly:
"message": "JSON parse error: Cannot deserialize value of type `java.util.LinkedHashMap<java.lang.String,java.lang.Object>` from Array value (token `JsonToken.START_ARRAY`); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.util.LinkedHashMap<java.lang.String,java.lang.Object>` from Array value (token `JsonToken.START_ARRAY`)\n at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 5, column: 7] (through reference chain: fr.ws.ui.model.request.RequestModel[\"data\"]->java.util.ArrayList[0])",
That's great... Here is my exception handler implementation.
#ExceptionHandler(value = { MethodArgumentNotValidException.class, HttpMessageNotReadableException.class })
public ResponseEntity<ErrorMessage> handleHttpMessageNotReadableException(HttpMessageNotReadableException ex,
WebRequest req) throws JsonProcessingException {
// weird behavior, I got the json but not complete
String output;
try {
output = IOUtils.toString(((ServletWebRequest) req).getRequest().getInputStream(), StandardCharsets.UTF_8);
System.out.println(output);
} catch (IOException e) {
throw new RuntimeException(e);
}
ErrorMessage errorMessage = ErrorMessage.builder()
.operationId(Utils.generateId())
.status(RequestOperationStatus.ERROR.name())
.message(ex.getMessage())
.createdAt(new Date())
.data(output)
.build();
return new ResponseEntity<>(errorMessage, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR);
}
Now, I want to retrieve the body of my request and I want to parse the content to extract data for building the ErrorMessage body. For this I used org.apache.commons.io library:
IOUtils.toString(((ServletWebRequest) req).getRequest().getInputStream(), StandardCharsets.UTF_8)
The request contains several properties and a file in Base64 format.
It works fine but not totally: I do not retrieve the full request body, I do not get the request body start. My String seems truncated. How can i get the whole request as String ?

WebClient builder Post Call giving bad request error for first time in Webflux

First post request giving bad request error for Webclient on first click.
org.springframework.web.reactive.function.client.WebClientResponseException$BadRequest: 400 Bad Request from POST
After that every request process succsfully.
exception i'm getting below
* Submitting xyz
* #param submitFlowRequest
*/
#Override
public Mono<ApiResponse<SubmitResponse>> submitFlow(SubmitFlowRequest submitFlowRequest,
Map<String, String> headers) {
long startTime = System.currentTimeMillis();
String uri = propertyConfig.getAggregationService()
+ propertyConfig.getAggregationSubmitCCInfoURL();
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(uri);
factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.URI_COMPONENT);
MultiValueMap<String, String> clientHeaders = buildHeaders(headers);
return webClientBuilder.uriBuilderFactory(factory).build().post()
.headers(httpHeaders -> httpHeaders.addAll(clientHeaders)).accept(MediaType.APPLICATION_JSON)
.syncBody(submitFlowRequest).retrieve().bodyToMono(ApiResponse.class)
.onErrorMap(ConnectException.class,
error -> new VzwRuntimeException(ErrorCodeEnum.V404.toString(), Constants.OPP_TC_SYSTEM_ERROR,
(Constants.CONNECTION_FAILURE_TEXT + Constants.AGGREGATION)))
.onErrorMap(WebClientResponseException.class,
error -> new VzwRuntimeException(ErrorCodeEnum.V404.toString(), Constants.OPP_TC_SYSTEM_ERROR,
(Constants.CONNECTION_FAILURE_TEXT + Constants.AGGREGATION)))
.flatMap(res -> {
Audit apiAudit = Audit.builder().apiUrl(uri).request(LoggerUtil.asJson(submitFlowRequest))
.response(LoggerUtil.asJson(res))
.executionTime(String.valueOf(System.currentTimeMillis() - startTime))
.headers(LoggerUtil.asJson(clientHeaders)).transactionType(res.getData()!=null?mapper.map(res.getData(), SubmitResponse.class).getTransactionType():"").build();
LoggerUtil.logExternalApiCalls(apiAudit);
return Mono.just((ApiResponse<SubmitResponse>) res);
});
}
Exception :::
org.springframework.web.reactive.function.client.WebClientResponseException$BadRequest: 400 Bad Request from POST http://WKWIN93.global.sangwan.net:9898/payment-ag/v1/creditcard/submitCreditCardInfo
at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:179)
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ 400 from POST http://payment-service/payment-ag/v1/creditcard/submitCreditCardInfo [DefaultWebClient]
Stack trace:
at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:179)
at org.springframework.web.reactive.function.client.DefaultClientResponse.lambda$createException$1(DefaultClientResponse.java:209)
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:100)
at com.sgw.common.logging.mdc.MDCContextHelper.onNext(MDCContextHelper.java:30)
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1630)
at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onComplete(FluxDefaultIfEmpty.java:100)
at com.sgw.common.logging.mdc.MDCContextHelper.onComplete(MDCContextHelper.java:46)
at reactor.core.publisher.FluxHide$SuppressFuseableSubscriber.onComplete(FluxHide.java:137)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onComplete(FluxMapFuseable.java:144)
at reactor.core.publisher.FluxContextStart$ContextStartSubscriber.onComplete(FluxContextStart.java:122)

Unable to download file: Could not find acceptable representation

This has tons of example on the internet but for some reason I just cannot download a csv file. I keep getting the error:
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation`.
Here is the code below for my #RestController:
#GetMapping(value = "/tasks/{taskId}/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public ResponseEntity<InputStreamResource> download(#PathVariable String taskId, #RequestParam String format) throws IOException {
var path = "string path to file"
var file = new UrlResource(Path.of(path).normalize().toUri());
return ResponseEntity
.ok()
.contentLength(file.contentLength())
.contentType(
MediaType.parseMediaType("application/octet-stream"))
.body(new InputStreamResource(file.getInputStream()));
}
I set the header Accept: application/octet-stream but still get the same error. What could be wrong any ideas?

no suitable HttpMessageConverter found for response type and content type

I was trying to get the ResponseEntity with spring rest template as given below. I am getting the below error,
Caused by: org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [interface org.springframework.security.oauth2.common.OAuth2AccessToken] and content type [application/json;charset=ISO-8859-1]
Code:
ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails();
resource.setAccessTokenUri("https://.../oauth2/token");
resource.setUsername("u");
resource.setPassword("p");
resource.setClientSecret(".....s");
resource.setClientId("....i");
resource.setGrantType("password");
List<String> scopes = new ArrayList<String>(2);
scopes.add("write");
scopes.add("read");
resource.setScope(scopes);
OAuth2RestTemplate oAuthRestTemplate = new OAuth2RestTemplate(resource);
try{
SSLUtil.turnOffSslChecking();
ResponseEntity<String> result = oAuthRestTemplate.getForEntity("https:......." + "/api/version", String.class);
System.out.println(result);
} catch (RestClientException e) {
e.printStackTrace();
}
I tried setting Media type as Application/json as in this post.But still the same error.
Full trace:
Exception in thread "main" error="access_denied", error_description="Error requesting access token."
at org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport.retrieveToken(OAuth2AccessTokenSupport.java:121)
at org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordAccessTokenProvider.obtainAccessToken(ResourceOwnerPasswordAccessTokenProvider.java:47)
at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainNewAccessTokenInternal(AccessTokenProviderChain.java:142)
at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainAccessToken(AccessTokenProviderChain.java:118)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.acquireAccessToken(OAuth2RestTemplate.java:216)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:168)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.createRequest(OAuth2RestTemplate.java:89)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:479)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.doExecute(OAuth2RestTemplate.java:123)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:446)
at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:236)
at com.ClientTemplate.main(ClientTemplate.java:56)
Caused by: org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [interface org.springframework.security.oauth2.common.OAuth2AccessToken] and content type [application/json;charset=ISO-8859-1]
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:107)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:491)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:454)
at org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport.retrieveToken(OAuth2AccessTokenSupport.java:113)
... 11 more
You need to add MappingJackson2HttpMessageConverter and add content type to be application/json to the header. See here

File Download from Dropbox

I am going to download file from Dropbox. they have provided their API for this but I am getting ERROR 400.
My code is:
RestTemplate restTemplate = new RestTemplate();
RestCall re= new RestCall();
ClientHttpRequestInterceptor ri = re.new LoggingRequestInterceptor();
List<ClientHttpRequestInterceptor> ris = new ArrayList<>();
ris.add(ri);
restTemplate.setInterceptors(ris);
PathEntity pathEntity = new PathEntity();
pathEntity.setPath("/Apps/DemoVivekApp/home/xpointers/Desktop/dmo/test");
ObjectMapper objectMapper = new ObjectMapper();
String jsonString = objectMapper.writeValueAsString(pathEntity);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM));
httpHeaders.add("Authorization","Bearer ItdjL2a2ihAAAAAAAAAAFd3cJhYxpQhbtlXjgb6RleJ7xVQj_Pon");
httpHeaders.add("Dropbox-API-Arg",jsonString);
httpHeaders.add("User-Agent", "api-explorer-client");
HttpEntity<PathEntity> entity = new HttpEntity<>(httpHeaders);
ResponseEntity<byte[]> response = restTemplate.exchange(DIRECT_FILE_DOWNLOAD, HttpMethod.POST, entity, byte[].class, "1");
PathEntity.java :
public class PathEntity {
private String path;
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
}
I tried to print my http request which is printed as below :
{Accept=[application/octet-stream, application/json, application/*+json, */*], Content-Type=[application/json], Authorization=[Bearer ItdjL2a2ihAAAAAAAAAAFd3cJhYxpQhbtlXjgb6RleJ7xVQj_Pon], Dropbox-API-Arg=[{path":"/newApp/ccJAR}], User-Agent=[api-explorer-client], Content-Length=[0]}
UPDATE:
My response body is :
org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://content.dropboxapi.com/2/files/download": Server returned HTTP response code: 400 for URL: https://content.dropboxapi.com/2/files/download; nested exception is java.io.IOException: Server returned HTTP response code: 400 for URL: https://content.dropboxapi.com/2/files/download
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:607)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:557)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:475)
at com.demo.RestCall.main(RestCall.java:134)
Caused by: java.io.IOException: Server returned HTTP response code: 400 for URL: https://content.dropboxapi.com/2/files/download
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1876)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1474)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
at org.springframework.http.client.SimpleClientHttpResponse.getBody(SimpleClientHttpResponse.java:81)
at com.demo.RestCall$LoggingRequestInterceptor.log(RestCall.java:199)
at com.demo.RestCall$LoggingRequestInterceptor.intercept(RestCall.java:192)
at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:85)
at org.springframework.http.client.InterceptingClientHttpRequest.executeInternal(InterceptingClientHttpRequest.java:69)
at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:596)
... 3 more
For download you have to use GET request instead of post.
ResponseEntity<byte[]> response = restTemplate.exchange(DIRECT_FILE_DOWNLOAD, HttpMethod.POST, entity, byte[].class, "1");
Change like below
ResponseEntity<byte[]> response = restTemplate.exchange(downloadFilePath, HttpMethod.GET, entity, byte[].class, "1");
Hope this will helps you.

Categories