I want to get four values from a website but need to edit parameter every step. I thought I can do it with executors but I couldn't. So, how can I edit parameter in every CompletableFuture before sending?
HttpRequest httpRequest = HttpRequest.newBuilder()
.version(Version.HTTP_1_1)
.uri(URI.create(sourceUrl))
.header("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
.method("POST", BodyPublishers.ofFile(Paths.get("Resources/Payload.txt")))
.build();
ExecutorService executorService = Executors.newFixedThreadPool(4);
HttpClient httpClient = HttpClient.newBuilder()
.executor(executorService)
.connectTimeout(Duration.ofSeconds(10))
.build();
CompletableFuture<HttpResponse<String>> a =
httpClient.sendAsync(httpRequest, BodyHandlers.ofString());
CompletableFuture<HttpResponse<String>> b =
httpClient.sendAsync(httpRequest, BodyHandlers.ofString());
CompletableFuture<HttpResponse<String>> c =
httpClient.sendAsync(httpRequest, BodyHandlers.ofString());
CompletableFuture<HttpResponse<String>> d =
httpClient.sendAsync(httpRequest, BodyHandlers.ofString());
}
Just use the HttpRequest.Builder and let it build two alternating instances.
Generally speaking, once you call .build() on it, the configuration is done.
eg. add a method which takes string and then returns instance of HttpRequest
... where the basic intention is, to reduce duplicate code.
An HttpRequest is stateful, meaning one instance can't represent multiple requests.
You have to create a new instance for each request.
Related
I want to use Java 11 HttpClient and send header first, check response and if response is OK then send the body.
How can I send header only?
this is my current code:
HttpClient httpClient = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.followRedirects(HttpClient.Redirect.NORMAL)
.connectTimeout(Duration.ofSeconds(10))
.authenticator(Authenticator.getDefault())
.build();
HttpRequest httpRequest = HttpRequest.newBuilder("someEndpoint)
.header(CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.header(AUTHORIZATION, "someApiKey)
.build();
HttpResponse<String> httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
However with such httpResponse I understand I send the body.
By default, the header comes first in requests.
What you asked is, The first request with header and then with a body are two different requests. A single request can't be broken this way.
If you are talking about, Http HEAD method usage, then
The HEAD method asks for a response identical to that of a GET request, but without the response body.
The HTTP HEAD method requests the headers that would be returned if the HEAD request's URL was instead requested with the HTTP GET method. For example, if a URL might produce a large download, a HEAD request could read its Content-Length header to check the file size without actually downloading the file.
an example to use HEAD method:-
var httpClient: HttpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
var requestHead = HttpRequest.newBuilder()
.method("HEAD", HttpRequest.BodyPublishers.noBody())
.uri(URI.create("https://www.test.com"))
.build();
val httpResponse = httpClient.send(requestHead, BodyHandlers.discarding());
HttpHeaders headers = response.headers();
headers.map().forEach((key, values) -> {
System.out.printf("%s: %s%n", key, values);
});
I'm absolute beginner in java. Trying to send some http request using the built in java httpclient.
How can I add the request parameters into the URI in such format:
parameter = hi
url = "https://www.url.com?parameter=hi"
With the code, I'm using, I can only set the headers but not the request parameters
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create(url))
.GET()
.build();
var reponse = client.send(request, HttpResponse.BodyHandlers.ofString());
return reponse.body();
Thank you very much!
With native Java 11, it has to be done like you did. You need to add the parameters within the url parameter already. Or you need to create your own builder that allows you to append parameter.
However, your requested behaviour is possible if you make use of libraries. One way to do it is to make use of Apache URIBuilder
var client = HttpClient.newHttpClient();
URI uri = new URIBuilder(httpGet.getURI())
.addParameter("parameter", "hi")
.build();
var request = HttpRequest.newBuilder(uri)
.GET()
.build();
var reponse = client.send(request, HttpResponse.BodyHandlers.ofString());
return reponse.body();
You don't have methods for adding parameters, but you can use String.format() to format the URL nicely.
final static String URL_FORMAT = "http://url.com?%s=%s";
final String request = String.format(URL_FORMAT, "paramater", "hi");
I am trying to make a GET request to a certain URL and get some data that I am going to use inside a Java servlet. This is the code I am using:
final HttpClient httpClient = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.build();
String httpPath = "http://path/to/the/thirdparty/service";
HttpRequest httpRequest = HttpRequest.newBuilder()
.GET()
.uri(URI.create(httpPath))
.build();
HttpResponse httpResponse = null;
try {
httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
} catch (InterruptedException e) {
response.getWriter().println(e.getMessage());
}
response.setContentType("application/json");
PrintWriter out = response.getWriter();
out.println(httpResponse.body().toString());
This works perfectly and gives the desired output when I run the code from inside a standalone class inside it's main method. However, when I run this from the servelet, I can't produce the output. The response code is 200, however the content is missing with a curl error:
* transfer closed with outstanding read data remaining
* Closing connection 0
curl: (18) transfer closed with outstanding read data remaining
To see whether the length of the data is the problem, I hardcoded the output that is expected from the third party response (and commented out the call from httpClient), that gets sent out in the response correctly when I make a curl request to the servlet. Any help is much appreciated.
I have below API which returns back the access_token.
POST https://idcs-xxxxxxxxxbf08128c3d93a19c.identity.c9dev2.oc9qadev.com/oauth2/v1/token
in header content-type is application/x-www-form-urlencoded. also in body it contains below parameter.
I send user name and password and it is secured with basic authentication. It provides access_token when I call from postman. also it provides output when I consume using HttpUrlConnection
url = new URL(tokenURL);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Authorization", auth);
connection.setRequestProperty("Accept", "application/json");
OutputStream os = connection.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
osw.write("grant_type=client_credentials&scope=" + scope);
The above code is working properly. But when I use jersey it gives 415 error. I am using below code.
String user="idcs-oda-zzzxxxxxf93560b94eb8a2e2a4c9aac9a3ff-t0_APPID";
String password="xxxxxxx-6f71-4af2-b5cc-9110890d1456";
String scope = "https://idcs-oda-xxxxxxxxxxxxxxxxe2a4c9aac9a3ff-t0.data.digitalassistant.oci.oc-test.com/api/v1";
String tokenURL = "https://idcs-xxxxxxxxxxxxxxxx28c3d93a19c.identity.c9dev2.oc9qadev.com/oauth2/v1/token";
HttpAuthenticationFeature feature= HttpAuthenticationFeature
.basicBuilder()
.nonPreemptive()
.credentials(user,password)
.build();
ClientConfig clientConfig = new ClientConfig();
clientConfig.register(feature);
Client client = ClientBuilder.newClient(clientConfig);
WebTarget webTarget= client.target(tokenURL);
PostDetails post= new PostDetails("client_credentials",scope); //Bean class to assign body parameter
Response response= webTarget.request()
.header("Content-Type", "application/x-www-form-urlencoded")
.post(Entity.json(post));
System.out.println(response);
Can somebody tell me what mistake I am doing in Response line.
You need to set your Accept on the request method:
Response response= webTarget.request(MediaType.APPLICATION_JSON)
.header("Content-Type", "application/x-www-form-urlencoded")
.post(Entity.json(post));
You also need to ensure that if your API accepts application/x-www-form-urlencoded content, that is what you are sending.
Currently, you are sending application/json content based on your usage of Entity.json(post).
I don't know what type is assigned to post, but you need to figure out how to convert it either to a Form or a MultiValuedMap<String,String>, and then use the form method on Entity to submit your content.
Response response= webTarget.request(MediaType.APPLICATION_JSON)
.header("Content-Type", "application/x-www-form-urlencoded")
.post(Entity.form(postForm)); //assuming postForm typed as Form or MultiValuedMap<String,String>
Taking a guess regarding post, creating postForm as a MultiValuedMap<String,String> may be as simple as the following (which you would place prior to your request, of course).
MultiValuedMap<String,String> postForm = new MultiValuedHashMap<>();
postForm.add("client_credentials",scope);
What you need is:
Response response= webTarget.request()
.accept("application/json") // Accept field from header of request
.header("Content-Type", "application/x-www-form-urlencoded") //manually set content-tyoe
.post(Entity.entity(input, MediaType.TEXT_PLAIN)); // request body
The best way to see what is Jersey actually is sending is to register logger, and log network. For example:
clientConfig.register(
new LoggingFeature(
new Slf4jLogger(this.getClass().getName(), null)));
where Slf4jLogger is from org.apache.cxf:cxf-core.
How could I set the accept and contentType to json projectwide in my rest tests?
given()
.accept(ContentType.JSON)
.contentType(ContentType.JSON)
This will reduce quite some repetitive code
RestAssured.requestSpecification = new RequestSpecBuilder()
.setContentType(ContentType.JSON)
.setAccept(ContentType.JSON)
.build();