How send request with query parameter "test[]=test" in spring? - java

I need to send get request to example.com/api with query param named test[]
For this i use spring rest tepmlate
UriComponentsBuilder builder = UriComponentsBuilder
.fromUriString(example.com/api)
.queryParam(test[], "test");
responseEntity = restTemplate.exchange(builder.toUriString(), HttpMethod.GET,
new HttpEntity<>(this.setHttpHeader()),
new ParameterizedTypeReference<List<MyDTO>>() {
});
But builder.toUriString() return example.com/api?test%5B%5D=test
I try to replace srting with my method
private String repairUri(String uri) {
return url.replaceAll("%5B%5D", "[]");
}
and call
responseEntity = restTemplate.exchange(repairUri(builder.toUriString()), HttpMethod.GET,
new HttpEntity<>(this.setHttpHeader()),
new ParameterizedTypeReference<List<MyDTO>>() {
});
But into restTemplate.exchange() this uri convert to example.com/api?test%5B%5D=test again.
Meanwhile i easy send example.com/api?test[]=test request by POSTMan and it's work.
How Can i send request to example.com/api?test[]=test in Spring?

I find one solution.
In my restTemplate bean definition I add this settings:
public RestTemplate myRestTemplate() {
RestTemplate restTemplate = restTemplate(timeout);
DefaultUriBuilderFactory builderFactory = new DefaultUriBuilderFactory();
builderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY);
restTemplate.setUriTemplateHandler(builderFactory);
restTemplate.setErrorHandler(new RestClientResponseExceptionHandler());
return restTemplate;
}
In this page some guys says that DefaultUriBuilderFactory.EncodingMode.NONE is also suitable.
Read more in link.

Just change your repairUri method to this when you call restTemplate.exchange to this :
responseEntity = restTemplate.exchange(URLDecoder.decode(builder.toUriString(), "UTF-8"), HttpMethod.GET,
new HttpEntity<>(this.setHttpHeader()),
new ParameterizedTypeReference<List<MyDTO>>() {
});

Related

Call rest void method in controller using Spring Boot

i'm using Spring Boot for making Rest Controllers.
my controller is :
#RestController
public class VersionRestController {
#Autowired
VersionService versionService;
#GetMapping(value = "/csv", produces = "text/csv")
#ResponseStatus(value = HttpStatus.OK)
public void exportCsv(HttpServletResponse response) throws Exception {
String fileName = "allVersions.csv";
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"");
StatefulBeanToCsv<Version> writer = new StatefulBeanToCsvBuilder<Version>(response.getWriter())
.withQuotechar(CSVWriter.NO_QUOTE_CHARACTER).withSeparator(CSVWriter.DEFAULT_SEPARATOR)
.withOrderedResults(true).build();
writer.write(versionService.findAll());
}
}
im calling it like this
public void exportVersionAsCsv(){
final String uri = "http://localhost:8070/csv";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Version> response = restTemplate.getForEntity(uri, Version.class);
}
when i call the rest method direct in the browser it works fine, but when i call exportVersionAsCsv() in vaadin on click button it gives me org.springframework.web.client.HttpClientErrorException$NotAcceptable: 406 Not Acceptable
why is this happening ? any suggestion ?
thank you
Try this set setAccept to Media type to that is being produced by url you are consuming.
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<>("body", headers);
restTemplate.exchange(url, HttpMethod.POST, entity, String.class);

How can I make a Put rest call along with POJO using RestTemplate

How can I make a PUT request to a rest service using RestTemplate, so that I get a response also.
The rest service I have to call is:
#RequestMapping(value = /forgotpassword, method = RequestMethod.PUT, produces = "application/json")
public SuccessResponse resetUserPassword(#RequestBody ResetPasswordDTO resetPasswordDTO) throws GenericException {
logger.info("--->reset Password");
return new SuccessResponse(userservice.resetUserPassword(resetPasswordDTO));
}
I need to send one POJO also which has two String properties.
The method put of RestTempalte in (Spring)[https://spring.io/] has no return,so if your want get response from server,please try use POST method.I modify your code like this:
In server side:
#RequestMapping(value = "/forgotpassword", method = RequestMethod.POST, produces = "application/json")
public ResponseEntity<SuccessResponse> resetUserPassword(#RequestBody ResetPasswordDTO resetPasswordDTO) throws Exception {
log.info("--->reset Password");
SuccessResponse response = new SuccessResponse();
response.setName(resetPasswordDTO.getUsername());
response.setMessage("success");
return new ResponseEntity<SuccessResponse>(response, HttpStatus.OK);
}
In client side you can use RestTemplate do a request:
ResetPasswordDTO request = new ResetPasswordDTO();
request.setPasswork("Huawei#123");
request.setUsername("c00382802");
ResponseEntity<SuccessResponse> response =template.postForEntity("http://localhost:8080//forgotpassword",request,SuccessResponse.class);
System.out.println(response.getBody().toString());
More info you can get from (Spring)[https://spring.io/]
For PUT use RestTemplate.exchange() method
Example
MyJaxbRequestDataObjectrequest = createMyJaxbRequestDataObject();
Map<String, String> uriArguments= createUriArguments();
String url = restBaseUrl + "/myputservice/{usertId}?servicekey={servicekey}";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
HttpEntity<MyJaxbRequestDataObject> entity = new HttpEntity<MyJaxbRequestDataObject>(request, headers);
ResponseEntity<MyJaxbResponseDataObject> responseWrapper = shogunRestTemplate.exchange(url, HttpMethod.PUT, entity, MyJaxbResponseDataObject.class, uriArguments);
MyJaxbResponseDataObjectresponse = responseWrapper.getBody();

How to make a rest api call in java and map the response object?

I'm currently developing my first java program who'll make a call to a rest api(jira rest api, to be more especific).
So, if i go to my browser and type the url =
"http://my-jira-domain/rest/api/latest/search?jql=assignee=currentuser()&fields=worklog"
I get a response(json) with all the worklogs of the current user.
But my problem is, how i do my java program to do this ?
Like,connect to this url, get the response and store it in a object ?
I use spring, with someone know how to this with it.
Thx in advance guys.
Im adding, my code here:
RestTemplate restTemplate = new RestTemplate();
String url;
url = http://my-jira-domain/rest/api/latest/search/jql=assignee=currentuser()&fields=worklog
jiraResponse = restTemplate.getForObject(url,JiraWorklogResponse.class);
JiraWorkLogResponse is a simple class with some attributes only.
Edit,
My entire class:
#Controller
#RequestMapping("/jira/worklogs")
public class JiraWorkLog {
private static final Logger logger = Logger.getLogger(JiraWorkLog.class.getName() );
#RequestMapping(path = "/get", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity getWorkLog() {
RestTemplate restTemplate = new RestTemplate();
String url;
JiraProperties jiraProperties = null;
url = "http://my-jira-domain/rest/api/latest/search?jql=assignee=currentuser()&fields=worklog";
ResponseEntity<JiraWorklogResponse> jiraResponse;
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders = this.createHeaders();
try {
jiraResponse = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<Object>(httpHeaders),JiraWorklogResponse.class);
}catch (Exception e){
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
}
return ResponseEntity.status(HttpStatus.OK).body(jiraResponse);
}
private HttpHeaders createHeaders(){
HttpHeaders headers = new HttpHeaders(){
{
set("Authorization", "Basic something");
}
};
return headers;
}
This code is returning :
org.springframework.http.converter.HttpMessageNotWritableException
Anyone knows why ?
All you need is http client. It could be for example RestTemplate (related to spring, easy client) or more advanced and a little more readable for me Retrofit (or your favorite client).
With this client you can execute requests like this to obtain JSON:
RestTemplate coolRestTemplate = new RestTemplate();
String url = "http://host/user/";
ResponseEntity<String> response
= restTemplate.getForEntity(userResourceUrl + "/userId", String.class);
Generally recommened way to map beetwen JSON and objects/collections in Java is Jackson/Gson libraries. Instead them for quickly check you can:
Define POJO object:
public class User implements Serializable {
private String name;
private String surname;
// standard getters and setters
}
Use getForObject() method of RestTemplate.
User user = restTemplate.getForObject(userResourceUrl + "/userId", User.class);
To get basic knowledge about working with RestTemplate and Jackson , I recommend you, really great articles from baeldung:
http://www.baeldung.com/rest-template
http://www.baeldung.com/jackson-object-mapper-tutorial
Since you are using Spring you can take a look at RestTemplate of spring-web project.
A simple rest call using the RestTemplate can be:
RestTemplate restTemplate = new RestTemplate();
String fooResourceUrl = "http://localhost:8080/spring-rest/foos";
ResponseEntity<String> response = restTemplate.getForEntity(fooResourceUrl + "/1", String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
The issue could be because of the serialization. Define a proper Model with fields coming to the response. That should solve your problem.
May not be a better option for a newbie, but I felt spring-cloud-feign has helped me to keep the code clean.
Basically, you will be having an interface for invoking the JIRA api.
#FeignClient("http://my-jira-domain/")
public interface JiraClient {
#RequestMapping(value = "rest/api/latest/search?jql=assignee=currentuser()&fields=", method = GET)
JiraWorklogResponse search();
}
And in your controller, you just have to inject the JiraClient and invoke the method
jiraClient.search();
And it also provides easy way to pass the headers.
i'm back and with a solution (:
#Controller
#RequestMapping("/jira/worklogs")
public class JiraWorkLog {
private static final Logger logger = Logger.getLogger(JiraWorkLog.class.getName() );
#RequestMapping(path = "/get", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity<JiraWorklogIssue> getWorkLog(#RequestParam(name = "username") String username) {
String theUrl = "http://my-jira-domain/rest/api/latest/search?jql=assignee="+username+"&fields=worklog";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<JiraWorklogIssue> response = null;
try {
HttpHeaders headers = createHttpHeaders();
HttpEntity<String> entity = new HttpEntity<>("parameters", headers);
response = restTemplate.exchange(theUrl, HttpMethod.GET, entity, JiraWorklogIssue.class);
System.out.println("Result - status ("+ response.getStatusCode() + ") has body: " + response.hasBody());
}
catch (Exception eek) {
System.out.println("** Exception: "+ eek.getMessage());
}
return response;
}
private HttpHeaders createHttpHeaders()
{
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Authorization", "Basic encoded64 username:password");
return headers;
}
}
The code above works, but can someone explain to me these two lines ?
HttpEntity<String> entity = new HttpEntity<>("parameters", headers);
response = restTemplate.exchange(theUrl, HttpMethod.GET, entity, JiraWorklogIssue.class);
And, this is a good code ?
thx (:

Content type 'null' not supported returned by Spring RESTTemplate getForObject method

I have a simple REST method in a Spring MVC controller as follows which has a signature of:
#RequestMapping(value="/person/{personId}", method=RequestMethod.GET)
public #ResponseBody Object getPerson(#PathVariable("personId") String personId) {
...
}
The output is type Object because several different data types are returned from this method.
When called from a test program within the Spring MVC application, as follows:
private static void getPerson() {
logger.info(Rest.class.getName() + ".getPerson() method called.");
RestTemplate restTemplate = new RestTemplate();
Person person = restTemplate.getForObject("http://localhost:8080/Library/rest/person/1", Person.class);
ObjectMapper responseMapper = new ObjectMapper();
...
}
The response is Content type 'null' not supported and the call fails.
Can anyone advise why?
When called from a test program in another application which doesn't use Spring but which makes HTTP GET requests, the controller method is called properly and works.
You can try this:
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setReadTimeout(VERSION_CHECK_READ_TIMEOUT);
RestTemplate template = new RestTemplate(requestFactory);
Person person = restTemplate.getForObject("http://localhost:8080/Library/rest/person/1", Person.class);
If above doesn't work you can try using a Entity approach like:
RestTemplate restTemplate = new RestTemplate();
// Prepare acceptable media type
List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
acceptableMediaTypes.add(MediaType.APPLICATION_XML); // Set what you need
// Prepare header
HttpHeaders headers = new HttpHeaders();
headers.setAccept(acceptableMediaTypes);
HttpEntity<Person> entity = new HttpEntity<Person>(headers);
// Send the request as GET
try {
ResponseEntity<PersonList> result = restTemplate.exchange("http://localhost:8080/Library/rest/person/1", HttpMethod.GET, entity, PersonList.class);
// Add to model
model.addAttribute("persons", result.getBody().getData());
} catch (Exception e) {
logger.error(e);
}
There are many useful examples here.
Hope to help

Basic authentication for REST API using spring restTemplate

I am completely new in RestTemplate and basically in the REST APIs also. I want to retrieve some data in my application via Jira REST API, but getting back 401 Unauthorised. Found and article on jira rest api documentation but don't really know how to rewrite this into java as the example uses the command line way with curl. I would appreciate any suggestion or advice how to rewrite:
curl -D- -X GET -H "Authorization: Basic ZnJlZDpmcmVk" -H "Content-Type: application/json" "http://kelpie9:8081/rest/api/2/issue/QA-31"
into java using spring rest template. Where the ZnJlZDpmcmVk is a base64 encoded string of username:password. Thank you very much.
Taken from the example on this site, I think this would be the most natural way of doing it, by filling in the header value and passing the header to the template.
This is to fill in the header Authorization:
String plainCreds = "willie:p#ssword";
byte[] plainCredsBytes = plainCreds.getBytes();
byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
String base64Creds = new String(base64CredsBytes);
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + base64Creds);
And this is to pass the header to the REST template:
HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<Account> response = restTemplate.exchange(url, HttpMethod.GET, request, Account.class);
Account account = response.getBody();
You may use spring-boot RestTemplateBuilder
#Bean
RestOperations rest(RestTemplateBuilder restTemplateBuilder) {
return restTemplateBuilder.basicAuthentication("user", "password").build();
}
See documentation
(before SB 2.1.0 it was #basicAuthorization)
There are multiple ways to add the basic HTTP authentication to the RestTemplate.
1. For a single request
try {
// request url
String url = "https://jsonplaceholder.typicode.com/posts";
// create auth credentials
String authStr = "username:password";
String base64Creds = Base64.getEncoder().encodeToString(authStr.getBytes());
// create headers
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + base64Creds);
// create request
HttpEntity request = new HttpEntity(headers);
// make a request
ResponseEntity<String> response = new RestTemplate().exchange(url, HttpMethod.GET, request, String.class);
// get JSON response
String json = response.getBody();
} catch (Exception ex) {
ex.printStackTrace();
}
If you are using Spring 5.1 or higher, it is no longer required to manually set the authorization header. Use headers.setBasicAuth() method instead:
// create headers
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth("username", "password");
2. For a group of requests
#Service
public class RestService {
private final RestTemplate restTemplate;
public RestService(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder
.basicAuthentication("username", "password")
.build();
}
// use `restTemplate` instance here
}
3. For each and every request
#Bean
RestOperations restTemplateBuilder(RestTemplateBuilder restTemplateBuilder) {
return restTemplateBuilder.basicAuthentication("username", "password").build();
}
I hope it helps!
As of Spring 5.1 you can use HttpHeaders.setBasicAuth
Create Basic Authorization header:
String username = "willie";
String password = ":p#ssword";
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth(username, password);
...other headers goes here...
Pass the headers to the RestTemplate:
HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<Account> response = restTemplate.exchange(url, HttpMethod.GET, request, Account.class);
Account account = response.getBody();
Documentation:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/HttpHeaders.html#setBasicAuth-java.lang.String-java.lang.String-
(maybe) the easiest way without importing spring-boot.
restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor("user", "password"));
Reference Spring Boot's TestRestTemplate implementation as follows:
https://github.com/spring-projects/spring-boot/blob/v1.2.2.RELEASE/spring-boot/src/main/java/org/springframework/boot/test/TestRestTemplate.java
Especially, see the addAuthentication() method as follows:
private void addAuthentication(String username, String password) {
if (username == null) {
return;
}
List<ClientHttpRequestInterceptor> interceptors = Collections
.<ClientHttpRequestInterceptor> singletonList(new BasicAuthorizationInterceptor(
username, password));
setRequestFactory(new InterceptingClientHttpRequestFactory(getRequestFactory(),
interceptors));
}
Similarly, you can make your own RestTemplate easily
by inheritance like TestRestTemplate as follows:
https://github.com/izeye/samples-spring-boot-branches/blob/rest-and-actuator-with-security/src/main/java/samples/springboot/util/BasicAuthRestTemplate.java
Instead of instantiating as follows:
TestRestTemplate restTemplate = new TestRestTemplate();
Just do it like this:
TestRestTemplate restTemplate = new TestRestTemplate(user, password);
It works for me, I hope it helps!
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth(username, password);
then continue with the same procedure mentioned by the others here:
HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET,
request, String.class);
Use setBasicAuth to define credentials
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth("myUsername", myPassword);
Then create the request like you prefer.
Example:
HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET,
request, String.class);
String body = response.getBody();
I'm using spring version 5.3.15 for my unit test environment. I used withBasicAuth for my tests :
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MyTestClass {
...
#Autowired
private TestRestTemplate restTemplate;
...
#Test
#SneakyThrows
public void TestGetSettings(){
DtoClass dtoClass = this.restTemplate
.withBasicAuth(UserServices.DEFAULT_USER, UserServices.DEFAULT_PASSWORD)
.getForObject(String.format("http://localhost:%d/setting",
port), DtoClass.class);
assertThat(dtoClass.getClientAddress()).isNotEmpty();
}
...
}
As you see this method only work for basic authentication. If you look at the details of the withBasicAuth method, you will find that the method source will be like this:
// TestRestTemplate.java file:
...
public class TestRestTemplate {
...
private final RestTemplateBuilder builder;
...
public TestRestTemplate withBasicAuth(String username, String password) {
TestRestTemplate template = new TestRestTemplate(this.builder, username, password, this.httpClientOptions);
...
}
}
As a result, for other types of authentication you can use the RestTemplateBuilder as a builder which is mentioned in other answers.
Follow Step By Step
I added Client Credentials In application.Properties file like below...
http.basicauth.username = yourUserName
http.basicauth.password = yourPassword
And , Then I created one class With two fields Because I'm loading those two fields from the Application.Properties file : username and password . Make sure your class is annotated with #Component..
#Value("${http.basicauth.username}")
private String username;
#Value("${http.basicauth.password}")
private String password;
And Then , You need to autowired above class From Wherever you want..
// I'm getting a username and password from application.properties file
String userCredentials = referenceClassName.getUsername()+":"+referenceClassName.getPassword();
// Encoded User Credentials and Convert it into a String
String encodedUserCredentials= Base64.getMimeEncoder().encodeToString(userCredentialsBytes.getBytes());
headers.set("Authorization", "Basic " +base64UserCredentials);
HttpEntity request = new HttpEntity(headers);
String url = "externalUrl";
// Getting a Json String body
String body = restTemplate.exchange(url,HttpMethod.GET,request,String.class).getBody();
Note :: For getting an Access Token from String Json body , That's why I converted it into a Json Object
JsonObject tokenJsonObject = new JsonParser().parse(body).getAsJsonObject();
// Getting access token as string from tokenJsonObject
String accessToken = tokenJsonObject.has("access_token") && !tokenJsonObject.get("access_token").isJsonNull() ? tokenJsonObject.get("access_token").getAsString() : "";
If you have any concerns, please let me know in comments..Hope It will helpful to you..
I have been using Spring above 5.1.x
// create headers for basic auth
var headers = new HttpHeaders();
headers.setBasicAuth("username", "password");

Categories