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:
Related
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?
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;
}
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.
#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.
While working on an application for android that uses web services I encounterd a bad request (response code 400) message when trying to retrieve some data in android versions 4.0.3 and 4.3. The perculiar thing however is that when sending the same request using the same code but on a device using android version 2.3.3 it works without any problems. I have also tried using httpGet instead of HttpsURLConnection, while this work for all versions it does not provide a solution as I need the added security.
My code is as follows:
private String executeRequest(String urlAddress)
{
String responce = null;
String msg = null;
int error = 0;
try {
URL url = new URL(urlAddress);
HttpsURLConnection connection = (HttpsURLConnection)url.openConnection();
SSLSocketFactory factory = SecureSocketFactory.getSSLSocketFactory();
connection.setSSLSocketFactory(factory);
connection.setHostnameVerifier(new Verifier());
connection.setDoOutput(true);
connection.setDoInput(true);
if (method == RequestMethod.POST)
{
connection.setRequestMethod("POST");
}
msg = connection.getResponseMessage();
error = connection.getResponseCode();
if ("OK".equals(msg))
{
InputStream content = (InputStream) connection.getContent();
responce = convertStreamToString(content);
}
else
{
responce = "Error " + error;
}
connection.disconnect();
} catch (Exception e) {
responce = e.toString();
}
return responce;
}
And the code of SecureSocketFactory.getSSLSocketFactory():
public static SSLSocketFactory getSSLSocketFactory()
throws IOException
{
if(ssf_ == null)
{
javax.net.ssl.KeyManager kms[] = null;
javax.net.ssl.TrustManager tms[] = null;
SSLContext context = null;
try
{
tms = CustomTrustManager.getTrustManagers();
context = SSLContext.getInstance("TLS");
context.init(kms, tms, null);
}
catch(GeneralSecurityException e)
{
IOException io = new IOException(e.getLocalizedMessage());
io.setStackTrace(e.getStackTrace());
throw io;
}
ssf_ = context.getSocketFactory();
}
return ssf_;
}
and the code of CustomTrustManager.getTrustManagers()
static TrustManager[] getTrustManagers(String trustStoreFile, String trustStorePW)
throws NoSuchAlgorithmException, KeyStoreException
{
String alg = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmFact = TrustManagerFactory.getInstance(alg);
tmFact.init((KeyStore)null);
TrustManager tms[] = tmFact.getTrustManagers();
for(int i = 0; i < tms.length; i++)
if(tms[i] instanceof X509TrustManager)
tms[i] = new CustomTrustManager((X509TrustManager)tms[i]);
return tms;
}
static TrustManager[] getTrustManagers()
throws NoSuchAlgorithmException, KeyStoreException
{
return getTrustManagers(null, null);
}
I have looked everywhere, but can't seem to find a solution please help.
I found my error, because do connection.setDoInput(true) it silencly sets my Requestmethod to post in version 4 which gives an error on the server causing it to return bad request.
apparently it does not set this in version 2, which explains why it does work there.
The following execute request method change fixed my code:
private String executeRequest(String urlAddress)
{
String responce = null;
String msg = null;
int error = 0;
try {
URL url = new URL(urlAddress);
HttpsURLConnection connection = (HttpsURLConnection)url.openConnection();
SSLSocketFactory factory = SecureSocketFactory.getSSLSocketFactory();
connection.setSSLSocketFactory(factory);
connection.setHostnameVerifier(new Verifier());
if (method == RequestMethod.POST)
{
connection.setDoOutput(true);
connection.setRequestMethod("POST");
}
else
{
connection.setDoInput(true);
connection.setRequestMethod("GET");
}
msg = connection.getResponseMessage();
error = connection.getResponseCode();
if ("OK".equals(msg))
{
InputStream content = (InputStream) connection.getContent();
responce = convertStreamToString(content);
}
else
{
responce = "Error " + error;
}
connection.disconnect();
} catch (Exception e) {
responce = e.toString();
}
return responce;
}