Specify raw query string when using WebTarget - java

I'm working with a large existing project, which utilises javax.ws.rs.client.WebTarget to talk to RESTful API. The API is developed by a third party and I have no control over it. I need to make a request in the following format:
https://end.point.url/endpoint/id?data
Unfortunately, I can't figure out how to specify such request using WebTarget. I tried using path("endpoint/id?data"), but this gets converted into endpoint/id%3Fdata and I get 404 back. I tried using queryParam specifying empty value, which gets me endpoint/id?data= - which results in error required parameter data missing.
What other option is there? Replacing WebTarget with something else isn't feasible, as it is all over the large project.

First, related question: Url encoding issue with Jersey Client
After quite a bit of research, it seems that the only way to do it is to specify the entire uri when the WebTarget is created, like so:
Client client = ClientBuilder.newClient().register(authFeature);
WebTarget webTarget = client.target("https://end.point.url/endpoint/id?data")

Related

How to make jersey client call to url in format http://ppp.com/yy?zz,aa,bb

I have searched through a lot but i am not able to figure out the solution to issue.
I have an external url which i want to call using jersey rest api. The url is in format http://ppp.com/yy?zz,aa,bb.
If i use queryparam then it gives url pattern '?test=data' but i don't want '=' after test. How can i create this specific pattern of url using jersey. Below is same code with issue.
Client client = ClientBuilder.newClient(config);
WebTarget target = client.target(getBaseURI()).path("yy").queryParam("zz,aa,bb","");
I have no idea why you need such a URL, but
WebTarget target = client.target(getBaseURI()).path("yy?zz,aa,bb")
Just build your path parameter prior to passing it in.

Params for a GET request for a REST Service Java

I am creating a REST service in Java ,and have a doubt with regards to params for the GET method .
I have to pass the below params in a GET request
Function
"GET" File status :
Params:
Time Range:(String)
FlowId:(String)
ID_A= or ID_B= or Both (String)
IS_ADD_A= or IS_ADD_B= or both (String)
Regex=(String)
Cookie=XXXXX
So as there are 6 params,so passing it as a query string would not be an efficient way and can't but the same in body(as it is against the HTTP GET specification)
Making this as a POST call would be against the REST principle as I want to get data from the server ,
What would be an efficient way of solving this ,would passing the params as query string is out of question,passing it in body which is against the HTTP spec ,making this as headers which may also be not good ,making this as POST request which will voilate the fielding's REST principle .
Passing data in the body of an HTTP GET call is not only against the spec but causes problems with various server-side technologies which assume you don't need access to the body in a GET call. (Some client side frameworks also have some issues with GET and a query in the body) If you have queried with long parameters I'd go with POST. It's then using POST for getting data but you'd not be the only one having to go this way to support potentially large queries.
If your parameters values aren't very long, using query string is your best option here. 6 params is not a lot, as long you don't exceed the IE limit of characters in the path - 2,048 (http://www.boutell.com/newfaq/misc/urllength.html). For example Google search engine uses many more params then 6. If there is a possibility that the URL path will exceed the limit above, you should use POST instead.

Can Elasticsearch stream the SearchResponse?

I have a rest application that can export some report data from Elasticsearch. It is easy to do with the Java API:
SearchResponse response = getClient()
.prepareSearch("my_index_name")
.setQuery(QueryBuilders.someQuery())
.addAggregation(AggregationBuilders.someAggregation())
.get();
The problem starts with the big responses. Using this code snippet, the response is read to build the SearchResponse object in memory. In my case, the response does not fits in memory.
Paging cannot help because we often need to return the full data and Aggregations do not support paging yet.
I know that I can use the Elasticsearch REST API to read the response as stream, but manually build the request it is cumbersome. I really want something like this:
// my dream API
InputStream response = getClient()
.prepareSearch("my_index_name")
.setQuery(QueryBuilders.someQuery())
.addAggregation(AggregationBuilders.someAggregation())
.getStream();
So, can the Elasticsearch Java API stream the SearchResponse?
A proposal for streaming results does exist but it doesn't seem to have picked up steam so far and was closed (for now).
There's a way to do it with XContentBuilder but that still requires the whole response to be in memory before being sent.
It might not be what you want, but that's the closest thing that I know which could fulfill your need. Worth giving it a try.
I believe there is no way to obtain an InputStream from the Java API (but I might be wrong). I also think there is no way to directly obtain an InputStream in Jest (a REST-based Elasticsearch Java API).
You mention that it is cumbersome to create the search request to the _search endpoint yourself: if you're referring to building the actual json query, I just would like to point out that once you have a SearchSourceBuilder, you can call toString() on it to get a fully working json representation of your query.
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(this.getQuery())
.from(this.getFrom())
.size(this.getSize())
.fetchSource(this.getSource(), null);
this.getSort().forEach(sourceBuilder::sort);
sourceBuilder.toString() // the json representation

HttpURLConnection "enctype" POST [duplicate]

How can I set content type of HTTP Put as xxxx+xml?
I was referring to solution in this link Android, sending XML via HTTP POST (SOAP). Its fine when we set content type like this, i mean the xml is came along with the request:
httppost.setHeader("Content-Type","application/soap+xml;charset=UTF-8");
but when i change type soap to something custom, the xml disappear on the request (i saw on the wireshark), like this:
httppost.setHeader("Content-Type","application/vnd.oma-pcc+xml;charset=UTF-8");
then, i tried put the xml only, so the request is ok again:
httppost.setHeader("Content-Type","application/xml;charset=UTF-8");
I want to know what exactly the rules for the content-type than come together with the xml type so that the xml still there.
Thanks.
Assuming you're using HTTPClient of 4.1.3 or greater -
When constructing you're entity, you have the option to specify the content being used for the POST or PUT operation for certain entities.
There is a ContentType object which should be used to specify this.
Using the factory method .create() you can specify the mimetype with a charset - the ContentType will be used by the framework to properly emit the header in question.
Example API call:
ContentType.create("application/vnd.oma-pcc+xml", CharSet.forName("UTF-8"));
NOTE Editing for HttpClient 4.1.2
In the case of 4.1.2, when you create your entity for the post or put operation, set the content type on the entity not the execution (HttpPost or HttpPut) using setContentType(String). This is deprecated in 4.1.3 and beyond.

How can I POST using Java and include parameters and a raw request body?

I am communicating with a web service that expects a POST parameter and also expect Request body. I have confirmed that such a POST request can be done using a REST Console I have, but I am unable to make such a request in Java using Apache libraries.
In the code below, I am able to POST to the web service, and it correctly receives the contents of the variable raw_body. If I uncomment the first of the two commented lines, the web service receives the "fname" parameter, but it no longer receives the body of the POST.
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
...
HttpClient httpClient = new HttpClient();
String urlStr = "http://localhost:8080/MyRestWebService/save";
PostMethod method = new PostMethod(urlStr);
String raw_body = "This is a very long string, much too long to be just another parameter";
RequestEntity re = new StringRequestEntity(raw_body, "text/xml", "UTF-16");
//method.addParameter("fname", "test.txt");
//httpClient.getParams().setParameter("fname", "test.txt");
method.setRequestEntity(re);
How can I transmit both the parameter and the body?
You could use the setQueryString method to add the parameters to the URL that is being POSTed to. From a RESTful perspective I'd argue you should normally not be doing that, however, since a POST should represent a call to a resource and anything that would qualify for a query parameter should be included in the representation that is being transferred in the request body...or it should represent qualification of the resource itself in which case it should be part of the path that is posted to which could then be extracted by the controller using #PathVariable/#PathParam or something similar. So in your case you could also be looking for something like POST /MyRestWebService/files/test.txt or more fittingly a PUT if you're saving the resource and know the URI. The code on the server could pull the filename out from a URL pattern.
You need to make a POST request using multipart-form. Here is the example:
Apache HttpClient making multipart form post
Alternatively, you can make a POST request with the content (parameters and files) encoded using application/x-www-form-urlencoded but it is not recommended when you want to make a POST request with large content, like files.

Categories

Resources