How to Spring Retryable with http status code - java

I'm currently using spring 2 with restTemplate and I would like to have a retry sending a post request only with a certain status codes or any of code 500.
How do I do this?
Here is my code
#Retryable(value = RestClientException.class, exclude = {UnknownHostException.class},
backoff=#Backoff(delayExpression = 10000,
multiplierExpression = 2,
maxDelayExpression = 50000))
public HttpStatus postRequest(final File file) throws RestClientException {
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file", new FileSystemResource(file));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.set("Token", mytoken);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
ResponseEntity<String> response = restTemplate.exchange(URI, HttpMethod.POST,requestEntity, String.class);
return response.getStatusCode();
}

Related

Could not write request: no suitable HttpMessageConverter found for request type MultipartFile

I try to pass MultipartFile to RestTemplate. But i get an error:
2023-02-14 19:22:16.267 WARN 49600 --- [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write request: no suitable HttpMessageConverter found for request type [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile]]
I've tried to apply FormHttpMessageConverter converter to RestTemplate, but it did nothing.
Here is my endpoint:
#PostMapping(value = "/send", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public void send(#RequestPart(name = "media") MultipartFile media) {
TwitterTemplate twitterTemplate = new TwitterTemplate();
twitterTemplate.uploadMedia(media);
}
And my service method:
public void uploadMedia(MultipartFile media) {
RestTemplate restTemplate = new RestTemplate();
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("media", media);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
messageConverters.add(new FormHttpMessageConverter());
restTemplate.setMessageConverters(messageConverters);
UploadMediaResponse u = restTemplate.postForObject(API + "/upload", requestEntity, UploadMediaResponse.class);
}
I can't figure out why does this issue appear.

401 unauthorized : [no body] with root cause in JAVA Spring

I'm creating my first REST API using JAVA Spring and when I'm making a rest call to an external API, I get
401 Unauthorized: [no body]
I think my problem is here:
requestParams.add("Grant_type", "client_credentials");
I saw some questions related to this but none well able to solve my problem.
Spring REST template - 401 Unauthorized error
Spring Boot Callable - 401 Unauthorized: [no body]
JAVA code:
public String getAuth(String client_id, String app_secret) {
String auth = client_id + ":" + app_secret;
return Base64.getEncoder().encodeToString(auth.getBytes());
}
#GetMapping(value = "/token")
public Object generateAccessToken() {
String auth = this.getAuth(
"CLIENT_ID",
"APP_SECRET"
);
RestTemplate restTemplate = new RestTemplate();
String base = "https://external-api.com";
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Basic " + auth);
MultiValueMap<String, String> requestParams = new LinkedMultiValueMap<>();
requestParams.add("Grant_type", "client_credentials");
ResponseEntity<Object> response = restTemplate.postForEntity(
base + "/v1/oauth2/token",
requestParams,
Object.class,
headers
);
return response.getBody();
}
Here's the solution to my own question.
This is what I had to change;
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
requestBody.add("grant_type", "client_credentials");
HttpEntity<?> request = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.postForEntity(
base +"/v1/oauth2/token",
request,
String.class
);
Here's the final solution:
public String generateAccessToken() {
String base = "example-api.com";
String auth = this.getAuth(
"client id",
"app_id"
);
// create an instance of RestTemplate
RestTemplate restTemplate = new RestTemplate();
// create headers
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.set("Authorization", "Basic " + auth);
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
requestBody.add("grant_type", "client_credentials");
HttpEntity<?> request = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.postForEntity(
base +"/v1/oauth2/token",
request,
String.class
);
// check response
if (response.getStatusCode() == HttpStatus.OK) {
System.out.println("Request Successful");
System.out.println(response.getBody());
} else {
System.out.println("Request Failed");
System.out.println(response.getStatusCode());
}
JSONObject object = new JSONObject(response.getBody());
return object.getString("access_token");
}

Mockito Restemplate Verify not invoked

I a trying to mock restetmplate but don't why I am getting the below error. I am using doreturn to verify the invocation of the resttemplate.Is there by other way to mock the rest template and mock the HTTP request
class ToTest{
public ResponseEntity<String> getValue(){
if (StringUtils.isNotEmpty(token)) {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + token);
headers.setContentType(MediaType.APPLICATION_JSON);
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(etsServiceResourceDetails.getAccessTokenUri())
.queryParam("test","tsetValue");
builder.queryParam("some","someValue");
HttpEntity<?> entity = new HttpEntity<>(headers);
try {
response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, entity, String.class);
}
catch (RestClientResponseException ex ) {
log.error(ex);
if ( ex.getRawStatusCode() == HttpStatus.NOT_FOUND.value()) {
return ResponseEntity.notFound().build();
}
}
}
}
}
Unit Test for the rest Temaplate
#Test
public void testExchange() {
String token="abbjabxkcbkscksckbckbkcbksckckkcb";
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
queryParams.add("query", "star");
queryParams.add("test", "star2");
UriComponents uriComponents = UriComponentsBuilder.newInstance().scheme("http").host("localhost:8080/some/add").path("/").queryParams(queryParams).buildAndExpand();
RestTemplate r = new RestTemplate();
RestTemplate r1 = spy(r);
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + token);
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<?> entity = new HttpEntity<>(headers);
// ResponseEntity responserm=
//r1.exchange(uriComponents.toUriString(),HttpMethod.GET,entity,String.class); //I am getting error org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://localhost:8080
doReturn(new ResponseEntity("", HttpStatus.OK)).when(r1).exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), any(Class.class));
verify(r1, times(1)).exchange(eq(uriComponents.toUriString()), any(), any(), eq(String.class));
assertEquals("check", "http://localhost:8080/some/add/?query=s1&test=s2", uriComponents.toUriString());
}
Errors
-> at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:581)
Actually, there were zero interactions with this mock.
Wanted but not invoked:

Rest template for postForEntity with file & other properties

I want to upload the file with Json request in rest template along with other properties. But I couldn't able to do this.
#Bean
public RestTemplate getRestTemplate(RestTemplateBuilder restTemplateBuilder) {
return restTemplateBuilder.build();
}
#Autowired
private RestTemplate restTemplate;
#Scheduled(fixedDelay = 1000)
public void _do() throws Exception {
HashMap<String, String> documentProperties = new HashMap<>();
documentProperties.put("number", "123");
MultipartFile file = Somefile;
UploadDocumentRequest uploadDocumentRequest = new UploadDocumentRequest();
uploadDocumentRequest.setDocumentClass("DocClass");
uploadDocumentRequest.setDocumentProperties(documentProperties);
uploadDocumentRequest.setFile(file); ----???
ResponseEntity<String> value = restTemplate.postForEntity("URL", uploadDocumentRequest, String.class);
}
You have to create HttpEntity with header and body.
Set the content-type header value to MediaType.MULTIPART_FORM_DATA.
Build the request body as an instance of LinkedMultiValueMap class.
Construct an HttpEntity instance that wraps the header and the body object and post it using a RestTemplate.
A sample code is shown as follows:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file", getFileToBeUploaded());
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.postForEntity(serviveUrl, requestEntity, String.class);

Consuming HTTP POST method which is secured with Basic Auth in spring

I want to consume a post method which is secured using basicAuth. I am using springBoot, Spring RestTemplate to consume it.
I've tried like this:
#CrossOrigin(origins = "*", maxAge = 3600)
#RequestMapping(value = "/ValidateAnswers", method = RequestMethod.POST)
public ResponseEntity<String> ValidateAnswers(#RequestBody Object requestIbject,
HttpServletRequest request, HttpServletResponse response) {
final String uri = "foo:8080//validateAnswers";
// hiding full path here,
RestTemplate restTemplate = new RestTemplate();
String plainClientCredentials = "user:pass";
String base64ClientCredentials = new String(
Base64.encodeBase64(plainClientCredentials.getBytes()));
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + base64ClientCredentials);
HttpEntity<String> entity = new HttpEntity<String>("parameters",
headers);
ResponseEntity<String> respEntity = restTemplate.postForObject(uri, requestIbject, String.class);
// .exchange(uri,
// HttpMethod.POST, entity, String.class);
System.err.println("=------------Response--------------");
System.err.println("----" + respEntity);
return respEntity;
}
How do I pass the headers with basicAuth and post request body ?
if you using spring > 4.3.1
RestTemplate restTemplate = new RestTemplate();
restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor("user", "password"));
From your code snippets I don't think you should use post method, try get first. And refer to my previous test:
public class Test {
private HttpHeaders getHeaders(){
String plainCredentials="admin:admin";
String base64Credentials = Base64.getEncoder().encodeToString(plainCredentials.getBytes());
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + base64Credentials);
return headers;
}
#Test
public void testLogin() {
RestTemplate restTemplate = new RestTemplate();
HttpEntity<String> request = new HttpEntity<String>(getHeaders());
ResponseEntity<String> response = restTemplate.exchange("http://localhost:8080/login", HttpMethod.GET,
request, String.class);
System.out.println(response.getBody());
}
}

Categories