I am using Jersey 1.9 in my Java Spring MVC web application. I am trying to make a post request for which I have to set two header values - authorization and content type. I was able to successfully make the post using postman REST client. I have tried many solutions found online, but the response I get is 401-Authorization failed. Following is the code is the code I use:
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource webResource = client.resource("https://api.constantcontact.com/v2/contacts?action_by=ACTION_BY_OWNER&api_key=tntkzy2drrmbwnhdv12s36vq");
WebResource.Builder builder = webResource.type(MediaType.APPLICATION_JSON);
builder.header(HttpHeaders.AUTHORIZATION, "Bearer 28ac08bc-58d5-426e-b811-3b1d1e505a9b");
ClientResponse responseMsg = webResource
.post(ClientResponse.class, jsonString);
responseMsg.getEntity(String.class);
Adding the postman screenshot:
After some research, I finally found what was missing in my case, based on the suggestions I got from the comments, I removed the query params from URL and added them as query params. ANd then added all query params to a multivalued map and used this multivalued map as the query param. My code was modified as follows:
MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();
queryParams.add("action_by", "ACTION_BY_OWNER");
queryParams.add("api_key", apiKey);
WebResource webResource = client.resource(url);
ClientResponse responseMsg = webResource
.queryParams(queryParams)
.header("Content-Type", "application/json;charset=UTF-8")
.header("Authorization", "Bearer "+authorisationToken.trim())
.post(ClientResponse.class, jsonString);
responseMsg.getEntity(String.class);
Somehow when there are multiple query params, adding headers was not working, but when the params were added as a single multivalued map, everything works. Hope this helps someone.
Related
We have a Controller running on tomcat 8.5.32 which receives a POST request with query params
/{path_param}/issue?title=4&description=5
request body is empty
Then controller redirects this request to Spring Boot microservice with tomcat 9.0.27.
At line
CloseableHttpResponse result = httpClient.execute(request);
request.getURI().getQuery() equals&title=1&description=2
But when it arrives to microservice parameters are duplicated (title=[4,4]&description=[5,5]).
This is the code which redirects request to microservice
private static <T, U> T executePostRequest(String url, U body, HttpServletRequest httpServletRequest, Function<String, T> readValueFunction) {
try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
URIBuilder uriBuilder = new URIBuilder(url);
httpServletRequest.getParameterMap().forEach((k, v) -> Arrays.stream(v).forEach(e -> uriBuilder.addParameter(k, e)));
HttpPost request = new HttpPost(uriBuilder.build());
CloseableHttpResponse result = httpClient.execute(request);
String json = EntityUtils.toString(result.getEntity(), "UTF-8");
handleResultStatus(result, json);
return readValueFunction.apply(json);
} catch (IOException | URISyntaxException e) {
...
}
}
I found that there was similar issue with jetty and it was fixed but did not find anything related to tomcat - and how it can be fixed.
I saw also this topic whith suggestion how to handle duplicated parameters in spring boot but i am wondering if anyone else experienced same issue and how did you resolve it if yes.
It's not a bug, it's a feature present in every servlet container.
The Servlet API does not require for the request parameters to have unique names. If you send a POST request for http://example.com/app/issue?title=1&description=2 with a body of:
title=3&description=4
then each parameter will have multiple values: title will have values 1 and 3, while description will have values 2 and 4 in that order:
Data from the query string and the post body are aggregated into the request
parameter set. Query string data is presented before post body data. For example, if
a request is made with a query string of a=hello and a post body of a=goodbye&a=
world, the resulting parameter set would be ordered a=(hello, goodbye, world).
(Servlet specification, section 3.1)
If you want to copy just the first value of the parameters use:
httpServletRequest.getParameterMap()//
.forEach((k, v) -> uriBuilder.addParameter(k, v[0]));
I am using Sping webflux module and create a WebClient, request uri and request body as follows:
// create webclient
WebClient wc3 = WebClient.builder()
.baseUrl("http://localhost:8080")
.defaultCookie("key", "val")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.build();
// set uri
WebClient.RequestBodySpec uri1 = wc3.method(HttpMethod.POST).uri("/getDocs");
// set a request body
WebClient.RequestBodySpec requestSpec1 = WebClient.create().method(HttpMethod.POST).uri("/getDocs")
.body(BodyInserters.fromPublisher(Mono.just("data")), String.class);
and when i am setting the request body, i am getting the following compilation error:
Multiple markers at this line
- Type mismatch: cannot convert from Mono<String> to P
- The method fromPublisher(P, Class<T>) in the type BodyInserters is not applicable for the arguments
(Mono<String>)
The java editor is showing just "Rename in file" as the suggestion.
I am not sure if i am using the BodyInserters perfectly or not. Please suggest.
It has to be like this
// set a request body
WebClient.RequestHeadersSpec<?> data = WebClient.create().method(HttpMethod.POST).uri("/getDocs")
.body(BodyInserters.fromPublisher(Mono.just("data"), String.class));
I can easily get the expected JSON response if I send the following get request from my browser:
http://www.bookandwalk.hu/api/AdminTransactionList?password=XXX&begindate=2016-04-30&enddate=2016-10-12&corpusid=HUBW
I tried to use SPRING BOOT 1.4 to create a small demo app to see how rest calls work in Spring.
So I created a POJO representing my domain object and I requested the list of domain objects by the following method invocation:
String startDate=new SimpleDateFormat("yyyy-MM-dd").format(start.getTime());
String endDate=new SimpleDateFormat("yyyy-MM-dd").format(end.getTime());
UriComponents uri=UriComponentsBuilder.newInstance().scheme("http").host("www.bookandwalk.hu").path("/api/AdminTransactionList").queryParam("password","xxx").queryParam("begindate",startDate).queryParam("enddate",endDate).queryParam("corpusid","HUBW").build().encode();
LOG.log(Level.INFO,"{0} were called as a rest call",uri.toString());
ResponseEntity<List<BandWTransaction>> transResponse =
restTemplate.exchange(uri.toString(),
HttpMethod.GET, null, new ParameterizedTypeReference<List<BandWTransaction>>() {
});
List<BandWTransaction> transactions = transResponse.getBody();
I got the following exception:
org.springframework.web.client.HttpClientErrorException: 404 Not Found
As I logged the uri.toString(), I copied it to my browser to double check the is there any typos in my uri but it was working without any failure.
Does Anybody have idea why the same string works from the browser but not from the code?
It seems that you should specify a user agent header in the request for this webapp. Use a HttpEntity object to set this header.
final HttpHeaders headers = new HttpHeaders();
headers.set("User-Agent", "eltabo");
final HttpEntity<String> entity = new HttpEntity<String>(headers);
ResponseEntity<List<BandWTransaction>> transResponse =
restTemplate.exchange(uri.toString(),
HttpMethod.GET, entity,
new ParameterizedTypeReference<List<BandWTransaction>>() {});
Hope it helps.
Need to query SOAP based endpoint using Sprint WS - but here instead of passing XML payload I will have pass a generated SOAP Request itself. I was using org.springframework.ws.client.core.WebServiceTemplate for this purpose right now ?
You can do the following:
ClientMessageCallBack _callBack =
new ClientMessageCallBack("yournamespaceuri/operationx");
final String _message =
"<ns1:operationx xmlns:ns1="yournamespaceuri"></ns1:operationx>";
StreamSource _source = new StreamSource(new StringReader(_message));
// the result will be output in the console
StreamResult _result = new StreamResult(System.out);
// suppose you have a reference to webServiceTemplate
webServiceTemplate.sendSourceAndReceiveToResult(_source,_callBack, _result);
I am attempting to test a rest service I created. The service is a post.
I wanted to create a file to pass the parameters(including a multi-part file).
From there I am trying to call the service at this point.
Pretty sure the service that doesn't work. But when I call rest Service. I have a simple form that just passes in a couple values including the jpg.
Here is the code.
HttpMessageConverter bufferedIamageHttpMessageConverter = new ByteArrayHttpMessageConverter();
restTemplate.postForObject("http://localhost:8080/sendScreeenAsPostCard", uploadItem.getFileData(), String.class));
My method signature is:
ResultStatus sendScreenAsPostcard( #RequestParam MultipartFile image, #RequestParamString userId)
That is the error I am getting.
Could not write request: no suitable HttpMessageConverter found for request type [org.springframework.web.multipart.commons.CommonsMultipartFile]
You need to simulate a file upload, which requires a particular content type header, body parameters, etc. Something like this should do the trick:
// Fill out the "form"...
MultiValueMap<String, Object> parameters = new LinkedMultiValueMap<String, Object>();
parameters.add("file", new FileSystemResource("file.jpg")); // load file into parameter
parameters.add("blah", blah); // some other form field
// Set the headers...
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "multipart/form-data"); // we are sending a form
headers.set("Accept", "text/plain"); // looks like you want a string back
// Fire!
String result = restTemplate.exchange(
"http://localhost:8080/sendScreeenAsPostCard",
HttpMethod.POST,
new HttpEntity<MultiValueMap<String, Object>>(parameters, headers),
String.class
).getBody();