How to pass complex parameter to POST request using Apache HTTP client? - java

I attempt to send POST request with body like this
{
"method": "getAreas",
"methodProperties": {
"prop1" : "value1",
"prop2" : "value2",
}
}
Here is my code
static final String HOST = "https://somehost.com";
public String sendPost(String method,
Map<String, String> methodProperties) throws ClientProtocolException, IOException {
HttpPost post = new HttpPost(HOST);
List<NameValuePair> urlParameters = new ArrayList<>();
urlParameters.add(new BasicNameValuePair("method", method));
List<NameValuePair> methodPropertiesList = methodProperties.entrySet().stream()
.map(entry -> new BasicNameValuePair(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
// ??? urlParameters.add(new BasicNameValuePair("methodProperties", methodPropertiesList));
post.setEntity(new UrlEncodedFormEntity(urlParameters));
try (CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = httpClient.execute(post)) {
return EntityUtils.toString(response.getEntity());
}
}
But constructor of BasicNameValuePair applies (String, String). So I need another class instead.
Is there any way to add methodPropertiesList to urlParameters?

your request looking like a json structure so post data like below:
class pojo1{
String method;
Map<String,String> methodProperties;
}
String postUrl = "www.site.com";// put in your url
Gson gson = new Gson();
HttpClient httpClient = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(postUrl);
StringEntity postingString = new StringEntity(gson.toJson(pojo1));//gson.tojson() converts your pojo to json
post.setEntity(postingString);
post.setHeader("Content-type", "application/json");
HttpResponse response = httpClient.execute(post);
ref:HTTP POST using JSON in Java

There is a well known approach to this problem.
In most cases you will create your own object describing the thing that you want to send in the HttpPost. So you will have something like:
static final String HOST = "https://somehost.com";
public String sendPost(String method,
Map<String, String> methodProperties) throws ClientProtocolException, IOException {
HttpPost post = new HttpPost(HOST);
MyResource resource = new MyResource();
resource.setMethod(method);
MyNestedResource nestedResource = new MyNestedResource();
nestedResource.setMethodProperties(methodProperties);
resource.setNestedResourceMethodProperties(nestedResource);
StringEntity strEntity = new StringEntity(gson.toJson(resource));
post.setEntity(strEntity);
try (CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = httpClient.execute(post)) {
return EntityUtils.toString(response.getEntity());
}
}
And that is usually how you approach more complext json objects with a nested structure. You have to create classes for the resources you want to send (in your example it may be one class and to use map in it, but usually you create a class for the nested object too if it has a specific structure). To get more familiar with the whole picture better cover this tutorial: https://www.baeldung.com/jackson-mapping-dynamic-object

Using Sushil Mittal answer here is my solution
static final String HOST = "https://somehost.com";
public String sendPost(String method, Map<String, String> methodProperties) throws ClientProtocolException, IOException {
HttpPost post = new HttpPost(HOST);
Gson gson = new Gson();
Params params = new Params(method, methodProperties);
StringEntity entity = new StringEntity(gson.toJson(params));
post.setEntity(entity);
try (CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = httpClient.execute(post)) {
return EntityUtils.toString(response.getEntity());
}
}
class Params {
String method;
Map<String, String> methodProperties;
public Params(String method, Map<String, String> methodProperties) {
this.method = method;
this.methodProperties = methodProperties;
}
//getters
}

Related

Send HTTPS request with JSON through Java [duplicate]

I would like to make a simple HTTP POST using JSON in Java.
Let's say the URL is www.site.com
and it takes in the value {"name":"myname","age":"20"} labeled as 'details' for example.
How would I go about creating the syntax for the POST?
I also can't seem to find a POST method in the JSON Javadocs.
Here is what you need to do:
Get the Apache HttpClient, this would enable you to make the required request
Create an HttpPost request with it and add the header application/x-www-form-urlencoded
Create a StringEntity that you will pass JSON to it
Execute the call
The code roughly looks like (you will still need to debug it and make it work):
// #Deprecated HttpClient httpClient = new DefaultHttpClient();
HttpClient httpClient = HttpClientBuilder.create().build();
try {
HttpPost request = new HttpPost("http://yoururl");
StringEntity params = new StringEntity("details={\"name\":\"xyz\",\"age\":\"20\"} ");
request.addHeader("content-type", "application/x-www-form-urlencoded");
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
} catch (Exception ex) {
} finally {
// #Deprecated httpClient.getConnectionManager().shutdown();
}
You can make use of Gson library to convert your java classes to JSON objects.
Create a pojo class for variables you want to send
as per above Example
{"name":"myname","age":"20"}
becomes
class pojo1
{
String name;
String age;
//generate setter and getters
}
once you set the variables in pojo1 class you can send that using the following code
String postUrl = "www.site.com";// put in your url
Gson gson = new Gson();
HttpClient httpClient = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(postUrl);
StringEntity postingString = new StringEntity(gson.toJson(pojo1));//gson.tojson() converts your pojo to json
post.setEntity(postingString);
post.setHeader("Content-type", "application/json");
HttpResponse response = httpClient.execute(post);
and these are the imports
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
and for GSON
import com.google.gson.Gson;
#momo's answer for Apache HttpClient, version 4.3.1 or later. I'm using JSON-Java to build my JSON object:
JSONObject json = new JSONObject();
json.put("someKey", "someValue");
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
try {
HttpPost request = new HttpPost("http://yoururl");
StringEntity params = new StringEntity(json.toString());
request.addHeader("content-type", "application/json");
request.setEntity(params);
httpClient.execute(request);
// handle response here...
} catch (Exception ex) {
// handle exception here
} finally {
httpClient.close();
}
It's probably easiest to use HttpURLConnection.
http://www.xyzws.com/Javafaq/how-to-use-httpurlconnection-post-data-to-web-server/139
You'll use JSONObject or whatever to construct your JSON, but not to handle the network; you need to serialize it and then pass it to an HttpURLConnection to POST.
protected void sendJson(final String play, final String prop) {
Thread t = new Thread() {
public void run() {
Looper.prepare(); //For Preparing Message Pool for the childThread
HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 1000); //Timeout Limit
HttpResponse response;
JSONObject json = new JSONObject();
try {
HttpPost post = new HttpPost("http://192.168.0.44:80");
json.put("play", play);
json.put("Properties", prop);
StringEntity se = new StringEntity(json.toString());
se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post.setEntity(se);
response = client.execute(post);
/*Checking response */
if (response != null) {
InputStream in = response.getEntity().getContent(); //Get the data in the entity
}
} catch (Exception e) {
e.printStackTrace();
showMessage("Error", "Cannot Estabilish Connection");
}
Looper.loop(); //Loop in the message queue
}
};
t.start();
}
Try this code:
HttpClient httpClient = new DefaultHttpClient();
try {
HttpPost request = new HttpPost("http://yoururl");
StringEntity params =new StringEntity("details={\"name\":\"myname\",\"age\":\"20\"} ");
request.addHeader("content-type", "application/json");
request.addHeader("Accept","application/json");
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
// handle response here...
}catch (Exception ex) {
// handle exception here
} finally {
httpClient.getConnectionManager().shutdown();
}
I found this question looking for solution about how to send post request from java client to Google Endpoints. Above answers, very likely correct, but not work in case of Google Endpoints.
Solution for Google Endpoints.
Request body must contains only JSON string, not name=value pair.
Content type header must be set to "application/json".
post("http://localhost:8888/_ah/api/langapi/v1/createLanguage",
"{\"language\":\"russian\", \"description\":\"dsfsdfsdfsdfsd\"}");
public static void post(String url, String json ) throws Exception{
String charset = "UTF-8";
URLConnection connection = new URL(url).openConnection();
connection.setDoOutput(true); // Triggers POST.
connection.setRequestProperty("Accept-Charset", charset);
connection.setRequestProperty("Content-Type", "application/json;charset=" + charset);
try (OutputStream output = connection.getOutputStream()) {
output.write(json.getBytes(charset));
}
InputStream response = connection.getInputStream();
}
It sure can be done using HttpClient as well.
You can use the following code with Apache HTTP:
String payload = "{\"name\": \"myname\", \"age\": \"20\"}";
post.setEntity(new StringEntity(payload, ContentType.APPLICATION_JSON));
response = client.execute(request);
Additionally you can create a json object and put in fields into the object like this
HttpPost post = new HttpPost(URL);
JSONObject payload = new JSONObject();
payload.put("name", "myName");
payload.put("age", "20");
post.setEntity(new StringEntity(payload.toString(), ContentType.APPLICATION_JSON));
For Java 11 you can use the new HTTP client:
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://localhost/api"))
.header("Content-Type", "application/json")
.POST(ofInputStream(() -> getClass().getResourceAsStream(
"/some-data.json")))
.build();
client.sendAsync(request, BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join();
You can use publishers from InputStream, String, File. Converting JSON to a String or IS can be done with Jackson.
Java 11 standardization of HTTP client API that implements HTTP/2 and Web Socket, and can be found at java.net.HTTP.*:
String payload = "{\"name\": \"myname\", \"age\": \"20\"}";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(URI.create("www.site.com"))
.header("content-type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
Java 8 with apache httpClient 4
CloseableHttpClient client = HttpClientBuilder.create().build();
HttpPost httpPost = new HttpPost("www.site.com");
String json = "details={\"name\":\"myname\",\"age\":\"20\"} ";
try {
StringEntity entity = new StringEntity(json);
httpPost.setEntity(entity);
// set your POST request headers to accept json contents
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
try {
// your closeablehttp response
CloseableHttpResponse response = client.execute(httpPost);
// print your status code from the response
System.out.println(response.getStatusLine().getStatusCode());
// take the response body as a json formatted string
String responseJSON = EntityUtils.toString(response.getEntity());
// convert/parse the json formatted string to a json object
JSONObject jobj = new JSONObject(responseJSON);
//print your response body that formatted into json
System.out.println(jobj);
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
I recomend http-request built on apache http api.
HttpRequest<String> httpRequest = HttpRequestBuilder.createPost(yourUri, String.class)
.responseDeserializer(ResponseDeserializer.ignorableDeserializer()).build();
public void send(){
ResponseHandler<String> responseHandler = httpRequest.execute("details", yourJsonData);
int statusCode = responseHandler.getStatusCode();
String responseContent = responseHandler.orElse(null); // returns Content from response. If content isn't present returns null.
}
If you want send JSON as request body you can:
ResponseHandler<String> responseHandler = httpRequest.executeWithBody(yourJsonData);
I higly recomend read documentation before use.

How to get full json response using httprequest

Simply I am trying to hit URL i.e. www.google.com
and I want to capture whole json responce as output ...
I tried multiple codes which help me to find only response code but I want full json response from which I can filter few information.
above thing I am doing for web..
I used ApacheHttpClient jar (version 4.5.1). You'll also need HttpCore library (I used 4.4.3) and maybe some other apache libraries (like codec).
Here are a GET method and a POST method:
public static String getJsonStringHttpGet(String url,Map<String,String> headers) throws IOException {
BasicCookieStore cookieStore = new BasicCookieStore();
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultCookieStore(cookieStore)
.build();
HttpCoreContext localContext = new HttpCoreContext();
HttpGet get = new HttpGet(url);
/*
* if you need to specify headers
*/
if (headers != null) {
for (String name : headers.keySet()) {
get.addHeader(name, headers.get(name));
}
}
HttpResponse response = httpClient.execute(get, localContext);
byte [] bytes = EntityUtils.toByteArray(response.getEntity());
return new String(bytes);
}
public static String getJsonStringHttpPost(String url,Map<String,String> postParams,Map<String,String> headers) throws IOException {
BasicCookieStore cookieStore = new BasicCookieStore();
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultCookieStore(cookieStore)
.build();
HttpCoreContext localContext = new HttpCoreContext();
HttpPost post = new HttpPost(url);
/*
* adding some POST params
*/
if (postParams != null && postParams.size() > 0) {
List<BasicNameValuePair> postParameters = new ArrayList<>();
for (String name : postParams.keySet()) {
postParameters.add(new BasicNameValuePair(name, postParams.get(name)));
}
post.setEntity(new UrlEncodedFormEntity(postParameters));
}
/*
* if you need to specify headers
*/
if (headers != null) {
for (String name : headers.keySet()) {
post.addHeader(name, headers.get(name));
}
}
HttpResponse response = httpClient.execute(post, localContext);
byte [] bytes = EntityUtils.toByteArray(response.getEntity());
return new String(bytes);
}
Then you can parse the json string as you like.
Hope this helps

add json object to Java HttpGet request to C# WebApi

i'm trying to send json object from java client to C# WebApi, but the input parameter is null.
the java code:
ObjectMapper mapper = new ObjectMapper();
Gson gson = new Gson();
String json = gson.toJson(per);
HttpClient httpclient = new DefaultHttpClient();
List<NameValuePair> qparams = new ArrayList<NameValuePair>();
qparams.add(new BasicNameValuePair("person", json.toString()));
HttpGet httpPost = new HttpGet("http://naviserver.azurewebsites.net/api/Person/Get?" + URLEncodedUtils.format(qparams, "UTF-8"));
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
httpPost.setHeader(
"Authorization",
"Bearer TokenRemovedBecauseUseless");
org.apache.http.HttpResponse httpResponse = httpclient.execute(httpPost);
the WebApi method:
public List<String> Get([FromUri]Person person)
{}
can someone tell me how to send json object?
The problem is that the WebApi is not expecting the person object in JSON format. By using FromUri with a complex object, it is expecting that the url with have a query parameter for each field in Person.
There is a nice example here about how it works.
Basically you will want your query parameters to look like this:
http://naviserver.azurewebsites.net/api/Person/Get?name=dave&age=30
and in Java:
qparams.add(new BasicNameValuePair("name", person.getName()));
qparams.add(new BasicNameValuePair("age", String.valueOf(person.getAge())));
If you want to send the person in JSON format, a better way would be to use a HTTP POST and set the JSON in the body. Then in the WebApi, your method would look like this:
public HttpResponseMessage Post([FromBody]Person person)
You will then also have to change your Java client to send a POST request.
HttpClient httpClient = HttpClientBuilder.create().build();
HttpPost httpPost = new HttpPost("http://naviserver.azurewebsites.net/api/Person");
Person person = new Person("dave", 30);
Gson gson = new Gson();
String json = gson.toJson(person);
StringEntity body = new StringEntity(json);
httpPost.setEntity(body);
HttpResponse response = httpClient.execute(httpPost);

How to pass a JSON string as a POST param avoiding character encoding in Java?

I'm trying to send a POST param to a REST endpoint I have. This param is a JSON String, that contains special chars like double quotes ("). On the endpoint I keep on getting the String encoded.
THis is the request part:
HttpClient client = HttpClientBuilder.create().build();
StringBuilder query = new StringBuilder();
query.append(callBackURL);
ArrayList<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
urlParameters.add(new BasicNameValuePair("update", "{\"object\":\"page\",\"entry\":[{\"id\":\"316492991876763\",\"time\":1417436403,\"changes\":[{\"field\":\"feed\",\"value\":{\"item\":\"comment\",\"verb\":\"add\",\"comment_id\":\"321528008039928_323256911200371\",\"parent_id\":\"316492991876763_321528008039928\",\"sender_id\":100006737955082,\"created_time\":1417436403}}]}]}"));
try {
HttpPost post = new HttpPost(query.toString());
post.setEntity(new UrlEncodedFormEntity(urlParameters));
post.addHeader("content-type", "application/json");
HttpResponse response = null;
try {
response = client.execute(post);
}
catch (IOException e) {
System.out.println(e.getMessage());
}
}
catch (UnsupportedEncodingException e2) {
System.out.println(e2.getMessage());
}
Now in the endpoint part:
/**
* Callback method that receives FB updates
* #return 200 OK if everything goes OK, 401 ERROR otherwise
*/
#POST
#Path("/callback")
#Consumes(MediaType.APPLICATION_JSON)
public Response facebookUpdate(String update, #Context HttpServletRequest request, #Context HttpServletResponse response) throws ServletException, IOException{
JsonParser jsonParser = new JsonParser();
//parse it
JsonElement json = jsonParser.parse(update);
...
}
What I'm getting is a String encoded like this:
%7B%22object%22%3A%22page%22%2C%22entry%22%3A%5B%7B%22id%22%3A%22316492991876763%22%2C%22time%22%3A1417436403%2C%22changes%22%3A%5B%7B%22field%22%3A%22feed%22%2C%22value%22%3A%7B%22item%22%3A%22comment%22%2C%22verb%22%3A%22add%22%2C%22comment_id%22%3A%22321528008039928_323256911200371%22%2C%22parent_id%22%3A%22316492991876763_321528008039928%22%2C%22sender_id%22%3A100006737955082%2C%22created_time%22%3A1417436403%7D%7D%5D%7D%5D%7D
Something I cannot convert to a JsonElement...
Any ideas how to avoid this?
Thanks!
Alejandro
UPDATE:
I found what the problem was, so I'm explaining it here in case anyone has the same problem.
I was trying to pass a param using a BasicNameValuePair, like so:
ArrayList<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
urlParameters.add(new BasicNameValuePair("update", "{\"object\":\"page\",\"entry\":[{\"id\":\"316492991876763\",\"time\":1417436403,\"changes\":[{\"field\":\"feed\",\"value\":{\"item\":\"comment\",\"verb\":\"add\",\"comment_id\":\"321528008039928_323256911200371\",\"parent_id\":\"316492991876763_321528008039928\",\"sender_id\":100006737955082,\"created_time\":1417436403}}]}]}"));
I've changed to a simple StringEntity, like this:
StringEntity params = new StringEntity(json.toString());
HttpPost post = new HttpPost(query.toString());
Thus, I don't need to decode. Mistery remains on why passing an Array of BasicNameValuePair will encode the String...
use annotation above the method you want to produce JSON from
#Produces("application/json")

Sending and Parsing Response using HTTP Client for a JSON List

With in my java code, I need to send a http post request to a specific URL with 3 headers:
URL: http://localhost/something
Referer: http://localhost/something
Authorization: Basic (with a username and password)
Content-type: application/json
This returns a response with a JSON "key":"value" pair in it that I then need to parse somehow to store the key/value (Alan/72) in a MAP. The response is (when using SOAPUI or Postman Rest):
{
"analyzedNames": [
{
"alternate": false
}
],
"nameResults": [
{
"alternate": false,
"givenName": "John",
"nameCategory": "PERSONAL",
"originalGivenName": "",
"originalSurname": "",
"score": 72,
"scriptType": "NOSCRIPT",
}
]
}
I can do this using SOAPUI or Postman Rest but how can I do this within Java as I'm getting an error:
****DEBUG main org.apache.http.impl.conn.DefaultClientConnection - Receiving response: HTTP/1.1 500 Internal Server Error****
My code is:
public class NameSearch {
/**
* #param args
* #throws IOException
* #throws ClientProtocolException
*/
public static void main(String[] args) throws ClientProtocolException, IOException {
// TODO Auto-generated method stub
DefaultHttpClient defaultHttpClient = new DefaultHttpClient();
StringWriter writer = new StringWriter();
//Define a postRequest request
HttpPost postRequest = new HttpPost("http://127.0.0.1:1400/dispatcher/api/rest/search");
//Set the content-type header
postRequest.addHeader("content-type", "application/json");
postRequest.addHeader("Authorization", "Basic ZW5zYWRtaW46ZW5zYWRtaW4=");
try {
//Set the request post body
StringEntity userEntity = new StringEntity(writer.getBuffer().toString());
postRequest.setEntity(userEntity);
//Send the request; return the response in HttpResponse object if any
HttpResponse response = defaultHttpClient.execute(postRequest);
//verify if any error code first
int statusCode = response.getStatusLine().getStatusCode();
}
finally
{
//Important: Close the connect
defaultHttpClient.getConnectionManager().shutdown();
}
}
}
Any help (with some sample code including which libraries to import) will be most appreciated.
THANKS
Yes, you can do it with java
You need apache HTTP client library http://hc.apache.org/ and commons-io
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://localhost/something");
post.setHeader("Referer", "http://localhost/something");
post.setHeader("Authorization", "Basic (with a username and password)");
post.setHeader("Content-type", "application/json");
// if you need any parameters
List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
urlParameters.add(new BasicNameValuePair("paramName", "paramValue"));
post.setEntity(new UrlEncodedFormEntity(urlParameters));
HttpResponse response = client.execute(post);
HttpEntity entity = response.getEntity();
Header encodingHeader = entity.getContentEncoding();
// you need to know the encoding to parse correctly
Charset encoding = encodingHeader == null ? StandardCharsets.UTF_8 :
Charsets.toCharset(encodingHeader.getValue());
// use org.apache.http.util.EntityUtils to read json as string
String json = EntityUtils.toString(entity, StandardCharsets.UTF_8);
JSONObject o = new JSONObject(json);
I recommend http-request built on Apache HTTP API.
HttpRequest<String> httpRequest = HttpRequestBuilder.createPost(yourUri
new TypeReference<Map<String, List<Map<String, Object>>>>{})
.basicAuth(userName, password)
.addContentType(ContentType.APPLICATION_JSON)
.build();
public void send(){
ResponseHandler<String> responseHandler = httpRequest.executeWithBody(yourJsonData);
int statusCode = responseHandler.getStatusCode();
Map<String, List<Map<String, Object>>> response = responseHandler.get(); // Before calling the get () method, make sure the response is present: responseHandler.hasContent()
System.out.println(response.get("nameResults").get(0).get("givenName")); //John
}
I highly recommend reading the documentation before use.
Note: You can create your custom type instead of Map to parse response. See my answer here.

Categories