Java PostMethod with xml - java

I am trying to post XML data as a body to a REST api.
I have a method that creates the request called doREST.
String url = null;
HttpMethod method;
LOG.info("QUERY: " + query);
if (StringUtil.isEmpty(query)) {
url = BuildRequestURL("/issues.ashx/issues/mywork");
method = doREST(url, false);
} else {
url = BuildRequestURL("/issues.ashx/issues/filters");
//method = doREST(url, true);
method = doREST(url, true);
String xml = "<IssuesFilterEN>" +
"<IssueID>" + query + "</IssueID>" +
"</IssuesFilterEN>";
RequestEntity entity = new StringRequestEntity(xml,"text/xml; charset=iso-8859-1", null);
method.setRequestEntity(entity);
}
and the doREST method
private HttpMethod doREST(String request, boolean post) throws Exception {
String uri = request;
HttpMethod method = post ? new PostMethod(uri) : new GetMethod(uri);
configureHttpMethod(method);
HttpClient client = getHttpClient();
client.getParams().setParameter(HttpClientParams.SO_TIMEOUT, timeoutLength);
client.executeMethod(method);
return method;
}
My issue is the method.setRequestEntity is saying that the method could not be found.
I have
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.*;
If i set method = PostMethod instead of method = doREST it works but I don't want to have to do that in all my other methods just to create queries.
Is there something I am missing as to why the method.setRequestEntity is not working the way it is right now?
EDIT:
I got my information for using setRequestEntity from PostMethod setRequestBody(String) deprecated - why?
EDIT 2:
Here is what I ended up doing.
private HttpMethod doREST(String request, RequestEntity entity) throws Exception {
String uri = request;
HttpMethod method;
if ( entity != null ){
method = new PostMethod(uri);
((PostMethod) method).setRequestEntity(entity);
} else {
method = new GetMethod(uri);
}
configureHttpMethod(method);
HttpClient client = getHttpClient();
client.getParams().setParameter(HttpClientParams.SO_TIMEOUT, timeoutLength);
client.executeMethod(method);
return method;
}

You should modify doREST to accept the RequestEntity instead of a boolean. Pass in null for a GET and a value for POST. Use that as the check to see if you need a PostMethod or a GetMethod. Then you can have the specific type so you can call the PostMethod only setRequestEntity().
EDIT:
You can avoid the cast like this:
private HttpMethod doREST(String request, RequestEntity entity) throws Exception {
String uri = request;
HttpMethod method;
if ( entity != null ){
PostMethod postMethod = new PostMethod(uri);
postMethod.setRequestEntity(entity);
method = postMethod;
} else {
method = new GetMethod(uri);
}
configureHttpMethod(method);
HttpClient client = getHttpClient();
client.getParams().setParameter(HttpClientParams.SO_TIMEOUT, timeoutLength);
client.executeMethod(method);
return method;
}

The method you should be calling is setEntity, not setRequestEntity. Also, your body should be wrapped in a StringEntity, not a StringRequestEntity, imported from org.apache.http.entity.

Related

How to add parameters to java.net.http.HttpClient GET request?

We found the following example, which works:
import java.net.http.HttpClient;
:
private static final HttpClient httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1)
.connectTimeout(Duration.ofSeconds(TIMEOUT)).build();
:
public String getStuff(HashMap<String,String> params) {
HttpRequest request = HttpRequest.newBuilder().GET().uri(URI.create("https://httpbin.org/get"))
.setHeader("User-Agent", "My Agent v1.0")
.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
return response.body();
}
The question is how do we get the params into the request? We could manually put them in the URI by string manipulation, but this wont work for POST.
We would expect a setParameter method similar to setHeader, but this doesnt exist (according to eclipse at least).
For now I am doing it manually thusly:
String uri = "http://Somesite.com/somepath";
if (params != null) {
uri += "?";
for (String key : params.keySet()) {
uri += "" + key + "=" + params.get(key);
}
}
HttpRequest request = HttpRequest.newBuilder().GET().uri(URI.create(uri))
.setHeader("User-Agent", agent)
.build();
Presumably for POST ill have to manually construct a body with the post params structure.
Use javax.ws.rs.core.UriBuilder
It has queryParam method.
e.g.:
UriBuilder.fromLink( Link.fromUri( "somehost" ).build() )
.path( API_SERVICES )
.queryParam( "path", path)
.queryParam( "method", method )
.build();

How can I pass headers using RestTemplate?

In my method I initially used RestTemplate postForObject method to post request to an endpoint. Now I have to add default OAuth token and pass it as Post request. Is there any way I can pass both request as well as Default Header as part of POST request by using postForObject?
Initiall I used below postForObject
String result = restTemplate.postForObject(url, request, String.class);
I am looking for something like below
restTemplate.exchange(url,HttpMethod.POST,getEntity(),String.class );
Here is my code
private final String url;
private final MarkBuild header;
public DataImpl(#Qualifier(OAuth) MarkBuild header,RestTemplate restTemplate) {
this.restTemplate= restTemplate;
this.header = header;
}
public void postJson(Set<String> results){
try {
Map<String, String> requestBody = new HashMap<>();
requestBody.put("news", "data");
JSONObject jsonObject = new JSONObject(requestBody);
HttpEntity<String> request = new HttpEntity<String>(jsonObject.toString(), null);
String result = restTemplate.postForObject(url, request, String.class);
}
}
Below is getHttpEntity which I want to pass with Post request
private HttpEntity getHttpEntity(Set <String>results) {
return new HttpEntity<>( null, getHttpHeaders() );
}
private HttpHeaders getHttpHeaders() {
return header.build();
}
}
Is there any way I can pass both request as well as Default Header as
part of POST request by using postForObject?
Yes, there is a way to do that, I can give a basic example:
HttpHeaders lHttpHeaders = new HttpHeaders();
lHttpHeaders.setContentType( MediaType.APPLICATION_JSON );//or whatever it's in your case
String payload="<PAYLOAD HERE>"
try
{
String lResponseJson = mRestTemplate.postForObject( url, new HttpEntity<Object>( payload, lHttpHeaders ), String.class);
return lResponseJson;
}
catch( Exception lExcp )
{
logger.error( lExcp.getMessage(), lExcp );
}
Let me know if this doesn't work!!

Sending MultipartFile with some parameter to rest api in java

I am using rest api to send file with some data.
Below is the signature of API
#RequestMapping(value = "/file", method = RequestMethod.POST)
public ModelAndView uploadFile(HttpServletRequest request,
HttpServletResponse response,
#RequestParam(required = false) String wfid,
#RequestParam String ssoToken,
#RequestParam(required = false) String typeMedia,
#RequestParam(required = false) String synopsisParam,
#RequestParam(required = false) String slideShowParam,
#RequestParam(required = false) String embedInContentParam,
#RequestParam(required = false) boolean sizeRestrictionRequiredFlag,
#RequestParam MultipartFile file) throws Exception {
logger.info("SSO - " + ssoToken);
return "Output";
}
Below is my method in which i am creating POST request
void myMethod(String restAPI, String ssoId, byte[] imageByte){
PostMethod post = null;
HttpClient httpClient = new HttpClient();
try {
post = new PostMethod(restAPI);
Part[] parts = new Part[] { new FilePart("myImage.JPG", new ByteArrayPartSource("myImage.JPG", imageByte))};
HttpMethodParams par = post.getParams();
par.getDefaults().setParameter("ssoToken", ssoId);
MultipartRequestEntity multipartRequestEntity = new MultipartRequestEntity(parts, post.getParams());
ByteArrayOutputStream requestContent = new ByteArrayOutputStream();
multipartRequestEntity.writeRequest(requestContent);
post.setRequestEntity(multipartRequestEntity);
post.setRequestHeader("content-type", multipartRequestEntity.getContentType());
/*NameValuePair[] postParameters = new NameValuePair[]{new NameValuePair("ssoToken", ssoId)};
post.setRequestBody(postParameters);*/
int status = httpClient.executeMethod(post);
String responseBody = post.getResponseBodyAsString();
} catch(Exception e){
} finally{
if(post != null){
post.releaseConnection();
}
}
}
I am getting 400 - Required String parameter 'ssoToken' is not present
When i tried commented code
/NameValuePair[] postParameters = new NameValuePair[]{new NameValuePair("ssoToken", ssoId)};
post.setRequestBody(postParameters);/
in above method and send NameValue pair as response body above exception is resolve but Multipart file exception occur.
Can someone help how create request to rest controller mentioned above.
Kindly let me know the issue before down vote.
Thanks in advance
The reason this is not working, is because, the Name-Value in parameters do not isolate customer Request Parameters that your Rest api needs.
Essentially, java wouldn't know where to look into, to extract the RequestParam "ssoToken" that your rest controller expects.
What you can do, however is this -
Part[] parts = new Part[] { new FilePart("file",file), new StringPart("ssoToken",ssoToken) };
MultipartRequestEntity multipartRequestEntity = new MultipartRequestEntity(parts, par);
HttpMethodParams par = post.getParams();
Then proceed with the rest of the code as is.
The controller isolates the parts and searches for the "ssoToken" object, which it will now find!
This, I beleive should fix this problem!

Mock Apache HTTPClient with ResponseHandler in Mockito

I've been trying to mock Apache HTTPClient with ResponseHandler, in order to test my service, using Mockito. The method in question is:
String response = httpClient.execute(httpGet, responseHandler);
where "responseHandler" is a ResponseHandler:
ResponseHandler<String> responseHandler = response -> {
int status = response.getStatusLine().getStatusCode();
if (status == HttpStatus.SC_OK) {
return EntityUtils.toString(response.getEntity());
} else {
log.error("Accessing API returned error code: {}, reason: {}", status, response.getStatusLine().getReasonPhrase());
return "";
}
};
Can somebody suggest how can I accomplish this? I want to mock "execute()" method, but I don't want to mock the "responseHandler" (I wan't to test the existing one).
Thanks!
You can mock HttpClient and use Mockito's thenAnswer() method. For example, something like:
#Test
public void http_ok() throws IOException {
String expectedContent = "expected";
HttpClient httpClient = mock(HttpClient.class);
when(httpClient.execute(any(HttpUriRequest.class), eq(responseHandler)))
.thenAnswer((InvocationOnMock invocation) -> {
BasicHttpResponse ret = new BasicHttpResponse(
new BasicStatusLine(HttpVersion.HTTP_1_1, HttpURLConnection.HTTP_OK, "OK"));
ret.setEntity(new StringEntity(expectedContent, StandardCharsets.UTF_8));
#SuppressWarnings("unchecked")
ResponseHandler<String> handler
= (ResponseHandler<String>) invocation.getArguments()[1];
return handler.handleResponse(ret);
});
String result = httpClient.execute(new HttpGet(), responseHandler);
assertThat(result, is(expectedContent));
}

How to call a RESTful web service from Android?

I have written a REST web service in Netbean IDE using Jersey Framework and Java.
For every request the user needs to provide a username and a password, I know that this authentication is not a best practice (using a curl command like: curl -u username:password -X PUT http://localhsot:8080/user).
Now I want to call a REST web service from an Android Class.
How should I do it?
I have an Android Class which uses DefaultHttpClient and CredentialUsernameAndPassword, but when I run it in Eclipse, sometimes I get a runtime exception or SDK exception.
This is an sample restclient class
public class RestClient
{
public enum RequestMethod
{
GET,
POST
}
public int responseCode=0;
public String message;
public String response;
public void Execute(RequestMethod method,String url,ArrayList<NameValuePair> headers,ArrayList<NameValuePair> params) throws Exception
{
switch (method)
{
case GET:
{
// add parameters
String combinedParams = "";
if (params!=null)
{
combinedParams += "?";
for (NameValuePair p : params)
{
String paramString = p.getName() + "=" + URLEncoder.encode(p.getValue(),"UTF-8");
if (combinedParams.length() > 1)
combinedParams += "&" + paramString;
else
combinedParams += paramString;
}
}
HttpGet request = new HttpGet(url + combinedParams);
// add headers
if (headers!=null)
{
headers=addCommonHeaderField(headers);
for (NameValuePair h : headers)
request.addHeader(h.getName(), h.getValue());
}
executeRequest(request, url);
break;
}
case POST:
{
HttpPost request = new HttpPost(url);
// add headers
if (headers!=null)
{
headers=addCommonHeaderField(headers);
for (NameValuePair h : headers)
request.addHeader(h.getName(), h.getValue());
}
if (params!=null)
request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
executeRequest(request, url);
break;
}
}
}
private ArrayList<NameValuePair> addCommonHeaderField(ArrayList<NameValuePair> _header)
{
_header.add(new BasicNameValuePair("Content-Type","application/x-www-form-urlencoded"));
return _header;
}
private void executeRequest(HttpUriRequest request, String url)
{
HttpClient client = new DefaultHttpClient();
HttpResponse httpResponse;
try
{
httpResponse = client.execute(request);
responseCode = httpResponse.getStatusLine().getStatusCode();
message = httpResponse.getStatusLine().getReasonPhrase();
HttpEntity entity = httpResponse.getEntity();
if (entity != null)
{
InputStream instream = entity.getContent();
response = convertStreamToString(instream);
instream.close();
}
}
catch (Exception e)
{ }
}
private static String convertStreamToString(InputStream is)
{
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try
{
while ((line = reader.readLine()) != null)
{
sb.append(line + "\n");
}
is.close();
}
catch (IOException e)
{ }
return sb.toString();
}
}
Recently discovered that a third party library - Square Retrofit can do the job very well.
Defining REST endpoint
public interface GitHubService {
#GET("/users/{user}/repos")
List<Repo> listRepos(#Path("user") String user,Callback<List<User>> cb);
}
Getting the concrete service
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://api.github.com")
.build();
GitHubService service = restAdapter.create(GitHubService.class);
Calling the REST endpoint
List<Repo> repos = service.listRepos("octocat",new Callback<List<User>>() {
#Override
public void failure(final RetrofitError error) {
android.util.Log.i("example", "Error, body: " + error.getBody().toString());
}
#Override
public void success(List<User> users, Response response) {
// Do something with the List of Users object returned
// you may populate your adapter here
}
});
The library handles the json serialization and deserailization for you. You may customize the serialization and deserialization too.
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.registerTypeAdapter(Date.class, new DateTypeAdapter())
.create();
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://api.github.com")
.setConverter(new GsonConverter(gson))
.build();
Stop with whatever you were doing ! :)
Implement the RESTful client as a SERVICE and delegate the intensive network stuff to activity independent component: a SERVICE.
Watch this insightful video
http://www.youtube.com/watch?v=xHXn3Kg2IQE where Virgil Dobjanschi is explaining his approach(es) to this challenge...
Using Spring for Android with RestTemplate
https://spring.io/guides/gs/consuming-rest-android/
// The connection URL
String url = "https://ajax.googleapis.com/ajax/" +
"services/search/web?v=1.0&q={query}";
// Create a new RestTemplate instance
RestTemplate restTemplate = new RestTemplate();
// Add the String message converter
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
// Make the HTTP GET request, marshaling the response to a String
String result = restTemplate.getForObject(url, String.class, "Android");
I used OkHttpClient to call restful web service. It's very simple.
OkHttpClient httpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
Response response = httpClient.newCall(request).execute();
String body = response.body().string()
What back-end? If JAVA then you can use REST with Java (JAX-RS) using Jersey.
On the Android side you can use this simple RestClient to work with that REST service.
For JSON <--> Object mapping on both sides (Android, Java back-end) you can use GSON.
Perhaps am late or maybe you've already used it before but there is another one called ksoap and its pretty amazing.. It also includes timeouts and can parse any SOAP based webservice efficiently. I also made a few changes to suit my parsing.. Look it up
Follow the below steps to consume RestFul in android.
Step1
Create a android blank project.
Step2
Need internet access permission. write the below code in AndroidManifest.xml file.
<uses-permission android:name="android.permission.INTERNET">
</uses-permission>
Step3
Need RestFul url which is running in another server or same machine.
Step4
Make a RestFul Client which will extends AsyncTask. See RestFulPost.java.
Step5
Make DTO class for RestFull Request and Response.
RestFulPost.java
package javaant.com.consuming_restful.restclient;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import com.google.gson.Gson;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import java.util.Map;
import javaant.com.consuming_restful.util.Util;
/**
* Created by Nirmal Dhara on 29-10-2015.
*/
public class RestFulPost extends AsyncTask<map, void,="" string=""> {
RestFulResult restFulResult = null;
ProgressDialog Asycdialog;
String msg;
String task;
public RestFulPost(RestFulResult restFulResult, Context context, String msg,String task) {
this.restFulResult = restFulResult;
this.task=task;
this.msg = msg;
Asycdialog = new ProgressDialog(context);
}
#Override
protected String doInBackground(Map... params) {
String responseStr = null;
Object dataMap = null;
HttpPost httpost = new HttpPost(params[0].get("url").toString());
try {
dataMap = (Object) params[0].get("data");
Gson gson = new Gson();
Log.d("data map", "data map------" + gson.toJson(dataMap));
httpost.setEntity(new StringEntity(gson.toJson(dataMap)));
httpost.setHeader("Accept", "application/json");
httpost.setHeader("Content-type", "application/json");
DefaultHttpClient httpclient= Util.getClient();
HttpResponse response = httpclient.execute(httpost);
int statusCode = response.getStatusLine().getStatusCode();
Log.d("resonse code", "----------------" + statusCode);
if (statusCode == 200)
responseStr = EntityUtils.toString(response.getEntity());
if (statusCode == 404) {
responseStr = "{\n" +
"\"status\":\"fail\",\n" +
" \"data\":{\n" +
"\"ValidUser\":\"Service not available\",\n" +
"\"code\":\"404\"\n" +
"}\n" +
"}";
}
} catch (Exception e) {
e.printStackTrace();
}
return responseStr;
}
#Override
protected void onPreExecute() {
Asycdialog.setMessage(msg);
//show dialog
Asycdialog.show();
super.onPreExecute();
}
#Override
protected void onPostExecute(String s) {
Asycdialog.dismiss();
restFulResult.onResfulResponse(s,task);
}
}
For more details and complete code please visit http://javaant.com/consume-a-restful-webservice-in-android/#.VwzbipN96Hs
Here is my Library That I have created for simple Webservice Calling,
You can use this by adding a one line gradle dependency -
compile 'com.scantity.ScHttpLibrary:ScHttpLibrary:1.0.0'
Here is the demonstration of using.
https://github.com/vishalchhodwani1992/httpLibrary

Categories