restTemplate.postForObject org.springframework.web.client.HttpClientErrorException: 404 Not Found - spring

#RequestMapping(method = RequestMethod.POST, produces = {
MediaType.APPLICATION_JSON_VALUE })
public #ResponseBody String provisionUser(#RequestBody(required = true) String body) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("key", "<key>");
HttpEntity<String> request = new HttpEntity<String>(body, headers);
String APIendpoint = "https://apiendpont.com/provision";
String obj = restTemplate.postForObject(APIendpoint, request, String.class);
return obj;
}
the restTemplate.postForObject() line in the above method is returning
org.springframework.web.client.HttpClientErrorException: 404 Not Found
I have tested the uri, and the header information in a REST client and receive a response - so I know that is the correct url.
I ran this in debug mode and the exception is thrown in RestTemplate.doExecute
protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback,
ResponseExtractor<T> responseExtractor) throws RestClientException {
Assert.notNull(url, "'url' must not be null");
Assert.notNull(method, "'method' must not be null");
ClientHttpResponse response = null;
try {
ClientHttpRequest request = createRequest(url, method);
if (requestCallback != null) {
requestCallback.doWithRequest(request);
}
response = request.execute();
if (!getErrorHandler().hasError(response)) {
logResponseStatus(method, url, response);
}
else {
handleResponseError(method, url, response);
}
if (responseExtractor != null) {
return responseExtractor.extractData(response);
}
else {
return null;
}
}
catch (IOException ex) {
throw new ResourceAccessException("I/O error on " + method.name() +
" request for \"" + url + "\":" + ex.getMessage(), ex);
}
finally {
if (response != null) {
response.close();
}
}
}
Any ideas on what's going on? Thanks.

Related

Get response body 401 spring

I'm consuming a service using Spring's Rest Template. I'm getting error 401 in response: [no body]. But I'm doing the same query by postman, and I get the body. can anybody help me?
code:
private static List<AcervoMarcSecao> assinar(List<AcervoMarcSecao> acervosMarcSecao, byte[] imgAssinatura) throws ClientException, IOException {
restTemplate = new RestTemplate();
ResponseEntity<String> response = null;
HttpEntity<?> request = getHttpEntity(acervosMarcSecao, imgAssinatura);
try {
response = restTemplate
.exchange(parametros.get("SERVICE_HUB2_BASE_URL") + "/fw/v1/pdf/kms/lote/assinaturas",
HttpMethod.POST, request, String.class);
if(response.getBody() != null) {
LoteAssinaturaDTO loteAssinatura = new Gson().fromJson(response.getBody(), LoteAssinaturaDTO.class);
for(int i = 0; i < acervosMarcSecao.size(); i++) {
byte[] documentoAssinado = ImageRecover.recoverImageFromUrl(loteAssinatura.getDocumentos().get(i)
.getLinks().get(0).getHref());
if(documentoAssinado != null)
if(acervosMarcSecao.get(i).getVinculo() == null)
acervosMarcSecao.get(i).setVinculo(new Vinculos());
acervosMarcSecao.get(i).getVinculo().setArquivoAssinado(documentoAssinado);
acervosMarcSecao.get(i).getVinculo().setDataGravacao(new Date());
}
}
return acervosMarcSecao;
} catch (RestClientResponseException e) {
ErrorDTO error = new Gson().fromJson(e.getResponseBodyAsString(), ErrorDTO.class);
if(error.getChave().equals("excecao.hub.perfil")) {
throw new AlertaException(resourceBundle.getString("lblTipoAssinaturaDigitalInvalida"));
}
throw new AlertaException(error.getMessage());
} catch (Exception e) {
throw new AlertaException(resourceBundle.getString("txtErroCertificarArquivo"));
}
}
postman:

Handling multipart response from spring rest controller

I am having controller method like this
#PostMapping(path = "/downloadAttachment",
produces = "application/octet-stream")
public ResponseEntity<?> downloadAttachment(#Valid #RequestBody Attachment attachmentModel) {
refreshProp(false);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
try {
String byteRes = null;
JSONArray responseFromDownloadAttachment =
databaseOperations.downloadAttachment(attachmentModel);
if (responseFromDownloadAttachment.length() == 0) {
return new ResponseEntity<>("", HttpStatus.NO_CONTENT);
}
else {
for (int blobRes = 0; blobRes < responseFromDownloadAttachment.length(); blobRes++) {
JSONObject blobObj = responseFromDownloadAttachment.getJSONObject(blobRes);
if (blobObj != null) {
byteRes = (String) blobObj.getString("file");
}
}
}
byte[] byteArrray = byteRes.getBytes();
return new ResponseEntity<>(byteArrray, HttpStatus.OK);
} catch (Exception e) {
log.error("Exception occurred!" + e);
e.printStackTrace();
JSONObject errObj = new JSONObject();
errObj.put("status", "E");
errObj.put("message", e);
return new ResponseEntity<>(errObj.toString(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
I am sending byte array as response.But i am not sure which type of file i will be getting from service layer.It can be in any form like xlsx,txt,png,jpg or any multimedia.I am setting headers to octet-stream and also produces to octet-stream.Can i use octet-stream to handle these type of responses?

How to Redirect request as post using ResponseEntity

I trying to include response from other url from ResponseEntity for oauth authorization but it is failing as I am unable to specify request method.
Below is the code
#RequestMapping(value = "/login/otp", method = RequestMethod.POST, produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
#ResponseBody
public ResponseEntity<?> getOTP(#Valid #RequestBody String loginDtls,UriComponentsBuilder ucBuilder) {
LoginDAO login = null;
ResponseEntity<?> resp = null;
try {
ObjectMapper mapper = new ObjectMapper();
String userId = "";
try {
JsonNode root = mapper.readTree(loginDtls);
userId = root.get("userId").textValue();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("UserController : getting otp for contact "+ userId);
login = loginService.findByUserId(userId);
if (login==null) {
System.out.println("A UserDAO with name " + userId + " does not exist");
resp = new ResponseEntity<String>(HttpStatus.NOT_FOUND);
}
String otp = GenUtil.generateOTP();
LoginDAO loginUpd = new LoginDAO(login);
loginUpd.setOtp(otp);
loginUpd.setOtpTimestamp(new Timestamp(System.currentTimeMillis()));
loginService.updateLogin(loginUpd);
System.out.println(loginUpd);
resp = getAuthenticated(ucBuilder);
System.out.println(resp.getStatusCodeValue());
System.out.println(resp.getBody());
}catch(Exception e) {
e.printStackTrace();
}
resp = new ResponseEntity<String>(login.toString(), HttpStatus.OK);
return resp;
}
private ResponseEntity<?> getAuthenticated(UriComponentsBuilder ucBuilder){
HttpHeaders headers = new HttpHeaders();
URI uri= ucBuilder.path("/oauth/token"+PASSWORD_GRANT).build().toUri();
List<MediaType> accept = new ArrayList<MediaType>();
accept.add(MediaType.APPLICATION_JSON_UTF8);
headers.setAccept(accept);
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
headers.setBasicAuth("my-trusted-client", "secret");
System.out.println(headers);
ResponseEntity<?> resp = ResponseEntity.created(uri).headers(headers).build();
return resp;
}

Spring boot HeaderWriterFilter overrides header created in controller

When I add a header to the responseEntity in the Controller, it is not added to the response. I debug the code, an when it reach the "HeaderWriterFilter" it adds default header, but it has no track of the one added in the Controller.
#RequestMapping(
value = "/get-file",
method = RequestMethod.GET
)
public ResponseEntity<Resource> download(Principal principal, Long fileId) throws IOException {
if (principal == null) {
throw new UsernameNotFoundException("User not found.");
}
try {
User loggedInUser = ((LoggedInUserDetails) ((UsernamePasswordAuthenticationToken) principal).getPrincipal()).getLoggedInUser();
// Get file
File file = this.fileService.getById(loggedInUser, fileId);
if (file == null) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
}
// Get file for download
java.io.File physicalFile = new java.io.File(file.getUrl());
if (file == null) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
}
InputStreamResource resource = new InputStreamResource(new FileInputStream(physicalFile));
HttpHeaders headers = new HttpHeaders();
headers.add("test", "test.yaml");
return ResponseEntity.ok()
.headers(headers)
.contentType(MediaType.parseMediaType("application/octet-stream"))
.contentLength(physicalFile.length())
.body(resource);
}
catch (FileNotFoundException e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
}
catch (Exception e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
}
}
The problem was a missing header in WebSecurityConfig. I solved the problem adding
configuration.setExposedHeaders(Arrays.asList("fileName"));
in CorsConfigurationSource.

Calling a different host from Spring Controller

My localhost is : http://localhost:8585/api/getproducts where i use #Requestmapping(/api/getproducts) in my ProductController to get to my product page.
On click of a button, i need to call an api on a different host :
http://10.120.130.22:9292/ and i tried to use the below code in a new Controller to call the host:
#RequestMapping("Trainer/reStaff/")
#RequestMapping(method = RequestMethod.POST)
public #ResponseBody response(#RequestParam("trainingId") final int trainingId, HttpServletRequest request)
throws ClientProtocolException, IOException {
String hostname="http://10.120.130.22:9292/";
CloseableHttpClient httpclient = HttpClients.custom().build();
CloseableHttpResponse response=null;
try{
String uri=hostname+"Trainer/reStaff/?trainingId="+trainingId;
HttpPost httpPost = new HttpPost(uri);
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-Type", "application/json");
response = httpclient.execute(httpPost);
String responseData = EntityUtils.toString(response.getEntity());
if(response.getStatusLine().getStatusCode()==200)
System.out.println(responseData+"\n");
else
System.out.println("Error :" + responseData+"\n");
}finally {
httpclient.close();
response.close();
}
But i get the error : HTTP Status 404 - type Status reportmessage description The requested resource is not available.
How do i call the new host from my controller?
I understood how this works. We need to pass the url through httpPost in the service layer :
HttpPost httpPost = new HttpPost(hostUri);
JsonObject jsonResponse = null;
try {
String httpRequestBody = jsonRequestBuilder.build().toString();
logger.info("Request Body: " + httpRequestBody);
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connManager).build();
httpPost.setHeader("Content-Type", "application/json");
httpPost.setHeader("Accept", "application/json");
httpPost.setEntity(new StringEntity(httpRequestBody));
HttpResponse httpResponse = httpClient.execute(httpPost);
logger.debug("Response Status: " + httpResponse.getStatusLine().getStatusCode());
BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
String line;
StringBuffer httpResponseBody = new StringBuffer();
while ((line = reader.readLine()) != null) {
httpResponseBody.append(line);
}
logger.info("Response Body: " + httpResponseBody.toString());
JsonReader jsonReader = Json.createReader(new StringReader(httpResponseBody.toString()));
jsonResponse = jsonReader.readObject();
jsonReader.close();
} catch (Exception ex) {
logger.error("Error occurred while invoking POST on ep: " + hostUrl, ex);
} finally {
httpPost.releaseConnection();
}
logger.debug("Exiting");
return jsonResponse;

Resources